diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 61d04d5a..358b2aac 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,7 +8,7 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/scilus/sf-pediatric/tree/master/.github/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/scilus/sf-pediatric/blob/master/docs/CONTRIBUTING.md) --> @@ -16,9 +16,9 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/scilus/sf-pe - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/scilus/sf-pediatric/tree/master/.github/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/scilus/sf-pediatric/blob/master/docs/CONTRIBUTING.md) - [ ] Make sure your code lints (`nf-core pipelines lint`). -- [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). +- [ ] Ensure the test suite passes (`nf-test test tests/.nf.test --profile=+docker`). - [ ] Check for unexpected warnings in debug mode (`nextflow run . -profile debug,test,docker --outdir `). - [ ] [Documentation](https://github.com/scilus/sf-pediatric-documentation) has been updated according to your changes - [ ] `CHANGELOG.md` is updated. diff --git a/CHANGELOG.md b/CHANGELOG.md index 80f7d055..5a983efd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.3.1] - [Unreleased] +## [0.3.1] - [2026-11-06] + +### `Added` + +- Support for subject-level `*_sessions.tsv` files ([#131](https://github.com/scilus/sf-pediatric/pull/133)) ### `Fixed` diff --git a/README.md b/README.md index 8041cb1b..43606543 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ Visit our documentation at https://scilus.github.io/sf-pediatric/ for detailed i ## Contributions and Support -Contributions welcome! See our [contributing guidelines](.github/CONTRIBUTING.md). +Contributions welcome! See our [contributing guidelines](docs/CONTRIBUTING.md). **sf-pediatric** was originally written by Anthony Gagnon. diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 80016830..a082fec5 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,5 +1,5 @@ report_comment: > - This report has been generated by the scilus/sf-pediatric analysis pipeline. + This report has been generated by the scilus/sf-pediatric analysis pipeline. report_section_order: "sf-pediatric-methods-description": diff --git a/assets/multiqc_config_global.yml b/assets/multiqc_config_global.yml index 922e8802..26184202 100644 --- a/assets/multiqc_config_global.yml +++ b/assets/multiqc_config_global.yml @@ -1,5 +1,5 @@ report_comment: > - This report has been generated by the scilus/sf-pediatric analysis pipeline. + This report has been generated by the scilus/sf-pediatric analysis pipeline. report_section_order: "sf-pediatric-methods-description": diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 2f413986..1986c59d 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,142 +1,93 @@ --- title: Contributing -markdownPlugin: checklist --- -# `scilus/sf_pediatric`: Contributing guidelines +# Contributing to scilus/sf-pediatric -Hi there! -Thanks for taking an interest in improving scilus/sf_pediatric. +Thanks for helping improve **sf-pediatric**, an [nf-neuro](https://nf-neuro.github.io/welcome) pipeline for pediatric diffusion MRI (0–18 years). -This page describes the recommended nf-core way to contribute to both scilus/sf_pediatric and nf-core pipelines in general, including: +Link to the documentation: [scilus.github.io/sf-pediatric](https://scilus.github.io/sf-pediatric/). +Questions and discussion: GitHub [issues](https://github.com/scilus/sf-pediatric/issues). -- [General contribution guidelines](#general-contribution-guidelines): common procedures or guides across all nf-core pipelines. -- [Pipeline-specific contribution guidelines](#pipeline-specific-contribution-guidelines): procedures or guides specific to the development conventions of scilus/sf_pediatric. +## Where to contribute -## General contribution guidelines +All type of contributions are accepted! However, their destination might change depending of what they are targeting. Here is a table to help guide towards the most appropriate destination: -### Contribution quick start +| Kind of change | Where it belongs | +| -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Workflow wiring, parameters, profiles, tests, QC reports, docs | This repository | +| Reusable neuroimaging process or subworkflow | [nf-neuro/modules](https://github.com/nf-neuro/modules) — follow [create a module](https://nf-neuro.github.io/contribute/create-your-module/1-template) or [create a subworkflow](https://nf-neuro.github.io/contribute/create-your-subworkflow/1-template), then install it here | +| Pediatric-only or not ready upstream | `modules/local/` or `subworkflows/local/` | -To contribute code to any nf-core pipeline: +Reusable-component tutorials can be seen on the [nf-neuro website](https://nf-neuro.github.io/contribute/setup). The current guidelines will cover how to modify the current pipeline. -- [ ] Ensure you have Nextflow, nf-core tools, and nf-test installed. See the [nf-core/tools repository](https://github.com/nf-core/tools) for instructions. -- [ ] Check whether a GitHub [issue](https://github.com/scilus/sf_pediatric/issues) about your idea already exists. If an issue does not exist, create one so that others are aware you are working on it. -- [ ] [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [scilus/sf_pediatric repository](https://github.com/scilus/sf_pediatric) to your GitHub account. -- [ ] Create a branch on your forked repository and make your changes following [pipeline conventions](#pipeline-contribution-conventions) (if applicable). -- [ ] To fix major bugs, name your branch `patch` and follow the [patch release](#patch-release) process. -- [ ] Update relevant documentation within the `docs/` folder, use nf-core/tools to update `nextflow_schema.json`, and update `CITATIONS.md`. -- [ ] Run and/or update tests. See [Testing](#testing) for more information. -- [ ] [Lint](#lint-tests) your code with nf-core/tools. -- [ ] Submit a pull request (PR) against the `dev` branch and request a review. +## Quick start -If you are not used to this workflow with Git, see the [GitHub documentation](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests) or [Git resources](https://try.github.io/) for more information. +- [ ] Open or comment on a GitHub [issue](https://github.com/scilus/sf-pediatric/issues) so others know you are working on it. +- [ ] [Fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) [`scilus/sf-pediatric`](https://github.com/scilus/sf-pediatric) and branch from `dev`. +- [ ] Use [GitHub Codespaces](https://github.com/codespaces/new/scilus/sf-pediatric) or the repo [devcontainer](../.devcontainer/devcontainer.json). For nf-neuro module work, use the [nf-neuro contribution setup](https://nf-neuro.github.io/contribute/setup). +- [ ] Make the change, then update `CHANGELOG.md` (Keep a Changelog; add the entry under the current unreleased version). +- [ ] Update `nextflow_schema.json` when necessary +- [ ] Update the [documentation](https://scilus.github.io/sf-pediatric/) when necessary and tag associated PRs. +- [ ] [Lint](#testing-and-linting) and run the relevant [nf-test](#testing-and-linting) profile(s). +- [ ] Open a pull request against **`dev`** and request a review. -### GitHub Codespaces +PRs to `main` or `master` are not accepted, they should be directed towards the **`dev`** branch. -You can contribute to scilus/sf_pediatric without installing a local development environment on your machine by using [GitHub Codespaces](https://github.com/codespaces). +New to GitHub PRs? See [GitHub’s collaboration docs](https://docs.github.com/en/pull-requests). -[GitHub Codespaces](https://github.com/codespaces) is an online developer environment that runs in your browser, complete with VS Code and a terminal. -Most nf-core repositories include a devcontainer configuration, which creates a GitHub Codespaces environment specifically for Nextflow development. -The environment includes pre-installed nf-core tools, Nextflow, and a few other helpful utilities via a Docker container. +## Repository map -To get started, open the repository in [Codespaces](https://github.com/scilus/sf_pediatric/codespaces). +| Path | What to edit there | +| --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| [`workflows/sf_pediatric.nf`](../workflows/sf_pediatric.nf) | Main workflow file | +| [`conf/*.config`](../conf) | Modules' `ext.*` options (`dwi_preprocessing`, `tracking`, `bundleseg`, `connectomics`, `qc`, …) | +| [`nextflow.config`](../nextflow.config) | Default parameters and Nextflow profiles | +| [`nextflow_schema.json`](../nextflow_schema.json) | Parameter documentation and validation | +| [`modules.json`](../modules.json) | Pinned nf-neuro / nf-core modules and optional `.diff` patches | +| [`tests/*.nf.test`](../tests) | Test suites | +| [`assets/multiqc_config.yml`](../assets/multiqc_config.yml) / [`assets/multiqc_config_global.yml`](../assets/multiqc_config_global.yml) | Subject-level and global MultiQC sections | -### Testing +## Install or update nf-neuro components -When you create a pull request with changes, GitHub Actions will run automatic tests. -Pull requests are typically reviewed when these tests are passing. - -#### Lint tests - -nf-core has a [set of guidelines](https://nf-co.re/docs/specifications/overview) which all pipelines must follow. -To enforce these, run linting with nf-core/tools: +This pipeline’s default module remote is [`nf-neuro/modules`](https://github.com/nf-neuro/modules) (`main`). List, install, and update with nf-core/tools — same commands as in the [nf-neuro pipeline tutorial](https://nf-neuro.github.io/pipeline/5-tutorial_step_4): ```bash -nf-core pipelines lint +nf-core modules list remote +nf-core modules install +nf-core modules update +nf-core subworkflows install ``` -If you encounter failures or warnings, follow the linked documentation printed to screen. -For more information about linting tests, see [nf-core/tools API documentation](https://nf-co.re/docs/nf-core-tools/api_reference/latest/pipeline_lint_tests/actions_awsfulltest). - -### Patch release - -> [!WARNING] -> Only in the unlikely event of a release that contains a critical bug. - -- [ ] Create a new branch `patch` on your fork based on `upstream/main` or `upstream/master`. -- [ ] Fix the bug and use nf-core/tools to bump the version to the next semantic version, for example, `1.2.3` → `1.2.4`. -- [ ] Open a Pull Request from `patch` directly to `main`/`master` with the changes. - -### Pipeline contribution conventions - -nf-core semi-standardises how you write code and other contributions to make the scilus/sf_pediatric code and processing logic more understandable for new contributors and to ensure quality. - -#### Add a new pipeline step - -To contribute a new step to the pipeline, follow the general nf-core coding procedure. -Please also refer to the [pipeline-specific contribution guidelines](#pipeline-specific-contribution-guidelines): - -- [ ] Define the corresponding [input channel](#channel-naming-schemes) into your new process from the expected previous process channel. -- [ ] Install a module with nf-core/tools, or write a local module (see [default processes resource requirements](#default-processes-resource-requirements)), and add it to the target `.nf`. -- [ ] Define the output channel if needed. Mix the version output channel into `ch_versions` and relevant files into `ch_multiqc`. -- [ ] Add new or updated parameters to `nextflow.config` with a [default value](#default-parameter-values). -- [ ] Add new or updated parameters and relevant help text to `nextflow_schema.json` with [nf-core/tools](#default-parameter-values). -- [ ] Add validation for relevant parameters to the pipeline utilisation section of `utils_nfcore_\_pipeline/main.nf` subworkflow. -- [ ] Perform local tests to validate that the new code works as expected. - - [ ] If applicable, add a new test in the `tests` directory. -- [ ] Update `usage.md`, `output.md`, and `citation.md` as appropriate. -- [ ] [Lint](#lint-tests) the code with nf-core/tools. -- [ ] Update any diagrams or pipeline images as necessary. -- [ ] Update MultiQC config `assets/multiqc_config.yml` so relevant suffixes, file name cleanup, and module plots are in the appropriate order. -- [ ] If applicable, create a [MultiQC](https://seqera.io/multiqc/) module. -- [ ] Add a description of the output files and, if relevant, images from the MultiQC report to `docs/output.md`. - -To update the minimum required Nextflow version, see the [Nextflow version bumping](#nextflow-version-bumping) section below. For more information about pipeline contributions, see [pipeline-specific contribution guidelines](#pipeline-specific-contribution-guidelines). +Inputs, outputs, and `ext.*` options are documented in the [nf-neuro API](https://nf-neuro.github.io/api). -#### Channel naming schemes +`modules.json` may record a `patch` (for example `bundle/recognize`, `preproc/eddy`). Prefer fixing the component upstream. Keep a `.diff` only when the change must stay pipeline-specific. -Use the following naming schemes for channels to make the channel flow easier to understand: +## Add a pipeline step -- Initial process channel: `ch_output_from_` -- Intermediate and terminal channels: `ch__for_` +- [ ] Reuse an existing nf-neuro module or subworkflow when one exists. +- [ ] Include and call it from `workflows/sf_pediatric.nf` or appropriate local subworkflow. +- [ ] Set `ext.*` in the matching file under `conf/`. +- [ ] Add new parameters in `nextflow.config` with a default, then edit the schema to reflect those changes. +- [ ] Mix software versions into `ch_versions`. Mix QC outputs (`mqc` / PNG / TSV) into the local [`QC` subworkflow](../subworkflows/local/QC/qc.nf). +- [ ] Extend the matching test in `tests/` (`tracking.nf.test`, `segmentation.nf.test`, `bundleseg.nf.test`, `connectomics.nf.test`, `chained.nf.test`, or `gpu.nf.test`). +- [ ] Update the [sf-pediatric-documentation](https://github.com/scilus/sf-pediatric-documentation) if needed. +- [ ] If you add `*_mqc.png` (or similar) files, update section order in `assets/multiqc_config.yml`. -#### Default parameter values +## Testing and linting -Parameters should be initialised and defined with default values within the `params` scope in `nextflow.config`. -They should also be documented in the pipeline JSON schema. +GitHub Actions run nf-test, prek (Prettier, nextflow-lint, and a hook that blocks committing pipeline `outdir`), and `nf-core pipelines lint`. PRs are usually reviewed once those checks pass. -To update `nextflow_schema.json`, run: +This repo’s nf-test config **ignores** tests under `modules/**` and `subworkflows/**`. To run the pipeline tests use: ```bash -nf-core pipelines schema build +nf-test test tests/tracking.nf.test --profile=+docker +# Or when you want to update the snapshots +nf-test test tests/tracking.nf.test --updateSnapshot --cleanSnapshot --profile=+docker ``` -The schema builder interface that loads in your browser should automatically update the defaults in the parameter documentation. - -#### Default processes resource requirements - -If you write a local module, specify a default set of resource requirements for the process. - -Sensible defaults for process resource requirements (CPUs, memory, time) should be defined in `conf/base.config`. -Specify these with generic `withLabel:` selectors, so they can be shared across multiple processes and steps of the pipeline. - -nf-core provides a set of standard labels that you should follow where possible, as seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/main/nf_core/pipeline-template/conf/base.config). -These labels define resource defaults for single-core processes, modules that require a GPU, and different levels of multi-core configurations with increasing memory requirements. - -Values assigned within these labels can be dynamically passed to a tool using the `${task.cpus}` and `${task.memory}` Nextflow variables in the `script:` block of a module (see an example in the [modules repository](https://github.com/nf-core/modules/blob/bd1b6a40f55933d94b8c9ca94ec8c1ea0eaf4b82/modules/nf-core/samtools/bam2fq/main.nf#L30)). - -#### Nextflow version bumping - -If you use a new feature from core Nextflow, bump the minimum required Nextflow version in the pipeline with: +Lint: ```bash -nf-core pipelines bump-version --nextflow . +nf-core pipelines lint ``` - -#### Images and figures guidelines - -If you update images or graphics, follow the nf-core [style guidelines](https://nf-co.re/docs/community/brand/workflow-schematics). - -## Pipeline specific contribution guidelines - - diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 5317cfd8..120f5996 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -1,29 +1,23 @@ { "@context": [ - "https://w3id.org/ro/crate/1.2/context", - { - "GithubService": "https://w3id.org/ro/terms/test#GithubService", - "JenkinsService": "https://w3id.org/ro/terms/test#JenkinsService", - "PlanemoEngine": "https://w3id.org/ro/terms/test#PlanemoEngine", - "TestDefinition": "https://w3id.org/ro/terms/test#TestDefinition", - "TestInstance": "https://w3id.org/ro/terms/test#TestInstance", - "TestService": "https://w3id.org/ro/terms/test#TestService", - "TestSuite": "https://w3id.org/ro/terms/test#TestSuite", - "TravisService": "https://w3id.org/ro/terms/test#TravisService", - "definition": "https://w3id.org/ro/terms/test#definition", - "engineVersion": "https://w3id.org/ro/terms/test#engineVersion", - "instance": "https://w3id.org/ro/terms/test#instance", - "resource": "https://w3id.org/ro/terms/test#resource", - "runsOn": "https://w3id.org/ro/terms/test#runsOn" - } + "https://w3id.org/ro/crate/1.3/context", + "https://w3id.org/ro/terms/test" ], "@graph": [ { "@id": "./", "@type": "Dataset", + "conformsTo": [ + { + "@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.1" + }, + { + "@id": "https://w3id.org/ro/wftest/0.2" + } + ], "creativeWorkStatus": "Stable", - "datePublished": "2026-06-18T00:51:23+00:00", - "description": "# sf-pediatric\n\n[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new/scilus/sf-pediatric)\n[![GitHub Actions CI Status](https://github.com/scilus/sf-pediatric/actions/workflows/nf-test.yml/badge.svg?branch=main)](https://github.com/scilus/sf-pediatric/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/scilus/sf-pediatric/actions/workflows/linting.yml/badge.svg?branch=main)](https://github.com/scilus/sf-pediatric/actions/workflows/linting.yml)\n[![Deploy documentation](https://github.com/scilus/sf-pediatric/actions/workflows/deploy.yml/badge.svg?branch=main)](https://github.com/scilus/sf-pediatric/actions/workflows/deploy.yml)\n[![Static Badge](https://img.shields.io/badge/bioarXiv-10?style=flat&logo=arxiv&logoColor=%23B31B1B&label=10.64898%2F2026.01.19.700454&color=%23B31B1B&link=https%3A%2F%2Fdoi.org%2F10.64898%2F2026.01.19.700454)](https://doi.org/10.64898/2026.01.19.700454)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A526.04.0-23aa62.svg)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n\n## Introduction\n\n**sf-pediatric** is an end-to-end age-adaptable pipeline for pediatric (0-18 years old) diffusion MRI. It leverages normative models of the brain diffusivities to perform connectomics analysis, WM bundles extraction and tractometry. Each pipeline run is wrapped in an interactive quality control reports for easy quality control of the processed data.\n\n![sf-pediatric-schema](/assets/sf-pediatric-schema.png)\n\n## Why sf-pediatric?\n\n**sf-pediatric** is an intelligent diffusion MRI pipeline that actively adapts to the rapidly evolving pediatric brain:\n\n- **Age-Adaptable**: Leverages normative trajectories from nearly 2,000 participants across six cohorts to dynamically adjust diffusion priors, template selection, and WM atlases based on each subject's age\n- **Birth to Adulthood**: Designed specifically for the 0-18 year age range, addressing the unique challenges of processing the developmental brain\n- **Rigorously Tested**: Demonstrates improved local modeling, cortical fanning, and robust recovery of known developmental trajectories of white matter microstructure\n- **Reproducible & Transparent**: Containerized workflows (Docker/Singularity) ensure consistent results across computing environments, with comprehensive quality control reports for every processing step\n- **Scalable & Portable**: Built with Nextflow for seamless deployment on cloud platforms, HPC clusters, or local computers\u2014ideal for large-scale pediatric neuroimaging studies\n- **Fully Automated**: End-to-end processing from raw acquisitions to statistics-ready datasets with integrated quality control reports\n- **Modular Workflows**: Four specialized profiles (tracking, segmentation, connectomics, bundling) tailored to your research question. Combined, these profiles allow you to:\n - Preprocess your diffusion and anatomical data.\n - Fit local models\n - Perform whole-brain tractography\n - White matter bundles extraction with tractometry\n - Cortical/Subcortical segmentation\n - Structural connectome analysis\n\n## Use Cases\n\n**sf-pediatric** is designed for researchers investigating:\n\n- White matter development and maturation trajectories\n- Structural brain connectivity across the developmental age-range\n- Neurodevelopmental disorders\n- Effects of early-life environmental factors on brain development\n- Normative vs. atypical brain development patterns\n- Large-scale multi-site pediatric neuroimaging studies\n- ...and much more!\n\n## Quick Start\n\nVisit our documentation at https://scilus.github.io/sf-pediatric/ for detailed instructions on organizing inputs, launching the pipeline, and analyzing results.\n\n**Encounter an issue?** Open an issue on GitHub!\n\n## Contributions and Support\n\nContributions welcome! See our [contributing guidelines](.github/CONTRIBUTING.md).\n\n**sf-pediatric** was originally written by Anthony Gagnon.\n\n## Citations\n\n**Methods boilerplate**. sf-pediatric provides a boilerplate methods section available in the QC reports. Users are encouraged to use this boilerplate in their publication. For a complete guide on how to navigate the reports, please [refer to the documentation](https://scilus.github.io/sf-pediatric/guides/qc).\n\nGagnon, A., Bor\u00e9, A., Valcourt Caron, A., Edde, M., Thoumyre, S., Lepage, J.-F., Talati, A., Posner, J., Ouellet, A., Brunet, M. A., Takser, L., Rheault, F., & Descoteaux, M. (2026). sf-pediatric: A robust and age-adaptable end-to-end pipeline for pediatric diffusion MRI. bioRxiv. https://doi.org/10.64898/2026.01.19.700454\n\n## License\n\nThis pipeline is released under the **MIT License**. See [LICENSE](LICENSE) for full details.\n\nThis pipeline uses code and infrastructure developed by the [nf-core](https://nf-co.re) community (MIT license) and incorporates tools from [nf-neuro](https://github.com/scilus/nf-neuro).\n", + "datePublished": "2026-11-06T16:37:38+00:00", + "description": "# sf-pediatric\n\n[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new/scilus/sf-pediatric)\n[![GitHub Actions CI Status](https://github.com/scilus/sf-pediatric/actions/workflows/nf-test.yml/badge.svg?branch=main)](https://github.com/scilus/sf-pediatric/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/scilus/sf-pediatric/actions/workflows/linting.yml/badge.svg?branch=main)](https://github.com/scilus/sf-pediatric/actions/workflows/linting.yml)\n[![Deploy documentation](https://github.com/scilus/sf-pediatric/actions/workflows/deploy.yml/badge.svg?branch=main)](https://github.com/scilus/sf-pediatric/actions/workflows/deploy.yml)\n[![Static Badge](https://img.shields.io/badge/bioarXiv-10?style=flat&logo=arxiv&logoColor=%23B31B1B&label=10.64898%2F2026.01.19.700454&color=%23B31B1B&link=https%3A%2F%2Fdoi.org%2F10.64898%2F2026.01.19.700454)](https://doi.org/10.64898/2026.01.19.700454)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A526.04.0-23aa62.svg)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n\n## Introduction\n\n**sf-pediatric** is an end-to-end age-adaptable pipeline for pediatric (0-18 years old) diffusion MRI. It leverages normative models of the brain diffusivities to perform connectomics analysis, WM bundles extraction and tractometry. Each pipeline run is wrapped in an interactive quality control reports for easy quality control of the processed data.\n\n![sf-pediatric-schema](/assets/sf-pediatric-schema.png)\n\n## Why sf-pediatric?\n\n**sf-pediatric** is an intelligent diffusion MRI pipeline that actively adapts to the rapidly evolving pediatric brain:\n\n- **Age-Adaptable**: Leverages normative trajectories from nearly 2,000 participants across six cohorts to dynamically adjust diffusion priors, template selection, and WM atlases based on each subject's age\n- **Birth to Adulthood**: Designed specifically for the 0-18 year age range, addressing the unique challenges of processing the developmental brain\n- **Rigorously Tested**: Demonstrates improved local modeling, cortical fanning, and robust recovery of known developmental trajectories of white matter microstructure\n- **Reproducible & Transparent**: Containerized workflows (Docker/Singularity) ensure consistent results across computing environments, with comprehensive quality control reports for every processing step\n- **Scalable & Portable**: Built with Nextflow for seamless deployment on cloud platforms, HPC clusters, or local computers—ideal for large-scale pediatric neuroimaging studies\n- **Fully Automated**: End-to-end processing from raw acquisitions to statistics-ready datasets with integrated quality control reports\n- **Modular Workflows**: Four specialized profiles (tracking, segmentation, connectomics, bundling) tailored to your research question. Combined, these profiles allow you to:\n - Preprocess your diffusion and anatomical data.\n - Fit local models\n - Perform whole-brain tractography\n - White matter bundles extraction with tractometry\n - Cortical/Subcortical segmentation\n - Structural connectome analysis\n\n## Use Cases\n\n**sf-pediatric** is designed for researchers investigating:\n\n- White matter development and maturation trajectories\n- Structural brain connectivity across the developmental age-range\n- Neurodevelopmental disorders\n- Effects of early-life environmental factors on brain development\n- Normative vs. atypical brain development patterns\n- Large-scale multi-site pediatric neuroimaging studies\n- ...and much more!\n\n## Quick Start\n\nVisit our documentation at https://scilus.github.io/sf-pediatric/ for detailed instructions on organizing inputs, launching the pipeline, and analyzing results.\n\n**Encounter an issue?** Open an issue on GitHub!\n\n## Contributions and Support\n\nContributions welcome! See our [contributing guidelines](docs/CONTRIBUTING.md).\n\n**sf-pediatric** was originally written by Anthony Gagnon.\n\n## Citations\n\n**Methods boilerplate**. sf-pediatric provides a boilerplate methods section available in the QC reports. Users are encouraged to use this boilerplate in their publication. For a complete guide on how to navigate the reports, please [refer to the documentation](https://scilus.github.io/sf-pediatric/guides/qc).\n\nGagnon, A., Boré, A., Valcourt Caron, A., Edde, M., Thoumyre, S., Lepage, J.-F., Talati, A., Posner, J., Ouellet, A., Brunet, M. A., Takser, L., Rheault, F., & Descoteaux, M. (2026). sf-pediatric: A robust and age-adaptable end-to-end pipeline for pediatric diffusion MRI. bioRxiv. https://doi.org/10.64898/2026.01.19.700454\n\n## License\n\nThis pipeline is released under the **MIT License**. See [LICENSE](LICENSE) for full details.\n\nThis pipeline uses code and infrastructure developed by the [nf-core](https://nf-co.re) community (MIT license) and incorporates tools from [nf-neuro](https://github.com/scilus/nf-neuro).\n", "hasPart": [ { "@id": "main.nf" @@ -31,9 +25,6 @@ { "@id": "assets/" }, - { - "@id": "bin/" - }, { "@id": "conf/" }, @@ -99,7 +90,7 @@ }, "mentions": [ { - "@id": "#6507a9c9-e86e-41fc-9b2f-42c6aa56c770" + "@id": "#140594af-1f25-41df-a35f-067957f6e95b" } ], "name": "scilus/sf_pediatric" @@ -110,14 +101,9 @@ "about": { "@id": "./" }, - "conformsTo": [ - { - "@id": "https://w3id.org/ro/crate/1.2" - }, - { - "@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.0" - } - ] + "conformsTo": { + "@id": "https://w3id.org/ro/crate/1.3" + } }, { "@id": "main.nf", @@ -132,7 +118,7 @@ } ], "dateCreated": "", - "dateModified": "2026-06-18T00:51:23Z", + "dateModified": "2026-11-06T16:37:38Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": [ "nf-core", @@ -152,10 +138,10 @@ }, "url": [ "https://github.com/scilus/sf-pediatric", - "https://nf-co.re/scilus/sf_pediatric/0.3.0/" + "https://nf-co.re/scilus/sf_pediatric/0.3.1/" ], "version": [ - "0.3.0" + "0.3.1" ] }, { @@ -168,14 +154,23 @@ "url": { "@id": "https://www.nextflow.io/" }, - "version": "!>=24.10.5" + "version": "!>=26.04.0" + }, + { + "@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.1", + "@type": [ + "CreativeWork", + "Profile" + ], + "name": "Workflow RO-Crate", + "version": "1.1" }, { - "@id": "#6507a9c9-e86e-41fc-9b2f-42c6aa56c770", + "@id": "#140594af-1f25-41df-a35f-067957f6e95b", "@type": "TestSuite", "instance": [ { - "@id": "#bb901282-0dd4-4f0f-b850-c3afcca70e63" + "@id": "#9be5a360-716d-4816-8275-b62fe9e04544" } ], "mainEntity": { @@ -184,7 +179,16 @@ "name": "Test suite for scilus/sf_pediatric" }, { - "@id": "#bb901282-0dd4-4f0f-b850-c3afcca70e63", + "@id": "https://w3id.org/ro/wftest/0.2", + "@type": [ + "CreativeWork", + "Profile" + ], + "name": "Workflow Testing RO-Crate", + "version": "0.2" + }, + { + "@id": "#9be5a360-716d-4816-8275-b62fe9e04544", "@type": "TestInstance", "name": "GitHub Actions workflow for testing scilus/sf_pediatric", "resource": "repos/scilus/sf-pediatric/actions/workflows/nf-test.yml", @@ -206,11 +210,6 @@ "@type": "Dataset", "description": "Additional files" }, - { - "@id": "bin/", - "@type": "Dataset", - "description": "Scripts that must be callable from a pipeline process" - }, { "@id": "conf/", "@type": "Dataset", @@ -315,7 +314,7 @@ { "@id": "https://orcid.org/0000-0002-4468-0269", "@type": "Person", - "affiliation": "Universit\u00e9 de Sherbrooke", + "affiliation": "Université de Sherbrooke", "email": "anthony.gagnon7@usherbrooke.ca", "name": "Anthony Gagnon", "url": "https://github.com/gagnonanthony" diff --git a/subworkflows/local/utils_nfcore_sf_pediatric_pipeline/main.nf b/subworkflows/local/utils_nfcore_sf_pediatric_pipeline/main.nf index 3c180e59..7952f2bb 100644 --- a/subworkflows/local/utils_nfcore_sf_pediatric_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_sf_pediatric_pipeline/main.nf @@ -114,6 +114,9 @@ workflow PIPELINE_INITIALISATION { // Create channel from input file provided through params.input using nf-bids plugin // if ( input_bids ) { + // Copy to preserve the value of input_bids for the sessions.tsv file. + def bids_path = input_bids + // ** To support comma separated participant labels and list ** // def participant_ids = params.participant_label ? params.participant_label instanceof String ? @@ -121,7 +124,7 @@ workflow PIPELINE_INITIALISATION { params.participant_label : [] ch_inputs = channel.fromBIDS( - input_bids, + bids_path, "$projectDir/assets/nf-bids_config.yml", [flatten_output: true, unpack_json_sidecar: true] @@ -131,20 +134,60 @@ workflow PIPELINE_INITIALISATION { def id = item.meta.subject def ses = item.meta.session == "NA" ? null : item.meta.session + // ** Instantiate a variable that will collect prints related to BIDS file matching ** // + // ** to be printed in a log file later ** // + def logs = [] + + // Look for a *sessions.tsv file to get the age per session if available. + def sessions_files = files("${bids_path}/${id}/*sessions.tsv") + def age = null + + if ( sessions_files && ses ) { + def log = null + def lines = sessions_files[0].readLines().findAll { line -> line.trim() } + def header = lines[0].split("\t") as List + def ses_idx = header.indexOf("session_id") + def age_idx = header.indexOf("age") + + // Find the age for the current session. + if ( ses_idx < 0 || age_idx < 0 ) { + log = "[${id}${ses ? "/" + ses : ""}] Missing 'session_id' or 'age' column in sessions.tsv file. Please validate." + } else { + def row = lines.drop(1) + .collect { line -> line.split("\t", -1) } + .find { cols -> cols[ses_idx] == ses.toString() || cols[ses_idx] == ses.toString().replaceAll("ses-", "") } + def value = row ? row[age_idx]?.trim() : null + + if ( !row ) { + log = "[${id}${ses ? "/" + ses : ""}] No row found for session ${ses} in sessions.tsv file. Please validate." + } else if ( value && value.isNumber() ) { + age = value.toFloat() + } else { + log = "[${id}${ses ? "/" + ses : ""}] Invalid age value '${value}' for session ${ses} in sessions.tsv file. Please validate." + } + + if ( log ) { + logs << log + } + } + + // Copy the sessions.tsv file to the output directory. + sessions_files[0].copyTo(file("$outdir/${id}/${id}_sessions.tsv")) + } + // Age is already fetched from the participants.tsv file, flag subjects with missing age and exit. - def age = item.meta.age ? item.meta.age.toFloat() : 0.0 - if ( age == 0.0 ) { + if ( age == null ) { + age = item.meta.age ? item.meta.age.toFloat() : null + } + if ( age == null ) { error "ERROR: Age not found for participant ${id}${ses ? " and session " + ses : ""} in participants.tsv file. Please validate." } + // Temp age in years for priors prediction (only if data is over 25, as we assume it is gestational age). // ** Setting to a minimum of 0.04 (~ 2 weeks) to avoid negative values for the priors prediction ** // age = age.toFloat() > 25 ? Math.max(Math.abs((age.toFloat() - 40) / 52), 0.04) : age.toFloat() def priors = fetchPriors(age) - // ** Instantiate a variable that will collect prints related to BIDS file matching ** // - // ** to be printed in a log file later ** // - def logs = [] - // DWI and associated files def dwi = item.dwi?.nii ?: [] def dwi_json = item.dwi?.json ?: [] diff --git a/tests/chained.nf.test.snap b/tests/chained.nf.test.snap index dcff2c15..203393a5 100644 --- a/tests/chained.nf.test.snap +++ b/tests/chained.nf.test.snap @@ -629,6 +629,7 @@ "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-MNIInfant_mode-image_desc-warp_xfm.nii.gz", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-affine_xfm.mat", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-warp_xfm.nii.gz", + "sub-test1/sub-test1_sessions.tsv", "sub-test2", "sub-test2/anat", "sub-test2/anat/sub-test2_run-01_seg-BrainnetomeChild_desc-labels_dseg.tsv", @@ -1666,6 +1667,7 @@ "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-T2w_to-T1w_mode-image_desc-affine_xfm.mat", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-affine_xfm.mat", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-warp_xfm.nii.gz", + "sub-test1/sub-test1_sessions.tsv", "sub-test2", "sub-test2/anat", "sub-test2/anat/sub-test2_run-01_space-DWI_desc-preproc_T2w.json", @@ -2313,6 +2315,7 @@ "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-T2w_to-T1w_mode-image_desc-affine_xfm.mat", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-affine_xfm.mat", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-warp_xfm.nii.gz", + "sub-test1/sub-test1_sessions.tsv", "sub-test2", "sub-test2/anat", "sub-test2/anat/sub-test2_run-01_space-DWI_desc-preproc_T2w.json", @@ -2681,6 +2684,7 @@ "sub-test1/ses-time1/multiqc/sub-test1_multiqc_data", "sub-test1/ses-time1/multiqc/sub-test1_multiqc_plots", "sub-test1/ses-time1/multiqc/sub-test1_multiqc_report.html", + "sub-test1/sub-test1_sessions.tsv", "sub-test3", "sub-test3/anat", "sub-test3/anat/sub-test3_seg-BrainnetomeChild_desc-labels_dseg.tsv", diff --git a/tests/data/bids/participants.tsv b/tests/data/bids/participants.tsv index 352208d1..d1e33744 100644 --- a/tests/data/bids/participants.tsv +++ b/tests/data/bids/participants.tsv @@ -1,6 +1,4 @@ participant_id session_id age -sub-test1 ses-baseline 43 -sub-test1 ses-time1 4 sub-test2 1 sub-test3 2 sub-test4 8 diff --git a/tests/data/bids/sub-test1/sub-test1_sessions.tsv b/tests/data/bids/sub-test1/sub-test1_sessions.tsv new file mode 100644 index 00000000..5b88adcc --- /dev/null +++ b/tests/data/bids/sub-test1/sub-test1_sessions.tsv @@ -0,0 +1,3 @@ +session_id age +ses-baseline 43 +ses-time1 4 diff --git a/tests/segmentation.nf.test.snap b/tests/segmentation.nf.test.snap index 9f163ec4..b47e27ae 100644 --- a/tests/segmentation.nf.test.snap +++ b/tests/segmentation.nf.test.snap @@ -86,6 +86,7 @@ "sub-test1/ses-time1/multiqc/sub-test1_multiqc_data", "sub-test1/ses-time1/multiqc/sub-test1_multiqc_plots", "sub-test1/ses-time1/multiqc/sub-test1_multiqc_report.html", + "sub-test1/sub-test1_sessions.tsv", "sub-test3", "sub-test3/anat", "sub-test3/anat/sub-test3_seg-BrainnetomeChild_desc-labels_dseg.tsv", diff --git a/tests/tracking.nf.test.snap b/tests/tracking.nf.test.snap index 47b843e0..c4506d07 100644 --- a/tests/tracking.nf.test.snap +++ b/tests/tracking.nf.test.snap @@ -376,6 +376,7 @@ "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-T2w_to-T1w_mode-image_desc-affine_xfm.mat", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-affine_xfm.mat", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-warp_xfm.nii.gz", + "sub-test1/sub-test1_sessions.tsv", "sub-test2", "sub-test2/anat", "sub-test2/anat/sub-test2_run-01_space-DWI_desc-preproc_T2w.json", @@ -833,10 +834,10 @@ "sub-test4/xfm/sub-test4_from-dwi_to-T1w_mode-image_desc-warp_xfm.nii.gz" ] ], - "timestamp": "2026-07-13T16:17:52.707781", + "timestamp": "2026-11-06T09:32:37.994202", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.4" + "nextflow": "26.04.6" } }, "Tracking profile no dwi preprocessing - should run successfully": { @@ -1135,6 +1136,7 @@ "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-T2w_to-T1w_mode-image_desc-affine_xfm.mat", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-affine_xfm.mat", "sub-test1/ses-time1/xfm/sub-test1_ses-time1_from-dwi_to-T1w_mode-image_desc-warp_xfm.nii.gz", + "sub-test1/sub-test1_sessions.tsv", "sub-test2", "sub-test2/anat", "sub-test2/anat/sub-test2_run-01_space-DWI_desc-preproc_T2w.json", @@ -1480,10 +1482,10 @@ "sub-test4/xfm/sub-test4_from-dwi_to-T1w_mode-image_desc-warp_xfm.nii.gz" ] ], - "timestamp": "2026-07-13T16:28:24.606351", + "timestamp": "2026-11-06T09:47:05.660257", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.4" + "nextflow": "26.04.6" } } } \ No newline at end of file