diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 6d9b74cc..00000000 --- a/.editorconfig +++ /dev/null @@ -1,37 +0,0 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true -indent_size = 4 -indent_style = space - -[*.{md,yml,yaml,html,css,scss,js}] -indent_size = 2 - -# These files are edited and tested upstream in nf-core/modules -[/modules/nf-core/**] -charset = unset -end_of_line = unset -insert_final_newline = unset -trim_trailing_whitespace = unset -indent_style = unset -[/subworkflows/nf-core/**] -charset = unset -end_of_line = unset -insert_final_newline = unset -trim_trailing_whitespace = unset -indent_style = unset - -[/assets/email*] -indent_size = unset - -# ignore python and markdown -[*.{py,md}] -indent_style = unset - -# ignore ro-crate metadata files -[**/ro-crate-metadata.json] -insert_final_newline = unset diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 332a5c4a..9b4e68ba 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -78,7 +78,7 @@ If you wish to contribute a new step, please use the following coding standards: 5. Add any new parameters to `nextflow_schema.json` with help text (via the `nf-core pipelines schema build` tool). 6. Add sanity checks and validation for all relevant parameters. 7. Perform local tests to validate that the new code works as expected. -8. If applicable, add a new test command in `.github/workflow/ci.yml`. +8. If applicable, add a new test in the `tests` directory. 9. Update MultiQC config `assets/multiqc_config.yml` so relevant suffixes, file name clean up and module plots are in the appropriate order. If applicable, add a [MultiQC](https://https://multiqc.info/) module. 10. Add a description of the output files and if relevant any appropriate images from the MultiQC report to `docs/output.md`. diff --git a/.github/actions/get-shards/action.yml b/.github/actions/get-shards/action.yml new file mode 100644 index 00000000..34085279 --- /dev/null +++ b/.github/actions/get-shards/action.yml @@ -0,0 +1,69 @@ +name: "Get number of shards" +description: "Get the number of nf-test shards for the current CI job" +inputs: + max_shards: + description: "Maximum number of shards allowed" + required: true + paths: + description: "Component paths to test" + required: false + tags: + description: "Tags to pass as argument for nf-test --tag parameter" + required: false +outputs: + shard: + description: "Array of shard numbers" + value: ${{ steps.shards.outputs.shard }} + total_shards: + description: "Total number of shards" + value: ${{ steps.shards.outputs.total_shards }} +runs: + using: "composite" + steps: + - name: Install nf-test + uses: nf-core/setup-nf-test@v1 + with: + version: ${{ env.NFT_VER }} + - name: Get number of shards + id: shards + shell: bash + run: | + # Run nf-test with dynamic parameter + nftest_output=$(nf-test test \ + --profile +docker \ + $(if [ -n "${{ inputs.tags }}" ]; then echo "--tag ${{ inputs.tags }}"; fi) \ + --dry-run \ + --ci \ + --changed-since HEAD^) || { + echo "nf-test command failed with exit code $?" + echo "Full output: $nftest_output" + exit 1 + } + echo "nf-test dry-run output: $nftest_output" + + # Default values for shard and total_shards + shard="[]" + total_shards=0 + + # Check if there are related tests + if echo "$nftest_output" | grep -q 'No tests to execute'; then + echo "No related tests found." + else + # Extract the number of related tests + number_of_shards=$(echo "$nftest_output" | sed -n 's|.*Executed \([0-9]*\) tests.*|\1|p') + if [[ -n "$number_of_shards" && "$number_of_shards" -gt 0 ]]; then + shards_to_run=$(( $number_of_shards < ${{ inputs.max_shards }} ? $number_of_shards : ${{ inputs.max_shards }} )) + shard=$(seq 1 "$shards_to_run" | jq -R . | jq -c -s .) + total_shards="$shards_to_run" + else + echo "Unexpected output format. Falling back to default values." + fi + fi + + # Write to GitHub Actions outputs + echo "shard=$shard" >> $GITHUB_OUTPUT + echo "total_shards=$total_shards" >> $GITHUB_OUTPUT + + # Debugging output + echo "Final shard array: $shard" + echo "Total number of shards: $total_shards" diff --git a/.github/actions/nf-test/action.yml b/.github/actions/nf-test/action.yml new file mode 100644 index 00000000..bf44d961 --- /dev/null +++ b/.github/actions/nf-test/action.yml @@ -0,0 +1,109 @@ +name: "nf-test Action" +description: "Runs nf-test with common setup steps" +inputs: + profile: + description: "Profile to use" + required: true + shard: + description: "Shard number for this CI job" + required: true + total_shards: + description: "Total number of test shards(NOT the total number of matrix jobs)" + required: true + paths: + description: "Test paths" + required: true + tags: + description: "Tags to pass as argument for nf-test --tag parameter" + required: false +runs: + using: "composite" + steps: + - name: Setup Nextflow + uses: nf-core/setup-nextflow@v2 + with: + version: "${{ env.NXF_VERSION }}" + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.13" + + - name: Install nf-test + uses: nf-core/setup-nf-test@v1 + with: + version: "${{ env.NFT_VER }}" + install-pdiff: true + + - name: Setup apptainer + if: contains(inputs.profile, 'singularity') + uses: eWaterCycle/setup-apptainer@main + + - name: Set up Singularity + if: contains(inputs.profile, 'singularity') + shell: bash + run: | + mkdir -p $NXF_SINGULARITY_CACHEDIR + mkdir -p $NXF_SINGULARITY_LIBRARYDIR + + - name: Conda setup + if: contains(inputs.profile, 'conda') + uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3 + with: + auto-update-conda: true + conda-solver: libmamba + conda-remove-defaults: true + + - name: Run nf-test + shell: bash + env: + NFT_WORKDIR: ${{ env.NFT_WORKDIR }} + run: | + nf-test test \ + --profile=+${{ inputs.profile }} \ + $(if [ -n "${{ inputs.tags }}" ]; then echo "--tag ${{ inputs.tags }}"; fi) \ + --ci \ + --changed-since HEAD^ \ + --verbose \ + --tap=test.tap \ + --shard ${{ inputs.shard }}/${{ inputs.total_shards }} + + # Save the absolute path of the test.tap file to the output + echo "tap_file_path=$(realpath test.tap)" >> $GITHUB_OUTPUT + + - name: Generate test summary + if: always() + shell: bash + run: | + # Add header if it doesn't exist (using a token file to track this) + if [ ! -f ".summary_header" ]; then + echo "# 🚀 nf-test results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Status | Test Name | Profile | Shard |" >> $GITHUB_STEP_SUMMARY + echo "|:------:|-----------|---------|-------|" >> $GITHUB_STEP_SUMMARY + touch .summary_header + fi + + if [ -f test.tap ]; then + while IFS= read -r line; do + if [[ $line =~ ^ok ]]; then + test_name="${line#ok }" + # Remove the test number from the beginning + test_name="${test_name#* }" + echo "| ✅ | ${test_name} | ${{ inputs.profile }} | ${{ inputs.shard }}/${{ inputs.total_shards }} |" >> $GITHUB_STEP_SUMMARY + elif [[ $line =~ ^not\ ok ]]; then + test_name="${line#not ok }" + # Remove the test number from the beginning + test_name="${test_name#* }" + echo "| ❌ | ${test_name} | ${{ inputs.profile }} | ${{ inputs.shard }}/${{ inputs.total_shards }} |" >> $GITHUB_STEP_SUMMARY + fi + done < test.tap + else + echo "| ⚠️ | No test results found | ${{ inputs.profile }} | ${{ inputs.shard }}/${{ inputs.total_shards }} |" >> $GITHUB_STEP_SUMMARY + fi + + - name: Clean up + if: always() + shell: bash + run: | + sudo rm -rf /home/ubuntu/tests/ diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index f810649a..607af751 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -14,7 +14,7 @@ jobs: run-platform: name: Run AWS full tests # run only if the PR is approved by at least 2 reviewers and against the master/main branch or manually triggered - if: github.repository == 'nf-core/pixelator' && github.event.review.state == 'approved' && (github.event.pull_request.base.ref == 'master' || github.event.pull_request.base.ref == 'main') || github.event_name == 'workflow_dispatch' + if: github.repository == 'nf-core/pixelator' && github.event.review.state == 'approved' && (github.event.pull_request.base.ref == 'master' || github.event.pull_request.base.ref == 'main') || github.event_name == 'workflow_dispatch' || github.event_name == 'release' runs-on: ubuntu-latest steps: - name: Set revision variable @@ -37,7 +37,7 @@ jobs: } profiles: test_full - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: Seqera Platform debug log file path: | diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 052d90a9..95cc749e 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -25,7 +25,7 @@ jobs: } profiles: test - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: Seqera Platform debug log file path: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 752ffb45..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,156 +0,0 @@ -name: nf-core CI -# This workflow runs the pipeline with the minimal test dataset to check that it completes without any syntax errors -on: - push: - branches: - - dev - pull_request: - paths-ignore: - - "docs/**" - release: - types: [published] - workflow_dispatch: - -env: - NFT_DIFF: "pdiff" - NFT_DIFF_ARGS: "--line-numbers --width 120 --expand-tabs=2" - NFT_VER: "0.9.2" - NFT_WORKDIR: "~" - NXF_ANSI_LOG: false - NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity - NXF_SINGULARITY_LIBRARYDIR: ${{ github.workspace }}/.singularity - TEST_DATA_BASE: "${{ github.workspace }}/test-datasets" - -concurrency: - group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" - cancel-in-progress: true - -jobs: - test: - runs-on: ubuntu-latest - name: "Test ${{ matrix.filter }} | ${{ matrix.profile }} | ${{ matrix.NXF_VER }} | ${{ matrix.shard }}/5" - strategy: - fail-fast: false - matrix: - NXF_VER: - - "24.04.2" - - "latest-everything" - filter: ["workflow", "function", "pipeline"] - # TODO: Add conda back when pixelator is available on bioconda again - profile: ["docker", "singularity"] - shard: [1, 2, 3, 4, 5] - isMaster: - - ${{ github.base_ref == 'master' }} - exclude: - # - isMaster: false - # profile: "conda" - - isMaster: false - profile: "singularity" - - steps: - - name: Check out pipeline code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - - - name: Set up Nextflow - uses: nf-core/setup-nextflow@v2 - with: - version: "${{ matrix.NXF_VER }}" - - - name: Set up nf-test - uses: nf-core/setup-nf-test@v1 - with: - version: ${{ env.NFT_VER }} - - - name: Set up apptainer - if: matrix.profile == 'singularity' - uses: eWaterCycle/setup-apptainer@main - - - name: Set up Singularity - if: matrix.profile == 'singularity' - run: | - mkdir -p $NXF_SINGULARITY_CACHEDIR - mkdir -p $NXF_SINGULARITY_LIBRARYDIR - - - name: Cache pdiff - uses: actions/cache@v4 - id: cache-pip-pdiff - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-pdiff - - - name: Install pdiff - run: python -m pip install --upgrade pip pdiff cryptography - - - name: Set up miniconda - if: matrix.profile == 'conda' - uses: conda-incubator/setup-miniconda@a4260408e20b96e80095f42ff7f1a15b27dd94ca # v3 - with: - miniconda-version: "latest" - auto-update-conda: true - conda-solver: libmamba - channels: conda-forge,bioconda - - - name: Set up Conda - if: matrix.profile == 'conda' - run: | - echo $(realpath $CONDA)/condabin >> $GITHUB_PATH - echo $(realpath python) >> $GITHUB_PATH - - - name: Disk space cleanup - uses: jlumbroso/free-disk-space@v1.3.1 - - - name: "Run pipeline with test data ${{ matrix.NXF_VER }} | ${{ matrix.test_name }} | ${{ matrix.profile }}" - continue-on-error: ${{ matrix.NXF_VER == 'latest-everything' }} - run: | - echo "## nf-test tests summary :rocket:" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "This \`${{ matrix.filter }}\` ${{ matrix.shard }}/5 shard was run on \`${{ matrix.profile }}\` | \`NXF_VER=${{ matrix.NXF_VER }}\`, and contains the following test(s):" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - nf-test test \ - --ci \ - --dryRun \ - --junitxml="TEST-${{ matrix.filter }}_${{ matrix.profile }}_${{ matrix.shard }}.xml" \ - --shard ${{ matrix.shard }}/5 \ - --changed-since HEAD^ \ - --follow-dependencies \ - --profile "+${{ matrix.profile }}" \ - --filter ${{ matrix.filter }} \ - | grep PASSED | cut -d "'" -f 2 | sed 's/^/- /' | sort -u >> $GITHUB_STEP_SUMMARY - - - name: "Run tests | ${{ matrix.filter }}_${{ matrix.profile }} | ${{ matrix.shard }}/5" - run: | - nf-test test \ - --ci \ - --debug \ - --verbose \ - --junitxml="TEST-${{ matrix.filter }}_${{ matrix.profile }}_${{ matrix.shard }}.xml" \ - --shard ${{ matrix.shard }}/5 \ - --changed-since HEAD^ \ - --follow-dependencies \ - --profile "+${{ matrix.profile }}" \ - --filter ${{ matrix.filter }} - - - name: Print success in summary - if: success() - run: | - echo "" >> $GITHUB_STEP_SUMMARY - echo "All test(s) successfull :tada:" >> $GITHUB_STEP_SUMMARY - - - name: Print failure in summary - if: failure() - run: | - echo "" >> $GITHUB_STEP_SUMMARY - echo "Some test(s) failed :cold_sweat:" >> $GITHUB_STEP_SUMMARY - - - name: Publish Test Report - uses: mikepenz/action-junit-report@v4 - if: success() || failure() # always run even if the previous step fails - with: - report_paths: "TEST-*.xml" - - - name: Clean up - if: success() || failure() - run: | - sudo rm -rf /home/ubuntu/tests/ diff --git a/.github/workflows/clean-up.yml b/.github/workflows/clean-up.yml index 0b6b1f27..ac030fd5 100644 --- a/.github/workflows/clean-up.yml +++ b/.github/workflows/clean-up.yml @@ -10,7 +10,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9 with: stale-issue-message: "This issue has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor. Remove stale label or add a comment otherwise this issue will be closed in 20 days." stale-pr-message: "This PR has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor. Remove stale label or add a comment if it is still useful." diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 3fa3e416..3dede1cf 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -12,14 +12,6 @@ on: required: true default: "dev" pull_request: - types: - - opened - - edited - - synchronize - branches: - - main - - master - pull_request_target: branches: - main - master @@ -52,9 +44,9 @@ jobs: - name: Disk space cleanup uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: - python-version: "3.12" + python-version: "3.13" architecture: "x64" - name: Setup Apptainer @@ -120,6 +112,7 @@ jobs: echo "IMAGE_COUNT_AFTER=$image_count" >> "$GITHUB_OUTPUT" - name: Compare container image counts + id: count_comparison run: | if [ "${{ steps.count_initial.outputs.IMAGE_COUNT_INITIAL }}" -ne "${{ steps.count_afterwards.outputs.IMAGE_COUNT_AFTER }}" ]; then initial_count=${{ steps.count_initial.outputs.IMAGE_COUNT_INITIAL }} @@ -132,3 +125,10 @@ jobs: else echo "The pipeline can be downloaded successfully!" fi + + - name: Upload Nextflow logfile for debugging purposes + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: nextflow_logfile.txt + path: .nextflow.log* + include-hidden-files: true diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix_linting.yml similarity index 96% rename from .github/workflows/fix-linting.yml rename to .github/workflows/fix_linting.yml index c13cea31..777ee611 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix_linting.yml @@ -32,9 +32,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} # Install and run pre-commit - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install pre-commit run: pip install pre-commit diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index dbd52d5a..8b0f88c3 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -3,9 +3,6 @@ name: nf-core linting # It runs the `nf-core pipelines lint` and markdown lint tests to ensure # that the code meets the nf-core guidelines. on: - push: - branches: - - dev pull_request: release: types: [published] @@ -16,10 +13,10 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - name: Set up Python 3.12 - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 + - name: Set up Python 3.13 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: - python-version: "3.12" + python-version: "3.13" - name: Install pre-commit run: pip install pre-commit @@ -36,13 +33,13 @@ jobs: - name: Install Nextflow uses: nf-core/setup-nextflow@v2 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: - python-version: "3.12" + python-version: "3.13" architecture: "x64" - name: read .nf-core.yml - uses: pietrobolcato/action-read-yaml@1.1.0 + uses: pietrobolcato/action-read-yaml@9f13718d61111b69f30ab4ac683e67a56d254e1d # 1.1.0 id: read_yml with: config: ${{ github.workspace }}/.nf-core.yml @@ -74,7 +71,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 95b6b6af..d43797d9 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download lint results - uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8 + uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11 with: workflow: linting.yml workflow_conclusion: completed @@ -21,7 +21,7 @@ jobs: run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - name: Post PR comment - uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2 + uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} number: ${{ steps.pr_number.outputs.pr_number }} diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml new file mode 100644 index 00000000..ddd8e832 --- /dev/null +++ b/.github/workflows/nf-test.yml @@ -0,0 +1,144 @@ +name: Run nf-test +on: + pull_request: + paths-ignore: + - "docs/**" + - "**/meta.yml" + - "**/*.md" + - "**/*.png" + - "**/*.svg" + release: + types: [published] + workflow_dispatch: + +# Cancel if a newer run is started +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NFT_VER: "0.9.2" + NFT_WORKDIR: "~" + NXF_ANSI_LOG: false + NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity + NXF_SINGULARITY_LIBRARYDIR: ${{ github.workspace }}/.singularity + +jobs: + nf-test-changes: + name: nf-test-changes + runs-on: # use self-hosted runners + - runs-on=${{ github.run_id }}-nf-test-changes + - runner=4cpu-linux-x64 + outputs: + shard: ${{ steps.set-shards.outputs.shard }} + total_shards: ${{ steps.set-shards.outputs.total_shards }} + steps: + - name: Clean Workspace # Purge the workspace in case it's running on a self-hosted runner + run: | + ls -la ./ + rm -rf ./* || true + rm -rf ./.??* || true + ls -la ./ + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + + - name: get number of shards + id: set-shards + uses: ./.github/actions/get-shards + env: + NFT_VER: ${{ env.NFT_VER }} + with: + max_shards: 7 + + - name: debug + run: | + echo ${{ steps.set-shards.outputs.shard }} + echo ${{ steps.set-shards.outputs.total_shards }} + + nf-test: + name: "${{ matrix.profile }} | ${{ matrix.NXF_VER }} | ${{ matrix.shard }}/${{ needs.nf-test-changes.outputs.total_shards }}" + needs: [nf-test-changes] + if: ${{ needs.nf-test-changes.outputs.total_shards != '0' }} + runs-on: # use self-hosted runners + - runs-on=${{ github.run_id }}-nf-test + - runner=4cpu-linux-x64 + strategy: + fail-fast: false + matrix: + shard: ${{ fromJson(needs.nf-test-changes.outputs.shard) }} + # For now remove the conda profile, since we do not support it + profile: [docker, singularity] + isMain: + - ${{ github.base_ref == 'master' || github.base_ref == 'main' }} + # Exclude conda and singularity on dev + exclude: + - isMain: false + profile: "conda" + - isMain: false + profile: "singularity" + NXF_VER: + - "24.10.5" + - "latest-everything" + env: + NXF_ANSI_LOG: false + TOTAL_SHARDS: ${{ needs.nf-test-changes.outputs.total_shards }} + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 + + - name: Run nf-test + id: run_nf_test + uses: ./.github/actions/nf-test + continue-on-error: ${{ matrix.NXF_VER == 'latest-everything' }} + env: + NFT_WORKDIR: ${{ env.NFT_WORKDIR }} + with: + profile: ${{ matrix.profile }} + shard: ${{ matrix.shard }} + total_shards: ${{ env.TOTAL_SHARDS }} + + - name: Report test status + if: ${{ always() }} + run: | + if [[ "${{ steps.run_nf_test.outcome }}" == "failure" ]]; then + echo "::error::Test with ${{ matrix.NXF_VER }} failed" + # Add to workflow summary + echo "## ❌ Test failed: ${{ matrix.profile }} | ${{ matrix.NXF_VER }} | Shard ${{ matrix.shard }}/${{ env.TOTAL_SHARDS }}" >> $GITHUB_STEP_SUMMARY + if [[ "${{ matrix.NXF_VER }}" == "latest-everything" ]]; then + echo "::warning::Test with latest-everything failed but will not cause workflow failure. Please check if the error is expected or if it needs fixing." + fi + if [[ "${{ matrix.NXF_VER }}" != "latest-everything" ]]; then + exit 1 + fi + fi + + confirm-pass: + needs: [nf-test] + if: always() + runs-on: # use self-hosted runners + - runs-on=${{ github.run_id }}-confirm-pass + - runner=2cpu-linux-x64 + steps: + - name: One or more tests failed (excluding latest-everything) + if: ${{ contains(needs.*.result, 'failure') }} + run: exit 1 + + - name: One or more tests cancelled + if: ${{ contains(needs.*.result, 'cancelled') }} + run: exit 1 + + - name: All tests ok + if: ${{ contains(needs.*.result, 'success') }} + run: exit 0 + + - name: debug-print + if: always() + run: | + echo "::group::DEBUG: `needs` Contents" + echo "DEBUG: toJSON(needs) = ${{ toJSON(needs) }}" + echo "DEBUG: toJSON(needs.*.result) = ${{ toJSON(needs.*.result) }}" + echo "::endgroup::" diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 76a9e67e..0f732495 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -30,7 +30,7 @@ jobs: bsky-post: runs-on: ubuntu-latest steps: - - uses: zentered/bluesky-post-action@80dbe0a7697de18c15ad22f4619919ceb5ccf597 # v0.1.0 + - uses: zentered/bluesky-post-action@6461056ea355ea43b977e149f7bf76aaa572e5e8 # v0.3.0 with: post: | Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! diff --git a/.github/workflows/template_version_comment.yml b/.github/workflows/template-version-comment.yml similarity index 95% rename from .github/workflows/template_version_comment.yml rename to .github/workflows/template-version-comment.yml index 537529bc..beb5c77f 100644 --- a/.github/workflows/template_version_comment.yml +++ b/.github/workflows/template-version-comment.yml @@ -14,7 +14,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} - name: Read template version from .nf-core.yml - uses: nichmor/minimal-read-yaml@v0.0.2 + uses: nichmor/minimal-read-yaml@1f7205277e25e156e1f63815781db80a6d490b8f # v0.0.2 id: read_yml with: config: ${{ github.workspace }}/.nf-core.yml diff --git a/.nf-core.yml b/.nf-core.yml index 0160c1e9..17389c31 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,16 +1,14 @@ lint: - actions_ci: false files_exist: - assets/multiqc_config.yml - conf/igenomes.config - conf/igenomes_ignored.config + - tests/default.nf.test files_unchanged: - assets/nf-core-pixelator_logo_light.png - # Ignore this for now since we haven't switched the name of the - # main branch to main from master yet - .github/PULL_REQUEST_TEMPLATE.md multiqc_config: false -nf_core_version: 3.2.1 +nf_core_version: 3.3.2 repository_type: pipeline template: author: Pixelgen Technologies AB @@ -24,4 +22,4 @@ template: - fastqc - multiqc - igenomes - version: 2.0.0 + version: 2.1.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2975758e..af7dec01 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,15 +6,24 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.2.5 - - - repo: https://github.com/editorconfig-checker/editorconfig-checker.python - rev: "3.1.2" - hooks: - - id: editorconfig-checker - alias: ec - - - repo: https://github.com/psf/black - rev: 24.2.0 + - prettier@3.6.2 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 hooks: - - id: black + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + exclude: | + (?x)^( + .*ro-crate-metadata.json$| + modules/nf-core/.*| + subworkflows/nf-core/.*| + .*\.snap$ + )$ + - id: end-of-file-fixer + exclude: | + (?x)^( + .*ro-crate-metadata.json$| + modules/nf-core/.*| + subworkflows/nf-core/.*| + .*\.snap$ + )$ diff --git a/.prettierrc.yml b/.prettierrc.yml index c81f9a76..07dbd8bb 100644 --- a/.prettierrc.yml +++ b/.prettierrc.yml @@ -1 +1,6 @@ printWidth: 120 +tabWidth: 4 +overrides: + - files: "*.{md,yml,yaml,html,css,scss,js,cff}" + options: + tabWidth: 2 diff --git a/.vscode/settings.json b/.vscode/settings.json index e8086828..4c79cdd4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,4 +4,3 @@ ], "nextflow.formatting.harshilAlignment": true } - diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c7765bd..d485bee2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,49 @@ 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). -## [[2.0.0](https://github.com/nf-core/pixelator/releases/tag/2.0.0)] - 2025-06-23 +## [[2.1.0](https://github.com/nf-core/pixelator/releases/tag/2.1.0)] - 2025-09-17 + +### Enhancements & fixes + +- Move to using quay.io as the container source, to avoid issues with users needing to login to access the + Github Container Registry by @johandahlberg in [#140](https://github.com/nf-core/pixelator/pull/140) +- Add a denoise step to the PNA workflow, that cleans data between the graph and analysis steps + by @johandahlberg in [#140](https://github.com/nf-core/pixelator/pull/140) +- Fix the PNA report not being generated by @fbdtemme in [#142](https://github.com/nf-core/pixelator/pull/142) +- Template update for nf-core/tools v3.3.2 by @fbdtemme in [#143](https://github.com/nf-core/pixelator/pull/143) +- Add the `experiment_summary` step which generates the Proximity Experiment Summary report by @johandahlberg in [#144](https://github.com/nf-core/pixelator/pull/144) +- Switch PIXELATOR_PNA_LAYOUT process label to process_high to allocate less memory by @ptajvar in [#147](https://github.com/nf-core/pixelator/pull/147) +- Simplify PNA_GENERATE_REPORTS subworkflow by @fbdtemme in [#150](https://github.com/nf-core/pixelator/pull/50) + +### Parameters + +| Old parameter | New parameter | +| ------------- | -------------------------------------------- | +| | `--skip_denoise` | +| | `--save_pna_denoise_pixelfile` | +| | `--pna_denoise_run_one_core_graph_denoising` | +| | `--pna_denoise_pval_threshold` | +| | `--pna_denoise_inflate_factor` | +| | `--pna_denoise_inflate_factor` | + +> [!NOTE] +> Parameter has been **updated** if both old and new parameter information is present. +> Parameter has been **added** if just the new parameter information is present. +> Parameter has been **removed** if new parameter information isn't present. + +### Software dependencies + +| Dependency | Old version | New version | +| ------------- | ----------- | ----------- | +| `pixelator` | 0.20.1 | 0.21.4 | +| `pixelatorES` | | 0.4.3 | + +> [!NOTE] +> Dependency has been **updated** if both old and new parameter information is present. +> Dependency has been **added** if just the new parameter information is present. +> Dependency has been **removed** if new parameter information isn't present. + +## [[2.0.0](https://github.com/nf-core/pixelator/releases/tag/2.0.0)] - 2024-05-27 This release is a major update of the nf-core/pixelator pipeline. It brings in support for the Proximity Network Analysis (PNA) workflow in addition to the Molecular Pixelation (MPX) workflow. diff --git a/README.md b/README.md index 3c3951a3..98b7cf64 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,14 @@ [![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.10015112-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.10015112) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A524.04.2-23aa62.svg)](https://www.nextflow.io/) +[![Nextflow](https://img.shields.io/badge/version-%E2%89%A524.10.5-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/) +[![nf-core template version](https://img.shields.io/badge/nf--core_template-3.3.2-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/3.3.2) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) [![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/pixelator) -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23pixelator-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/pixelator)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23pixelator-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/pixelator)[![Follow on Bluesky](https://img.shields.io/badge/bluesky-%40nf__core-1185fe?labelColor=000000&logo=bluesky)](https://bsky.app/profile/nf-co.re)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) ## Introduction @@ -35,9 +36,10 @@ For PNA data, the pipeline will run the following steps: 2. Create groups of amplicons based on their marker assignments ([`pixelator single-cell-pna demux`](https://github.com/PixelgenTechnologies/pixelator)) 3. Derive original molecules to use as edge list downstream by error correcting, and counting input amplicons ([`pixelator single-cell-pna collapse`](https://github.com/PixelgenTechnologies/pixelator)) 4. Compute the components of the graph from the edge list in order to create putative cells ([`pixelator single-cell-pna graph`](https://github.com/PixelgenTechnologies/pixelator)) -5. Analyze the spatial information in the cell graphs ([`pixelator single-cell-pna analysis`](https://github.com/PixelgenTechnologies/pixelator)) -6. Generate 3D graph layouts for visualization of cells ([`pixelator single-cell-pna layout`](https://github.com/PixelgenTechnologies/pixelator)) -7. Report generation ([`pixelator single-cell-pna report`](https://github.com/PixelgenTechnologies/pixelator)) +5. Denoise the cell graphs ([`pixelator single-cell-pna denoise`](https://github.com/PixelgenTechnologies/pixelator)) +6. Analyze the spatial information in the cell graphs ([`pixelator single-cell-pna analysis`](https://github.com/PixelgenTechnologies/pixelator)) +7. Generate 3D graph layouts for visualization of cells ([`pixelator single-cell-pna layout`](https://github.com/PixelgenTechnologies/pixelator)) +8. Report generation ([`pixelator single-cell-pna report`](https://github.com/PixelgenTechnologies/pixelator)) For MPX data, the pipeline will run the following steps: @@ -66,8 +68,8 @@ First, prepare a samplesheet with your input data that looks as follows (the exa `samplesheet.csv`: ```csv -sample,design,panel,fastq_1,fastq_2 -sample1,pna-2,proxiome-immuno-155,sample1_R1_001.fastq.gz,sample1_R2_001.fastq.gz +sample,sample_alias,condition,design,panel,fastq_1,fastq_2 +sample1,s1,control,pna-2,proxiome-immuno-155,sample1_R1_001.fastq.gz,sample1_R2_001.fastq.gz ``` Each row represents a sample and gives the design, a panel file and the input fastq files. diff --git a/assets/samplesheet_pna.csv b/assets/samplesheet_pna.csv index 897cd3f2..f3d94e7a 100644 --- a/assets/samplesheet_pna.csv +++ b/assets/samplesheet_pna.csv @@ -1,3 +1,3 @@ -sample,design,panel,fastq_1,fastq_2 -sample1,pna-2,proxiome-immuno-155,sample1_R1_001.fastq.gz,sample1_R2_001.fastq.gz -sample2,pna-2,proxiome-immuno-155,sample2_R1_001.fastq.gz,sample2_R2_001.fastq.gz +sample,sample_alias,condition,design,panel,fastq_1,fastq_2 +sample1,s1,control,pna-2,proxiome-immuno-155,sample1_R1_001.fastq.gz,sample1_R2_001.fastq.gz +sample2,s2,treatment,pna-2,proxiome-immuno-155,sample2_R1_001.fastq.gz,sample2_R2_001.fastq.gz diff --git a/conf/base.config b/conf/base.config index 0930b520..e674f262 100644 --- a/conf/base.config +++ b/conf/base.config @@ -14,7 +14,7 @@ process { memory = { 6.GB * task.attempt } time = { 4.h * task.attempt } - errorStrategy = { task.exitStatus in ((130..145) + 104) ? 'retry' : 'finish' } + errorStrategy = { task.exitStatus in ((130..145) + 104 + 175) ? 'retry' : 'finish' } maxRetries = 1 maxErrors = '-1' @@ -57,4 +57,8 @@ process { errorStrategy = 'retry' maxRetries = 2 } + withLabel: process_gpu { + ext.use_gpu = { workflow.profile.contains('gpu') } + accelerator = { workflow.profile.contains('gpu') ? 1 : null } + } } diff --git a/conf/modules.pna.config b/conf/modules.pna.config index a3b0f97e..d9b31e61 100644 --- a/conf/modules.pna.config +++ b/conf/modules.pna.config @@ -14,111 +14,108 @@ process { withName: PIXELATOR_PNA_AMPLICON { - ext.args = { [ + ext.args = { + [ "--design ${meta.design}", - params.pna_amplicon_mismatches ? "--mismatches ${params.pna_amplicon_mismatches}": '', - params.pna_amplicon_remove_polyg ? "--remove-polyg": '', - params.pna_amplicon_quality_cutoff ? "--quality-cutoff ${params.pna_amplicon_quality_cutoff}": '', + params.pna_amplicon_mismatches ? "--mismatches ${params.pna_amplicon_mismatches}" : '', + params.pna_amplicon_remove_polyg ? "--remove-polyg" : '', + params.pna_amplicon_quality_cutoff ? "--quality-cutoff ${params.pna_amplicon_quality_cutoff}" : '', ].join(' ').trim() } - publishDir = [ [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: 'amplicon/*.amplicon.fq.zst', - saveAs: { (params.save_pna_amplicon_reads || params.save_all) ? it : null } + saveAs: { params.save_pna_amplicon_reads || params.save_all ? it : null }, ], [ path: { "${params.outdir}/pixelator/logs/${meta.id}" }, mode: params.publish_dir_mode, - pattern: "*.log" + pattern: "*.log", ], [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: '**/*.{report,meta}.json', - saveAs: { params.save_json || params.save_all ? it : null } - ] + saveAs: { params.save_json || params.save_all ? it : null }, + ], ] } withName: PIXELATOR_PNA_DEMUX { - ext.args = { + ext.args = { [ - (params.pna_demux_mismatches instanceof Integer) ? "--mismatches ${params.pna_demux_mismatches}": '', - params.pna_demux_output_chunk_reads ? "--output-chunk-reads ${params.pna_demux_output_chunk_reads}": '', - (params.pna_demux_output_max_chunks != null) ? "--output-max-chunks ${params.pna_demux_output_max_chunks}": '', + params.pna_demux_mismatches instanceof Integer ? "--mismatches ${params.pna_demux_mismatches}" : '', + params.pna_demux_output_chunk_reads ? "--output-chunk-reads ${params.pna_demux_output_chunk_reads}" : '', + params.pna_demux_output_max_chunks ? "--output-max-chunks ${params.pna_demux_output_max_chunks}" : '', "--strategy ${params.pna_demux_strategy}", ].join(' ').trim() } - publishDir = [ [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: 'demux/*.parquet', - saveAs: { (params.save_pna_demux_parquet || params.save_all) ? it : null } + saveAs: { params.save_pna_demux_parquet || params.save_all ? it : null }, ], [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: 'demux/*.demux.passed.fq.zst', - saveAs: { (params.save_pna_demux_passed_reads || params.save_all) ? it : null } + saveAs: { params.save_pna_demux_passed_reads || params.save_all ? it : null }, ], [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: 'demux/*.demux.failed.fq.zst', - saveAs: { (params.save_pna_demux_failed_reads || params.save_all) ? it : null } + saveAs: { params.save_pna_demux_failed_reads || params.save_all ? it : null }, ], [ path: { "${params.outdir}/pixelator/logs/${meta.id}" }, mode: params.publish_dir_mode, - pattern: '*.log' + pattern: '*.log', ], [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: '**/*.{report,meta}.json', - saveAs: { params.save_json || params.save_all ? it : null } - ] + saveAs: { params.save_json || params.save_all ? it : null }, + ], ] } withName: PIXELATOR_PNA_COLLAPSE { - ext.args = { + ext.args = { [ params.pna_collapse_mismatches ? "--mismatches ${params.pna_collapse_mismatches}" : '', - params.pna_collapse_algorithm ? "--algorithm ${params.pna_collapse_algorithm}": '', + params.pna_collapse_algorithm ? "--algorithm ${params.pna_collapse_algorithm}" : '', ].join(' ').trim() } - publishDir = [ [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: 'collapse/*.parquet', - saveAs: { (params.save_collapsed_reads || params.save_all) ? it : null } + saveAs: { params.save_collapsed_reads || params.save_all ? it : null }, ], [ path: { "${params.outdir}/pixelator/logs/${meta.id}" }, mode: params.publish_dir_mode, - pattern: '*.log' + pattern: '*.log', ], [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: '**/*.{report,meta}.json', - saveAs: { params.save_json || params.save_all ? it : null } - ] + saveAs: { params.save_json || params.save_all ? it : null }, + ], ] } withName: PIXELATOR_PNA_GRAPH { - ext.args = { + ext.args = { [ - params.pna_graph_multiplet_recovery ? "--multiplet-recovery" : '', params.pna_graph_leiden_iterations ? "--leiden-iterations ${params.pna_graph_leiden_iterations}" : '', params.pna_graph_initial_stage_leiden_resolution ? "--initial-stage-leiden-resolution ${params.pna_graph_initial_stage_leiden_resolution}" : '', @@ -134,32 +131,67 @@ process { params.pna_graph_component_size_min_threshold ? "--component-size-min-threshold ${params.pna_graph_component_size_min_threshold}" : '', ].join(' ').trim() } - publishDir = [ [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: 'graph/*.pxl', - saveAs: { (params.save_pna_graph_pixelfile || params.save_all) ? it : null } + saveAs: { params.save_pna_graph_pixelfile || params.save_all ? it : null }, ], [ path: { "${params.outdir}/pixelator/logs/${meta.id}" }, mode: params.publish_dir_mode, - pattern: '*.log' + pattern: '*.log', ], [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: '**/*.{report,meta}.json', - saveAs: { params.save_json || params.save_all ? it : null } - ] + saveAs: { params.save_json || params.save_all ? it : null }, + ], ] } + withName: PIXELATOR_PNA_DENOISE { + ext.when = { !params.skip_denoise } + ext.args = { + [ + params.pna_denoise_run_one_core_graph_denoising ? "--run-one-core-graph-denoising" : '', + params.pna_denoise_pval_threshold ? "--pval-threshold ${params.pna_denoise_pval_threshold}" : '', + params.pna_denoise_inflate_factor ? "--inflate-factor ${params.pna_denoise_inflate_factor}" : '', + ].join(' ').trim() + } + publishDir = [ + [ + path: { "${params.outdir}/pixelator" }, + mode: params.publish_dir_mode, + pattern: 'denoise/*.pxl', + saveAs: { + if (params.save_pna_denoise_pixelfile) { + return it + } + return null + }, + ], + [ + path: { "${params.outdir}/pixelator/logs/${meta.id}" }, + mode: params.publish_dir_mode, + pattern: '*.log', + ], + [ + path: { "${params.outdir}/pixelator" }, + mode: params.publish_dir_mode, + pattern: '**/*.{report,meta}.json', + saveAs: { params.save_json ? it : null }, + ], + ] + } + + withName: PIXELATOR_PNA_ANALYSIS { - ext.when = { !params.skip_analysis } - ext.args = { + ext.when = { !params.skip_analysis } + ext.args = { [ params.pna_analysis_compute_proximity ? "--compute-proximity" : '', params.pna_analysis_proximity_nbr_of_permutations ? "--proximity-nbr-of-permutations ${params.pna_analysis_proximity_nbr_of_permutations}" : '', @@ -168,7 +200,6 @@ process { params.pna_analysis_svd_nbr_of_pivots ? "--svd-nbr-of-pivots ${params.pna_analysis_svd_nbr_of_pivots}" : '', ].join(' ').trim() } - publishDir = [ [ path: { "${params.outdir}/pixelator" }, @@ -179,25 +210,25 @@ process { return it } return null - } + }, ], [ path: { "${params.outdir}/pixelator/logs/${meta.id}" }, mode: params.publish_dir_mode, - pattern: '*.log' + pattern: '*.log', ], [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: '**/*.{report,meta}.json', - saveAs: { params.save_json || params.save_all ? it : null } - ] + saveAs: { params.save_json || params.save_all ? it : null }, + ], ] } withName: PIXELATOR_PNA_LAYOUT { - ext.when = { !params.skip_layout } - ext.args = { + ext.when = { !params.skip_layout } + ext.args = { [ params.pna_layout_no_node_marker_counts ? "--no-node-marker-counts" : '', params.pna_layout_layout_algorithm ? "--layout-algorithm ${params.pna_layout_layout_algorithm} " : '', @@ -205,7 +236,6 @@ process { params.pna_layout_wpmds_k ? "--wpmds-k ${params.pna_layout_wpmds_k} " : '', ].join(' ').trim() } - publishDir = [ [ path: { "${params.outdir}/pixelator" }, @@ -214,19 +244,19 @@ process { saveAs: { // Trim the annotate directory prefix from the output name new File(it).name - } + }, ], [ path: { "${params.outdir}/pixelator/logs/${meta.id}" }, mode: params.publish_dir_mode, - pattern: '*.log' + pattern: '*.log', ], [ path: { "${params.outdir}/pixelator" }, mode: params.publish_dir_mode, pattern: '**/*.{report,meta}.json', - saveAs: { params.save_json || params.save_all ? it : null } - ] + saveAs: { params.save_json || params.save_all ? it : null }, + ], ] } } diff --git a/conf/test.config b/conf/test.config index db56b164..ff089546 100644 --- a/conf/test.config +++ b/conf/test.config @@ -39,9 +39,6 @@ params { colocalization_n_permutations = 10 colocalization_neighbourhood_size = 1 - // For now skip the layout step since it is very slow on these - // small test datasets - skip_layout = true // using this since the default pmds_3d does not work on very small graphs layout_algorithm = "fruchterman_reingold_3d" } diff --git a/conf/test_full.config b/conf/test_full.config index 1cb281af..106e2708 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -14,6 +14,6 @@ params { config_profile_name = 'Full test profile' config_profile_description = 'Full test dataset to check pipeline function' - input = params.pipelines_testdata_base_path + "/pixelator/samplesheet/mpx/samplesheet_full.csv" + input = params.pipelines_testdata_base_path + "/samplesheet/mpx/samplesheet_full.csv" input_basedir = "s3://pixelgen-technologies-datasets/nf-core-pixelator/testdata/full/" } diff --git a/conf/test_pna.config b/conf/test_pna.config index 89995f01..018591df 100644 --- a/conf/test_pna.config +++ b/conf/test_pna.config @@ -25,7 +25,7 @@ params { pna_demux_output_chunk_reads = '50K' // Input data - input = params.pipelines_testdata_base_path + '/samplesheet/pna/samplesheet_pna.csv' + input = params.pipelines_testdata_base_path + '/samplesheet/pna/samplesheet_pna_es.csv' input_basedir = params.pipelines_testdata_base_path + '/testdata/pna' pna_graph_component_size_min_threshold = 100 diff --git a/docs/images/nf-core-pixelator-metromap.svg b/docs/images/nf-core-pixelator-metromap.svg index 4ce4019a..dcdb1786 100644 --- a/docs/images/nf-core-pixelator-metromap.svg +++ b/docs/images/nf-core-pixelator-metromap.svg @@ -1,18 +1,21 @@ - + + + + - + - + - - - + + + @@ -23,7 +26,7 @@ - + @@ -32,7 +35,7 @@ - + @@ -56,16 +59,19 @@ - - + + + + - - + + + @@ -83,9 +89,9 @@ - - - + + + @@ -113,7 +119,7 @@ - + @@ -121,11 +127,14 @@ - + + + + - - + + @@ -133,44 +142,60 @@ - - + + - + - + - + + + + + + + + - + - - + + - + + + + + + + + + + @@ -178,10 +203,10 @@ - + - + @@ -190,7 +215,7 @@ - + @@ -199,229 +224,270 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + + + + - + - + diff --git a/docs/output.md b/docs/output.md index f9a5044e..d2e36f08 100644 --- a/docs/output.md +++ b/docs/output.md @@ -26,9 +26,11 @@ The PNA pipeline consists of the following steps: - [Demultiplexing](#demultiplexing) - [Molecule collapsing and error correction](#molecule-collapsing-and-error-correction) - [Graph construction](#graph-construction) +- [Denoising](#denoising) - [Analysis](#analysis) - [Layout creation](#compute-layouts-for-visualization) -- [Report generation](#report-generation) +- [Per sample report generation](#generate-reports-per-sample) +- [Per run run report generation](#generate-report-for-all-samples) - [Pipeline information](#pipeline-information) The output of the Proximity Network Assay (PNA) pipeline is organized into several directories, each corresponding to a specific step in the pipeline. Below is an overview of the output structure and the files generated at each step: @@ -66,9 +68,7 @@ These processed and discarded FASTQ reads are intermediate and by default not pl Output files - `pixelator` - - `demux` - - `.demux.failed.fq.zst`: Discarded reads that do not match a marker. - `.demux.m1.part_000.parquet`: Marker 1 reads in parquet format. - `.demux.m2.part_000.parquet`: Marker 2 reads in parquet format. @@ -94,9 +94,7 @@ The output of this step is then used as an edge list input for the graph constru Output files - `pixelator` - - `collapse` - - `.collapse.parquet`: Edge list of the graph. - `.report.json`: QC metrics for the collapse step. - `.meta.json`: Command invocation metadata. @@ -120,10 +118,8 @@ the [pixelator documentation](https://software.pixelgen.com/pixelator/outputs/px Output files - `pixelator` - - `graph` - - - `.graph.pxl`: Edge list dataframe after recovering technical multiplets. + - `.graph.pxl`: The pixel file containing all data after resolving multiplets. - `.meta.json`: Command invocation metadata. - `.report.json`: QC metrics for the graph step. @@ -132,6 +128,30 @@ the [pixelator documentation](https://software.pixelgen.com/pixelator/outputs/px +### Denoising + +This step uses the `pixelator single-cell-pna denoise` command. It will try to find differences between +the well-connected parts of each component graph and the less well-connected parts of the graph. It will +then try to find differences in marker profiles between these two parts of the graph and use these +differences to denoise the graph. This reduces the effect of marker bleed-over due to incorrect cutting +in the graph step. + +The denoised graph will be saved as a new PXL file. + +
+Output files + +- `pixelator` + - `denoise` + - `.denoise.pxl`: The pixel file containing the denoised data. + - `.meta.json`: Command invocation metadata. + - `.report.json`: QC metrics for the graph step. + + - `logs` + - `.pixelator-denoise.log`: pixelator log output. + +
+ ### Analysis This step uses the `pixelator single-cell-pna analysis` command to calculate spatial statistics. @@ -140,9 +160,7 @@ This step uses the `pixelator single-cell-pna analysis` command to calculate spa Output files - `pixelator` - - `analysis` - - `.analysis.dataset.pxl`: PXL file with the analysis results added to it. - `.meta.json`: Command invocation metadata. - `.report.json`: Statistics for the analysis step. @@ -165,9 +183,7 @@ This entire step can also be skipped using the `--skip_layout` option. Output files - `pixelator` - - `layout` - - `.layout.pxl`: PXL file with the layout results added to it. - `.meta.json`: Command invocation metadata. - `.report.json`: Statistics for the layout step. @@ -177,7 +193,7 @@ This entire step can also be skipped using the `--skip_layout` option. -#### Generate reports +#### Generate per sample reports This step uses the `pixelator single-cell-pna report` command. @@ -190,9 +206,7 @@ More information on the report can be found in the [pixelator documentation](htt Output files - `pixelator` - - `report` - - `_report.html`: Pixelator summary report. - `logs` @@ -200,6 +214,25 @@ More information on the report can be found in the [pixelator documentation](htt +#### Generate report for all samples + +This step uses [pixelator-es](https://github.com/PixelgenTechnologies/pixelatores) to generate a Proxime Experiment Summary +that contains information about all the samples in the run. + +It will collect metrics and outputs generated by previous stages and generate a report in HTML format. + +More information on the report can be found [here](https://github.com/PixelgenTechnologies/pixelatores). + +The output from this step will be placed in the output folder root. + +
+Output files + +- `pixelator` + - `experiment_summary.html`: Proxiome Experiment Summary report + +
+ #### Pipeline information
@@ -231,9 +264,7 @@ Below is an example output structure for a pipeline run using the default settin - `pipeline_info/` - `pixelator/` - - `logs/` - - `/`: - `*.log` @@ -272,9 +303,7 @@ Set `--save_amplicon_reads` or `--save_all` to enable publishing of these files Output files - `pixelator` - - `amplicon` - - `.merged.fastq.gz`: Combine R1 and R2 reads into full amplicon reads and calculate Q30 scores for the amplicon regions. - `.report.json`: Q30 metrics of the amplicon. @@ -305,9 +334,7 @@ Alternatively, set `--save_all` to keep all intermediary outputs of all steps. Output files - `pixelator` - - `preqc` - - `.processed.fastq.gz`: Processed reads. - `.failed.fastq.gz`: Discarded reads. - `.report.json`: Fastp json report. @@ -315,7 +342,6 @@ Alternatively, set `--save_all` to keep all intermediary outputs of all steps. - `.meta.json`: Command invocation metadata. - `adapterqc` - - `.processed.fastq.gz`: Processed reads. - `.failed.fastq.gz`: Discarded reads. - `.report.json`: Cutadapt json report. @@ -340,9 +366,7 @@ Alternatively, set `--save_all` to keep all intermediary outputs of all steps. Output files - `pixelator` - - `demux` - - `.processed-.fastq.gz`: Reads demultiplexed per antibody. - `.failed.fastq.gz`: Discarded reads that do not match an antibody barcode. - `.report.json`: Cutadapt json report. @@ -372,9 +396,7 @@ Alternatively, set `--save_all` to keep all intermediary outputs of all steps. Output files - `pixelator` - - `collapse` - - `.collapsed.parquet`: Edge list of the graph. - `.report.json`: Statistics for the collapse step. - `.meta.json`: Command invocation metadata. @@ -404,9 +426,7 @@ Alternatively, set `--save_all` to keep all intermediary outputs of all steps. Output files - `pixelator` - - `graph` - - `.edgelist.parquet`: Edge list dataframe after recovering technical multiplets. - `.components_recovered.csv`: @@ -438,9 +458,7 @@ Set `--save_annotate_dataset` to include these files. Output files - `pixelator` - - `annotate` - - `.annotate.dataset.pxl`: The annotated PXL dataset, - `.meta.json`: Command invocation metadata. - `.raw_components_metrics.csv.gz` @@ -474,9 +492,7 @@ Alternatively, set `--save_all` to keep all intermediary outputs of all steps. Output files - `pixelator` - - `analysis` - - `.analysis.dataset.pxl`: PXL file with the analysis results added to it. - `.meta.json`: Command invocation metadata. - `.report.json`: Statistics for the analysis step. @@ -500,9 +516,7 @@ Set `--save_all` to keep all intermediary outputs of all steps. Output files - `pixelator` - - `layout` - - `.layout.dataset.pxl`: PXL file with the layout results added to it. - `.meta.json`: Command invocation metadata. - `.report.json`: Statistics for the layout step. @@ -564,9 +578,7 @@ Below is an example output structure for a pipeline run using the default settin - `pipeline_info/` - `pixelator/` - - `logs/` - - `/`: - `*.log` diff --git a/docs/usage.md b/docs/usage.md index eabf6008..b43f9ea2 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -38,13 +38,15 @@ sample2,pna-2,proxiome-immuno-155,sample2_R1_001.fastq.gz,sample2_R2_001.fastq.g Columns not defined in the table below are ignored by the pipeline but can be useful to add extra information for downstream processing. -| Column | Required | Description | -| ----------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `sample` | Yes | Custom sample name. This entry will be identical for multiple sequencing libraries/runs from the same sample. Spaces in sample names are automatically converted to underscores (`_`). | -| `design` | Yes | The name of the pixelator design configuration. | -| `panel`

