Skip to content

Commit d4f5af6

Browse files
committed
🥅 Guardrail BBR only
1 parent 4203333 commit d4f5af6

12 files changed

Lines changed: 725 additions & 179 deletions

File tree

CPAC/pipeline/nipype_pipeline_engine/__init__.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
1-
'''Module to import Nipype Pipeline engine and override some Classes.
2-
See https://fcp-indi.github.io/docs/developer/nodes
3-
for C-PAC-specific documentation.
4-
See https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.html
5-
for Nipype's documentation.
6-
7-
Copyright (C) 2022 C-PAC Developers
1+
# Copyright (C) 2022 C-PAC Developers
82

9-
This file is part of C-PAC.
3+
# This file is part of C-PAC.
104

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

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

21-
You should have received a copy of the GNU Lesser General Public
22-
License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.''' # noqa: E501
15+
# You should have received a copy of the GNU Lesser General Public
16+
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
17+
'''Module to import Nipype Pipeline engine and override some Classes.
18+
See https://fcp-indi.github.io/docs/developer/nodes
19+
for C-PAC-specific documentation.
20+
See https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.html
21+
for Nipype's documentation.''' # noqa: E501 # pylint: disable=line-too-long
2322
from nipype.pipeline import engine as pe
2423
# import everything in nipype.pipeline.engine.__all__
2524
from nipype.pipeline.engine import * # noqa: F401,F403

CPAC/pipeline/nipype_pipeline_engine/engine.py

Lines changed: 106 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,57 @@
1-
'''Module to import Nipype Pipeline engine and override some Classes.
2-
See https://fcp-indi.github.io/docs/developer/nodes
3-
for C-PAC-specific documentation.
4-
See https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.html
5-
for Nipype's documentation.
1+
# STATEMENT OF CHANGES:
2+
# This file is derived from sources licensed under the Apache-2.0 terms,
3+
# and this file has been changed.
64

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

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

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

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

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

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

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

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

36-
This file is part of C-PAC.''' # noqa: E501
33+
# C-PAC is free software: you can redistribute it and/or modify it under
34+
# the terms of the GNU Lesser General Public License as published by the
35+
# Free Software Foundation, either version 3 of the License, or (at your
36+
# option) any later version.
37+
38+
# C-PAC is distributed in the hope that it will be useful, but WITHOUT
39+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
40+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
41+
# License for more details.
42+
43+
# You should have received a copy of the GNU Lesser General Public
44+
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
45+
'''Module to import Nipype Pipeline engine and override some Classes.
46+
See https://fcp-indi.github.io/docs/developer/nodes
47+
for C-PAC-specific documentation.
48+
See https://nipype.readthedocs.io/en/latest/api/generated/nipype.pipeline.engine.html
49+
for Nipype's documentation.''' # noqa: E501 # pylint: disable=line-too-long
3750
import os
3851
import re
39-
from logging import getLogger
4052
from inspect import Parameter, Signature, signature
53+
from logging import getLogger
54+
from typing import Iterable, Tuple, Union
4155
from nibabel import load
4256
from nipype import logging
4357
from nipype.interfaces.utility import Function
@@ -53,6 +67,7 @@
5367
UNDEFINED_SIZE = (42, 42, 42, 1200)
5468

5569
random_state_logger = getLogger('random')
70+
logger = getLogger("nipype.workflow")
5671

5772

5873
def _check_mem_x_path(mem_x_path):
@@ -399,10 +414,9 @@ def run(self, updatehash=False):
399414
if self.seed is not None:
400415
self._apply_random_seed()
401416
if self.seed_applied:
402-
random_state_logger.info('%s',
403-
'%s # (Atropos constant)' %
404-
self.name if 'atropos' in
405-
self.name else self.name)
417+
random_state_logger.info('%s\t%s', '# (Atropos constant)' if
418+
'atropos' in self.name else
419+
str(self.seed), self.name)
406420
return super().run(updatehash)
407421

408422

@@ -483,6 +497,40 @@ def _configure_exec_nodes(self, graph):
483497
TypeError):
484498
self._handle_just_in_time_exception(node)
485499

500+
def connect_retries(self, nodes: Iterable['Node'],
501+
connections: Iterable[Tuple['Node', Union[str, tuple],
502+
str]]) -> None:
503+
"""Method to generalize making the same connections to try and
504+
retry nodes.
505+
506+
For each 3-tuple (``conn``) in ``connections``, will do
507+
``wf.connect(conn[0], conn[1], node, conn[2])`` for each ``node``
508+
in ``nodes``
509+
510+
Parameters
511+
----------
512+
nodes : iterable of Nodes
513+
514+
connections : iterable of 3-tuples of (Node, str or tuple, str)
515+
"""
516+
wrong_conn_type_msg = (r'connect_retries `connections` argument '
517+
'must be an iterable of (Node, str or '
518+
'tuple, str) tuples.')
519+
if not isinstance(connections, (list, tuple)):
520+
raise TypeError(f'{wrong_conn_type_msg}: Given {connections}')
521+
for node in nodes:
522+
if not isinstance(node, Node):
523+
raise TypeError('connect_retries requires an iterable '
524+
r'of nodes for the `nodes` parameter: '
525+
f'Given {node}')
526+
for conn in connections:
527+
if not all((isinstance(conn, (list, tuple)), len(conn) == 3,
528+
isinstance(conn[0], Node),
529+
isinstance(conn[1], (tuple, str)),
530+
isinstance(conn[2], str))):
531+
raise TypeError(f'{wrong_conn_type_msg}: Given {conn}')
532+
self.connect(*conn[:2], node, conn[2])
533+
486534
def _handle_just_in_time_exception(self, node):
487535
# pylint: disable=protected-access
488536
if hasattr(self, '_local_func_scans'):
@@ -492,6 +540,32 @@ def _handle_just_in_time_exception(self, node):
492540
# TODO: handle S3 files
493541
node._apply_mem_x(UNDEFINED_SIZE) # noqa: W0212
494542

