Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5364b5a

Browse files
committed
Revert "stripped out workflow code"
This reverts commit 3c63562.
1 parent 3c63562 commit 5364b5a

File tree

8 files changed

+381
-1
lines changed

8 files changed

+381
-1
lines changed

example-specs/workflow/dmriprep.yaml

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
function: dmriprep.default:default_workflow
2+
args:
3+
subject_id: test
4+
# bids_dir:
5+
# bids_filters:
6+
# debug:
7+
# derivatives:
8+
# echo_idx:
9+
# fmriprep_dir:
10+
# get:
11+
layout:
12+
type: bids:BIDSLayout
13+
args:
14+
root: /Users/tclose/Data/openneuro/ds000114
15+
# output_dir:
16+
# sloppy:
17+
# task_id:
18+
# version:
19+
# nipype_version:
20+
# anat_only:
21+
# cifti_output:
22+
# force_syn:
23+
# hires:
24+
ignore: []
25+
# level:
26+
# longitudinal:
27+
# run_msmsulc:
28+
# run_reconall:
29+
# skull_strip_t1w:
30+
# skull_strip_template:
31+
# skull_strip_fixed_seed:
32+
# spaces:
33+
# use_syn_sdc:
34+
splits:
35+
- func_name: registration
36+
first_node: ds_surfs
37+
- func_name: segmentation
38+
first_node: lta2itk_fwd
39+
ignore_tasks:
40+
- smriprep.interfaces.DerivativesDataSink
41+
- nipype.interfaces.utility.base.IdentityInterface
42+
43+
44+
45+
46+
47+
48+
49+
50+
51+
52+
53+
54+
55+
56+
57+
58+
59+
60+
61+
62+

example-specs/workflow/fmriprep.yaml

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
function: fmriprep.default:default_workflow
2+
args:
3+
subject_id: test
4+
# bids_dir:
5+
# bids_filters:
6+
# debug:
7+
# derivatives:
8+
# echo_idx:
9+
# fmriprep_dir:
10+
# get:
11+
layout:
12+
type: bids:BIDSLayout
13+
args:
14+
root: /Users/tclose/Data/openneuro/ds000114
15+
# output_dir:
16+
# sloppy:
17+
# task_id:
18+
# version:
19+
# nipype_version:
20+
# anat_only:
21+
# cifti_output:
22+
# force_syn:
23+
# hires:
24+
ignore: []
25+
# level:
26+
# longitudinal:
27+
# run_msmsulc:
28+
# run_reconall:
29+
# skull_strip_t1w:
30+
# skull_strip_template:
31+
# skull_strip_fixed_seed:
32+
# spaces:
33+
# use_syn_sdc:
34+
splits:
35+
- func_name: registration
36+
first_node: ds_surfs
37+
- func_name: segmentation
38+
first_node: lta2itk_fwd
39+
ignore_tasks:
40+
- smriprep.interfaces.DerivativesDataSink
41+
- nipype.interfaces.utility.base.IdentityInterface
42+
43+
44+
45+
46+
47+
48+
49+
50+
51+
52+
53+
54+
55+
56+
57+
58+
59+
60+
61+
62+