or
`panel_file` | Yes | Name of the panel to use.
or
Path to a CSV file containing a custom panel. | -| `fastq_1` | Yes | Path to FastQ file for Illumina short reads 1. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". | -| `fastq_2` | No | Path to FastQ file for Illumina short reads 2. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". Parameter only used if you are running paired-end. | +| Column | Required | Description | +| ----------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `sample` | Yes | Custom sample name. This entry will be identical for multiple sequencing libraries/runs from the same sample. Spaces in sample names are automatically converted to underscores (`_`). | +| `sample_alias` | Yes (Only for PNA runs) | Custom sample alias. Will be used to identify the sample in reports and visualizations. | +| `condition` | Yes (Only for PNA run) | Experimental condition for the sample (e.g. control, treatment). | +| `design` | Yes | The name of the pixelator design configuration. | +| `panel`
or
`panel_file` | Yes | Name of the panel to use.
or
Path to a CSV file containing a custom panel. | +| `fastq_1` | Yes | Path to FastQ file for Illumina short reads 1. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". | +| `fastq_2` | No | Path to FastQ file for Illumina short reads 2. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". Parameter only used if you are running paired-end. | The `panel` and `panel_file` options are mutually exclusive. If both are specified, the pipeline will throw an error. One of them has to be specified. @@ -56,10 +58,10 @@ The pipeline will auto-detect whether a sample is single- or paired-end based on The `sample` identifiers have to be the same when you have re-sequenced the same sample more than once e.g. to increase sequencing depth. The pipeline will concatenate the raw reads before performing any downstream analysis. Below is an example for the same sample sequenced across 3 lanes: ```csv title="samplesheet.csv" -sample,design,panel,fastq_1,fastq_2 -uropod_control_1,pna-2,proxiome-immuno-155,uropod_control_S1_L001_R1_001.fastq.gz,uropod_control_S1_L001_R2_001.fastq.gz -uropod_control_1,pna-2,proxiome-immuno-155,uropod_control_S1_L002_R1_001.fastq.gz,uropod_control_S1_L002_R2_001.fastq.gz -uropod_control_1,pna-2,proxiome-immuno-155,uropod_control_S1_L003_R1_001.fastq.gz,uropod_control_S1_L003_R2_001.fastq.gz +sample,sample_alias,condition,design,panel,fastq_1,fastq_2 +uropod_control_1,s1,control,pna-2,proxiome-immuno-155,uropod_control_S1_L001_R1_001.fastq.gz,uropod_control_S1_L001_R2_001.fastq.gz +uropod_control_1,s1,control,pna-2,proxiome-immuno-155,uropod_control_S1_L002_R1_001.fastq.gz,uropod_control_S1_L002_R2_001.fastq.gz +uropod_control_1,s1,control,pna-2,proxiome-immuno-155,uropod_control_S1_L003_R1_001.fastq.gz,uropod_control_S1_L003_R2_001.fastq.gz ``` ### Relative paths @@ -80,8 +82,8 @@ Given following directory structure: You can use following samplesheet: ```csv title="samplesheet.csv" -sample,design,panel,panel_file,fastq_1,fastq_2 -sample1,pna-2,proxiome-immuno-155,,fastq/sample1_R1.fq.gz,fastq/sample1_R2.fq.gz +sample,sample_alias,condition,design,panel,panel_file,fastq_1,fastq_2 +sample1,s1,control,pna-2,proxiome-immuno-155,,fastq/sample1_R1.fq.gz,fastq/sample1_R2.fq.gz ``` Using the `--input_basedir` option you can specify a different location that will be used to resolve relative paths. @@ -213,8 +215,10 @@ Use this parameter to choose a configuration profile. Profiles can give configur Several generic profiles are bundled with the pipeline which instruct the pipeline to use software packaged using different methods (Docker, Singularity, Podman, Shifter, Charliecloud, Apptainer, Conda) - see below. -> [!IMPORTANT] -> We highly recommend the use of Docker or Singularity containers for full pipeline reproducibility, however when this is not possible, Conda is also supported. +> [!WARNING] +> This version of the pipeline does not support conda environments, due to issues with upstream dependencies. +> This means you cannot use the `conda` and `mamba` profiles. Please use `docker` or `singularity` instead. +> We hope to add support for conda environments in the future. The pipeline also dynamically loads configurations from [https://github.com/nf-core/configs](https://github.com/nf-core/configs) when it runs, making multiple config profiles for various institutional clusters available at run time. For more information and to check if your system is supported, please see the [nf-core/configs documentation](https://github.com/nf-core/configs#documentation). @@ -240,8 +244,6 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) - `wave` - A generic configuration profile to enable [Wave](https://seqera.io/wave/) containers. Use together with one of the above (requires Nextflow ` 24.03.0-edge` or later). -- `conda` - - A generic configuration profile to be used with [Conda](https://conda.io/docs/). Please only use Conda as a last resort i.e. when it's not possible to run the pipeline with Docker, Singularity, Podman, Shifter, Charliecloud, or Apptainer. :::warning Since Nextflow 23.07.0-edge, Nextflow no longer mounts the host's home directory when using Apptainer or Singularity. diff --git a/modules/local/collect_metadata/main.nf b/modules/local/collect_metadata/main.nf index 2685fb77..c8de2f97 100644 --- a/modules/local/collect_metadata/main.nf +++ b/modules/local/collect_metadata/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_COLLECT_METADATA { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" output: path "metadata.json", emit: metadata diff --git a/modules/local/experiment_summary/main.nf b/modules/local/experiment_summary/main.nf new file mode 100644 index 00000000..af6f39a5 --- /dev/null +++ b/modules/local/experiment_summary/main.nf @@ -0,0 +1,52 @@ +process EXPERIMENT_SUMMARY { + tag "${meta.id}" + label "process_medium" + + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'quay.io/pixelgen-technologies/pixelatores:0.4.3' + : 'quay.io/pixelgen-technologies/pixelatores:0.4.3'}" + + input: + path samplesheet_path + tuple ( + val(meta), + path(amplicon_data , stageAs: "results/amplicon/*"), + path(demux_data , stageAs: "results/demux/*"), + path(collapse_data , stageAs: "results/collapse/*"), + path(graph_data , stageAs: "results/graph/*"), + path(denoise_data , stageAs: "results/denoise/*"), + path(analysis_data , stageAs: "results/analysis/*"), + path(layout_data , stageAs: "results/layout/*") + ) + + output: + tuple val(meta), path("*experiment-summary.html") , emit: html + path("versions.yml") , emit: versions + + script: + + """ + # Copy the full quarto dir from the read-only image into the workdir + cp -r /workspace/inst/quarto/ ./quarto/ + quarto render ./quarto/pixelatorES.qmd \\ + -P sample_sheet="\$PWD/${samplesheet_path}" \\ + -P data_folder="\$PWD/results/" + + mv ./quarto/pixelatorES.html experiment-summary.html + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + experiment-summary: \$(Rscript -e 'cat(as.character(packageVersion("pixelatorES")), "\\n")') + END_VERSIONS + """ + + stub: + """ + touch experiment-summary.html + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + experiment-summary: \$(Rscript -e 'cat(as.character(packageVersion("pixelatorES")), "\\n")') + END_VERSIONS + """ +} diff --git a/modules/local/experiment_summary/tests/main.nf.test b/modules/local/experiment_summary/tests/main.nf.test new file mode 100644 index 00000000..93dfea28 --- /dev/null +++ b/modules/local/experiment_summary/tests/main.nf.test @@ -0,0 +1,166 @@ +nextflow_process { + + name "Test Process EXPERIMENT_SUMMARY" + script "../main.nf" + process "EXPERIMENT_SUMMARY" + tag "modules" + tag "pixelator" + tag "pixelator/pna" + tag "pixelator/experiment_summary" + + test("PNA experiment summary - small") { + when { + process { + """ + input[0] = [ file(params.pipelines_testdata_base_path + 'samplesheet/pna/samplesheet_pna_es.csv', checkIfExists: true) ] + input[1] = [ + [id:'all', design:'pna-2', panel:'proxiome-immuno-155', technology:'pna' ], + // amplicon + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // demux + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // (combined collapse) + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // graph + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // denoise + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // analysis + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // layout + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.layout.pxl', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_unfiltered_S7.layout.pxl', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { + with(process.out.html) { + assert path(get(0).get(1)).endsWith("experiment-summary.html") + assert path(get(0).get(1)).exists() + } + }, + { assert snapshot(process.out.versions).match("versions") }, + ) + } + } + + + + test("PNA experiment summary - stub") { + when { + process { + """ + input[0] = [ file(params.pipelines_testdata_base_path + 'samplesheet/pna/samplesheet_pna_es.csv', checkIfExists: true) ] + input[1] = [ + [id:'all', design:'pna-2', panel:'proxiome-immuno-155', technology:'pna' ], + // amplicon + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // demux + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // (combined collapse) + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // graph + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // denoise + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // analysis + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ], + // layout + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.layout.pxl', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_unfiltered_S7.layout.pxl', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_unfiltered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_unfiltered_S7.report.json', checkIfExists: true), + ] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { + with(process.out.html) { + assert path(get(0).get(1)).endsWith("experiment-summary.html") + assert path(get(0).get(1)).exists() + } + }, + { assert snapshot(process.out.versions).match("stub-versions") }, + ) + } + } +} diff --git a/modules/local/experiment_summary/tests/main.nf.test.snap b/modules/local/experiment_summary/tests/main.nf.test.snap new file mode 100644 index 00000000..0f6b5c0e --- /dev/null +++ b/modules/local/experiment_summary/tests/main.nf.test.snap @@ -0,0 +1,26 @@ +{ + "versions": { + "content": [ + [ + "versions.yml:md5,1c35ddcd59548b42fc730937c4263809" + ] + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.6" + }, + "timestamp": "2025-08-27T07:10:33.460197901" + }, + "stub-versions": { + "content": [ + [ + "versions.yml:md5,1c35ddcd59548b42fc730937c4263809" + ] + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.6" + }, + "timestamp": "2025-08-27T07:13:26.253720282" + } +} \ No newline at end of file diff --git a/modules/local/pixelator/list_options/main.nf b/modules/local/pixelator/list_options/main.nf index 23ac82af..19a25fca 100644 --- a/modules/local/pixelator/list_options/main.nf +++ b/modules/local/pixelator/list_options/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_LIST_OPTIONS { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" output: path "design_options.txt", emit: designs diff --git a/modules/local/pixelator/single-cell-mpx/amplicon/main.nf b/modules/local/pixelator/single-cell-mpx/amplicon/main.nf index b104b506..b4b1f1cf 100644 --- a/modules/local/pixelator/single-cell-mpx/amplicon/main.nf +++ b/modules/local/pixelator/single-cell-mpx/amplicon/main.nf @@ -6,8 +6,8 @@ process PIXELATOR_AMPLICON { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(reads) diff --git a/modules/local/pixelator/single-cell-mpx/amplicon/tests/main.nf.test b/modules/local/pixelator/single-cell-mpx/amplicon/tests/main.nf.test index e072c0ad..4355695d 100644 --- a/modules/local/pixelator/single-cell-mpx/amplicon/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-mpx/amplicon/tests/main.nf.test @@ -75,4 +75,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-mpx/amplicon/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-mpx/amplicon/tests/main.nf.test.snap index 2d290ebb..8bedeeef 100644 --- a/modules/local/pixelator/single-cell-mpx/amplicon/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-mpx/amplicon/tests/main.nf.test.snap @@ -39,7 +39,7 @@ "nf-test": "0.9.2", "nextflow": "25.04.2" }, - "timestamp": "2025-05-22T17:14:02.644424062" + "timestamp": "2025-07-28T11:06:59.496585652" }, "Test MPX amplicon - stub": { "content": [ @@ -89,7 +89,7 @@ ] ], "4": [ - "versions.yml:md5,ae1c0b9d6a279b22f0a6b4011b795f54" + "versions.yml:md5,bf50187b2cc40ff86ce55c588f21876d" ], "log": [ [ @@ -136,14 +136,14 @@ ] ], "versions": [ - "versions.yml:md5,ae1c0b9d6a279b22f0a6b4011b795f54" + "versions.yml:md5,bf50187b2cc40ff86ce55c588f21876d" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "25.04.2" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-22T17:13:19.244421007" + "timestamp": "2025-08-28T06:21:19.924751125" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-mpx/analysis/main.nf b/modules/local/pixelator/single-cell-mpx/analysis/main.nf index c5a97dae..7d118019 100644 --- a/modules/local/pixelator/single-cell-mpx/analysis/main.nf +++ b/modules/local/pixelator/single-cell-mpx/analysis/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_ANALYSIS { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(data) diff --git a/modules/local/pixelator/single-cell-mpx/analysis/tests/main.nf.test b/modules/local/pixelator/single-cell-mpx/analysis/tests/main.nf.test index bffb8e92..11e6d695 100644 --- a/modules/local/pixelator/single-cell-mpx/analysis/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-mpx/analysis/tests/main.nf.test @@ -50,20 +50,10 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot( - process.out.report_json, - process.out.metadata - ).match() - }, - { - with (process.out.dataset.get(0)) { - assert path(get(1)).zip.extract("adata.h5ad").exists() - assert path(get(1)).zip.extract("edgelist.parquet").exists() - assert snapshot( - path(get(1)).zip.extract("metadata.json") - ).match("pxl") - } - }, + {assert path(process.out.report_json.get(0).get(1)).exists()}, + {assert path(process.out.metadata.get(0).get(1)).exists()}, + {assert path(process.out.dataset.get(0).get(1)).exists()}, + {assert process.out.dataset.get(0).get(1).endsWith(".pxl")}, { with (process.out.log) { assert path(get(0).get(1)).readLines().last().contains("Finished pixelator analysis") @@ -73,4 +63,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-mpx/analysis/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-mpx/analysis/tests/main.nf.test.snap index f0cef13b..4816bb31 100644 --- a/modules/local/pixelator/single-cell-mpx/analysis/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-mpx/analysis/tests/main.nf.test.snap @@ -1,45 +1,4 @@ { - "Test MPX analysis - SCSP v1 | Immunology-I": { - "content": [ - [ - [ - { - "id": "sample01_1k_pbmcs_scsp_v1_immunology1", - "design": "D21", - "panel": "human-sc-immunology-spatial-proteomics-1", - "technology": "mpx" - }, - "sample01_1k_pbmcs_scsp_v1_immunology1.report.json:md5,5db6473f8c444276e3b287231fc87481" - ] - ], - [ - [ - { - "id": "sample01_1k_pbmcs_scsp_v1_immunology1", - "design": "D21", - "panel": "human-sc-immunology-spatial-proteomics-1", - "technology": "mpx" - }, - "sample01_1k_pbmcs_scsp_v1_immunology1.meta.json:md5,f2597ab5ea83e5257f8c96330df16484" - ] - ] - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" - }, - "timestamp": "2025-05-06T15:09:46.871992381" - }, - "pxl": { - "content": [ - "metadata.json:md5,57e6b62b023056bbe857829a5796bb7a" - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" - }, - "timestamp": "2025-05-06T15:09:46.933037588" - }, "Test MPX analysis - stub": { "content": [ { @@ -103,7 +62,7 @@ ] ], "5": [ - "versions.yml:md5,cba752118838dc2eab39eca1d236fb9e" + "versions.yml:md5,da2799a306092c4927321a66c981c358" ], "all_results": [ [ @@ -165,14 +124,14 @@ ] ], "versions": [ - "versions.yml:md5,cba752118838dc2eab39eca1d236fb9e" + "versions.yml:md5,da2799a306092c4927321a66c981c358" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:06:37.407882678" + "timestamp": "2025-08-28T06:21:35.05538814" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-mpx/annotate/main.nf b/modules/local/pixelator/single-cell-mpx/annotate/main.nf index 079a82ec..bee0aaf6 100644 --- a/modules/local/pixelator/single-cell-mpx/annotate/main.nf +++ b/modules/local/pixelator/single-cell-mpx/annotate/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_ANNOTATE { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(dataset), path(panel_file), val(panel) diff --git a/modules/local/pixelator/single-cell-mpx/annotate/tests/main.nf.test b/modules/local/pixelator/single-cell-mpx/annotate/tests/main.nf.test index 0e5cd5f0..72b07014 100644 --- a/modules/local/pixelator/single-cell-mpx/annotate/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-mpx/annotate/tests/main.nf.test @@ -57,11 +57,8 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot( - process.out.report_json, - process.out.metadata - ).match() - }, + {assert path(process.out.report_json.get(0).get(1)).exists()}, + {assert path(process.out.metadata.get(0).get(1)).exists()}, { with (process.out.dataset.get(0)) { assert path(get(1)).zip.extract("adata.h5ad").exists() @@ -80,4 +77,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-mpx/annotate/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-mpx/annotate/tests/main.nf.test.snap index e9ed6992..998b652e 100644 --- a/modules/local/pixelator/single-cell-mpx/annotate/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-mpx/annotate/tests/main.nf.test.snap @@ -1,44 +1,13 @@ { - "Test MPX annotate - SCSP v1 | Immunology-I": { - "content": [ - [ - [ - { - "id": "sample01_1k_pbmcs_scsp_v1_immunology1", - "design": "D21", - "panel": "human-sc-immunology-spatial-proteomics-1", - "technology": "mpx" - }, - "sample01_1k_pbmcs_scsp_v1_immunology1.report.json:md5,46497e565adecc96af90e90faffaf372" - ] - ], - [ - [ - { - "id": "sample01_1k_pbmcs_scsp_v1_immunology1", - "design": "D21", - "panel": "human-sc-immunology-spatial-proteomics-1", - "technology": "mpx" - }, - "sample01_1k_pbmcs_scsp_v1_immunology1.meta.json:md5,d665597d94d168a92632ec419a79617f" - ] - ] - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" - }, - "timestamp": "2025-05-06T15:10:43.635775337" - }, "pxl": { "content": [ - "metadata.json:md5,ac897f1995d7b8c3dc037e5bb0cf8026" + "metadata.json:md5,74c84444915851c0ef2e79f8c50a5265" ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:10:43.651855906" + "timestamp": "2025-08-28T06:22:57.937828169" }, "Test MPX annotate - stub": { "content": [ @@ -103,7 +72,7 @@ ] ], "5": [ - "versions.yml:md5,362a461b413bba48ee271ac7c2c00644" + "versions.yml:md5,9946c23bd209322c9d07000cdba9b30f" ], "all_results": [ [ @@ -165,14 +134,14 @@ ] ], "versions": [ - "versions.yml:md5,362a461b413bba48ee271ac7c2c00644" + "versions.yml:md5,9946c23bd209322c9d07000cdba9b30f" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:10:06.901396439" + "timestamp": "2025-08-28T06:22:43.841118883" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-mpx/collapse/main.nf b/modules/local/pixelator/single-cell-mpx/collapse/main.nf index 968e34ab..adda020d 100644 --- a/modules/local/pixelator/single-cell-mpx/collapse/main.nf +++ b/modules/local/pixelator/single-cell-mpx/collapse/main.nf @@ -6,8 +6,8 @@ process PIXELATOR_COLLAPSE { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(reads), path(panel_file), val(panel) diff --git a/modules/local/pixelator/single-cell-mpx/collapse/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-mpx/collapse/tests/main.nf.test.snap index 17f30810..afda146c 100644 --- a/modules/local/pixelator/single-cell-mpx/collapse/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-mpx/collapse/tests/main.nf.test.snap @@ -89,7 +89,7 @@ ] ], "4": [ - "versions.yml:md5,33ceab3376a4210ddbc799ac7a7ebe0e" + "versions.yml:md5,5506d89774209f01bda4884fc87ffc8d" ], "collapsed": [ [ @@ -136,14 +136,14 @@ ] ], "versions": [ - "versions.yml:md5,33ceab3376a4210ddbc799ac7a7ebe0e" + "versions.yml:md5,5506d89774209f01bda4884fc87ffc8d" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:11:14.246480277" + "timestamp": "2025-08-28T06:23:03.875538255" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-mpx/demux/main.nf b/modules/local/pixelator/single-cell-mpx/demux/main.nf index 4ef56c6f..eb281584 100644 --- a/modules/local/pixelator/single-cell-mpx/demux/main.nf +++ b/modules/local/pixelator/single-cell-mpx/demux/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_DEMUX { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(reads), path(panel_file), val(panel) diff --git a/modules/local/pixelator/single-cell-mpx/demux/tests/main.nf.test b/modules/local/pixelator/single-cell-mpx/demux/tests/main.nf.test index 2dfc5da9..39b4bafa 100644 --- a/modules/local/pixelator/single-cell-mpx/demux/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-mpx/demux/tests/main.nf.test @@ -77,4 +77,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-mpx/demux/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-mpx/demux/tests/main.nf.test.snap index 6e0368df..e879dcbd 100644 --- a/modules/local/pixelator/single-cell-mpx/demux/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-mpx/demux/tests/main.nf.test.snap @@ -58,7 +58,7 @@ ] ], "5": [ - "versions.yml:md5,ae56fdfb0890b69ef107b2940c461b33" + "versions.yml:md5,bbc9fbac3b95e696dacd1284c006c59b" ], "failed": [ [ @@ -116,15 +116,15 @@ ] ], "versions": [ - "versions.yml:md5,ae56fdfb0890b69ef107b2940c461b33" + "versions.yml:md5,bbc9fbac3b95e696dacd1284c006c59b" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:12:03.324003268" + "timestamp": "2025-08-28T06:23:19.18525599" }, "Test MPX demux - SCSP v1 | Immunology-I": { "content": [ @@ -243,14 +243,14 @@ ] ], [ - "versions.yml:md5,ae56fdfb0890b69ef107b2940c461b33" + "versions.yml:md5,bbc9fbac3b95e696dacd1284c006c59b" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:12:31.35960066" + "timestamp": "2025-08-28T06:23:31.586233595" }, "report_json": { "content": [ @@ -261,8 +261,8 @@ 3 ], "cutadapt_version": "5.0", - "python_version": "3.11.12", - "cores": 16, + "python_version": "3.12.11", + "cores": 4, "input": { "path1": "sample01_1k_pbmcs_scsp_v1_immunology1.processed.fastq.gz", "path2": null, @@ -2868,8 +2868,8 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:12:31.953138619" + "timestamp": "2025-08-28T06:23:31.865830713" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-mpx/graph/main.nf b/modules/local/pixelator/single-cell-mpx/graph/main.nf index 3b9dcf02..222aa0b4 100644 --- a/modules/local/pixelator/single-cell-mpx/graph/main.nf +++ b/modules/local/pixelator/single-cell-mpx/graph/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_GRAPH { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(edge_list) diff --git a/modules/local/pixelator/single-cell-mpx/graph/tests/main.nf.test b/modules/local/pixelator/single-cell-mpx/graph/tests/main.nf.test index ca0eca80..9e066b1e 100644 --- a/modules/local/pixelator/single-cell-mpx/graph/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-mpx/graph/tests/main.nf.test @@ -67,4 +67,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-mpx/graph/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-mpx/graph/tests/main.nf.test.snap index 847dad75..823758f6 100644 --- a/modules/local/pixelator/single-cell-mpx/graph/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-mpx/graph/tests/main.nf.test.snap @@ -104,7 +104,7 @@ ] ], "5": [ - "versions.yml:md5,8f016aac4cad3146ab620ee43f18769e" + "versions.yml:md5,a1a93db4f529ac7673675c34960d3f38" ], "all_results": [ [ @@ -166,14 +166,14 @@ ] ], "versions": [ - "versions.yml:md5,8f016aac4cad3146ab620ee43f18769e" + "versions.yml:md5,a1a93db4f529ac7673675c34960d3f38" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:12:51.304782952" + "timestamp": "2025-08-28T06:23:37.515356389" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-mpx/layout/main.nf b/modules/local/pixelator/single-cell-mpx/layout/main.nf index 2c9079af..a7d04d91 100644 --- a/modules/local/pixelator/single-cell-mpx/layout/main.nf +++ b/modules/local/pixelator/single-cell-mpx/layout/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_LAYOUT { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(data) diff --git a/modules/local/pixelator/single-cell-mpx/layout/tests/main.nf.test b/modules/local/pixelator/single-cell-mpx/layout/tests/main.nf.test index 6f90834c..0b09efe0 100644 --- a/modules/local/pixelator/single-cell-mpx/layout/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-mpx/layout/tests/main.nf.test @@ -79,4 +79,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-mpx/layout/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-mpx/layout/tests/main.nf.test.snap index d955020d..c864b113 100644 --- a/modules/local/pixelator/single-cell-mpx/layout/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-mpx/layout/tests/main.nf.test.snap @@ -103,7 +103,7 @@ ] ], "5": [ - "versions.yml:md5,8372f492411527afb668d03159f5cf2b" + "versions.yml:md5,edb14a73a037227849c470ce2d784137" ], "all_results": [ [ @@ -165,14 +165,14 @@ ] ], "versions": [ - "versions.yml:md5,8372f492411527afb668d03159f5cf2b" + "versions.yml:md5,edb14a73a037227849c470ce2d784137" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:13:34.808792997" + "timestamp": "2025-08-28T06:23:51.114411733" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-mpx/qc/main.nf b/modules/local/pixelator/single-cell-mpx/qc/main.nf index f96d1fef..7106fb2c 100644 --- a/modules/local/pixelator/single-cell-mpx/qc/main.nf +++ b/modules/local/pixelator/single-cell-mpx/qc/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_QC { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(reads) diff --git a/modules/local/pixelator/single-cell-mpx/qc/tests/main.nf.test b/modules/local/pixelator/single-cell-mpx/qc/tests/main.nf.test index 439ff91e..b1b2964c 100644 --- a/modules/local/pixelator/single-cell-mpx/qc/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-mpx/qc/tests/main.nf.test @@ -85,4 +85,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-mpx/qc/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-mpx/qc/tests/main.nf.test.snap index 50be8215..b479e5ce 100644 --- a/modules/local/pixelator/single-cell-mpx/qc/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-mpx/qc/tests/main.nf.test.snap @@ -97,7 +97,7 @@ ] ], "16": [ - "versions.yml:md5,e639f8b84132f6d23483d08dfc933599" + "versions.yml:md5,50b1b1443a2edf9e786504f2b832303f" ], "2": [ [ @@ -382,14 +382,14 @@ ] ], "versions": [ - "versions.yml:md5,e639f8b84132f6d23483d08dfc933599" + "versions.yml:md5,50b1b1443a2edf9e786504f2b832303f" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:14:33.70808719" + "timestamp": "2025-08-28T06:24:09.42162242" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-mpx/report/main.nf b/modules/local/pixelator/single-cell-mpx/report/main.nf index 774b2afc..3b01c1e9 100644 --- a/modules/local/pixelator/single-cell-mpx/report/main.nf +++ b/modules/local/pixelator/single-cell-mpx/report/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_REPORT { // TODO: Add conda back // conda "${moduleDir}/environment.yml" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(panel_file), val(panel) diff --git a/modules/local/pixelator/single-cell-mpx/report/tests/main.nf.test b/modules/local/pixelator/single-cell-mpx/report/tests/main.nf.test index 6540d59e..ccd8fab0 100644 --- a/modules/local/pixelator/single-cell-mpx/report/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-mpx/report/tests/main.nf.test @@ -153,4 +153,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-mpx/report/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-mpx/report/tests/main.nf.test.snap index ea71cc9e..feb311d0 100644 --- a/modules/local/pixelator/single-cell-mpx/report/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-mpx/report/tests/main.nf.test.snap @@ -25,7 +25,7 @@ ] ], "2": [ - "versions.yml:md5,60f4a660ecd6dce3dfb7943f258f40a5" + "versions.yml:md5,d0e22c07271c3e669b70e748959a0ffb" ], "log": [ [ @@ -50,27 +50,27 @@ ] ], "versions": [ - "versions.yml:md5,60f4a660ecd6dce3dfb7943f258f40a5" + "versions.yml:md5,d0e22c07271c3e669b70e748959a0ffb" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:15:36.810505624" + "timestamp": "2025-08-28T06:24:33.575047855" }, "Test MPX report - SCSP v1 | Immunology-I": { "content": [ null, [ - "versions.yml:md5,60f4a660ecd6dce3dfb7943f258f40a5" + "versions.yml:md5,d0e22c07271c3e669b70e748959a0ffb" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:16:03.182142967" + "timestamp": "2025-08-28T06:24:42.203502039" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-pna/amplicon/main.nf b/modules/local/pixelator/single-cell-pna/amplicon/main.nf index 35cbe1b2..60634075 100644 --- a/modules/local/pixelator/single-cell-pna/amplicon/main.nf +++ b/modules/local/pixelator/single-cell-pna/amplicon/main.nf @@ -5,8 +5,8 @@ process PIXELATOR_PNA_AMPLICON { // TODO: Add conda // conda "bioconda::pixelator=0.18.2" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(reads, arity: '1..*') diff --git a/modules/local/pixelator/single-cell-pna/amplicon/tests/main.nf.test b/modules/local/pixelator/single-cell-pna/amplicon/tests/main.nf.test index 31d37b8e..6e23f95d 100644 --- a/modules/local/pixelator/single-cell-pna/amplicon/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-pna/amplicon/tests/main.nf.test @@ -38,4 +38,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-pna/amplicon/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-pna/amplicon/tests/main.nf.test.snap index 52bc1bdf..a002e09d 100644 --- a/modules/local/pixelator/single-cell-pna/amplicon/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-pna/amplicon/tests/main.nf.test.snap @@ -9,7 +9,7 @@ "panel": "proxiome-immuno-155", "technology": "pna" }, - "PNA055_Sample07_filtered_S7.amplicon.fq.zst:md5,0a72e445b3899ca4aece43f2baa13e70" + "PNA055_Sample07_filtered_S7.amplicon.fq.zst:md5,460f0dd9af7c5ebec8bcad76e3964b7d" ] ] ], @@ -17,7 +17,7 @@ "nf-test": "0.9.2", "nextflow": "25.04.2" }, - "timestamp": "2025-06-18T13:24:23.05558255" + "timestamp": "2025-06-27T08:26:22.987687656" }, "report_json": { "content": [ diff --git a/modules/local/pixelator/single-cell-pna/analysis/main.nf b/modules/local/pixelator/single-cell-pna/analysis/main.nf index 34459110..6e49f498 100644 --- a/modules/local/pixelator/single-cell-pna/analysis/main.nf +++ b/modules/local/pixelator/single-cell-pna/analysis/main.nf @@ -6,8 +6,8 @@ process PIXELATOR_PNA_ANALYSIS { // conda "bioconda::pixelator=0.18.2" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(data) diff --git a/modules/local/pixelator/single-cell-pna/analysis/tests/main.nf.test b/modules/local/pixelator/single-cell-pna/analysis/tests/main.nf.test index 8263257b..97a17121 100644 --- a/modules/local/pixelator/single-cell-pna/analysis/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-pna/analysis/tests/main.nf.test @@ -38,4 +38,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-pna/analysis/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-pna/analysis/tests/main.nf.test.snap index b86c17b3..50925ed0 100644 --- a/modules/local/pixelator/single-cell-pna/analysis/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-pna/analysis/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "versions": { "content": [ [ - "versions.yml:md5,2d1a07140a8b47a20120030ca937b17f" + "versions.yml:md5,e04e75f13369e2ee24b9114c2d9d86cb" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:21:57.156086276" + "timestamp": "2025-08-28T06:25:43.662466623" }, "report_json": { "content": [ diff --git a/modules/local/pixelator/single-cell-pna/collapse/main.nf b/modules/local/pixelator/single-cell-pna/collapse/main.nf index 306fd8a1..fe1dc992 100644 --- a/modules/local/pixelator/single-cell-pna/collapse/main.nf +++ b/modules/local/pixelator/single-cell-pna/collapse/main.nf @@ -7,8 +7,8 @@ process PIXELATOR_PNA_COLLAPSE { // TODO: Add conda // conda "bioconda::pixelator=0.18.2" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(reads), path(panel_file), val(panel), val(design) diff --git a/modules/local/pixelator/single-cell-pna/collapse/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-pna/collapse/tests/main.nf.test.snap index 10790556..77f5aeb7 100644 --- a/modules/local/pixelator/single-cell-pna/collapse/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-pna/collapse/tests/main.nf.test.snap @@ -59,26 +59,26 @@ "versions": { "content": [ [ - "versions.yml:md5,bb0a7cb4ba82775da4724188e0adafaf" + "versions.yml:md5,a39e602f828076585b3e314469f16297" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:22:20.885778521" + "timestamp": "2025-08-28T06:25:53.937757371" }, "multi_versions": { "content": [ [ - "versions.yml:md5,bb0a7cb4ba82775da4724188e0adafaf" + "versions.yml:md5,a39e602f828076585b3e314469f16297" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:22:45.539202416" + "timestamp": "2025-08-28T06:26:04.668538674" }, "header": { "content": [ diff --git a/modules/local/pixelator/single-cell-pna/combine_collapse/main.nf b/modules/local/pixelator/single-cell-pna/combine_collapse/main.nf index d9ba053a..9d811ba0 100644 --- a/modules/local/pixelator/single-cell-pna/combine_collapse/main.nf +++ b/modules/local/pixelator/single-cell-pna/combine_collapse/main.nf @@ -6,8 +6,8 @@ process PIXELATOR_PNA_COMBINE_COLLAPSE { // conda "bioconda::pixelator=0.18.2" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(parquet_files, stageAs: "parquet/*"), path(json_report_files, stageAs: "reports/*") diff --git a/modules/local/pixelator/single-cell-pna/combine_collapse/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-pna/combine_collapse/tests/main.nf.test.snap index f339bdbe..80b383cb 100644 --- a/modules/local/pixelator/single-cell-pna/combine_collapse/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-pna/combine_collapse/tests/main.nf.test.snap @@ -24,13 +24,13 @@ ] ], [ - "versions.yml:md5,1504b7b37e1e2aff46caec380024adc2" + "versions.yml:md5,8dd7d21ecf0788170bb71a252525f8a4" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:23:09.893021534" + "timestamp": "2025-08-28T06:26:13.840544303" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-pna/demux/main.nf b/modules/local/pixelator/single-cell-pna/demux/main.nf index ae0de739..7efdb68d 100644 --- a/modules/local/pixelator/single-cell-pna/demux/main.nf +++ b/modules/local/pixelator/single-cell-pna/demux/main.nf @@ -6,8 +6,8 @@ process PIXELATOR_PNA_DEMUX { // conda "bioconda::pixelator=0.18.2" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(reads), path(panel_file), val(panel), val(design) diff --git a/modules/local/pixelator/single-cell-pna/demux/tests/main.nf.test b/modules/local/pixelator/single-cell-pna/demux/tests/main.nf.test index 380370e9..dc531252 100644 --- a/modules/local/pixelator/single-cell-pna/demux/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-pna/demux/tests/main.nf.test @@ -10,6 +10,9 @@ nextflow_process { test("PNA demux - small test") { when { + params { + skip_experiment_summary = true + } process { """ input[0] = [ @@ -48,6 +51,9 @@ nextflow_process { config "./multiple_chunks.config" when { + params { + skip_experiment_summary = true + } process { """ input[0] = [ @@ -82,4 +88,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-pna/demux/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-pna/demux/tests/main.nf.test.snap index 749ae3e4..86df347e 100644 --- a/modules/local/pixelator/single-cell-pna/demux/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-pna/demux/tests/main.nf.test.snap @@ -129,15 +129,15 @@ "panel": "proxiome-immuno-155", "technology": "pna" }, - "PNA055_Sample07_filtered_S7.meta.json:md5,d1f57d2764f4dac79eee0f03860e4484" + "PNA055_Sample07_filtered_S7.meta.json:md5,e264dd4b88e2ef36d8af6640adbe79ac" ] ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.5" + "nextflow": "25.04.2" }, - "timestamp": "2025-03-20T10:45:20.481383302" + "timestamp": "2025-06-24T17:10:34.346405357" }, "metadata_json": { "content": [ @@ -149,7 +149,7 @@ "panel": "proxiome-immuno-155", "technology": "pna" }, - "PNA055_Sample07_filtered_S7.meta.json:md5,76e64fbe2518c5c56da1316c2e6afbd3" + "PNA055_Sample07_filtered_S7.meta.json:md5,2bd1ff0d69fc6584e455196d8805f587" ] ] ], @@ -157,6 +157,6 @@ "nf-test": "0.9.2", "nextflow": "25.04.2" }, - "timestamp": "2025-05-22T17:34:08.919733329" + "timestamp": "2025-06-24T17:09:59.60486159" } } \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-pna/denoise/main.nf b/modules/local/pixelator/single-cell-pna/denoise/main.nf new file mode 100644 index 00000000..29fe7cea --- /dev/null +++ b/modules/local/pixelator/single-cell-pna/denoise/main.nf @@ -0,0 +1,64 @@ +process PIXELATOR_PNA_DENOISE { + tag "$meta.id" + label 'process_high' + + // TODO: Add conda + // conda "bioconda::pixelator=0.18.2" + + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" + + input: + tuple val(meta), path(data) + + output: + tuple val(meta), path("denoise/*.pxl") , emit: pixelfile + tuple val(meta), path("denoise/*.report.json") , emit: report_json + tuple val(meta), path("denoise/*.meta.json") , emit: metadata_json + tuple val(meta), path("denoise/*") , emit: all_results + tuple val(meta), path("*pixelator-denoise.log") , emit: log + + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + + prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + + """ + pixelator \\ + --cores $task.cpus \\ + --log-file ${prefix}.pixelator-denoise.log \\ + --verbose \\ + single-cell-pna \\ + denoise \\ + --output . \\ + $args \\ + $data + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + pixelator: \$(echo \$(pixelator --version 2>/dev/null) | sed 's/pixelator, version //g' ) + END_VERSIONS + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + + """ + mkdir denoise + touch denoise/${prefix}.report.json + touch denoise/${prefix}.meta.json + touch denoise/${prefix}.pxl + touch ${prefix}.pixelator-denoise.log + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + pixelator: \$(echo \$(pixelator --version 2>/dev/null) | sed 's/pixelator, version //g' ) + END_VERSIONS + """ +} diff --git a/modules/local/pixelator/single-cell-pna/denoise/tests/main.nf.test b/modules/local/pixelator/single-cell-pna/denoise/tests/main.nf.test new file mode 100644 index 00000000..152571a1 --- /dev/null +++ b/modules/local/pixelator/single-cell-pna/denoise/tests/main.nf.test @@ -0,0 +1,40 @@ +nextflow_process { + + name "Test Process PIXELATOR_PNA_DENOISE" + script "../main.nf" + process "PIXELATOR_PNA_DENOISE" + tag "modules" + tag "pixelator" + tag "pixelator/pna" + tag "pixelator/single_cell_pna_denoise" + + test("PNA denoise - small test") { + when { + process { + """ + input[0] = [ + [ id:'PNA055_Sample07_filtered_S7', design:'pna-2', panel:'proxiome-immuno-155', technology:'pna' ], + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.graph.pxl', checkIfExists: true), + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out.metadata_json).match("metadata_json") }, + { + with (process.out.report_json) { + assert snapshot(path(get(0).get(1)).readLines()[0..5]).match("report_json") } + }, + { assert snapshot(process.out.versions).match("versions") }, + { + with (process.out.log) { + assert path(get(0).get(1)).readLines().last().contains("Finished pixelator denoise") + } + }, + ) + } + } +} diff --git a/modules/local/pixelator/single-cell-pna/denoise/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-pna/denoise/tests/main.nf.test.snap new file mode 100644 index 00000000..960c3d9c --- /dev/null +++ b/modules/local/pixelator/single-cell-pna/denoise/tests/main.nf.test.snap @@ -0,0 +1,51 @@ +{ + "versions": { + "content": [ + [ + "versions.yml:md5,f5d5ee43ffc7aa33ba098ca7c17411a5" + ] + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.6" + }, + "timestamp": "2025-08-28T06:27:05.223650997" + }, + "report_json": { + "content": [ + [ + "{", + " \"sample_id\": \"PNA055_Sample07_filtered_S7\",", + " \"product_id\": \"single-cell-pna\",", + " \"report_type\": \"denoise\",", + " \"number_of_umis_removed\": 599,", + " \"ratio_of_umis_removed\": 0.019271604143877484," + ] + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.2" + }, + "timestamp": "2025-06-27T14:53:31.61894306" + }, + "metadata_json": { + "content": [ + [ + [ + { + "id": "PNA055_Sample07_filtered_S7", + "design": "pna-2", + "panel": "proxiome-immuno-155", + "technology": "pna" + }, + "PNA055_Sample07_filtered_S7.meta.json:md5,d0728a1efc25964039497c7bc22cdc35" + ] + ] + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.2" + }, + "timestamp": "2025-06-27T14:53:31.58914569" + } +} \ No newline at end of file diff --git a/modules/local/pixelator/single-cell-pna/graph/main.nf b/modules/local/pixelator/single-cell-pna/graph/main.nf index 7809e5eb..0a2134b7 100644 --- a/modules/local/pixelator/single-cell-pna/graph/main.nf +++ b/modules/local/pixelator/single-cell-pna/graph/main.nf @@ -4,8 +4,8 @@ process PIXELATOR_PNA_GRAPH { label 'process_long' container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(edge_list), path(panel_file), val(panel) diff --git a/modules/local/pixelator/single-cell-pna/graph/tests/main.nf.test b/modules/local/pixelator/single-cell-pna/graph/tests/main.nf.test index 177583a4..d6824f66 100644 --- a/modules/local/pixelator/single-cell-pna/graph/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-pna/graph/tests/main.nf.test @@ -41,4 +41,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-pna/graph/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-pna/graph/tests/main.nf.test.snap index afabe882..cce8274c 100644 --- a/modules/local/pixelator/single-cell-pna/graph/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-pna/graph/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "versions": { "content": [ [ - "versions.yml:md5,014a0d8870a21fc70b6025ee7813a4cd" + "versions.yml:md5,c2b5282ea89815e5acfa1149ebc9e585" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:25:29.63045379" + "timestamp": "2025-08-28T06:27:13.929297872" }, "report_json": { "content": [ @@ -21,7 +21,7 @@ "panel": "proxiome-immuno-155", "technology": "pna" }, - "PNA055_Sample07_filtered_S7.report.json:md5,25236e45949c32ce93506db00eda246a" + "PNA055_Sample07_filtered_S7.report.json:md5,8c7cfca24198dc8d0dd2fd9551c08b97" ] ] ], @@ -29,7 +29,7 @@ "nf-test": "0.9.2", "nextflow": "25.04.2" }, - "timestamp": "2025-05-22T17:35:26.902757909" + "timestamp": "2025-06-24T17:10:53.237758536" }, "metadata_json": { "content": [ diff --git a/modules/local/pixelator/single-cell-pna/layout/main.nf b/modules/local/pixelator/single-cell-pna/layout/main.nf index 46e624d5..d2836806 100644 --- a/modules/local/pixelator/single-cell-pna/layout/main.nf +++ b/modules/local/pixelator/single-cell-pna/layout/main.nf @@ -1,12 +1,12 @@ process PIXELATOR_PNA_LAYOUT { tag "${meta.id}" - label 'process_high_memory' + label 'process_high' // TODO: Add conda // conda "bioconda::pixelator=0.18.2" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: tuple val(meta), path(data) diff --git a/modules/local/pixelator/single-cell-pna/report/main.nf b/modules/local/pixelator/single-cell-pna/report/main.nf index 1af02da8..b119cfaf 100644 --- a/modules/local/pixelator/single-cell-pna/report/main.nf +++ b/modules/local/pixelator/single-cell-pna/report/main.nf @@ -6,18 +6,22 @@ process PIXELATOR_PNA_REPORT { // TODO: Add conda // conda "bioconda::pixelator=0.18.2" container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'ghcr.io/pixelgentechnologies/pixelator:0.20.1' - : 'ghcr.io/pixelgentechnologies/pixelator:0.20.1'}" + ? 'quay.io/pixelgen-technologies/pixelator:0.21.4' + : 'quay.io/pixelgen-technologies/pixelator:0.21.4'}" input: - tuple val(meta), path(panel_file), val(panel) - path amplicon_data, stageAs: "results/amplicon/*" - path demux_data, stageAs: "results/demux/*" - path collapse_data, stageAs: "results/collapse/*" - path graph_data, stageAs: "results/graph/*" - path analysis_data, stageAs: "results/analysis/*" - path post_analysis_data, stageAs: "results/post_analysis/*" - path layout_data, stageAs: "results/layout/*" + tuple ( + val(meta), + path(panel_file), + val(panel), + path(amplicon_data, stageAs: "results/amplicon/*"), + path(demux_data, stageAs: "results/demux/*"), + path(collapse_data, stageAs: "results/collapse/*"), + path(graph_data, stageAs: "results/graph/*"), + path(denoise_data, stageAs: "results/denoise/*"), + path(analysis_data, stageAs: "results/analysis/*"), + path(layout_data, stageAs: "results/layout/*") + ) output: tuple val(meta), path("report/*.html"), emit: report diff --git a/modules/local/pixelator/single-cell-pna/report/tests/main.nf.test b/modules/local/pixelator/single-cell-pna/report/tests/main.nf.test index 18f55b1d..078f2094 100644 --- a/modules/local/pixelator/single-cell-pna/report/tests/main.nf.test +++ b/modules/local/pixelator/single-cell-pna/report/tests/main.nf.test @@ -16,35 +16,35 @@ nextflow_process { [ id:'PNA055_Sample07_filtered_S7', design:'pna-2', panel:'proxiome-immuno-155', technology:'pna' ], [], 'proxiome-immuno-155', - ] - input[1] = [ - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), - ] - input[2] = [ - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), - ] - input[3] = [ - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), - ] - input[4] = [ - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.graph.pxl', checkIfExists: true), - ] - input[5] = [ - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), - ] - input[6] = [ - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/post_analysis/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/post_analysis/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), - ] - input[7] = [ - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), - file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/amplicon/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + ], + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/demux/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + ], + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/collapse/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + ], + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/graph/PNA055_Sample07_filtered_S7.graph.pxl', checkIfExists: true), + ], + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/denoise/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + ], + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/analysis/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + ], + [ + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.meta.json', checkIfExists: true), + file(params.pipelines_testdata_base_path + 'testdata/pna/modules/layout/PNA055_Sample07_filtered_S7.report.json', checkIfExists: true), + ] ] """ } @@ -66,4 +66,3 @@ nextflow_process { } } } - diff --git a/modules/local/pixelator/single-cell-pna/report/tests/main.nf.test.snap b/modules/local/pixelator/single-cell-pna/report/tests/main.nf.test.snap index b75a655f..f186d128 100644 --- a/modules/local/pixelator/single-cell-pna/report/tests/main.nf.test.snap +++ b/modules/local/pixelator/single-cell-pna/report/tests/main.nf.test.snap @@ -2,13 +2,13 @@ "versions": { "content": [ [ - "versions.yml:md5,42b1d77f0c9a9c714a0d736117873bc2" + "versions.yml:md5,b8568f43655813b75e8cbd407a14661d" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:26:09.344032637" + "timestamp": "2025-09-17T14:22:24.534737422" } } \ No newline at end of file diff --git a/nextflow.config b/nextflow.config index 1b733dde..03cbbae8 100644 --- a/nextflow.config +++ b/nextflow.config @@ -87,6 +87,7 @@ params { // skip options skip_report = false + skip_denoise = false skip_analysis = false skip_layout = false @@ -105,6 +106,7 @@ params { save_pna_demux_failed_reads = false save_pna_collapsed_reads = false save_pna_graph_pixelfile = false + save_pna_denoise_pixelfile = false save_pna_analysis_pixelfile = false // PNA amplicon @@ -137,6 +139,11 @@ params { pna_graph_graph_min_component_size_to_prune = 100 pna_graph_component_size_min_threshold = null + // PNA denoise + pna_denoise_run_one_core_graph_denoising = true + pna_denoise_pval_threshold = 0.05 + pna_denoise_inflate_factor = 1.5 + // PNA analysis pna_analysis_compute_proximity = true pna_analysis_proximity_nbr_of_permutations = 100 @@ -150,6 +157,9 @@ params { pna_layout_pmds_pivots = 50 pna_layout_wpmds_k = 5 + // Experiment summary + skip_experiment_summary = false + // Common output options save_json = true save_all = false @@ -187,6 +197,10 @@ includeConfig 'conf/base.config' def container_env_options = [ "MPLCONFIGDIR": '/tmp/.config/matplotlib', "NUMBA_CACHE_DIR": "/tmp/.numba_cache", + + // quarto needs a writeable cache directory + "XDG_CACHE_HOME": "/tmp/.cache", + "XDG_DATA_HOME": "/tmp/.data", ] profiles { @@ -302,6 +316,12 @@ profiles { ] } } + gpu { + docker.runOptions = '-u $(id -u):$(id -g) --gpus all' + apptainer.runOptions = '--nv' + singularity.runOptions = '--nv' + } + test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } test_panel_v2 { includeConfig 'conf/test_panel_v2.config' } @@ -309,11 +329,8 @@ profiles { test_pna { includeConfig 'conf/test_pna.config' } } -// Load nf-core custom profiles from different Institutions -includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${params.custom_config_base}/nfcore_custom.config" : "/dev/null" - -// Load nf-core/pixelator custom profiles from different institutions. -includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${params.custom_config_base}/pipeline/pixelator.config" : "/dev/null" +// Load nf-core custom profiles from different institutions +includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !params.custom_config_base.startsWith('http')) ? "${params.custom_config_base}/nfcore_custom.config" : "/dev/null" // Set default registry for Apptainer, Docker, Podman, Charliecloud and Singularity independent of -profile // Will not be used unless Apptainer / Docker / Podman / Charliecloud / Singularity are enabled @@ -400,14 +417,14 @@ manifest { description = """Pipeline for analysis of Molecular Pixelation assays""" mainScript = 'main.nf' defaultBranch = 'master' - nextflowVersion = '!>=24.04.2' - version = '2.0.0' + nextflowVersion = '!>=24.10.5' + version = '2.1.0' doi = '10.1101/2023.06.05.543770' } // Nextflow plugins plugins { - id 'nf-schema@2.2.0' // Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-schema@2.4.2' // Validation of pipeline parameters and creation of an input channel from a sample sheet } validation { diff --git a/nextflow_schema.json b/nextflow_schema.json index 4355b2b5..a3ab14f0 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -511,6 +511,40 @@ } } }, + "pna_denoise_options": { + "title": "Options for pixelator denoise command.", + "type": "object", + "properties": { + "skip_denoise": { + "description": "Skip denoise step", + "type": "boolean" + }, + "save_pna_denoise_pixelfile": { + "fa_icon": "fas fa-save", + "type": "boolean", + "default": false, + "description": "Save the PXL dataset after the denoise stage.", + "help": "By default, the PXL file after denoise will not be saved to the results directory." + }, + "pna_denoise_run_one_core_graph_denoising": { + "description": "Activate the one-core graph denoising algorithm", + "type": "boolean", + "default": true + }, + "pna_denoise_pval_threshold": { + "type": "number", + "description": "The p-value threshold for the a marker to be considered significantly over-expressed in the one-core layer of a component", + "default": 0.05, + "minimum": 0.0 + }, + "pna_denoise_inflate_factor": { + "type": "number", + "description": "The inflate factor for the number of nodes from over-expressed markers to be removed from the one-core layer of a component", + "default": 1.5, + "minimum": 1.0 + } + } + }, "analysis_options": { "title": "Options for pixelator analysis command.", "type": "object", @@ -701,6 +735,16 @@ } } }, + "experiment_summary_options": { + "title": "Options for experiment summary.", + "type": "object", + "properties": { + "skip_experiment_summary": { + "description": "Skip experiment summary generation", + "type": "boolean" + } + } + }, "global_config_options": { "title": "Global options", "type": "object", @@ -877,6 +921,9 @@ { "$ref": "#/$defs/pna_graph_options" }, + { + "$ref": "#/$defs/pna_denoise_options" + }, { "$ref": "#/$defs/annotate_options" }, @@ -895,6 +942,9 @@ { "$ref": "#/$defs/report_options" }, + { + "$ref": "#/$defs/experiment_summary_options" + }, { "$ref": "#/$defs/global_config_options" }, diff --git a/nf-test.config b/nf-test.config index 84c773dd..fc8042d8 100644 --- a/nf-test.config +++ b/nf-test.config @@ -1,16 +1,21 @@ config { - // Location of nf-tests + // location for all nf-test tests testsDir "." - // nf-test directory used to create temporary files for each test + // nf-test directory including temporary files for each test workDir System.getenv("NFT_WORKDIR") ?: ".nf-test" - // Location of an optional nextflow.config file specific for executing pipeline tests + // location of an optional nextflow.config file specific for executing tests configFile "tests/nextflow.config" + // ignore tests coming from the nf-core/modules repo + ignore 'modules/nf-core/**/tests/*', 'subworkflows/nf-core/**/tests/*' + // run all test with defined profile(s) from the main nextflow.config - profile "test_scsp_v1_immunology_v1" - triggers 'nextflow.config', 'nf-test.config', 'conf/test.config', 'conf/test_full.config' + profile "test" + + // list of filenames or patterns that should be trigger a full test run + triggers 'nextflow.config', 'nf-test.config', 'conf/test.config', 'tests/nextflow.config', 'tests/.nftignore' // load the necessary plugins plugins { diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index d8a94b37..f1702efb 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -22,8 +22,8 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "Stable", - "datePublished": "2025-05-27T08:46:46+00:00", - "description": "