543+
def nodes_and_guardrails(self, *nodes, registered, add_clones=True):
544+
"""Returns a two tuples of Nodes: (try, retry) and their
545+
respective guardrails
546+
547+
Parameters
548+
----------
549+
nodes : any number of Nodes
550+
551+
Returns
552+
-------
553+
nodes : tuple of Nodes
554+
555+
guardrails : tuple of Nodes
556+
"""
557+
from CPAC.registration.guardrails import registration_guardrail_node, \
558+
retry_clone
559+
nodes = list(nodes)
560+
if add_clones is True:
561+
nodes.extend([retry_clone(node) for node in nodes])
562+
guardrails = [None] * len(nodes)
563+
for i, node in enumerate(nodes):
564+
guardrails[i] = registration_guardrail_node(
565+
f'guardrail_{node.name}', i)
566+
self.connect(node, registered, guardrails[i], 'registered')
567+
return tuple(nodes), tuple(guardrails)
568+
495569

496570
def get_data_size(filepath, mode='xyzt'):
497571
"""Function to return the size of a functional image (x * y * z * t)

CPAC/pipeline/schema.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from itertools import chain, permutations
2222
import numpy as np
2323
from pathvalidate import sanitize_filename
24-
from voluptuous import All, ALLOW_EXTRA, Any, Capitalize, Coerce, \
24+
from voluptuous import All, ALLOW_EXTRA, Any, Capitalize, Coerce, Equal, \
2525
ExactSequence, ExclusiveInvalid, In, Length, Lower, \
2626
Match, Maybe, Optional, Range, Required, Schema
2727
from CPAC import docs_prefix
@@ -526,9 +526,12 @@ def sanitize(filename):
526526
},
527527
},
528528
'boundary_based_registration': {
529-
'run': forkable,
529+
'run': All(Coerce(ListFromItem),
530+
[Any(bool1_1, All(Lower, Equal('fallback')))],
531+
Length(max=3)),
530532
'bbr_schedule': str,
531-
'bbr_wm_map': In({'probability_map', 'partial_volume_map'}),
533+
'bbr_wm_map': In({'probability_map',
534+
'partial_volume_map'}),
532535
'bbr_wm_mask_args': str,
533536
'reference': In({'whole-head', 'brain'})
534537
},

CPAC/qc/__init__.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,22 @@
1-
from .utils import *
2-
from .qc import *
1+
# Copyright (C) 2013-2022 C-PAC Developers
2+
3+
# This file is part of C-PAC.
4+
5+
# C-PAC is free software: you can redistribute it and/or modify it under
6+
# the terms of the GNU Lesser General Public License as published by the
7+
# Free Software Foundation, either version 3 of the License, or (at your
8+
# option) any later version.
9+
10+
# C-PAC is distributed in the hope that it will be useful, but WITHOUT
11+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13+
# License for more details.
14+
15+
# You should have received a copy of the GNU Lesser General Public
16+
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
17+
"""Quality control utilities for C-PAC"""
18+
from CPAC.qc.globals import registration_guardrail_thresholds, \
19+
update_thresholds
20+
from CPAC.qc.qcmetrics import qc_masks
21+
__all__ = ['qc_masks', 'registration_guardrail_thresholds',
22+
'update_thresholds']

CPAC/qc/globals.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright (C) 2022 C-PAC Developers
2+
3+
# This file is part of C-PAC.
4+
5+
# C-PAC is free software: you can redistribute it and/or modify it under
6+
# the terms of the GNU Lesser General Public License as published by the
7+
# Free Software Foundation, either version 3 of the License, or (at your
8+
# option) any later version.
9+
10+
# C-PAC is distributed in the hope that it will be useful, but WITHOUT
11+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13+
# License for more details.
14+
15+
# You should have received a copy of the GNU Lesser General Public
16+
# License along with C-PAC. If not, see <https://www.gnu.org/licenses/>.
17+
"""Global QC values"""
18+
_REGISTRATION_GUARDRAIL_THRESHOLDS = {'thresholds': {}}
19+
20+
21+
def registration_guardrail_thresholds() -> dict:
22+
"""Get registration guardrail thresholds
23+
24+
Returns
25+
-------
26+
dict
27+
"""
28+
return _REGISTRATION_GUARDRAIL_THRESHOLDS['thresholds']
29+
30+
31+
def update_thresholds(thresholds) -> None:
32+
"""Set a registration guardrail threshold
33+
34+
Parameters
35+
----------
36+
thresholds : dict of {str: float or int}
37+
38+
Returns
39+
-------
40+
None
41+
"""
42+
_REGISTRATION_GUARDRAIL_THRESHOLDS['thresholds'].update(thresholds)

0 commit comments

Comments
 (0)