Skip to content

Pydeface module#373

Open
loboehme1 wants to merge 3 commits into
nf-neuro:mainfrom
loboehme1:pydeface
Open

Pydeface module#373
loboehme1 wants to merge 3 commits into
nf-neuro:mainfrom
loboehme1:pydeface

Conversation

@loboehme1

Copy link
Copy Markdown

Describe your changes

This PR adds a new PYDEFACE module under modules/nf-neuro/anonymization/pydeface.
The module runs PyDeface on anatomical MRI NIfTI files to remove facial structures for anonymization.
It takes a tuple containing sample metadata and an input NIfTI image, creates a BIDS-like output path using subject and session metadata, and emits the defaced NIfTI image, log files, and software version information.

List test packages used by your module

The module test uses the nf-neuro LOAD_TEST_DATA subworkflow to provide a test T1w NIfTI image.
Test data/package used: T1w.zip

The test checks that:

  • The PYDEFACE process completes successfully
  • One defaced NIfTI file is produced
  • Output logs are created
  • The output filename matches the expected *_defaced.nii.gz pattern
  • Output files exist and are non-empty

Checklist before requesting a review

  • Create the tool:
    • Edit ./modules/nf-neuro/<category>/<tool>/main.nf
    • Edit ./modules/nf-neuro/<category>/<tool>/meta.yml
    • Edit ./modules/nf-neuro/<category>/<tool>/environment.yml --> we use the PyDeface container directly
  • Generate the tests:
    • Edit ./modules/nf-neuro/<category>/<tool>/tests/main.nf.test
    • Run the tests to generate the main.nf.test.snap snapshots
  • Ensure the syntax is correct :
    • Run prettier and editorconfig-checker to fix common syntax issues
    • Run nf-core modules lint and fix all errors --> there are still a few errors and warnings
    • Ensure your variables have good, clear names

@loboehme1
loboehme1 requested a review from a team June 24, 2026 00:13

@AlexVCaron AlexVCaron left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work ! My comments and suggestions should get everything inline with our guidelines 🙂 Don't hesitate to get in touch here or via slack if you need my help !

Comment on lines +5 to +9
container {
workflow.containerEngine in ['singularity', 'apptainer'] && !(task.ext.singularity_pull_docker_container ?: false)
? 'docker://poldracklab/pydeface:latest'
: 'docker.io/poldracklab/pydeface:latest'
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, use the docker container definition directly. Support for apptainer and other environments is in the team's backlog and will be deployed over the whole library in the future.

Suggested change
container {
workflow.containerEngine in ['singularity', 'apptainer'] && !(task.ext.singularity_pull_docker_container ?: false)
? 'docker://poldracklab/pydeface:latest'
: 'docker.io/poldracklab/pydeface:latest'
}
container "poldracklab/pydeface:latest"

Comment on lines +15 to +17
cpus { (params.pydeface_cpus ?: 4) as Integer }
memory { params.pydeface_mem ?: '8 GB' }
time { params.pydeface_time ?: '2h' }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For resources, we use nf-core labels. They used to have a better definition of the kind of resources attached to each, we need to document that better on our side.

For this case I'd use the process_medium label:

Suggested change
cpus { (params.pydeface_cpus ?: 4) as Integer }
memory { params.pydeface_mem ?: '8 GB' }
time { params.pydeface_time ?: '2h' }
label "process_medium"

tuple val(meta), path(nifti)

output:
tuple val(meta), path("sub-${meta.subject}/ses-${meta.session}/anat/*_defaced.nii.gz"), emit: defaced

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the bids-like output structure here needed for the PyDeface tool ? The group opted to keep the outputs of modules unstandardized, and manage the outputs conversion using publishDir at the pipeline level. You can see the docs for that standard here.

Comment on lines +34 to +35
sub="sub-${meta.subject}"
ses="ses-${meta.session}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be general, don't expect to have access to the subject or session here, but you'll always have access to the meta.id field. It should be used instead to name the output files. The conversion to BIDS will then be handled at file publishing by the pipeline, like stated above.

Comment on lines +57 to +60
if [[ "\$base" == *"_defaced" ]]; then
echo "[SKIP] Input already looks defaced: \$base" | tee -a "\$out_log"
cp "${nifti}" "\$out_file"
else

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This main condition should not be required. The including subworkflow or pipeline will have the job of filtering out those data points

Groovy Map containing sample information.
Expected keys for this module currently include `subject` and `session`,
for example `[ subject: '01', session: '001' ]`.
- sub-${meta.subject}/ses-${meta.session}/anat/*_defaced.nii.gz: {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block should contain a short description of the image content and descriptors. Here's a (recent module](

) that contains everything formatted as we intend

Comment on lines +34 to +43
versions_pydeface:
- - "${task.process}":
type: string
description: The name of the process.
- "pydeface":
type: string
description: The name of the tool.
- "pydeface_version":
type: string
description: The version of PyDeface used by the process.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refer to the module linked above to replace the versions block. You can use the exact same one, copy-pasted !

Comment on lines +54 to +65
topics:
versions:
- - "${task.process}":
type: string
description: The name of the process.
- "pydeface":
type: string
description: The name of the tool.
'"versions"':
- versions.yml:
type: string
description: The name of the process.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this default ? I have to get a look at newest updates to the nf-core guidelines, we should update documentation on our end to align with the latest additions 😅

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove most of the content of this file, defaults like trace and timeline are already set by overhead test configurations. Refer here for the content that should appear (if you need some, maybe you could also just remove the file).

@arnaudbore
arnaudbore requested review from arnaudbore and removed request for Manonedde and gagnonanthony June 30, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants