Skip to content

Commit

Permalink
🥅 Guardrail BBR only
Browse files Browse the repository at this point in the history
  • Loading branch information
shnizzedy committed Oct 31, 2022
1 parent 4203333 commit d4f5af6
Show file tree
Hide file tree
Showing 12 changed files with 725 additions and 179 deletions.
35 changes: 17 additions & 18 deletions CPAC/pipeline/nipype_pipeline_engine/__init__.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
'''Module to import Nipype Pipeline engine and override some Classes.
See https://fcp-indi.github.io/docs/developer/nodes
for C-PAC-specific documentation.
See https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.html
for Nipype's documentation.
Copyright (C) 2022 C-PAC Developers
# Copyright (C) 2022 C-PAC Developers

This file is part of C-PAC.
# This file is part of C-PAC.

C-PAC is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
# C-PAC is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.

C-PAC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
# C-PAC is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details.

You should have received a copy of the GNU Lesser General Public
License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.''' # noqa: E501
# You should have received a copy of the GNU Lesser General Public
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
'''Module to import Nipype Pipeline engine and override some Classes.
See https://fcp-indi.github.io/docs/developer/nodes
for C-PAC-specific documentation.
See https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.html
for Nipype's documentation.''' # noqa: E501 # pylint: disable=line-too-long
from nipype.pipeline import engine as pe
# import everything in nipype.pipeline.engine.__all__
from nipype.pipeline.engine import * # noqa: F401,F403
Expand Down
138 changes: 106 additions & 32 deletions CPAC/pipeline/nipype_pipeline_engine/engine.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,57 @@
'''Module to import Nipype Pipeline engine and override some Classes.
See https://fcp-indi.github.io/docs/developer/nodes
for C-PAC-specific documentation.
See https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.html
for Nipype's documentation.
# STATEMENT OF CHANGES:
# This file is derived from sources licensed under the Apache-2.0 terms,
# and this file has been changed.

STATEMENT OF CHANGES:
This file is derived from sources licensed under the Apache-2.0 terms,
and this file has been changed.
# CHANGES:
# * Supports just-in-time dynamic memory allocation
# * Skips doctests that require files that we haven't copied over
# * Applies a random seed
# * Supports overriding memory estimates via a log file and a buffer
# * Adds quotation marks around strings in dotfiles

CHANGES:
* Supports just-in-time dynamic memory allocation
* Skips doctests that require files that we haven't copied over
* Applies a random seed
* Supports overriding memory estimates via a log file and a buffer
# ORIGINAL WORK'S ATTRIBUTION NOTICE:
# Copyright (c) 2009-2016, Nipype developers

ORIGINAL WORK'S ATTRIBUTION NOTICE:
Copyright (c) 2009-2016, Nipype developers
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0

http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
# Prior to release 0.12, Nipype was licensed under a BSD license.

Prior to release 0.12, Nipype was licensed under a BSD license.
# Modifications Copyright (C) 2022 C-PAC Developers

Modifications Copyright (C) 2022 C-PAC Developers
# This file is part of C-PAC.

This file is part of C-PAC.''' # noqa: E501
# C-PAC is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.

# C-PAC is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
'''Module to import Nipype Pipeline engine and override some Classes.
See https://fcp-indi.github.io/docs/developer/nodes
for C-PAC-specific documentation.
See https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.html
for Nipype's documentation.''' # noqa: E501 # pylint: disable=line-too-long
import os
import re
from logging import getLogger
from inspect import Parameter, Signature, signature
from logging import getLogger
from typing import Iterable, Tuple, Union
from nibabel import load
from nipype import logging
from nipype.interfaces.utility import Function
Expand All @@ -53,6 +67,7 @@
UNDEFINED_SIZE = (42, 42, 42, 1200)

random_state_logger = getLogger('random')
logger = getLogger("nipype.workflow")


def _check_mem_x_path(mem_x_path):
Expand Down Expand Up @@ -399,10 +414,9 @@ def run(self, updatehash=False):
if self.seed is not None:
self._apply_random_seed()
if self.seed_applied:
random_state_logger.info('%s',
'%s # (Atropos constant)' %
self.name if 'atropos' in
self.name else self.name)
random_state_logger.info('%s\t%s', '# (Atropos constant)' if
'atropos' in self.name else
str(self.seed), self.name)
return super().run(updatehash)


Expand Down Expand Up @@ -483,6 +497,40 @@ def _configure_exec_nodes(self, graph):
TypeError):
self._handle_just_in_time_exception(node)

def connect_retries(self, nodes: Iterable['Node'],
connections: Iterable[Tuple['Node', Union[str, tuple],
str]]) -> None:
"""Method to generalize making the same connections to try and
retry nodes.
For each 3-tuple (``conn``) in ``connections``, will do
``wf.connect(conn[0], conn[1], node, conn[2])`` for each ``node``
in ``nodes``
Parameters
----------
nodes : iterable of Nodes
connections : iterable of 3-tuples of (Node, str or tuple, str)
"""
wrong_conn_type_msg = (r'connect_retries `connections` argument '
'must be an iterable of (Node, str or '
'tuple, str) tuples.')
if not isinstance(connections, (list, tuple)):
raise TypeError(f'{wrong_conn_type_msg}: Given {connections}')
for node in nodes:
if not isinstance(node, Node):
raise TypeError('connect_retries requires an iterable '
r'of nodes for the `nodes` parameter: '
f'Given {node}')
for conn in connections:
if not all((isinstance(conn, (list, tuple)), len(conn) == 3,
isinstance(conn[0], Node),
isinstance(conn[1], (tuple, str)),
isinstance(conn[2], str))):
raise TypeError(f'{wrong_conn_type_msg}: Given {conn}')
self.connect(*conn[:2], node, conn[2])

def _handle_just_in_time_exception(self, node):
# pylint: disable=protected-access
if hasattr(self, '_local_func_scans'):
Expand All @@ -492,6 +540,32 @@ def _handle_just_in_time_exception(self, node):
# TODO: handle S3 files
node._apply_mem_x(UNDEFINED_SIZE) # noqa: W0212

def nodes_and_guardrails(self, *nodes, registered, add_clones=True):
"""Returns a two tuples of Nodes: (try, retry) and their
respective guardrails
Parameters
----------
nodes : any number of Nodes
Returns
-------
nodes : tuple of Nodes
guardrails : tuple of Nodes
"""
from CPAC.registration.guardrails import registration_guardrail_node, \
retry_clone
nodes = list(nodes)
if add_clones is True:
nodes.extend([retry_clone(node) for node in nodes])
guardrails = [None] * len(nodes)
for i, node in enumerate(nodes):
guardrails[i] = registration_guardrail_node(
f'guardrail_{node.name}', i)
self.connect(node, registered, guardrails[i], 'registered')
return tuple(nodes), tuple(guardrails)


def get_data_size(filepath, mode='xyzt'):
"""Function to return the size of a functional image (x * y * z * t)
Expand Down
9 changes: 6 additions & 3 deletions CPAC/pipeline/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from itertools import chain, permutations
import numpy as np
from pathvalidate import sanitize_filename
from voluptuous import All, ALLOW_EXTRA, Any, Capitalize, Coerce, \
from voluptuous import All, ALLOW_EXTRA, Any, Capitalize, Coerce, Equal, \
ExactSequence, ExclusiveInvalid, In, Length, Lower, \
Match, Maybe, Optional, Range, Required, Schema
from CPAC import docs_prefix
Expand Down Expand Up @@ -526,9 +526,12 @@ def sanitize(filename):
},
},
'boundary_based_registration': {
'run': forkable,
'run': All(Coerce(ListFromItem),
[Any(bool1_1, All(Lower, Equal('fallback')))],
Length(max=3)),
'bbr_schedule': str,
'bbr_wm_map': In({'probability_map', 'partial_volume_map'}),
'bbr_wm_map': In({'probability_map',
'partial_volume_map'}),
'bbr_wm_mask_args': str,
'reference': In({'whole-head', 'brain'})
},
Expand Down
24 changes: 22 additions & 2 deletions CPAC/qc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
from .utils import *
from .qc import *
# Copyright (C) 2013-2022 C-PAC Developers

# This file is part of C-PAC.

# C-PAC is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.

# C-PAC is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
"""Quality control utilities for C-PAC"""
from CPAC.qc.globals import registration_guardrail_thresholds, \
update_thresholds
from CPAC.qc.qcmetrics import qc_masks
__all__ = ['qc_masks', 'registration_guardrail_thresholds',
'update_thresholds']
42 changes: 42 additions & 0 deletions CPAC/qc/globals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright (C) 2022 C-PAC Developers

# This file is part of C-PAC.

# C-PAC is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.

# C-PAC is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
"""Global QC values"""
_REGISTRATION_GUARDRAIL_THRESHOLDS = {'thresholds': {}}


def registration_guardrail_thresholds() -> dict:
"""Get registration guardrail thresholds
Returns
-------
dict
"""
return _REGISTRATION_GUARDRAIL_THRESHOLDS['thresholds']


def update_thresholds(thresholds) -> None:
"""Set a registration guardrail threshold
Parameters
----------
thresholds : dict of {str: float or int}
Returns
-------
None
"""
_REGISTRATION_GUARDRAIL_THRESHOLDS['thresholds'].update(thresholds)
Loading

0 comments on commit d4f5af6

Please sign in to comment.