example-specs/workflow/qsiprep.yaml

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
function: qsiprep.workflows.base:init_single_subject_wf
2+
args:
3+
subject_id: test
4+
name: single_subject_qsipreptest_wf
5+
reportlets_dir: .
6+
output_dir: .
7+
bids_dir: .
8+
bids_filters: null
9+
anatomical_contrast: T1w
10+
ignore: []
11+
debug: false
12+
low_mem: false
13+
output_resolution: 1.25
14+
denoise_before_combining: true
15+
dwi_denoise_window: 7
16+
denoise_method: patch2self
17+
unringing_method: mrdegibbs
18+
b1_biascorrect_stage: false
19+
no_b0_harmonization: false
20+
dwi_only: false
21+
anat_only: false
22+
longitudinal: false
23+
b0_threshold: 100
24+
freesurfer: false
25+
hires: false
26+
raw_image_sdc: false
27+
force_spatial_normalization: true
28+
combine_all_dwis: true
29+
distortion_group_merge: none
30+
pepolar_method: TOPUP
31+
omp_nthreads: 1
32+
skull_strip_template: OASIS
33+
skull_strip_fixed_seed: false
34+
template: MNI152NLin2009cAsym
35+
prefer_dedicated_fmaps: false
36+
motion_corr_to: iterative
37+
b0_to_t1w_transform: Rigid
38+
intramodal_template_iters: 0
39+
intramodal_template_transform: Rigid
40+
hmc_model: 3dSHORE
41+
hmc_transform: Affine
42+
eddy_config: null
43+
shoreline_iters: 2
44+
infant_mode: false
45+
impute_slice_threshold: 0.0
46+
write_local_bvecs: false
47+
fmap_bspline: false
48+
fmap_demean: true
49+
use_syn: false
50+
force_syn: false
51+
splits:
52+
# - func_name: registration
53+
# first_node: ds_surfs
54+
# - func_name: segmentation
55+
# first_node: lta2itk_fwd
56+
ignore_tasks:
57+
# - smriprep.interfaces.DerivativesDataSink
58+
- nipype.interfaces.utility.base.IdentityInterface
59+

example-specs/workflow/smriprep.yaml

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
function: smriprep.workflows.base:init_single_subject_wf
2+
args:
3+
debug: false
4+
freesurfer: true
5+
fast_track: false
6+
hires: true
7+
layout:
8+
type: bids:BIDSLayout
9+
args:
10+
root: test-data/bids-data/ds000113
11+
longitudinal: false
12+
low_mem: false
13+
name: single_subject_wf
14+
omp_nthreads: 1
15+
output_dir: .
16+
skull_strip_fixed_seed: false
17+
skull_strip_mode: force
18+
skull_strip_template:
19+
type: niworkflows.utils.spaces:Reference
20+
args:
21+
space: OASIS30ANTs
22+
spaces:
23+
type: niworkflows.utils.spaces:SpatialReferences
24+
args:
25+
spaces:
26+
- MNI152NLin2009cAsym
27+
- fsaverage5
28+
subject_id: test
29+
bids_filters: null
30+
splits:
31+
- func_name: registration
32+
first_node: ds_surfs
33+
- func_name: segmentation
34+
first_node: lta2itk_fwd
35+
ignore_tasks:
36+
- smriprep.interfaces.DerivativesDataSink
37+
- nipype.interfaces.utility.base.IdentityInterface
38+

nipype2pydra/cli.py

+13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import yaml
44
from nipype2pydra import __version__
55
import nipype2pydra.task
6+
from .workflow import WorkflowConverter
67

78

89
# Define the base CLI entrypoint
@@ -51,3 +52,15 @@ def task(yaml_spec, package_root, callables, output_module):
5152
output_module=output_module, callables_module=callables, **spec
5253
)
5354
converter.generate(package_root)
55+
56+
57+
@cli.command(help="Port Nipype workflow creation functions to Pydra")
58+
@click.argument("yaml-spec", type=click.File())
59+
@click.argument("output_file", type=click.Path(path_type=Path))
60+
def workflow(yaml_spec, output_file):
61+
62+
spec = yaml.safe_load(yaml_spec)
63+
64+
converter = WorkflowConverter(spec)
65+
out_str = converter.generate()
66+
output_file.write_text(out_str)

