From 84777cb93c082167e437647a62fbffe4aeb2402f Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Thu, 25 Sep 2025 17:50:56 -0400 Subject: [PATCH 1/6] sty: Use fmt:skip in workflows.base and workflows.outputs [ignore-rev] --- sdcflows/workflows/base.py | 8 ++------ sdcflows/workflows/outputs.py | 12 +++--------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/sdcflows/workflows/base.py b/sdcflows/workflows/base.py index 88c5afd267..b4ef0d4216 100644 --- a/sdcflows/workflows/base.py +++ b/sdcflows/workflows/base.py @@ -157,13 +157,10 @@ def init_fmap_preproc_wf( niu.IdentityInterface(fields=fields), name=f'in_{estimator.sanitized_id}', ) - # fmt:off workflow.connect([ (inputnode, est_wf, [(f, f"inputnode.{f}") for f in fields]) - ]) - # fmt:on + ]) # fmt:skip - # fmt:off workflow.connect([ (est_wf, fmap_derivatives_wf, [ ("outputnode.fmap", "inputnode.fieldmap"), @@ -182,8 +179,7 @@ def init_fmap_preproc_wf( ("outputnode.fmap_mask", "fmap_mask"), ("outputnode.method", "method") ]), - ]) - # fmt:on + ]) # fmt:skip for field, mergenode in out_merge.items(): workflow.connect(out_map, field, mergenode, f'in{n}') diff --git a/sdcflows/workflows/outputs.py b/sdcflows/workflows/outputs.py index ce5aa09997..46e0e32d89 100644 --- a/sdcflows/workflows/outputs.py +++ b/sdcflows/workflows/outputs.py @@ -105,7 +105,6 @@ def init_fmap_reports_wf( for k, v in custom_entities.items(): setattr(ds_fmap_report.inputs, k, v) - # fmt:off workflow.connect([ (inputnode, fmap_rpt, [(("fieldmap", _pop), "fieldmap"), ("fmap_ref", "reference"), @@ -113,8 +112,7 @@ def init_fmap_reports_wf( (fmap_rpt, ds_fmap_report, [("out_report", "in_file")]), (inputnode, ds_fmap_report, [("source_files", "source_file")]), - ]) - # fmt:on + ]) # fmt:skip return workflow @@ -200,7 +198,6 @@ def init_fmap_derivatives_wf( setattr(ds_reference.inputs, k, v) setattr(ds_fieldmap.inputs, k, v) - # fmt:off workflow.connect([ (inputnode, merge_fmap, [("fieldmap", "in_files")]), (inputnode, ds_reference, [("source_files", "source_file"), @@ -213,8 +210,7 @@ def init_fmap_derivatives_wf( (("out_file", _getname), "AnatomicalReference"), ]), (inputnode, ds_fieldmap, [(("fmap_meta", _selectintent), "IntendedFor")]), - ]) - # fmt:on + ]) # fmt:skip if not write_coeff: return workflow @@ -236,15 +232,13 @@ def init_fmap_derivatives_wf( for k, v in custom_entities.items(): setattr(ds_coeff.inputs, k, v) - # fmt:off workflow.connect([ (inputnode, ds_coeff, [("source_files", "source_file"), ("fmap_coeff", "in_file")]), (inputnode, gen_desc, [("fmap_coeff", "infiles")]), (gen_desc, ds_coeff, [("out", "desc")]), (ds_coeff, ds_fieldmap, [(("out_file", _getname), "AssociatedCoefficients")]), - ]) - # fmt:on + ]) # fmt:skip return workflow From 012000126f980cef6b50d7368de772ce0d37eb16 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 26 Sep 2025 07:09:39 -0400 Subject: [PATCH 2/6] sty: Use trait_set, tuple(dictionary) --- sdcflows/workflows/outputs.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/sdcflows/workflows/outputs.py b/sdcflows/workflows/outputs.py index 46e0e32d89..dcd8da55a6 100644 --- a/sdcflows/workflows/outputs.py +++ b/sdcflows/workflows/outputs.py @@ -98,12 +98,11 @@ def init_fmap_reports_wf( suffix='fieldmap', desc=fmap_type, dismiss_entities=('fmap',), - allowed_entities=tuple(custom_entities.keys()), + allowed_entities=tuple(custom_entities), ), name='ds_fmap_report', ) - for k, v in custom_entities.items(): - setattr(ds_fmap_report.inputs, k, v) + ds_fmap_report.inputs.trait_set(**custom_entities) workflow.connect([ (inputnode, fmap_rpt, [(("fieldmap", _pop), "fieldmap"), @@ -174,7 +173,7 @@ def init_fmap_derivatives_wf( suffix='fieldmap', datatype='fmap', dismiss_entities=('fmap',), - allowed_entities=tuple(custom_entities.keys()), + allowed_entities=tuple(custom_entities), ), name='ds_reference', ) @@ -186,7 +185,7 @@ def init_fmap_derivatives_wf( suffix='fieldmap', datatype='fmap', compress=True, - allowed_entities=tuple(custom_entities.keys()), + allowed_entities=tuple(custom_entities), ), name='ds_fieldmap', ) @@ -194,9 +193,8 @@ def init_fmap_derivatives_wf( if bids_fmap_id: ds_fieldmap.inputs.B0FieldIdentifier = bids_fmap_id - for k, v in custom_entities.items(): - setattr(ds_reference.inputs, k, v) - setattr(ds_fieldmap.inputs, k, v) + ds_reference.inputs.trait_set(**custom_entities) + ds_fieldmap.inputs.trait_set(**custom_entities) workflow.connect([ (inputnode, merge_fmap, [("fieldmap", "in_files")]), @@ -221,7 +219,7 @@ def init_fmap_derivatives_wf( suffix='fieldmap', datatype='fmap', compress=True, - allowed_entities=tuple(custom_entities.keys()), + allowed_entities=tuple(custom_entities), ), name='ds_coeff', iterfield=('in_file', 'desc'), @@ -229,8 +227,7 @@ def init_fmap_derivatives_wf( gen_desc = pe.Node(niu.Function(function=_gendesc), name='gen_desc') - for k, v in custom_entities.items(): - setattr(ds_coeff.inputs, k, v) + ds_coeff.inputs.trait_set(**custom_entities) workflow.connect([ (inputnode, ds_coeff, [("source_files", "source_file"), From e3bc6f5c3edb646142ede2aebca86a95b958bf22 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 26 Sep 2025 07:10:35 -0400 Subject: [PATCH 3/6] feat: Pass datasink outputs to outputnodes --- sdcflows/workflows/base.py | 6 ++++-- sdcflows/workflows/outputs.py | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/sdcflows/workflows/base.py b/sdcflows/workflows/base.py index b4ef0d4216..feaba371ba 100644 --- a/sdcflows/workflows/base.py +++ b/sdcflows/workflows/base.py @@ -172,10 +172,12 @@ def init_fmap_preproc_wf( ("outputnode.fmap_ref", "inputnode.fmap_ref"), ("outputnode.fmap_mask", "inputnode.fmap_mask"), ]), - (est_wf, out_map, [ - ("outputnode.fmap", "fmap"), + (fmap_derivatives_wf, out_map, [ + ("outputnode.fieldmap", "fmap"), ("outputnode.fmap_ref", "fmap_ref"), ("outputnode.fmap_coeff", "fmap_coeff"), + ]), + (est_wf, out_map, [ ("outputnode.fmap_mask", "fmap_mask"), ("outputnode.method", "method") ]), diff --git a/sdcflows/workflows/outputs.py b/sdcflows/workflows/outputs.py index dcd8da55a6..8a93450b5c 100644 --- a/sdcflows/workflows/outputs.py +++ b/sdcflows/workflows/outputs.py @@ -163,6 +163,10 @@ def init_fmap_derivatives_wf( ), name='inputnode', ) + outputnode = pe.Node( + niu.IdentityInterface(fields=['fieldmap', 'fmap_coeff', 'fmap_ref']), + name='outputnode', + ) merge_fmap = pe.Node(MergeSeries(), name='merge_fmap') @@ -208,6 +212,8 @@ def init_fmap_derivatives_wf( (("out_file", _getname), "AnatomicalReference"), ]), (inputnode, ds_fieldmap, [(("fmap_meta", _selectintent), "IntendedFor")]), + (ds_fieldmap, outputnode, [("out_file", "fieldmap")]), + (ds_reference, outputnode, [("out_file", "fmap_ref")]), ]) # fmt:skip if not write_coeff: @@ -235,6 +241,7 @@ def init_fmap_derivatives_wf( (inputnode, gen_desc, [("fmap_coeff", "infiles")]), (gen_desc, ds_coeff, [("out", "desc")]), (ds_coeff, ds_fieldmap, [(("out_file", _getname), "AssociatedCoefficients")]), + (ds_coeff, outputnode, [("out_file", "fmap_coeff")]), ]) # fmt:skip return workflow From 4119e15d0d9ba5edf0430b67eb9aa1491459955d Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 26 Sep 2025 07:14:52 -0400 Subject: [PATCH 4/6] feat: Save fieldmap mask to output directory --- sdcflows/workflows/base.py | 8 +++++--- sdcflows/workflows/outputs.py | 27 +++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/sdcflows/workflows/base.py b/sdcflows/workflows/base.py index feaba371ba..40f938b6a6 100644 --- a/sdcflows/workflows/base.py +++ b/sdcflows/workflows/base.py @@ -137,6 +137,7 @@ def init_fmap_preproc_wf( fmap_derivatives_wf = init_fmap_derivatives_wf( output_dir=str(output_dir), write_coeff=True, + write_mask=True, bids_fmap_id=estimator.bids_id, name=f'fmap_derivatives_wf_{estimator.sanitized_id}', ) @@ -166,20 +167,21 @@ def init_fmap_preproc_wf( ("outputnode.fmap", "inputnode.fieldmap"), ("outputnode.fmap_ref", "inputnode.fmap_ref"), ("outputnode.fmap_coeff", "inputnode.fmap_coeff"), + ("outputnode.fmap_mask", "inputnode.fmap_mask"), ]), (est_wf, fmap_reports_wf, [ ("outputnode.fmap", "inputnode.fieldmap"), ("outputnode.fmap_ref", "inputnode.fmap_ref"), ("outputnode.fmap_mask", "inputnode.fmap_mask"), ]), + (est_wf, out_map, [ + ("outputnode.method", "method") + ]), (fmap_derivatives_wf, out_map, [ ("outputnode.fieldmap", "fmap"), ("outputnode.fmap_ref", "fmap_ref"), ("outputnode.fmap_coeff", "fmap_coeff"), - ]), - (est_wf, out_map, [ ("outputnode.fmap_mask", "fmap_mask"), - ("outputnode.method", "method") ]), ]) # fmt:skip diff --git a/sdcflows/workflows/outputs.py b/sdcflows/workflows/outputs.py index 8a93450b5c..de72d4cb34 100644 --- a/sdcflows/workflows/outputs.py +++ b/sdcflows/workflows/outputs.py @@ -123,6 +123,7 @@ def init_fmap_derivatives_wf( custom_entities=None, name='fmap_derivatives_wf', write_coeff=False, + write_mask=False, ): """ Set up datasinks to store derivatives in the right location. @@ -159,12 +160,12 @@ def init_fmap_derivatives_wf( workflow = pe.Workflow(name=name) inputnode = pe.Node( niu.IdentityInterface( - fields=['source_files', 'fieldmap', 'fmap_coeff', 'fmap_ref', 'fmap_meta'] + fields=['source_files', 'fieldmap', 'fmap_coeff', 'fmap_ref', 'fmap_mask', 'fmap_meta'] ), name='inputnode', ) outputnode = pe.Node( - niu.IdentityInterface(fields=['fieldmap', 'fmap_coeff', 'fmap_ref']), + niu.IdentityInterface(fields=['fieldmap', 'fmap_coeff', 'fmap_ref', 'fmap_mask']), name='outputnode', ) @@ -216,6 +217,28 @@ def init_fmap_derivatives_wf( (ds_reference, outputnode, [("out_file", "fmap_ref")]), ]) # fmt:skip + if write_mask: + ds_mask = pe.Node( + DerivativesDataSink( + base_directory=output_dir, + compress=True, + desc='brain', + suffix='mask', + datatype='fmap', + dismiss_entities=('fmap',), + allowed_entities=tuple(custom_entities), + ), + name='ds_mask', + ) + + ds_mask.inputs.trait_set(**custom_entities) + + workflow.connect([ + (inputnode, ds_mask, [("source_files", "source_file"), + ("fmap_mask", "in_file")]), + (ds_mask, outputnode, [("out_file", "fmap_mask")]), + ]) # fmt:skip + if not write_coeff: return workflow From 5cca67d534c03bbf8b9a20571b68d1a2d07907a1 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 26 Sep 2025 07:15:36 -0400 Subject: [PATCH 5/6] chore: Drop removed ruff rule from ignores --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 37ab4b2241..aaef895ccf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -193,7 +193,6 @@ ignore = [ "B019", "SIM108", "C901", - "UP038", ] [tool.ruff.lint.flake8-quotes] From 38e9b63cb1c225a11c4c7d1b8f6a1413457caaad Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 26 Sep 2025 08:00:14 -0400 Subject: [PATCH 6/6] chore: Patch file patterns to allow masks --- sdcflows/workflows/outputs.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sdcflows/workflows/outputs.py b/sdcflows/workflows/outputs.py index de72d4cb34..a7913d4a0c 100644 --- a/sdcflows/workflows/outputs.py +++ b/sdcflows/workflows/outputs.py @@ -230,6 +230,13 @@ def init_fmap_derivatives_wf( ), name='ds_mask', ) + ds_mask._interface._file_patterns += ( + 'sub-{subject}[/ses-{session}]/{datatype|fmap}/' + 'sub-{subject}[_ses-{session}][_hash-{hash}][_acq-{acquisition}]' + '[_dir-{direction}][_run-{run}][_part-{part}][_space-{space}]' + '[_cohort-{cohort}][_res-{resolution}][_fmapid-{fmapid}]' + '[_desc-{desc}]_{suffix}{extension<.nii|.nii.gz|.json>|.nii.gz}', + ) ds_mask.inputs.trait_set(**custom_entities)