\n \n \n \"nf-core/pixelator\"\n \n

\n\n[![GitHub Actions CI Status](https://github.com/nf-core/pixelator/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/pixelator/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/pixelator/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/pixelator/actions/workflows/linting.yml)\n[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/pixelator/results)\n[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A524.04.2-23aa62.svg)](https://www.nextflow.io/)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\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[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/pixelator)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23pixelator-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/pixelator)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core)\n\n## Introduction\n\n**nf-core/pixelator** is a bioinformatics best-practice analysis pipeline for analysis of data from the\nMolecular Pixelation (MPX) and Proximity Network (PNA) assays. It takes a samplesheet as input and will process your data\nusing `pixelator` to produce a PXL file containing single-cell protein abundance and protein interactomics data.\n\n![](./docs/images/nf-core-pixelator-metromap.svg)\n\nDepending on the input data the pipeline will run different steps.\n\nFor PNA data, the pipeline will run the following steps:\n\n1. Do quality control checks of input reads and build amplicons ([`pixelator single-cell-pna amplicon`](https://github.com/PixelgenTechnologies/pixelator))\n2. Create groups of amplicons based on their marker assignments ([`pixelator single-cell-pna demux`](https://github.com/PixelgenTechnologies/pixelator))\n3. Derive original molecules to use as edge list downstream by error correcting, and counting input amplicons ([`pixelator single-cell-pna collapse`](https://github.com/PixelgenTechnologies/pixelator))\n4. Compute the components of the graph from the edge list in order to create putative cells ([`pixelator single-cell-pna graph`](https://github.com/PixelgenTechnologies/pixelator))\n5. Analyze the spatial information in the cell graphs ([`pixelator single-cell-pna analysis`](https://github.com/PixelgenTechnologies/pixelator))\n6. Generate 3D graph layouts for visualization of cells ([`pixelator single-cell-pna layout`](https://github.com/PixelgenTechnologies/pixelator))\n7. Report generation ([`pixelator single-cell-pna report`](https://github.com/PixelgenTechnologies/pixelator))\n\nFor MPX data, the pipeline will run the following steps:\n\n1. Build an amplicons from the input reads ([`pixelator single-cell-mpx amplicon`](https://github.com/PixelgenTechnologies/pixelator))\n2. Read QC and filtering, correctness of the pixel binding sequence sequences ([`pixelator single-cell-mpx preqc | pixelator adapterqc`](https://github.com/PixelgenTechnologies/pixelator))\n3. Assign a marker (barcode) to each read ([`pixelator single-cell-mpx demux`](https://github.com/PixelgenTechnologies/pixelator))\n4. Error correction, duplicate removal, compute read counts ([`pixelator single-cell-mpx collapse`](https://github.com/PixelgenTechnologies/pixelator))\n5. Compute the components of the graph from the edge list in order to create putative cells ([`pixelator single-cell-mpx graph`](https://github.com/PixelgenTechnologies/pixelator))\n6. Call and annotate cells ([`pixelator single-cell-mpx annotate`](https://github.com/PixelgenTechnologies/pixelator))\n7. Analyze the cells for polarization and colocalization ([`pixelator single-cell-mpx analysis`](https://github.com/PixelgenTechnologies/pixelator))\n8. Generate 3D graph layouts for visualization of cells ([`pixelator single-cell-mpx layout`](https://github.com/PixelgenTechnologies/pixelator))\n9. Report generation ([`pixelator single-cell-mpx report`](https://github.com/PixelgenTechnologies/pixelator))\n\n> [!WARNING]\n> Since Nextflow 23.07.0-edge, Nextflow no longer mounts the host's home directory when using Apptainer or Singularity.\n> This causes issues in some dependencies. As a workaround, you can revert to the old behavior by setting the environment variable\n> `NXF_APPTAINER_HOME_MOUNT` or `NXF_SINGULARITY_HOME_MOUNT` to `true` in the machine from which you launch the pipeline.\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data.\n\nFirst, prepare a samplesheet with your input data that looks as follows (the exact values you need to input depend on the design and panel you are using):\n\n`samplesheet.csv`:\n\n```csv\nsample,design,panel,fastq_1,fastq_2\nsample1,pna-2,proxiome-immuno-155,sample1_R1_001.fastq.gz,sample1_R2_001.fastq.gz\n```\n\nEach row represents a sample and gives the design, a panel file and the input fastq files.\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run nf-core/pixelator \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\n\n> [!WARNING]\n> This version of the pipeline does not support conda environments, due to issues with upstream dependencies.\n> This means you cannot use the `conda` and `mamba` profiles. Please use `docker` or `singularity` instead.\n> We hope to add support for conda environments in the future.\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/usage/getting_started/configuration#custom-configuration-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/pixelator/usage) and the [parameter documentation](https://nf-co.re/pixelator/parameters).\n\n## Pipeline output\n\nTo see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/pixelator/results) tab on the nf-core website pipeline page.\nFor more details about the output files and reports, please refer to the\n[output documentation](https://nf-co.re/pixelator/output).\n\n## Credits\n\nnf-core/pixelator was originally written for [Pixelgen Technologies AB](https://www.pixelgen.com/) by:\n\n- Florian De Temmerman\n- Johan Dahlberg\n- Alvaro Martinez Barrio\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#pixelator` channel](https://nfcore.slack.com/channels/pixelator) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\nIf you use nf-core/pixelator for your analysis, please cite it using the following doi: [10.5281/zenodo.10015112](https://doi.org/10.5281/zenodo.10015112)\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nYou can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n\nYou can cite the molecular pixelation technology as follows:\n\n> **Molecular pixelation: spatial proteomics of single cells by sequencing.**\n>\n> Filip Karlsson, Tomasz Kallas, Divya Thiagarajan, Max Karlsson, Maud Schweitzer, Jose Fernandez Navarro, Louise Leijonancker, Sylvain Geny, Erik Pettersson, Jan Rhomberg-Kauert, Ludvig Larsson, Hanna van Ooijen, Stefan Petkov, Marcela Gonz\u00e1lez-Granillo, Jessica Bunz, Johan Dahlberg, Michele Simonetti, Prajakta Sathe, Petter Brodin, Alvaro Martinez Barrio & Simon Fredriksson\n>\n> _Nat Methods._ 2024 May 08. doi: [10.1038/s41592-024-02268-9](https://doi.org/10.1038/s41592-024-02268-9)\n", + "datePublished": "2025-09-01T07:00:42+00:00", + "description": "

\n \n \n \"nf-core/pixelator\"\n \n

\n\n[![GitHub Actions CI Status](https://github.com/nf-core/pixelator/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/pixelator/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/pixelator/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/pixelator/actions/workflows/linting.yml)\n[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/pixelator/results)\n[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.10015112-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.10015112)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A524.10.5-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-3.3.2-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/3.3.2)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\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[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/pixelator)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23pixelator-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/pixelator)[![Follow on Bluesky](https://img.shields.io/badge/bluesky-%40nf__core-1185fe?labelColor=000000&logo=bluesky)](https://bsky.app/profile/nf-co.re)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core)\n\n## Introduction\n\n**nf-core/pixelator** is a bioinformatics best-practice analysis pipeline for analysis of data from the\nMolecular Pixelation (MPX) and Proximity Network (PNA) assays. It takes a samplesheet as input and will process your data\nusing `pixelator` to produce a PXL file containing single-cell protein abundance and protein interactomics data.\n\n![](./docs/images/nf-core-pixelator-metromap.svg)\n\nDepending on the input data the pipeline will run different steps.\n\nFor PNA data, the pipeline will run the following steps:\n\n1. Do quality control checks of input reads and build amplicons ([`pixelator single-cell-pna amplicon`](https://github.com/PixelgenTechnologies/pixelator))\n2. Create groups of amplicons based on their marker assignments ([`pixelator single-cell-pna demux`](https://github.com/PixelgenTechnologies/pixelator))\n3. Derive original molecules to use as edge list downstream by error correcting, and counting input amplicons ([`pixelator single-cell-pna collapse`](https://github.com/PixelgenTechnologies/pixelator))\n4. Compute the components of the graph from the edge list in order to create putative cells ([`pixelator single-cell-pna graph`](https://github.com/PixelgenTechnologies/pixelator))\n5. Denoise the cell graphs ([`pixelator single-cell-pna denoise`](https://github.com/PixelgenTechnologies/pixelator))\n6. Analyze the spatial information in the cell graphs ([`pixelator single-cell-pna analysis`](https://github.com/PixelgenTechnologies/pixelator))\n7. Generate 3D graph layouts for visualization of cells ([`pixelator single-cell-pna layout`](https://github.com/PixelgenTechnologies/pixelator))\n8. Report generation ([`pixelator single-cell-pna report`](https://github.com/PixelgenTechnologies/pixelator))\n\nFor MPX data, the pipeline will run the following steps:\n\n1. Build an amplicons from the input reads ([`pixelator single-cell-mpx amplicon`](https://github.com/PixelgenTechnologies/pixelator))\n2. Read QC and filtering, correctness of the pixel binding sequence sequences ([`pixelator single-cell-mpx preqc | pixelator adapterqc`](https://github.com/PixelgenTechnologies/pixelator))\n3. Assign a marker (barcode) to each read ([`pixelator single-cell-mpx demux`](https://github.com/PixelgenTechnologies/pixelator))\n4. Error correction, duplicate removal, compute read counts ([`pixelator single-cell-mpx collapse`](https://github.com/PixelgenTechnologies/pixelator))\n5. Compute the components of the graph from the edge list in order to create putative cells ([`pixelator single-cell-mpx graph`](https://github.com/PixelgenTechnologies/pixelator))\n6. Call and annotate cells ([`pixelator single-cell-mpx annotate`](https://github.com/PixelgenTechnologies/pixelator))\n7. Analyze the cells for polarization and colocalization ([`pixelator single-cell-mpx analysis`](https://github.com/PixelgenTechnologies/pixelator))\n8. Generate 3D graph layouts for visualization of cells ([`pixelator single-cell-mpx layout`](https://github.com/PixelgenTechnologies/pixelator))\n9. Report generation ([`pixelator single-cell-mpx report`](https://github.com/PixelgenTechnologies/pixelator))\n\n> [!WARNING]\n> Since Nextflow 23.07.0-edge, Nextflow no longer mounts the host's home directory when using Apptainer or Singularity.\n> This causes issues in some dependencies. As a workaround, you can revert to the old behavior by setting the environment variable\n> `NXF_APPTAINER_HOME_MOUNT` or `NXF_SINGULARITY_HOME_MOUNT` to `true` in the machine from which you launch the pipeline.\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data.\n\nFirst, prepare a samplesheet with your input data that looks as follows (the exact values you need to input depend on the design and panel you are using):\n\n`samplesheet.csv`:\n\n```csv\nsample,sample_alias,condition,design,panel,fastq_1,fastq_2\nsample1,s1,control,pna-2,proxiome-immuno-155,sample1_R1_001.fastq.gz,sample1_R2_001.fastq.gz\n```\n\nEach row represents a sample and gives the design, a panel file and the input fastq files.\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run nf-core/pixelator \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\n\n> [!WARNING]\n> This version of the pipeline does not support conda environments, due to issues with upstream dependencies.\n> This means you cannot use the `conda` and `mamba` profiles. Please use `docker` or `singularity` instead.\n> We hope to add support for conda environments in the future.\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/usage/getting_started/configuration#custom-configuration-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/pixelator/usage) and the [parameter documentation](https://nf-co.re/pixelator/parameters).\n\n## Pipeline output\n\nTo see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/pixelator/results) tab on the nf-core website pipeline page.\nFor more details about the output files and reports, please refer to the\n[output documentation](https://nf-co.re/pixelator/output).\n\n## Credits\n\nnf-core/pixelator was originally written for [Pixelgen Technologies AB](https://www.pixelgen.com/) by:\n\n- Florian De Temmerman\n- Johan Dahlberg\n- Alvaro Martinez Barrio\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#pixelator` channel](https://nfcore.slack.com/channels/pixelator) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\nIf you use nf-core/pixelator for your analysis, please cite it using the following doi: [10.5281/zenodo.10015112](https://doi.org/10.5281/zenodo.10015112)\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nYou can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n\nYou can cite the molecular pixelation technology as follows:\n\n> **Molecular pixelation: spatial proteomics of single cells by sequencing.**\n>\n> Filip Karlsson, Tomasz Kallas, Divya Thiagarajan, Max Karlsson, Maud Schweitzer, Jose Fernandez Navarro, Louise Leijonancker, Sylvain Geny, Erik Pettersson, Jan Rhomberg-Kauert, Ludvig Larsson, Hanna van Ooijen, Stefan Petkov, Marcela Gonz\u00e1lez-Granillo, Jessica Bunz, Johan Dahlberg, Michele Simonetti, Prajakta Sathe, Petter Brodin, Alvaro Martinez Barrio & Simon Fredriksson\n>\n> _Nat Methods._ 2024 May 08. doi: [10.1038/s41592-024-02268-9](https://doi.org/10.1038/s41592-024-02268-9)\n", "hasPart": [ { "@id": "main.nf" @@ -105,7 +105,7 @@ }, "mentions": [ { - "@id": "#8e6d0fb4-4d09-426c-9602-72a16ab2002e" + "@id": "#62e83080-a3fc-4320-a06a-f4464e6d22fd" } ], "name": "nf-core/pixelator" @@ -141,7 +141,7 @@ } ], "dateCreated": "", - "dateModified": "2025-05-27T10:46:46Z", + "dateModified": "2025-09-01T09:00:42Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": [ "nf-core", @@ -175,10 +175,10 @@ }, "url": [ "https://github.com/nf-core/pixelator", - "https://nf-co.re/pixelator/2.0.0/" + "https://nf-co.re/pixelator/2.1.0/" ], "version": [ - "2.0.0" + "2.1.0" ] }, { @@ -191,14 +191,14 @@ "url": { "@id": "https://www.nextflow.io/" }, - "version": "!>=24.04.2" + "version": "!>=24.10.5" }, { - "@id": "#8e6d0fb4-4d09-426c-9602-72a16ab2002e", + "@id": "#62e83080-a3fc-4320-a06a-f4464e6d22fd", "@type": "TestSuite", "instance": [ { - "@id": "#452746e3-839f-42f4-9760-90982d05cf24" + "@id": "#1a6258f9-30b9-430d-992c-cfa2adbc7f41" } ], "mainEntity": { @@ -207,10 +207,10 @@ "name": "Test suite for nf-core/pixelator" }, { - "@id": "#452746e3-839f-42f4-9760-90982d05cf24", + "@id": "#1a6258f9-30b9-430d-992c-cfa2adbc7f41", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/pixelator", - "resource": "repos/nf-core/pixelator/actions/workflows/ci.yml", + "resource": "repos/nf-core/pixelator/actions/workflows/nf-test.yml", "runsOn": { "@id": "https://w3id.org/ro/terms/test#GithubService" }, diff --git a/subworkflows/local/generate_reports/tests/main.nf.test.snap b/subworkflows/local/generate_reports/tests/main.nf.test.snap index cebbd9b9..21d2572c 100644 --- a/subworkflows/local/generate_reports/tests/main.nf.test.snap +++ b/subworkflows/local/generate_reports/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "Test MPX Generate reports - SCSP v1 | Immunology-I": { "content": [ [ - "versions.yml:md5,13db40f3913afc717d4a5d9ea5b75a55" + "versions.yml:md5,1ddc3d1ac0e1d5d985ecff623d902eaf" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:30:27.935023389" + "timestamp": "2025-08-28T06:27:44.57710868" }, "Test MPX Generate reports - stub": { "content": [ @@ -26,7 +26,7 @@ ] ], "1": [ - "versions.yml:md5,13db40f3913afc717d4a5d9ea5b75a55" + "versions.yml:md5,1ddc3d1ac0e1d5d985ecff623d902eaf" ], "pixelator_reports": [ [ @@ -40,14 +40,14 @@ ] ], "versions": [ - "versions.yml:md5,13db40f3913afc717d4a5d9ea5b75a55" + "versions.yml:md5,1ddc3d1ac0e1d5d985ecff623d902eaf" ] } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:29:57.329529017" + "timestamp": "2025-08-28T06:27:35.996352215" } } \ No newline at end of file diff --git a/subworkflows/local/mpx/main.nf b/subworkflows/local/mpx/main.nf index a3650b80..178401ef 100644 --- a/subworkflows/local/mpx/main.nf +++ b/subworkflows/local/mpx/main.nf @@ -191,17 +191,6 @@ workflow MPX { ch_versions = ch_versions.mix(GENERATE_REPORTS.out.versions) - // - // Collate and save software versions - // - softwareVersionsToYAML(ch_versions) - .collectFile( - storeDir: "${params.outdir}/pipeline_info", - name: 'nf_core_' + 'pixelator_software_' + 'mqc_' + 'versions.yml', - sort: true, - newLine: true - ).set { ch_collated_versions } - // TODO: Add MultiQC when plugins are ready emit: @@ -213,4 +202,3 @@ workflow MPX { THE END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - diff --git a/subworkflows/local/pna/generate_reports.nf b/subworkflows/local/pna/generate_reports.nf index a8d6a515..eb62302f 100644 --- a/subworkflows/local/pna/generate_reports.nf +++ b/subworkflows/local/pna/generate_reports.nf @@ -5,6 +5,7 @@ */ include { PIXELATOR_PNA_REPORT } from '../../../modules/local/pixelator/single-cell-pna/report/main' +include { EXPERIMENT_SUMMARY } from '../../../modules/local/experiment_summary/main' /* ======================================================================================== @@ -14,13 +15,17 @@ include { PIXELATOR_PNA_REPORT } from '../../../modules/local/pixelator/single-c workflow PNA_GENERATE_REPORTS { take: - panel_files // channel: [meta, path(panel_file) | []] - amplicon_data // channel: [meta, [path, ...]] - demux_data // channel: [meta, [path, ...]] - collapse_data // channel: [meta, [path, ...]] - graph_data // channel: [meta, [path, ...]] - analysis_data // channel: [meta, [path, ...]] - layout_data // channel: [meta, [path, ...]] + samplesheet // channel: [path(samplesheet)] + panel_files // channel: [meta, path(panel_file) | []] + amplicon_data // channel: [meta, [path, ...]] + demux_data // channel: [meta, [path, ...]] + collapse_data // channel: [meta, [path, ...]] + graph_data // channel: [meta, [path, ...]] + denoise_data // channel: [meta, [path, ...]] + analysis_data // channel: [meta, [path, ...]] + layout_data // channel: [meta, [path, ...]] + + skip_experiment_summary // boolean main: ch_versions = Channel.empty() @@ -37,89 +42,66 @@ workflow PNA_GENERATE_REPORTS { return [id, data] } - ch_panel_col = panel_files.map { meta, data -> [meta.id, data] } - - // - // These first subcommands each return two files per sample used by the reporting - // A json file with stats and a command invocation metadata json file - // - ch_amplicon_col = amplicon_data.map { meta, data -> [meta.id, data] } - ch_demux_col = demux_data.map { meta, data -> [meta.id, data] } - ch_collapse_col = collapse_data.map { meta, data -> [meta.id, data] } - ch_graph_col = graph_data.map { meta, data -> [meta.id, data] } - ch_analysis_col = analysis_data.map { meta, data -> [meta.id, data] } - ch_layout_col = layout_data.map { meta, data -> [meta.id, data] } - - // - // Combine all inputs and group them, then split them up again. - // This is neded to have the per subcommand outputs in the sample order - // - // ch_report_data: [ - // [ - // meta, panel_files, - // [amplicon files...], - // [preqc files...], - // [adapterqc files...], - // [demux files...], - // [collapse files...], - // [cluster files], - // [annotate files...], - // [analysis files...] - // [post analysis files...] - // ], - // [ same structure repeated for each sample ] - // ] - ch_report_data = ch_meta_col - .concat(ch_panel_col) - .concat(ch_amplicon_col) - .concat(ch_demux_col) - .concat(ch_collapse_col) - .concat(ch_graph_col) - .concat(ch_analysis_col) - .concat(ch_layout_col) - .groupTuple(size: 9) - - // - // Split up everything per stage so we can recreate the expected directory structure for - // `pixelator single-cell report` using stageAs for each stage - // - // These ch__grouped channels all emit a list of input files for each sample in the samplesheet - // The channels will emit values in the same order so eg. the first list of files from each ch__grouped - // channel will match the same sample from the samplesheet. - - // If no `panel_file` (data[1]) is given we need to pass in `panel` from the samplesheet instead - // - ch_split_report_data = ch_report_data.multiMap { _id, data -> - panel_files: [data[0], data[1], data[1] ? null : data[0].panel] - amplicon: data[2] ? data[2].flatten() : [] - demux: data[3] ? data[3].flatten() : [] - collapse: data[4] ? data[4].flatten() : [] - graph: data[5] ? data[5].flatten() : [] - analysis: data[6] ? data[6].flatten() : [] - post_analysis: data[7] ? data[7].flatten() : [] - layout: data[8] ? data[8].flatten() : [] + .join( panel_files.map { meta, data -> [ meta.id, data ] } ) + .join( amplicon_data.map { meta, data -> [ meta.id, data ] } ) + .join( demux_data.map { meta, data -> [ meta.id, data ] } ) + .join( collapse_data.map { meta, data -> [ meta.id, data ] } ) + .join( graph_data.map { meta, data -> [ meta.id, data ] } ) + .join( denoise_data.map { meta, data -> [ meta.id, data ] } ) + .join( analysis_data.map { meta, data -> [ meta.id, data ] } ) + .join( layout_data.map { meta, data -> [ meta.id, data ] } ) + + ch_pna_report_input = ch_report_data.map { + _id, meta, panels, amplicon, demux, collapse, graph, denoise, analysis, layout -> + [meta, panels, panels ? null : meta.panel, amplicon, demux, collapse, graph, denoise, analysis, layout] + } + + PIXELATOR_PNA_REPORT ( ch_pna_report_input ) + + // Accumulate results across all samples grouped per stage + + def accumulator = [ + meta: [ id: "all-samples", samples: [] ], + amplicon: [], + demux: [], + collapse: [], + graph: [], + denoise: [], + analysis: [], + layout: [] + ] + + ch_grouped_data = ch_report_data.reduce ( accumulator ) { acc, val -> + def (_id, meta, _panels, amplicon, demux, collapse, graph, denoise, analysis, layout) = val + acc.meta.samples += meta.id + acc.amplicon += amplicon + acc.demux += demux + acc.collapse += collapse + acc.graph += graph + acc.denoise += denoise + acc.analysis += analysis + acc.layout += layout + return acc + }.map { acc -> + [ acc.meta, acc.amplicon, acc.demux, acc.collapse, acc.graph, acc.denoise, acc.analysis, acc.layout ] } + // Filter out the entry if it just contains empty lists, eg when no PNA samples are present + .filter { it -> it[0].samples.size() > 0 } - // - // MODULE: Run pixelator single-cell report for each samples - // - // NB: These channels need to be split per stage to allow PIXELATOR_PNA_REPORT to - // use stageAs directives to stage files expected from a pixelator workdir - PIXELATOR_PNA_REPORT( - ch_split_report_data.panel_files, - ch_split_report_data.amplicon, - ch_split_report_data.demux, - ch_split_report_data.collapse, - ch_split_report_data.graph, - ch_split_report_data.analysis, - ch_split_report_data.post_analysis, - ch_split_report_data.layout, - ) + if (!skip_experiment_summary) { + EXPERIMENT_SUMMARY ( samplesheet, ch_grouped_data ) + + ch_versions = ch_versions.mix(EXPERIMENT_SUMMARY.out.versions) + ch_experiment_summary = EXPERIMENT_SUMMARY.out.html + } else { + ch_experiment_summary = ch_grouped_data.map { it -> it[0] }.combine(Channel.of([])) + } ch_versions = ch_versions.mix(PIXELATOR_PNA_REPORT.out.versions.first()) emit: - pixelator_reports = PIXELATOR_PNA_REPORT.out.report - versions = ch_versions + pixelator_reports = PIXELATOR_PNA_REPORT.out.report + experiment_summary = ch_experiment_summary + versions = ch_versions } diff --git a/subworkflows/local/pna/main.nf b/subworkflows/local/pna/main.nf index 0576123a..22955a5f 100644 --- a/subworkflows/local/pna/main.nf +++ b/subworkflows/local/pna/main.nf @@ -21,6 +21,7 @@ include { PIXELATOR_PNA_AMPLICON } from '../../../modules/local/pixelato include { PIXELATOR_PNA_DEMUX } from '../../../modules/local/pixelator/single-cell-pna/demux/main' include { PIXELATOR_PNA_COLLAPSE } from '../../../modules/local/pixelator/single-cell-pna/collapse/main' include { PIXELATOR_PNA_GRAPH } from '../../../modules/local/pixelator/single-cell-pna/graph/main' +include { PIXELATOR_PNA_DENOISE } from '../../../modules/local/pixelator/single-cell-pna/denoise/main' include { PIXELATOR_PNA_ANALYSIS } from '../../../modules/local/pixelator/single-cell-pna/analysis/main' include { PIXELATOR_PNA_COMBINE_COLLAPSE } from '../../../modules/local/pixelator/single-cell-pna/combine_collapse/main' include { PIXELATOR_PNA_LAYOUT } from '../../../modules/local/pixelator/single-cell-pna/layout/main' @@ -139,10 +140,18 @@ workflow PNA { ch_graph = PIXELATOR_PNA_GRAPH.out.pixelfile ch_versions = ch_versions.mix(PIXELATOR_PNA_GRAPH.out.versions.first()) + // + // MODULE: Run pixelator single-cell denoise + // + PIXELATOR_PNA_DENOISE ( ch_graph ) + ch_denoise = PIXELATOR_PNA_DENOISE.out.pixelfile + ch_versions = ch_versions.mix(PIXELATOR_PNA_DENOISE.out.versions.first()) + // // MODULE: Run pixelator single-cell analysis // - PIXELATOR_PNA_ANALYSIS(ch_graph) + ch_analysis_input = params.skip_denoise ? ch_graph : ch_denoise + PIXELATOR_PNA_ANALYSIS(ch_analysis_input) ch_analysis = PIXELATOR_PNA_ANALYSIS.out.pixelfile ch_versions = ch_versions.mix(PIXELATOR_PNA_ANALYSIS.out.versions.first()) @@ -168,34 +177,30 @@ workflow PNA { .groupTuple(size: 2) ch_cluster_data = PIXELATOR_PNA_GRAPH.out.all_results + ch_denoise_data = PIXELATOR_PNA_DENOISE.out.all_results ch_analysis_data = PIXELATOR_PNA_ANALYSIS.out.all_results ch_layout_data = PIXELATOR_PNA_LAYOUT.out.report_json .concat(PIXELATOR_PNA_LAYOUT.out.metadata_json) .groupTuple(size: 2) + + ch_input = Channel.of(params.input) + PNA_GENERATE_REPORTS( + ch_input, panel_files, ch_amplicon_data, ch_demux_data, ch_collapse_data, ch_cluster_data, + ch_denoise_data, ch_analysis_data, ch_layout_data, + params.skip_experiment_summary ) ch_versions = ch_versions.mix(PNA_GENERATE_REPORTS.out.versions) - // - // Collate and save software versions - // - softwareVersionsToYAML(ch_versions) - .collectFile( - storeDir: "${params.outdir}/pipeline_info", - name: 'nf_core_' + 'pixelator_software_' + 'mqc_' + 'versions.yml', - sort: true, - newLine: true - ).set { ch_collated_versions } - emit: versions = ch_versions graph = ch_graph diff --git a/subworkflows/local/pna/tests/main.nf.test b/subworkflows/local/pna/tests/main.nf.test index 8a67b8bc..838d27e9 100644 --- a/subworkflows/local/pna/tests/main.nf.test +++ b/subworkflows/local/pna/tests/main.nf.test @@ -14,6 +14,7 @@ nextflow_workflow { params { pna_graph_component_size_min_threshold = 100 + skip_experiment_summary = true } workflow { diff --git a/subworkflows/local/pna/tests/main.nf.test.snap b/subworkflows/local/pna/tests/main.nf.test.snap index 2a756471..010581b2 100644 --- a/subworkflows/local/pna/tests/main.nf.test.snap +++ b/subworkflows/local/pna/tests/main.nf.test.snap @@ -2,19 +2,21 @@ "versions": { "content": [ [ - "versions.yml:md5,008d461c0a873cba26e5acce42c5a30b", - "versions.yml:md5,3287aa1204587f64ea633234091d2858", - "versions.yml:md5,a472e3de71bcfc5aba6d8433c610762a", - "versions.yml:md5,b1e342fded9151f1ea3de7c3a3e1e27c", - "versions.yml:md5,bc1bd306f1ade35c060c42e383a59990", - "versions.yml:md5,cf4872baac4b98fbffa390aac56d3bbf", - "versions.yml:md5,d9f448e5ec1ad5a222482d2882c55193" + "versions.yml:md5,2b76dc677520f080b38a835b42d9234f", + "versions.yml:md5,45d66075b78e83ca12377ce2a8f00a41", + "versions.yml:md5,69408cfc661c191ca717e63d776a730f", + "versions.yml:md5,72ca8b012eed35b9680b7579c1a4cdcc", + "versions.yml:md5,7fc022b3ebfc95329e61f5333d13cfb6", + "versions.yml:md5,8682cffd6978e21db0c33352e6b129ef", + "versions.yml:md5,cb883de819d1f83c67c8f2ce4fcc22d6", + "versions.yml:md5,dafb241aadf5e309e534b364769a5f85", + "versions.yml:md5,fd40ac67016fc5a1d101f556bd9b4987" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "25.04.6" }, - "timestamp": "2025-05-06T15:32:59.670096405" + "timestamp": "2025-08-28T06:29:54.809801941" } } \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test.snap b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test.snap index e3f0baf4..25f2017f 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test.snap +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.function.nf.test.snap @@ -4,10 +4,10 @@ "v9.9.9" ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.2", + "nextflow": "25.04.2" }, - "timestamp": "2024-02-28T12:02:05.308243" + "timestamp": "2025-06-26T13:20:08.944676306" }, "Test Function checkCondaChannels": { "content": null, diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config index 0907ac58..09ef842a 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config @@ -1,5 +1,5 @@ plugins { - id "nf-schema@2.1.0" + id "nf-schema@2.4.2" } validation { diff --git a/tests/.nftignore b/tests/.nftignore index b03dfe32..a0657e49 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -1,2 +1,3 @@ +.DS_Store pixelator/logs/**/*.log pipeline_info/*.{html,json,txt,yml} diff --git a/tests/default_mpx.nf.test b/tests/default_mpx.nf.test index 3b2fcbdf..ff28b45d 100644 --- a/tests/default_mpx.nf.test +++ b/tests/default_mpx.nf.test @@ -25,6 +25,8 @@ nextflow_pipeline { { assert snapshot( // Number of successful tasks workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we tests pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_pixelator_software_mqc_versions.yml"), // All stable path name, with a relative path stable_name, // All files with stable contents diff --git a/tests/default_mpx.nf.test.snap b/tests/default_mpx.nf.test.snap index 76a77ef5..48d51328 100644 --- a/tests/default_mpx.nf.test.snap +++ b/tests/default_mpx.nf.test.snap @@ -5,7 +5,6 @@ [ "pipeline_info", "pipeline_info/nf_core_pixelator_software_mqc_versions.yml", - "pipeline_info/nf_core_pixelator_software_versions.yml", "pixelator", "pixelator/adapterqc", "pixelator/adapterqc/sample01.meta.json", @@ -55,17 +54,48 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "25.04.2" + "nextflow": "24.10.3" }, - "timestamp": "2025-06-18T14:11:56.861718339" + "timestamp": "2025-07-28T15:15:34.886989428" }, "Params: default": { "content": [ 10, + { + "PIXELATOR_AMPLICON": { + "pixelator": "0.21.4" + }, + "PIXELATOR_ANALYSIS": { + "pixelator": "0.21.4" + }, + "PIXELATOR_ANNOTATE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_COLLAPSE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_DEMUX": { + "pixelator": "0.21.4" + }, + "PIXELATOR_GRAPH": { + "pixelator": "0.21.4" + }, + "PIXELATOR_LAYOUT": { + "pixelator": "0.21.4" + }, + "PIXELATOR_QC": { + "pixelator": "0.21.4" + }, + "PIXELATOR_REPORT": { + "pixelator": "0.21.4" + }, + "Workflow": { + "nf-core/pixelator": "v2.1.0" + } + }, [ "pipeline_info", "pipeline_info/nf_core_pixelator_software_mqc_versions.yml", - "pipeline_info/nf_core_pixelator_software_versions.yml", "pixelator", "pixelator/adapterqc", "pixelator/adapterqc/sample01.meta.json", @@ -115,8 +145,8 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "25.04.2" + "nextflow": "25.04.6" }, - "timestamp": "2025-06-18T14:11:19.987334253" + "timestamp": "2025-09-01T08:00:33.053912672" } } \ No newline at end of file diff --git a/tests/default_pna.nf.test b/tests/default_pna.nf.test index 7321bee7..899757f0 100644 --- a/tests/default_pna.nf.test +++ b/tests/default_pna.nf.test @@ -3,6 +3,9 @@ nextflow_pipeline { name "Test PNA pipeline with default settings" script "../main.nf" + tag "pixelator" + tag "pixelator/pna" + test("Params: default") { when { @@ -13,6 +16,7 @@ nextflow_pipeline { outdir = "$outputDir" pna_graph_component_size_min_threshold = 100 + skip_experiment_summary = true } } @@ -28,6 +32,8 @@ nextflow_pipeline { { assert snapshot( // Number of successful tasks workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we tests pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_pixelator_software_mqc_versions.yml"), // All stable path name, with a relative path stable_name, // All files with stable contents @@ -47,6 +53,8 @@ nextflow_pipeline { input = "$pipelines_testdata_base_path/samplesheet/pna/samplesheet_pna.csv" input_basedir = "$pipelines_testdata_base_path/testdata/pna/" outdir = "$outputDir" + + skip_experiment_summary = true } } diff --git a/tests/default_pna.nf.test.snap b/tests/default_pna.nf.test.snap index 71ee7451..9d2804a4 100644 --- a/tests/default_pna.nf.test.snap +++ b/tests/default_pna.nf.test.snap @@ -1,11 +1,10 @@ { "Params: default - stub": { "content": [ - 9, + 11, [ "pipeline_info", "pipeline_info/nf_core_pixelator_software_mqc_versions.yml", - "pipeline_info/nf_core_pixelator_software_versions.yml", "pixelator", "pixelator/PNA055_Sample07_filtered_S7.pxl", "pixelator/amplicon", @@ -25,6 +24,9 @@ "pixelator/demux", "pixelator/demux/PNA055_Sample07_filtered_S7.meta.json", "pixelator/demux/PNA055_Sample07_filtered_S7.report.json", + "pixelator/denoise", + "pixelator/denoise/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/denoise/PNA055_Sample07_filtered_S7.report.json", "pixelator/graph", "pixelator/graph/PNA055_Sample07_filtered_S7.meta.json", "pixelator/graph/PNA055_Sample07_filtered_S7.report.json", @@ -34,13 +36,17 @@ "pixelator/logs", "pixelator/logs/PNA055_Sample07_filtered_S7", "pixelator/logs/PNA055_Sample07_filtered_S7.pixelator-combine-collapse.log", + "pixelator/logs/PNA055_Sample07_filtered_S7.pixelator-report.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.demux.m1.part_000.pixelator-collapse.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.demux.m2.part_000.pixelator-collapse.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-amplicon.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-analysis.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-demux.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-denoise.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-graph.log", - "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-layout.log" + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-layout.log", + "pixelator/report", + "pixelator/report/PNA055_Sample07_filtered_S7.report.html" ], [ @@ -48,17 +54,48 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "25.04.2" + "nextflow": "24.10.3" }, - "timestamp": "2025-06-18T14:16:06.777952595" + "timestamp": "2025-07-28T15:28:52.030014387" }, "Params: default": { "content": [ - 9, + 11, + { + "PIXELATOR_PNA_AMPLICON": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_ANALYSIS": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_COLLAPSE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_COMBINE_COLLAPSE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_DEMUX": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_DENOISE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_GRAPH": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_LAYOUT": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_REPORT": { + "pixelator": "0.21.4" + }, + "Workflow": { + "nf-core/pixelator": "v2.1.0" + } + }, [ "pipeline_info", "pipeline_info/nf_core_pixelator_software_mqc_versions.yml", - "pipeline_info/nf_core_pixelator_software_versions.yml", "pixelator", "pixelator/PNA055_Sample07_filtered_S7.layout.pxl", "pixelator/amplicon", @@ -78,6 +115,9 @@ "pixelator/demux", "pixelator/demux/PNA055_Sample07_filtered_S7.meta.json", "pixelator/demux/PNA055_Sample07_filtered_S7.report.json", + "pixelator/denoise", + "pixelator/denoise/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/denoise/PNA055_Sample07_filtered_S7.report.json", "pixelator/graph", "pixelator/graph/PNA055_Sample07_filtered_S7.meta.json", "pixelator/graph/PNA055_Sample07_filtered_S7.report.json", @@ -87,12 +127,16 @@ "pixelator/logs", "pixelator/logs/PNA055_Sample07_filtered_S7", "pixelator/logs/PNA055_Sample07_filtered_S7.pixelator-combine-collapse.log", + "pixelator/logs/PNA055_Sample07_filtered_S7.pixelator-report.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-amplicon.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-analysis.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-collapse.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-demux.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-denoise.log", "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-graph.log", - "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-layout.log" + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-layout.log", + "pixelator/report", + "pixelator/report/PNA055_Sample07_filtered_S7.qc-report.html" ], [ @@ -100,8 +144,8 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "25.04.2" + "nextflow": "25.04.6" }, - "timestamp": "2025-06-18T14:15:24.670481367" + "timestamp": "2025-09-01T08:03:18.225519143" } } \ No newline at end of file diff --git a/tests/nextflow.config b/tests/nextflow.config index 307d66fa..79cd7ca6 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -4,6 +4,8 @@ ======================================================================================== */ +aws.client.anonymous = true // fixes S3 access issues on self-hosted runners + params { // Base directory for nf-core/modules test data modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' @@ -11,7 +13,6 @@ params { // TODO: check if we rather do this or disable publishdir for all processes when testing modules/subworkflows outdir = 'results' - dump_channels = true } validation { diff --git a/tests/pna_es.nf.test b/tests/pna_es.nf.test new file mode 100644 index 00000000..74fb13e9 --- /dev/null +++ b/tests/pna_es.nf.test @@ -0,0 +1,79 @@ +nextflow_pipeline { + + name "Test PNA pipeline with experiment summary" + script "../main.nf" + + tag "pixelator" + tag "pixelator/pna" + + test("small") { + + when { + params { + + pipelines_testdata_base_path = "https://raw.githubusercontent.com/nf-core/test-datasets/pixelator/" + input = "$pipelines_testdata_base_path/samplesheet/pna/samplesheet_pna_es.csv" + input_basedir = "$pipelines_testdata_base_path/testdata/pna/" + outdir = "$outputDir" + + pna_graph_component_size_min_threshold = 100 + skip_experiment_summary = false + } + } + + then { + // stable_name: All files + folders in ${params.outdir}/ with a stable name + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_path: All files in ${params.outdir}/ with stable content + def stable_path = [] + + assertAll( + { assert workflow.success}, + { assert snapshot( + // Number of successful tasks + workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we tests pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_pixelator_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path + ).match() } + ) + } + } + + test("small - stub") { + + options "-stub" + tag "stub" + + when { + params { + pipelines_testdata_base_path = "https://raw.githubusercontent.com/nf-core/test-datasets/pixelator/" + input = "$pipelines_testdata_base_path/samplesheet/pna/samplesheet_pna_es.csv" + input_basedir = "$pipelines_testdata_base_path/testdata/pna/" + outdir = "$outputDir" + skip_experiment_summary = false + } + } + + then { + // stable_name: All files + folders in ${params.outdir}/ with a stable name + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_path: All files in ${params.outdir}/ with stable content + def stable_path = [] + assertAll( + { assert workflow.success }, + { assert snapshot( + // Number of successful tasks + workflow.trace.succeeded().size(), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path + ).match() } + ) + } + } +} diff --git a/tests/pna_es.nf.test.snap b/tests/pna_es.nf.test.snap new file mode 100644 index 00000000..8efff243 --- /dev/null +++ b/tests/pna_es.nf.test.snap @@ -0,0 +1,219 @@ +{ + "small": { + "content": [ + 22, + { + "EXPERIMENT_SUMMARY": { + "experiment-summary": "0.4.3" + }, + "PIXELATOR_PNA_AMPLICON": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_ANALYSIS": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_COLLAPSE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_COMBINE_COLLAPSE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_DEMUX": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_DENOISE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_GRAPH": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_LAYOUT": { + "pixelator": "0.21.4" + }, + "PIXELATOR_PNA_REPORT": { + "pixelator": "0.21.4" + }, + "Workflow": { + "nf-core/pixelator": "v2.1.0" + } + }, + [ + "pipeline_info", + "pipeline_info/nf_core_pixelator_software_mqc_versions.yml", + "pixelator", + "pixelator/PNA055_Sample07_filtered_S7.layout.pxl", + "pixelator/PNA055_Sample07_unfiltered_S7.layout.pxl", + "pixelator/amplicon", + "pixelator/amplicon/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/amplicon/PNA055_Sample07_filtered_S7.report.json", + "pixelator/amplicon/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/amplicon/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/analysis", + "pixelator/analysis/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/analysis/PNA055_Sample07_filtered_S7.report.json", + "pixelator/analysis/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/analysis/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/collapse", + "pixelator/collapse/PNA055_Sample07_filtered_S7.collapse.m1.part_000.meta.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.collapse.m1.part_000.report.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.collapse.m2.part_000.meta.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.collapse.m2.part_000.report.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.collapse.parquet", + "pixelator/collapse/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.report.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.collapse.m1.part_000.meta.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.collapse.m1.part_000.report.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.collapse.m2.part_000.meta.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.collapse.m2.part_000.report.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.collapse.parquet", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/demux", + "pixelator/demux/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/demux/PNA055_Sample07_filtered_S7.report.json", + "pixelator/demux/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/demux/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/denoise", + "pixelator/denoise/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/denoise/PNA055_Sample07_filtered_S7.report.json", + "pixelator/denoise/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/denoise/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/experiment-summary.html", + "pixelator/graph", + "pixelator/graph/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/graph/PNA055_Sample07_filtered_S7.report.json", + "pixelator/graph/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/graph/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/layout", + "pixelator/layout/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/layout/PNA055_Sample07_filtered_S7.report.json", + "pixelator/layout/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/layout/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/logs", + "pixelator/logs/PNA055_Sample07_filtered_S7", + "pixelator/logs/PNA055_Sample07_filtered_S7.pixelator-combine-collapse.log", + "pixelator/logs/PNA055_Sample07_filtered_S7.pixelator-report.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-amplicon.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-analysis.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-collapse.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-demux.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-denoise.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-graph.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-layout.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7", + "pixelator/logs/PNA055_Sample07_unfiltered_S7.pixelator-combine-collapse.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7.pixelator-report.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-amplicon.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-analysis.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-collapse.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-demux.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-denoise.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-graph.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-layout.log", + "pixelator/report", + "pixelator/report/PNA055_Sample07_filtered_S7.qc-report.html", + "pixelator/report/PNA055_Sample07_unfiltered_S7.qc-report.html" + ], + [ + + ] + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.6" + }, + "timestamp": "2025-09-01T08:09:15.051954045" + }, + "small - stub": { + "content": [ + 22, + [ + "pipeline_info", + "pipeline_info/nf_core_pixelator_software_mqc_versions.yml", + "pixelator", + "pixelator/PNA055_Sample07_filtered_S7.pxl", + "pixelator/PNA055_Sample07_unfiltered_S7.pxl", + "pixelator/amplicon", + "pixelator/amplicon/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/amplicon/PNA055_Sample07_filtered_S7.report.json", + "pixelator/amplicon/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/amplicon/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/analysis", + "pixelator/analysis/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/analysis/PNA055_Sample07_filtered_S7.report.json", + "pixelator/analysis/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/analysis/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/collapse", + "pixelator/collapse/PNA055_Sample07_filtered_S7.collapse.meta.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.collapse.parquet", + "pixelator/collapse/PNA055_Sample07_filtered_S7.demux.m1.part_000.meta.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.demux.m1.part_000.report.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.demux.m2.part_000.meta.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.demux.m2.part_000.report.json", + "pixelator/collapse/PNA055_Sample07_filtered_S7.report.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.collapse.meta.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.collapse.parquet", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.demux.m1.part_000.meta.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.demux.m1.part_000.report.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.demux.m2.part_000.meta.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.demux.m2.part_000.report.json", + "pixelator/collapse/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/demux", + "pixelator/demux/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/demux/PNA055_Sample07_filtered_S7.report.json", + "pixelator/demux/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/demux/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/denoise", + "pixelator/denoise/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/denoise/PNA055_Sample07_filtered_S7.report.json", + "pixelator/denoise/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/denoise/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/experiment-summary.html", + "pixelator/graph", + "pixelator/graph/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/graph/PNA055_Sample07_filtered_S7.report.json", + "pixelator/graph/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/graph/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/layout", + "pixelator/layout/PNA055_Sample07_filtered_S7.meta.json", + "pixelator/layout/PNA055_Sample07_filtered_S7.report.json", + "pixelator/layout/PNA055_Sample07_unfiltered_S7.meta.json", + "pixelator/layout/PNA055_Sample07_unfiltered_S7.report.json", + "pixelator/logs", + "pixelator/logs/PNA055_Sample07_filtered_S7", + "pixelator/logs/PNA055_Sample07_filtered_S7.pixelator-combine-collapse.log", + "pixelator/logs/PNA055_Sample07_filtered_S7.pixelator-report.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.demux.m1.part_000.pixelator-collapse.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.demux.m2.part_000.pixelator-collapse.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-amplicon.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-analysis.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-demux.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-denoise.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-graph.log", + "pixelator/logs/PNA055_Sample07_filtered_S7/PNA055_Sample07_filtered_S7.pixelator-layout.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7", + "pixelator/logs/PNA055_Sample07_unfiltered_S7.pixelator-combine-collapse.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7.pixelator-report.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.demux.m1.part_000.pixelator-collapse.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.demux.m2.part_000.pixelator-collapse.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-amplicon.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-analysis.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-demux.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-denoise.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-graph.log", + "pixelator/logs/PNA055_Sample07_unfiltered_S7/PNA055_Sample07_unfiltered_S7.pixelator-layout.log", + "pixelator/report", + "pixelator/report/PNA055_Sample07_filtered_S7.report.html", + "pixelator/report/PNA055_Sample07_unfiltered_S7.report.html" + ], + [ + + ] + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.6" + }, + "timestamp": "2025-08-25T11:37:33.484947103" + } +} \ No newline at end of file diff --git a/tests/save_all.nf.test b/tests/save_all.nf.test index 9a4569c8..393b2ea9 100644 --- a/tests/save_all.nf.test +++ b/tests/save_all.nf.test @@ -26,6 +26,8 @@ nextflow_pipeline { { assert snapshot( // Number of successful tasks workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we tests pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_pixelator_software_mqc_versions.yml"), // All stable path name, with a relative path stable_name, // All files with stable contents diff --git a/tests/save_all.nf.test.snap b/tests/save_all.nf.test.snap index fa38afd3..905127cd 100644 --- a/tests/save_all.nf.test.snap +++ b/tests/save_all.nf.test.snap @@ -2,10 +2,41 @@ "Params: --save_all": { "content": [ 10, + { + "PIXELATOR_AMPLICON": { + "pixelator": "0.21.4" + }, + "PIXELATOR_ANALYSIS": { + "pixelator": "0.21.4" + }, + "PIXELATOR_ANNOTATE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_COLLAPSE": { + "pixelator": "0.21.4" + }, + "PIXELATOR_DEMUX": { + "pixelator": "0.21.4" + }, + "PIXELATOR_GRAPH": { + "pixelator": "0.21.4" + }, + "PIXELATOR_LAYOUT": { + "pixelator": "0.21.4" + }, + "PIXELATOR_QC": { + "pixelator": "0.21.4" + }, + "PIXELATOR_REPORT": { + "pixelator": "0.21.4" + }, + "Workflow": { + "nf-core/pixelator": "v2.1.0" + } + }, [ "pipeline_info", "pipeline_info/nf_core_pixelator_software_mqc_versions.yml", - "pipeline_info/nf_core_pixelator_software_versions.yml", "pixelator", "pixelator/adapterqc", "pixelator/adapterqc/sample01.failed.fastq.gz", @@ -147,9 +178,9 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nextflow": "24.10.3" }, - "timestamp": "2025-05-15T14:16:04.664176925" + "timestamp": "2025-07-28T15:42:09.850381652" }, "Params: --save_all - stub": { "content": [ @@ -157,7 +188,6 @@ [ "pipeline_info", "pipeline_info/nf_core_pixelator_software_mqc_versions.yml", - "pipeline_info/nf_core_pixelator_software_versions.yml", "pixelator", "pixelator/adapterqc", "pixelator/adapterqc/sample01.meta.json", @@ -207,8 +237,8 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "25.04.2" + "nextflow": "24.10.3" }, - "timestamp": "2025-06-18T14:21:26.46401542" + "timestamp": "2025-07-28T15:43:17.696960351" } } \ No newline at end of file diff --git a/workflows/pixelator.nf b/workflows/pixelator.nf index 90905faf..2eb9c19b 100644 --- a/workflows/pixelator.nf +++ b/workflows/pixelator.nf @@ -147,13 +147,11 @@ workflow PIXELATOR { softwareVersionsToYAML(ch_versions) .collectFile( storeDir: "${params.outdir}/pipeline_info", - name: 'nf_core_' + 'pixelator_software_' + 'versions.yml', + name: 'nf_core_' + 'pixelator_software_' + 'mqc_' + 'versions.yml', sort: true, newLine: true ).set { ch_collated_versions } - // TODO: Add MultiQC when plugins are ready - emit: versions = ch_versions // channel: [ path(versions.yml) ] }