nipype2pydra/workflow.py

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
from __future__ import annotations
2+
import typing as ty
3+
import json
4+
import tempfile
5+
from pathlib import Path
6+
import subprocess as sp
7+
from collections import defaultdict
8+
import black
9+
from nipype.interfaces.base import isdefined
10+
from .utils import load_class_or_func
11+
12+
13+
class WorkflowConverter:
14+
# creating the wf
15+
def __init__(self, spec):
16+
self.spec = spec
17+
18+
self.wf = load_class_or_func(self.spec["function"])(
19+
**self._parse_workflow_args(self.spec["args"])
20+
)
21+
# loads the 'function' in smriprep.yaml, and implement the args (creates a
22+
# dictionary)
23+
24+
def node_connections(
25+
self,
26+
workflow,
27+
functions: dict[str, dict],
28+
# wf_inputs: dict[str, str],
29+
# wf_outputs: dict[str, str],
30+
):
31+
connections: defaultdict = defaultdict(dict)
32+
33+
# iterates over wf graph, Get connections from workflow graph, store connections
34+
# in a dictionary
35+
for edge, props in workflow._graph.edges.items():
36+
src_node = edge[0].name
37+
dest_node = edge[1].name
38+
dest_node_fullname = workflow.get_node(dest_node).fullname
39+
for node_conn in props["connect"]:
40+
src_field = node_conn[0]
41+
dest_field = node_conn[1]
42+
if src_field[1].startswith("def"):
43+
functions[dest_node_fullname][dest_field] = src_field[1]
44+
else:
45+
connections[dest_node_fullname][
46+
dest_field
47+
] = f"{src_node}.lzout.{src_field}"
48+
49+
for nested_wf in workflow._nested_workflows_cache:
50+
connections.update(self.node_connections(nested_wf, functions=functions))
51+
return connections
52+
53+
def generate(self, format_with_black: bool = False):
54+
55+
functions = defaultdict(dict)
56+
connections = self.node_connections(self.wf, functions=functions)
57+
out_text = ""
58+
for node_name in self.wf.list_node_names():
59+
node = self.wf.get_node(node_name)
60+
61+
interface_type = type(node.interface)
62+
63+
task_type = interface_type.__module__ + "." + interface_type.__name__
64+
node_args = ""
65+
for arg in node.inputs.visible_traits():
66+
val = getattr(node.inputs, arg) # Enclose strings in quotes
67+
if isdefined(val):
68+
try:
69+
val = json.dumps(val)
70+
except TypeError:
71+
pass
72+
if isinstance(val, str) and "\n" in val:
73+
val = '"""' + val + '""""'
74+
node_args += f",\n {arg}={val}"
75+
76+
for arg, val in connections[node.fullname].items():
77+
node_args += f",\n {arg}=wf.{val}"
78+
79+
out_text += f"""
80+
wf.add(
81+
{task_type}(
82+
name="{node.name}"{node_args}
83+
)
84+
)"""
85+
86+
if format_with_black:
87+
out_text = black.format_file_contents(
88+
out_text, fast=False, mode=black.FileMode()
89+
)
90+
return out_text
91+
92+
@classmethod
93+
def _parse_workflow_args(cls, args):
94+
dct = {}
95+
for name, val in args.items():
96+
if isinstance(val, dict) and sorted(val.keys()) == ["args", "type"]:
97+
val = load_class_or_func(val["type"])(
98+
**cls._parse_workflow_args(val["args"])
99+
)
100+
dct[name] = val
101+
return dct
102+
103+
def save_graph(
104+
self, out_path: Path, format: str = "svg", work_dir: ty.Optional[Path] = None
105+
):
106+
if work_dir is None:
107+
work_dir = Path(tempfile.mkdtemp())
108+
work_dir = Path(work_dir)
109+
graph_dot_path = work_dir / "wf-graph.dot"
110+
self.wf.write_hierarchical_dotfile(graph_dot_path)
111+
dot_path = sp.check_output("which dot", shell=True).decode("utf-8").strip()
112+
sp.check_call(
113+
f"{dot_path} -T{format} {str(graph_dot_path)} > {str(out_path)}", shell=True
114+
)

pyproject.toml

-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ test = [
6060
"pytest-env>=0.6.2",
6161
"pytest-cov>=2.12.1",
6262
"fileformats-medimage-extras",
63-
"qsiprep",
6463
]
6564
docs = [
6665
"packaging",

0 commit comments

Comments
 (0)