From b0120a4b466ecca14ac4668eb14f6e47b08e31d0 Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Mon, 26 Feb 2024 10:51:44 +0000 Subject: [PATCH 001/334] Better readme WIP comment --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 36efe8d..0e4f229 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ ## Introduction +[WIP] WORK IN PROGRESS AND NOT YET STABLE - DO NOT USE FOR PRODUCTIVE SETTINGS YET + **nf-core/datasync** is a system operation pipeline that provides several workflows for handling system operation / automation tasks that are commonly helpful for various tasks in large data processing / analysis facilities. This includes: - Data Synchronization & Checksum generation From ebfa1da49f28af906760bcd5a7bec243d27e9a09 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 29 Feb 2024 16:09:48 +0000 Subject: [PATCH 002/334] Template update for nf-core/tools version 2.13.1 --- .devcontainer/devcontainer.json | 10 +---- .github/CONTRIBUTING.md | 14 +++--- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/awsfulltest.yml | 4 +- .github/workflows/awstest.yml | 4 +- .github/workflows/ci.yml | 2 +- .github/workflows/download_pipeline.yml | 2 +- .github/workflows/linting.yml | 2 +- .github/workflows/release-announcements.yml | 2 +- .gitpod.yml | 6 +-- README.md | 3 +- assets/nf-core-datasync_logo_light.png | Bin 81179 -> 81181 bytes docs/images/nf-core-datasync_logo_dark.png | Bin 30611 -> 30659 bytes docs/images/nf-core-datasync_logo_light.png | Bin 26076 -> 26126 bytes modules.json | 8 ++-- modules/nf-core/multiqc/environment.yml | 2 +- modules/nf-core/multiqc/main.nf | 4 +- .../nf-core/multiqc/tests/main.nf.test.snap | 12 ++--- .../utils_nfcore_datasync_pipeline/main.nf | 10 +++-- .../tests/main.function.nf.test | 2 +- .../tests/main.function.nf.test.snap | 12 ++++- .../tests/main.workflow.nf.test | 20 ++------- .../tests/nextflow.config | 2 +- .../tests/main.function.nf.test.snap | 42 +++++++++++++++--- .../tests/main.workflow.nf.test.snap | 6 ++- .../tests/main.nf.test | 2 +- 26 files changed, 99 insertions(+), 74 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4ecfbfe..b290e09 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,15 +10,7 @@ "vscode": { // Set *default* container specific settings.json values on container create. "settings": { - "python.defaultInterpreterPath": "/opt/conda/bin/python", - "python.linting.enabled": true, - "python.linting.pylintEnabled": true, - "python.formatting.autopep8Path": "/opt/conda/bin/autopep8", - "python.formatting.yapfPath": "/opt/conda/bin/yapf", - "python.linting.flake8Path": "/opt/conda/bin/flake8", - "python.linting.pycodestylePath": "/opt/conda/bin/pycodestyle", - "python.linting.pydocstylePath": "/opt/conda/bin/pydocstyle", - "python.linting.pylintPath": "/opt/conda/bin/pylint" + "python.defaultInterpreterPath": "/opt/conda/bin/python" }, // Add the IDs of extensions you want installed when the container is created. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 7ad182e..5402f7f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -9,9 +9,8 @@ Please use the pre-filled template to save time. However, don't be put off by this template - other more general issues and suggestions are welcome! Contributions to the code are even more welcome ;) -:::info -If you need help using or modifying nf-core/datasync then the best place to ask is on the nf-core Slack [#datasync](https://nfcore.slack.com/channels/datasync) channel ([join our Slack here](https://nf-co.re/join/slack)). -::: +> [!NOTE] +> If you need help using or modifying nf-core/datasync then the best place to ask is on the nf-core Slack [#datasync](https://nfcore.slack.com/channels/datasync) channel ([join our Slack here](https://nf-co.re/join/slack)). ## Contribution workflow @@ -27,8 +26,11 @@ If you're not used to this workflow with git, you can start with some [docs from ## Tests -You can optionally test your changes by running the pipeline locally. Then it is recommended to use the `debug` profile to -receive warnings about process selectors and other debug info. Example: `nextflow run . -profile debug,test,docker --outdir `. +You have the option to test your changes locally by running the pipeline. For receiving warnings about process selectors and other `debug` information, it is recommended to use the debug profile. Execute all the tests with the following command: + +```bash +nf-test test --profile debug,test,docker --verbose +``` When you create a pull request with changes, [GitHub Actions](https://github.com/features/actions) will run automatic tests. Typically, pull-requests are only fully reviewed when these tests are passing, though of course we can help out before then. @@ -90,7 +92,7 @@ Once there, use `nf-core schema build` to add to `nextflow_schema.json`. Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/master/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. -The process resources can be passed on to the tool dynamically within the process with the `${task.cpu}` and `${task.memory}` variables in the `script:` block. +The process resources can be passed on to the tool dynamically within the process with the `${task.cpus}` and `${task.memory}` variables in the `script:` block. ### Naming schemes diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ff8f68a..08d7669 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,7 +18,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/data - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/.github/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). -- [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). +- [ ] Ensure the test suite passes (`nf-test test main.nf.test -profile test,docker`). - [ ] Check for unexpected warnings in debug mode (`nextflow run . -profile debug,test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. - [ ] Output Documentation in `docs/output.md` is updated. diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 2b7c8ef..9724711 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Launch workflow via tower - uses: seqeralabs/action-tower-launch@922e5c8d5ac4e918107ec311d2ebbd65e5982b3d # v2 + uses: seqeralabs/action-tower-launch@v2 # TODO nf-core: You can customise AWS full pipeline tests as required # Add full size test data (but still relatively small datasets for few samples) # on the `test_full.config` test runs with only one set of parameters @@ -31,7 +31,7 @@ jobs: } profiles: test_full - - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 + - uses: actions/upload-artifact@v4 with: name: Tower debug log file path: | diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index b93ec43..2aeceb1 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -12,7 +12,7 @@ jobs: steps: # Launch workflow using Tower CLI tool action - name: Launch workflow via tower - uses: seqeralabs/action-tower-launch@922e5c8d5ac4e918107ec311d2ebbd65e5982b3d # v2 + uses: seqeralabs/action-tower-launch@v2 with: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} @@ -25,7 +25,7 @@ jobs: } profiles: test - - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 + - uses: actions/upload-artifact@v4 with: name: Tower debug log file path: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf91dbd..3a8a037 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Install Nextflow - uses: nf-core/setup-nextflow@b9f764e8ba5c76b712ace14ecbfcef0e40ae2dd8 # v1 + uses: nf-core/setup-nextflow@v1 with: version: "${{ matrix.NXF_VER }}" diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index f823210..08622fd 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Install Nextflow - uses: nf-core/setup-nextflow@b9f764e8ba5c76b712ace14ecbfcef0e40ae2dd8 # v1 + uses: nf-core/setup-nextflow@v1 - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 748b431..073e187 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -35,7 +35,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 - name: Install Nextflow - uses: nf-core/setup-nextflow@b9f764e8ba5c76b712ace14ecbfcef0e40ae2dd8 # v1 + uses: nf-core/setup-nextflow@v1 - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 with: diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index c3674af..d468aea 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -12,7 +12,7 @@ jobs: - name: get topics and convert to hashtags id: get_topics run: | - curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ' > $GITHUB_OUTPUT + curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ' >> $GITHUB_OUTPUT - uses: rzr/fediverse-action@master with: diff --git a/.gitpod.yml b/.gitpod.yml index 363d5b1..105a182 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -10,13 +10,11 @@ tasks: vscode: extensions: # based on nf-core.nf-core-extensionpack - - codezombiech.gitignore # Language support for .gitignore files - # - cssho.vscode-svgviewer # SVG viewer - esbenp.prettier-vscode # Markdown/CommonMark linting and style checking for Visual Studio Code - - eamodio.gitlens # Quickly glimpse into whom, why, and when a line or code block was changed - EditorConfig.EditorConfig # override user/workspace settings with settings found in .editorconfig files - Gruntfuggly.todo-tree # Display TODO and FIXME in a tree view in the activity bar - mechatroner.rainbow-csv # Highlight columns in csv files in different colors - # - nextflow.nextflow # Nextflow syntax highlighting + # - nextflow.nextflow # Nextflow syntax highlighting - oderwat.indent-rainbow # Highlight indentation level - streetsidesoftware.code-spell-checker # Spelling checker for source code + - charliermarsh.ruff # Code linter Ruff diff --git a/README.md b/README.md index af9e43f..a57e162 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,13 @@ [![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml) [![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) +[![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%A523.04.0-23aa62.svg)](https://www.nextflow.io/) [![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 Nextflow Tower](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Nextflow%20Tower-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/datasync) +[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://tower.nf/launch?pipeline=https://github.com/nf-core/datasync) [![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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) diff --git a/assets/nf-core-datasync_logo_light.png b/assets/nf-core-datasync_logo_light.png index fa8dbfca1d568c20aacbec0eaee4430c737f6852..1be8821913f3bd95caaedb4047204cbe13e601f2 100644 GIT binary patch delta 49749 zcmc$`2{={z|3A97Z5}HmbAvKuC}bWgB!tW%Ln<;)+dQnTNvSBI!BoZ&5+Q8XsUwvT zl9`Rl7+Z)C_q{mhe9yi2dG3Aw&;8y1_jx#{+G~B*dw9L)_u9$Jw5iLq&p5)7nFH_M zt9XwDwXkxSo6z1#;nNm*aOB`{44(BcOU|L9$MrX>C#xokstaa{G7G9NZsn!Z=@hUr z=c>Pqr!`3s8Qy7l?CNRrgDsaM*Od-^IB;U@;ds%Ya=>&;Kx)BN=bTB^$18a%qhXP8 zTyEonL5uG-Zn!LjSe|&rYh8GQOm`Erir(jUKO#MSbQcv2+S+|Pb;J*wCLUTo`x!cZ<^ z!1$?*kt^>#7JWPG#cW%wh#p_1)AN?8dl8l=zKBPDP~V%v-R?U*KKxXy8+m$v zSnj#gN_>8y1QQETkdRj3=5FzV19+ z(7ofaJ&1qx!dayuUAcF!;>^7`na&Y5AGytdNYTb1y<%t%D;N6PM7(Wyq;FoDe@>WTQIaf4N1&S8Ge}* z_u&lh{&e?{nO`>wYhz9~>VA6`e%Wb%$sH%#;*dQDWMy*~S0o~vYAkXX3>RcuzDJ~O zjqz(|J;mIoESD~!oyyFLORji$E9ARTkSlSEg=y-5?(!kom5HA&r*n&iT~#DkkMCC= za$&P+dUHCzBDHh26)z%=J~LWEqK2g9^zxOA<@MsTtmQ&JLDn2IME{al`#hV@@wn|90Qh@@8rBjUd5G}_UFVJ zb^5mAm*)?P=IQ5)vuMV1p|9dZ^y1B1ZW!9?Fq}N!k@w6IfY(t-9l0z#J}|Mwcfy80 zceXgE!$XZ$NnS-)SOv|^&^m5kMCCA!MYHE*fW)eYkl-Ww z3CsNa_RctYL8CuzTOtqn1s`3`SLh%86qq|%{w{vPZG8+^`j$yEUcYgJ1lk~N2F7Or zM4ZLv;V~S+yh2w0a+Tpy33X3@Z)z((Yn$(@7737RIeH`0e}4QmCfQdRSLQgM1rcMd z&kgCCx`Md?FOLKTcak_G%N|ddpE_RXyhkT`hhG4)f3-6E9?^SyWLBc&YG1GWlh5Ud zOPOlFK_^t?Mu7;?}_`HhC+Ez;41IKVr1pWaQpkUt5jIeBv zbhhee)-+nWGu_0rp-oE_`mVhy+QQO=$Ss0L<7wE!hFqd`SVrTt!JrQT;~PgW8ALRQbZ*&bTrSOcdYBAKvOQ=D2W(KaO6AGc}W=0-uYy6UW!~ z7}N3QrkFE~&pHZ}_i6(^q+$V58?3B__qQ2TRaBAJ;y=515lP#g^bpgHU#Rv60v$2W zFAS|3k|HwvSy6V-lq+JmiIOW-c0QpeLCKc=`w{>qj&GHRbn_KOSC21RPI{6-ztZR& z==Y2=wRLPuJeP-z1j=P$y=>6&217;Eb~l9ypQFd*W{LnQmK99$mn<={eCBhF zfXBc|uQ;eG`3o-8rodcPUXblYq~naL3`sDPaJ=o|sSTJg2UIgwGf~m8E%{me83fi- z{mkN*$~}oBe6_R+$y^r16ISp&$sW9}9HnbaAVOuA3P~gp)q-o^4q!a}%~EeBfmUfJ z=xBTy$SDsalFoFvDU?5s4AQgz+jtSOg=dKf=(i&_X!`Vv z?J@|uEFT~rl|h|*0c53AaYz2V!G7S+iBl@XS8+t|fbichXe%XDF6+C4v0b(-JxC+K zlbUHP3OLTgq~!`BY!9%Pb@DH@3CbvS%sN#o3?R2qu7#I7&x37$IzPX{tXQGiU*Ebb zD?V@JayskO;55;nxFt_JjaE$_5a~r*D*#f{cQnpFl#cEqx8arCE{v?AD} zFo2vIP84~h(H`-ra@=(WXf9I$FZ9=G>b6a9rZEo~(DT`y)3JDLi`IJxApQVu-i4GO z{uhY2JV}5^8fpSj@OBg@X1jWy@~8x_$-Q}(|3a9Gp`>-k-Auxh_zCk3%k>2nBA1sv z$IlPx+LUVQFfcm8AI5K)yBBoHl&kjhZyX~aAn1s~5fXx%1PyI-lu*&eJlYoU0wsa; z<+1Ds9XoXxZtG9PkKyn_oo)(zAi)c8It!%(3(H3#EK6Jh3-+c_lT~RTfj=@=+0cXt z@~D42kkpvzPaEv#-FEd;TopGDSYu6<=O`VxgwNl==i#?eE628&GSvul$$}D^-GZv> zZm{pt+dI3(u@sEJ8GPLMCU`BY4yYU^^+%~^YCZ8wp=RE)sQ6w3uDnbkKynqQwpWG3 zmDl0%0Y4xB@Gx4ulZ7M-fm=j1ZftK}?5WB!olORz$CtGUXAo#ZoWUNAz`|ElnB3oV z_<|+vJFC}j(I7>}vEO3fNvA5%r3wTU(bjTfsQ5wwS|6fCSOmA&1X|*R%~FW(#xXH0 zQfhgM?GvY#UP^!+nOf2Gk8QytLYPU!uW*gv7*vD2zZ|~U+ z>$b@&x{}^d_V5-tL+gpD^bPhcs3+O^ctQ7ZbPW(T)f1Q-=1*kIy9uE4qqL0);J@Lb z!C&r%TYi&rbw|fu+o8FbLailjln~pA#WXKEP$;5bzY%51+7b@~FSmIh*ad*u^pXlP z{aL&AfKlJc#oYoa2Oa^GeUS#>eo2I|v(r14{bO#+y#2a^l?t_O{|L3UnZD3O{4ncd?lkba&AQ zTN7h7B1ABE@&SNK`<%Kb&wLZTiwYbuwx0L2V%v6Mniq;uXx`$OV&D@p9R(H|ckQNIDFPNsQTuW)Q}0kR|+5 z!x%0<0es3aQf7u0Yg8`5RwtT~x-y0{eb@1VN}$GAmin%bZE4#HvJ64_u_$|a3>R;{ z4?r{cAoQMnpiP-iq~Kt?z66#!i0HMEJ6=-fRxL|sAA!5N2}k47I0YRU)ieQ|)ubz! zf2rO!b}X8)4Z(pcJj!?bpku|@mWWEOr8AfZd{B3t{UptbHpA^K?!WjCGy&T8puGTW zS!qJjvFIJow7@O=&d@Tq0NLFPHPTy-faokFcvPZvp!02Zt1=C_q~hyi`Kj0&pearO zhWWg~EO@7!NxTa0>=zv0)x zYbKgBc#>md*-xGcfc%`Y2pEb{Qbbe^KSLnQ0!p&1&7qJHg(n+fblwGjF@vAtP0ggm zybs%^WFvm>gFDWK1yS@T%^F^{3>7+Of|A`r5og_Fql|tSNO#u)9J?+>m4MDX;A~Z# z%+2Q3=<{d;mY^}IE2|vV19xH02T(vDh_9&Zfism+JwTE@aZ92-cse%9v#~AQ^Q?|@ zV5CU|9MkV9p8z+WgHC4r zjWGqlnD8G=n)^Qxgs^02Gc6?wW3J!m7k;V5va}?O$e3tV-A=v}YV=Dvr{d6+oX4OS zpq4M~xO=D#C&Ke{A{}XBS-B*p)i`nj(bh!q_XqBt2taAZ4v zR2KxDrFg!z?T`n3_~Q!hc=Pjd3__S4cM=?KVO~D~tT-OBygaT=jJbcDCVFS=7?ln_ z3sqJe`{TsWAcK4L)@VGa&IV1+)Jm|P85|GG@TXlqvS}gtJ1Z6>)C86gEdJiYU?=Py zRHcjoxCv6{QOf1?4lGD9Z+h_;a~Iq7g(nRsPCf#DZ40`Wc2I*_tt~GERe4gTfbLlL zL;O%~ik0w~onR^`n9*gpEiu7>wvBDsJNp^jz$ZZBRX}1jq2)Rtu^tuO2(9WgU5K=b z_PeQS$RlL?Z|=>@`HQ8+D`U95&zY!A;CdX1w^b&%BQ)4od4ttYmP=_&R26o9Mj3!F z6R>=CCCIa%34^c5f6_lbz`hEuQ12#g(CrX^v<|}^1(cukvUS%o6(NfkV^~*HIn3nA z<{=DVf`?)D@7_91EXG9&rDkeRbF5}{cnEA0%#sEmP8T|laH2;k0f(7mA%aS+;%aK( zQ$E3r%SMlu(oC%CJcFtfAupDgQf2mmGncsGT`Q|mk_Kn`TV^UZg*y(+yq%Y9ozZ(DR?2sz&XYDE!QMD zy)u1}%FxFvxclREuuzEj=Ud$r(%4o#iLs7eqkBCCDlEtqh9nud1JaPZYRLa`fy~ct z3bpj72{jyDs!Eo;WZFsx;x&!cGBDy@n4()j(G~QF5PxcB*3auurEKatV1>^oh+N0VIB{DK$An)C^VUrq5G=#o3%Z{ym?sY` zUTi0MW|Y#}(xz}iXral~VGzq(#0di+(mGSmV@|H1TPXuHLw{NanRU_R6DVL#JNBYn z=@*OF9x=Vi;Xr%$3UA2Se%yMDB}0+9#~8#)?h)#|p&W{1H`M`Q;NjN{O($8IeOIlo z!%N1oZ=L$G0oH4b@C0dUh~xU0xQh8(k6bnJcJElkS($RR zAhGD&*l(;v;(#!H9#W^go7<&QG-=fKsOVmY8pu>>@CjB%PcCZ3aIV>us*_4VA4uqs z>u>mf4v=wwpnn*lvDbNVLjwompY(a(67zjJ@Fu(LadM%m#&O>x=G5^qT-yN)IKXH@K^GFpeb2Mv%}%TkkHG>s=f)_Z_76Zk!g2B4i{ z@3;D&z1vjT0+NifixPhE@K$Q(CDxGnEEYwy9+uD)deZ`~)vW!n;2 z0cIq~pB)OE_JMFA-CH`~bEtl@^fivfoPXL7S{6hzW_%0H@;(EDf3Lkmt+ zuyvQdBSPVUPw=froXv{67I`TFf0(@gVg^C`OxrZEg|0cK*#zH$lLkiDA%j(jV>fdq z$G6;tBXy(PN$DmD=7HA?Eh7L6`zbRJ&dx9|9mgV$GK=OUfQxj5H+6?FZz{3_*-wq2 zjJJk}aJxnPumep$EDFr+rPtV+nt4=+Hk?BUie7UI_ zj&+n%1aMx}s8xo4!k=ke+3AFgOCPQd(0wh&$=qr--5o@O#SFGxxvM9PX$JI4nmP}9 z&Al)!{xSz(o%N;IAe3BikT#xwDC3H0^XDI~SAREJY{6jo6ks?=leQx@lLp+w0me+u zkz`X3hu`=Z*J}(7`{K*M-k}lUx~#$c1yY4MpBPS>PJjR%i0$C(V0?bX`OXo@6ZB9v zlt--m@{^G;>52s#S5e9oJUV`CryQ0&Av8-;)D*Ckxq5qL^R^Gm($oex?YV0GXLC&t zz$hSvOHk}+LHB*AtJ2!s6pXUEj20TWILA}I$gzO9|LLdYeObGjaq?*Z|MIJru|Jmr z(Ff>$%U{o~2a0gHFZ6g<$HCEtp zfZtU2UA(^?48JX9=bj~NRy&iocvx1ig6W8 z)@9&58a5xBY5D6ExT(`Lr|C``m*~9CkLx4^(cI_^D9MLHJ6mjrr?GG6Vo$7~xb!t^ zudc&@!1n-+voS2bRmEB)!~vw@O_-sJv@3rO{w)|sRiWHE6=<7o8)XJb(jlMSR3j+k z&K(zMQ^ie#MeyM2Y`<1!K@4Vke+=>;+Af~pQ!~LAW_+WcoUkd_X!~V>2ieFKgNQ^@ zOn3Ay@zt9~H!DajxP}uWxx#AIt|Erf8|I7T83RSjKoOpznNj*lo1pY8=&4yj_bHk_ za?e2>llkte0fP^+9xP}`u0CzqN*;*=B*~$pP%;IWoB@S7qdTZ>6mb(}iLpB9-+za) z;7liEq@WB@Gp?LDNp1O|D4!+)#{(I zc9y?p*T`q@vi<7gOMyTyNF9a`=IS&g*YsU#cMy#Fi~P1BMk_QrMDi&g^ycK#g>d~t(#_@&#YkfBgLkO!HzY}hv@ zqpbhY{r8_veeJrKF*P!Hc7aUag>}YiKSK@)wxoCdb8qwH9q=&DgJU>;ccRm(59J2> zIb!v>U{rt9yY9CluA!Sa;)gtH0D<5!Ko>5da>M)>)HHyZ8vdn7ViNNMf?8n^t_)-* z1F?ypRA2)Iexf<>~`R_+`0Qc0o;ebhA~i z(C0!@#B;DT?@H|8AUTZGPV?u}34B)lECLR`!{D$P`i<;RJ?zWx$R#TNp{yXv7}5f_ zF;A}EU0%Y1+W9X>X;gKgE-VH>6l1AA-KnKHK8i5%bxxPK|gy z-;L^i1e&D}Bj9uy+M*NzTOT80k_0p**0jX;l|Ru8ld@4-U+bM-h)vGCbfOdBV~;9! zFV)Sw_eNayS)>LnLLk%Qe+;QHJ{Yowyg!>Cb;axR?L+7_pgWOYB16c9x@-cpqjuHJ z(5GhmQYgf7!Ym`D0iLO=&5-v5iD5r!vIjNG(As#w87@VcX6=_S!r=O_3Ch`6hDa`G zPGmysnXX1vC0hRV8o3`Cmj={ySa^GesQXwEx98uzNzA$7dVWr=;wC;0Ylre?Q3K_88PF!b>W=tvaI z;Gv(gtLgR)k_^=G6Gi>wMl|busapBTmPly{3$+ihQOU0)u5vjms++v1#IPhx`2tTi zB+Qw=)1>jw)H3gChjhT9=VCVq&yvebcCh8cPeQq1>W;xcdd>7KjZNG*ABHlVUP(bE z+WZ(Y9%m>NjrDGq%O z$}ieassL0Fy}^Of#7L=%G}ZFp7vtDlqlKY|v&mkn^-4gCU6ezt(ao06m+!vEFi9X) z92?!St=JBlX5vV>4nL@uE|R7uxqF5HCP?#_C{KbY3BkOSK$$i-aJFoyruOJ<1(b^# z^xddJP*A&#kDQ#5AnKX~3E|clrY#nJ*z}k1VmZ*hz#ZoR$;3Jpl=bZrqj?~PoX1_e z14@sm4f<97{Jhryk&~5`eX2-KBexXyaGv!wm9F9 z*+EECZfvWf>B2AM-s>;M-nDa2c}}Z@ zbZ))p@Vm0OteV66bHUL583>mDvelcX zXSz&=ET6nlESPumFSP^Q)^-F7Jp-c5_hGF+s)Xd9c{R;+YwBR`Yrv3glnc!bK*Q@t zFnYz;$ihH6hlCAGxttnrtuDY&T_ANwx+Wy3>kk;skAXoTJE`5gONe=p%zFdm_w|Cc z(6wDWb|rJkMZYHRO4~p8xMUzK+8;T3M5c27J#l1s?`yx;_4`T4{aeOrP+W4QNM zKzR1|fNlffcmNEMAc#CX53=e-4aAK!3?=}jfRWhdU4?&$_?!cKR#mx{wFb^%KPmH> zxkS_Dy0gfLOa@1rD|rSVKjES!y86`3pYolnJ{{ci4&nT5uOTf>MmxKyGn4(v+hvqT z=Q;<%n@eS0`u#d{&n|$P>*X!nmHP03xDR4q(La9~s47a^`!(lbM9aynu|%%}ec@wCy~6&#pMPz#zQ%;0>jQo(XB|Sv6AirW zp3f_mE(j20X~KO0790cjjb$N6DXxg<{EF7$lbf|Gc@@gcO0u4B&e7S9SGTJ(1=~Wz zzPv`aWJzRXI>ju|o~*GqZx~$WJ@L;w^!UH=q61j}kAad4W$l#*w_MNJ;$~>p;N&%7 zZbW9ShBvsI7&-j*?eWp8^#;vrQ!j2r{{C=dU3T;VhGEe@pwH{HM#ufHHy0~|-#!1% zUOkn6$*A^Qjz5n~`tr!5w4m)}ByY@lEk+_kV0~}lcPrOquV|E@i%K7>A0z>PZblF+ z{U@M^4g@YNgJ-Zuj{0shh#`7_bWOkw$hm1??jSGY@0mqWub9EYAx_)S!X`_!j-Utu z-xv$}j*#}wS%=s1zJQRKN#ZD+96fQ+ZzLdS)FIWcDZ`(mdMxH;%W`{1+;6H>kU;pz zkGv*&t~re)!#^6l$aAg6HD6>_B7fu~$&vnxKl1Vi?w2t53}8hN)K>?=2J=k_32tL{TtR6To@%x7?mekq(C!pqN@4L3PSt%eKLGB|596T#@(aL7 zr|IbnA$~prd9skzt)cB$6J#s(3iy$uO>dyVyqEH1z!$-?F<0~+Np4@mc1a<0ZqXAo z&tMXc2v{$SG!9iw&NN%41@+pQY1U?vSCm8Ec{S#A?b`RXN-Fu{U9Y;iN5+G`qB6bD z1J(+Hx&zyrzBPA0@qA9>!Ldq&gNl0si-W==4K>ezyl8`&sg{&yN3JI0VTiwTBgP?F z_({9qP?q|4Pwp`^+|kbj+MzxeJ=s^Elri_jvR2#VO@jPo;1%kb23#G@&s)uVEdET+ zgcA5qU^oaEeoSw&WZm%%9sC*F3l>&)WVUuV_wHGiBvz$HKFmFGEh&6F&2Ht;-ei>; z)@!%NWuSFnq^9Pai{mIlxfWrqK$qJ$ph5kl+Ea7kMia95(5@o6H$`>yaqG+F+oTpO zd&N;4%KIk;8}aY}MSPmE$$Uug>6%-^MMq7yY~;_TBq*VwJ6-e8>C1d;Ye?2}XiC&U zp*w=QWR^ZrXr{4m?X@v#yA5e}1#sws)5QIZZASJaTK_Y8l*DUn6+CKM`7)}7e2Dsf zz;_Xp^9wDuQZ9NZV0+-U6oanl8_s8%R4UTtT;L+(;`YNODDYTh#kp}W)a%mQ1HAyR z(do*`t?AWYr0vUe<~SOr%YXm)+^5VD*W3|ZL0Cb4r3BUd@>G;mp$}&1Sg%H`w+kN5 z-@nPiZD0Wga5aodSB7H`=s_~6{vzn{xK^vR{Cq8o+TeAZsXBP4{or-aMln&C{_xF` zu{CNgH9Cv7~vOf*nVQ=+ogeWV_TZu zLcb}!gS_8{5EPH@!>xxke&=6JeiE}0QhB6b#*bD!82Uw(e< z-#)w-SsKbvEnjc@9%N4=pGjx}@&B!YM?ili(7!{8XK80iP?lacH0R==Yg|D{f7SZ& zp2`?}2%efw}TIx-mik6j$??D>#Z@!wvU2m3W!E74y{D_F&AK)sve8QncB}nCV zT%jB{6$jePz-R?gp4rPe&Yz=66;-$HnPZ)TY5SpN8B{f6?)ct0f&3SRZ;RpX5OA!C zuk2d!0P~t(?r-|a!rj{A20|M$HA5!_rw+J$nXc;(z2TtwbOne3NtMJ(Q7Yt-X<7 zt5M6=5OeFssIyQ7=Vn|wE&&PQN*?sF59thr-WXFe%^GMz7~+7ku5X2 zCutYBZU9bttuIs*mwfA{QNliygLzQkz^bKlh0g=SbkCgNlR+wxXnEf5kriWg$!ft?km{rnr35mE&XgKBzmU4 z5J^X6pb1~KnQSMX0v90+;4p#8nH3aqp38wVSKGy8Z#Z2reD>RdxJBv4_Pr$Ac zFmH~B#MKqf;&>)Q{R-OW1uK(5XgC;}*JHRb?%ya=h%!9x4#&p^_ zu*U9Td&LsKc9 zCF(~w!=89w7Cv;L;lOJ!OR~jg{!z)lB;%MqFj%)yY=yZ12H1loea-+U^cJ2~Ezw|a zKQIxE$AX9q?J(uaZAO^-1?j_N&Mpq<-v~85$wo(!C|!_RE~r_qC$;D<-Dj{~X?UDB zjSy@2ew8@qCN3X|XF&j^PN2nwxKnQdGG&BKfN_;2snFud)OKwBnk(1{+W}z@R{-YP zs&)foW*e&C?ET1#fRr5I*FQ>>P#4#ndCO0fs)-WdUl0QzmhO)biQN8idnmUXNOgZm zeZ1OaOu7W0Ho}L8K$soI-uvGz(s0m4@(Ji3l%=v!UUJbr%MT@VR2`!NOeT}m<3E3U zj&b{20UqvR5qeMtYn1T8A;#j;Y6AEaqk~LZ9X?W2W7G?PPzb*hV}~seFb;%XjW3vq zlJ4@tj$VLCExUg_^r(qxB_K(Za+0!z())+6{7RCUN6E6jV>C$N1V|&ay8S!-XwOby z-rrFTsxA1uS3=KSUb)6t1rU*5coKzVt8eVX5G77=Wt?qkyU_6#J8^KBGFf82@ z^*ajY2}mndi6@xlnY;Im4l`iav*eERpN*tKFqShJAXI4Bn2sxd)#ZEY4=E;00gwI# zhPK<2o(srAprcicxM&?~Y*u0VH3zmS{09av7PhQgzP!{KbO6|)fT*AoMb=RHbONTW{v<`% zLTkrrCJSs-{;V0Id40zBv;~n z6`;qHk_EkST(Cg>{QXgyAQ2WlbG~;kFxe&Hrjrnri{wM=1*s&eEfJ%n}eGzGSxx zQknP7W%1#V*4qm{JhnJy_jYA3wGqf%xqf>=3r#s2o2BtxR7NbPepO)UET~Y3A8~yK ziH-&;2i3_?F?tV($Y+J6ddjK~3>EC&w_)4kc@-ST7*;Qz}iJ$-0;OuXUMOwi%tf~`S8KeFBlKa_4Kcocemq%&4?t8h*zB~@yk>fN96%jgzX|M*X}(ad*~}05t?WnzX~?x4HSzAo*=vIM6lYZK}(3y`|9g6T_$7=Sh1UTX{L7%U_zB3#q)C?EUw7igfNSl*5!e1!~g* z58MxXWr@8?ts8E=7$?$%O{tiuv@uLK80KRcOyZs&LS-Gdonkx+sw?I+wCc?_NHF zUb42P2|b{L4>NKsV+#<~x#QAd+7ct|a6Zq)8I(7Q8@vX2rvn1fPZT2yYu@-r)zS27 zyWF|@DI3K@0jtKdGm*66zV!$&eJ{sNGkBD|Z?*Ye*ZFhSFslBr{nvxVLuV^aCWLM; z{27cze!`Nc{$gu&b)>FiXMjL8E}2!S$B^r8;pf295NYnQD%};y;{a^Q#rQ4c?|sC8 z;B0@!O6@qk>%zhMB-;X^Ae@!opsTu~txziLPK@Mo-Ob1!ehE6A#B|yYI^`kN-D=*& zme*+nqB{qoyAlE}6@py{<`M1=dwJzqf;W_<^bE{S9{LSRI>^w)-o=zw*L?g7FCmDKgQdS{-er&?M7oF_JeFle{^Befq z5pS}Y9>^`)tnhh@1zLgmiL!PmQkt&Xl3HM@QWn1{sCfO2#*WvNAoPN-4RED$XQ%LA z9J%mpKtS-3v9RxcMLqs;))>$0x=;~leM267vOO;wjXPeCpK@%6ymkpW-b#`Bd#CI5Ss>ca@dylO7;CUU z!{)C@;buax!ROURT>pdqW^vu-`SstfmN=i5EcwXm0zs91Nw%#T?ST z6961{C=4cHaUR?M+mQIsY^b9bEXZNI96=bbWs%IMVP2Pie-Q(kF92rP61`zZ^9cJlT#~%u9`abLlY|%V~joFYl_<;iWkS~-Iw7Cn( zVqQAv^8xP7ZapGm822B3B{qC_gAU{j*xO=kbubSNf{Ba%G!J?QjI#>6KK(z}=g+)D zFJZwwoMHu{>v#=k3gb0nV21nYC0dH*KAZuz$=Qfh-eSjehY%!4X~- z$~z~GV+ZZ}=z@%XZ+2QS8JS)IA5A8?V7v5euyF(ya1UyPIy#LVsag_u9Pq~2O_*T$ zH|OvhlI{4p&rt+2e+_7bz=FQsi+N!b{Bzc}C0gp2cO?iNymNV{Z0J}{PRf1p4OPIC zxZz1s5MHD*N>7;42SS;N++yFImj+FcbjB3!R4wNCs7~KqPhSPd=XvRg>GFwp^ai=!Wjz?}gs2uvC}T^R_;uFPuwcyh zsFXwilT3j(TG~ErHX$~cKcvnX?1(K;!jRD(+e8L|5=o=D3h_=0S{=V9T0+%>KQ?bCzoxo_0Kz3yZ%Zau}9^3Z{$_Fpw8#u zAIj*3X@Anc$-H!2j#7E;Tir0SZT2FBasFBPkq9b^j(rFjq)#|?BLe#fGbx+ zkn|`n9d8fwLsPz!RtmFZn@%77kky8mh2PVhCO5U>XgW6Co-FIw>@( zb#N*&zQ}{k^>A?v_V^lHSNPRZwoC)kBEbPR3g9iqn^~v+1)pn>au`s2!PQacp+bFI5I@mYY?M{!kqC3#|ZUNXD`6$rJdu zIbu7dJ1I5TFrGHp2TG8mm$UR?4y5_eDLMZbF)9A#jvdJYw$#xFYkz{I*(hwND#_D% zdCux1hggh;CVWN-l^D1GmxW_T`lAL|a@z&jgDDtb&knek0q;QflM%Kqkx_y%+~+gt zq45raYZ9tSvyLlso_nc3=0-66MwJ1| z<|P=Z%;0O-g1K)ywR_y&i;i>cP4@-|V69EdFdxWq&LH=I`x?24T{qK z(}pI~%A8BHU%F^Iwe?D0{U;fS7x8=q4rT>E^GIyngImBQXEi=!%HM@}dwlG-U=33+ zi%%V1^S2>t%|(Z#3*!;68j4P^UTO3H>5MEmqbZ7qrkKFa8e4j>maZlkVy<25k!4sM z8o;H|2rvoYr<7hB`$|!JJ7V3XmX6233v_>p3Y6;n5k#FS7Nd!_|EsBm_lEjquD(QdRB&4~z)*>7FgCkMXa4R5Tt9{*%o*7z*8 z&6iF8Vv=Tl-}+Sj`yVZj(Ql=zWmYu8c+3U)^h#>p6LC%2Y@KZ~k+luh1dP#0^tF|0 z`M_J_i2YPKia7--16~>xe$45`U;GCYa7R}Bgdx5sHDhV+q@$?g%0P+MOvw?G32WcJ zHq}UmRocprp4B3*mH&PM+$C|&2zEgJqX7}U_W$H88+7DvPK*Az1Tnqxe?4P!RJlnt z{MUTfzl8&oG5;qjZX9E=*$DsVv3W=TV}%>1aBsd9_s=u`O~Z!&|1Z+;m;b@CoBxU& z{?0!)1odB_0r|HwHoW`)UO8;&|NotabM}Dijyt9*2UT9<$cm%k77)q)0aU!DqU@nV z+^I)Qb+QsB=GjI}lt%}locIUBBCY}OjRgO?LF8}H{v-eYCDi`U3F@!>XOp!50u9LD zg7{mQ|C?#pu)qI14V&u*ZOhpS_AKGMRdg?>%pE7v|E<6*Sr`QUN4fuBeAGYo|NrEq z{^!*FHwPH;8>>4vpr^|t*=RpH{6cMjz3;xiy&5_g3yZfejj)%|u%8S_S3d8~ z{zNO(rTWwUt8Y+De2X)_Bq=wch){%EYf~-4Nz+J|vx*d2&rF8!#P|)woYk@RwxvWC z2;Q=8_UHE*;fvKnD6*92DRbXT9~_Aw;c9TRwU?;A3d%uAAX-ni3TaI;zPv@UN|qRKxUb#zPRtq;`RLl z`@M91_qgtw|}!D>&|o$HttTQJR4JefAL!S@}U8pYHi<=bM+%X z21;%sVGduWiiR!_DngsG%+8naa z=xHAPX;EA!lLd&8Gv96GkO1eJjdy;UAqtTcvN#&UUnK@`b8eu?ckp;VXDtYG2v4Dt?@KS z0A)@1s_&@0KZv%HvGUpCQf|sz+gnG-+yhT7nMh?NC=k}@gB7SJVAEh?Y&(SkwIa=Y zO_`Y<<*{9A-MKJ5rGZnrpXiMWGnXN|{S!Yr#ay?qqpjsw?Yryo8eTvpdKYoFe^YsU zQarmb>Jmwp!0`O}7qctZUk8~ajIEvUJu}xfFe04F1>dZ6$F%3V)9;@2;f2wd22VKb z1pOLr_2Tfi*A8D&*7^ALBfW1R4ntM_3F!)nfAaP4^& zz5H_f$Keh!vcFzig_L!bo{`Q(Drc!HsIgyjKSeG7`hfhq27L5lZ1lnKVqKS4{al@snxB&D9*aAwDAWky8;3n^|irP#jL_&GK6!6*KR2*&#P zLQ#{xU8Bh}4}$PiJ4yj$V+=05eB>WZkJPsYo1k+^e@tTUkUdSAL-w}r$_L^drO|++ z{JXNtl&M4tFTB`GcH+D;4*PbIG^;z5g3gwk6;&m)HAWpH#%@#YKHBv`UtIm7(|ZTI z)O3Fh85Qlsh4<N>xs7{d#Khl)6}DJqX$$GLyR;$k!I=Tuq4 z7|TZ6BxgmTzCK>{(j2R~{dpY`xweo0trWWhn1f;D(Tzcwr$1Zmj@5~nl;@^)! zRe#?p`Q0TSzTkxOFz}KgI5aB{3Z>|BCz`sM)a;AUs234-xZC_xJm&l3mN7w>YP$O( zdSBsdQW86=IY-4PY+OO{ZqBI;HFBfj-(omEP0>_bN$0(7+H-e!a^5FqoV9jVI{GUb zCnh}+xd#~yxAIAQpVz&pwb1gaMgFBxLek{r>CB+c`Gcr|So!2b&g3Vi(>YzoW*X5T zzvfhmTB&sQd@zLvW8+K89Q3kTZwxGECO?@mA8qt+=76sxaTd>}Rf~60?P?&z(FL-y zWxp7wabPfd-1W0@vB#!(VDhGw8CQhlG+T2j!gW`&PUm3WWOXVD1-aQWZ z8o{nT3WidvjKN{ezZ4Huqn<-9goR@TaSO50SFg4b`*eI~$Cpy(u7DacFg0kxd$kl5 z6Xhb#LrJE5kGqN{xzRh7P47;O;Rb1qoZrfLVw-xo)ibE#;mL11|&`9)!l> zX7kpu@5-Z#y3t~H2NL2MOgt`yGuG1z-}uror%QQ_x=fyowLnbu7a8o0;B`0|rP!Tj zCw~9h=3~?RQV@0kvU&jd@5emn4zRCsK6Cd;QCa4z7kV3TW+<0KJUfEKvk=Qb-_Uwh zm2+tem3*dlNuCoBrw*^vy$NtaE>s$Q(gxFq=s6ihzBIyGx<9G~m(KUbbKX?n8>az% zV{P^(<#iF2KMx!ikDv>-hi|noi0b!iR@7#={%QY`8h(jCCeNRN#($5T>#=_36vkEW z<`5I&j(RYWElXjP8J~y7)&b(>&wtBO`&0ZCl^}I~0VR3%J=2F;$n3>6&8SqT_9w@H zAYFY|eo8iZ1f?iFw7!RLAmoNx^*^*;Y7ITL^hbcx+m}YHc?oSoXfNp=KDi+$FEJaX zrM9NbwOlOya6h3f2@P2CcD)k!HDz#zV8(>0ezM7l6Zw;M1?_&#Fy+}%Hc&RxfHNK! zWFX8P)pFg^gEk-}4x81y^n|t%QiZ7p{=4P#4qtw%HHA}owDDr;@pyCiel&A8@ocTA zbvmK#sX8y<>kp+&^^I|{+4q;eT$>sSl&gRDV*Q=+;8ww$6PR4x?3R2}pKy0x-*v~7 zk8bVC@Ua_)PVJutgh?DYhxf`dx7bTdO!d=g?BQKcks^c;7;v=bjh?umj>+wUf=s{W zTp;vvLfZg(hRfDKgZD!HKGR1ERE?Owm>`@hR$#dn zP$;5z9^7Mgf@#k!r};%_E}GkJkFC>4G(>TN{4B_pJe)Rv4X# zdgt{Reev(Ks|@u&?Y2j}|0+R2#L8Flr$h=9+K!+hn3?%1kCwtaSk~Y^V#cEah=lq; zd##XGd2q!#C8NBkoG<^W{!S5Ui}I+9E<@`F195eMU=AN`AFiev_o%yK<>T(U(RV~# zyC6K~&6m%F3LX&d+N~5j(ew)80LLH@EJfY!*x4m75j81ZZgu*$zx_7BeK620)b(W6 zEaJ4eHL0yLuOI4-AGk78{eHR_MF_&hZjZqc@b~rjUg7wbvM#QoZLv@r)X&%_qhfG- zaWrL6NYH6tcEYr=ukSizjGl(kY%6gU7i`!ZBCB#u!Cv3hC8kpa_TP@da5ONa)(*b@ zkTQ@faVw!M5^WLRw-VfD&78pOO}m{&_|F@a5>whG0gdOyv+phFKa6*K8*tQpNW}y% zp8Y!NhM4rzrP_kk^4ukjFdhAIDKgUzi@A631tNYY;O$q{gyp0NoQ9yFobt5JVDpDJa}T?GMN(kWQS#VSzc)8w;I`>9FZT5Y zZ$%04Z3%g=6c~(fwdtlm)b;AK64K~Sv)0@jo-xG|hPSWcj%Fv6>x)Mu4#(CVBMRj; zo9c&UC)9F;Ul~4{TBZ?4+pH%Zp_W}1K-{5M+6b`~4ag9&d@wPWF(%n_Arl=X&6(-{ zA549DAe3$U_Kd+~8%;#^8YFEBiLupVBuiv3dn)_RWC{1o^HheiYa#m@ij=ZzDy4-H z63H@2h9M~lW%sXCLfj&bg z!jcYMy*Zn1Y5d~oI2cy-xdZKDwBNjGlX#AT|Gs`c{|)`|hm=c>m`srp z%JsAnBUbm7DDJtUjGlfglcMfZr61eiNwQbEko~zrb>I0sT$=H9=ed| z*+);Qku~M&NvW72l4^2bSP3Z!i!hlIr&~}x(egF%#Se(0OD-la`Q|YI z+BRtlEuok{ec*NXJJKmxWWeJTIWCLK41%%btxjq+h$6Hbr`ecPiKrDHJhmV}zX?5H z)89DCZ^hbV`iT9@^D4E=D30R(%Bp&DUYGd|>SDd42y-PFJwuaQ$*G7{)Yc%}+|1-| zcnP>{qx(Bc!Vsns{S!PW?XM0@E9|r7e|FKYc;wvXGK>n1LAYbVSXNDVxwRrNzC=a2 zBo1}nh_yjAHMCWWNb1^EGg;(A-1NE>lWG;kKj-WA=-sBF-Mlipm-rO&LL}T+PZ|(>P5NE`i!3K^nUax z$vDmKfkcpl$<$%U4;z<^6Zap302Cstr|`q8ue3awFu+RDk~MW;8rHaVE(OLynZMNH zk;pePOv`JVAG3Aofj2hOnh0EMe*(``SZ z`88prWi4Kh&&)7x2UQ6StDH<>8{2{AfQ#Nvyr6#JT>c59HZ|(tN-R3!beI_ACK~V0 z6-ivR`lZB~hYZVnDEzG66YAjF$nG*$CSOr5kUk&WqQ!cI(x)*jx#lT|JdBY#;Vhu< zIg!m7N@c*lm629mr16)D_g=&Itber&az1K1O2WA3S|_E`icKPdO{V%FL1|p_nOFlL zvWU74RTiBa%XW)$=DR^)K1}%srfn^UaY}Gnk3@eePoo_hOP?52HE*?^f#XTW8lg7#q zc8r7`D7t@CO_9|ssFaEFL-=)e!FY{6^7n35DC08hz=64*jGo7!q7y~+cWy&s1V&4C zn=NVHg*j)&R*EvYR#BW{7%T4vb5TA185lZ{#UnsD3o~<=HzrYM)2s#|+69byjamG7 z3mRHkEa7wN&`=n^4G!oxVCBR#t0)PL--^akECe~9E}&rSknT_|0%)9hey>n@_WS|* z6u=&)1h@$pvL;cK%i7)bTFVvsk1JCDu{JS3;h3D!6G~l#HagC{w!Uwj_dSl9c&j8# z=|S%E$`>la$;?3fnHZQE zY;)S;nDQ6Ur88>+NQC>JOv)XoB=V<;1n*KY?&D3KqX3FrTK_N@@_!LY=Gm05MK<8%u{L zTNI`)f-Y|aLPGi3g}g?smb#Lh;s}*^+(zY+A0fMSIUF(!@jGT3n9ceC@|EWEaZ0&F z=FggZZ}i6(aSE-EQq9p~MsXX?g;lTEAGG*0M3Vlcx%j)LPD$9K$&Gj`6Ql{%Zp0B| zt91wp8rL>^K{2L6-xD3C;U6hE&@tTx^LCD=LcE7@z0AP-*~8S_ZCr1I?{zPLnru@T zJ}ttO=-&2swDbTG4h?7;Ncn;dmgI4f$uUT?*+tg*sA8PeTHvS@^|c8X&)CmRq(6YE zc2-PbdLTj-puVQ;qDTcLm}SPO!fZTgnADkKWin5ZhoQ7fevC+O*v7^0Gn1%)u31I# zF09DzhSES$$j}^DT+vS9e6i1GfM)(7j5;U-QMlT(uS!IPmtCJ|@o1KNZ{dzPn2pn? zU4;$+Z;&~w1Q?rtNO*u}AkqEaD;GrcL&X>DOcJ7mxgNR}X)@)`q)hInCh@Lm5!+C! zLU)ga(NIdzPZK5=SC%pHZ{U6*!|KVMX86>dK%BjU13APz%Mr5&YS-N}ey;!VAb(Z? z*4WAv>MrzAvAmq9Mo%P9lhu5~eXvW2zFfJ!p3#Gdi8}7mm5dOaQy7|cKd#3Ytw|*1 zV@oq+vqIMl!cx%XeWaq?`yq_$oKX*Qi$y0EyOMCKTM=QM9e;LPBOAh`E=OhaQs19L zf9(&6?fY~jUjSz3oW4Fb{jgg*i=IShw46TZhPeHvuHk^A)VchzF=dx=)=7i==EX>c ztnoLZ%PwbBwBS+{WBDBorNz>w$}QqJbTOw|ddCi(-30q%+5FAPW4eLPGRJBZhmV^o zccPzzi-7_-l(Fvu$>;czF(-)h{iA*U(gOMpl^Hz`HHSU7lXsZEb4IOHg*#=0&N6<8 zEUeASngw(H;-i0}=6E2#B8wBUxB|)saPE95=aYf*Q5gz*(7q?Q<;wSQP!6A$Iu6rk~yOH?q`G{&aMEu0ES zLHeg10cR@GwJFu$u4?V#Q0p=>?kEs)_#;^E=il0p+IOE5MXk@&p0djpT-zH&4Eku6 znCqICJx_po_)pxFj2;(y0Ub}b{`S@G>C|4PMa!ow+oVdWA^i^Be>HkfX~vNqM~Hy} ze*N0#u#kt?^32=o{;Bqi9!vwR}bED~X)Y#mqND=m8uA8W>P7yZ1o z$vmRW@6~Q)cJ`ao>kiG-DDha?Y^%X0-VYEj!dPVSP)5$=M#=hTbXU-kM?aHpMkR;; zSX+loMt8JYLfUdEBqu)C+a|}9yPgWzD4S=MrFLt+9`w414)cTGlCbr%^|136`#-L0 zB$TgJ%4MFnSae+o#wPHsH&um1Bq6S8#aZ(T8Si$KyhXXlF#l)OIQ}M`W0Bs z8&7Q5J-NE72Vvgh({lkh+b&henAFji>4tQ&<4p-;q+B z@sJmnKOp(z8$F$(>+vhn$HUi6j@iSMzCYzGTB6#S-K4zM>2!4e=XGJa92hXhM0zO@ z0^dfye-!Oqlf&s`6e0>cpsU>NjE~Pw;y)%kN`CM&$0wyXhwub#3JPH?mrm|mg;kr^ zT%^CIl%Yc1MXo*vjt0ir>_4hpqN=i?4*iH5@)ul7&hNj{%#^>NrQd7g&>DO~HqJ_) zvy&5XHH{foZ5Q7cQNy`)0wr{I5)b8VulyP1MuZUM+H@OoMfo$a8{kB$=t04^eRayO z^we7Wf{QbH#6(4q5w00k8mmJqS#T^8fL_?{XT^DqL>1P`w z@xgbS5N1EjsS~D#hB8b~%Wsad_Oj2QtX&%W{dkRG)lRopDT~Xz@OTp;%1jRjkL`K=M3z)%JIues6aq6<4W{X-Qq_)tplI* zU#8Y!gtIzXlFt`ZOWqa^tQ9iC%fGtxP1#SUTSciX?5cgF$cp|ej23%xsp0xF(dqv1 z9i`{jwKThk3#Ew8b@%Vt)oNv5FO>x$Efl>`>WP+QH|o5f|PS%pCBOmOhKT z#oXc{O3(;?p57J02!|)hv^1S?6>b*&dhccu?yligmGLf70sVvt;{GjFA~BUKL8KRZRb*|qqt0(^% zeXkY^W=H*a{Y3b(^4>WFy>yDPT*cIpg6Q5Rfs1Wjc;ALD9Llgr#_jKoDoHjTVpPhR zQsq!(T%(fL77LV1px4A$PDm%@kcH!azR+>e>)3MyW?c>(gAt5aVc+-It-!`JmPJIB zMqG|q2BmpGS^Odw_H*{)3oXt@Kfl`?>5`s3zpTZwNB>51r^H!0ooLvqVOjDv(o}_Vx)1|1B0D|EJAb1P zGn<+j>(EDKJKVqC2#t+pL>5;3`G1*OtTHYO?!8wS)*-@hxr6Bl?QGsuBhS*ogu)5% zhpw`viv?ON(@@6x)lj{STX@!T-F=_D8acYn*vc6g3M&zUH`A6f~UCFouURtb+S}bwPA;ZvfVYz8i z??n95-gS_<`s4L%BXb6%yht#b9JTeoEdcNl-~t3TZ;Sa7_+8Njqs$ zQ?_zSizQX`lr%Y<`0LrEbVV(0P9mYEy9gxzb9T#3!53Pthl0b0wJFj!OKaKZSk*R0 zRU$xPBK!B)x+uv?%4~gsEyR$fHzV6a7|F#u^pUS2=SoC!xmU2Ni-~o?Lo_h1!*QeW};5=@f{>Tzbm?~#a9b1XqGFMlh^L;Q{ z;#Q|vkncX5-XJRz;ryk8u1aM~l167ULR&>6MCTsBtj`~G&T54K|IZ+%^wt*TgTs^i z&H{O&!&>>O#lmtW^XMIEaZQGR3@*0`OCCAV1zZA_i3SI1yd)VNTCNawJ6s<*Gv5#3*i$(*2UI#AI*xY~ zq*Jkwx!fpIYyu{cm93u_8oTM)be}K^5dyijx&x|Nkt;5fuduiD#!Toj1a9{r1aPnM z4d}8~fC+xkO|7U3$Ij1Fo(Ni1bBxBhEl*DqVZBB>T!Q}8xka$3+SY=_Q#UKi+!s5a&l&SB59)yA$Z|5EZ zS^YTjk_ki0dT1GlxoevSR7)}-2w~rxZrdG_Q-2+}K;;trrSZS4@&Yd7jw=Ff%ZSvQ zLnUb6nvOli26ma6n`c_%$~Tip69gz=gR6Z4W7R$NcN6Tf)5O~df= z-~-PRTa_SHxE*}C7OVPmb{_AHaI~}+wjC-)G$3NT*#1#q{TV&g{AcRBX&lp)ik--| zm^>!&X7>xNQS+MNu|06qOwMfs$6$e!dh;PuNKJi#luWtQBPBlyl0AQ?Mf=ub=?$@a zyEUycsxb%Q@`Za6&lXoIq!Nq`W0s;BaDm2#a=DiN8(q)RrjokR9xqIx0kzGLemG!{ zZWDwi6WODv87}F#UR_1wEHbF}ll$-kbp45JxR~Ovoi!zNBT7pMWBoJF&|@$}Le0uV zBR)S7(32>n!JIoNr``w_b*jO)+4ZIo_7>FR8~_i45k{L|W~h0!OnKzRgPKgjJWKhK z+C6h^lhPO%ds|VQJ^z)u4v^t?!o~0Bjg|d*;DQk&J|}KzFrL0)DUGlNsiAB8?y5j5 zzcbtM1n?+!Aba9p-tsVyoNVq z9JxbsP!$d4ew)EWUh76*I{bBZs%Xb65$HpbxNE^>4WX~ju98~sFk0e1-i}0Qon=jA za|-kQFD#ia;R^2$F(`{~}&9lzg_|8l#PJ#WKUzLGtE9|>guB9S-l*#`{{ zRwhj-Vfda&b0!&BjWh>th-?sF3!CRry3kgF_nHO+`0fR{P{&EB!t?$l>hMpvNy`j; z$qOz0B=_m74llG+xEYX8F6PnECAJ;8_2WXJ5Hn29)*;ZHr4NM3+oQ^zmvJ?z?1zbC z>^0h1IjDbAhXRBROk=nXqy>x$l--nHFvrMdhw3S^ocguBOyyb8^2b@mXKY*3PfFTV zi71W{Eg>kw!+xM)KP(x`)7=uhGwEPGY`>5Bn|PbDAKWp+E4-ZvcJ2~0czXngVxUciUB^nP3F@6`G z-U@sy?FI%N#yNBNdx+HYM=s`tLj(_%xhCU_bgCAsi-cgiV-}8V1WFx$CLMMc)gNya znsY0=Q7jgBRQU@u@Am;UW)f3pI>-woHcjaG%aLIy@}473wOxmZiH(=en*}5Rz!pDOk_88Yt;ro;S2gYiM8SQ=XAfG<3TyM zc>Ci`Ucx~^64Iuh&nRmfV2n!2S6HU%HLHpqtrkyIC)_nN9wsML6nF%?!Rpx_QDbFY zRK%gMB$PE>Duh9f&DjGHQ>lp(R$W_`qZDMyXs+6nvD;k`-lTSXG(>-00Tt?Xg2~E^x zMH_(Rl`d?Lc^6#S*Z@<3j>Cl_;pjk4OIMn@mssqN7jO&CHH-k5ZKUT&J*r-f*haDa z_E(jHVFL)j&Rgd{Dxu3Dzj+x~$bO~Ozq}fw$gfYgrtX27nUoKa-Zyf@We)ZJgj;CP zBR4}^IXABu_vAyPeoaQtEd3$KVD{C}Rt_EJ52~)pxuXJO_e`K6P4o%5P?ZgLm<Xz8FFCrybT6s|2QXX)`+Qjz8pwm_N9<%yfcXo#QZAKz4e}O}>&TIsa7QmDA=L19^ zKe1@B{n+-#Z^<3Vmn<}FjKZDE)1>8-OUlyR+38k;Dnwd^GAmj)h;su;I|+N@dPa{E zG_grzew?gJ?oSDQVsSu6gM&?3NVfK$T_>D?DFYl`yeqwQ1PHe*G{U)2?KRA`wR%=> zo-rx|Xz7d!vktiQ1%588N9J%u#WTI3xB{2-5{o3<*3Q!Gd7-6WCH%5L;L)#PNGprx6;=k&Mv;@MI4)<|>^>xkSG3>8%h3x7d-m z4R!^g8Rp^5xCW9Ie@bp+y1*7 zFF$8D!L@~2CX zd?cejgd@6e>rz}v#?J&?4R1-dj=E{*p#KeLUQS;#cNP?l_wHg8Ysn-qncWqJYpYPeNWU(f5if${&z-= zll616`_H~K+b9il9t&c!>$h#e1tlJVcQPOl)FBl}LIwg5JrlY57#7T+&NbL5+55oyXss z2w~`(Dm(Mf!0csu60hDy8TX4BJx{4v5^GC}Kq!L+tLMFCe)0Rxirx!(O%%C5Y+i!L zN7i~>_~^%LS3f^~{63<~n1-HXlTnXtl-=vUM+}7OCe{$z@TSh$}eGT$=kvYy>Vxx?A?ImcGMy4+1 z7PaeAn$S|{aEX|q6c3SbhM?Yhbe4F<-hzht-(!kvOYTtI*W8h<{~F0Qmgo`icOHIm zRef8P$S%kM{>rhDc@yl5QjyjT*dnwZ9p|y+dDMQ;JNP^*?@p4}dmMrfUhHVTOFVOi z#ioeGG!PH@WIlb+>wi>fWo5S-%gzY)+%}ZySwCwlbDU0<^X5;~@RQSt^27RJ{Dl1W zeN<`T4^ncg>^^;R;z-*ROlHXwi_A{VtTU?*jw~hr6S=9eF?E;sH6Wj!ah7vj=8gO` zN<~5!ei{!n5F&SWf~VxH&xcrmY!5079Mt1H=Dy7LZId@>U`%^3r~B|$uPcy8eX683 z2f^uMt@@QXP?IcP+=^g-O6)SWeydvb?WB}TdkJ6p}Faf=G$ND(NpXrRmE4KaPj2iI58E;yl&XWW46BD)#P!E`M#+AI$>;) zUQpB?s2b{W>gM*{YSl@!K(6Yl0Ppt3At~A)Dc4s9_N7zcG>%?9FMPzo%mIj80nUWxO1U*3oANg=gCAzrd<@(zY~@3o@# zDpb)f7qQlxE9@gw9Ix=oAJ=vj|X~=n+N!oLW0|m!*>d&s`HgnWe7{>>ye82@@8au2bCPH7SJ|km1NFpwx>g_B%GIz<1OH8txhYHh`f!_b z;{z%*dSmy}Xn96$`pA*COV6C0yFVv7dB1T|vb!$4pqQ5NW*+Si9kZlEIA;T0y9wNRsqseBfo;p36Mn`)#X;kC9x-`i#N1lpI&O=0cl zs&PAxhrBW;`SI&Cj`@lYG!YM_U32dR`>|RAzg6&d08unEkXmZktrl3Gl+w7D@Q_CP zih6|3wHxlWp5|KT%9g~(8MO(>yCZ$K?tdba*fZjJ6n7viFl*XL|SP0-sZ^Mo;He2qEz zc&d5exJk@s;{MHulagf238kNvxHl(sHZE-l3Lr^K;H!5M{SE81Hqa`-VYn)dall*YfJk6N?c<k>}HN0RrFb6?i-O0A+O(I&iQ?t z7W!<`)l!L3@Rrc10vZ1NuMD?|PsY8Z${Cw(##^9cu{srvhOZy+-91GnU52yUwLqOF zmDQVv^@>+w)Ps}JIFxxZt>3UsvhT1#N+!Y`dvdt@Ue1Rl0={PNT&+f{U5%7?Ra|

d+G#Qd{efl~_QER?|(r{8uSQC|v+y&nX?gQYnGBOETkF4cOF552Ae zk5%eSirzRNaH6Hr(BV>R_Rv-`wEhtDEg&6%t;D>oIFA{Sl6EG`^)8&+;hibgNhv2or!KRn=2H}&(8kB+{J59g}0F}g)Y zM{ij=M)I?i>9s!p=24z_`1nQqe$T)2)-&luk(HHR_dJfLO4^n)r&jmJHe_*Z18(Ig zfuP6VT+oOZI2<+@ypdY^H|$5L{WQrVmv06(TU8iqeuc)ei~G?zd48J4P7)gyig?Sd zzfQ8)n6+u1vRWap;H{;@>Av^Q=WIuT(8?0ygf}1l8;|K${fm>*+ru$V zN_r@#lQIRWQcwj&6Sj%_@kX`}z2`&ZraVNQU{qxj!6*#Zd^A6xi zF3(*r`eQ`zfJ;@6r{z$RZNrc5Do>Vb=&=dOIc~HN07hdMwcjrM)>~<24F22I?x2g$ zKe@Rb#Ym?UFS3-?|M8Bg3nx<)?ohV1j6Cvy-x>F)2Q!TfnDk`zO?c!3#8ZXQ~gQzF+!>PKII~DT9 z66|@{<2|s)XIq?=ROh$5i8D*tVpq=-aI04gJ=P?ajLAlqpT|gceWErcEr*&HZOh?S zEdOvRY@zIrr0scv{P9vv>Cv0=A77?9dut>VSFyjqQ-$EEm=+g!swlHW@M}YMz}I;C zqCBC(Aj)kKT#dgJeo^WZOKLj)ur>Quht7SFU%NLcBXexuRnEx;F+Fcw`bnr!x#07L z;4Z?v4>GZPAxhr9Vw_lzJGn|s&D7^QcN#&h-*%`fgRECuHajIro4Y=rSZMf3=QHc# z=@qA5pFcp0uhI@%`(jrM7(cO(^saqE{>=7rL}-{r6{?gkKAGhTDCfrXg66#gWLu-KlO7}d(G877hNrczDiLJ)hC-$Dd=s1nqMJDDeX<7uIc&84uT*&6 z0NcS!Ams8l*EbqSVl32BwnLkcuIdf2Li*ShPtJq231fYIc$qr!r;&-{1^D2v`=fJ% zb4Atf;5s^_0E2le4mruZDLnQ+0#O`~1Tl>;oAH%noA17fKY7pfZi_UwEBg|xJRTg2k002#cxZ=18?Xb(}h9AJWOb zkdLdESc(GA-$_s5jh#TEZ3sbi-hzIbT8BC) z%DUxT$+hmxS9FFw{Gh+QgY^x&)nv?s`N{g{!KdK_KR1`%S9jwX3qyD3rFP zG3l_4SY$`hNeg?|@tToM$xU20(KnN19Z`$u*`X);_O1~j|EQZ*iQI=o{;-qMHF>p1 zoAFr8y5I`-uBCtK_L&m=w|5=VgHo{`ifZeUcx2Rl3+A2*7tU#96k@NE2EyI0pMXJ& zPf89>ull}ee!O^vy%C_X&mVxAi#nt>C%-Uk-iMY6k(e`uh5$K={+S8G`%BRR2g%|N z1&LQ_1E_(7iHgLF$yl^hS7Ax@(2J`cU1axX4d!9V({21OIyhqh+w3XfT!GxkJC($q z;@fDrC+Yd77qq(c{Ivu6O9% z$KT_eUDTH|tbTiX0JYJxTj-lmYci&l6TYR{bW-y^HvWC8C4ZWp9JPn=4l8Rpy#L~w zU^I2YaLBacw4IGdE>AX3w9r<923Vn7oQ~AM-Kwf9QVmGYZU|u0r%4b_chJ4&Sn2q0 z`t;Y-y6*LDaogVSBs_fGVO?QB^b%&ygJ=z8YHxwd57igPAG#+*YbwL0v%{Dz)M_TbLMmjV?Sq7TBn z1SnJIAi?g@KkF;YbeUC_bGV{EnwK#8}R>ij^* zil>_zU<4)lo(HyB7sc(cVcnBIDlwJX4tLR=DUTP&u&Rq_N|?T71Jcn+KK z&jh_IXte>t`O}q{V!kLFGF^0u=WdM0YVV?q%#vEW5Hu78NG zg`UaAMy!3f=x^@3r#)PpWD4Vh0YhzrrWCUK1}CNMJJhNf9T>GxaktZMh*8$p%F}Z{ z^7ckJkq?32;G^^P$?S!R+Ak~kV0`s_+S`K$(o63(2(l;s9Nvzl?xl| z@#zpV3nXTyc`}dGCP}}4*gX?p5#SZxvd?GdB~zoDU)iE*IBHyzY>q zRNIEvGCA=?sy;%z8(?cD@F)Hae%-Na%S8Ud>+2_;f)(L?Mn&?duR2U6CM>5_AY|F@ zc9TuvI*4lWm}q8ieDFM7syH(==gmf-y2?A8QZkj!PQa%}(l4nip;om!-CXQ`3bpyr z9|EX)2qCG!ELtZdRev<{Byw7~1M{;IAU5B!HTe*=lga@t@P$Cs4VVKBGFMLnn&~e| zO4G@!|=&cEyCJ0$nAL#bB~rHftK9dyLo>5)+IQs{0D zvhC+c3H}i2Hm^=~{n@nth9G|>RpNGxJ#Yc!0_hQnhuh3os`+&u!JF+_n}Ma@IrFN+1)lG`r$OW;4K5vR(^{u7$;{qlzwEl>{rOC$p* zAGj0&>9k(?F+C1)^!qC`q%UR0QYL>BN7_FT3krgACJQ>6_o_Y0%v33pSc}|yS3k(# z|D=*XV2-mzhkI5lv>oQ$nLK@Xky=*|2Iq8)k(V9!skCsq^Q-zMf`FYP=2 zE0A8wd5Zyh=jkx8Ka@;L9VWPcK>(l$z5|f^zN-Rb^Bhc{hm(@J zXq5;iE%Tt~M7ZkwGJTjDj$(;=9&1V@xSNwn*UwH&(N!w6xBCHm!w1LL1@NR;OmM+L zg;Hlo`hzSVfZC$LHBhYK(}pA>49OSNc?~|iSUpRoyy7^(DB(Z1wUrwwGMLVIfoE4@}YtzOyIxE2fBmEu>g+Ock`nq5kV)9y)Qbz z-||82c6{G4>q$V#x-iI~hrQuWtuHkYK%bRq67Phak!X}F$?qh`ro0uy#;T7~^M0eN zAqe&GKHC0vgg@IEqU`^Fl5a-OOmtCYD2w}MgsK(&AuJ&mrKc_4nSEoTz3&fcR;+O) z78#MT9k%p325}un8Xp3V-X^?)ir)I?EIm#wfcQFJ&Ey2||MO^fAm}|}MI%&$PLjJa zPBanom43G6X*th-22APmzMv2N?A#TaGXzA&X@d}KuWcBzk+Jl$X3Buz?Y?aXA<}du z#>OX>j8NWMf_(G$^X;+qkj3cm*WYS9%YWNa<_$J8a_?L(8+Ye!x?1RD;JI{l9Rs-~ z^imjU=-;@a2eh-kBRj5arCFCSYbmp>^G%9I-OvjejZs5gH~jwMf~&z`dX7W;W#$o# zWY^<75!}j^Wc!O@?IRGSynWcABcq9wH5LsVp)UeW`3IyKhcJy$Ms`?HN9=$KVZtWv zs9KOIneuki!H~F4p;sJRc04R3heo>?0Ql(Li#Il$IGh%#(i{V0nD6&eNNb0Euw-lPoOCQ5##K! z7lr7#3|mgVV^eb93#{juYscMF5PJWS{<#ltJywMOR>-Dp1L~PD_M09^k*PSZV9b`s z#zF|h6YDsjJWEt2!^n%x5Pl*YI~vuc_R^NhHwf zEl4xME3y%>!AT0nEfe%)v0sK{dd7g*(kaqyTN%}hLw-5t{hSDMtq;Ak7Z~kMh8^H* zn5t4R`IK10Kc~k$i2t~LT}eTWwSUO>j?9w8qv1+St=Vtn-;ikM&ptLq`5tkulNNE7 zd^FFn%>)0ANZMl~ zDzgFgHP^MLiY`oWZ(*nS;A=L|HM4Ph`ZfcJaz2W5+W~BQ%!d~_@sWM#i?Xxin`(b{ zf13Dh3$vKE1a201N_l%*tY||mF~965Z$Np{8~0WOyq>Z3xUafWo_DZHzLxELP2VzyYqwnx`u@Y1ICX_OIq%Ee>AR&eiaWO0DXqKqI2MmuC3QYL% z_||~&sw-f>xaY30X?sI*-cWu-=4@cb&|l)ejk9m$ZW$}>*SU0%doZD+SyU5f9s~(h zY;9FEM$$9IQE|56X61V*Km{WN_Z;>OZ*jb@QCk2$SUQNi)f~#UY=WRGiYQ%QLv-gK z7S_}tF7&RwzK5RsL|bwo`B};IUZX|G&wXSk5&G@1w=Wd< zkL&3YWC0evTUZ{ywD~|CF@NAP!Tmm)wt4@>{#h`L8<0!2<}+N`V)*qba-13<$#Q{8 zOw{ZK<`wn^bmx&`1#f(2BzI?@sl&r2%x`qNQJcAe+)6y{0AXx1K3IJYn|1KrZP#ol zQoaUj+B4+~tDoJh-n$lfg*FnqPHJOwqOouIq)YWQg810f`)7izy(4FJ?czKSiVY~0 z74oG+ztsQPr$lNqm3Qw$*!jT;G$SshH_~T`XPk*2S+#&)Es|-F)H9g}C3TN@Nx8d#$7!<7=$RW^pR5g0?hfQ6`+ZHg+H6ww) z3E1F6KIEkghF>_pJpf1GMrKlIH?p=}q7CdO{N#xhfV{b<1T-i4{sSgjC?+RjYfunL zS_F@1+qIkB@9w%7XBRFC5b=rXyb1F|pA6=le9&>u_EvUeV^=K5M%dxa5yG8U8$kj- z$d9%5S>DIvZzh?m{Ms4BH)qX!K+o}g4V;e|0Em+JkBIrFXAMIY*gW`eCEcVIcAw=g zclF2X&9tTcozBfFMGd^CC-*WsmirL=u8$Ugel^gznGed2yLJ-Z6)uPG6Ezrp!BbyI zbTiS}vJ|!8AcdDQYK!yIIKG}c<)ZJb#QTEme)k+IRzq?nGL~dE-&MMEoxaaiK!WY? z<{?;i-WkWtsrVadVeLPk^sah-Iz?Bas1e3$X-j6L8Bx5o?hX--ZmSWHF>8FVYS8{p z**8`6BM-=6?;c)SB3uXB2f<{!40j)%=Bh5sq&09`iKe|de9v~mJIU3*A1QUJ zEb60jFX{`6k?qLzS1&p)Z<*anPp7o-HfAnt1cr(x){rV-&&k%9#fx`mpXvT}*#{py zN?YRUw4D6PQ|gn0xJvf(^~Y18pJE6{U-Yi}6&1OVGG4ny_u%jA>?E#Gs=l3(;9-xo zP3z9~--s%Z&*^BET>@q_cYt^4Aaq|P&@>eZKND#Pq?wJ{csE-XeawZD0VyM0rCujI zvSrRr=RNd&jX-${-9gJ0rDreGeM$;$6V?q#q*)`>Pe#d~DCuhR6B>UJ#&Xra>P2js zivYGq(m(nOZu%{~>qW5oKaK`JB(ru60CU-MPn<&!%t zqGM%5;n5qfyOSmKN=m!gci&?vf2aYW*qjrWzEG+$c{G{|`urIvq&RkU4YOs;7EwYx zOAVfWd5>|m@ctl?85ss5M{X1M;?1wSjhjlf^{N_(+1klRN0HhT)$RTAu-W=iP8*!` zqMRU|R@EV%KU8m=mM-;!SHz88JbV-RT>OVT@Wb>iaB zFJ2nisDOAHTs*S-TRmk$X6fLb@5qg&7wxu`KJV7>{^I3P&yS}?+|;tf@7AGaP3KM5 zexR-|7C9SlK_Y{5e&^#)jKHSZ!{hjVvky)va55;+ME%SG;1Dg2|7$nNhS zG9!C6^@2${DHAOAeM)=x?MKcNz$J8tSBZqr1kmFsK$ab*yJRj`jv=LXhHciAIv_i= zT8VCMt^CoVfTzzK(it{NvpeqLL2AY>d5~YD{9c7z>XaX|WB%&?#Oo#-G(GuAI%`zv z-O2IOW_Rt=6v!#yBO!aRm(a?!;!8HQxP$Z4jq>^x_HDz@Q9G;|T+!r6YP+m@|Eqm} z^W~2%+QW%M&$Z}?e5HKp8(dNQEIwFaPJp?nuHU87*|Gfkmr9cP*Z1x}BKFPEx=%li z7pvq*ubd>1`4)Ogk0|N&MfPF>G6<2JRd3y@H&S*{6^h+39sRppJcw zdc#QVjH0o_;mqYbG?+Xx$rh{G*(r4{rnd?*_IPY;7-F<`eS-auR^K+O%VKXj#oG|$ z`M+3ikScvyO)bK?*BwtQPH*2v$VD{+Q1{QAIuh_{29R2vMyIW7m&C$f4JE5t8yFuP-jD&c7PG{VjopMaOYT+17~? z!M-4rbM4f;htg@8*CFh)!nVk4c^jV$d{m73+weMXo--3C>5G-x#n*BMpB)3$OPXjD zJ7E7|Rg=)V5ie!ae#M%k!@DH=RJ*lqvH$Ds3wvF(PWT_ls`Puv`>;&wnWryvR?u?* zxWHiW6rYIuwJW(SFh9AV0OcuROiq3bnSJJbUkr~J-A{dRl5AQ4OmImb-XJ}*9j#;+ zE_i{H0uqGm$TtVLN1>Pz$~1aCkJgcOeHsEx+-_+XnSF*6s6Z6s3gq5NW&KSYud;S^ zBCD{~S*?};0Q&}^%np02*GVbh6R}&RO61dh$vHtc3+CT6O=W`KCIoLmqcH^24BJ`= zV@-6bx>BQ1rvC3~pau4!#Cx-uP~;DZYXrhfu!aH>8vS^Pg7Lym%i30m$46*U&{KUVgM zRitQNava1}9s!U7AV2v{6@Sw#;=sNyMKP$5_xM;xzo_2-)+^W%W-_cQj>`h;BB)cGSp8w!buJ@&BSBja7dgBucCDeYr2P*~ zR`t50`byQ|m?PxNuu{8R(9Nn29W6qu!8}*RTTiU#L}DLa?P{g~LKr(wm#TCu9T=t{ z*fm{35;j&)npgT}X5B*x)xrEh!Fsv7d*%+gVcoRd`ZOGgOcikN6C^Nif>5snyih<$ z&aM5}`mdAU!Y{8Z+$4+%GQ+ag{rBceXf&hh1?wg2qt3RL5#0B!f?s#zty>QLjvu1YROp@nmeecM0_9JFvNUWP4LxDNdYnWlai zYlFS=xGqRO+)y|AM}%CE0V!K>1-B$$=Wp)JKeS;eBlBRghO2nYZIk)X;O=&!x=PAz zf!jv+`5xf!ew(b32(n1h#UmyZS%}H&^mE4E0b>?nsWn+k)|ey-MXP(yd&=_aZ@$=XD3uD<+;_%Aj7EU($6(o1x!)y@}@a1 zruQ?rb;;O)uhIs4%UaKD-rS=+c}br>Mx3-6+Ip*ha{AKjYAQeb@J0-+R69b$xHw{Gpj=t!EwX zb+7yW-M@RS!G)4Wkm{8ek?O{~!=GL!)&hNCU~{9h{s(i8fHy0JIQ}M6Ug^Qj&c( z4b>)uT<(r_KL%&e6w^Igj6hSa0+fJmOn#sg195B)qymp#Pd#RW+1~}7x3;F?VOTNF`_u=-wi(ot3<$90{{tPXxg2W$y_nAT&gFMKr>%kl1bar zatP?4Gsfis2`{mM8UxXL29jeK6Uj@p%$OV(G3#?Fs~Q5uXZw!v`%12T7&507<-dYf zYGbV&+)R(nwO+F%2;grGPD0p9LfGIDAsFOV$l>WH`S z6??Pqf=DiTx1o8;F2ig=w{Uw@-W!ZX1ncHNp~AN-P~!(>3_2o7Z}TIbc%`236?=q! z#E3}OV9nor!jFaw$?O7;oK=!c{%|D2{urN%E4sfWD#n-$Q0d20_c0H!{s3?T=D;z@ zH{nWP(B1B&%d;&Hjy&q5xF(O58wYGSc|6v3M+*S0Imd~1Iv4nGjfsBfHb!FctgNT} z6wKRF=jK_jaZi>?I8V+3&MaEhMbU>!k4Qs7Jiofpzd>k%e9J_1=jamg2GI~KpPV;7 z;y1uci2@A;h+q=TERjk?tnL6U?a?>hn``s0`HE-r3jE)yEOjmb32W|%*Z8Ui2>p{ANKIK2afxi~<=o^Y+HCOtIOWC7^-LOULSi@vRX16`c!s&Up7~xwL zBC9u9nz8xADDll7lKdJEX# zD;_1joyso?#<&KHp{w9;R3|(1d?ZfdA$FW0T+BRBEW3FY`SAEtP zzG=Ot1*?|y>c;}C;(-bAM< zQ&nX&MxxTEHgwPh{j_RRTK5WG7~sZFOnKGKTuw$!Xq#OdV-rRqaGnX17`8yd=MRT7 z;^`rMo(%Ae7PW(dsmG&(L{TsASc56Z@Y*(B%EHCucEYN*!{z&hF{01tU}49pfHVZP z#0!vf=E>%B72)8Vq#`%!rxmOCu}^%2*_7 z=O!S*JT*ytLM{K9^78Oj zQ2WtKV!Z>^0QOzriI^C3)#45xTtqg*mwUIEUnxI}Hevyrot|`>0u|$g!kI(?Kj_J} z1}>Lgpg11N^k}(EvsP#N(DiqcY8Rl!au_tMy z?;x4`KA+>YV~G>6!kP`3KhSysdZBEEBflAFv@^Y%P^QJbRN|NsNxI=dFR#xo_d`s` zW=fe;hD%D;-M@>IrSQSHdx9I*mQ-|1>HoF!sQX_ao8=1B1whi#sPVyAK|+|}Hf)B8 z*_M8`IP3_^Mq>?Hrfc;?Kvp9*G&&zCF{h3Ox#14k&F4o3oLh+e+e>#yF$g8-{;gW=j# zv=Jv%Se6&O)ei8sBe1!OozkIj12tgLis5)b1Og6(}XGyMfeSFZgnCYQ; zyI|Tk!L;Awr)QyA%KErrZi(a1pOtxkpo6{qh|^(5mP=1lT<@lPgFIMGXZq6*h8$u8 zn9kG^ot>wn3yBTDSUMiOOmIO*{{oupT9wD|2HO!^+xfW;A@c@ZI1jUs`HA7suY(U^ z@g?!8cH}H#m%UWOJK&NX(d-F7V|iUtWg5oLQf^!2ydwM@Zk3<7nk+5pIB!_Zw|k+N z_4!50590*^b|K1zi=J=2zJz@j52|vYVBhf{$fF!|6|od|&UGM0WWCgNEmAW&~9zGwkTYeo2X;9AI>RrU~mf5K`Z}-SaYr)0L;kwXc zt;r#U8agF>>J$hz>}MoieJczo^c~FQmz7vMB&`<2e*utCjL1bo{xrA+ z!9}@T(dWR~g(=hYtS= zj@M_PGiIDZwf)2wz`C|o^>p>fF)y9Nv${PLKxh&QAPBq(rv4KvbSogMLr$tNm zCsH<65sR)wFPE5SsYO(M^!libdxI;*`)Qlxds)J^EMR?$(j3% zd$q)Igwzfx6gvelbCOVpm0!RRwIwD+asoR#8c}eT+n^l?Wk^$cR z{ei_tJpz*drs8A{^tW3sWILURuOfyhMG|%{d0x|%p&D~qyiRtyU>{|rrn$1rQ8b@- zymF=2fDm0--)WUr&A1%pX)+b?A^*3%!!vewzE3vLvip-r$*E`Bj|GDMI>qhVUdFOz5@Ru-m5yjoa+u`;!Nz-f2PgX>$ z=~h3IU5b*yK1l>*-LbtwkzNUt-|#?!+wPz3bZ?JzfKOmFYbJ8T# zIa`;V&8}b>(8aGRZ8!wYUYw|cl6%9yvSmtFIvNKCMMCGJdVo>R$2W1_97pus)9Wn# zUZi_|ZQxVyT04x)(iAGjy0z4#0{fx;9~#I>qE$5o^f47g17A*f;L`1-={?gCkt_O1 ze972}1YvrmeGy-TYvFKQp+Y1t(D?DYrNM`cLVf7ZO}lH(B*r_w2(q=&Z7Q_#%L`UW zCVoqyukSg}=f8#^LCw6!r2(`brH`_FOI4akGB?bquJbLN`SU}@Wk&~B1G~UJ=G2ON zM*g0`m+xiDwuoNvsRb5}Ymw=i-ijEG`cS}YSuVW>yTY~y_K)a1DZ8EEf_qtD%GuzG zvm?e5^u&R40pV53;^Eh@qf$H|(PF-4m`DI{ht>sMGaU;04rgF+8*bFc)v zf;yEsUGU?J$i7a2GoqNB8|{pYx`~?jWn2r)bv#0}t0l$9I|mfv4^0uAW*uM+5dvK! zop~`LAJQ>XWtqjKV;OPB z1DHm8H;R0D8v|&@ou#Vm9-J~=Y~BEbXE&ur6+zR-LE(IM93GjL8?9fwE1;g~rJnxq zJ<%5VvNGkWll`z77E@Jh$9sGoF@cm*&6`ti%oa$WDdXXmA>6>8gD%7p6)R<{z=SH4 zHwYq}W$Z)*5iU-3=)rMK1QMYI<$ZXG*w0s`8Dc5x0j_;nuT_S4U9gME7Qd5) z%vWh*FXW@g(l1=?P}kj?y;@ERa-#p%N^2={HTqWUu3eWRlpS*Isd3^H z=S}dPX-Y}LmAn*I2>!tr#oNJPJw7%uvcT!DCU3bb85I6mrR2M(I&wwgv@+A?KC2~U zGqbMLv?WH}&eBpx?Z*7G{crihp)e;-)iX6ak?=PX;r#&G=mXUoH8Tu))PA>4G`oZ2 z&gD+!>T&lbq^OR{wsBgum-Vff>XZtI0fnx4(>l}=z`T86u2|}f^m?)S{gaiw`fh66 zP`aTbIDMo+D|$8g_uG=N>W^)noVNBNVxiYxZGR?R+z8}_(KqwSAsJ0}T*?BYy(>6K z&jW#fCM$#xv|gHX=-oadr|141_8qN3u99FtbU9^*e`cuJ#aBUIGB?@C`9x~4z71S_ z1R2e^!rZ}cW%Puq9Tb=PB3$8@mg^mf@epX)9)HZ$%qE@w!yl^46p|H^aj}^wQYfh5 z0xr-7J;q1n4#v96Z0>~K-uG?*X(*uxqh5;t=(*CcYk0_C18_dU(r@=~eKcs@Bt3ld zCZs?Pts=dG+EoR2hwH3q^Oz{6y0?S zj;yc-gaMOiPx~PI@OAu1-U#<|PFYf7YO2`&%+LOXk%OerHK3#F5y-DmT58m-kS^?_ z=`P=_>?c;0)0V(2ENMs^#qdO@+ow^`L33@s(TnfhS$Wqh>E2%|(Ve$t3CzG-vH<1{ zS^jjV@TqSbD7mXWpB^yD89pX%>I`S8Qcb~kbN&t4J*UDJcSugq1n!oyJgEm%gz@Zz zcm(%6XD+L|G@NyPd7ZW~xJzLFUD;w*6<>Ru?)N27Nz;^l=7izcq9-j)<)esYfii>Qa)F91eJj67)zD-8Q#vw@5> z9ceH%jb2ax2Fzml`^qIpv4Mk6{yNytn|^(#Hl+9I2GIH8%Qm>kMgB)>ec@evNeR|Y3U@=k^JLiwqPS zKHDHx#nl*gJSHE;u%lvA1S=$Iz)#Eo(;NGrI^@KTeVt10pg__P5ENC-W1 z=l}4%r$Wrd@dacEhN!%Dr`l)CaLiX5tLD`AYSxiBC>BS+>O=xQ%2QUcBE{I*Xn=9b zi+_K-vdn}ml*ixThshyuFZU*70nrbu#7TW(JdIm^yTEGszU1~#cJ@ z6o2v^xDdeH$E6618;sB7CqT}Rjn8}W-pN-S|GY)yJn`nr$*0vDop{wi4#yM%$bV|_ z`|l+_1&L5J+H0as5dIn$xr%UeNin}H$J$=rt?Sf@*5>TFmrieLZyr}K6!P~XVTzJ^ z{_wu>$~Y^(7vW+>&Oj0Qm5h{ClVwH*v_-vW^e+=-0DG5DSZYq}DiYI^o=F=Y_{S9! zgOdLsR)uOo78Z>UR~ulRV`b`HlyR%*;XxG*75qTy_-~0sW$8${N0^#v#j(0 zr}UoKoGL8*9v)F_P#=@J+6@WuhlnABNTS6LNobij&VbLKKd!!OBLKk|dn^NiOeunp zNK>Igg7_c)LBaTPxC55#l7~5!@JwCh#4z`-u@9QkrAF0eF21q(K+VZ?#V%skY4qIA zD!GK@e3IvfW7QrsF?xy1v=8qP&SZUN?^tr7n-@*V9n=GSdA8i1NX^lhXaVAMUt2SZ z5Q)=QrK&Y)a4mn#o!7otWC@2*UqT0SkBnVITfb*QKmtw~?Inruyb-o3OW>Gt2p>g! z$@y^ZylT2jxO1Zc>t`TM+WB5JdnR9j-R z`CzDu1gR2=fLV!Mq=|xsru1Hz-MvR6{O;}n|5nOkm(y(S+HM?!GwkSaGV#fGpgSp(I>7=>% z19A%!tN(r^~27`HlAv>I-jr?DXfd{>7;QV+|JJ{CyBH3xO3|LP`Z`~123G9ZMBV+6mZ0$wE(1G)`~=8N*={|1_vf+HliR-wEWaK&sPf9XcuDf-x-;EJYu^mZE(+EnKP;WJAYfl!ZS^G-}=!?ulmtQ&8Y&~kv4&5msbxT zYzS>q4KA(=n9Eb$u{?EyrsS}F^#_6FezCX>woB7l_p4s=1@rSn?K(3@?&zd7nhqRC zWbS`CsQ!Z^EP?-vKzjx8gpkqEB?qIhc4w~{E213XZgc0_h{C735#IG*BdO1y7toe% zrcQq?C<%RIS$sBVawzi1YGvaK%~V3y^n(L$J;+#>F6%Od?19mp(R^ky-J`$swe{Sb z21qgEKYmIT@^F$ezBqhz7qn}A=9O2K+=KXcVB-W_j@qy&A0^!4Ed3igqz&TSUVpxk zTDz|LyVLSVeUcVS)FWyPP`*16udJt+6UT_)6S?n3+{bG<>a#fdCWzO|AW1qtAxuR-PTF8bob`UU+P-+JY)WbkZ~CF$9f+C> zb?iSR8><`}sZmo>yKkCGl(90{`-K`K&F)9ngI~=XZqAZR!&}-0iXQc&yMOKWMo-QN z%Nshq%OlVs3Xv&v8`@9Z)Im5mf=P{vj?LJ}f0ggfexFg9+;VZ&4Y-wy8F3$mlT_X? zrpPSw0P){?=OB3|soI@2euAq#9=!()SXOkOGw}$n@k!i~TQnO52NW@-{yu;{J3_|T z>vHBi6w>8fePrOW*2CkqbMA&GsR_JwVB3UzC z-7OZc9cTE8B54pOz3M{;7VGd)Z#>@w!Sm#Hdu5DV-DFcmk*xX=$9S=#Nyg}2%hP?0 zU46+686X3J6Q-AcX?#s^`umJ-r`j&Z1B;hQ0Ot9;E-HU@Vb9_GKC0<}7LrksJGAY3 z=h*7$OPvkn_oAZ6J$k`EMyp3K2Hc9T`_59fFX(Sm;3R=gkcj4fDh*q=3hIJz$fbRY%osx_iRF*je&dja&4X@oNcSk!|TJ1obb@T7*^H^NVI>u7jvBr9dNs zV@k{+Zf!f~Krz(1Zru~cT{Y*H^iK~_W6Jx#S(lmp>c#_Rr6_tj!9PA)({G`|D1k8a zN>Itmf8;1cF~XCM=Xgy?y=zr9=#1(#*QdBKqv9@sa0F*%KQLT2VNyi^c$x{lMpA3n zme>$mFkZr7t^7{_ID15vC0E4vO2H_+W=~z0hc64Q#|VnZNS8RDku*}Ufz$fGkFxRzOdOp(khhm>fs@_?xUtScrSu_ z%F}8JnfPXEyK=ger7GC`{T4NstKI%1Z&n;~yjX`C-?4UE;f)b8SE1W+HWj6sbkmk9 z^?_WlT12_aQvX^|K*kXWXb8CWB{e6%yrJeG?`ko!>{!75mtZ-I+nIy6ALRmKBBNss zv!b^zoNyTo%1%r_n6d6Gj!7T6s@0DPmje(Qx&-G{sP$d$^?tnYD5`KS#70@|P@MH= za206-^9Rv*ZPb#XpkY_KWCsENgKS;)v32*JAxZ}p{}l;x>a4Fw$K$-XHU3gNut{YGjzSYM?u-O z7ekA_2j~;YmO^mrVEXfsXsr|Ui*V;{*VK3y$bF#(+cy1yN3!(}+m6Q_SOm`b{gQDl z(Ds4F${%o;T}7iVCmZmd9V5!}bbfC!L?khYNV(E{V2oXGL_Ayzz1~Mxmu+f)k@4Dg zl6(uN4o+}+Z6GMP^yqTx%LMup_mNw``*n#I1q!>pyg2IAP%{9y%s1=+50;{T>>wcc zuhf`~PXFH=i~Er5!&$wfMvD5lK3*w<^w!(&F(q}>rfQ;&3a0ITv{h~6KAgmQ!lroY zD{^Z((1KfS*Wz)|Q2f&iWaBg`@H$C@OmJEhCjIO{b3yDuG0{i9R6mJPvK*+K#sMRA z=MGW%sW;Q`8Ty5Y+i@Z0S5VZWniy%hx#vKzVL&fEr^n+Ao8=ARj-6+aXg;p*KSnTC zCcsUzK{5p%HbDJjmAezli^i%mg@N?3<|R$QvLFyUa{yKN4LsOXk&>Jaaa;#YoTLq2 zbqCUib-)9XYIt{+GmYyh^SeMqCYUL|2b3|e07jtmrBuRkx%wCN?lIb8ySVQ%$&oan=uTO0NfCU-XcGb%QmeK(d z0@c!>&K>moBV4iv;B?LqPv8v(o0c%}&&g63WU0R}cW{pQ3fw){awSeB)Z$L*>9L(X zMkME@4~){d9RvpyT==i^iTq`X6YW@w4^ zn694wg}1;8I49A8j_eo|Dlf#v32UCCR$bvnqG_O*>rpp(I(dZ4>LpkhKRW{CbC7tb zy8{XRk+xR;kHY2|sYcyp{ zjfrQrgK=&_?1;qZ>FTYfWaI1)>9Mga(8~rASlAGq{P)$q#EXh3sqitM0cr@6KyfD@ z0;3Re=ia>HZTfc!SB=rgQlm)gcRT+B8&?^!1G z)5uk&G)%!j;Yvbu_Q}n+3Ps zRr4LLc&&v%`c)1rjsl$?HV7~tSKlJg8IGvXoP$kl-+j?BHM1;T?oU6%IF}- z&{3XP$;E1_2K6}E)U$#)i^`P(#aXHa-Cm06Qh8Z(VL^w8da={sQV}c?abF21?l@@m z@Tt9Gec1LG#z@mT`b|`^2RQXOZ(W3IBZf^Y2%wq7@Np^esFZely}rh0Hrnk^&&G<2 z63q6S;+3MJxk?18cc~r7J0Fz&E0~@(678}DsLeZFDq{oFZleyE%pQVzTc3te=U8>J z&BrA`!oXJ01@-sw9#(BwpXg|=N^O7*SG<#>P170s;w8d*gs|rGjw<|(dGk3dQYE{| znbY#THv!KI%$omzR~Z_xAZfm=q-$!zBzW6z6m*|Mvq^(YFdfRrp4s?@4jxmsC1te(nZSLLWaV52H!Ql zt*Ar9pI<@lHZ(xVCIkrAf%zi!^iDmZ4RoIL-(0d)?XP`2ApyigcW0JT8suxF-o!vc z+d0COd%pi&KJy42S=Q0h7t8U?{}rA$F!~jx?nL(K;kGA&Bx^J>nXe$uPE%e*Ztexm zkiZT66y&j2ES1ekV&LK7+AeRryG}5hY9&NC0>R8xKJBPXK@mxSu+i#m45hhat;|#< z`2Xh-E{}777)J`c`^T|O%)97EKR00 z2EF%+UD3UwKmL)I`VG>R1!v!Q8-vbzf)L@z0ef5@aBUo38_j<@Jwbi1D9$>;x1OJ) zq*mRFx{!8oEDccg!Ba_#_cf;zX9gXj<~T&nSMY(G;8H}5=AOu!`GfF*o4_qfCc&Td z*Rz~}3Y>^n8BkMr^>`{RWp;ZdNeq}Pfp1&f_q4}JqI@aymD-*+0Xd%m-vWY0#?!Nx zM#ypRSF6+m45ZXf+yN%cTNiZ?K7!K?M}q3hk7ovV^dQW=;58Gk_p>ReDs5b3tAXZ z7UZ7k>bQwj3ymXJcLTYE(eF!x=Xl2kWvfd<#7#e;OE!f|%z?#kjNGXKBdVkS#N4(B zkJ1*sv)5(DT}t1ZZRvA6Xisu__*TV@9snBUt-Y187kUoeed=oa;ufAA z0o&NsTBP9(zn!F}f?kiOAI!^vXj9zn6)wcu&h*SXm(8l8K(Kji;)w!P?+|FCj3STy zrCW82Dho_t2Jw>3xb>kb$dw8+7Xntp+(A_A7)0sWc!lv=}tyErnbKE$M#S zMT**$rf&Ee3inIXVuGkyCP)XSE;m|xE7MJK-m39e!}Q*6v8_DfO1<#2NV3h7#Z;zcOKe&?!o*Fj?bJe$!ROHOT9I`L6>&!QWOdlmntf2)nuJ zo#_5-*aF)KWidrh~MXjfdQ{*kYR++U-KI(sW`VoO#2Jg6@elQC(A0oo! zq}w7Lax&BLG{2mT(HT5l9!`6>z4@J`Hr!SZP7ojnJb;7*{$&dOwdIIc_WYg*!BK}7 z?i`@)_m;lu#X~?|xt~+?6^<0_6`QA|g0SA?J!G2#W)tM$GG;BxsWJv}88e*>Vllo! zWWdZ!j^0hRrLuz$INKww&#+bl-}9B}Wu}m!`|cHU#w_tIh>CD3#T4?)i9wEf=$aQt zIK)*5Aohfc4IMODpk2E3PUtw41CN*QdCDcCu{T+-C z+fEJ>HYe^#-Pw3RYVs2+lJ%EMznQBmFXV9rM3*%x1lCsCmq*(W4w59m11XiqDuZ*p zJqHG!Copf*-pm}S^BLt$)4C7w1fqI)vTJ;^B)%A1d95%%x#|$-k5Lxww6#I!7<9~i zW}S8+K3^JIoQ2cZ4_(1Gp6s4H8-?LqT?ri&$RlGx`n(K?IS`z}qg`c$y{muW+Q$iC zyzOLdGY1XCIq0=-aE%ei2B_zhI3EavnL@@_sZ%A1EDQ9wl5s5>h^M2?Xb#0uT-ZgBBlo$ zjN$1amgWI!vqW}%NcdDV*-hxPa99&ieM}PylkH%<_N_agj?(yWq%KcHse!XjlI8gR zvJSkkNbbSdbvgts{ssR_L!W?px8?vFl&&pN zX2#N{=(M3AGh@5L>5fU!;j5P_Ph*=W9t zOA$tIf_2x`^U49|_=O+DN>oQTex|}dZoDWxn^{9K$b)7lpeIE`f2T_)oU4*C$J z-%;TLA(}-`l)0`|@H@x@^K9qG%7rDRiG1)mQtH zTp)a9>>l?Xo?!xz-UH1aj53Lo& zsZl;RUgivpnxH8XPCLRUH`bPF5z4s_g3AJj3TL$hi?f;h;$chQyTFrBk=!5;P&C6@ zNYuyF#jI)M{$<)AgE$G5=on;oPBh5XIGh9r{<<&nkX93%;}+UiR1Z{c+M)yP1orA0 z(`6v_qt1W{DQY8f#7ntBE8kU{3mQXcLl9D)@yTgwBKZniu>Q%J?ES$PF|np9itmOe<2^OHW9>PXBlM;m zA%n1j{@7yvXKMS%(-0n&RUvI0;dkmOlcuIOGG>sEE45Jyq$hCzM02`Bgg3u*A&hF; z5uA3U&j#~Vy^n%VF=;&vqA4Fi95TXtK|{k%2oovReYE=qk0xr{boDCQ8SRrC3u0eWc4Z`o^+ zj(_JybPYd2bX_0_T$rA_o5gScV&Zkiv6T){IR$iSPX9ucdn{{iySRpR4pLC#ooo#t zKsVSVnQcj~=3rhT(8qcv@(pcUuqTNSHhH)NO=z~^v~Wp^Y6=bhE~fDddv>X-r9DYO z`#YU{cR&>1{iTLqIq%Ybk_#cps!DklvnAJb1vOoeuRHOIuOEP0`pR5JVi>VmFG}n8 zn;J}MMdLF&@7GJ*Sr1((dEf_j=s|F}^~5hNB3}gT!@Y&ym~TKE2BIN>M7`z-ZjFs< zu2x_vN&Eu9Wwqv|`~`i=N?DKvfo+k)&yaY_0c0Lo=%Huuk)bO)-U4Jd=Tw+v!?cJIT3ov*_- z`3<7=RXHeOMVBXLdNhMMNPE;2v@EtKS-t}UPIA`C)g0Ha3j#!D_6m7}5fK5FD$~i0 zBmsRAS+pew<)|VwGOFSz+K;tX& zNCC!726b)GocO9~J6k+!9xl=X%2OsBI`SSJ6-^rKUh)9)4!|RD}6s11UOu!tpxk*W*U#;K%7Z z>%z0QEPr{4kFFb;9F?D_ZOcHaOI>^Gfo}_S)acmhA?!V;TiEBmP|k#9eDL?u9ykzj7oeqW-i#);`Bjo8sQRNF=A~>FJ}@bU(k!Up49cRroFN14Oj?S3yhh zSvkLtaCwVt^(-7s4>@Q)?m894Bb z!<(&bh(b%D_teuC?S1ciJ_84xRDs*d(bcKZ7ed;s?(lvS`q6Jbq56Bs*9ztNFX0H~ zXTrKw`Z7OO(Z7vwAs%vC{ea?#=-6_fP<)Rb{x-aL@T)OZAL5z`ATbzVFIqk0nCoss z{{d=jj|LjhOx}O80$4$TUf4A=mGES5V}0i0tJ_N_zrSl*3hhpB2>F%FZ(kFg80c7b z!ee^mXO9MBj}46#Ci1g|xR!8sybCkMxFV5ckyLd6<=`mSwsh!i(Ii<<6vK0Bg+4bo{z87lFRM)6=aC0WxIfB^qM5pOYQ}cE*a_<_y1`wlgb6!F!w(`!k;iLTa z;CF%OklY|nu?a+-Bi}w!_j5-s$mO&e#ytn^E*a3FN(-|gUd>nnn7*P&`R7>PALOH&@kcR2e?+Tpapi*)gEYR!T~$>TpZT>e&ZySFL~=tzHPb zsD|sQspJb;<3lDlAIv-4$b0(Ru@DcmYhbf=_VVp=w6`lm$9E7qxqa{{G>EfT`EHai z!Rx-1+d9GeR?r4=GxHj@l4*ef1NWZfrfYKa0f7tJlMs6w+Z9RQ*3?gAYVm4Rw>y7$ zbnIhVndu``Xi~?Z>bGJW&9QXl!P%VggdN^(`!-{i!=}AsNXQErn;i`&J3bAzzYSRZ zoQoNcO6_-0>p4otv{}d7*kwL14T67{*D0IkxR-4!bg&PEx<*w;qxHNEy|!cRx)KqU znyUF*84;(0Yn;+ofQT0L{Mjmv=Qw&vHA7iY9_a6130oY%nsK4MgvgzN5Q`=rvlQW{+9MI%tERD1dL* zfeRYDGk<1vg9F8|Y1L$-!oGL&w5k4h^2%L%2-H1)TzQa0=QYY!+HmA+ z{f@imO=)LZq$H84!MUZ^@ybg}MVS^>NWH>wWqLoV^iW6SF{lPhZKqgJ&bj5BRs-5# zzl-)MWl=DC!oQ|=Eqm!O^opzU4%HC0U@9(efY7P@o93!=T ziDh0rTT}a8aF`Z4{I=c4cQQ1{sr*%(Y~}S_hcX!pzfa!5;><^Vll08Qs>h(nj{Of(-8i7Kys2dG*+sPs8^l`$=)tq1joV z;jcRCICYLKvnO8&B!wg3#uh%l(@$EJ7Kcs;(cFRpW(zp=f@d~iogHBIL!vhN)VI_o z;NTvk zRxo<|mX@!)Ctf`U(6N2v(fE;C`Qg)Dqr3MOz7UdcXz#SE<0*NyQPk~2oGk0pM6lMk z>%xOCc$7~s{k-E?>GZkdff=>v?fEm@rwe7K0&u6#JU)qXgUKeSKFo6oE4NvV4C z%U%5Jvv?&OYcSClv7cPNmd8Q^D)RHw_7I=^vmcFuddFsyMa8s3JU#OS2P!y{#e{dx zPn!z$H%!?0)(*MCG*!_U{QCS#a>x!*k_Y6!P7WaRuMg9^XDJFEQ4KC4#us#bd+0R{pxSrJO zP~!~+(YLcMXJz&1QK}wA-L^CZk&9^5nL$dh&YZr?^p3oW!souA`A496!;ftv$~%)ku+~@gFFiNyKcn8)D*9-g-QH)mcFREUv`n9GT+rRUZ>Ia6%h?18I}txb zRVg(DAuY-L4d+JR9_N_r-}H}4;}1dpc@hvR$>P`*8T?EC9MJk86yjI#gV3ut%BiEV zhnFaO$>wH-;*m+H2XEuI&@U-@+(la;pU1S~5(tc2<#N^;ILrH=j__ToGZZ*(-^Vtb6Dow02bvqa#&^R~tNw9ki`nV~hWLOKd)|jJtyC{?SlH}{*R`tp zVIEtXmF2eR(eY_wsr=MbQ2$vQqDl9_I>N^8?gH3&gVZ?x9fN3^RoyiEazrQ>9Yp-3 z4pAC8vUBW;5H>#lUcJtH;PcuRUb&$pzX$>Fb1!}kZOD-wU7TRzU=HgavTcJf)UJV& z8qV7W(~>ZW5^ZMJpYt*WQrBooZSc~Y-RAM3>9B>=Uj z1$=fZ3R+m4lWh|O4nj~80vY2SKqDA&4p_SqZOW^M#=1{%O);AjSO409bn}|^A?(Zr z_|VgS*E6`m@WB|pBjLRMr*YlrNKPcg@z1_tE)kUc$zd&AKK^%AV9t(?%Rsf~s5EL% zT3E(z(5f?5f;(w_QrelHnh3K5vaX*{)d&)#a?vd*OF+Ix^LSA)+pzuxX1GfqT2@v= zLJ0vhm&l0Zi}n2W61E14;FBQl+y?hGfqvXDK8CaHI^#y#?<}(gD~SW*LIylhe+Dh*=OJlnFur?SBL!NLs9Y~@rl1- z5S_tSpp|&TQoFuTdXQg3gr(yb?RtXVM=g`(pyrM7T8@i8cJE6rvY*wrOEvp;s~GB2Y;+O_FF+C4OykJE<}Mo>0W_2 za*Ja%V9#&Fqlbl%XV7VJTU`&&a_nIpLHHY9bjyU_Vy zra)h%Vdpku2(Xxb@qta&`{csw`5*>ci9Ay^qT5+f zqYX>Lee3UYo%xJOMWCe>Foi52J zGzXGaNbv$dSQv*ab1pc;Fl-G|jV`lqyJ7*U4c~wduLXZ!N3hU?of_UGm@|IG#ymKx z`Sm?j_rWn-^?DU{)(J?6wyNpIz0>pE^?3jqvpbpF=!MjxQY$;o9-K3_VfBLlbDLXX z+$F)FmL;wQSV=LLS=g(#FAp|HGF(<%a4!NaEP0F*bj6q0L)JDk+ba9;4t#Lc(y!V&trzp zPunrS@TQ!6c)q7{WaUGgthLRt?fjtd)>2hFX#IrYnM?3F+SEN;D;Gj{7tQav`GLw$ zSr6-0n@l@P#=H$!U*L5?x`BXw0bou|u^?qL#o3}jXnH#xI4an~tJ4L#?Dgbqbd6b( zYJ)%+v$_n%p)Z^`gw$gjQf4VCm z>{b=!CAQASEIcKgpQYoQzaNQjx20Zz#m(mr4)Y$GoO!o_x&e%-)J&dPOZ`Y~xZ!>9 z+g}O%a|iR$j{jJREHOOaST{d{kC6$ z6~N}VW|w+pPMnZMQa}PPYoQYSR3OoECrD*P_jKu^-wLeY>a7?U4ed(F2t=D}oC_pl z(TmAYDmcPwYIpMQz!x_UD*&R@Az2P`$^n19P{K~b0TchVqe(RXoqkbGJTvGXQPxpp zW_SZNo$T#;-SCTAMEi{{@+9mjpS}<#oogO?aKja|)yo>Zy}KV~KV`6yUVX==20$Xc zMJcx*CQRB`$!m;}CfKr=I|(kIcM_T$jbtQ>5qr7c1%=b-n8mXs$enAo!hGBHvUwS*HQ2q8qZ#j1``*kOHb_3Q7b=eiMxq+sg5= z%^sdSh>xM=zPpI{#+v@ z>eu??dpMNWl*hWhLJ9?A`Y7A0=R7r)RW;Pm4FdVC))9FT?f?T{D6;dip!Sr<%U=bn zzC8^XJGU8Bdd!4K1`#vn(Om3Ef2&-#A(#*6(4|hQ%1ecc$_?9xQO87Ci6<6(Z4nc& zPbJy}5Ur<NbgoNhHD}lQxIe+w@wp!?Q6Bv%?o0I6bojUpj znM|Iv1l12cusq#6Y>2j*;jq(&mb;K$5$}< zF+^()q*TnR39_BkSCwdA`6>F zxBk)t!T0`4@Q+iWEfJBZ$(aZw zM=z52#g)KRv+x0n|I!dQM7JdOv?XBM>L7O3@`wJZcA7AuGR_5dqoN zFSEj9sg3wSKwgF*WYy~U5O?sSRyC^n)=K7?UOiFQfHeHypJYB59R*LTZh`D54t&h+ z5cvc4j zXSfjaEM4ZYZ0CH9P{PZZH8?UZc^#l2c z1)_O~ULX<9iz55NvjkW`A%6@XeoJfRW-zLK6vSHAk452ht@ zGC^X@PoS^C)M$Q4hiEt_?uG3oL&Wgco2J!Wb~5YXHKX+7((xDm(4jQZZhA(9;PX> z@AT%>{EJ1n2JUdwfl^UHZ~r4`Jdjc^_70m;1h}R$z7~ox6XI2A?;INQg&xI5w~9?& zIAjbAVb3{p5ybDqOlBONaUa^R=}S)B%JB-ykZ0bt(&&S)e*<^hBal;zt_gCo_90LY z+kiTav%&fbE)peyeuftV$Ok!9zm=uIkCG_}rxW(|wNrPn!MH(e0}f5oX=!u`1Hpe0 zn+!~*l(0o?mDfN@Bk}D61;9$1|l1mH#DYDad(-j=FMqA(XJd7jbT#Fd^w8$6$UPs(M{gMs5Ot zLc`%9Dk_0eg)L?meXM#qU=!1VzMB5};i8ja-p>DgVySYs?EokJA;fIh%aBG|%YVbZ z2Q$ge5KG##p2VY3_!__Mw<>+vX#-3ZP+9*u=5od|ukErvALlEAi2%#hEt* z9{(Q2{UMiox*&1PeUXK;*b)Oj6YVA8kQO*Wrel+sC(15<7^p4xQ0ggBzgTN*N;>`8 z;Z?CLRm39h-M`Wg$W-v5_Qv(AL*zKa=xtf zr0r}-E1cnTI9IxGW%cV1z&tq6of!V8#Kt2i z98~?d{7y~wYHs}!L?=+|P=CE33VTq0iiZ_NbHB0w>CT_PzbuaPQfo2|V`uu)(Wp?> z#teWbwy*xY)KGfJ@CbnRwdz*)L=IBf`g=CV2(aR_*;bE{GXc< znva<0z^YeFFZk;|Ya`0v*Q=>NalP8{eLoRb6a?Z`ER|UCbQi1Pu}Sm5(}0O`v|I3T+op#EF@O7kQUIQDFbvEnbCJ zF8p*9;}9RvhGz}l^pry~%N3f3{ce7mu732S<31}XWkB6}VYr#YrZgVk;CgiE@6b%sHCBs^2ER8%_H< z^JcVCgVRLX?1OfQz3UULZa36BemTsC-REet!YT)DhkHmsgZE}J_;P@=DL~%l?=x<> znbpnqbM#iuRe$T{?v4EPwW-xwP3bF5d1KpyqZ5e1PYO^H%lnT->XM)c(t#+-|hmg!W$yBawFg8kP}IzW6y_;`ZWna>0_@ z$CEKO!%2O6kcGw_262Y)Jj5z}S#MsAf?$pEITq$+)x^LKmtmU!8^dL9GsDrp=rQ%s z2%D@w=nxodE{YAp&ZddH?kfzAoRz5JHMCEb3u|%8|Fudsb9~hCE&Ebu*uufKpYzxs z2AxNyG&Wh88hR)-4?ni<59r-#=CIm!wz@oc$Hx?51*A4#M;$sL)N+43SW&sCST)DFzOt#t|0j(A+hX%^04=qTLpiQF!h zV?f_Q|3(}7Nwcz%l+EnHrA9NZ#s;KBE4L|r)-c7SY_VJ`n;ErrXY{weFo&QA0X?)K z>%;9jH?3?BmtLZI?{F@qhb9zf1rq9c{!$$lb4POa$64ZKGbgq>-P|e0SG~;L;zse< zGa*EGjj(zFPYMao*H~KJF!#j7+^<$(ZK^-6optPJ5nIB;@E$S`g(oxyX;qbvUVT&g zck8Mm*8Bro$Y0FE^ihG}_O~6a)EG)JUi-D`V0XKG5MA%W+uHmvZTh|hBw*3yzTkT+ z3C!fG@)j3(G^qpb-+aBhh*v)jO_XsF&T~Zrfi0PHiePi!GUP>Jb zjp5HeYW&b-ck@`OFlN}if8Y0(r0KLb+kpSeb>XW+PG#Pz#6;tsk+)c+*4FfN6R5$I zVyw2)Z60lSb@NQ+yRaS19GXAIsoYUA7~_t~#%6y>D&}Q$D8g7h@atLE4Kd@d2lo}5`cl=oq9zqqcC##eZO1QcwH^$`H4pfbj%zNqags3MQo{?`^n?eUVhtP0 zTk!I$Luk8UV`5)w+iO+CS)5>YGGz+)l^L5oYJJouZKy`_;b#+j`lDWGAqTGp87>|V3Q zFvqr^7e}sco6<1jPT5l47JBgP6}+B#K~9ZgU5awq+8zVe3A6 z-C5nXpXDQ0kHsP8^AgRM`fAipSxpX{TFkr^^gx868tW?d67Sc{+-kJ-GSa{iE;k%* z?-#ReTjtxekk)yJi1_gER<-)9t(CD_^}$JBgj`@6kbu|DE1)?l>EV3uS6{d68h4-% zs1EN*SlrjT(?^}ThZkJmB0NPxw^Z%Ipyll*nAHmi2O^Eh0S$Yqv*UhW1-@^J5R$T0 zu6?~-Ce5)!4=d9O?Gd7Xp2xpY_%6^5)b&cf;e` zd<2BM#OE?Y)fU76d}v+kVdNt*xG*wug?% zB|dGP8yE33-k@<9G&v`l{6hU5_=4ZH4oKd#*akrn*=cKQcE)o%@5bO?3(x) zV9fOItqWbkg|B8EAY69uPQBH6j&j><_58Q>Nm9=R@|VH|RrU_|^D%Bndu)ZT@OnAo zJ-v&sj?k;Bk{#V(P}=D4sKV^Ja;wvc$`jVIcp;#CsSTsWz2J98Uc*=zz6ebSp8qeP zPCtFa)G(8h&6I;iloS8A4M}@m7h$yc!-GVsI*nxOu`Kvbk89#_0ZV6zPj~6do+E^q zz!ya{Q+KKkkEb7eS)fdxR-s=L$nTuse;p005H;*7Sk_?D^!X8yW<%Kl$&l^LGY+lU z1vLWp10-J7{@W8T;xm^{}R61WsJQfpkQX%bR|adWEo% z3+g>it}^pl56i{f{@a=C^e)w5qYL)X>CoULS$fK59waZbORO76``}M^-)n9d17ApR zbn3;I;wyc|0=`M-q=&=9h=<>+Fw-k?Ca5vP*X*V=6b_jirc)cu`@Krdyo@InH?Y<) zyOX9rjojglH=p0ZMDj+W-C88((H`=y!+| z_8I%U>3D%+qsfTqj@O2=1g-^bx@?Eshm980cCxA2>N4x4z+!0w_+l+HS=5V<&i=YO zBGe6Dxg8P4lSUNIB6ONYaFtfMCXX>zphvm zd>-1SWhbo7;dC<~C6ce>vXLw@p+99ea*3+%7wwiX2?LS0Tjus!d4TG%B%RWSF}^BB z6!VW!)Np!J$Xc6Agsqi6j}$Y1bkbt8GDN>?Jm?13fsCVx%pKEtveqq9Qs=2HIJ!jpb-7%lv&`j<@UQo?czNH7wS<=&P zbtYOE@?EvGH1rs{)mck!#K}K7CJ8gnuqoc7@dpe?_fpSNkHeEFHAb?UoGc!uze_D$ zJid!T6($E*7{*+UzM*&&A^@L;=`BmcQ7zfbWju*XV`GipxjqTj*5)Gv*S7~@r(aPg z{vW2^JRZvSiyt>LmW0tn*&4ExBq?MWLXR!Vl09pwM9Dr`bI(){gDi<^WXrxwWXm!Y zX|ZIB$}*`8LyT02@;lS>{rtY)zk1QjeP8!=o$H+Ud7pE=FF4d(9pQIuYehDa2g)*; z)S%XV1dqb})H-v87U_cT$LM?GhSPa4HD_Mip1z0f#ORqRtX?_Rk)N7{a^Y;wp6s=T zcw7eE?Ee660GDuW(znexILY?BLcw8cGd*;xMZkRvr+YD&^F^t;Y1Z#m2*&+gFkL_B zVY!C(jzf%p!E{gM(L@mPlC@ckVP|=K#!@Ej4#-2a+eN)K@cYsLLQ?t$^-Y#$B~{IHD6Jb$#LF#qh)1R&2~>6#Ar{9;f!(D-@4)ou&3zMI;QqOHq`nbA?@Rq0o(~EE46`;RhX&0_l2uhnb#V z0=AD?kebN7pWAK6m<*&?+pz0<49#Z3XjFFXBjxr7InceVlV#mX?dP#ElQ8N$nvR2U zAkr|9qY7WK>)SPVHyNoiz33^a{cR>O<)%HWXnHw#hY^i}TIiwT8VWm?U-dadyALOk zTmNbqY(>O62n#+6=t=GTOaE zsaei@1lqz->w61o4PZBxAi+A8{8nZ&CA0-{40n;&0dZPHp6pw4+4?@lUcKKD_QCo& zuY4J>gz^R772=d0C-VH{vq*VPj!jL`P)pS}o4HAoA~T@J6)2UP0A%i_TBBRJQ-4(& znD%pPZ_$K5djoY{YlX0^yQdWjLacl~KC%mruT809Yl)^JhM5j!GtLWFS^N9&NA|za z%9gHAg>%W{2~YemQ37+4W6(8gYX@Jq)7s3O zzD5hm1xJmkR%Okm_T!-Tl5hP@=OD(~tj5|*3ZqMzSSY(5*b{+tNcgrltMu_97YjD`Bv=)pp1&dSONB^ zn}=#DY8UI@yrRaEmLhD#L^oxO5Lln^wWI^e1#PV#uTQGzCDpryEjW-UEfb4ZUJQ( z=X>*)KPaY{>g;CQiXqnyJbue`4fM5|H}5U@ejCu^ZEHgGq|+07m%$y&xiPJtqwPqFT!ohqeK55jlWQPnTJSk6 zS5Toqi#AL)fG0+&@9yfHs~H~&!qZL#g(u1^C!QD|p2^OdHUs|};96X~$-fsw~C zVjmqoUm4eT+E;LL zme&7!D)jmknw!n|vrovSc98xzDi_<|}+myz~w$~Kq(~ta@ z9;8|et#H2qGm^7269PW&T9)w_cs*)YK*9?zJ`pyeKjT6q2n5c#UiMscvyLYoLECu+-LK z#|J`7Y45Y;t<8F$Ej(7s5A1QkK#OK7ZNSt0anPB`y7hCQy(i2mRN z(NG|AXOjWA*+k|_LQNsOS1@kq3Y_NO@&Ua8{qm-JE1cL5eas;bZ6T^%ZJ!<}_0l=SUJs5sZdjJWWyoe8;@claoW0@&@-E^Fz(n{Vm zg?;F(qDlj835`Q?0twq$^U#=J?LG7j(Ya|Ijs}CkdKZ4lxPxAT2ux?ec7yfs=d|ja zi1GWJ;RltCS~G}odjMbWh?DO4`rk5x*yj(Wf?DkZ8ZZfJ!ETw>@7cn0woZ=-mO!Lo zI-z?A6TFqJ0ylCSR623HV7Di-4buBjR)+O^4MHw*_K!qpB-nzw9zi zj{?vEtt%;JWxkBq06P3>e-6+9JgpM2Utoz1%@i(e-XT7Qqd$Z+8H}Q$Pa+TVN~R!K zll5~Ny5QvCVY&sWSzJ1Y*kh|5pH}Bi$v;%w5hhcRN?K+&=~%$TlMz`PGh$TR{0wb3 zNGrOGne1&7DM$s8%|139&gL<`Y6AuhN`*`VGjAcfEPLzShcI6L-~4^iS=<`8;ZWim z#SL9XI3H(bi;)@LLDPvp5;`yYoi1T_03=0cqb}5RSF-s<7*-TyXoq2%)V{kx|M^bS zy^rqe!gN6s8=P^)1@_p`Vj;8jw++_6p4$IhSaE%@+q*^St6bVdd>#fy?-p&qR*Ycl zalSS6E9nV=gXbw1K9;}^XYY=JLvxH+SvW2zo3AgA;meb~iXW2rQ+BTieb2~*(_dS; zgn&J!FeXos`Nzy#9-%kI9qm+7qU zo?fArg%)hwyeJw^7l)QrUSO&OX$TjsfcAy}GqWNHDbP5QGy1xK! zEirlU&Uw(=b~2ms9$dOu3)48$9gDTvwa$~w{@_R7rU3+MF+dv_zFw`I5i5csjy^AP z58(inBNm9`ywk4a_U+M9b{ZB;wSF(!AoxJ&0bj?fy%APENLiiW1I0g7ewUtA2Ze%o z((hbnG@fhySa3VXVcZCa>(Wf2%KhuIqnY>Ro-otk7d!J)x3X;%%pATn!P;z@$4wmk zN@?ah;n!z3+@Z){k{bO(XE7Hv^_)1@g;x%;j?vdMmilK_Xj+Vah0A`s2xioOLoC^( z5b~%WG_6sVw6FWPzo^nWb7j$EdIjI<8B5uD2Hg4fisC;q{-X1LtS9CT7MlPOCZoa> zS)gYMMqZH)t9GycL^HLL8l>70xTGkl!Qo1;Op|;poL!$V-p5(Tb9oN`m}3q70sDPJ zKgIL8s%R@8wCv8P+A?Cn!6OQ8uP-((kuA{^ue2t%;*x_}F)Jq*b{44J^Wd0P5XNj4 zjGZoxwIK;wMNT+7KzER-#vq_75?kjrJ06={J1%J{z#a8BdECx+ulYleSe5}`6n9vr zTHxa}m_0myMzr^LX@wN6#fBr71@l9fRs(2f$oRswFeE=N9qpSpve^Td9FY{ir%rh^ zw4k$lF;eUc9s1-RL4+qnf7MwmpC)b9k_dI^SrzG%R-C;w5pa271!=Jh$mVNK@lZTq zek)_?l0rchs*2*v8?4642AN!zXxu$2^YdjeTwKcA4@YPlh9>;9HWXVv1?Dcx@AyS? zWc+A#+>N)r4>hhL92wj$2V7tGRGIgLp;+{Z1Ac7o zw4YVZte7k`R4<1{EVL!I_X9OhN_?c^a?{bs-=P#Yd|UR@|tHJUicrp~WSAI5CHQu(Ua57zOn&agSD1 zft{JcA+}1qtrd5xK%|J~;S29p?Otm2@=Rft!jV=uJ?G5wYPK;Ls^M%9UcvZF`b)DQ zd=Cx$Hq>G$#8oW&7B=Wd0tV&O;n&;}YP+x)H85svlav=)W0UghV_2?k^dy9u_d7Iq zHpz~hq%A>&HHs-uLdJ)$LW9sTg|C~Nc}02ZHVKq9WGrbZ6zEw;3RINkDb%S;c!I<% zs3L|tZ*pn>wvDD-7}`6}q>An|g}66oQcavbLzd@wY`(lS*mWBY@$7nnSDiU5Y;Z1J zH{`^6W+TZ%o}`CCdbB1E+_Fr!Zc^@8&K4{f!O`#2t|=hVoV!e|JD?%d+(@JNy0uvq zheh0caq??8)Nw1YN5i=DyKF(NLdQ>(GFKL7SDez`1e4Dhh!p@B`rQJD43 zD~DK}4<`hu*6#&0b3=A;`Us2Ly2?*wB*i8=rlnf9|NAbF6vCzBCk7hhIhMEVBFrDC z1CYPNh()|@-Y*&IS(}+yjjCBWOyr6Fr2hPxC<{b%p5r1ziDm&h8W~G3c4nPVwl?du zD*tZdz?jOAf?O2f^%~~Uukm{xT+=)zCdcbj`+0@kmxBFp;?04X(+|Bqk6`*Q~Rmia5; z5ByH`t2~OZbW6z>0Q3b}_IGD`Umt!Oc(ZG?r0|endnYsRkhqFbH`9P3v&^CSd+{l* zFTSGBql++lT>Hzvsl04?{4*Q#x2LPLLa z1go&Vfj(B#wiRywy{vd7BS>5Q{1~tpMbJBDy%11Oy79h6UfHxi8mbM;Dc0|kJU(D5 z#tUd|pEF{ka64v>1;)f;^2Euy29Kf1*A8 z)`(}M{FTVJA_%Q74gtZ!6rHPcWgl&Rd7Ym;l~c@^N};b9F1a*16$^JG=RMEnq~b{hW^1=%At=#N^*JzwPlQU4Urr|zU>4A19`kk?x5ss8mK@=Wty zEe34hD)diih%|K9SAM*^W9zdN=F6q)km8iAhvjN;K6HoFYxwQC5uTllW;MpT9bH;j z#G)rjsWg?~H^b#0985btJ?4+t7oC`xCM!8?Esneleq0p>po1tEz2sESw9D2Q4*#P;Z z89He}f3O{l10w)1Q5g^L#$xfr!eQ35(piF%Wx=&|v`?5)|=NBa84dDj)M{8aJ52%{Dv5yMiZdG)Mre973r;nfDfUxGh* zttG`d$FYMiLm~qZ2;^_emqj1g1slHHS2$w%2OcfZcMumIk{h+F$sp}5O4qVl?mIjL zuXTPw7!%mTuo=}_-oLZ+ZL0m){I4|TizTG}LTHwwyq%t33G%ihp=oewg zbG+sbYB?csPqnjxedD{sjCDONh7-ASD_=8?Hgx|J5!B%Rw1E4K4&Zl>WHt%{fKJWZQ4%* z(Ej+x?KvHgO){+Hz`oKN4twYCePtiIm4CC`tswhuNmUEdZO*|Yj>dP~Va!1?P}mw$~13ji&*698|Zj(A0wW|n&@4XbXIIsWi9q?GE0dJ=ru7=~aK7K9sYCD(7Z{2& znx)^!SW1JeEPA>k>W?@*fBN>;chZDY;w>tKoa+{7$-6;+0)mgG!9>2&LKGP5oN>c7 zQs_T8Fx&n&;8_*JEr42bF+{2#_Cl+)wb3XCq(z4q>y;TxhuDXNA4jZe(Ry>8%{=bF zTuQVrwL=3)fHKS_X!mZRSM{OnlKHYZesYWpjEXx8SJhV>&s^9p6=xR!P!!E$9Kt^W zn=XImjl?f8cG_sY)!-oO7P~qh1=Xy5oQW^B+V(Oc5r^R8X<(k|K~X#%=Gb0T&n63? zgr=eCjlGn*NQ;~3m^J!dQK~f@ zfoTPf^GKHb{QZY)Y`w`K@P4r+Y;;@Go<=A*@Qo%-VrQD%LkZGwg@BEX*|P^KOUMZj zx@zYbyZ#I(4h;zfaIZ$25lA;bXin7LJfcF#m8;Bc5L;=7QejGvTWZiB&z@BUS}U!H zblLy5oT&jcK`SkZMxJQfqWLuKO8%oJ{E7zsj~3%oL>a#qH>B=)Bfg7MusRKv!K8e4 zonBwZa@4@CSLlP4&wz~v66NYBsKsy&4>`JETJ7{Ag`U4>0_}SvannQIj^W>>5^-s9 zzgPtsOHV;slkmeWMpq)nsvfq^ZskPmo>)FIW;80?6TmJ^Cu)RObGySvs+{*VsDYh> z)KkSR$(bQOrs~zQtw&dC3^xsQhX9~Rai9!3NsXCzq9HN01Y94&S;l;` zI%aL=%wZWfzlY36HVEtiW~Btm3SYGtNvH@+3`#Gj74sElt^=deb<(ZbNYEd+ zc*oYGjaxD+C@QEY>`3tOvCkQ8{BTxL*73`P;jQQlMy!68Jc*elUq``idKeZ=J1{+l zzarPcYKQ26`N?JmWnQRSn@O0M_>d05p{{n0Odw`~DoO`Y?A>{?Xn|)J8=sNQe3P^j z_UDTJEScSW^*$u}T8sfCsHe9}YvW*(NlJbxG+5`SUPeob!k1#{L^v8{s>I=DS{?Gp z&-!`z;Wx2~n`+_0k9@mtIwvHvtnQ@CJ9or?1kT0S-NopkLxJpluna5< zI3KfVTRK^b0n{n6C8ACZkOv3REw=ns$iZXJUM(5MLMd)8EEk90a<&aF5(2Zd4}M01 z{C%g@F6ADm2o|}0cpglu0#+BpGN(VBrs$`+HXZ;V4eXamjyh{!{UT5pc2hJYi31yl z-4rawg1doA&ieAW-3-!w7_w;f1vFuM;9d@*yPMNqpEVfBk{oTxup}(2IKK(IK6l6ZJv?^kc97fg zEA_|TZ`RZ#cpSD3JeMnAHQbh6TGWfF=hiSRVa{3=|J;64f_Y2pyu)c|1xjPkEV}_y zqJDyF55!s3@9Hf$q$L&_+_UNjMXNlJbiX<{V{xja9MQ3~y~c>WP{Oo7JMa-MViDiG zL;^kcBf#NKo0yfDw$vpw?qjT%!S=HPyl3sR>TF^sxe{g;te>pMu_26ylv@oCls@QC zqp#%De=e8X$yk4t5d@sv#oIxDWc>qzO-Os&$h!r=%@0BSEie#jIvRzkFqtgBmk+MD34F)zJj~U|{fuT!_|4maB)IXy_QyY!az;>W z#SyK8%f4#sLD>zg-g$8PZ@k$}39|V|W-GXzIxFTpO?b+S2-x*e z-e%Rmj|Wk)ycoE>#Bp;M`TGjveV4E`v1+L@@FhDkE!=^&tI`o9` z`rCuE`ultV@Fiv?YjBT)B+Xl)fDq+}l+G+^#a&8eda4!J{+o8MOy#Z`zB12|XjWPV zhwW-FD-?{8zvgOl&us^$j%~*?Q#8vKyN~Agsn9mUVVchE_99KLA{K1OpI+q8;eXl8 zJ9~PIolVawfj&5$xD(jYav-MF{m;TJXIGvmeYOj#WZ4KLC1N+R8Z(d}xI2VB>sl-u zKS9`u4}@1P1NCQqtquIjNI$%xR21ySKO$H^b`G@;#o@$p5^1nX2v$Dz%8!g|#ly^g zc{tO1Gq7j))9k&yp|-&^k`kA$*k8*O+Obkn-vSGmks0K+1%5R^|29oRl`&rlqzHE` z86t;V;8r%c?m>#P$5H_=iO+kbg}Ez*$DM*AU{oLOq7`!+rSKh9i}4yr{;dsr3Hle| zrn+os=5SyW#B$x7JWQW6vkfaZuK#E@JqcL+>R<_P`da#6*EU0QBFf*}xoCxspA>3dgV+po(rf zP>jbP(6?(%Rx~}qb`T%JE5IwiQr^SAwJ{Xh=-VR-pI5OH$b{ISdQ2PGB^%Z+a*^kvVSl6X_N+WoEOD z=ih8%{WexFZI?p9#83O*?^GI0zbsK<@1EOHsc>fCcmQ1W(dZjYdOLjtE`7Ru0bHeN z|M7Goe9i#~L7Z>~n3O*={2})Nug`mJ^<2%iZj>kH82PciW)sa-i*eeKxdBRDsM2q+ zLS!AwLF2Sup<8_jYTJ+L@kM}3-n2Vpsm~cLFC2rQm!~jwKR8ccu?Kl1K_ioWx2(hW z__s|bq8fKHBH2|Z8KO9$Dwj~f3X%sECicFdex_Mo`6`ZQZG3pV;Q#v7w^N^%tt8Wh zah$fcoJVXQ#J6}T7dv_!$=m&0G~q<~>W%95kz+Rm|CQO9OTzPAjXO%as#ZX`RlX>J zG;wcXjOH+!8FS0;7M$q~Ob%1U{W9u>VdT)Iz92!mFU^?dYTV{~v?f;jJa^khWV*=x z{r4Mt*Cu!US@D1l)#k1Yz1K*FsaSu!m+Sb8G&NMEkYYPASHhwkJKb=IB$AjVVf;*Q zqCo7ASpTETPNVZQMyae*oq^%#VO3?M94q#&k&t8LUV=?7yz#7l;L=g~^>rOphCSQj z%|Y+=8L^5~#03E4rFT-pj(8)~_jSsw6Q?Se z$=kc{i$$*eLwxbVs&c7GY{i&(UF}?H8_!!6!*(bB*#w$i)!%&rZ935xk4}tWT#~5{ zFiHavTp3yrEy<&^J(RyYmVdypig+#aAd%=Kscin*uT+smV*;4oQ-{>_1z zZ}tUW&V14JT4oZB6mD$Hy4LJw&GjvPp#a(VVtVzGXOE)K!1Z%eL%2mH`k^5ur4LjE z(Un-rCDNKhNbTpH?tUqQ(#{924OnV-X>c4%$sdPi!iH#d)>0>v!@F3HT#-G`QG>0xWt5vvxa5h9fkGvd-u)bTif-FmZ>?{rEKNPFtCZ+}q-MR) zXwhJCTz?oDj{QUyu{Gg;@k?!3pk>oenH~%_ukq){2VKpj`^`V4P)$tQV@LmR*6BKL z8{u6s3+S}sj{3vDo(tRB{^|B1loDar|BMAH1Q=mlNN!l?VseH(e&>&|>5H#llZN|T zp2&=NeqWdHKV!I_;%T!SK@AHy=g33+{Tbo*X1U1Uens?%Y-+VwuOytJ&kL+So2E+P zI?;MuSgypEUCw+T)U+RC+)ER^-o@|P0Sgg<60G>OqVz#t^|7x1UT?=}HC9k05uAjz zgnbFtDmI}EvpK^C24H9CBZPD3-hV&r^gHv>0%wU(EcDu4rK}hkuAedVaU4a4wz*Ec zNaKD@^!T^YqRV1<80uNGWwM-VRk!9inzN^VwSbvO;1<788iFpRd(vn57lLL>aMe*C zJEdOD=q{13l)|-ty98#;sy>xspnmtBPU}4&5I|>)GC4~8WF`Y}i)ZMTGzl^>?pD*; zZFB{Q$GdQgd6dwO>F<1qlIyTWV8N4s%)8r$W7CFbh#tY2A9~BQYi%XaRUAKg_9szf zWj%%|BM%#nDehFQ%3GcAJ&F$X{n&||_}J+?aGDwxMTA=;^CRqeYNxxveWc{8YqC_2 z8%V5B1y^KlsO`or7E{2Ygu6{SgJ2B4#B`C*Z73IEoI8brT#CO}c%le~ARUk?sy!UL zZ6Jm?X)=UzsDLmIoZhBe=xzwD@~k?>TDNG2-<>BCguVFj8biiB-$Y%5oBcD`*BOn)_tjL~&*I zCg!n-uFq$)mMKEt=Hb|Lv(E?t2fFWV8^jB8j`L)Q;)+b#5v_IAD=JINwCW+eQiQQ# zxhpHc{lx*di_Kd#i`h14Y}j?$aSbi<-|J6r(z`zUbKV92=HanYO#c3O${`p%t%RQu z`qP_bOOK#w;THE-1F&n=5FfO2q zx#xHH8;jMG5~21_I+e6e7Sp1rRM>O1Df8%ZdwgF?naa|0COahjH|HPt8yX1u%u-4y zKZ_?lWPjC3XH~~#PF-w<2yP*fLM*)&7aS$)z?2=1EujWSkAY36yY>=~vL4yL)t|N1yfdo+X-zo(^!*#dJ0 z)9Z^{%$Y1aBHr>EX=5hdKCB^=+mTc+^h{H0@@|(-Bh0YpsiSar7=#Bo(+lws4%BLe zqW(DHcM?qvM};)EhRRn84S1b_##Sxb_70^>%-1lpVUUV*c>1 z7#OY-WZWd#>n_kW594+g9H~Y+k~C5;9$qd5KqdCR0Rqt-hrf2zAu=7qK9hWG8_p6H zC8$%{Wc2zG?}O7s!}##(n~KEDS;L|Ri{Rlqr5Lq;!^%!v^?p{Zx~_e-gm-1kt^ED(bKo5sV76eZ9pr4}G!R7nUk%&!IAT=FyN?h% z*TIEPyU44339qp@JLOGNF4Z24Q}VXR)KZdhv&O4#d2Gj1JGZKoDfeT?sZG}|PV^kF za!nnyn}z-NSHS(hg-K^GOeH}-{W5M*`jq9VAI$CEV!wg|uMKKd3NcBo6+%*_SgSH* zULaCYCh-P^$G-FXXb4HMOxCFu$7-JxFde2c^L)Tcl?GxB71rW)^r<; zJ6X3EvwZGEBbrR-86Us%k#j-r5~JWyvSP{Y2&$!cD3J zx~gj4szi&nCOcV{_i=MV=Mh>mx8`o*=3W~w?tx#vRq*BF*QCGlmY-xxOAl`6iBjW) zIgrIwA7%-pCt#40W8sZA70o4vd5MmG!?9iKDApGyHZ4Mc^@-wGM93FZS=xST0cPP6 z4kt*ZEok4ob*-?ggC-4LNR8V-eC1>wK_9w;l-S>N+%=;8K!4dp$g7nQadI&8Z)M>lA&6kYQb;P?*V*BLH!XJ{Y(Ee!jAn@S{CP zfq2$4>m)4P8I^pEjwUIX;s5hszV_BlrAOi^=A>S`kfSw&Yw+MWc(BJ7c<>+5P&{Up zF@z7_`v9>t>?*;|G+ZO|0Vr1Mv59iid_Hl}>8l;A*O}T2U=Pjx$Nv9mAWO;rIuz{A zp1`71y4W3sD=T*n1^?a}|fK8@><1pCT)bJqcfIvnZi*4^}m!suV6O zu`*$|iNmEW7^mPOFb?GZ?h6bKXUXN}GA5lsmKQrJL?_&r6dMF1%jWr0(_~=tF%!3# z&ZH!Mxb?Bw;@cZa!?I{pc0iV}S_Sq+mqZzWkQ=_0Sg$?^5MaNT;Ml<3XtnOYJ-IR- zcFnm)zYi9}EC|4OsZT0|sH@WSZvJT`SXOBOV!#6?rSer*JV^=wuGfyD_0Y^aa>QOR z0`-dj$MJ{k2|HgE&3r_|l*#5F6dMJvfF9=k@p32IaAmp`T!YG-Z7-P9BXHFxh(}|- z+5;{)nb{+R`+!--+q|wNXsISu026ZXHIuacuQ&zrcfp!k0lS7khY=-pgq)o#`a$ zOjgZlLx|15RSj~3JDZ7Sl5USZBIxgBInmvQaQ&hJmt`H&x4^i&bA}NZ_@M_FR?MXE z(0eTzH&{9&Y9q%;O;g^kpu1yfE;R({VvH|$>j`+E(1Cn%wibk7Ht4?O&z|ASPm`b# zIhAr3(+rCwUUS6nv)QN5g!@_I>#%g^QAy8lDMZgBvQGsnsqgN6bO}+(vk8}(Z2i7L zcymo<=@r6uz9eb5mU}oHd?cCuP&k+O>#G*c9>#iC0MLTCER6N$EN3$G-7HCwhdDIt zmy6q7NlA7l!6!W3xFg$Ou$DI{R2O7?dEg4iPj)cn6$21<7+moGL8LI-KR$rj<@5T( z6Q%w>v0X+*ed!|Y895J@&EpQG0U;Wie09UWNf{zBdg*N%dAG=f&%F==!Mgsb1nZ(s z@WCjL_@`Y&Nh4cTmMo#Q24wt%8O5$;=nYr)oe?=vT z4N}ctoP*F6q5mIJ-?1WAcz?{O^`v3B8(#X+S&>r~kny2>VFEuA?zaYJI>vQnWK**- zAP=tCbK>#kI7+MF`QxvwELPtglzHol#J069fb0>^&k`^x-lk@-q5qr<8-q6G!jEMr zXNVR`?+PFeZ<+8`Oo*Ai{_7QS5_@*4k-DlzFQAI6$o76!>~Qd(Ei5^uJuI&WT7elfvBN930w~riMps9o#>k^owOw(mZK}dFT1) zy0lE^6$X>f(l^=jCDG%pi+tg|+4jvZy8KMqkI?im8z>)J=X~A>Z^P!psxdzcvroS4 zYBO#}>cyTX&&884x0f}H+FiXXH_g?wKnmjhG`ddy0eAO3Qg1O9f_l2#-=ID*YM=@> zFlI4?!Uu}66zRh>1)2gitZ!db+rRgk_$uBMni=|V_!tFsKYz+NLVI50HKPd8?p;u( zV?d?Q*e62uRft9OCETJN-IaEajQlv3r>1a`qlyO{UjLED2XBzG&l|NnQNsoT|Fnwq zFW5Y-;>4D+*GA$!uO5fs-^&OFgCI~@dAdpAg2;!;oSon#Wi&l(2xa4=%aWi!rb$!7 z!UF_3s9}fvN2gcsQ9!p}nB_%}rD2?s?&*SY)G!FuJ}@2zK<5;dB`5k7+#)YsfaXk& z7_|3B|3UFY**kgu*)3yHC{{aHLnNJluzvcEh`DaT;D6X%?X*Fp5bG0Z!S4Su99+-B z4-P|zsgq&3piXYnnayx`N~W8y;f`%*d2yExpC;c5LEq4adv22sK2-g|X;)V<4J5GO zq<^O4?%~)!{+W00_tATcWF`@k1IOe34e1!^cY9^(UU%IpGaz_{(D}f&MyT4ND`J`I z%b)8!;=sS=kH7A6mYJ;LpM6hnt#SvK(xRK_5Hi;f{_5}^8GCS)yQg_q4qZ8c zf8Diy_KteMo!zR+Jzc+5f<%y0Li7@~dxFEmw;#QND1R9;83v(GuTrQcm0Evxs+HP! z_yMLn&Ddes-ut+l75>eMHI#;}NiDq*SN#jW&gkWtpVnJwI-|0b3SQ{KOIQV^2rI+U z0s#GT-YJoNNW=bOtk=6t(pPZzyy4bFT51D2RF;*~weIFQjyU1fe5qQ>s)D^;^&B<< zUydIeeUawLFonf@O3ZC@k$=8NHR)v+!mW;R!>$WA6x5m3u%0qW`^7V(i26hmKJ^?i zVb|N4&dlP;8QqlV&o|)9yYDxmPXeB)2lr5^=fEQz>O&-{9Z4$1-bJ@@*7bIctu>I@ zc6kyB%=FKkhLn}}MOPy=?3AajP=jK3nmf+nYfMN)b`|s%+d&P#ZS- zIh3I0J^)7;d&;qU=#SjsMZ@eDEdgNwwE#D9SBGUfGtncP^Kw^Le3^mTL9jU0&jeJ1 z1wVPVoy`eR!}L8{cZ`URAUCIiX1#QN7x76t;NKWg!*u*3;iKHP;EqKku(W9DmpW^w zKjhuYfY(K9vVu&CMxbg=%mO@hsGXeM2??uEpx&vkOv*n}FStb^= z@H)eIV~5V)9^V^(c%8bE4!5;PfjrU`@0{Duvt!QtZbFLIefV{v6p$+=@*CeN!(pc4 z=^zv0BY_hHbOQTcm`#*X9Ky#`W#(P+(&n_EL#TgsZ&9Vn6Ri~4OVvaC$AC^au}9VK zRhO*F(lhF6Fuex^6|~797N;a241isNhhrE_<`lzdLr&%`N0#egf3)g6;Mvjs>0 zox1SEl`MsEyFbv%W73{%8F8<=s~NQt&Ynb3T+sH_r6SC%eMc?8Uk=j?&Yo^h4)9dF zSGS8pllhll6An7D>8cYQB!Inq30W|__lwC~mp{&uJ-5ImjqiIBsxN}oi zyL1k!>fNIDV$}1sP}39M(Mt~>`t7vG)Kw%-KVYW>{(|(I@$0KSuYXBIfHa#QgsW|< zHbi}L1Ujkg?{otBAN}<^P@zfjlmyri$iWY#gd7@jeu`@dcOmV+h4b3vB2SQ0^}}a! zeDCXuRO#k;6GZAoolkxKk>=L-WsoCm#@pbnK7YYgAAxT(?QdYe zqsWd&I4l5WZ$GYj?*mh!$?Ko5x*!l<$b`?~Z?N#vcaaa5Q|;~P+UV{&kCMPBW3U{R zB}%h!N)_>Be4yD4;e_hW8T#~2=Vxa%iE6SxWb^MzLe7hD+C2cJrYX<6AsS0eLIAK# zqO94P96j@pxBI1?!NUlMqYXC|yKlfMfxjqHS!(K9xA$zl>bb&bq(#vlJvx_JOC;*w zNr*OGu9)|F63-?okH2Z9YE{8oN|Cdm5x#8*Z!|8Bn}z45$R$Ac+cWh+p(uOQxGi2f z;iW6U?8||kSq}L7TiF{K61V&QnWChw=3T0S5c4r11!BinaP+C)aqr3rIXuw^Y=8OD z3gMgnvMuK1Gi8`KAI|3ce?4Lbc#1kzGJIBC^M0APNM&O3^HaaUXZ>y_=$~V6sOPYu zJ`xTdpoRr`Mrp8(93Lw0ZxQge_QM{TDO;1^lb%`F^@mMop1!TX-p!F!UFu@vKeR#1 zTfS4nkmInKqyT{KGDU6fp2Im$dz0cD?5zd1xW`34SeqSi z^tg4z8p@l_o0Yrb-v~v}hchcz%>Y!IQw>TnabHDokN=uOHylX*CF^fPG`w$44uLtS zdEf;3TxAv3s$_KtL0OwL{(WfeacY`GfuU-4p;#JrEwvXm1 zx7EIrrQqt%_Ax-hAb)>ZJ9|)!0G$~-a)SuMo%x{2QeZz192BIdGL7u z&R(B?*K(HM9w&=V*r;Y?R~8JSXvXc^TFjyb2X6J0-oBcnK79P#(R{8uoM zGgq)&C7Yll{;qg;DzsXFOU}Bgyk2@Qy7uN{U)Xa*NPo`MTtSk`zZ7wuiGIgNLx| zo9G&93!&moNrvq|VJ^(X`;F(rhfsTmz9hILbb?h8UctWT`$3%KqQ&ACuQQWdUw3gK zH2G5P&0|0vt42(=4R|xGZp$fsI8FO9gtM7EgImmHQl#T3Uu7nF;6f^VX#}uS;yh7? zo;_Sq4r2$o(3%Hi)QhoHW1!-R*KRW*%iDfQ6qhxAzy%2Xp}9-&;1ghvak}L~%N$W+ zI54cC(lg=nCbW(roKa;Jf}OtA)y!dOa@P~#j$)^G1AA5dP}uVMyIafN%n3B-5YFzA znbgHqOTp#cs~uVpyTPEGrtbj0@o=V_;HvG3FN6d0hy+(C#ynhe;3+;Xr5<=l+u4pM zI2D{)uJUaAUfLRY!ua|Il9k+*(dl1RcbR^E{c;)hjSBMh7Ilf8w!gYkK{ypxjs+gj z%?{sx9#?(RFp^hOAavWjjaiDC;{JT6={HQ0!Z*!yzqu<8UneDP@HqudO_1Mwu!DEH z!#jhP%dpeMWe~@v2nSuRILk|7Gq&IsZfrt)vu{k;^9X}aS&!PB0gmtkRdCJ*z7`qS zubPChsF=SiQ-*=`2C#zbaKs(=lFd=qxNN4k88~2%6LkQVLO>N1LcxK@zC7D+!iCo zsqeX;7Qwhv%g1^~ajYWbI~jt@t7Sozs~y0C>I+_X#}44a07oA6Y*v02HRcy zYPQhf);uVqD~h{l+xh*4-4M!Xe+72Bq=n>MDvQ+KtpW&U9TS;3byiJjo=dIBSGSIk zA1^cc5*M(?AI(ysWe>smFt|smwphv*#>wDli>IvF#|W>fM77*CqlT&apCg*Yt8)Me zb${!X@fWUQ;2U}AVnaAr2sNmgH3AOS{}w!P=-}al?dBC>{C-<%w^73s{H+jT%%3T< z$b@4l_Ku!z96OxG4icwALHx?Q?$Y@|U#lE2Zu?6Iy>BGD(S0?%cwEE^|a& zQ%B}!5~aKB3}GH}KrUpzgsWb`%aIm>K2qcE=?R;h*i{6Zd}J@J4Goo-GFcA`;+xu7 z3XfqsgBj0>i5+2&$)LTE2f5#hh@}D61|TZHjAwsC7RrvEyLJ9 zg@BbUi4!aarubJ>;Ip`N05@|+VB5s@xVsN8hOjH2oCePFZrF_NxQ!WNjH-G&xr7fw z(7ZqW26Gdt+c*#EYGixs7|Wx%Jt4xax4jbwO6!kkY@t#aKsP1~BwKSQeGJ>5;FO1k(6A z(3PlP%`tuwA7CQm(cLHhE1h}U2rOq)bc02?KqP63am)4B`qInmJ}`KC7n7t5ev2kK zglCsV*jW;RX#?5xqE&jC4kCrCilgkA_wM$Zpuc11$kyq<^E-#^p;F`1y0dr}p5Mg| zfAGuOBC+dQx-xF!2oyqi5^M~0wrXZg-R+m2?dR2F!?DnCL!CB)$7W!R-{eaBe%{~x z2pkT*8+S16UM+5MldrQu(af69aO}sxOws6WP)?FJZnqdZi2rsSuxXaAYM48hZ)KvW zrseX@eCnDyi@~H|!?rw-V%?#vEKo)Y30_-eJccMpsFPvjzn(7`r_wdF!qS0Gw>g!r zE~Ca}9FlM;SRJ^Hy=5nnoE>m%(x-a@Up3Q_-%3kLM{8jT{k%?SPg# zz!7`(C2ItV5Y34+VMqLko=l-B;Xd$K0e`HLj0oq`ec4hFaTM|up#G-`)<+d6cj z28X+sXrcT|98UJB(tpr0FTREVngX3^{d16u9bC@Un*R<}-fv#-ul!&ZZ#$UYgSZ*4 zU!TevyVK`#?O?FT`6*@Jes4P?B|0@LZQv^SzRsCQBVEx} zJ&dzS@jP$Yj5?(*$sM^>Q&z?zp3)1;ggZENO$Aqd*-%Fokf?35pQpiGm@#UP==f7iUHLTeu zxjm&=M=@#`?in5(y7d7=U*nfS6-N`ZCV;{fhU*1x!Fmr~3qB0aJJZ zsc=u3y*}Hn-(WF1j-?5DRsIS$`jPy(R`hq|Pvs#z*AyBlPZYh{wZ84o|x`w;$cwE)WxZcf^U3kWov6T)q5#U&+D1oq|{KRcWhOVLOQx5#b$=Z_WrYv`{w zInzv)d=b*4z}8KXt%TfX>Ktxb;l2qJ#D@IIxVM^S3Se168mPilp&G;KPoq zv6LWk+rC8?{Uz-Bz3pLB$o_A$dudFy?8g`T*B5G7?>I+pOm)mEk=FVnF>QbHH&7A9 zfY>_^j3&5{G)&sVX?mWX_MOMyPp98@E!B3KGM>M*A7G`?C2XX!Oq9t|?&lDdrNV&q z=eR}v^s0(pw4_N5cSstnvEf9c#lDF#k|1Uwo`NACR$UtIFh?rlC`B9##q)atU5GSV zq`->kgUiGhq|l}$xdc;BPs3)B6?@`q4xd+n(S5R$_VizUL6`%A4aD!WJJJ_4-k$tC zeD@Tn0Hvz{axa18jk2&-=F?Iw;gA~(Z=~lf9cTg{;rI+@{P&q?^#O5z1PSlH?joeoksT$ z^A5+hvS~;l8&PgTxbqxq9BZCa9gj}l+J;-^X?^KmrSiv)NJ~CDbqH>58@8+GZ`Vne zRy6Iudv>Z`cCwxZ1b2I>njiB=LQ9I=%w>;f%)DD&K~6$%Y{SJ2G{>*40fxTxHq@y78p(i^Q0lxH?}k5s z=s*5QvvkJxbRC1Fq9kS<#m_W63i)597*qR0Em~!1ADw3iZ~fZh>m;{{r<+NTYkYdy z*Ql*H_Zt*}(lgH$WF#?>*&p%UAJ%3=?5#zr@a1*l-FE8Em=6OPlQoC@L!uAP0c)!X z1SPbWwAhi0P!Z@mhVA!pi%GZuWO=gkWIUxU?_Kfx@}`0}Km~gf+uxj>s;2P{;V~cC z8y-bnm1uqoGW#>a^BF!l~_8SXr4Mk_PI$al3>}?!YX-6>;2#S&-3* z>`GCm6T=QX$Eh}Dn8A~kLiGWe(;~yMi%tTe+z)vCj~GH{hg1SWkvB9vAN^8h(hawG zn9h+dG#1@ewL!dGg%u^mdt0!e`|PW3mp~q*` z*Wih{HQs#OVB=MppJIP|w*70P#rJEo?Po6u z!oA3P^mK%x36*GJoVIa$c*muBs8JcUXMutaUs*(9`;j3OrcTfQ649{t>pkicdx5Hq z9d@_2uoW0gkJUpBfbbDRKxfc9hvSHse#|C6qGp|+udT*V<3N2%&>-Vxpwy4kp9-x_KasB4-*8=c8YzQRR)=L%iK|(tge5bTwCl`jSe}5yUW3Dl~}r zTKKU9Yk}5g(jGvwBpHx_4SuU`V0_Q!9%>m=$0fOGj>Cti{JrNfp7jF4sm+;iVUm;S ze;tPRT;!QusCn)1KfX8HqHGK^P#G3WZM|G-m>3a`J17T?Lsb_8O3_?CXdl$5M1x*; zPOkx3z;ijN@8U!+a@>-;{E-B9{rIb!)G#*u6lj<5ve@BP4|*taruBg66qzlwCDI|t zgn8e$5l->9CP*|YGC$@qe$xbS0b5xS^rX?cgG2>?Nb)_$b>2t1em|KuH9MKxOHfme zD(5RVsX;x$Jy@K6$3L>8f#*Ru-$uq2y7Bzi-{PTR2=O`rsx2Lj7Qr#I?cY!Gg}#|S zc^d)?zME*mJNocNRoNSt6ZM2{Mpv|25uf*$D|v)d)5dHD8CjyZ)QIV~#NiZ(Mj zOrjM@g-$4htqil|5VHo8cT^i4(CRpo!-mSC&{D+2Y;^Qa7%Y{;q}>sUX=f9e^t<12 z*!^AK>-t{5Yxnx~N7s1Y=e?i%IX}3y_Lp z!qt|t=^+Bh)T$on15`C$%Zr2#C1qC{uXWNFnLLu&-bZX7B$xP(A=>f1?`f zgr+4s6$*DaIEg(dMHy3OfO@*3-f&Wivnxh``gzgG3=ha{VImmmca&=J`ER!w{8T@o zE$SRf&3RVe?PDTlE%Y8wq=0cFBHNufUk3st#mfJC8GEkC}U*0|^`AvTHb z=GzFMe%mtQ03pRIuCM|`+JMNnJ&KGQWT!NgqxAX1A{&K^ON-V~0O>cF+OiyWy$fNM z-SikG3_iT&%FnAi%erf~+?2RdzRnL!+>dn;3|MG9O9t{%4`wip&OUv9#GDlmrPi+S zqpi!xI?H+pCK~?MVBt3IWHAJI$OK~%MM%S_QT&Vk3XD?nUKxjN24AE-ehFLTH}iu4 z*(5j7oDRJt8~5~DaIY1cR#v0-s^h?H$`Ju+s`!JFKp@4jF2^9yzbuF=WqY?{>L3(h zaEHdL^DHv~&2cCt5cYp1tqF`+T1w4hn$y~TOkk&#cqL$C#Q+y42!IKQwMZ-&i|MPQ zBCs0dpN2_N_c2;V=mQHjWpKX$DKTC4x}gKlU(s{4)7zri23ng626%F((jYPxA>#nZ zP4Gv{sCb(5LxbOFH1Mw25SWpxI!?n(AaFeaJIw}%86k<4IQkCC(-Jk-S=3&0+>Mq( zQdS5Nz6Y#i#E*NULt|(eSag}gM`IIn$6|8_&#{!=0LmO4FtF5Z$Nt#h-<3l>g5W&8 zy$KrS6t>Ski7@YUSnyRCc0>RcTMvK00T@xB`*8z}TiJx3OkNMPCrnkVP9#sJ1l@NI4DuW(6-2E3P2{?)9j>g6;L1{QR-UTNKVMrOpc$Rx#sz z09JyyF;MthXt&PzURp}!;ZnJPOxAibWvqt_&BWjIaW5sotK-CkQozlkXVKYPb?$g< zJUJObNva|{nTJ;mG1b@^otNGCJDX5XnOtZM2tA+)+#Ac!@{($@lP|uk89^&bOrM`+ zA#%Omp!8AmXs!J}q*-$u{dz8s9L(OTfQhWt9KSH6c;l>*jE;|MEZR(LGmdj(A7o8f z>wg5(>UW^!;*)Sn;ViHPf?5q>l!uP)blv#~{q*j+GVP%&QT!Yz8_%?=i^)zszXNRu zdU-?zj!vTlfcY$Mp-qD7ee=~m>7VPC6q#;V@0eRERTV%xk~J${OJpx-1m4(khf6G@ zlJqaf$beBQQth5LgqisGQhJ%AKefGqDph{kKy&hKe@GOYb!f1ET#GAP=D*5E#<39W z7B{L3fBUy=G8Kfr63VgmWzFlR|ozLoehK2kyGgUzY$AgvRN{6pk{Ig6B7s>NQ0 zsa`6Z!(t(&YOQb5k^*`vYW6*eht2c*b(E?3bo;1pu{mLTE|?XMgH46|l!d{^oc8c0Z=c{QVSlOs zuk5MOO9tM}61P`Bvg#EKm9n;CA=cV;VA}4tiuvVrY43$r&Ms5;Cmq}vD{)(g@gCsE z<2>{4n5-}U;}^918aXeeH$C?SdugYVyHY2jR1~eNHu>jvN`Q>yr<#46;M`gUHs>X2 zo|FJtdwf?Jwu2~AhajI}R$@QW!|!wadh!Cus`UNX-k86X6>lusFL;C1*Z@&XfC7-7 zFN#;?6@~CmL8rVpe6-z`K(B0YxO+PhHqL*LSGo;dMmfgBKvmA->N*765SJ9ee6$TX zw6X$Y`jUzV!!NjM*j`|xPOvbZ)Idj8c(j%?tciWT2CX5i_$8v`AvId=@X-_19vjmF z31D0Xn4GjN1s~$&x`jpD;M1`wGvO=Z2ZG@V9|jm(dEjgK-5yH78P-aL0QK&zJ^3EB zYOuGjYu{IggqXo%l%puQTH|uJ3OAmCG7@Qz)=6|k`9q3WCceMHq%UmZ?f{w&SY}~u z#f=q?T(rs=F?Az+oj@4KPi}6NtN_wk!8wRd`DDMam!u_$(5Eg-mp9B}O#+^JKh*Rk zc+hrO4BfcHZ6b>6i`O69TNz)eoP*{etD>^EDr3#8$~CtVy92Ly)ptAxE)VAPy@sM& zuuN@V^Yc6FAXj$D7I46?JPcJ;gxVhwo=B|{9J=ef%0^~X-f-aN*sBXHn-F0iVN^E4 z;_0^fEIE5?V*PFdD-tVS6{3S59@55&v+NPg={tQ@`xQj>LbYwRR)~0>AhE+>NB@lZ zvAqi$ko{kfp88URgWhC>0A~dsVbAO=p1odq7?>U%6 zJDKnjC%DWS%zooyC6*EFX8IfsT><@I{`(xCIpEV{{6R`XBJ8Cq$7IuN{YO4X!nKjXg zcI(pZU}?@E?{g?u;2rl@liBhkDk1P%GIE<2D|agKP7gQsdk}!B?q`tqYxX>QA~E-E zk%Mm|kelz1@z8kKAQTLqW(5*PHdpuv^e%oJ@Dc1Vp(Z=>)W(rNrp$R z4N_0}n^kIp1I1}pX9&!P7H~l5lmGelCav$~M3kUOR6?bly85(EWpefDyCsArZf#&5 zPam5%LSP`NLee7Ii$J&s?!y!G^97a~T&b%`ve9 z-mHl_lyjTBvFb5uP86?(VAp+KA3}#D$Akt$Ybe6w9jj{gvEsFPEzOa|e(gr3TE1$X z$A1T`hBYBZ8Oy=Io=v*;xzJH_d_`0rDna&AdVLKbIMm`}5(=QkGsaMU>=QJMD0ZaE zBMwK7IPQrx7JUx&_;Z38DFdOW$6ySY?HAr>O?b0^$!*4Wc4$*kOZi?xxC6OHoH_J` zg&)Pxy@EBlNst9CIw>crL>bpdw~n4iIr?->(f$4f@4?=D9_a80A>YP<@fER3E@xd# ze~RAX9=P9~%GTP_H}c?^Hy6z3E|?K@iFJQ}u z`0)xZW&{71m5Z~-W7LCu1f1t4JbpBHm|EBRxw`Ll+{4!fuO|sFaAkz2mLA({BV_7i z!fnV!FUyC%KzLgyy_u}YtGa0Q)f(4NU^k|hYVAAAat(&De5r+T*I|KZ|HX)E+3`5G zjWq|h&ezqp+w2#PG97ouRlb=%5)_O)LQ9BZEt1(3XP)h4Tep+7YU7$BCdxQSNs=B4 zV2OYrgoS4|Jd8_{2R7BJs6}7b-`-@7ye0?5!O)#ZMZ4D!E6AH*c^6y77zvWNmg7fg zec3pUZnYm}Y9A$MyFtObMXHo=b^U;zyd>}w(FfAa6I72F^BINf&f)|IxbN=o_N^f@ zk-YeQ4X(tt%f38p6j;1)Bt~Ln6k79Z-j=>cXbRp_woa}3YWu`mgxCB-Tr-M1Mt77P z0ZUJXowD|d!idukOiV`PINIZhf`D7Aeed0Xg=a*aK_o^N@>-X;G`>o%l39ZsZCU4g^ezDfp2!^kys9dH(_qE>(~eRsO}@|9{a*hl3g+3bZaGAwd_#5yPlu>(U}<9B8jm_W;S0{vIuMp~IrKfkMhRQNeUHVH409Y?;U z1nlh2U#_8%Q7~~iA;dm8Y;ljGzMTF%$(O`t%aPWzsi_J$qsw;3UCc)|1P!3}mE;0* z;3nn_J1e*}{@QIV5x4Yb)!7{p{>d*37T)PtHFPZ%f(zvX`;)Vp=on~l`57GIm0@E@ zwNA+1cdb>d$Zh_8VHM8yN8!LdUEXch7?A~rprxbP&SUfM$zX>+$&nYevlX%Fkjr58(gc@ zr8-Wh1o#@Xd4U7UFSNXn4V^}gVSn2H@X}v{WNFjtzm1_7wULtJbtxY)PE9St*TPVO zvs?sr?t~ljcA4xY3MRNQ$!56W4sG`<=FD7(FQxYW7IxV&#`L|Oy32_E70*VTK`>Og z?)$7A-1<0Ohh#-fD5tz~L$G6kqj6duh9pt27IcJBw2@R%<}vW?lGoqW)0%lLMA(dNSAE-G-)6o|cEzjb>B>J(Pr5rXSjLSeA!Uo`E36X(8Nd^NR8lddb;&er+m+lr}6)2>e1T+^L;c1(Eb zBQH5IJ*nsHAmiGEyZYQc2$u=8Bg&^Dh$2xTPsuD9pP}! zG1*HH;7RLg%80!0c=%TB+u=SH<1H`lxu;cFiT}7~Nxfsz-%ILCjE%nGyL+?=&A`Yp zBtJysrbCtL=k80C41pzg!)8fBNKnUaMxh*+$Mu3RnF}{dYD5_;uS_KMI|VkJUQ*Nt zyz~bvOuQ9F{ zed#x1yXw~!^LXlQ%AwYNIu6Q?MlnAQ2*Csq_3HH||1xmhgnve5!h3;%&%y%ybI_~k1Q$OVT z4f7>vg>}^-hZ|4(b2rC?I)p?}-Zfuv`8-ZxH>bJSkRm?N-Lq>}m^jSiT&u~K6EhPN zuz6zRhR9_B%8KmVmHUo628^$LcW*RV=hJE;QTb;GILG(hNXq^72YmZm;at2V02 zK3^5RZ96~f#6c@whh@D&I^YkRPbR=%Wx6zGGsUdlux}m={)95V1t1hoE^d2nKmX%1 zM0kchj}`3HujLO!Zn)$J+~MI>7wnft9@2JP80oIc-51<$tKF?CVkp`T!J4keXTZRBQG&&H^V54K9mBXgL(8R_;alm{%ap zxS|}RQb`k&q9XS%g5YR@a33@Falte3QSdy(UKVWx7o#lqm@Cx29@%bFVp%apHHYWJ zQm-K_QL#7z3=o9!dbmUxdzF@AHhZ<3oJs!_0#V=#BdCwpTZz?Sql~3^pFEes;$*5F zcSI$mYd|ptf*ix^#Q=m#e`FSny`5)YO3ri11&5Flf3lp2kkN@pvF!)y=H zKp~qmzbiRnS;GeK%q^yYt2$02+EU~S>rt#g(i#KqE%ltfuT4f|!qx2O(-(;pgA^DC z4p8fUD+j^?_Wi&~&6)3O!Dbk9L85MAl3cMU-;%2 z7raX02Sj66-Hp4HZpeEYLKL5veH(~SXflR4$hU!6uJ;AbN( zzuS7iZKw4qSV%J!0lGb%?O%86dbcMM#oe=VV2zup1oM6$u8x!p3E$7Z=$qU%Gj-5uGeq6Q8Lf}rT)np6@*U3 z0QG6nn<3!+bRGpiMBo8y)&aXPCb}SadM?Klfk>vP>1-YbbI&!o7l`7MGgU{OnA0{^ zQFMN$;wtyfJw5i;Spd#~VKf9dpCHwD)m$MOXx1VW>spxo3u1@a&eli4w>69CzL<|H z0Dkbw8$!@XleqCk{vO0PF%cMn6cZNzm#~9!qIOiWZ{`hKcTU*L>MTmvz;DRVe5o)J zIONRKVuMIW@QxL~efAqTUP#4e7EG-%p!-vD0%jDTG|zT~qP`>yZfeFb6-?YKh{GB;&@ ze5EM(MQw6=u8N#fyC+T=ESLb5-WyspU8LOsgMgS}deC0LX`Co7m?><#+MFBH@(7!78IM8}3OYV*8n{3tv?}yX9ba3v1_=M${n}&1D zP_q_ny1mRVjd0^h*CzBYvL0$8Y|HV3FjF>xIZ5!teb8U~L1sk$`syb2RXVo0LU!p6=9y$IrepBc zm8i7t3v}TaB9-9gdn|RAUNy1&5%BRz& z{jVF+0YFc=z8!O&o~~Hzf9n0Y;XVDB28Ob~y@yZcX5ask0QtMje+gR{A+7TNw*-Hy|Npl<{;ItH%mVpGz2+~8Ft_|G3DWxicOtL``o|Lfs{em1 zVy-g&i3DVJb1*ICpNRNZ5`a(epPk}AT2zAU@4oMU{KFrOIQZx0;^AEC6moTg?!}9p{Ql=W-{HxN zeO<}U+IwcrthHwDxhGOtQ3?Z<2o(STV8}>|s{#P9+5i9yJTfBmm)il^3FsFe8!<6u z88I;m4F|2{w(Ha2-ax&5T}CQek6+x*A%;_()h*^z$9z+VzEfVglU|tGR64Y!yxx>) zpR9L``}oKWoOpVTM}jesNI?=>BbJt;^UYH}MB|>PAiD+OhuW17G6q56A9qwF7ElM0 z1`3*kZU4qOr6oqvhE9cUWa=wFPR{RH_;d3a95^O5OM8;AoDWR8VvN{nk6H7Xc=6Tf zyK9uMkN8FkX5?k1EHiJ0D5g`uWXps4Kl>vRCalCGk;63~y8Ls(+)k)IZ-?(4SBrSmB;IR3;N|{P9}tMuv%~Ge zwH5$-oyA?QLjlXF6#xiq|0ha?4WNQm;ZAX){Bq1l^8W77cAf!5?X6Bvz!dp!B=x0O zY1f55hOeewvlti{M3_vkjviZHQGv#Rm+4&7(lUiJgafAW!ZTED%Ri!DA| zh@Et!OPV7BDMNn*)n%rGQE+foypm{`rNr4~DbaRZjM{fnktDZSn`pUbVg7rQsky#W zKZ3g$(yfO70OQ0Z<*zbRLLD8mNU_^9{v020Je>7O zw7FhRM7IuVW3Y4OVLNS}LX4Lb7zj{}yLPep*n2D7x|!*4KZ{2$bXP1_ttfP11`nhh z24fFQeHn@F`94=2@Hhno_vXk1(?XvSBS!w^Zb%KU{Qc7qG9pKu?`E1q$5W@CkKfYj z+ti(6zI2o#&9E8x29D9~(dSg*hMDO4j_3Wg| zN%Gg!ix2&L7)p7zaT zJjMFQ|GW2r!>3Er8y|oSdV@5szcwbs*{~#jz4&jO=YY0Ig>EFNxNwi>&cL@~F`{Ui z{twVQ!;x4y{sXS}uJSQJps{I>U$GfcWpT7JbfO998PuL_CFTHu)WZ0`c6OkTt4jR% zpY_aOIWNK3hB(;a%4v~Ji}#jPy0iaASCMc?Yf@l2sVRhRQ^JJxxMxAJ8vk=g0-P?F zJdVZO%7Tci)o=Djs}D&g$d%nc_yhZ&{*3Q2x05*h-~ZjU)jB#*WcP!phU+GlY|UT> z_6-aSeup!5wK&aG8rgdXk!HY91@=$HxyqYm#QdiL=p<~Y%YazGtL~31V;HutBeL&L z_OL~s#fMvY*lWxLLi9k~Zg!|B7PGtgY^mwwk03_{j%e!3fPU@ z;Mv}d-jg1IT4!(_ffET4Er)U|eS3PuJ!mZkh#g-Wi8ek?OCt^B(ZT#R2CM$=F9)4l7W z>$TvKb=(#8^JLKw1G~t$h&j89f6?FBfXI0ohD-;>Htc-Tj* zM0bFSgL>{_-{*Zq#!>7BHAmjJY4j9oBrA2RuBSOM4i~M&@mAaLdnKk?#18CvxtgsMpG&FTaX0_=DrAv z8M7@2TFnpJ9#OCg?dONuU+M9ftKJZ9QDnR9n`aMqcQ&GuD_zqOyUlh#`9v}7CuD3x zn1RWmbeQ~*s+#*S%&rEPJ7IK@QWzYq&Nm&oxzF}GKdVtb?LNizL=NR!E3{Znt>|ps zuequGDL6!g|DhSExjhai`*r~t zxXWGk>V*frU>1-7`}xJQiB1d2z&pr*PcXYLYLkpmidkWedPZcN+&T(9u-{<~L+UFG zb15w;a|wO^YiEeTR*IWoXGQHz7`N_&737>uTfE9G;Qdx62RHoDm=ErZdfSY9MfH{` z?w^KBjqv+w*@9GB&iCWJ*Z|m~q%Val2M78-o5cAGVG8!`AE47S*&g?_y1Zgi*MBZc z>3NCnbPQcv>W#IX+f8_!PrOwNN@MA~z?u8AN-XYrv~6sdgM!!+3lW6ydvv@4KP9V? z)r~{f9;YKR+X=G9=fVZ&-NEP-*&Lta@<4v}3K_!~MH+F5}f?NwEi8reek6EyL;VxT%P^Tgw~$eK!ll57Ls45Wrqb zM$AQ4h+$xDMcGdmt#T2kOh|tVc32zY0Yyn%HR(5dE=tytWkr!R+UHSUDTL(6#Gpr| z0>Xg@Gb9p;FaXjdd9?z^KDEIkU%>rsa^S`gg0UeTe!o4BYk~gHDM}Z5q7M;S} zYx-4YKb>0*74|$Y_~5?vOC8Jn!jQ9*ok^!@&z4$WgK22f*RVQt_i zB3^uQuc$f$LZRTQV~1j&A0IF#2W;JUJV=~-VHeq_QFhaUoLEwlR%RlcUFy&%C4~{P z9b;HAG&8^2VO%!g$0+!-LzOYV=YC%YdTsEQ6) zVnP*Qv?P(hK9POYF*z80Y z7qece{rK}m2*~Q_XCABOzVTdU9#0ZIh8Jl2JDuvs$jC#7<(vJUNe8J+-Rg`4KI8Ok zceD^|VynKN&zQ~DXJS3Cx2tkqe?PuJtcjkBt~}ZTvl#!PFl@6(mt(zZRs~{TU6QbE zgI>@WZ#ZL9_?gp&jtk%)`*Z!P2+lLW`tBEo_ih5fpL_PYDU(Lq-ui+$RVlP6=krH` z00{EgKy*QB^`Mlj~gG$UYIrZyMjP6?|!vCHE3 zQ#xYS7HTERduLP~gEsF@D*v8#AarL!{(gaNe_I)@nF%8@1QF+AI>0wO;GC9TxK#ni zz=AQ!k3Z`we5m3XO6WxWL_!FE%MBud20tpfS8R|b(r@||i-`ReQ&pF8HN+*;L=FEP z1%QDB>!!^e>p^t(*r$(G*PzjyPpU{8&)J4gt?F9t$hwf6?5_0Tnwp-+>EJNTK|N*< zr%Zk#-CU`uWNb48PGSK6I}8A;4`-%~&xONbl0$qX#=^%xlYK#tPXO5JxZ~T3&^Rkch-{V=Q2}~7U64p13t~B8yp3de4SsE zep1pa*NoY6Yt7oy^4@iOPl|K>T+N~RfhE&x4?zumgb@C0Jjgw4cLn?<30$(%0a>f2 zU@}W&rS;>1k-8E;<(Uq3ooqg=2~(}a-a`|={mkgU4tdEx$B6!z^LqYEx{HvmM6w4c z?>wKUzJ|xC0DZ|xog8ZO=f4hheZsliH{gi?)3K|?QzaKsamX$hVp&SYkaYd#!Jgr# z(mnROho^e0VBNq<_lZ1ePw-Z{8-3VwhRr#pM((seXkE?ERo3R~gEA(}mp-5;@M?*A;N(;Lcc|)V+riWt<|*Gue)B z7V4oRDQ*YQ-SNBUqIw$@_aHR8sD67s+Vyi!1&s~$%W+!6UoP^K_XI+agx~JN{Gl1x7E6 zWNRLs8$hZnJMu6Xq(NwJf=D7c?!`0}u%##g02}_p0l_W(=c8g7mIB;svl@*|Ofykp;zx}@7X0C+$oM7#P zrDE5E6cgmYC8ief(PDL3!Li}9gM3MgBx4G>ZWftge`iYZe0P+yT0rW?^2*8z551zL zVgt*Xn%%4IkS8qiGv^KFFr8l8!BvS`*teZ-Sdl9s>>28Wrxxr1i~a9UGnPNsmX=!0 z5@{T1w$%?j>v-JfOyJg*mBiI^B;)4kYOyGVs$)CG+OI-rWZtH$wDlr0=n*g9s+w2$ zLhb1(SG7G4dn}UvoSC53nz+;mJaA|<9P;YwC#xt_l@R9SaMk}N6(}HXl%rD-ztulz z$g5uIug3yHl7{sMAfUyk zaDVQWC5L8(T)hvH5Isw|i@4f+09zZw#i)JOv2r^3Em zM$?b~BZ_NpyJ8)IhTH;4F^0>dX%&o3u)f+K1@8?ywxcwtiRGV18_tZY=SKkkA+wTN zmv4HlwTOmgzz{T&fYN3I5piZ>gVqOsA)ucqW3!Rl-Gp34i^QpI1D@G(;OLf$&OO4( ziSFWG3^?P14d4JF@H5UfoL!zh=ZBQ)nc)GemG@QEV?T*htAkwZ0b!UI%Ib+fnq)4r zKxx7u0w&O3tr$=m_Dp!{w`qREfu{kVi*NMfTU#Z4S0%;sN z+XmBl7;8lcRCQAKbTw94(IJw`f&l8G`G*G6@#?B~Yj>{)jw$G;;Gn)`Qxw!{Y$`=V z_f-pF*4qQApcbN#=0P{BiTWxfONE>M&&gHC0D?0!?sB36eoAO`PAy%zGJVo}Smk%m z-S(F4!OB;Cy~r{nl-@4j{m#hnPYU8{g-#Zdvz*nm5xX`cxt9L3D5p|h+%5lmzgtb# zN52vL$Rm;pMdH~ir-$`h zS>P{92d%R?V$xNr{>;X!u5Oh=58$2xyEl<@t~$5Pwo#*c(if4GiLvaRQkMYNdt&^& zr-@QYezuu5E(I(w$X9{zMmEl587Gk_4xLJt`1rI2GwNP=dYFVDM2e*UX~Hx{BxZW} zq7WPZA4{jU-m_QXf#7kb#fpk%B~}=LQE3c_y8ZoRpDATdrcy3tF=VoK=^Nbr#E$X$ zFPn})S%@%}9roI`sc);o2kxV7_iA8QfHbks4K%aDRWV@->Wr-13mmf!B%JwqC+^G| z$Yw2=Q8AZi-@rnPI1>?(zL51X_i-zL_y=7z%oXkpWXtI8Hu@6j=mR9Vx_P~0G(B;7 zHqCv#=h9w@Wnxi6v4tmn9&UR3>fqd)=`yoECpT%iMudW#&|jo*UZrJ}s!N zhMN@V4n*Q7*??&8oeDv!x#r2o;_`Da`RQ+x3(-6W;%^ z&EF<%0(BxlYOD^ts6UPZpa_E!X2wf&!Z z@^1}}TnGDLXQ9q3V%ghatJE@cY=g&c_Z>GmrQS0~Jzd_J&h=yip*LFcU16Lc8xc7T zB5L7cc;+f#vwDqn}mn79mDy&CqU=q_jTI4aR{b7h%VZt>5i zCpF}q<|md=h?Yfgf7T*e>3KN93_Q{h-wR13JbS7H6|w5piAaCGS^I`*&ztS7ywa2S zyp9jkWmmih{8?1``g`ydU|sVD`}y z=@=nju$U!2#FTujByzuKDm#*esJD}v*3#*?J0QOyoi0`j*bIcCFiUcfRo?OaN}v2X zVrUb)z46`t{2_v|sf2P^{6rR;`NARUHbbJ+$e)=fr`L=-ko??j;)Qr=E;N8r6<=+| zwkGs+EZrrS@BHsVh`rhHZ=vgj{rG^lqqw-)jFew;c^1EbH>HX!@81m^-!FM@Jr+Aq z2}Ou9;W(ZSzd9`vt7+G0%<|-k+t1>m4>a zY=AF|ly{~-U_<<+#fu!g>qJPzdf&C>JL3&qhxc2JnPq;7p?$QJQ|#PDGxq1zT7RE8 zxt)ksdRxsO(}-ovn6fNC)q*S8i$qVx%?QYCC;cU!TYrtxe-+P3clS0m$$5THt5!4A z_A@_GeDLYYanA7mIyyX2f8mSAiG^RZQtyixXt))DTuU%XLSWuPs>mG*-O*eAn2`j& zqOm1TedpTY5)4GvVubLo9aCu~yBrJK+9@Fy_$5^mSt14jG~W%&)rpQ1iQITC$G`OZ z{7ap+v=t!p0C{4Ud+=*{?MeSsW=nhTClGL{>(G*A4BdVpIi%Izv-WN7kG*#ZpqZ|gukdZh62F333*tu#6wSe9uOB6Q9_#O2 zep37&L0seOILRIAcAV{`pT6InTwZQzFu%$;ee?cRUvF)Z6t-Oun^B1SY9%Bw(YEb( zuVQxgHeqcsuPa8}c^vQX&6=1~%uWIR4#D!m=JP1O;Op(2g~Vq^hFV%k&}eIlEQB>q z%+?3r=*u^ST6tfMKMK4ffb{&y3?3Q#TDN`9#*(`{L3>p#L`^-yOa!Xn8_K{Z&gU~1 zXEDxj76YfB8*)mWXS}ghMH|f{1XY@4cpQ}m#I_@HjYzK?BD7|FE~T(-z3t5S)!U6{ zNpv!XGf_27x*V!<@`##i4hw-UMMrS5S!1z1 zhL_AKIDqxV>0g<~##DS)msyvsh0h>`IXJxI2Q2&T`&5jojDv1H8RRM0F3dpFX?XR@ zIY%ViTCdc2C|=h7O9${)>Qsj?o-6naUp?RRzwF<*^NpV zx=3V3QmopsIO6kkw!qscU=N->08`BKB|D>;DZ{oqiM4#;l?hz6`L6?M7WK?b>P%^5 zgqjqP&g_FwyE!*1;gGKo6|Aw92A`~$Y@<{BA`r`x|Jqn?-!jA~L9U{U#qZ>EdQCKhZHjzBuRE7A z+$Ic@!)%MA%;_?_w8TqVj7hcIh~nD7BZ+SZvA~{x&UjiIihRdcA-?gE$dgaTxIMGKv_}$W@{EB& zA7a!0B?}6R3a$TCeo*@}lAzc<-WFZX&`fOSNn$d>H+*k9--AVI# z%JI+G5}ZGho*{F}No`_UTx;!rLYDBIM{DMcm4+T4APU zk>E>{subz@dOslCJ_<(_m9kCm^HsNaQ)px^+>3YkB*1)el}ka*h$%%q)dDe)4waT% z9e=wc(pog8D}=5a4t&To>jS%dqMw*;frM1ZI~4q^LmW*oaFa0DS2NzlDx_;LJ%I<<^UG7fZmDDKhxc3NX1m zdxj3;Es9nMt~)&E0{+LKWxcw#`DvCFO39R!c z@_;@qlDR%E=e>zCGJV<1z|rWBdDpR6pZH&iAFwFfy~l#XOjeGy)_0Qm6AT{d?3;7X zvDrl=Rm_DuA7u?iV}{8LV)Y#)Nz4>(R|J~t_a%ohZOnjXZJZqBcJ|*t(z+gECsoFR z89vO+4X6K(kuj`{6{HBgD!_hur3hB7h$)!B>A(UblGZjiafV+KA=X8K2J8t8<|sl?D0TqrxCJG0*I@@#W5&*~1T)@yZO>MNa3`m%%#G>wT{ z>Frc!!r*JKkV*X03Vz{Zs&o8|C_Y@NQhuiXFyMA_ex9R{|0H&DLI)dELscj`a`p(p z2i>4~GYm@c7^yNBm+L9e`q-ht5;sbEplLe%f5@ELl0?lxyV|GIEWe4DhYxgTWmSAF zPI9T5B9e_!tY4zm{Sz{}cPT4N-7t?oGMqA&pQTMXes|C7fZ!{x{Qb*})Rig6=$6XS z>e@fh(aEJ%qt8dl@v#gMaYIATXWb*Y{&HdUTeCo!AruG;{KR>q)%`HSaHaRlf~={W z`tt*meKq4OQ(==N^4kiR+vS>7o*&VPC8gcvmCn75#d$!1$f+?pjJPdZ_8NZQB~c`V z)Gbw(-a2cXr6mtNTdr0vk<|kYGpyx)cKbCofnDp%61J0^&pym=H^E@_?8!cH@mx}qq9{} zH#>#M2e`xF*3p3)T~lmuNAE=1zjr30N)6auN*^xjsN$KmPQQc+`|WJKcVE=>vkp1C zpug>j7oQRb3<7Q_$Jb@V{bGmfX(`R=?aU4_Qq#5MI6bG%KG{oYK)=zvG`mQ^2s#;OaMc#AooE@RzV(uW}V=puZ+O>h>$M z@Tv>Ns1^UjD)?Jde!VN6K(;`P@KoXw6h)_#{uw$F+hvHGT)|jr*mqsZo}>zz>#4!;yu>wQGMldvzi&{?$9oA+ggs;FWtc?K*=O@z?my+=^p z!Pm+RRA9Wlr2vXNGR~ytVG}bBdDByA)Q!@IAP3lc%ZsCjiO!|6bH>aV45#x=#M#k+ zBGT}66dA)ty9RWhrRPj3*@PhSF=3k{#$6*}tLa}mSyOnfCWSL;#*}n{Bc4DYQ~jhQ zyaYUZDyCF|)XnWzlK{@E$}dE2NGGhE^;lrqFBfE49sA z_QvZvo)J|wf9Jk+rN_6&qx^%j!Bbsk-KgBW>O+ZcUiQXiG=K*nRH=W(0}5mjPb2I0 z_8^VpNWOc*AqJwPf3CNIQbksXW9wazn0;lvSlRLR_9s^FJ%@puC$A111oEu>MlsHb z#*rQDVhJ@Zbaz{w$SWaU-zAnG)$G~_`W%F_@IP`t8Q&GJazJq48W5Rgpyh8II5t8j zQxRG?4UPp1I}75nQP6J#jIJ%zz+t*i-@-=2O1&tZ!oa%UrF6@kQ2X!{>eO*cYYClo z(*VnbVbN=doayZ`C^)DA@jM2kdYWy<47D1v)Ew_5GPAc49K-ahJ)>G`z~(JJC)^)w zqAK*dA=r86y#X?bLTxe9r@faQYF=_F8gRcrf2uVyD}-hD_ZlmNtB_U7Px8bA2ZnXE ziK8>ar2*CD!sfUR=Zxv}=n;}15=vZezR9%fUp%ncr2J}d1uqIu*GiRL?=Tt``9&^C`^cmsR?TKq+mKn*{j&02k`qPDwtDko zG!fYR**^YEHdux)f_%+QJDE`}hA;$b7DvCtc>r!peYU(_FDO86NVGD@s4RxiRTDuY z=j+bY@Ujt)Stsl^LF?853yGd?I3cbVOKdC&&ws}IgTso&H|A9zR*$apCwO8lrmMjd zX_cj4HFjul{pa|6p=J=KB~4fo>TYUt4MwLbW1WjxVO_3jl<1!UK0k%bl4tfA88J5e z{JYpPAYr009@I;R(nrL9B9?0$=KVCc`Y# zAvUU{T95+hF{%oyKdcPjY5>^2Z1?7r**>L&P*CA+ zcDYbToWgW#HHHyS=SW65`dLzpAQ$5$t5U#pR?m;M7RvIw1lC$+qpXmiKB$9BU$S|v z@t743MWs{iC1!$lQp{>+rMc*RJS}hhrr02Jw>x1yuRH}KIyC(sHx4Q%IUoSS!3~tk=QngP}!^uVwfYqM;Qzue|s(`9*S9A^HX{ue77X}&v ztVg`@%`F-1`9Bv=Y3u!SV-6-(9ADot@ZMCm4NjQNCvYtO{&a1EY`;!XsD*1IZ-LlU z=m2n`MA0-bM^7cVN#BLTV8!B3&CuhpEN4Hk`1#Sy+Dw|U+pbZpqDJ^a&H5`9{AF9Q zdcng&95mr5Q%>v~SC(Z|xF50{;r`&8nOhvYA%MxTfCr>RB!}HQ9mHL2bDH2@vbH3_ z7JZ%4XXliSgpAhH9>&zme_#O}{FILOJ`_#p9|m~_9_>%IYqd}`4N%SC^ml5z0=Vn> z3&$vfGU!8&u+c4ICM=UxjSujB8o$YJP$I=);X^@3bfJ)p&Mbo2Ix|Zu2pf%R$fQMC z)7L+qrOo$~Ca8}3o(nzklL&PY4?oFlHBiB!qBv>sR?rmzs#Ps#fqj&KoCF|8WfU~e zgg*9s4Ao3;z9$4!rZD}*vt)mKv@~k#Rx+w?&VZgaqtznf(H$Kfnp~VE36?VWxeQ<6 zvFy(-D1R&3nMw~%w)cd5bsblh<5V76l3|MA)ksVak)xe6xCA_8jsmC-xOpq;mHyNC z?)J9Ibi1HX$>rzvSJ}LaY=NG!0&Y{GMB+`*oIxLovMEe}_n1Ue>fb z>+S_SjIJE)6aJ8ixB+4c!0NdVu>ktt*eO{ z03=l4y5HxmMl^dZrxYkq+kzRGrl+FW@>)%GVBgZ(Jt8cJTT;$b(pdFcCMs6M|Dd>P z_1}rvD2$(M{G?i+<)3?Po-MsnMw52GeV8F&S^)jMXg`FN8;^(x-UtC;Q^CcM-lxwA+Ty$>{3i!K*Nsx} zgH1gfH-#sX{rCkXjn>2c{iN-8Pe6r|F2v?v9QKQ2sX|uEmT_%7ax4CZCOVn!v08Rz zSIZHK*MBOY+Eu2v zC#~ch=m)4FE=Bx5CM}dQX9s_2I6vvvO1OsiX{FpMZ9`;v5T9V%5QiEr^juw9&p(7O zRT{ebB51q-B$tJS2Hc}bEcS6MX|lo|HSgRLsIeKP^$%7N+W~nrW3A0RNM^`Wjl^ml zzdO$)Aknd`YPy8M|Cpedn?B7&=Bw|$j(rji>Qav?5&BELKHDc-nmBie{fo_2Pp$R$ zsd3{tYfXp&muy_`|xDWIO?&wJ6 z=`g5gq=L&$ zE#m`Kr;BLGwfNy}w4cgFxX^?i1ajOu0RO_`yitgyc^Ho&_>v5|j03&ouJq<)&~tsz zf~c-+JfHdXTM6^(zRKu5^Fbzr7Sf6H-amz&VGJ)Dglyf{7bJ_K3&mcgad#-xBNQuI z4;L5d;)tS$A$3eWUANPZx8HZEtSlHLqif^rg)ff9_IExv*FWRi+rw1Id;}6g?tJ4+ z{BJLSX&M(a78i>kp~T@fs?a*R&~0yT?>5zP*R+((KW5poy5u6Vq#wK1j1pFL2;l-% zqDwa$(86y$GM*;HxsIr>^n5<8F8fix)cU5rX0_ZiQLP>%`Hok0*OHJ1KNs`d9})N# z*uy>bSstd|-D&yjS|b#}!@Uy+3nzhHXQrYu?4Iq&0xLzYl)|?iqS#*6*@gd|RcK62 zWOCa@t7WL?5md`Z@P3N!+o9l(%D`G&b%g_r)Lj$Ims}@0{#OWRBl%?~VJBali9K>KJe+5gqq*Pmt;2`d`?( zhX}mul-+Nv+H01;Nz7dR83)df-GJ*O15BF0aOwu%|I5IT4s}Pkg3;h0zhXPh z5wbr~y^9a@aH{Gwx6NyYh{rT?_ z%6v@tN05kAxodH=H_}olJoBY#Rps)L18;9_vgK2Fy81Q!a5}vfYe$`ppTX6NW3t1G zKjWkAuKM#Bj-=c|`8S?7u78FV1_kiqJ?Y?86OO%9YNl7($18~Bu&KR5jC0a!BP1`C zECkL8!hzNIL(ct&Y8p^wb+v5O$ece_cI?gt%C8m3tnW!t^1sF|S~zVugJ_D2g*H%y zjvB)B&x2?vLy_(7?lVrwoBTK9mU5o??VXTxUilUMnsbQ())@CE7I(c_GcwRa?*e-U z4ZVwZ_y?XBZ0!cNN(sgrAN-bHTmHW0{D)ynqx2LWWVTL4`Z3lju(G+^GF{ZpG3H!kULm}P`>^AtHrsEm6E!Wwq-S0-&ZtQ< zB{HaiDjB?clToREJ#d2I=;d4fo+k0B_&28!BQuez-}XuI6zce`$-$G}mzguCbDz@j z?wyx+b4V>c#C`u;BbzB~@~*QQ&=4v&n~t61-u7E0VZqVf&3R~D=7w8kQ(2) zRg4^{5-1y8wtlrRPqWw`s=00$=nszYlrA2w75tqid<73zZ$1*Fyv0?$QKYjvme(=D z0jA0xUSl*l5anX@=#JaCelrnkhm=1@W~3Mnb65~r0TX8%@UY|d=Wa|L*t|A5%e3WNV%mJ$BaJ65I!TF6`_HY#>{ zopo?>GsZ0?o3_QYd6k%Y>lQHdxQMMf(v7<4kthxDnP}0xOG6TRPK}s76ASQhw%;-! z{^xud?tjzuK#H!KioE|4KKo&(9b1lEzhRxE-qz21u}S8b*@s`277}A632+1{VNwAs{zNG}zb^YBU_i|rR(Y+Q%6nqF*JpLlynv!Bw_uehy|>; z$UV5nvpv%c*^`$NXSWFgM8)G<_-j;5cErTp8@s5*oxp*bF2?gd31JT$E3_`P0uL&I zxu(k2^kWR`U+$V#HBza!83UfVBFB$*6m2kB{1{#Nljl zWM-f24t_;~wtZHY;UsUIkpP>|d&xY{SP(9;7)k)wK^_@t0|FYHk%!^d$Ib`4$d53} zwwR2Wa1vhiv1#F=K!Eu0ck-`&!>JYh*n!2mY!X}T1-&;9r_Y{=izXw9cLH?73axZ= zQ9mSy3+Gc(E#lHFgpMs1BWG@K0c5s>$glv1Ht@MMB}ytb;G5Kl{p;)NND9tBDiO!| zVJ^eHasUJ)8IkW06|0!4@E7-zzRMe7Y0f<$xkH%d-Y+_6 z;Bn(EG?w;?k2fRG460DjZ9H+XpoqKFWFoxvDQfz9^@cT^zJ(X(z+(EXUivI>>u_wb zMN6&8t1Q)e-@^vV0vmsU2qVA|TU96naDiNbAAri2FX0RDe^-JjHjV!LsFuyNv_-=JX})0kdmXrWx- z8{D?tB@##o*l^|xxf34!;-V)h*tD+eqiF6ghW-|`YQ>w4#f<(1G3W?TQ+Z_vO{^1C z>Cv0H;7q%c!9-a`HZhb}9qt+BN-%Y0bSnEW!YDv=qAcYfc!G1u6i}v`bw5>K;zF56 zYl6l$cIG_;CMTl>mk9cNR=QqndPm6@>Zw4w${=N{=n&Cn?Ha7a&%AxQ&uW%$7RWnX zR9#6K@iW7zfnC~WI8owE5ar4U+^%@a$6kPI`(pPJHg|1>S0YV-@j;R(vekzxrE%YM zo|e_D=|7sR)!eozCuYb>99OK>cS{Q8^A)8-T+^fTYzXwu-+*@KO6gCnl%cI3c3>eB z{tH{|h*?v$h6@gBX_M{!K5>*U7~{N*2dCAn?~vR(#%*87M7|lpO?g5tm&|v+ndOlR zX;0nOC!D@mQ~dP&;R)=Z1f@F7vx&N?O?(6GSpMHnoLtz)<>rGo3hlDic#9Gd!V3nw z9|6eX2_LzsF%eh}=C=kXm+%oZ-UlVCZ6rzd2!R@a7wkT)IWEB;%Xuh;X6buEtIHP( zhT{vN(HXol+TgNPR2Ak5K9Q>)(X)5d0sDj}O}n%1YNi%xahSe^@fYgD-2{FpLnLkl zyY7^33}qzt(nK#3AE=>s$Kzu}`IrKD2lg%Ko@Rlq6__`t0t3^A2`(dhCNEI{Ni@cB zm3lx8YOpnH;Jev@BUNY;^_As;XB&@ulGGYsIOTb1T3o+^%h*Zr?u8eupon-G9!&Lpof~bBu^$Uf^Tq}ukZ)=u^XbM*e^Rhy*Pgt6u{|=Cd}S;o zfak;sG!R9O0N(hIJA3?CjRdyRD-VpLRIr|+F7QkPC=jNV#F<63WyRw;=DI0EpB>tE z!lgd4XtPsMPiM4`@Ok8`e$Gz6w=(_|XvN{u3My%;9wxnPNH?O;3c3Cae5HjA7;iYM zfqpCoAIXrl%L1R=$WPJm*@~ZT4y9~|ADVxrFHHr0A}7L&+rxf9oKXZ=LOGEw8hE*8 zBFOzP+DL`_LtQaVUg3OSK2X1zSNoL_a+fu*Jl8ef3nP;IK!9S}IefhVR#u0*lC1)Z zC^fAdUg-*v<VEZH3jZ8ddQQ1WRs<3%hJ{l;+^kL*iK zOa1<$!}((&Fn$Vn6?drE{cU}Mj}f}Ti-J46whdMZIJL{;eVv}SVnD4JYSu+dKk=n7 zuc_SYv20y=%~Zw!33-xNj`~m;hb?|X{@3DrGB7Rx+;JsSRrm}mZLk^j_1YfTToR4KP{Yl49`XHj3)Vwk(#y=SF-vq@>y{kcE$98jWhk^Ix~ zad>V*=jn*6V~rvVTNItyGMAw1xpC3*us@e1UGbn3*T~#(D4xVb_dB&L;td6r|;Xj&1`#-(CX*iVaA2&Wy z(IVt76GisyCS<1=ijoq=STl@evXm`ksYXV~Z5unKY%vsuEMqGp8KViK1|!LgB}T+# ze@^%BIR3By$MfRpg%>e%o!51p=XHL*pXGb~TAG;{cs1De?{yil6Algx2$}0)H^rP3Y1gm0u@o7a3Sa)?|rK#XlhX^SMwq? z_CCExz3M9}wRw_{b?VbKHh1^H8CbrnjS!xmrMzEz88T@v+iJxXx_7!z*j$u^kj-?@fz&rhi~ryJaJzBVmU3LJcK@4G5c-=Jt=@S}&COh{rvz;g0y(>1 zYR0Ahg{!XI-X6DgQ{L7h^;OkAWa7`f2-O&If~>~wG3)fq-_&2>&hk!t3nMihx3PGL z)kO$_l>|P_4SuD95jZGg2YDw0@?KyW+gy`66|?)x4|Yy1|ep7!5*HRh$d|L^J; zYh)k3CoHwFI^wT&@#NhP4R}Jc9&6T_fk@ci-ro83>(}OmL!Cn4qqDMrj=O7MV6fNK z1+rm>K7==s*Q_nSuzMsv&^4j%5D&!E;SB^M+bso#`j0Gfx5EIhL=K>CcgK#E{ci$e z1d4k8m$=7xoi+de|0j3IvUcRWN@rsDQFW{FH@DwkK{2Annt}(i8soB8E_G|2%=)Gl z*nLQ~<#Qi-EJ0Xx0jkO-j==&u$@%2bKC%J?PMe%Dk^s}#vDN5eanQgc`xMP8&d4(c?Bv@gR*rCj={(mgI* z`WN7H7k@;ae6ZM|(p&TOqi$B?woV8Fn=QwkHAfuJ&JOipHp1%+)U9NS;wg=1A&1U$ zyV{fjlQ+0fB zAt&mwwNDZuWM7OhSEa0^7`462Y>n^hKM=k9Y}U{2`8$w-tgwSIVyFf93jIQvSi=^) z4u`$D=l(NnK_bjBrDP@z+-cRsues$y>X`!?W7p9J$ynwTYv9CMXyc(FHrmFbm^^wJ zUg4Ig81HpA@wc~R_*wH*8F-x!X8fs_(93fjyWSpKg$!paxc?%f%@}QvggqC=r~Y`Y zI8aOQb~}2tVoQdU70%w7CAM8fZy7+2*{Fv5#%4DxGuZv)i;(-poG2?vdI$8zeh5B6 z^QsO@Ur_ljWy}=b;DwLA0Pok*S-pi3SUnaVCq>-(P1f28cXv6+qf2QAj$q% zFQ>pFzr*Tslt%7!>+U_;Un1H(6YoaggS%@D`E zsU;-ehuX`$6GIZ1&Ytj8X~?33Wccf8-TEil9LVA)rQUJ>vWBhszgG)bG~-&oeL@Xy~>y;XtHp@6VzK;8t$Jp6p! z;~C5^^~#WmJmGimPohf)xj}7t4{)9{f)VHxk8dNFi@$^(+E;r5RdC!`y8z1&K~%HsIVa~K<)8~l(&*jN1y zhMCeFo)Ga<*)$fmd{qK7%&i@p&3}$`<;0>MMnELos=cHe)!J6*$`p?kXmwJ_6!-R; z+6P;vfO=q$c3L(EMw;gOy)~B9$Mn(CwJ5h-%?_-(CBG6U&^cs}8~Z#kP}@@QP9ft{ zfkkTtZO;o1kO⪚VXuyrs76 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

upODYw^JW=dW-^}B(Yvn{7 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 GZvQV4vtNe* diff --git a/docs/images/nf-core-datasync_logo_light.png b/docs/images/nf-core-datasync_logo_light.png index 3be10530437f2387c49cf833da548b1b11284e77..31788ebf53454c84fca68a96b901f1dd4296647c 100644 GIT binary patch delta 25527 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 delta 25457 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.04.0' version = '9.9.9' doi = 'https://doi.org/10.5281/zenodo.5070524' -} \ No newline at end of file +} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap index 10f948e..1037232 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap @@ -1,25 +1,41 @@ { "Test Function checkProfileProvided": { "content": null, - "timestamp": "2024-02-09T15:43:55.145717" + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:03.360873" }, "Test Function checkConfigProvided": { "content": [ true ], - "timestamp": "2024-01-19T11:34:13.548431224" + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:02:59.729647" }, "Test Function nfCoreLogo": { "content": [ "\n\n-\u001b[2m----------------------------------------------------\u001b[0m-\n \u001b[0;32m,--.\u001b[0;30m/\u001b[0;32m,-.\u001b[0m\n\u001b[0;34m ___ __ __ __ ___ \u001b[0;32m/,-._.--~'\u001b[0m\n\u001b[0;34m |\\ | |__ __ / ` / \\ |__) |__ \u001b[0;33m} {\u001b[0m\n\u001b[0;34m | \\| | \\__, \\__/ | \\ |___ \u001b[0;32m\\`-._,-`-,\u001b[0m\n \u001b[0;32m`._,._,'\u001b[0m\n\u001b[0;35m nextflow_workflow v9.9.9\u001b[0m\n-\u001b[2m----------------------------------------------------\u001b[0m-\n" ], - "timestamp": "2024-01-19T11:34:38.840454873" + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:10.562934" }, "Test Function workflowCitation": { "content": [ "If you use nextflow_workflow for your analysis please cite:\n\n* The pipeline\n https://doi.org/10.5281/zenodo.5070524\n\n* The nf-core framework\n https://doi.org/10.1038/s41587-020-0439-x\n\n* Software dependencies\n https://github.com/nextflow_workflow/blob/master/CITATIONS.md" ], - "timestamp": "2024-01-19T11:34:22.24352016" + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:07.019761" }, "Test Function without logColours": { "content": [ @@ -73,13 +89,21 @@ "biwhite": "" } ], - "timestamp": "2024-01-19T11:35:04.418416984" + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:17.969323" }, "Test Function dashedLine": { "content": [ "-\u001b[2m----------------------------------------------------\u001b[0m-" ], - "timestamp": "2024-01-19T11:34:55.420000755" + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:14.366181" }, "Test Function with logColours": { "content": [ @@ -133,6 +157,10 @@ "biwhite": "\u001b[1;97m" } ], - "timestamp": "2024-01-19T11:35:13.436366565" + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:21.714424" } } \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap index d07ce54..859d103 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.workflow.nf.test.snap @@ -10,6 +10,10 @@ ] } ], - "timestamp": "2024-01-19T11:35:22.538940073" + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:25.726491" } } \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test index 517ee54..5784a33 100644 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test +++ b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test @@ -197,4 +197,4 @@ nextflow_workflow { ) } } -} \ No newline at end of file +} From cb7bcafd5bf6046e87512308c1d5cd4b1be6775d Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Wed, 8 May 2024 13:58:15 +0000 Subject: [PATCH 003/334] Template update for nf-core/tools version 2.14.0 --- .editorconfig | 6 +- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/awsfulltest.yml | 10 +- .github/workflows/awstest.yml | 12 +- .github/workflows/ci.yml | 4 +- .github/workflows/download_pipeline.yml | 22 ++- .github/workflows/fix-linting.yml | 6 +- .github/workflows/linting.yml | 18 +- .github/workflows/linting_comment.yml | 2 +- .github/workflows/release-announcements.yml | 6 +- .nf-core.yml | 1 + .pre-commit-config.yaml | 3 + README.md | 2 +- conf/base.config | 3 - conf/modules.config | 8 - conf/test.config | 2 +- conf/test_full.config | 2 +- docs/usage.md | 2 + modules.json | 4 +- modules/nf-core/fastqc/main.nf | 6 + nextflow.config | 176 +++++++++--------- nextflow_schema.json | 7 + pyproject.toml | 15 -- .../utils_nfcore_datasync_pipeline/main.nf | 16 +- .../nf-core/utils_nfcore_pipeline/main.nf | 8 +- workflows/datasync.nf | 46 +++-- 26 files changed, 220 insertions(+), 169 deletions(-) delete mode 100644 pyproject.toml diff --git a/.editorconfig b/.editorconfig index dd9ffa5..72dda28 100644 --- a/.editorconfig +++ b/.editorconfig @@ -28,10 +28,6 @@ indent_style = unset [/assets/email*] indent_size = unset -# ignore Readme -[README.md] -indent_style = unset - -# ignore python +# ignore python and markdown [*.{py,md}] indent_style = unset diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 08d7669..ff8f68a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,7 +18,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/data - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/.github/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core lint`). -- [ ] Ensure the test suite passes (`nf-test test main.nf.test -profile test,docker`). +- [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). - [ ] Check for unexpected warnings in debug mode (`nextflow run . -profile debug,test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. - [ ] Output Documentation in `docs/output.md` is updated. diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 9724711..4edea42 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -8,12 +8,12 @@ on: types: [published] workflow_dispatch: jobs: - run-tower: + run-platform: name: Run AWS full tests if: github.repository == 'nf-core/datasync' runs-on: ubuntu-latest steps: - - name: Launch workflow via tower + - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 # TODO nf-core: You can customise AWS full pipeline tests as required # Add full size test data (but still relatively small datasets for few samples) @@ -33,7 +33,7 @@ jobs: - uses: actions/upload-artifact@v4 with: - name: Tower debug log file + name: Seqera Platform debug log file path: | - tower_action_*.log - tower_action_*.json + seqera_platform_action_*.log + seqera_platform_action_*.json diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 2aeceb1..bf4a3ee 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -5,13 +5,13 @@ name: nf-core AWS test on: workflow_dispatch: jobs: - run-tower: + run-platform: name: Run AWS tests if: github.repository == 'nf-core/datasync' runs-on: ubuntu-latest steps: - # Launch workflow using Tower CLI tool action - - name: Launch workflow via tower + # Launch workflow using Seqera Platform CLI tool action + - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 with: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} @@ -27,7 +27,7 @@ jobs: - uses: actions/upload-artifact@v4 with: - name: Tower debug log file + name: Seqera Platform debug log file path: | - tower_action_*.log - tower_action_*.json + seqera_platform_action_*.log + seqera_platform_action_*.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a8a037..3e85cf8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,10 +28,10 @@ jobs: - "latest-everything" steps: - name: Check out pipeline code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 + uses: nf-core/setup-nextflow@v2 with: version: "${{ matrix.NXF_VER }}" diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 08622fd..2d20d64 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -14,6 +14,8 @@ on: pull_request: types: - opened + - edited + - synchronize branches: - master pull_request_target: @@ -28,11 +30,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 + uses: nf-core/setup-nextflow@v2 - - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - name: Disk space cleanup + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 + + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: - python-version: "3.11" + python-version: "3.12" architecture: "x64" - uses: eWaterCycle/setup-singularity@931d4e31109e875b13309ae1d07c70ca8fbc8537 # v7 with: @@ -65,8 +70,17 @@ jobs: - name: Inspect download run: tree ./${{ env.REPOTITLE_LOWERCASE }} - - name: Run the downloaded pipeline + - name: Run the downloaded pipeline (stub) + id: stub_run_pipeline + continue-on-error: true env: NXF_SINGULARITY_CACHEDIR: ./ NXF_SINGULARITY_HOME_MOUNT: true run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -stub -profile test,singularity --outdir ./results + - name: Run the downloaded pipeline (stub run not supported) + id: run_pipeline + if: ${{ job.steps.stub_run_pipeline.status == failure() }} + env: + NXF_SINGULARITY_CACHEDIR: ./ + NXF_SINGULARITY_HOME_MOUNT: true + run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -profile test,singularity --outdir ./results diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml index e1813a5..e7e5b56 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix-linting.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 with: token: ${{ secrets.nf_core_bot_auth_token }} @@ -32,9 +32,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} # Install and run pre-commit - - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: - python-version: 3.11 + python-version: "3.12" - name: Install pre-commit run: pip install pre-commit diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 073e187..a3fb254 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -14,12 +14,12 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - - name: Set up Python 3.11 - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - name: Set up Python 3.12 + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: - python-version: 3.11 + python-version: "3.12" cache: "pip" - name: Install pre-commit @@ -32,14 +32,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - name: Install Nextflow - uses: nf-core/setup-nextflow@v1 + uses: nf-core/setup-nextflow@v2 - - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: - python-version: "3.11" + python-version: "3.12" architecture: "x64" - name: Install dependencies @@ -60,7 +60,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index b706875..40acc23 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@f6b0bace624032e30a85a8fd9c1a7f8f611f5737 # v3 + uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3 with: workflow: linting.yml workflow_conclusion: completed diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index d468aea..03ecfcf 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -12,7 +12,7 @@ jobs: - name: get topics and convert to hashtags id: get_topics run: | - curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ' >> $GITHUB_OUTPUT + echo "topics=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ')" >> $GITHUB_OUTPUT - uses: rzr/fediverse-action@master with: @@ -25,13 +25,13 @@ jobs: Please see the changelog: ${{ github.event.release.html_url }} - ${{ steps.get_topics.outputs.GITHUB_OUTPUT }} #nfcore #openscience #nextflow #bioinformatics + ${{ steps.get_topics.outputs.topics }} #nfcore #openscience #nextflow #bioinformatics send-tweet: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5 + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: python-version: "3.10" - name: Install dependencies diff --git a/.nf-core.yml b/.nf-core.yml index 3805dc8..d6daa40 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1 +1,2 @@ repository_type: pipeline +nf_core_version: "2.14.0" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af57081..4dc0f1d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,6 +3,9 @@ repos: rev: "v3.1.0" hooks: - id: prettier + additional_dependencies: + - prettier@3.2.5 + - repo: https://github.com/editorconfig-checker/editorconfig-checker.python rev: "2.7.3" hooks: diff --git a/README.md b/README.md index a57e162..71cc9fe 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ [![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://tower.nf/launch?pipeline=https://github.com/nf-core/datasync) +[![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/datasync) [![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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) diff --git a/conf/base.config b/conf/base.config index de5a3d9..3fe0aa6 100644 --- a/conf/base.config +++ b/conf/base.config @@ -59,7 +59,4 @@ process { errorStrategy = 'retry' maxRetries = 2 } - withName:CUSTOM_DUMPSOFTWAREVERSIONS { - cache = false - } } diff --git a/conf/modules.config b/conf/modules.config index e3ea8fa..d203d2b 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -22,14 +22,6 @@ process { ext.args = '--quiet' } - withName: CUSTOM_DUMPSOFTWAREVERSIONS { - publishDir = [ - path: { "${params.outdir}/pipeline_info" }, - mode: params.publish_dir_mode, - pattern: '*_versions.yml' - ] - } - withName: 'MULTIQC' { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ diff --git a/conf/test.config b/conf/test.config index d9e3341..0443309 100644 --- a/conf/test.config +++ b/conf/test.config @@ -22,7 +22,7 @@ params { // Input data // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = 'https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv' + input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv' // Genome references genome = 'R64-1-1' diff --git a/conf/test_full.config b/conf/test_full.config index 159a853..f11bc7e 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,7 +17,7 @@ params { // Input data for full size test // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = 'https://raw.githubusercontent.com/nf-core/test-datasets/viralrecon/samplesheet/samplesheet_full_illumina_amplicon.csv' + input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_full_illumina_amplicon.csv' // Genome references genome = 'R64-1-1' diff --git a/docs/usage.md b/docs/usage.md index 234441a..21a383f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -156,6 +156,8 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) - `apptainer` - 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. diff --git a/modules.json b/modules.json index 1c60c7a..1f795b3 100644 --- a/modules.json +++ b/modules.json @@ -7,7 +7,7 @@ "nf-core": { "fastqc": { "branch": "master", - "git_sha": "f4ae1d942bd50c5c0b9bd2de1393ce38315ba57c", + "git_sha": "285a50500f9e02578d90b3ce6382ea3c30216acd", "installed_by": ["modules"] }, "multiqc": { @@ -26,7 +26,7 @@ }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "git_sha": "92de218a329bfc9a9033116eb5f65fd270e72ba3", "installed_by": ["subworkflows"] }, "utils_nfvalidation_plugin": { diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 9e19a74..d79f1c8 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -25,6 +25,11 @@ process FASTQC { def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } def rename_to = old_new_pairs*.join(' ').join(' ') def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ') + + def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') + // FastQC memory value allowed range (100 - 10000) + def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) + """ printf "%s %s\\n" $rename_to | while read old_name new_name; do [ -f "\${new_name}" ] || ln -s \$old_name \$new_name @@ -33,6 +38,7 @@ process FASTQC { fastqc \\ $args \\ --threads $task.cpus \\ + --memory $fastqc_memory \\ $renamed_files cat <<-END_VERSIONS > versions.yml diff --git a/nextflow.config b/nextflow.config index 7b66a17..e227b16 100644 --- a/nextflow.config +++ b/nextflow.config @@ -16,7 +16,8 @@ params { genome = null igenomes_base = 's3://ngi-igenomes/igenomes/' igenomes_ignore = false - fasta = null// MultiQC options + + // MultiQC options multiqc_config = null multiqc_title = null multiqc_logo = null @@ -24,15 +25,16 @@ params { multiqc_methods_description = null // Boilerplate options - outdir = null - publish_dir_mode = 'copy' - email = null - email_on_fail = null - plaintext_email = false - monochrome_logs = false - hook_url = null - help = false - version = false + outdir = null + publish_dir_mode = 'copy' + email = null + email_on_fail = null + plaintext_email = false + monochrome_logs = false + hook_url = null + help = false + version = false + pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' // Config options config_profile_name = null @@ -68,103 +70,109 @@ try { } // Load nf-core/datasync custom profiles from different institutions. -// Warning: Uncomment only if a pipeline-specific institutional config already exists on nf-core/configs! -// try { -// includeConfig "${params.custom_config_base}/pipeline/datasync.config" -// } catch (Exception e) { -// System.err.println("WARNING: Could not load nf-core/config/datasync profiles: ${params.custom_config_base}/pipeline/datasync.config") -// } +try { + includeConfig "${params.custom_config_base}/pipeline/datasync.config" +} catch (Exception e) { + System.err.println("WARNING: Could not load nf-core/config/datasync profiles: ${params.custom_config_base}/pipeline/datasync.config") +} profiles { debug { - dumpHashes = true - process.beforeScript = 'echo $HOSTNAME' - cleanup = false + dumpHashes = true + process.beforeScript = 'echo $HOSTNAME' + cleanup = false nextflow.enable.configProcessNamesValidation = true } conda { - conda.enabled = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - channels = ['conda-forge', 'bioconda', 'defaults'] - apptainer.enabled = false + conda.enabled = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + conda.channels = ['conda-forge', 'bioconda', 'defaults'] + apptainer.enabled = false } mamba { - conda.enabled = true - conda.useMamba = true - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - apptainer.enabled = false + conda.enabled = true + conda.useMamba = true + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + apptainer.enabled = false } docker { - docker.enabled = true - conda.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - apptainer.enabled = false - docker.runOptions = '-u $(id -u):$(id -g)' + docker.enabled = true + conda.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + apptainer.enabled = false + docker.runOptions = '-u $(id -u):$(id -g)' } arm { - docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' + docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' } singularity { - singularity.enabled = true - singularity.autoMounts = true - conda.enabled = false - docker.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false - apptainer.enabled = false + singularity.enabled = true + singularity.autoMounts = true + conda.enabled = false + docker.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + apptainer.enabled = false } podman { - podman.enabled = true - conda.enabled = false - docker.enabled = false - singularity.enabled = false - shifter.enabled = false - charliecloud.enabled = false - apptainer.enabled = false + podman.enabled = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + shifter.enabled = false + charliecloud.enabled = false + apptainer.enabled = false } shifter { - shifter.enabled = true - conda.enabled = false - docker.enabled = false - singularity.enabled = false - podman.enabled = false - charliecloud.enabled = false - apptainer.enabled = false + shifter.enabled = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + podman.enabled = false + charliecloud.enabled = false + apptainer.enabled = false } charliecloud { - charliecloud.enabled = true - conda.enabled = false - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - apptainer.enabled = false + charliecloud.enabled = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + apptainer.enabled = false } apptainer { - apptainer.enabled = true - apptainer.autoMounts = true - conda.enabled = false - docker.enabled = false - singularity.enabled = false - podman.enabled = false - shifter.enabled = false - charliecloud.enabled = false + apptainer.enabled = true + apptainer.autoMounts = true + conda.enabled = false + docker.enabled = false + singularity.enabled = false + podman.enabled = false + shifter.enabled = false + charliecloud.enabled = false + } + wave { + apptainer.ociAutoPull = true + singularity.ociAutoPull = true + wave.enabled = true + wave.freeze = true + wave.strategy = 'conda,container' } gitpod { - executor.name = 'local' - executor.cpus = 4 - executor.memory = 8.GB + executor.name = 'local' + executor.cpus = 4 + executor.memory = 8.GB } test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } diff --git a/nextflow_schema.json b/nextflow_schema.json index dbf346f..d7abdbb 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -265,6 +265,13 @@ "description": "Validation of parameters in lenient more.", "hidden": true, "help_text": "Allows string values that are parseable as numbers or booleans. For further information see [JSONSchema docs](https://github.com/everit-org/json-schema#lenient-mode)." + }, + "pipelines_testdata_base_path": { + "type": "string", + "fa_icon": "far fa-check-circle", + "description": "Base URL or local path to location of pipeline test dataset files", + "default": "https://raw.githubusercontent.com/nf-core/test-datasets/", + "hidden": true } } } diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 5611062..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,15 +0,0 @@ -# Config file for Python. Mostly used to configure linting of bin/*.py with Ruff. -# Should be kept the same as nf-core/tools to avoid fighting with template synchronisation. -[tool.ruff] -line-length = 120 -target-version = "py38" -cache-dir = "~/.cache/ruff" - -[tool.ruff.lint] -select = ["I", "E1", "E4", "E7", "E9", "F", "UP", "N"] - -[tool.ruff.lint.isort] -known-first-party = ["nf_core"] - -[tool.ruff.lint.per-file-ignores] -"__init__.py" = ["E402", "F401"] diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 425f6dd..c1ba8c9 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -140,6 +140,10 @@ workflow PIPELINE_COMPLETION { imNotification(summary_params, hook_url) } } + + workflow.onError { + log.error "Pipeline failed. Please refer to troubleshooting docs: https://nf-co.re/docs/usage/troubleshooting" + } } /* @@ -230,8 +234,16 @@ def methodsDescriptionText(mqc_methods_yaml) { meta["manifest_map"] = workflow.manifest.toMap() // Pipeline DOI - meta["doi_text"] = meta.manifest_map.doi ? "(doi: ${meta.manifest_map.doi})" : "" - meta["nodoi_text"] = meta.manifest_map.doi ? "": "

  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " + if (meta.manifest_map.doi) { + // Using a loop to handle multiple DOIs + // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers + // Removing ` ` since the manifest.doi is a string and not a proper list + def temp_doi_ref = "" + String[] manifest_doi = meta.manifest_map.doi.tokenize(",") + for (String doi_ref: manifest_doi) temp_doi_ref += "(doi: ${doi_ref.replace("https://doi.org/", "").replace(" ", "")}), " + meta["doi_text"] = temp_doi_ref.substring(0, temp_doi_ref.length() - 2) + } else meta["doi_text"] = "" + meta["nodoi_text"] = meta.manifest_map.doi ? "" : "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " // Tool references meta["tool_citations"] = "" diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index a8b55d6..14558c3 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -65,9 +65,15 @@ def checkProfileProvided(nextflow_cli_args) { // Citation string for pipeline // def workflowCitation() { + def temp_doi_ref = "" + String[] manifest_doi = workflow.manifest.doi.tokenize(",") + // Using a loop to handle multiple DOIs + // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers + // Removing ` ` since the manifest.doi is a string and not a proper list + for (String doi_ref: manifest_doi) temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + "* The pipeline\n" + - " ${workflow.manifest.doi}\n\n" + + temp_doi_ref + "\n" + "* The nf-core framework\n" + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + "* Software dependencies\n" + diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 49f36c1..a1e07fe 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -40,22 +40,44 @@ workflow DATASYNC { // Collate and save software versions // softwareVersionsToYAML(ch_versions) - .collectFile(storeDir: "${params.outdir}/pipeline_info", name: 'nf_core_pipeline_software_mqc_versions.yml', sort: true, newLine: true) - .set { ch_collated_versions } + .collectFile( + storeDir: "${params.outdir}/pipeline_info", + name: 'nf_core_pipeline_software_mqc_versions.yml', + sort: true, + newLine: true + ).set { ch_collated_versions } // // MODULE: MultiQC // - ch_multiqc_config = Channel.fromPath("$projectDir/assets/multiqc_config.yml", checkIfExists: true) - ch_multiqc_custom_config = params.multiqc_config ? Channel.fromPath(params.multiqc_config, checkIfExists: true) : Channel.empty() - ch_multiqc_logo = params.multiqc_logo ? Channel.fromPath(params.multiqc_logo, checkIfExists: true) : Channel.empty() - summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") - ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) - ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) - ch_methods_description = Channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) - ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) - ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) - ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml', sort: false)) + ch_multiqc_config = Channel.fromPath( + "$projectDir/assets/multiqc_config.yml", checkIfExists: true) + ch_multiqc_custom_config = params.multiqc_config ? + Channel.fromPath(params.multiqc_config, checkIfExists: true) : + Channel.empty() + ch_multiqc_logo = params.multiqc_logo ? + Channel.fromPath(params.multiqc_logo, checkIfExists: true) : + Channel.empty() + + summary_params = paramsSummaryMap( + workflow, parameters_schema: "nextflow_schema.json") + ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) + + ch_multiqc_custom_methods_description = params.multiqc_methods_description ? + file(params.multiqc_methods_description, checkIfExists: true) : + file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) + ch_methods_description = Channel.value( + methodsDescriptionText(ch_multiqc_custom_methods_description)) + + ch_multiqc_files = ch_multiqc_files.mix( + ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) + ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) + ch_multiqc_files = ch_multiqc_files.mix( + ch_methods_description.collectFile( + name: 'methods_description_mqc.yaml', + sort: true + ) + ) MULTIQC ( ch_multiqc_files.collect(), From 15bc72a032a170a80e44560503f2d35313fcaa8d Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 9 May 2024 11:40:23 +0000 Subject: [PATCH 004/334] Template update for nf-core/tools version 2.14.1 --- .github/workflows/linting.yml | 1 - .nf-core.yml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index a3fb254..1fcafe8 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -20,7 +20,6 @@ jobs: uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 with: python-version: "3.12" - cache: "pip" - name: Install pre-commit run: pip install pre-commit diff --git a/.nf-core.yml b/.nf-core.yml index d6daa40..e0b85a7 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,2 +1,2 @@ repository_type: pipeline -nf_core_version: "2.14.0" +nf_core_version: "2.14.1" From f1ceb78d6258c96bbc9088bd2d30f7f885a90ef2 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 8 Oct 2024 12:30:43 +0000 Subject: [PATCH 005/334] Template update for nf-core/tools version 3.0.0 --- .editorconfig | 4 + .github/CONTRIBUTING.md | 10 +- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/awsfulltest.yml | 23 +- .github/workflows/ci.yml | 17 +- .github/workflows/download_pipeline.yml | 53 ++- .github/workflows/linting.yml | 23 +- .github/workflows/linting_comment.yml | 2 +- .github/workflows/release-announcements.yml | 2 +- .../workflows/template_version_comment.yml | 43 ++ .gitpod.yml | 7 +- .nf-core.yml | 17 +- .pre-commit-config.yaml | 2 +- .prettierignore | 1 + CITATIONS.md | 4 +- README.md | 5 +- assets/schema_input.json | 2 +- conf/base.config | 34 +- conf/igenomes_ignored.config | 9 + conf/modules.config | 1 - conf/test.config | 13 +- docs/images/mqc_fastqc_adapter.png | Bin 23458 -> 0 bytes docs/images/mqc_fastqc_counts.png | Bin 33918 -> 0 bytes docs/images/mqc_fastqc_quality.png | Bin 55769 -> 0 bytes docs/output.md | 11 +- docs/usage.md | 12 +- main.nf | 10 +- modules.json | 12 +- modules/nf-core/fastqc/environment.yml | 2 - modules/nf-core/fastqc/main.nf | 5 +- modules/nf-core/fastqc/meta.yml | 57 +-- modules/nf-core/fastqc/tests/main.nf.test | 225 ++++++++--- .../nf-core/fastqc/tests/main.nf.test.snap | 370 ++++++++++++++++-- modules/nf-core/multiqc/environment.yml | 4 +- modules/nf-core/multiqc/main.nf | 14 +- modules/nf-core/multiqc/meta.yml | 78 ++-- modules/nf-core/multiqc/tests/main.nf.test | 8 + .../nf-core/multiqc/tests/main.nf.test.snap | 20 +- modules/nf-core/multiqc/tests/nextflow.config | 5 + nextflow.config | 146 ++++--- nextflow_schema.json | 85 +--- .../utils_nfcore_datasync_pipeline/main.nf | 56 +-- .../nf-core/utils_nextflow_pipeline/main.nf | 24 +- .../tests/nextflow.config | 2 +- .../nf-core/utils_nfcore_pipeline/main.nf | 45 ++- .../nf-core/utils_nfschema_plugin/main.nf | 46 +++ .../nf-core/utils_nfschema_plugin/meta.yml | 35 ++ .../utils_nfschema_plugin/tests/main.nf.test | 117 ++++++ .../tests/nextflow.config | 8 + .../tests/nextflow_schema.json | 8 +- .../nf-core/utils_nfvalidation_plugin/main.nf | 62 --- .../utils_nfvalidation_plugin/meta.yml | 44 --- .../tests/main.nf.test | 200 ---------- .../utils_nfvalidation_plugin/tests/tags.yml | 2 - workflows/datasync.nf | 23 +- 55 files changed, 1204 insertions(+), 806 deletions(-) create mode 100644 .github/workflows/template_version_comment.yml create mode 100644 conf/igenomes_ignored.config delete mode 100755 docs/images/mqc_fastqc_adapter.png delete mode 100755 docs/images/mqc_fastqc_counts.png delete mode 100755 docs/images/mqc_fastqc_quality.png create mode 100644 modules/nf-core/multiqc/tests/nextflow.config create mode 100644 subworkflows/nf-core/utils_nfschema_plugin/main.nf create mode 100644 subworkflows/nf-core/utils_nfschema_plugin/meta.yml create mode 100644 subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test create mode 100644 subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config rename subworkflows/nf-core/{utils_nfvalidation_plugin => utils_nfschema_plugin}/tests/nextflow_schema.json (95%) delete mode 100644 subworkflows/nf-core/utils_nfvalidation_plugin/main.nf delete mode 100644 subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml delete mode 100644 subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test delete mode 100644 subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml diff --git a/.editorconfig b/.editorconfig index 72dda28..e105881 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,6 +11,7 @@ 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 @@ -25,9 +26,12 @@ 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 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5402f7f..e904891 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -19,7 +19,7 @@ If you'd like to write some code for nf-core/datasync, the standard workflow is 1. Check that there isn't already an issue about your idea in the [nf-core/datasync issues](https://github.com/nf-core/datasync/issues) to avoid duplicating work. If there isn't one already, please create one so that others know you're working on this 2. [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [nf-core/datasync repository](https://github.com/nf-core/datasync) to your GitHub account 3. Make the necessary changes / additions within your forked repository following [Pipeline conventions](#pipeline-contribution-conventions) -4. Use `nf-core schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). +4. Use `nf-core pipelines schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). 5. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged If you're not used to this workflow with git, you can start with some [docs from GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests) or even their [excellent `git` resources](https://try.github.io/). @@ -40,7 +40,7 @@ There are typically two types of tests that run: ### Lint tests `nf-core` has a [set of guidelines](https://nf-co.re/developers/guidelines) which all pipelines must adhere to. -To enforce these and ensure that all pipelines stay in sync, we have developed a helper tool which runs checks on the pipeline code. This is in the [nf-core/tools repository](https://github.com/nf-core/tools) and once installed can be run locally with the `nf-core lint ` command. +To enforce these and ensure that all pipelines stay in sync, we have developed a helper tool which runs checks on the pipeline code. This is in the [nf-core/tools repository](https://github.com/nf-core/tools) and once installed can be run locally with the `nf-core pipelines lint ` command. If any failures or warnings are encountered, please follow the listed URL for more documentation. @@ -75,7 +75,7 @@ If you wish to contribute a new step, please use the following coding standards: 2. Write the process block (see below). 3. Define the output channel if needed (see below). 4. Add any new parameters to `nextflow.config` with a default (see below). -5. Add any new parameters to `nextflow_schema.json` with help text (via the `nf-core schema build` tool). +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`. @@ -86,7 +86,7 @@ If you wish to contribute a new step, please use the following coding standards: Parameters should be initialised / defined with default values in `nextflow.config` under the `params` scope. -Once there, use `nf-core schema build` to add to `nextflow_schema.json`. +Once there, use `nf-core pipelines schema build` to add to `nextflow_schema.json`. ### Default processes resource requirements @@ -103,7 +103,7 @@ Please use the following naming schemes, to make it easy to understand what is g ### Nextflow version bumping -If you are using a new feature from core Nextflow, you may bump the minimum required version of nextflow in the pipeline with: `nf-core bump-version --nextflow . [min-nf-version]` +If you are using a new feature from core Nextflow, you may bump the minimum required version of nextflow in the pipeline with: `nf-core pipelines bump-version --nextflow . [min-nf-version]` ### Images and figures diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ff8f68a..68ec5da 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,7 +17,7 @@ Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/data - [ ] If you've fixed a bug or added code that should be tested, add tests! - [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/.github/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. -- [ ] Make sure your code lints (`nf-core lint`). +- [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). - [ ] Check for unexpected warnings in debug mode (`nextflow run . -profile debug,test,docker --outdir `). - [ ] Usage Documentation in `docs/usage.md` is updated. diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 4edea42..2f90ed1 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -1,18 +1,33 @@ name: nf-core AWS full size tests -# This workflow is triggered on published releases. +# This workflow is triggered on PRs opened against the master branch. # It can be additionally triggered manually with GitHub actions workflow dispatch button. # It runs the -profile 'test_full' on AWS batch on: - release: - types: [published] + pull_request: + branches: + - master workflow_dispatch: + pull_request_review: + types: [submitted] + jobs: run-platform: name: Run AWS full tests - if: github.repository == 'nf-core/datasync' + if: github.repository == 'nf-core/datasync' && github.event.review.state == 'approved' runs-on: ubuntu-latest steps: + - uses: octokit/request-action@v2.x + id: check_approvals + with: + route: GET /repos/${{ github.repository }}/pulls/${{ github.event.review.number }}/reviews + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - id: test_variables + run: | + JSON_RESPONSE='${{ steps.check_approvals.outputs.data }}' + CURRENT_APPROVALS_COUNT=$(echo $JSON_RESPONSE | jq -c '[.[] | select(.state | contains("APPROVED")) ] | length') + test $CURRENT_APPROVALS_COUNT -ge 2 || exit 1 # At least 2 approvals are required - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 # TODO nf-core: You can customise AWS full pipeline tests as required diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e85cf8..0775ffc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,7 @@ on: pull_request: release: types: [published] + workflow_dispatch: env: NXF_ANSI_LOG: false @@ -24,7 +25,7 @@ jobs: strategy: matrix: NXF_VER: - - "23.04.0" + - "24.04.2" - "latest-everything" steps: - name: Check out pipeline code @@ -38,9 +39,21 @@ jobs: - name: Disk space cleanup uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - name: Run pipeline with test data + - name: Run pipeline with test data (docker) # TODO nf-core: You can customise CI pipeline run tests as required # For example: adding multiple test runs with different parameters # Remember that you can parallelise this by using strategy.matrix run: | nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results + + - name: Run pipeline with test data (singularity) + # TODO nf-core: You can customise CI pipeline run tests as required + run: | + nextflow run ${GITHUB_WORKSPACE} -profile test,singularity --outdir ./results + if: "${{ github.base_ref == 'master' }}" + + - name: Run pipeline with test data (conda) + # TODO nf-core: You can customise CI pipeline run tests as required + run: | + nextflow run ${GITHUB_WORKSPACE} -profile test,conda --outdir ./results + if: "${{ github.base_ref == 'master' }}" diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 2d20d64..713dc3e 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -1,4 +1,4 @@ -name: Test successful pipeline download with 'nf-core download' +name: Test successful pipeline download with 'nf-core pipelines download' # Run the workflow when: # - dispatched manually @@ -8,7 +8,7 @@ on: workflow_dispatch: inputs: testbranch: - description: "The specific branch you wish to utilize for the test execution of nf-core download." + description: "The specific branch you wish to utilize for the test execution of nf-core pipelines download." required: true default: "dev" pull_request: @@ -39,9 +39,11 @@ jobs: with: python-version: "3.12" architecture: "x64" - - uses: eWaterCycle/setup-singularity@931d4e31109e875b13309ae1d07c70ca8fbc8537 # v7 + + - name: Setup Apptainer + uses: eWaterCycle/setup-apptainer@4bb22c52d4f63406c49e94c804632975787312b3 # v2.0.0 with: - singularity-version: 3.8.3 + apptainer-version: 1.3.4 - name: Install dependencies run: | @@ -54,33 +56,64 @@ jobs: echo "REPOTITLE_LOWERCASE=$(basename ${GITHUB_REPOSITORY,,})" >> ${GITHUB_ENV} echo "REPO_BRANCH=${{ github.event.inputs.testbranch || 'dev' }}" >> ${GITHUB_ENV} + - name: Make a cache directory for the container images + run: | + mkdir -p ./singularity_container_images + - name: Download the pipeline env: - NXF_SINGULARITY_CACHEDIR: ./ + NXF_SINGULARITY_CACHEDIR: ./singularity_container_images run: | - nf-core download ${{ env.REPO_LOWERCASE }} \ + nf-core pipelines download ${{ env.REPO_LOWERCASE }} \ --revision ${{ env.REPO_BRANCH }} \ --outdir ./${{ env.REPOTITLE_LOWERCASE }} \ --compress "none" \ --container-system 'singularity' \ - --container-library "quay.io" -l "docker.io" -l "ghcr.io" \ + --container-library "quay.io" -l "docker.io" -l "community.wave.seqera.io" \ --container-cache-utilisation 'amend' \ - --download-configuration + --download-configuration 'yes' - name: Inspect download run: tree ./${{ env.REPOTITLE_LOWERCASE }} + - name: Count the downloaded number of container images + id: count_initial + run: | + image_count=$(ls -1 ./singularity_container_images | wc -l | xargs) + echo "Initial container image count: $image_count" + echo "IMAGE_COUNT_INITIAL=$image_count" >> ${GITHUB_ENV} + - name: Run the downloaded pipeline (stub) id: stub_run_pipeline continue-on-error: true env: - NXF_SINGULARITY_CACHEDIR: ./ + NXF_SINGULARITY_CACHEDIR: ./singularity_container_images NXF_SINGULARITY_HOME_MOUNT: true run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -stub -profile test,singularity --outdir ./results - name: Run the downloaded pipeline (stub run not supported) id: run_pipeline if: ${{ job.steps.stub_run_pipeline.status == failure() }} env: - NXF_SINGULARITY_CACHEDIR: ./ + NXF_SINGULARITY_CACHEDIR: ./singularity_container_images NXF_SINGULARITY_HOME_MOUNT: true run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -profile test,singularity --outdir ./results + + - name: Count the downloaded number of container images + id: count_afterwards + run: | + image_count=$(ls -1 ./singularity_container_images | wc -l | xargs) + echo "Post-pipeline run container image count: $image_count" + echo "IMAGE_COUNT_AFTER=$image_count" >> ${GITHUB_ENV} + + - name: Compare container image counts + run: | + if [ "${{ env.IMAGE_COUNT_INITIAL }}" -ne "${{ env.IMAGE_COUNT_AFTER }}" ]; then + initial_count=${{ env.IMAGE_COUNT_INITIAL }} + final_count=${{ env.IMAGE_COUNT_AFTER }} + difference=$((final_count - initial_count)) + echo "$difference additional container images were \n downloaded at runtime . The pipeline has no support for offline runs!" + tree ./singularity_container_images + exit 1 + else + echo "The pipeline can be downloaded successfully!" + fi diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 1fcafe8..b882838 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -1,6 +1,6 @@ name: nf-core linting # This workflow is triggered on pushes and PRs to the repository. -# It runs the `nf-core lint` and markdown lint tests to ensure +# It runs the `nf-core pipelines lint` and markdown lint tests to ensure # that the code meets the nf-core guidelines. on: push: @@ -41,17 +41,32 @@ jobs: python-version: "3.12" architecture: "x64" + - name: read .nf-core.yml + uses: pietrobolcato/action-read-yaml@1.0.0 + id: read_yml + with: + config: ${{ github.workspace }}/.nf-core.yaml + - name: Install dependencies run: | python -m pip install --upgrade pip - pip install nf-core + pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} + + - name: Run nf-core pipelines lint + if: ${{ github.base_ref != 'master' }} + env: + GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_PR_COMMIT: ${{ github.event.pull_request.head.sha }} + run: nf-core -l lint_log.txt pipelines lint --dir ${GITHUB_WORKSPACE} --markdown lint_results.md - - name: Run nf-core lint + - name: Run nf-core pipelines lint --release + if: ${{ github.base_ref == 'master' }} env: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_PR_COMMIT: ${{ github.event.pull_request.head.sha }} - run: nf-core -l lint_log.txt lint --dir ${GITHUB_WORKSPACE} --markdown lint_results.md + run: nf-core -l lint_log.txt pipelines lint --release --dir ${GITHUB_WORKSPACE} --markdown lint_results.md - name: Save PR number if: ${{ always() }} diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 40acc23..42e519b 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@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3 + uses: dawidd6/action-download-artifact@bf251b5aa9c2f7eeb574a96ee720e24f801b7c11 # v6 with: workflow: linting.yml workflow_conclusion: completed diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 03ecfcf..c6ba35d 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -12,7 +12,7 @@ jobs: - name: get topics and convert to hashtags id: get_topics run: | - echo "topics=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ')" >> $GITHUB_OUTPUT + echo "topics=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ')" | sed 's/-//g' >> $GITHUB_OUTPUT - uses: rzr/fediverse-action@master with: diff --git a/.github/workflows/template_version_comment.yml b/.github/workflows/template_version_comment.yml new file mode 100644 index 0000000..9dea41f --- /dev/null +++ b/.github/workflows/template_version_comment.yml @@ -0,0 +1,43 @@ +name: nf-core template version comment +# This workflow is triggered on PRs to check if the pipeline template version matches the latest nf-core version. +# It posts a comment to the PR, even if it comes from a fork. + +on: pull_request_target + +jobs: + template_version: + runs-on: ubuntu-latest + steps: + - name: Check out pipeline code + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 + + - name: Read template version from .nf-core.yml + uses: pietrobolcato/action-read-yaml@1.0.0 + id: read_yml + with: + config: ${{ github.workspace }}/.nf-core.yml + + - name: Install nf-core + run: | + python -m pip install --upgrade pip + pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} + + - name: Check nf-core outdated + id: nf_core_outdated + run: pip list --outdated | grep nf-core + + - name: Post nf-core template version comment + uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 + if: | + ${{ steps.nf_core_outdated.outputs.stdout }} =~ 'nf-core' + with: + repo-token: ${{ secrets.NF_CORE_BOT_AUTH_TOKEN }} + allow-repeats: false + message: | + ## :warning: Newer version of the nf-core template is available. + + Your pipeline is using an old version of the nf-core template: ${{ steps.read_yml.outputs['nf_core_version'] }}. + Please update your pipeline to the latest version. + + For more documentation on how to update your pipeline, please see the [nf-core documentation](https://github.com/nf-core/tools?tab=readme-ov-file#sync-a-pipeline-with-the-template) and [Synchronisation documentation](https://nf-co.re/docs/contributing/sync). + # diff --git a/.gitpod.yml b/.gitpod.yml index 105a182..4611863 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -4,17 +4,14 @@ tasks: command: | pre-commit install --install-hooks nextflow self-update - - name: unset JAVA_TOOL_OPTIONS - command: | - unset JAVA_TOOL_OPTIONS vscode: extensions: # based on nf-core.nf-core-extensionpack - - esbenp.prettier-vscode # Markdown/CommonMark linting and style checking for Visual Studio Code + #- esbenp.prettier-vscode # Markdown/CommonMark linting and style checking for Visual Studio Code - EditorConfig.EditorConfig # override user/workspace settings with settings found in .editorconfig files - Gruntfuggly.todo-tree # Display TODO and FIXME in a tree view in the activity bar - mechatroner.rainbow-csv # Highlight columns in csv files in different colors - # - nextflow.nextflow # Nextflow syntax highlighting + - nextflow.nextflow # Nextflow syntax highlighting - oderwat.indent-rainbow # Highlight indentation level - streetsidesoftware.code-spell-checker # Spelling checker for source code - charliermarsh.ruff # Code linter Ruff diff --git a/.nf-core.yml b/.nf-core.yml index e0b85a7..020096b 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,2 +1,17 @@ +bump_version: null +lint: null +nf_core_version: 3.0.0 +org_path: null repository_type: pipeline -nf_core_version: "2.14.1" +template: + author: Alexander Peltzer + description: A simple sysops pipeline that can be used to synchronize, integrity + check and permanently archive data. + force: false + is_nfcore: true + name: datasync + org: nf-core + outdir: . + skip_features: null + version: 1.0dev +update: null diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4dc0f1d..9e9f0e1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - prettier@3.2.5 - repo: https://github.com/editorconfig-checker/editorconfig-checker.python - rev: "2.7.3" + rev: "3.0.3" hooks: - id: editorconfig-checker alias: ec diff --git a/.prettierignore b/.prettierignore index 437d763..610e506 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,4 @@ + email_template.html adaptivecard.json slackreport.json diff --git a/CITATIONS.md b/CITATIONS.md index b2a7707..3032c6f 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -12,11 +12,11 @@ - [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) - > Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. +> Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. - [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) - > Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. +> Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. ## Software packaging/containerisation tools diff --git a/README.md b/README.md index 71cc9fe..ae71bb4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![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%A523.04.0-23aa62.svg)](https://www.nextflow.io/) +[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A524.04.2-23aa62.svg)](https://www.nextflow.io/) [![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/) @@ -67,8 +67,7 @@ nextflow run nf-core/datasync \ ``` > [!WARNING] -> 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/usage/configuration#custom-configuration-files). +> 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). For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/parameters). diff --git a/assets/schema_input.json b/assets/schema_input.json index 160d278..3147ec3 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://raw.githubusercontent.com/nf-core/datasync/master/assets/schema_input.json", "title": "nf-core/datasync pipeline - params.input schema", "description": "Schema for the file provided with params.input", diff --git a/conf/base.config b/conf/base.config index 3fe0aa6..6b945e8 100644 --- a/conf/base.config +++ b/conf/base.config @@ -11,9 +11,9 @@ process { // TODO nf-core: Check the defaults for all processes - cpus = { check_max( 1 * task.attempt, 'cpus' ) } - memory = { check_max( 6.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } + cpus = { 1 * task.attempt } + memory = { 6.GB * task.attempt } + time = { 4.h * task.attempt } errorStrategy = { task.exitStatus in ((130..145) + 104) ? 'retry' : 'finish' } maxRetries = 1 @@ -27,30 +27,30 @@ process { // TODO nf-core: Customise requirements for specific processes. // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors withLabel:process_single { - cpus = { check_max( 1 , 'cpus' ) } - memory = { check_max( 6.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } + cpus = { 1 } + memory = { 6.GB * task.attempt } + time = { 4.h * task.attempt } } withLabel:process_low { - cpus = { check_max( 2 * task.attempt, 'cpus' ) } - memory = { check_max( 12.GB * task.attempt, 'memory' ) } - time = { check_max( 4.h * task.attempt, 'time' ) } + cpus = { 2 * task.attempt } + memory = { 12.GB * task.attempt } + time = { 4.h * task.attempt } } withLabel:process_medium { - cpus = { check_max( 6 * task.attempt, 'cpus' ) } - memory = { check_max( 36.GB * task.attempt, 'memory' ) } - time = { check_max( 8.h * task.attempt, 'time' ) } + cpus = { 6 * task.attempt } + memory = { 36.GB * task.attempt } + time = { 8.h * task.attempt } } withLabel:process_high { - cpus = { check_max( 12 * task.attempt, 'cpus' ) } - memory = { check_max( 72.GB * task.attempt, 'memory' ) } - time = { check_max( 16.h * task.attempt, 'time' ) } + cpus = { 12 * task.attempt } + memory = { 72.GB * task.attempt } + time = { 16.h * task.attempt } } withLabel:process_long { - time = { check_max( 20.h * task.attempt, 'time' ) } + time = { 20.h * task.attempt } } withLabel:process_high_memory { - memory = { check_max( 200.GB * task.attempt, 'memory' ) } + memory = { 200.GB * task.attempt } } withLabel:error_ignore { errorStrategy = 'ignore' diff --git a/conf/igenomes_ignored.config b/conf/igenomes_ignored.config new file mode 100644 index 0000000..b4034d8 --- /dev/null +++ b/conf/igenomes_ignored.config @@ -0,0 +1,9 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for iGenomes paths +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Empty genomes dictionary to use when igenomes is ignored. +---------------------------------------------------------------------------------------- +*/ + +params.genomes = [:] diff --git a/conf/modules.config b/conf/modules.config index d203d2b..d266a38 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -21,7 +21,6 @@ process { withName: FASTQC { ext.args = '--quiet' } - withName: 'MULTIQC' { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ diff --git a/conf/test.config b/conf/test.config index 0443309..7f9aa8a 100644 --- a/conf/test.config +++ b/conf/test.config @@ -10,15 +10,18 @@ ---------------------------------------------------------------------------------------- */ +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '1.h' + ] +} + params { config_profile_name = 'Test profile' config_profile_description = 'Minimal test dataset to check pipeline function' - // Limit resources so that this can run on GitHub Actions - max_cpus = 2 - max_memory = '6.GB' - max_time = '6.h' - // Input data // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets // TODO nf-core: Give any required params for the test so that command line flags are not needed diff --git a/docs/images/mqc_fastqc_adapter.png b/docs/images/mqc_fastqc_adapter.png deleted file mode 100755 index 361d0e47acfb424dea1f326590d1eb2f6dfa26b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23458 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 diff --git a/docs/images/mqc_fastqc_quality.png b/docs/images/mqc_fastqc_quality.png deleted file mode 100755 index a4b89bf56ab2ba88cab87841916eb680a816deae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55769 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�)v~C(0C)c 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 M)78&qol`;+0Fu7JivR!s diff --git a/docs/output.md b/docs/output.md index 1c847a5..3734de7 100644 --- a/docs/output.md +++ b/docs/output.md @@ -14,6 +14,7 @@ The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes d - [FastQC](#fastqc) - Raw read QC - [MultiQC](#multiqc) - Aggregate report describing results and QC from the whole pipeline + - [Pipeline information](#pipeline-information) - Report metrics generated during the workflow execution ### FastQC @@ -29,16 +30,6 @@ The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes d [FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). -![MultiQC - FastQC sequence counts plot](images/mqc_fastqc_counts.png) - -![MultiQC - FastQC mean quality scores plot](images/mqc_fastqc_quality.png) - -![MultiQC - FastQC adapter content plot](images/mqc_fastqc_adapter.png) - -:::note -The FastQC plots displayed in the MultiQC report shows _untrimmed_ reads. They may contain adapter sequence and potentially regions with low quality. -::: - ### MultiQC -[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). - -### MultiQC +[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/).### MultiQC
    Output files @@ -43,9 +40,7 @@ The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes d [MultiQC](http://multiqc.info) is a visualization tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in the report data directory. -Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQC. The pipeline has special steps which also allow the software versions to be reported in the MultiQC output for future traceability. For more information about how to use MultiQC reports, see . - -### Pipeline information +Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQC. The pipeline has special steps which also allow the software versions to be reported in the MultiQC output for future traceability. For more information about how to use MultiQC reports, see .### Pipeline information
    Output files diff --git a/docs/usage.md b/docs/usage.md index e575084..210645c 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -130,7 +130,7 @@ Several generic profiles are bundled with the pipeline which instruct the pipeli > [!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. -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 suported, please see the [nf-core/configs documentation](https://github.com/nf-core/configs#documentation). +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). Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! They are loaded in sequence, so later profiles can overwrite earlier profiles. diff --git a/nextflow.config b/nextflow.config index 5cd47e9..76e74f1 100644 --- a/nextflow.config +++ b/nextflow.config @@ -283,3 +283,6 @@ validation { afterText = validation.help.afterText } } + +// Load modules.config for DSL2 module specific options +includeConfig 'conf/modules.config' diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 4b09e1c..4d0f716 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -22,8 +22,8 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "InProgress", - "datePublished": "2024-12-12T11:22:33+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))\n2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "datePublished": "2024-12-20T13:07:04+00:00", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    [![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#9f490429-3d14-493a-b124-be2775fcbd2f" + "@id": "#63fa5199-fed9-480a-848b-17faef7231b0" } ], "name": "nf-core/datasync" @@ -121,31 +121,47 @@ }, { "@id": "main.nf", - "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "@type": [ + "File", + "SoftwareSourceCode", + "ComputationalWorkflow" + ], "creator": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], "dateCreated": "", - "dateModified": "2024-12-12T11:22:33Z", + "dateModified": "2024-12-20T13:07:04Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", - "keywords": ["nf-core", "nextflow"], - "license": ["MIT"], + "keywords": [ + "nf-core", + "nextflow" + ], + "license": [ + "MIT" + ], "maintainer": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], - "name": ["nf-core/datasync"], + "name": [ + "nf-core/datasync" + ], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" }, "sdPublisher": { "@id": "https://nf-co.re/" }, - "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/dev/"], - "version": ["1.0dev"] + "url": [ + "https://github.com/nf-core/datasync", + "https://nf-co.re/datasync/dev/" + ], + "version": [ + "1.0dev" + ] }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", @@ -160,11 +176,11 @@ "version": "!>=24.04.2" }, { - "@id": "#9f490429-3d14-493a-b124-be2775fcbd2f", + "@id": "#63fa5199-fed9-480a-848b-17faef7231b0", "@type": "TestSuite", "instance": [ { - "@id": "#de2f5e14-73b2-45aa-9f4c-e1a1c17e3843" + "@id": "#f33fcba2-d0bc-4097-8be8-43eaaeec8844" } ], "mainEntity": { @@ -173,7 +189,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#de2f5e14-73b2-45aa-9f4c-e1a1c17e3843", + "@id": "#f33fcba2-d0bc-4097-8be8-43eaaeec8844", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/ci.yml", @@ -308,4 +324,4 @@ "name": "Alexander Peltzer" } ] -} +} \ No newline at end of file diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 311fba1..838e8bd 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -117,7 +117,7 @@ workflow PIPELINE_COMPLETION { main: summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") def multiqc_reports = multiqc_report.toList() - + // // Completion email and summary // From 05350dd00aced866724a3b4519a4ff7f445aae7f Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Mon, 20 Jan 2025 14:33:36 +0000 Subject: [PATCH 011/334] Template update for nf-core/tools version 3.1.2 --- .github/workflows/ci.yml | 2 ++ .github/workflows/download_pipeline.yml | 28 +++++++++------- .nf-core.yml | 2 +- CITATIONS.md | 4 ++- README.md | 10 ++++-- conf/test.config | 4 +-- nextflow.config | 2 +- ro-crate-metadata.json | 44 ++++++++----------------- 8 files changed, 45 insertions(+), 51 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 137b8f7..26ae93d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,6 +46,8 @@ jobs: 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 diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 13b51e2..ab06316 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -34,6 +34,17 @@ jobs: REPO_LOWERCASE: ${{ steps.get_repo_properties.outputs.REPO_LOWERCASE }} REPOTITLE_LOWERCASE: ${{ steps.get_repo_properties.outputs.REPOTITLE_LOWERCASE }} REPO_BRANCH: ${{ steps.get_repo_properties.outputs.REPO_BRANCH }} + steps: + - name: Get the repository name and current branch + id: get_repo_properties + run: | + echo "REPO_LOWERCASE=${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT" + echo "REPOTITLE_LOWERCASE=$(basename ${GITHUB_REPOSITORY,,})" >> "$GITHUB_OUTPUT" + echo "REPO_BRANCH=${{ github.event.inputs.testbranch || 'dev' }}" >> "$GITHUB_OUTPUT" + + download: + runs-on: ubuntu-latest + needs: configure steps: - name: Install Nextflow uses: nf-core/setup-nextflow@v2 @@ -56,21 +67,10 @@ jobs: python -m pip install --upgrade pip pip install git+https://github.com/nf-core/tools.git@dev - - name: Get the repository name and current branch set as environment variable - id: get_repo_properties - run: | - echo "REPO_LOWERCASE=${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT" - echo "REPOTITLE_LOWERCASE=$(basename ${GITHUB_REPOSITORY,,})" >> "$GITHUB_OUTPUT" - echo "REPO_BRANCH=${{ github.event.inputs.testbranch || 'dev' }}" >> "$GITHUB_OUTPUT" - - name: Make a cache directory for the container images run: | mkdir -p ./singularity_container_images - download: - runs-on: ubuntu-latest - needs: configure - steps: - name: Download the pipeline env: NXF_SINGULARITY_CACHEDIR: ./singularity_container_images @@ -87,6 +87,9 @@ jobs: - name: Inspect download run: tree ./${{ needs.configure.outputs.REPOTITLE_LOWERCASE }} + - name: Inspect container images + run: tree ./singularity_container_images | tee ./container_initial + - name: Count the downloaded number of container images id: count_initial run: | @@ -123,7 +126,8 @@ jobs: final_count=${{ steps.count_afterwards.outputs.IMAGE_COUNT_AFTER }} difference=$((final_count - initial_count)) echo "$difference additional container images were \n downloaded at runtime . The pipeline has no support for offline runs!" - tree ./singularity_container_images + tree ./singularity_container_images > ./container_afterwards + diff ./container_initial ./container_afterwards exit 1 else echo "The pipeline can be downloaded successfully!" diff --git a/.nf-core.yml b/.nf-core.yml index 0a65c21..15d35d2 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 3.1.1 +nf_core_version: 3.1.2 repository_type: pipeline template: author: Alexander Peltzer diff --git a/CITATIONS.md b/CITATIONS.md index 29e6bd4..3032c6f 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -12,7 +12,9 @@ - [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) -> Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online].- [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) +> Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. + +- [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) > Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. diff --git a/README.md b/README.md index ffba325..e035b8a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,9 @@ nf-core/datasync -[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml) + + +[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml) [![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) @@ -32,7 +34,7 @@ ## Usage > [!NOTE] -> 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. +> 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. - + + + An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. diff --git a/conf/test.config b/conf/test.config index 7f9aa8a..7b7af9e 100644 --- a/conf/test.config +++ b/conf/test.config @@ -25,8 +25,6 @@ params { // Input data // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv' - - // Genome references + input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv'// Genome references genome = 'R64-1-1' } diff --git a/nextflow.config b/nextflow.config index 76e74f1..57a8f14 100644 --- a/nextflow.config +++ b/nextflow.config @@ -249,7 +249,7 @@ manifest { // Nextflow plugins plugins { - id 'nf-schema@2.1.1' // Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-schema@2.3.0' // Validation of pipeline parameters and creation of an input channel from a sample sheet } validation { diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 4d0f716..643a1e5 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -22,8 +22,8 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "InProgress", - "datePublished": "2024-12-20T13:07:04+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    [![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\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", + "datePublished": "2025-01-20T14:33:22+00:00", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#63fa5199-fed9-480a-848b-17faef7231b0" + "@id": "#b8d306fd-dd52-4477-8464-bff33fd29bd7" } ], "name": "nf-core/datasync" @@ -121,47 +121,31 @@ }, { "@id": "main.nf", - "@type": [ - "File", - "SoftwareSourceCode", - "ComputationalWorkflow" - ], + "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], "creator": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], "dateCreated": "", - "dateModified": "2024-12-20T13:07:04Z", + "dateModified": "2025-01-20T14:33:22Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", - "keywords": [ - "nf-core", - "nextflow" - ], - "license": [ - "MIT" - ], + "keywords": ["nf-core", "nextflow"], + "license": ["MIT"], "maintainer": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], - "name": [ - "nf-core/datasync" - ], + "name": ["nf-core/datasync"], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" }, "sdPublisher": { "@id": "https://nf-co.re/" }, - "url": [ - "https://github.com/nf-core/datasync", - "https://nf-co.re/datasync/dev/" - ], - "version": [ - "1.0dev" - ] + "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/dev/"], + "version": ["1.0dev"] }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", @@ -176,11 +160,11 @@ "version": "!>=24.04.2" }, { - "@id": "#63fa5199-fed9-480a-848b-17faef7231b0", + "@id": "#b8d306fd-dd52-4477-8464-bff33fd29bd7", "@type": "TestSuite", "instance": [ { - "@id": "#f33fcba2-d0bc-4097-8be8-43eaaeec8844" + "@id": "#51ac4b70-c54e-4154-9628-16883ce620c6" } ], "mainEntity": { @@ -189,7 +173,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#f33fcba2-d0bc-4097-8be8-43eaaeec8844", + "@id": "#51ac4b70-c54e-4154-9628-16883ce620c6", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/ci.yml", @@ -324,4 +308,4 @@ "name": "Alexander Peltzer" } ] -} \ No newline at end of file +} From 446c8caaf25418201f1e729a46070b45a910650c Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Mon, 27 Jan 2025 14:45:38 +0000 Subject: [PATCH 012/334] Template update for nf-core/tools version 3.2.0 --- .github/workflows/linting_comment.yml | 2 +- .github/workflows/release-announcements.yml | 33 ------------------- .nf-core.yml | 2 +- .pre-commit-config.yaml | 2 +- docs/output.md | 11 +++++-- modules.json | 4 +-- modules/nf-core/fastqc/main.nf | 20 +++++------ modules/nf-core/fastqc/tests/tags.yml | 2 -- modules/nf-core/multiqc/environment.yml | 2 +- modules/nf-core/multiqc/main.nf | 4 +-- .../nf-core/multiqc/tests/main.nf.test.snap | 24 +++++++------- nextflow.config | 16 ++++----- ro-crate-metadata.json | 12 +++---- 13 files changed, 52 insertions(+), 82 deletions(-) delete mode 100644 modules/nf-core/fastqc/tests/tags.yml diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 0bed96d..95b6b6a 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@80620a5d27ce0ae443b965134db88467fc607b43 # v7 + uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8 with: workflow: linting.yml workflow_conclusion: completed diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 450b1d5..76a9e67 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -27,39 +27,6 @@ jobs: ${{ steps.get_topics.outputs.topics }} #nfcore #openscience #nextflow #bioinformatics - send-tweet: - runs-on: ubuntu-latest - - steps: - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 - with: - python-version: "3.10" - - name: Install dependencies - run: pip install tweepy==4.14.0 - - name: Send tweet - shell: python - run: | - import os - import tweepy - - client = tweepy.Client( - access_token=os.getenv("TWITTER_ACCESS_TOKEN"), - access_token_secret=os.getenv("TWITTER_ACCESS_TOKEN_SECRET"), - consumer_key=os.getenv("TWITTER_CONSUMER_KEY"), - consumer_secret=os.getenv("TWITTER_CONSUMER_SECRET"), - ) - tweet = os.getenv("TWEET") - client.create_tweet(text=tweet) - env: - TWEET: | - Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! - - Please see the changelog: ${{ github.event.release.html_url }} - TWITTER_CONSUMER_KEY: ${{ secrets.TWITTER_CONSUMER_KEY }} - TWITTER_CONSUMER_SECRET: ${{ secrets.TWITTER_CONSUMER_SECRET }} - TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} - TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} - bsky-post: runs-on: ubuntu-latest steps: diff --git a/.nf-core.yml b/.nf-core.yml index 15d35d2..bc2f6f8 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 3.1.2 +nf_core_version: 3.2.0 repository_type: pipeline template: author: Alexander Peltzer diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e9f0e1..1dec865 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - prettier@3.2.5 - repo: https://github.com/editorconfig-checker/editorconfig-checker.python - rev: "3.0.3" + rev: "3.1.2" hooks: - id: editorconfig-checker alias: ec diff --git a/docs/output.md b/docs/output.md index e7beb92..1b7eb8b 100644 --- a/docs/output.md +++ b/docs/output.md @@ -12,7 +12,8 @@ The directories listed below will be created in the results directory after the The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: -- [FastQC](#fastqc) - Raw read QC- [MultiQC](#multiqc) - Aggregate report describing results and QC from the whole pipeline +- [FastQC](#fastqc) - Raw read QC +- [MultiQC](#multiqc) - Aggregate report describing results and QC from the whole pipeline - [Pipeline information](#pipeline-information) - Report metrics generated during the workflow execution ### FastQC @@ -26,7 +27,9 @@ The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes d
    -[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/).### MultiQC +[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). + +### MultiQC
    Output files @@ -40,7 +43,9 @@ The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes d [MultiQC](http://multiqc.info) is a visualization tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in the report data directory. -Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQC. The pipeline has special steps which also allow the software versions to be reported in the MultiQC output for future traceability. For more information about how to use MultiQC reports, see .### Pipeline information +Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQC. The pipeline has special steps which also allow the software versions to be reported in the MultiQC output for future traceability. For more information about how to use MultiQC reports, see . + +### Pipeline information
    Output files diff --git a/modules.json b/modules.json index 9eb34fb..ac0474c 100644 --- a/modules.json +++ b/modules.json @@ -7,12 +7,12 @@ "nf-core": { "fastqc": { "branch": "master", - "git_sha": "dc94b6ee04a05ddb9f7ae050712ff30a13149164", + "git_sha": "08108058ea36a63f141c25c4e75f9f872a5b2296", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "cf17ca47590cc578dfb47db1c2a44ef86f89976d", + "git_sha": "f0719ae309075ae4a291533883847c3f7c441dad", "installed_by": ["modules"] } } diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 752c3a1..033f415 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -1,5 +1,5 @@ process FASTQC { - tag "$meta.id" + tag "${meta.id}" label 'process_medium' conda "${moduleDir}/environment.yml" @@ -19,30 +19,30 @@ process FASTQC { task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" // Make list of old name and new name pairs to use for renaming in the bash while loop def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } - def rename_to = old_new_pairs*.join(' ').join(' ') + def rename_to = old_new_pairs*.join(' ').join(' ') def renamed_files = old_new_pairs.collect{ _old_name, new_name -> new_name }.join(' ') // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 // Dividing the task.memory by task.cpu allows to stick to requested amount of RAM in the label - def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') / task.cpus + def memory_in_mb = task.memory ? task.memory.toUnit('MB').toFloat() / task.cpus : null // FastQC memory value allowed range (100 - 10000) def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) """ - printf "%s %s\\n" $rename_to | while read old_name new_name; do + printf "%s %s\\n" ${rename_to} | while read old_name new_name; do [ -f "\${new_name}" ] || ln -s \$old_name \$new_name done fastqc \\ - $args \\ - --threads $task.cpus \\ - --memory $fastqc_memory \\ - $renamed_files + ${args} \\ + --threads ${task.cpus} \\ + --memory ${fastqc_memory} \\ + ${renamed_files} cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/nf-core/fastqc/tests/tags.yml b/modules/nf-core/fastqc/tests/tags.yml deleted file mode 100644 index 7834294..0000000 --- a/modules/nf-core/fastqc/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -fastqc: - - modules/nf-core/fastqc/** diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index 6f5b867..a27122c 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -2,4 +2,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.25.1 + - bioconda::multiqc=1.27 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index cc0643e..58d9313 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -3,8 +3,8 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.25.1--pyhdfd78af_0' : - 'biocontainers/multiqc:1.25.1--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.27--pyhdfd78af_0' : + 'biocontainers/multiqc:1.27--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index 2fcbb5f..7b7c132 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "multiqc_versions_single": { "content": [ [ - "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" + "versions.yml:md5,8f3b8c1cec5388cf2708be948c9fa42f" ] ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.4" + "nf-test": "0.9.2", + "nextflow": "24.10.4" }, - "timestamp": "2024-10-02T17:51:46.317523" + "timestamp": "2025-01-27T09:29:57.631982377" }, "multiqc_stub": { "content": [ @@ -17,25 +17,25 @@ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" + "versions.yml:md5,8f3b8c1cec5388cf2708be948c9fa42f" ] ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.4" + "nf-test": "0.9.2", + "nextflow": "24.10.4" }, - "timestamp": "2024-10-02T17:52:20.680978" + "timestamp": "2025-01-27T09:30:34.743726958" }, "multiqc_versions_config": { "content": [ [ - "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" + "versions.yml:md5,8f3b8c1cec5388cf2708be948c9fa42f" ] ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.4" + "nf-test": "0.9.2", + "nextflow": "24.10.4" }, - "timestamp": "2024-10-02T17:52:09.185842" + "timestamp": "2025-01-27T09:30:21.44383553" } } \ No newline at end of file diff --git a/nextflow.config b/nextflow.config index 57a8f14..318c768 100644 --- a/nextflow.config +++ b/nextflow.config @@ -195,14 +195,14 @@ env { } // Set bash options -process.shell = """\ -bash - -set -e # Exit if a tool returns a non-zero status/exit code -set -u # Treat unset variables and parameters as an error -set -o pipefail # Returns the status of the last command to exit with a non-zero status or zero if all successfully execute -set -C # No clobber - prevent output redirection from overwriting files. -""" +process.shell = [ + "bash", + "-C", // No clobber - prevent output redirection from overwriting files. + "-e", // Exit if a tool returns a non-zero status/exit code + "-u", // Treat unset variables and parameters as an error + "-o", // Returns the status of the last command to exit.. + "pipefail" // ..with a non-zero status or zero if all successfully execute +] // Disable process selector warnings by default. Use debug profile to enable warnings. nextflow.enable.configProcessNamesValidation = false diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 643a1e5..b0ca823 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -22,7 +22,7 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "InProgress", - "datePublished": "2025-01-20T14:33:22+00:00", + "datePublished": "2025-01-27T14:45:23+00:00", "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#b8d306fd-dd52-4477-8464-bff33fd29bd7" + "@id": "#74bb7024-cb39-4596-bd6d-3e863c87b753" } ], "name": "nf-core/datasync" @@ -128,7 +128,7 @@ } ], "dateCreated": "", - "dateModified": "2025-01-20T14:33:22Z", + "dateModified": "2025-01-27T14:45:23Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": ["nf-core", "nextflow"], "license": ["MIT"], @@ -160,11 +160,11 @@ "version": "!>=24.04.2" }, { - "@id": "#b8d306fd-dd52-4477-8464-bff33fd29bd7", + "@id": "#74bb7024-cb39-4596-bd6d-3e863c87b753", "@type": "TestSuite", "instance": [ { - "@id": "#51ac4b70-c54e-4154-9628-16883ce620c6" + "@id": "#040b220d-6ba5-4765-93b4-fedcb0a7fb4a" } ], "mainEntity": { @@ -173,7 +173,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#51ac4b70-c54e-4154-9628-16883ce620c6", + "@id": "#040b220d-6ba5-4765-93b4-fedcb0a7fb4a", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/ci.yml", From 970f28e4520dba3f55d783de7cf516f46a891994 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Wed, 30 Apr 2025 12:26:13 +0000 Subject: [PATCH 013/334] Template update for nf-core/tools version 3.2.1 --- .github/workflows/awsfulltest.yml | 41 ++++++++----------------------- .github/workflows/ci.yml | 1 + .nf-core.yml | 2 +- nextflow.config | 2 +- ro-crate-metadata.json | 12 ++++----- 5 files changed, 19 insertions(+), 39 deletions(-) diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 1fb97f5..a2012fc 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -4,44 +4,23 @@ name: nf-core AWS full size tests # It runs the -profile 'test_full' on AWS batch on: - pull_request: - branches: - - main - - master workflow_dispatch: pull_request_review: types: [submitted] + release: + types: [published] jobs: run-platform: name: Run AWS full tests - # run only if the PR is approved by at least 2 reviewers and against the master branch or manually triggered - if: github.repository == 'nf-core/datasync' && github.event.review.state == 'approved' && github.event.pull_request.base.ref == 'master' || github.event_name == 'workflow_dispatch' + # 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/datasync' && github.event.review.state == 'approved' && (github.event.pull_request.base.ref == 'master' || github.event.pull_request.base.ref == 'main') || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: - - name: Get PR reviews - uses: octokit/request-action@v2.x - if: github.event_name != 'workflow_dispatch' - id: check_approvals - continue-on-error: true - with: - route: GET /repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews?per_page=100 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Check for approvals - if: ${{ failure() && github.event_name != 'workflow_dispatch' }} - run: | - echo "No review approvals found. At least 2 approvals are required to run this action automatically." - exit 1 - - - name: Check for enough approvals (>=2) - id: test_variables - if: github.event_name != 'workflow_dispatch' + - name: Set revision variable + id: revision run: | - JSON_RESPONSE='${{ steps.check_approvals.outputs.data }}' - CURRENT_APPROVALS_COUNT=$(echo $JSON_RESPONSE | jq -c '[.[] | select(.state | contains("APPROVED")) ] | length') - test $CURRENT_APPROVALS_COUNT -ge 2 || exit 1 # At least 2 approvals are required + echo "revision=${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'release') && github.sha || 'dev' }}" >> "$GITHUB_OUTPUT" - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 @@ -52,12 +31,12 @@ jobs: workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} - revision: ${{ github.sha }} - workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/datasync/work-${{ github.sha }} + revision: ${{ steps.revision.outputs.revision }} + workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/datasync/work-${{ steps.revision.outputs.revision }} parameters: | { "hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}", - "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/datasync/results-${{ github.sha }}" + "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/datasync/results-${{ steps.revision.outputs.revision }}" } profiles: test_full diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26ae93d..2233b37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,5 +83,6 @@ jobs: uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # 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: | nextflow run ${GITHUB_WORKSPACE} -profile ${{ matrix.test_name }},${{ matrix.profile }} --outdir ./results diff --git a/.nf-core.yml b/.nf-core.yml index bc2f6f8..51650ea 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 3.2.0 +nf_core_version: 3.2.1 repository_type: pipeline template: author: Alexander Peltzer diff --git a/nextflow.config b/nextflow.config index 318c768..0178c9b 100644 --- a/nextflow.config +++ b/nextflow.config @@ -249,7 +249,7 @@ manifest { // Nextflow plugins plugins { - id 'nf-schema@2.3.0' // Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-schema@2.2.0' // Validation of pipeline parameters and creation of an input channel from a sample sheet } validation { diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index b0ca823..b28afa0 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -22,7 +22,7 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "InProgress", - "datePublished": "2025-01-27T14:45:23+00:00", + "datePublished": "2025-04-30T12:26:03+00:00", "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#74bb7024-cb39-4596-bd6d-3e863c87b753" + "@id": "#4303c0df-da0f-4235-9588-26f3d66c0341" } ], "name": "nf-core/datasync" @@ -128,7 +128,7 @@ } ], "dateCreated": "", - "dateModified": "2025-01-27T14:45:23Z", + "dateModified": "2025-04-30T12:26:03Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": ["nf-core", "nextflow"], "license": ["MIT"], @@ -160,11 +160,11 @@ "version": "!>=24.04.2" }, { - "@id": "#74bb7024-cb39-4596-bd6d-3e863c87b753", + "@id": "#4303c0df-da0f-4235-9588-26f3d66c0341", "@type": "TestSuite", "instance": [ { - "@id": "#040b220d-6ba5-4765-93b4-fedcb0a7fb4a" + "@id": "#b70eee80-dd7e-4ae3-ab12-7e2658c3720e" } ], "mainEntity": { @@ -173,7 +173,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#040b220d-6ba5-4765-93b4-fedcb0a7fb4a", + "@id": "#b70eee80-dd7e-4ae3-ab12-7e2658c3720e", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/ci.yml", From 0354e6f8c1257b6ab4f4185566027a063aab363f Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 3 Jun 2025 11:01:32 +0000 Subject: [PATCH 014/334] Template update for nf-core/tools version 3.3.1 --- .editorconfig | 37 ----- .github/CONTRIBUTING.md | 2 +- .github/actions/get-shards/action.yml | 69 +++++++++ .github/actions/nf-test/action.yml | 113 ++++++++++++++ .github/workflows/awsfulltest.yml | 4 +- .github/workflows/awstest.yml | 2 +- .github/workflows/ci.yml | 88 ----------- .github/workflows/clean-up.yml | 2 +- .github/workflows/download_pipeline.yml | 20 +-- .../{fix-linting.yml => fix_linting.yml} | 4 +- .github/workflows/linting.yml | 15 +- .github/workflows/linting_comment.yml | 4 +- .github/workflows/nf-test.yml | 142 ++++++++++++++++++ .github/workflows/release-announcements.yml | 2 +- ...mment.yml => template-version-comment.yml} | 2 +- .nf-core.yml | 2 +- .pre-commit-config.yaml | 26 +++- .prettierrc.yml | 5 + README.md | 7 +- conf/base.config | 5 +- nextflow.config | 17 ++- nf-test.config | 24 +++ ro-crate-metadata.json | 16 +- .../utils_nfcore_datasync_pipeline/main.nf | 1 - tests/.nftignore | 10 ++ tests/default.nf.test | 35 +++++ tests/nextflow.config | 12 ++ 27 files changed, 487 insertions(+), 179 deletions(-) delete mode 100644 .editorconfig create mode 100644 .github/actions/get-shards/action.yml create mode 100644 .github/actions/nf-test/action.yml delete mode 100644 .github/workflows/ci.yml rename .github/workflows/{fix-linting.yml => fix_linting.yml} (96%) create mode 100644 .github/workflows/nf-test.yml rename .github/workflows/{template_version_comment.yml => template-version-comment.yml} (95%) create mode 100644 nf-test.config create mode 100644 tests/.nftignore create mode 100644 tests/default.nf.test create mode 100644 tests/nextflow.config diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 6d9b74c..0000000 --- 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 04e0dfc..8aed170 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 0000000..3408527 --- /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 0000000..243e782 --- /dev/null +++ b/.github/actions/nf-test/action.yml @@ -0,0 +1,113 @@ +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 + + # TODO Skip failing conda tests and document their failures + # https://github.com/nf-core/modules/issues/7017 + - name: Run nf-test + shell: bash + env: + NFT_DIFF: ${{ env.NFT_DIFF }} + NFT_DIFF_ARGS: ${{ env.NFT_DIFF_ARGS }} + 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 a2012fc..5f5aa19 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/datasync' && 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/datasync' && 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 @@ -40,7 +40,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 bf4a3ee..d937e2f 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 2233b37..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,88 +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: - release: - types: [published] - workflow_dispatch: - -env: - NXF_ANSI_LOG: false - NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity - NXF_SINGULARITY_LIBRARYDIR: ${{ github.workspace }}/.singularity - -concurrency: - group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" - cancel-in-progress: true - -jobs: - test: - name: "Run pipeline with test data (${{ matrix.NXF_VER }} | ${{ matrix.test_name }} | ${{ matrix.profile }})" - # Only run on push if this is the nf-core dev branch (merged PRs) - if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/datasync') }}" - runs-on: ubuntu-latest - strategy: - matrix: - NXF_VER: - - "24.04.2" - - "latest-everything" - profile: - - "conda" - - "docker" - - "singularity" - test_name: - - "test" - isMaster: - - ${{ github.base_ref == 'master' }} - # Exclude conda and singularity on dev - 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 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: 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: Clean up Disk space - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # 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: | - nextflow run ${GITHUB_WORKSPACE} -profile ${{ matrix.test_name }},${{ matrix.profile }} --outdir ./results diff --git a/.github/workflows/clean-up.yml b/.github/workflows/clean-up.yml index 0b6b1f2..ac030fd 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 ab06316..999bcc3 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 1f3206f..42f855d 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 dbd52d5..f2d7d1d 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] @@ -17,9 +14,9 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Set up Python 3.12 - 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 @@ -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 95b6b6a..7e8050f 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@4c1e823582f43b179e2cbb49c3eade4e41f992e2 # v10 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 0000000..f03aea0 --- /dev/null +++ b/.github/workflows/nf-test.yml @@ -0,0 +1,142 @@ +name: Run nf-test +on: + push: + paths-ignore: + - "docs/**" + - "**/meta.yml" + - "**/*.md" + - "**/*.png" + - "**/*.svg" + 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=$-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=$-nf-test + - runner=4cpu-linux-x64 + strategy: + fail-fast: false + matrix: + shard: ${{ fromJson(needs.nf-test-changes.outputs.shard) }} + profile: [conda, 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.04.2" + - "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 + uses: ./.github/actions/nf-test + env: + NFT_DIFF: ${{ env.NFT_DIFF }} + NFT_DIFF_ARGS: ${{ env.NFT_DIFF_ARGS }} + NFT_WORKDIR: ${{ env.NFT_WORKDIR }} + with: + profile: ${{ matrix.profile }} + shard: ${{ matrix.shard }} + total_shards: ${{ env.TOTAL_SHARDS }} + confirm-pass: + needs: [nf-test] + if: always() + runs-on: # use self-hosted runners + - runs-on=$-confirm-pass + - runner=2cpu-linux-x64 + steps: + - name: One or more tests failed + 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::" + + - name: Clean Workspace # Purge the workspace in case it's running on a self-hosted runner + if: always() + run: | + ls -la ./ + rm -rf ./* || true + rm -rf ./.??* || true + ls -la ./ diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 76a9e67..4abaf48 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@4aa83560bb3eac05dbad1e5f221ee339118abdd2 # v0.2.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 537529b..beb5c77 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 51650ea..82ea73d 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 3.2.1 +nf_core_version: 3.3.1 repository_type: pipeline template: author: Alexander Peltzer diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1dec865..9d0b248 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,10 +4,24 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.2.5 - - - repo: https://github.com/editorconfig-checker/editorconfig-checker.python - rev: "3.1.2" + - prettier@3.5.0 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 hooks: - - id: editorconfig-checker - alias: ec + - 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 c81f9a7..07dbd8b 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/README.md b/README.md index e035b8a..4a3cc67 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,14 @@ [![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![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.04.2-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.1-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.1) [![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/datasync) -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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 @@ -28,7 +29,7 @@ --> + workflows use the "tube map" design for that. See https://nf-co.re/docs/guidelines/graphic_design/workflow_diagrams#examples for examples. --> 1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) ## Usage diff --git a/conf/base.config b/conf/base.config index 3f8e13e..8a59c38 100644 --- a/conf/base.config +++ b/conf/base.config @@ -15,7 +15,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' @@ -59,4 +59,7 @@ process { errorStrategy = 'retry' maxRetries = 2 } + withLabel: process_gpu { + ext.use_gpu = { workflow.profile.contains('gpu') } + } } diff --git a/nextflow.config b/nextflow.config index 0178c9b..68a61a0 100644 --- a/nextflow.config +++ b/nextflow.config @@ -160,16 +160,25 @@ 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' } } -// 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 custom profiles from different institutions + +// If params.custom_config_base is set AND either the NXF_OFFLINE environment variable is not set or params.custom_config_base is a local path, the nfcore_custom.config file from the specified base path is included. +// Load nf-core/datasync 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" + // Load nf-core/datasync custom profiles from different institutions. // TODO nf-core: Optionally, you can add a pipeline-specific nf-core config at https://github.com/nf-core/configs -// includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${params.custom_config_base}/pipeline/datasync.config" : "/dev/null" +// includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !params.custom_config_base.startsWith('http')) ? "${params.custom_config_base}/pipeline/datasync.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 @@ -249,7 +258,7 @@ manifest { // 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.3.0' // Validation of pipeline parameters and creation of an input channel from a sample sheet } validation { diff --git a/nf-test.config b/nf-test.config new file mode 100644 index 0000000..889df76 --- /dev/null +++ b/nf-test.config @@ -0,0 +1,24 @@ +config { + // location for all nf-test tests + testsDir "." + + // 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 tests + configFile "tests/nextflow.config" + + // ignore tests coming from the nf-core/modules repo + ignore 'modules/nf-core/**/*', 'subworkflows/nf-core/**/*' + + // run all test with defined profile(s) from the main nextflow.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 { + load "nft-utils@0.0.3" + } +} diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index b28afa0..a99dec5 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -22,8 +22,8 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "InProgress", - "datePublished": "2025-04-30T12:26:03+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "datePublished": "2025-06-03T11:01:27+00:00", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A524.04.2-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.1-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.1)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#4303c0df-da0f-4235-9588-26f3d66c0341" + "@id": "#6e1856e4-68ad-483f-95f4-97b1f4ec6a75" } ], "name": "nf-core/datasync" @@ -128,7 +128,7 @@ } ], "dateCreated": "", - "dateModified": "2025-04-30T12:26:03Z", + "dateModified": "2025-06-03T11:01:27Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": ["nf-core", "nextflow"], "license": ["MIT"], @@ -160,11 +160,11 @@ "version": "!>=24.04.2" }, { - "@id": "#4303c0df-da0f-4235-9588-26f3d66c0341", + "@id": "#6e1856e4-68ad-483f-95f4-97b1f4ec6a75", "@type": "TestSuite", "instance": [ { - "@id": "#b70eee80-dd7e-4ae3-ab12-7e2658c3720e" + "@id": "#8316b07c-aa2f-4100-b61a-d1aa1321ccfd" } ], "mainEntity": { @@ -173,10 +173,10 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#b70eee80-dd7e-4ae3-ab12-7e2658c3720e", + "@id": "#8316b07c-aa2f-4100-b61a-d1aa1321ccfd", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", - "resource": "repos/nf-core/datasync/actions/workflows/ci.yml", + "resource": "repos/nf-core/datasync/actions/workflows/nf-test.yml", "runsOn": { "@id": "https://w3id.org/ro/terms/test#GithubService" }, diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 838e8bd..e65bbf3 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -261,4 +261,3 @@ def methodsDescriptionText(mqc_methods_yaml) { return description_html.toString() } - diff --git a/tests/.nftignore b/tests/.nftignore new file mode 100644 index 0000000..c10bc1f --- /dev/null +++ b/tests/.nftignore @@ -0,0 +1,10 @@ +.DS_Store +multiqc/multiqc_data/fastqc_top_overrepresented_sequences_table.txt +multiqc/multiqc_data/multiqc.log +multiqc/multiqc_data/multiqc_data.json +multiqc/multiqc_data/multiqc_sources.txt +multiqc/multiqc_data/multiqc_software_versions.txt +multiqc/multiqc_plots/{svg,pdf,png}/*.{svg,pdf,png} +multiqc/multiqc_report.html +fastqc/*_fastqc.{html,zip} +pipeline_info/*.{html,json,txt,yml} diff --git a/tests/default.nf.test b/tests/default.nf.test new file mode 100644 index 0000000..43cf2c9 --- /dev/null +++ b/tests/default.nf.test @@ -0,0 +1,35 @@ +nextflow_pipeline { + + name "Test pipeline" + script "../main.nf" + tag "pipeline" + + test("-profile test") { + + when { + params { + outdir = "$outputDir" + } + } + + 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 = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + 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 test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path + ).match() } + ) + } + } +} diff --git a/tests/nextflow.config b/tests/nextflow.config new file mode 100644 index 0000000..12b4c0a --- /dev/null +++ b/tests/nextflow.config @@ -0,0 +1,12 @@ +/* +======================================================================================== + Nextflow config file for running nf-test tests +======================================================================================== +*/ + +// TODO nf-core: Specify any additional parameters here +// Or any resources requirements +params.modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' +params.pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync' + +aws.client.anonymous = true // fixes S3 access issues on self-hosted runners From 9cc02c147005b83c7d585fc4b681b6f6a74bbb0a Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 15:59:57 +0000 Subject: [PATCH 015/334] Channel to channel --- .../utils_nfcore_datasync_pipeline/main.nf | 6 ++--- .../nf-core/utils_nfcore_pipeline/main.nf | 2 +- workflows/datasync.nf | 27 +++++++------------ 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index e65bbf3..d51e1e3 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -28,14 +28,14 @@ workflow PIPELINE_INITIALISATION { take: version // boolean: Display version and exit validate_params // boolean: Boolean whether to validate parameters against the schema at runtime - monochrome_logs // boolean: Do not use coloured log outputs + _monochrome_logs // boolean: Do not use coloured log outputs nextflow_cli_args // array: List of positional nextflow CLI args outdir // string: The output directory where the results will be saved input // string: Path to input samplesheet main: - ch_versions = Channel.empty() + ch_versions = channel.empty() // // Print version and exit if required and dump pipeline parameters to JSON file @@ -72,7 +72,7 @@ workflow PIPELINE_INITIALISATION { // Create channel from input file provided through params.input // - Channel + channel .fromList(samplesheetToList(params.input, "${projectDir}/assets/schema_input.json")) .map { meta, fastq_1, fastq_2 -> diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index bfd2587..2f30e9a 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -98,7 +98,7 @@ def workflowVersionToYAML() { // Get channel of software versions used in pipeline in YAML format // def softwareVersionsToYAML(ch_versions) { - return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(Channel.of(workflowVersionToYAML())) + return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(channel.of(workflowVersionToYAML())) } // diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 6905242..4dcd9b7 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -3,7 +3,6 @@ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { FASTQC } from '../modules/nf-core/fastqc/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' @@ -22,16 +21,8 @@ workflow DATASYNC { ch_samplesheet // channel: samplesheet read in from --input main: - ch_versions = Channel.empty() - ch_multiqc_files = Channel.empty() - // - // MODULE: Run FastQC - // - FASTQC ( - ch_samplesheet - ) - ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}) - ch_versions = ch_versions.mix(FASTQC.out.versions.first()) + ch_versions = channel.empty() + ch_multiqc_files = channel.empty() // // Collate and save software versions @@ -48,24 +39,24 @@ workflow DATASYNC { // // MODULE: MultiQC // - ch_multiqc_config = Channel.fromPath( + ch_multiqc_config = channel.fromPath( "$projectDir/assets/multiqc_config.yml", checkIfExists: true) ch_multiqc_custom_config = params.multiqc_config ? - Channel.fromPath(params.multiqc_config, checkIfExists: true) : - Channel.empty() + channel.fromPath(params.multiqc_config, checkIfExists: true) : + channel.empty() ch_multiqc_logo = params.multiqc_logo ? - Channel.fromPath(params.multiqc_logo, checkIfExists: true) : - Channel.empty() + channel.fromPath(params.multiqc_logo, checkIfExists: true) : + channel.empty() summary_params = paramsSummaryMap( workflow, parameters_schema: "nextflow_schema.json") - ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) + ch_workflow_summary = channel.value(paramsSummaryMultiqc(summary_params)) ch_multiqc_files = ch_multiqc_files.mix( ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) - ch_methods_description = Channel.value( + ch_methods_description = channel.value( methodsDescriptionText(ch_multiqc_custom_methods_description)) ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) From 3f4e7a8dcf8efa8c642c0be0f7876aebb2802e21 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:04:52 +0000 Subject: [PATCH 016/334] fix linting --- modules/nf-core/fastqc/environment.yml | 5 + modules/nf-core/fastqc/main.nf | 64 +++ modules/nf-core/fastqc/meta.yml | 67 +++ modules/nf-core/fastqc/tests/main.nf.test | 309 ++++++++++++++ .../nf-core/fastqc/tests/main.nf.test.snap | 392 ++++++++++++++++++ 5 files changed, 837 insertions(+) create mode 100644 modules/nf-core/fastqc/environment.yml create mode 100644 modules/nf-core/fastqc/main.nf create mode 100644 modules/nf-core/fastqc/meta.yml create mode 100644 modules/nf-core/fastqc/tests/main.nf.test create mode 100644 modules/nf-core/fastqc/tests/main.nf.test.snap diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml new file mode 100644 index 0000000..691d4c7 --- /dev/null +++ b/modules/nf-core/fastqc/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::fastqc=0.12.1 diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf new file mode 100644 index 0000000..033f415 --- /dev/null +++ b/modules/nf-core/fastqc/main.nf @@ -0,0 +1,64 @@ +process FASTQC { + tag "${meta.id}" + label 'process_medium' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' : + 'biocontainers/fastqc:0.12.1--hdfd78af_0' }" + + input: + tuple val(meta), path(reads) + + output: + tuple val(meta), path("*.html"), emit: html + tuple val(meta), path("*.zip") , emit: zip + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + // Make list of old name and new name pairs to use for renaming in the bash while loop + def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } + def rename_to = old_new_pairs*.join(' ').join(' ') + def renamed_files = old_new_pairs.collect{ _old_name, new_name -> new_name }.join(' ') + + // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) + // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 + // Dividing the task.memory by task.cpu allows to stick to requested amount of RAM in the label + def memory_in_mb = task.memory ? task.memory.toUnit('MB').toFloat() / task.cpus : null + // FastQC memory value allowed range (100 - 10000) + def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) + + """ + printf "%s %s\\n" ${rename_to} | while read old_name new_name; do + [ -f "\${new_name}" ] || ln -s \$old_name \$new_name + done + + fastqc \\ + ${args} \\ + --threads ${task.cpus} \\ + --memory ${fastqc_memory} \\ + ${renamed_files} + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) + END_VERSIONS + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.html + touch ${prefix}.zip + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) + END_VERSIONS + """ +} diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml new file mode 100644 index 0000000..2b2e62b --- /dev/null +++ b/modules/nf-core/fastqc/meta.yml @@ -0,0 +1,67 @@ +name: fastqc +description: Run FastQC on sequenced reads +keywords: + - quality control + - qc + - adapters + - fastq +tools: + - fastqc: + description: | + FastQC gives general quality metrics about your reads. + It provides information about the quality score distribution + across your reads, the per base sequence content (%A/C/G/T). + + You get information about adapter contamination and other + overrepresented sequences. + homepage: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/ + documentation: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/ + licence: ["GPL-2.0-only"] + identifier: biotools:fastqc +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - reads: + type: file + description: | + List of input FastQ files of size 1 and 2 for single-end and paired-end data, + respectively. +output: + - html: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.html": + type: file + description: FastQC report + pattern: "*_{fastqc.html}" + - zip: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.zip": + type: file + description: FastQC report archive + pattern: "*_{fastqc.zip}" + - versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" +authors: + - "@drpatelh" + - "@grst" + - "@ewels" + - "@FelixKrueger" +maintainers: + - "@drpatelh" + - "@grst" + - "@ewels" + - "@FelixKrueger" diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test new file mode 100644 index 0000000..e9d79a0 --- /dev/null +++ b/modules/nf-core/fastqc/tests/main.nf.test @@ -0,0 +1,309 @@ +nextflow_process { + + name "Test Process FASTQC" + script "../main.nf" + process "FASTQC" + + tag "modules" + tag "modules_nfcore" + tag "fastqc" + + test("sarscov2 single-end [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [ id: 'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. + // looks like this:
    Mon 2 Oct 2023
    test.gz
    + // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } + ) + } + } + + test("sarscov2 paired-end [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } + ) + } + } + + test("sarscov2 interleaved [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } + ) + } + } + + test("sarscov2 paired-end [bam]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } + ) + } + } + + test("sarscov2 multiple [fastq]") { + + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, + { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, + { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } + ) + } + } + + test("sarscov2 custom_prefix") { + + when { + process { + """ + input[0] = Channel.of([ + [ id:'mysample', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } + ) + } + } + + test("sarscov2 single-end [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id: 'test', single_end:true ], + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 paired-end [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 interleaved [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 paired-end [bam] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 multiple [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 custom_prefix - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id:'mysample', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap new file mode 100644 index 0000000..d5db309 --- /dev/null +++ b/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -0,0 +1,392 @@ +{ + "sarscov2 custom_prefix": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:16.374038" + }, + "sarscov2 single-end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:24.993809" + }, + "sarscov2 custom_prefix - stub": { + "content": [ + { + "0": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:03:10.93942" + }, + "sarscov2 interleaved [fastq]": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:42.355718" + }, + "sarscov2 paired-end [bam]": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:53.276274" + }, + "sarscov2 multiple [fastq]": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:05.527626" + }, + "sarscov2 paired-end [fastq]": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:31.188871" + }, + "sarscov2 paired-end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:34.273566" + }, + "sarscov2 multiple [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:03:02.304411" + }, + "sarscov2 single-end [fastq]": { + "content": [ + [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ] + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:19.095607" + }, + "sarscov2 interleaved [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:44.640184" + }, + "sarscov2 paired-end [bam] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:53.550742" + } +} \ No newline at end of file From d40ae14e0d70e060c81bdd9576ced7922a4f5335 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:06:31 +0000 Subject: [PATCH 017/334] fix linting --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- .github/workflows/linting.yml | 2 +- .github/workflows/linting_comment.yml | 2 +- ro-crate-metadata.json | 32 ++++++++++++++++++++------- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 68ec5da..de61861 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/.github/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/.github/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/.github/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/.github/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index f2d7d1d..8b0f88c 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - name: Set up Python 3.12 + - name: Set up Python 3.13 uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.13" diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 7e8050f..d43797d 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@4c1e823582f43b179e2cbb49c3eade4e41f992e2 # v10 + uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11 with: workflow: linting.yml workflow_conclusion: completed diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index a99dec5..5b443cf 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "InProgress", "datePublished": "2025-06-03T11:01:27+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A524.04.2-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.1-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.1)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A524.04.2-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.1-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.1)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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[WIP] WORK IN PROGRESS AND NOT YET STABLE - DO NOT USE FOR PRODUCTIVE SETTINGS YET\n\n**nf-core/datasync** is a system operation pipeline that provides several workflows for handling system operation / automation tasks that are commonly helpful for various tasks in large data processing / analysis facilities. This includes:\n\n- Data Synchronization & Checksum generation\n - Configurable: Can provide YAML file which files to include or exclude from sync\n - Checksum backend: Can configure which backend to use for checksum generation (e.g. sha256sum, md5, ...)\n - Configurable whether to include (sub-) folders in the sync or not (search for checkpoint files, e.g. has to have DEMUX_DONE that signals a demultiplexing run was finished & successfully copied)\n- Data Integrity validation\n - Provided with a directory to check, can validate that file(s) found are matching checksums from Synchronization subworkflow\n- Data Archival & Deletion\n - Can check source and target location for existence of file(s) and decide based on user configurable rules whether files can be considered archived\n - Timestamp older than X days\n - Checksums match Integrity validation report\n - Create empty files to make it obvious that archival was performed\n - Optionally: Delete files or create list of files to be deleted for manual deletion process\n\nThe pipeline can be configured by users to execute any of the aforementioned subworkflows and then produces a report using MultiQC custom content that also serves as a report of _what_ was done by the pipeline for documentation purposes.\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\nNow, you can run the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n --sync\n --sync_backend 'sha256'\n --sync_done true #Creates SYNC_DONE file when done in each folder\n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -121,7 +121,11 @@ }, { "@id": "main.nf", - "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "@type": [ + "File", + "SoftwareSourceCode", + "ComputationalWorkflow" + ], "creator": [ { "@id": "https://orcid.org/0000-0002-6503-2180" @@ -130,22 +134,34 @@ "dateCreated": "", "dateModified": "2025-06-03T11:01:27Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", - "keywords": ["nf-core", "nextflow"], - "license": ["MIT"], + "keywords": [ + "nf-core", + "nextflow" + ], + "license": [ + "MIT" + ], "maintainer": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], - "name": ["nf-core/datasync"], + "name": [ + "nf-core/datasync" + ], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" }, "sdPublisher": { "@id": "https://nf-co.re/" }, - "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/dev/"], - "version": ["1.0dev"] + "url": [ + "https://github.com/nf-core/datasync", + "https://nf-co.re/datasync/dev/" + ], + "version": [ + "1.0dev" + ] }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", @@ -308,4 +324,4 @@ "name": "Alexander Peltzer" } ] -} +} \ No newline at end of file From 36690ff0c0621c9ad2bacfeca5173795cdcaa3f0 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:10:06 +0000 Subject: [PATCH 018/334] fix linting --- subworkflows/nf-core/utils_nfcore_pipeline/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index 2f30e9a..bfd2587 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -98,7 +98,7 @@ def workflowVersionToYAML() { // Get channel of software versions used in pipeline in YAML format // def softwareVersionsToYAML(ch_versions) { - return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(channel.of(workflowVersionToYAML())) + return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(Channel.of(workflowVersionToYAML())) } // From 6f449a6ff537755889730314d9c98b1e46197382 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:20:25 +0000 Subject: [PATCH 019/334] fix nextflow lint --- modules/local/sync/sync.nf | 4 ++-- nextflow.config | 21 --------------------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/modules/local/sync/sync.nf b/modules/local/sync/sync.nf index f7d8e0b..dd8d0b2 100644 --- a/modules/local/sync/sync.nf +++ b/modules/local/sync/sync.nf @@ -10,7 +10,7 @@ process SYNC { tuple val(run_id), path(origin), path(sync) // [run_id, rundir, origin] output: //We do not really have outputs, this happens in the directories already as they are just "mounted" and copied over from - tuple val(run_id), path(${run_id}_sha256_checksums.txt) , emit: synced + tuple val(run_id), path("${run_id}_sha256_checksums.txt") , emit: synced path "versions.yml" , emit: versions when: @@ -21,7 +21,7 @@ process SYNC { //Run checksums first for file in $(find ${origin} -type f) do - sha256sum ${file} >> ${run_id}_sha256_checksums.txt + sha256sum file >> ${run_id}_sha256_checksums.txt touch ${origin}/CHECKSUM_DONE ##Needs to be parameterized , currently always creates this done fi diff --git a/nextflow.config b/nextflow.config index 68a61a0..7f4d63a 100644 --- a/nextflow.config +++ b/nextflow.config @@ -269,27 +269,6 @@ validation { command = "nextflow run nf-core/datasync -profile --input samplesheet.csv --outdir " fullParameter = "help_full" showHiddenParameter = "show_hidden" - beforeText = """ --\033[2m----------------------------------------------------\033[0m- - \033[0;32m,--.\033[0;30m/\033[0;32m,-.\033[0m -\033[0;34m ___ __ __ __ ___ \033[0;32m/,-._.--~\'\033[0m -\033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m -\033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m - \033[0;32m`._,._,\'\033[0m -\033[0;35m nf-core/datasync ${manifest.version}\033[0m --\033[2m----------------------------------------------------\033[0m- -""" - afterText = """${manifest.doi ? "\n* The pipeline\n" : ""}${manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${manifest.doi ? "\n" : ""} -* The nf-core framework - https://doi.org/10.1038/s41587-020-0439-x - -* Software dependencies - https://github.com/nf-core/datasync/blob/master/CITATIONS.md -""" - } - summary { - beforeText = validation.help.beforeText - afterText = validation.help.afterText } } From 63397ad301c38856037170c1fd9dbbfc728f5331 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:24:14 +0000 Subject: [PATCH 020/334] add missing snap --- tests/default.nf.test.snap | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/default.nf.test.snap diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap new file mode 100644 index 0000000..634e59a --- /dev/null +++ b/tests/default.nf.test.snap @@ -0,0 +1,32 @@ +{ + "-profile test": { + "content": [ + 1, + { + "Workflow": { + "nf-core/datasync": "v1.0dev" + } + }, + [ + "multiqc", + "multiqc/multiqc_data", + "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc_citations.txt", + "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_datasync_software_mqc_versions.yml" + ], + [ + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "25.04.6" + }, + "timestamp": "2026-06-12T16:23:53.372790566" + } +} \ No newline at end of file From 99850139e83af538e3934f9f4b79d420d84afef3 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 17:05:34 +0000 Subject: [PATCH 021/334] nf-core version to 4.0.2 --- .nf-core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nf-core.yml b/.nf-core.yml index 82ea73d..0f562d9 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 3.3.1 +nf_core_version: 4.0.2 repository_type: pipeline template: author: Alexander Peltzer From 6c6b3a334fffca23023492fdc4f331cd3c4620c3 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 17:42:14 +0000 Subject: [PATCH 022/334] back to older nf-core version --- .nf-core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nf-core.yml b/.nf-core.yml index 0f562d9..82ea73d 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 4.0.2 +nf_core_version: 3.3.1 repository_type: pipeline template: author: Alexander Peltzer From be25fc14af2609cd39cc3ebf9b7f0f5f0f6eb52f Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 18:40:51 +0000 Subject: [PATCH 023/334] Template update for nf-core/tools version 3.3.2 --- .github/PULL_REQUEST_TEMPLATE.md | 4 +- .github/actions/nf-test/action.yml | 4 - .github/workflows/linting.yml | 2 +- .github/workflows/linting_comment.yml | 2 +- .github/workflows/nf-test.yml | 45 +++---- .github/workflows/release-announcements.yml | 2 +- .nf-core.yml | 2 +- .pre-commit-config.yaml | 2 +- README.md | 6 +- assets/schema_input.json | 6 +- conf/base.config | 1 + modules.json | 4 +- modules/nf-core/fastqc/environment.yml | 2 + modules/nf-core/fastqc/main.nf | 2 +- modules/nf-core/fastqc/meta.yml | 23 ++-- modules/nf-core/multiqc/environment.yml | 4 +- modules/nf-core/multiqc/main.nf | 4 +- modules/nf-core/multiqc/meta.yml | 110 ++++++++++-------- .../nf-core/multiqc/tests/main.nf.test.snap | 18 +-- nextflow.config | 9 +- nextflow_schema.json | 2 +- nf-test.config | 2 +- ro-crate-metadata.json | 46 +++++--- .../tests/nextflow.config | 2 +- tests/.nftignore | 1 + tests/nextflow.config | 6 +- 26 files changed, 175 insertions(+), 136 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 68ec5da..de61861 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/.github/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/.github/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/.github/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/.github/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). diff --git a/.github/actions/nf-test/action.yml b/.github/actions/nf-test/action.yml index 243e782..bf44d96 100644 --- a/.github/actions/nf-test/action.yml +++ b/.github/actions/nf-test/action.yml @@ -54,13 +54,9 @@ runs: conda-solver: libmamba conda-remove-defaults: true - # TODO Skip failing conda tests and document their failures - # https://github.com/nf-core/modules/issues/7017 - name: Run nf-test shell: bash env: - NFT_DIFF: ${{ env.NFT_DIFF }} - NFT_DIFF_ARGS: ${{ env.NFT_DIFF_ARGS }} NFT_WORKDIR: ${{ env.NFT_WORKDIR }} run: | nf-test test \ diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index f2d7d1d..8b0f88c 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - name: Set up Python 3.12 + - name: Set up Python 3.13 uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.13" diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 7e8050f..d43797d 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@4c1e823582f43b179e2cbb49c3eade4e41f992e2 # v10 + uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11 with: workflow: linting.yml workflow_conclusion: completed diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml index f03aea0..e7b5844 100644 --- a/.github/workflows/nf-test.yml +++ b/.github/workflows/nf-test.yml @@ -1,12 +1,5 @@ name: Run nf-test on: - push: - paths-ignore: - - "docs/**" - - "**/meta.yml" - - "**/*.md" - - "**/*.png" - - "**/*.svg" pull_request: paths-ignore: - "docs/**" @@ -35,7 +28,7 @@ jobs: nf-test-changes: name: nf-test-changes runs-on: # use self-hosted runners - - runs-on=$-nf-test-changes + - runs-on=${{ github.run_id }}-nf-test-changes - runner=4cpu-linux-x64 outputs: shard: ${{ steps.set-shards.outputs.shard }} @@ -69,7 +62,7 @@ jobs: needs: [nf-test-changes] if: ${{ needs.nf-test-changes.outputs.total_shards != '0' }} runs-on: # use self-hosted runners - - runs-on=$-nf-test + - runs-on=${{ github.run_id }}-nf-test - runner=4cpu-linux-x64 strategy: fail-fast: false @@ -85,7 +78,7 @@ jobs: - isMain: false profile: "singularity" NXF_VER: - - "24.04.2" + - "24.10.5" - "latest-everything" env: NXF_ANSI_LOG: false @@ -97,23 +90,39 @@ jobs: 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_DIFF: ${{ env.NFT_DIFF }} - NFT_DIFF_ARGS: ${{ env.NFT_DIFF_ARGS }} 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=$-confirm-pass + - runs-on=${{ github.run_id }}-confirm-pass - runner=2cpu-linux-x64 steps: - - name: One or more tests failed + - name: One or more tests failed (excluding latest-everything) if: ${{ contains(needs.*.result, 'failure') }} run: exit 1 @@ -132,11 +141,3 @@ jobs: echo "DEBUG: toJSON(needs) = ${{ toJSON(needs) }}" echo "DEBUG: toJSON(needs.*.result) = ${{ toJSON(needs.*.result) }}" echo "::endgroup::" - - - name: Clean Workspace # Purge the workspace in case it's running on a self-hosted runner - if: always() - run: | - ls -la ./ - rm -rf ./* || true - rm -rf ./.??* || true - ls -la ./ diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 4abaf48..0f73249 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@4aa83560bb3eac05dbad1e5f221ee339118abdd2 # v0.2.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/.nf-core.yml b/.nf-core.yml index 82ea73d..d30cf8a 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 3.3.1 +nf_core_version: 3.3.2 repository_type: pipeline template: author: Alexander Peltzer diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9d0b248..bb41bee 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.5.0 + - prettier@3.6.2 - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: diff --git a/README.md b/README.md index 4a3cc67..8e199af 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@ -[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml) +[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml) [![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) -[![Nextflow](https://img.shields.io/badge/version-%E2%89%A524.04.2-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.1-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.1) +[![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/) diff --git a/assets/schema_input.json b/assets/schema_input.json index 3147ec3..248b66e 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://raw.githubusercontent.com/nf-core/datasync/master/assets/schema_input.json", + "$id": "https://raw.githubusercontent.com/nf-core/datasync/main/assets/schema_input.json", "title": "nf-core/datasync pipeline - params.input schema", "description": "Schema for the file provided with params.input", "type": "array", @@ -17,14 +17,14 @@ "type": "string", "format": "file-path", "exists": true, - "pattern": "^\\S+\\.f(ast)?q\\.gz$", + "pattern": "^([\\S\\s]*\\/)?[^\\s\\/]+\\.f(ast)?q\\.gz$", "errorMessage": "FastQ file for reads 1 must be provided, cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" }, "fastq_2": { "type": "string", "format": "file-path", "exists": true, - "pattern": "^\\S+\\.f(ast)?q\\.gz$", + "pattern": "^([\\S\\s]*\\/)?[^\\s\\/]+\\.f(ast)?q\\.gz$", "errorMessage": "FastQ file for reads 2 cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" } }, diff --git a/conf/base.config b/conf/base.config index 8a59c38..24db1e3 100644 --- a/conf/base.config +++ b/conf/base.config @@ -61,5 +61,6 @@ process { } withLabel: process_gpu { ext.use_gpu = { workflow.profile.contains('gpu') } + accelerator = { workflow.profile.contains('gpu') ? 1 : null } } } diff --git a/modules.json b/modules.json index ac0474c..8e1bd7b 100644 --- a/modules.json +++ b/modules.json @@ -7,12 +7,12 @@ "nf-core": { "fastqc": { "branch": "master", - "git_sha": "08108058ea36a63f141c25c4e75f9f872a5b2296", + "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "f0719ae309075ae4a291533883847c3f7c441dad", + "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", "installed_by": ["modules"] } } diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml index 691d4c7..f9f54ee 100644 --- a/modules/nf-core/fastqc/environment.yml +++ b/modules/nf-core/fastqc/environment.yml @@ -1,3 +1,5 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json channels: - conda-forge - bioconda diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 033f415..23e1663 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -29,7 +29,7 @@ process FASTQC { // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 // Dividing the task.memory by task.cpu allows to stick to requested amount of RAM in the label - def memory_in_mb = task.memory ? task.memory.toUnit('MB').toFloat() / task.cpus : null + def memory_in_mb = task.memory ? task.memory.toUnit('MB') / task.cpus : null // FastQC memory value allowed range (100 - 10000) def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml index 2b2e62b..c8d9d02 100644 --- a/modules/nf-core/fastqc/meta.yml +++ b/modules/nf-core/fastqc/meta.yml @@ -29,9 +29,10 @@ input: description: | List of input FastQ files of size 1 and 2 for single-end and paired-end data, respectively. + ontologies: [] output: - - html: - - meta: + html: + - - meta: type: map description: | Groovy Map containing sample information @@ -40,8 +41,9 @@ output: type: file description: FastQC report pattern: "*_{fastqc.html}" - - zip: - - meta: + ontologies: [] + zip: + - - meta: type: map description: | Groovy Map containing sample information @@ -50,11 +52,14 @@ output: type: file description: FastQC report archive pattern: "*_{fastqc.zip}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@drpatelh" - "@grst" diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index a27122c..812fc4c 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -1,5 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.27 + - bioconda::multiqc=1.29 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 58d9313..0ac3c36 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -3,8 +3,8 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.27--pyhdfd78af_0' : - 'biocontainers/multiqc:1.27--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.29--pyhdfd78af_0' : + 'biocontainers/multiqc:1.29--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index b16c187..ce30eb7 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -15,57 +15,71 @@ tools: licence: ["GPL-3.0-or-later"] identifier: biotools:multiqc input: - - - multiqc_files: - type: file - description: | - List of reports / files recognised by MultiQC, for example the html and zip output of FastQC - - - multiqc_config: - type: file - description: Optional config yml for MultiQC - pattern: "*.{yml,yaml}" - - - extra_multiqc_config: - type: file - description: Second optional config yml for MultiQC. Will override common sections - in multiqc_config. - pattern: "*.{yml,yaml}" - - - multiqc_logo: + - multiqc_files: + type: file + description: | + List of reports / files recognised by MultiQC, for example the html and zip output of FastQC + ontologies: [] + - multiqc_config: + type: file + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML + - extra_multiqc_config: + type: file + description: Second optional config yml for MultiQC. Will override common sections + in multiqc_config. + pattern: "*.{yml,yaml}" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML + - multiqc_logo: + type: file + description: Optional logo file for MultiQC + pattern: "*.{png}" + ontologies: [] + - replace_names: + type: file + description: | + Optional two-column sample renaming file. First column a set of + patterns, second column a set of corresponding replacements. Passed via + MultiQC's `--replace-names` option. + pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 # TSV + - sample_names: + type: file + description: | + Optional TSV file with headers, passed to the MultiQC --sample_names + argument. + pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 # TSV +output: + report: + - "*multiqc_report.html": type: file - description: Optional logo file for MultiQC - pattern: "*.{png}" - - - replace_names: + description: MultiQC report file + pattern: "multiqc_report.html" + ontologies: [] + data: + - "*_data": + type: directory + description: MultiQC data dir + pattern: "multiqc_data" + plots: + - "*_plots": type: file - description: | - Optional two-column sample renaming file. First column a set of - patterns, second column a set of corresponding replacements. Passed via - MultiQC's `--replace-names` option. - pattern: "*.{tsv}" - - - sample_names: + description: Plots created by MultiQC + pattern: "*_data" + ontologies: [] + versions: + - versions.yml: type: file - description: | - Optional TSV file with headers, passed to the MultiQC --sample_names - argument. - pattern: "*.{tsv}" -output: - - report: - - "*multiqc_report.html": - type: file - description: MultiQC report file - pattern: "multiqc_report.html" - - data: - - "*_data": - type: directory - description: MultiQC data dir - pattern: "multiqc_data" - - plots: - - "*_plots": - type: file - description: Plots created by MultiQC - pattern: "*_data" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@abhi18av" - "@bunop" diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index 7b7c132..88e9057 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "multiqc_versions_single": { "content": [ [ - "versions.yml:md5,8f3b8c1cec5388cf2708be948c9fa42f" + "versions.yml:md5,c1fe644a37468f6dae548d98bc72c2c1" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.4" + "nextflow": "25.04.2" }, - "timestamp": "2025-01-27T09:29:57.631982377" + "timestamp": "2025-05-22T11:50:41.182332996" }, "multiqc_stub": { "content": [ @@ -17,25 +17,25 @@ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,8f3b8c1cec5388cf2708be948c9fa42f" + "versions.yml:md5,c1fe644a37468f6dae548d98bc72c2c1" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.4" + "nextflow": "25.04.2" }, - "timestamp": "2025-01-27T09:30:34.743726958" + "timestamp": "2025-05-22T11:51:22.448739369" }, "multiqc_versions_config": { "content": [ [ - "versions.yml:md5,8f3b8c1cec5388cf2708be948c9fa42f" + "versions.yml:md5,c1fe644a37468f6dae548d98bc72c2c1" ] ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.4" + "nextflow": "25.04.2" }, - "timestamp": "2025-01-27T09:30:21.44383553" + "timestamp": "2025-05-22T11:51:06.198928424" } } \ No newline at end of file diff --git a/nextflow.config b/nextflow.config index 68a61a0..63b7fc3 100644 --- a/nextflow.config +++ b/nextflow.config @@ -235,7 +235,6 @@ dag { manifest { name = 'nf-core/datasync' - author = """Alexander Peltzer""" // The author field is deprecated from Nextflow version 24.10.0, use contributors instead contributors = [ // TODO nf-core: Update the field with the details of the contributors to your pipeline. New with Nextflow version 24.10.0 [ @@ -250,15 +249,15 @@ manifest { homePage = 'https://github.com/nf-core/datasync' description = """A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.""" mainScript = 'main.nf' - defaultBranch = 'master' - nextflowVersion = '!>=24.04.2' + defaultBranch = 'main' + nextflowVersion = '!>=24.10.5' version = '1.0dev' doi = '' } // Nextflow plugins plugins { - id 'nf-schema@2.3.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 { @@ -284,7 +283,7 @@ validation { https://doi.org/10.1038/s41587-020-0439-x * Software dependencies - https://github.com/nf-core/datasync/blob/master/CITATIONS.md + https://github.com/nf-core/datasync/blob/main/CITATIONS.md """ } summary { diff --git a/nextflow_schema.json b/nextflow_schema.json index d9e3dd8..a0b283e 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://raw.githubusercontent.com/nf-core/datasync/master/nextflow_schema.json", + "$id": "https://raw.githubusercontent.com/nf-core/datasync/main/nextflow_schema.json", "title": "nf-core/datasync pipeline parameters", "description": "A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.", "type": "object", diff --git a/nf-test.config b/nf-test.config index 889df76..3a1fff5 100644 --- a/nf-test.config +++ b/nf-test.config @@ -9,7 +9,7 @@ config { configFile "tests/nextflow.config" // ignore tests coming from the nf-core/modules repo - ignore 'modules/nf-core/**/*', 'subworkflows/nf-core/**/*' + ignore 'modules/nf-core/**/tests/*', 'subworkflows/nf-core/**/tests/*' // run all test with defined profile(s) from the main nextflow.config profile "test" diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index a99dec5..e13b950 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -22,8 +22,8 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "InProgress", - "datePublished": "2025-06-03T11:01:27+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A524.04.2-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.1-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.1)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "datePublished": "2026-06-12T18:40:42+00:00", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#6e1856e4-68ad-483f-95f4-97b1f4ec6a75" + "@id": "#2ee1040b-6496-408f-a4f1-da9334861141" } ], "name": "nf-core/datasync" @@ -121,31 +121,47 @@ }, { "@id": "main.nf", - "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "@type": [ + "File", + "SoftwareSourceCode", + "ComputationalWorkflow" + ], "creator": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], "dateCreated": "", - "dateModified": "2025-06-03T11:01:27Z", + "dateModified": "2026-06-12T18:40:42Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", - "keywords": ["nf-core", "nextflow"], - "license": ["MIT"], + "keywords": [ + "nf-core", + "nextflow" + ], + "license": [ + "MIT" + ], "maintainer": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], - "name": ["nf-core/datasync"], + "name": [ + "nf-core/datasync" + ], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" }, "sdPublisher": { "@id": "https://nf-co.re/" }, - "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/dev/"], - "version": ["1.0dev"] + "url": [ + "https://github.com/nf-core/datasync", + "https://nf-co.re/datasync/dev/" + ], + "version": [ + "1.0dev" + ] }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", @@ -157,14 +173,14 @@ "url": { "@id": "https://www.nextflow.io/" }, - "version": "!>=24.04.2" + "version": "!>=24.10.5" }, { - "@id": "#6e1856e4-68ad-483f-95f4-97b1f4ec6a75", + "@id": "#2ee1040b-6496-408f-a4f1-da9334861141", "@type": "TestSuite", "instance": [ { - "@id": "#8316b07c-aa2f-4100-b61a-d1aa1321ccfd" + "@id": "#b2bb2540-4adb-49b2-a272-31ef8ae53dba" } ], "mainEntity": { @@ -173,7 +189,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#8316b07c-aa2f-4100-b61a-d1aa1321ccfd", + "@id": "#b2bb2540-4adb-49b2-a272-31ef8ae53dba", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/nf-test.yml", @@ -308,4 +324,4 @@ "name": "Alexander Peltzer" } ] -} +} \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config index 0907ac5..09ef842 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 c10bc1f..158c83c 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -1,5 +1,6 @@ .DS_Store multiqc/multiqc_data/fastqc_top_overrepresented_sequences_table.txt +multiqc/multiqc_data/BETA-multiqc.parquet multiqc/multiqc_data/multiqc.log multiqc/multiqc_data/multiqc_data.json multiqc/multiqc_data/multiqc_sources.txt diff --git a/tests/nextflow.config b/tests/nextflow.config index 12b4c0a..247cc7f 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -6,7 +6,9 @@ // TODO nf-core: Specify any additional parameters here // Or any resources requirements -params.modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' -params.pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync' +params { + modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' + pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync' +} aws.client.anonymous = true // fixes S3 access issues on self-hosted runners From 5406163a9b8825089ce9478dc8657a4722beb8fe Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 18:45:44 +0000 Subject: [PATCH 024/334] Template update for nf-core/tools version 4.0.2 --- .devcontainer/devcontainer.json | 29 +- .devcontainer/setup.sh | 13 + .github/CONTRIBUTING.md | 125 -- .github/PULL_REQUEST_TEMPLATE.md | 4 +- .github/actions/get-shards/action.yml | 2 +- .github/actions/nf-test/action.yml | 14 +- .github/workflows/awsfulltest.yml | 37 +- .github/workflows/awstest.yml | 16 +- .github/workflows/branch.yml | 2 +- .github/workflows/clean-up.yml | 2 +- .github/workflows/download_pipeline.yml | 18 +- .github/workflows/fix_linting.yml | 32 +- .github/workflows/linting.yml | 36 +- .github/workflows/linting_comment.yml | 4 +- .github/workflows/nf-test.yml | 9 +- .github/workflows/release-announcements.yml | 10 +- .../workflows/template-version-comment.yml | 6 +- .gitignore | 1 + .gitpod.yml | 10 - .nf-core.yml | 2 +- .pre-commit-config.yaml | 18 +- .prettierignore | 5 +- README.md | 13 +- assets/adaptivecard.json | 67 - assets/slackreport.json | 34 - conf/base.config | 2 +- conf/containers_conda_lock_files_amd64.config | 2 + conf/containers_conda_lock_files_arm64.config | 2 + conf/containers_docker_amd64.config | 2 + conf/containers_docker_arm64.config | 2 + .../containers_singularity_https_amd64.config | 2 + .../containers_singularity_https_arm64.config | 2 + conf/containers_singularity_oras_amd64.config | 2 + conf/containers_singularity_oras_arm64.config | 2 + docs/CONTRIBUTING.md | 185 ++ docs/usage.md | 10 +- main.nf | 12 +- modules.json | 10 +- .../linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt | 822 +++++++++ .../linux_arm64-bd-e455e32f745abe68_1.txt | 769 ++++++++ modules/nf-core/fastqc/main.nf | 43 +- modules/nf-core/fastqc/meta.yml | 51 +- modules/nf-core/fastqc/tests/main.nf.test | 12 +- .../nf-core/fastqc/tests/main.nf.test.snap | 228 ++- .../linux_amd64-bd-c1f4a7982b743963_1.txt | 1552 +++++++++++++++++ .../linux_amd64-bd-db7c73dae76bc9e6_1.txt | 126 ++ .../linux_arm64-bd-40bf3b435e89dc22_1.txt | 1502 ++++++++++++++++ .../linux_arm64-bd-d167b8012595a136_1.txt | 125 ++ modules/nf-core/multiqc/environment.yml | 2 +- modules/nf-core/multiqc/main.nf | 51 +- modules/nf-core/multiqc/meta.yml | 165 +- .../multiqc/tests/custom_prefix.config | 5 + modules/nf-core/multiqc/tests/main.nf.test | 191 +- .../nf-core/multiqc/tests/main.nf.test.snap | 435 ++++- modules/nf-core/multiqc/tests/nextflow.config | 1 + modules/nf-core/multiqc/tests/tags.yml | 2 - nextflow.config | 66 +- nextflow_schema.json | 20 +- nf-test.config | 26 +- ro-crate-metadata.json | 23 +- .../utils_nfcore_datasync_pipeline/main.nf | 52 +- .../utils_nextflow_pipeline/tests/tags.yml | 2 - .../nf-core/utils_nfcore_pipeline/main.nf | 68 +- .../utils_nfcore_pipeline/tests/main.nf.test | 29 + .../tests/main.nf.test.snap | 19 + .../utils_nfcore_pipeline/tests/tags.yml | 2 - .../nf-core/utils_nfschema_plugin/main.nf | 41 +- .../utils_nfschema_plugin/tests/main.nf.test | 56 + .../tests/nextflow.config | 4 +- tests/.nftignore | 3 +- tests/default.nf.test | 16 +- tests/nextflow.config | 2 +- workflows/datasync.nf | 100 +- 73 files changed, 6503 insertions(+), 852 deletions(-) create mode 100755 .devcontainer/setup.sh delete mode 100644 .github/CONTRIBUTING.md delete mode 100644 .gitpod.yml delete mode 100644 assets/adaptivecard.json delete mode 100644 assets/slackreport.json create mode 100644 conf/containers_conda_lock_files_amd64.config create mode 100644 conf/containers_conda_lock_files_arm64.config create mode 100644 conf/containers_docker_amd64.config create mode 100644 conf/containers_docker_arm64.config create mode 100644 conf/containers_singularity_https_amd64.config create mode 100644 conf/containers_singularity_https_arm64.config create mode 100644 conf/containers_singularity_oras_amd64.config create mode 100644 conf/containers_singularity_oras_arm64.config create mode 100644 docs/CONTRIBUTING.md create mode 100644 modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt create mode 100644 modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt create mode 100644 modules/nf-core/multiqc/tests/custom_prefix.config delete mode 100644 modules/nf-core/multiqc/tests/tags.yml delete mode 100644 subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap delete mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b290e09..237c9ed 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,20 +1,21 @@ { + "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json", "name": "nfcore", - "image": "nfcore/gitpod:latest", - "remoteUser": "gitpod", - "runArgs": ["--privileged"], + "image": "nfcore/devcontainer:latest", - // Configure tool-specific properties. - "customizations": { - // Configure properties specific to VS Code. - "vscode": { - // Set *default* container specific settings.json values on container create. - "settings": { - "python.defaultInterpreterPath": "/opt/conda/bin/python" - }, + "remoteUser": "root", + "privileged": true, - // Add the IDs of extensions you want installed when the container is created. - "extensions": ["ms-python.python", "ms-python.vscode-pylance", "nf-core.nf-core-extensionpack"] - } + "remoteEnv": { + // Workspace path on the host for mounting with docker-outside-of-docker + "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" + }, + + "onCreateCommand": "./.devcontainer/setup.sh", + + "hostRequirements": { + "cpus": 4, + "memory": "16gb", + "storage": "32gb" } } diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh new file mode 100755 index 0000000..c0ca3c6 --- /dev/null +++ b/.devcontainer/setup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Customise the terminal command prompt +echo "export PROMPT_DIRTRIM=2" >> $HOME/.bashrc +echo "export PS1='\[\e[3;36m\]\w ->\[\e[0m\\] '" >> $HOME/.bashrc +export PROMPT_DIRTRIM=2 +export PS1='\[\e[3;36m\]\w ->\[\e[0m\\] ' + +# Update Nextflow +nextflow self-update + +# Update welcome message +echo "Welcome to the nf-core/datasync devcontainer!" > /usr/local/etc/vscode-dev-containers/first-run-notice.txt diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index 8aed170..0000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,125 +0,0 @@ -# `nf-core/datasync`: Contributing Guidelines - -Hi there! -Many thanks for taking an interest in improving nf-core/datasync. - -We try to manage the required tasks for nf-core/datasync using GitHub issues, you probably came to this page when creating one. -Please use the pre-filled template to save time. - -However, don't be put off by this template - other more general issues and suggestions are welcome! -Contributions to the code are even more welcome ;) - -> [!NOTE] -> If you need help using or modifying nf-core/datasync then the best place to ask is on the nf-core Slack [#datasync](https://nfcore.slack.com/channels/datasync) channel ([join our Slack here](https://nf-co.re/join/slack)). - -## Contribution workflow - -If you'd like to write some code for nf-core/datasync, the standard workflow is as follows: - -1. Check that there isn't already an issue about your idea in the [nf-core/datasync issues](https://github.com/nf-core/datasync/issues) to avoid duplicating work. If there isn't one already, please create one so that others know you're working on this -2. [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [nf-core/datasync repository](https://github.com/nf-core/datasync) to your GitHub account -3. Make the necessary changes / additions within your forked repository following [Pipeline conventions](#pipeline-contribution-conventions) -4. Use `nf-core pipelines schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). -5. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged - -If you're not used to this workflow with git, you can start with some [docs from GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests) or even their [excellent `git` resources](https://try.github.io/). - -## Tests - -You have the option to test your changes locally by running the pipeline. For receiving warnings about process selectors and other `debug` information, it is recommended to use the debug profile. Execute all the tests with the following command: - -```bash -nf-test test --profile debug,test,docker --verbose -``` - -When you create a pull request with changes, [GitHub Actions](https://github.com/features/actions) will run automatic tests. -Typically, pull-requests are only fully reviewed when these tests are passing, though of course we can help out before then. - -There are typically two types of tests that run: - -### Lint tests - -`nf-core` has a [set of guidelines](https://nf-co.re/developers/guidelines) which all pipelines must adhere to. -To enforce these and ensure that all pipelines stay in sync, we have developed a helper tool which runs checks on the pipeline code. This is in the [nf-core/tools repository](https://github.com/nf-core/tools) and once installed can be run locally with the `nf-core pipelines lint ` command. - -If any failures or warnings are encountered, please follow the listed URL for more documentation. - -### Pipeline tests - -Each `nf-core` pipeline should be set up with a minimal set of test-data. -`GitHub Actions` then runs the pipeline on this data to ensure that it exits successfully. -If there are any failures then the automated tests fail. -These tests are run both with the latest available version of `Nextflow` and also the minimum required version that is stated in the pipeline code. - -## Patch - -:warning: Only in the unlikely and regretful event of a release happening with a bug. - -- On your own fork, make a new branch `patch` based on `upstream/main` or `upstream/master`. -- Fix the bug, and bump version (X.Y.Z+1). -- Open a pull-request from `patch` to `main`/`master` with the changes. - -## Getting help - -For further information/help, please consult the [nf-core/datasync documentation](https://nf-co.re/datasync/usage) and don't hesitate to get in touch on the nf-core Slack [#datasync](https://nfcore.slack.com/channels/datasync) channel ([join our Slack here](https://nf-co.re/join/slack)). - -## Pipeline contribution conventions - -To make the `nf-core/datasync` code and processing logic more understandable for new contributors and to ensure quality, we semi-standardise the way the code and other contributions are written. - -### Adding a new step - -If you wish to contribute a new step, please use the following coding standards: - -1. Define the corresponding input channel into your new process from the expected previous process channel. -2. Write the process block (see below). -3. Define the output channel if needed (see below). -4. Add any new parameters to `nextflow.config` with a default (see below). -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 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`. - -### Default values - -Parameters should be initialised / defined with default values within the `params` scope in `nextflow.config`. - -Once there, use `nf-core pipelines schema build` to add to `nextflow_schema.json`. - -### Default processes resource requirements - -Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/main/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. - -The process resources can be passed on to the tool dynamically within the process with the `${task.cpus}` and `${task.memory}` variables in the `script:` block. - -### Naming schemes - -Please use the following naming schemes, to make it easy to understand what is going where. - -- initial process channel: `ch_output_from_` -- intermediate and terminal channels: `ch__for_` - -### Nextflow version bumping - -If you are using a new feature from core Nextflow, you may bump the minimum required version of nextflow in the pipeline with: `nf-core pipelines bump-version --nextflow . [min-nf-version]` - -### Images and figures - -For overview images and other documents we follow the nf-core [style guidelines and examples](https://nf-co.re/developers/design_guidelines). - -## GitHub Codespaces - -This repo includes a devcontainer configuration which will create a GitHub Codespaces for Nextflow development! This is an online developer environment that runs in your browser, complete with VSCode and a terminal. - -To get started: - -- Open the repo in [Codespaces](https://github.com/nf-core/datasync/codespaces) -- Tools installed - - nf-core - - Nextflow - -Devcontainer specs: - -- [DevContainer config](.devcontainer/devcontainer.json) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index de61861..87aab4d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/.github/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/.github/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). diff --git a/.github/actions/get-shards/action.yml b/.github/actions/get-shards/action.yml index 3408527..e2833ee 100644 --- a/.github/actions/get-shards/action.yml +++ b/.github/actions/get-shards/action.yml @@ -21,7 +21,7 @@ runs: using: "composite" steps: - name: Install nf-test - uses: nf-core/setup-nf-test@v1 + uses: nf-core/setup-nf-test@4069fbbaabe94c08faba4ad261bfa88225ba133f # v2 with: version: ${{ env.NFT_VER }} - name: Get number of shards diff --git a/.github/actions/nf-test/action.yml b/.github/actions/nf-test/action.yml index bf44d96..ad686e8 100644 --- a/.github/actions/nf-test/action.yml +++ b/.github/actions/nf-test/action.yml @@ -20,24 +20,24 @@ runs: using: "composite" steps: - name: Setup Nextflow - uses: nf-core/setup-nextflow@v2 + uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 with: version: "${{ env.NXF_VERSION }}" - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: - python-version: "3.13" + python-version: "3.14" - name: Install nf-test - uses: nf-core/setup-nf-test@v1 + uses: nf-core/setup-nf-test@4069fbbaabe94c08faba4ad261bfa88225ba133f # v2 with: version: "${{ env.NFT_VER }}" install-pdiff: true - name: Setup apptainer if: contains(inputs.profile, 'singularity') - uses: eWaterCycle/setup-apptainer@main + uses: eWaterCycle/setup-apptainer@3f706d898c9db585b1d741b4692e66755f3a1b40 # v2 - name: Set up Singularity if: contains(inputs.profile, 'singularity') @@ -48,10 +48,12 @@ runs: - name: Conda setup if: contains(inputs.profile, 'conda') - uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3 + uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4 with: auto-update-conda: true conda-solver: libmamba + channels: conda-forge + channel-priority: strict conda-remove-defaults: true - name: Run nf-test diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 5f5aa19..b498008 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -23,26 +23,45 @@ jobs: echo "revision=${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'release') && github.sha || 'dev' }}" >> "$GITHUB_OUTPUT" - name: Launch workflow via Seqera Platform - uses: seqeralabs/action-tower-launch@v2 + uses: seqeralabs/action-tower-launch@51565b514bff1827cf34620de25d0055759f1fc9 # v2 # TODO nf-core: You can customise AWS full pipeline tests as required # Add full size test data (but still relatively small datasets for few samples) # on the `test_full.config` test runs with only one set of parameters with: - workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} + workspace_id: ${{ vars.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} - compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + compute_env: ${{ vars.TOWER_COMPUTE_ENV }} revision: ${{ steps.revision.outputs.revision }} - workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/datasync/work-${{ steps.revision.outputs.revision }} + workdir: s3://${{ vars.AWS_S3_BUCKET }}/work/datasync/work-${{ steps.revision.outputs.revision }} + nextflow_config: | + plugins { + id 'nf-slack@0.5.0' + } + slack { + enabled = true + bot { + token = '${{ secrets.NFSLACK_BOT_TOKEN }}' + channel = 'datasync' + } + onStart { + enabled = false + } + onComplete { + message = ':white_check_mark: *datasync/test_full* completed successfully! :tada:' + } + onError { + message = ':x: *datasync/test_full* failed :crying_cat_face:' + } + } parameters: | { - "hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}", - "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/datasync/results-${{ steps.revision.outputs.revision }}" + "outdir": "s3://${{ vars.AWS_S3_BUCKET }}/datasync/results-${{ steps.revision.outputs.revision }}" } profiles: test_full - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: Seqera Platform debug log file path: | - seqera_platform_action_*.log - seqera_platform_action_*.json + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index d937e2f..b9e6efa 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -12,22 +12,22 @@ jobs: steps: # Launch workflow using Seqera Platform CLI tool action - name: Launch workflow via Seqera Platform - uses: seqeralabs/action-tower-launch@v2 + uses: seqeralabs/action-tower-launch@51565b514bff1827cf34620de25d0055759f1fc9 # v2 with: - workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} + workspace_id: ${{ vars.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} - compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + compute_env: ${{ vars.TOWER_COMPUTE_ENV }} revision: ${{ github.sha }} - workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/datasync/work-${{ github.sha }} + workdir: s3://${{ vars.AWS_S3_BUCKET }}/work/datasync/work-${{ github.sha }} parameters: | { - "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/datasync/results-test-${{ github.sha }}" + "outdir": "s3://${{ vars.AWS_S3_BUCKET }}/datasync/results-test-${{ github.sha }}" } profiles: test - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: Seqera Platform debug log file path: | - seqera_platform_action_*.log - seqera_platform_action_*.json + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 72e58e1..7716a7b 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -21,7 +21,7 @@ jobs: # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets - name: Post PR comment if: failure() - uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 + uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3 with: message: | ## This PR is against the `${{github.event.pull_request.base.ref}}` branch :x: diff --git a/.github/workflows/clean-up.yml b/.github/workflows/clean-up.yml index ac030fd..172de6f 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@5bef64f19d7facfb25b37b414482c7164d639639 # v9 + - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10 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 999bcc3..a7bf4fc 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -38,15 +38,18 @@ jobs: runs-on: ubuntu-latest needs: configure steps: + - name: Check out pipeline code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - name: Install Nextflow - uses: nf-core/setup-nextflow@v2 + uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 - name: Disk space cleanup uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: - python-version: "3.13" + python-version: "3.14" architecture: "x64" - name: Setup Apptainer @@ -54,10 +57,15 @@ jobs: with: apptainer-version: 1.3.4 + - name: Read .nf-core.yml + id: read_yml + run: | + echo "nf_core_version=$(yq '.nf_core_version' ${{ github.workspace }}/.nf-core.yml)" >> "$GITHUB_OUTPUT" + - name: Install dependencies run: | python -m pip install --upgrade pip - pip install git+https://github.com/nf-core/tools.git@dev + pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} - name: Make a cache directory for the container images run: | @@ -127,7 +135,7 @@ jobs: fi - name: Upload Nextflow logfile for debugging purposes - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: nextflow_logfile.txt path: .nextflow.log* diff --git a/.github/workflows/fix_linting.yml b/.github/workflows/fix_linting.yml index 42f855d..8837738 100644 --- a/.github/workflows/fix_linting.yml +++ b/.github/workflows/fix_linting.yml @@ -13,13 +13,13 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: token: ${{ secrets.nf_core_bot_auth_token }} # indication that the linting is being fixed - name: React on comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: eyes @@ -31,30 +31,26 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} - # Install and run pre-commit - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: "3.13" - - - name: Install pre-commit - run: pip install pre-commit + - name: Install Nextflow + uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 - - name: Run pre-commit - id: pre-commit - run: pre-commit run --all-files + # Install and run prek + - name: Run prek + id: prek + uses: j178/prek-action@6ad80277337ad479fe43bd70701c3f7f8aa74db3 # v2 continue-on-error: true # indication that the linting has finished - name: react if linting finished succesfully - if: steps.pre-commit.outcome == 'success' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + if: steps.prek.outcome == 'success' + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: "+1" - name: Commit & push changes id: commit-and-push - if: steps.pre-commit.outcome == 'failure' + if: steps.prek.outcome == 'failure' run: | git config user.email "core@nf-co.re" git config user.name "nf-core-bot" @@ -67,21 +63,21 @@ jobs: - name: react if linting errors were fixed id: react-if-fixed if: steps.commit-and-push.outcome == 'success' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: hooray - name: react if linting errors were not fixed if: steps.commit-and-push.outcome == 'failure' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: confused - name: react if linting errors were not fixed if: steps.commit-and-push.outcome == 'failure' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: issue-number: ${{ github.event.issue.number }} body: | diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 8b0f88c..8738ffc 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -11,33 +11,31 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - name: Set up Python 3.13 - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: "3.13" - - - name: Install pre-commit - run: pip install pre-commit + - name: Install Nextflow + uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 - - name: Run pre-commit - run: pre-commit run --all-files + - name: Run prek + uses: j178/prek-action@6ad80277337ad479fe43bd70701c3f7f8aa74db3 # v2 nf-core: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Install Nextflow - uses: nf-core/setup-nextflow@v2 + uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: - python-version: "3.13" + python-version: "3.14" architecture: "x64" + - name: Setup uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + - name: read .nf-core.yml uses: pietrobolcato/action-read-yaml@9f13718d61111b69f30ab4ac683e67a56d254e1d # 1.1.0 id: read_yml @@ -45,12 +43,10 @@ jobs: config: ${{ github.workspace }}/.nf-core.yml - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} + run: uv tool install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} - name: Run nf-core pipelines lint - if: ${{ github.base_ref != 'master' }} + if: ${{ github.base_ref != 'master' || github.base_ref != 'main' }} env: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -58,7 +54,7 @@ jobs: run: nf-core -l lint_log.txt pipelines lint --dir ${GITHUB_WORKSPACE} --markdown lint_results.md - name: Run nf-core pipelines lint --release - if: ${{ github.base_ref == 'master' }} + if: ${{ github.base_ref == 'master' || github.base_ref == 'main' }} env: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -71,7 +67,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index d43797d..5b0c24f 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@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11 + uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 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@52423e01640425a022ef5fd42c6fb5f633a02728 # v2 + uses: marocchino/sticky-pull-request-comment@70d2764d1a7d5d9560b100cbea0077fc8f633987 # v3 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 index e7b5844..efd72d6 100644 --- a/.github/workflows/nf-test.yml +++ b/.github/workflows/nf-test.yml @@ -18,7 +18,7 @@ concurrency: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NFT_VER: "0.9.2" + NFT_VER: "0.9.4" NFT_WORKDIR: "~" NXF_ANSI_LOG: false NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity @@ -40,7 +40,7 @@ jobs: rm -rf ./* || true rm -rf ./.??* || true ls -la ./ - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 @@ -78,14 +78,14 @@ jobs: - isMain: false profile: "singularity" NXF_VER: - - "24.10.5" + - "25.10.4" - "latest-everything" env: NXF_ANSI_LOG: false TOTAL_SHARDS: ${{ needs.nf-test-changes.outputs.total_shards }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 @@ -95,6 +95,7 @@ jobs: continue-on-error: ${{ matrix.NXF_VER == 'latest-everything' }} env: NFT_WORKDIR: ${{ env.NFT_WORKDIR }} + NXF_VERSION: ${{ matrix.NXF_VER }} with: profile: ${{ matrix.profile }} shard: ${{ matrix.shard }} diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 0f73249..78d5dbe 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -14,7 +14,11 @@ jobs: run: | echo "topics=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ')" | sed 's/-//g' >> $GITHUB_OUTPUT - - uses: rzr/fediverse-action@master + - name: get description + id: get_description + run: | + echo "description=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .description')" >> $GITHUB_OUTPUT + - uses: rzr/fediverse-action@563159eb8d45f70ab6aaba36ed55cd037e51f441 # master with: access-token: ${{ secrets.MASTODON_ACCESS_TOKEN }} host: "mstdn.science" # custom host if not "mastodon.social" (default) @@ -22,7 +26,7 @@ jobs: # https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#release message: | Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! - + ${{ steps.get_description.outputs.description }} Please see the changelog: ${{ github.event.release.html_url }} ${{ steps.get_topics.outputs.topics }} #nfcore #openscience #nextflow #bioinformatics @@ -30,7 +34,7 @@ jobs: bsky-post: runs-on: ubuntu-latest steps: - - uses: zentered/bluesky-post-action@6461056ea355ea43b977e149f7bf76aaa572e5e8 # v0.3.0 + - uses: zentered/bluesky-post-action@5a91cc2ad10a304a4e96c16182dbe4918710bcf6 # v0.4.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 index beb5c77..ea30827 100644 --- a/.github/workflows/template-version-comment.yml +++ b/.github/workflows/template-version-comment.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.sha }} @@ -29,7 +29,7 @@ jobs: run: echo "OUTPUT=$(pip list --outdated | grep nf-core)" >> ${GITHUB_ENV} - name: Post nf-core template version comment - uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 + uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3 if: | contains(env.OUTPUT, 'nf-core') with: @@ -42,5 +42,5 @@ jobs: > Your pipeline is using an old version of the nf-core template: ${{ steps.read_yml.outputs['nf_core_version'] }}. > Please update your pipeline to the latest version. > - > For more documentation on how to update your pipeline, please see the [nf-core documentation](https://github.com/nf-core/tools?tab=readme-ov-file#sync-a-pipeline-with-the-template) and [Synchronisation documentation](https://nf-co.re/docs/contributing/sync). + > For more documentation on how to update your pipeline, please see the [Synchronisation documentation](https://nf-co.re/docs/developing/template-syncs/overview). # diff --git a/.gitignore b/.gitignore index a42ce01..cc2b1a7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ testing/ testing* *.pyc null/ +.lineage/ diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index 83599f6..0000000 --- a/.gitpod.yml +++ /dev/null @@ -1,10 +0,0 @@ -image: nfcore/gitpod:latest -tasks: - - name: Update Nextflow and setup pre-commit - command: | - pre-commit install --install-hooks - nextflow self-update - -vscode: - extensions: - - nf-core.nf-core-extensionpack # https://github.com/nf-core/vscode-extensionpack diff --git a/.nf-core.yml b/.nf-core.yml index d30cf8a..0f562d9 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 3.3.2 +nf_core_version: 4.0.2 repository_type: pipeline template: author: Alexander Peltzer diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bb41bee..f51e1a2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,24 +4,30 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.6.2 + - prettier@3.8.3 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: trailing-whitespace args: [--markdown-linebreak-ext=md] exclude: | (?x)^( .*ro-crate-metadata.json$| - modules/nf-core/.*| - subworkflows/nf-core/.*| + modules/(?!local/).*| + subworkflows/(?!local/).*| .*\.snap$ )$ - id: end-of-file-fixer exclude: | (?x)^( .*ro-crate-metadata.json$| - modules/nf-core/.*| - subworkflows/nf-core/.*| + modules/(?!local/).*| + subworkflows/(?!local/).*| .*\.snap$ )$ + - repo: https://github.com/seqeralabs/nf-lint-pre-commit + rev: v0.3.0 + hooks: + - id: nextflow-lint + files: '\.nf$|nextflow\.config$' + args: ["-output", "json"] diff --git a/.prettierignore b/.prettierignore index edd29f0..63cde50 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,4 @@ email_template.html -adaptivecard.json -slackreport.json .nextflow* work/ data/ @@ -10,4 +8,7 @@ testing/ testing* *.pyc bin/ +.nf-test/ ro-crate-metadata.json +modules/nf-core/ +subworkflows/nf-core/ diff --git a/README.md b/README.md index 8e199af..8492c0a 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,13 @@ +[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync) [![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml) [![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) -[![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) +[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.10.4-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-4.0.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/4.0.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/) @@ -29,13 +30,13 @@ --> + workflows use the "tube map" design for that. See https://nf-co.re/docs/community/brand/workflow-schematics#examples for examples. --> 1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) ## Usage > [!NOTE] -> 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. +> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data. diff --git a/docs/usage.md b/docs/usage.md index 210645c..1c85a3e 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -76,7 +76,7 @@ If you wish to repeatedly use the same parameters for multiple runs, rather than Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. > [!WARNING] -> Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). +> Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/running/run-pipelines#configuring-pipelines), other infrastructural tweaks (such as output directories), or module arguments (args). The above pipeline run specified with a params file in yaml format: @@ -149,7 +149,7 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - `shifter` - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) - `charliecloud` - - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) + - A generic configuration profile to be used with [Charliecloud](https://charliecloud.io/) - `apptainer` - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) - `wave` @@ -173,19 +173,19 @@ Specify the path to a specific config file (this is a core Nextflow command). Se Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the pipeline steps, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher resources request (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. -To change the resource requests, please see the [max resources](https://nf-co.re/docs/usage/configuration#max-resources) and [tuning workflow resources](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources) section of the nf-core website. +To change the resource requests, please see the [max resources](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#set-max-resources) and [customise process resources](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#customize-process-resources) section of the nf-core website. ### Custom Containers In some cases, you may wish to change the container or conda environment used by a pipeline steps for a particular tool. By default, nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However, in some cases the pipeline specified version maybe out of date. -To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/usage/configuration#updating-tool-versions) section of the nf-core website. +To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#update-tool-versions) section of the nf-core website. ### Custom Tool Arguments A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. -To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/usage/configuration#customising-tool-arguments) section of the nf-core website. +To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#modifying-tool-arguments) section of the nf-core website. ### nf-core/configs diff --git a/main.nf b/main.nf index e23a4c6..637723e 100644 --- a/main.nf +++ b/main.nf @@ -51,7 +51,11 @@ workflow NFCORE_DATASYNC { // WORKFLOW: Run pipeline // DATASYNC ( - samplesheet + samplesheet, + params.multiqc_config, + params.multiqc_logo, + params.multiqc_methods_description, + params.outdir, ) emit: multiqc_report = DATASYNC.out.multiqc_report // channel: /path/to/multiqc_report.html @@ -74,7 +78,10 @@ workflow { params.monochrome_logs, args, params.outdir, - params.input + params.input, + params.help, + params.help_full, + params.show_hidden ) // @@ -92,7 +99,6 @@ workflow { params.plaintext_email, params.outdir, params.monochrome_logs, - params.hook_url, NFCORE_DATASYNC.out.multiqc_report ) } diff --git a/modules.json b/modules.json index 8e1bd7b..578acbb 100644 --- a/modules.json +++ b/modules.json @@ -7,12 +7,12 @@ "nf-core": { "fastqc": { "branch": "master", - "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", + "git_sha": "008f9d3e61209bf995edac3ba531f54e269e1215", "installed_by": ["modules"] } } @@ -21,17 +21,17 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "c2b22d85f30a706a3073387f30380704fcae013b", + "git_sha": "05954dab2ff481bcb999f24455da29a5828af08d", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "51ae5406a030d4da1e49e4dab49756844fdd6c7a", + "git_sha": "a3fb7351b1fdb2b1de282b765816bbea190e86a8", "installed_by": ["subworkflows"] }, "utils_nfschema_plugin": { "branch": "master", - "git_sha": "2fd2cd6d0e7b273747f32e465fdc6bcc3ae0814e", + "git_sha": "fdc08b8b1ae74f56686ce21f7ea11ad11990ce57", "installed_by": ["subworkflows"] } } diff --git a/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt new file mode 100644 index 0000000..7770ccd --- /dev/null +++ b/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt @@ -0,0 +1,822 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-64: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 +md5: a9f577daf3de00bca7c3c76c0ecbd1de +depends: +- __glibc >=2.17,<3.0.a0 +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28948 +timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda +sha256: d88aa7ae766cf584e180996e92fef2aa7d8e0a0a5ab1d4d49c32390c1b5fff31 +md5: dcdc58c15961dbf17a0621312b01f5cb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: LGPL-2.1-or-later +license_family: GPL +size: 584660 +timestamp: 1768327524772 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 +md5: d2ffd7602c02f2b316fd921d39876885 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 260182 +timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda +sha256: 06525fa0c4e4f56e771a3b986d0fdf0f0fc5a3270830ee47e127a5105bde1b9a +md5: bb6c4808bfa69d6f7f6b07e5846ced37 +depends: +- __glibc >=2.17,<3.0.a0 +- fontconfig >=2.15.0,<3.0a0 +- fonts-conda-ecosystem +- icu >=78.1,<79.0a0 +- libexpat >=2.7.3,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libglib >=2.86.3,<3.0a0 +- libpng >=1.6.53,<1.7.0a0 +- libstdcxx >=14 +- libxcb >=1.17.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pixman >=0.46.4,<1.0a0 +- xorg-libice >=1.1.2,<2.0a0 +- xorg-libsm >=1.2.6,<2.0a0 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: LGPL-2.1-only or MPL-1.1 +size: 989514 +timestamp: 1766415934926 +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c +md5: c9f6a4b12229f7331f79c9a00dd6e240 +depends: +- font-ttf-dejavu-sans-mono +- fontconfig +- openjdk >=8.0.144 +- perl +license: GPL >=3 +size: 11664291 +timestamp: 1677946722445 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +sha256: aa4a44dba97151221100a637c7f4bde619567afade9c0265f8e1c8eed8d7bd8c +md5: 867127763fbe935bab59815b6e0b7b5c +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 270705 +timestamp: 1771382710863 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 +md5: fee5683a3f04bd15cbd8318b096a27ab +depends: +- fonts-conda-forge +license: BSD-3-Clause +license_family: BSD +size: 3667 +timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda +sha256: aac402a8298f0c0cc528664249170372ef6b37ac39fdc92b40601a6aed1e32ff +md5: 3bf7b9fd5a7136126e0234db4b87c8b6 +depends: +- libgcc-ng >=12 +license: MIT +license_family: MIT +size: 77248 +timestamp: 1712692454246 +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda +sha256: 25ba37da5c39697a77fce2c9a15e48cf0a84f1464ad2aafbe53d8357a9f6cc8c +md5: 2cd94587f3a401ae05e03a6caf09539d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: LGPL-2.0-or-later +license_family: LGPL +size: 99596 +timestamp: 1755102025473 +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda +sha256: 477f2c553f72165020d3c56740ba354be916c2f0b76fd9f535e83d698277d5ec +md5: 14470902326beee192e33719a2e8bb7f +depends: +- __glibc >=2.17,<3.0.a0 +- cairo >=1.18.4,<2.0a0 +- graphite2 >=1.3.14,<2.0a0 +- icu >=78.3,<79.0a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.2 +- libfreetype6 >=2.14.2 +- libgcc >=14 +- libglib >=2.86.4,<3.0a0 +- libstdcxx >=14 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 2384060 +timestamp: 1774276284520 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a +md5: c80d8a3b84358cb967fa81e7075fbc8a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12723451 +timestamp: 1773822285671 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda +sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 +md5: b38117a3c920364aff79f870c984b4a3 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: LGPL-2.1-or-later +size: 134088 +timestamp: 1754905959823 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda +sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 +md5: fb53fb07ce46a575c5d004bbc96032c2 +depends: +- __glibc >=2.17,<3.0.a0 +- keyutils >=1.6.3,<2.0a0 +- libedit >=3.1.20250104,<3.2.0a0 +- libedit >=3.1.20250104,<4.0a0 +- libgcc >=14 +- libstdcxx >=14 +- openssl >=3.5.5,<4.0a0 +license: MIT +license_family: MIT +size: 1386730 +timestamp: 1769769569681 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +sha256: 836ec4b895352110335b9fdcfa83a8dcdbe6c5fb7c06c4929130600caea91c0a +md5: 6f2e2c8f58160147c4d1c6f4c14cbac4 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 249959 +timestamp: 1768184673131 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +sha256: f84cb54782f7e9cea95e810ea8fef186e0652d0fa73d3009914fa2c1262594e1 +md5: a752488c68f2e7c456bcbd8f16eec275 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 261513 +timestamp: 1773113328888 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda +sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c +md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 +depends: +- __glibc >=2.17,<3.0.a0 +- krb5 >=1.22.2,<1.23.0a0 +- libgcc >=14 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +license: Apache-2.0 +license_family: Apache +size: 4518030 +timestamp: 1770902209173 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 +md5: 6c77a605a7a689d17d4819c0f8ac9a00 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 73490 +timestamp: 1761979956660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda +sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 +md5: c277e0a4d549b03ac1e9d6cbbe3d017b +depends: +- ncurses +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- ncurses >=6.5,<7.0a0 +license: BSD-2-Clause +license_family: BSD +size: 134676 +timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 +md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76798 +timestamp: 1771259418166 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 +md5: a360c33a5abe61c07959e449fa1453eb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 58592 +timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 +md5: e289f3d17880e44b633ba911d57a321b +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8049 +timestamp: 1774298163029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d +md5: fb16b4b69e3f1dcfe79d80db8fd0c55d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 384575 +timestamp: 1774298162622 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 +md5: 0aa00f03f9e39fb9876085dee11a85d4 +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1041788 +timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 +md5: d5e96b1ed75ca01906b3d2469b4ce493 +depends: +- libgcc 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27526 +timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda +sha256: a27e44168a1240b15659888ce0d9b938ed4bdb49e9ea68a7c1ff27bcea8b55ce +md5: bb26456332b07f68bf3b7622ed71c0da +depends: +- __glibc >=2.17,<3.0.a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- libiconv >=1.18,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pcre2 >=10.47,<10.48.0a0 +constrains: +- glib 2.86.4 *_1 +license: LGPL-2.1-or-later +size: 4398701 +timestamp: 1771863239578 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 +md5: 239c5e9546c38a1e884d69effcf4c882 +depends: +- __glibc >=2.17,<3.0.a0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 603262 +timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda +sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f +md5: 915f5995e94f60e9a4826e0b0920ee88 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: LGPL-2.1-only +size: 790176 +timestamp: 1754908768807 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32 +md5: 8397539e3a0bbd1695584fb4f927485a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 633710 +timestamp: 1762094827865 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb +md5: c7c83eecbb72d88b940c249af56c8b17 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 113207 +timestamp: 1768752626120 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +sha256: 36ade759122cdf0f16e2a2562a19746d96cf9c863ffaa812f2f5071ebbe9c03c +md5: 5f13ffc7d30ffec87864e678df9957b4 +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 317669 +timestamp: 1770691470744 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e +md5: 1b08cd684f34175e4514474793d44bcb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc 15.2.0 he0feb66_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5852330 +timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 +md5: cd5a90476766d53e901500df9215e927 +depends: +- __glibc >=2.17,<3.0.a0 +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 435273 +timestamp: 1762022005702 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee +md5: db409b7c1720428638e7c0d509d3e1b5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 40311 +timestamp: 1766271528534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b +md5: aea31d2e5b1091feca96fcfe945c3cf9 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 429011 +timestamp: 1752159441324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa +md5: 92ed62436b625154323d40d5f2f11dd7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 395888 +timestamp: 1727278577118 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda +sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c +md5: 5aa797f8787fe7a17d1b0821485b5adc +depends: +- libgcc-ng >=12 +license: LGPL-2.1-or-later +size: 100393 +timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 +md5: d87ff7921124eccd67248aa483c23fec +depends: +- __glibc >=2.17,<3.0.a0 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 63629 +timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 +md5: 47e340acb35de30501a76c7c799c41d7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 891641 +timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda +sha256: 3825a4c84676a8a5cc23b397a2911e4efa4a805daf2af764153bd904e142ec41 +md5: a41092b0177362dbe5eb2a18501e86c0 +depends: +- xorg-libx11 +- xorg-libxext +- xorg-libxi +- xorg-libxrender +- xorg-libxtst +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- xorg-libxrender >=0.9.12,<0.10.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- giflib >=5.2.2,<5.3.0a0 +- xorg-libxrandr >=1.5.5,<2.0a0 +- harfbuzz >=12.3.2 +- fontconfig >=2.17.1,<3.0a0 +- fonts-conda-ecosystem +- xorg-libxtst >=1.2.5,<2.0a0 +- xorg-libxi >=1.8.2,<2.0a0 +- lcms2 >=2.18,<3.0a0 +- alsa-lib >=1.2.15.3,<1.3.0a0 +- libpng >=1.6.55,<1.7.0a0 +- xorg-libxt >=1.3.1,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- xorg-libxext >=1.3.7,<2.0a0 +- xorg-libx11 >=1.8.13,<2.0a0 +- libcups >=2.3.3,<2.4.0a0 +license: GPL-2.0-or-later WITH Classpath-exception-2.0 +license_family: GPL +size: 122465031 +timestamp: 1771443671180 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c +md5: f61eb8cd60ff9057122a3d338b99c00f +depends: +- __glibc >=2.17,<3.0.a0 +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3164551 +timestamp: 1769555830639 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda +sha256: 5e6f7d161356fefd981948bea5139c5aa0436767751a6930cb1ca801ebb113ff +md5: 7a3bff861a6583f1889021facefc08b1 +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 1222481 +timestamp: 1763655398280 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda +build_number: 7 +sha256: 9ec32b6936b0e37bcb0ed34f22ec3116e75b3c0964f9f50ecea5f58734ed6ce9 +md5: f2cfec9406850991f4e3d960cc9e3321 +depends: +- libgcc-ng >=12 +- libxcrypt >=4.4.36 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 13344463 +timestamp: 1703310653947 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda +sha256: 43d37bc9ca3b257c5dd7bf76a8426addbdec381f6786ff441dc90b1a49143b6a +md5: c01af13bdc553d1a8fbfff6e8db075f0 +depends: +- libgcc >=14 +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +license: MIT +license_family: MIT +size: 450960 +timestamp: 1754665235234 +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d +md5: f2c23a77b25efcad57d377b34bd84941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 593603 +timestamp: 1769710381284 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 +md5: b3c17d95b5a10c6e64a21fa17573e70e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 8252 +timestamp: 1726802366959 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda +sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b +md5: fb901ff28063514abb6046c9ec2c4a45 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 58628 +timestamp: 1734227592886 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda +sha256: 277841c43a39f738927145930ff963c5ce4c4dacf66637a3d95d802a64173250 +md5: 1c74ff8c35dcadf952a16f752ca5aa49 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libuuid >=2.38.1,<3.0a0 +- xorg-libice >=1.1.2,<2.0a0 +license: MIT +license_family: MIT +size: 27590 +timestamp: 1741896361728 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda +sha256: 516d4060139dbb4de49a4dcdc6317a9353fb39ebd47789c14e6fe52de0deee42 +md5: 861fb6ccbc677bb9a9fb2468430b9c6a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libxcb >=1.17.0,<2.0a0 +license: MIT +license_family: MIT +size: 839652 +timestamp: 1770819209719 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b +md5: b2895afaf55bf96a8c8282a2e47a5de0 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 15321 +timestamp: 1762976464266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 +md5: 1dafce8548e38671bea82e3f5c6ce22f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 20591 +timestamp: 1762976546182 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda +sha256: 79c60fc6acfd3d713d6340d3b4e296836a0f8c51602327b32794625826bd052f +md5: 34e54f03dfea3e7a2dcf1453a85f1085 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 50326 +timestamp: 1769445253162 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda +sha256: 83c4c99d60b8784a611351220452a0a85b080668188dce5dfa394b723d7b64f4 +md5: ba231da7fccf9ea1e768caf5c7099b84 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 20071 +timestamp: 1759282564045 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda +sha256: 1a724b47d98d7880f26da40e45f01728e7638e6ec69f35a3e11f92acd05f9e7a +md5: 17dcc85db3c7886650b8908b183d6876 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxfixes >=6.0.1,<7.0a0 +license: MIT +license_family: MIT +size: 47179 +timestamp: 1727799254088 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda +sha256: 80ed047a5cb30632c3dc5804c7716131d767089f65877813d4ae855ee5c9d343 +md5: e192019153591938acf7322b6459d36e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: MIT +license_family: MIT +size: 30456 +timestamp: 1769445263457 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda +sha256: 044c7b3153c224c6cedd4484dd91b389d2d7fd9c776ad0f4a34f099b3389f4a1 +md5: 96d57aba173e878a2089d5638016dc5e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 33005 +timestamp: 1734229037766 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda +sha256: a8afba4a55b7b530eb5c8ad89737d60d60bc151a03fbef7a2182461256953f0e +md5: 279b0de5f6ba95457190a1c459a64e31 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libice >=1.1.1,<2.0a0 +- xorg-libsm >=1.2.4,<2.0a0 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 379686 +timestamp: 1731860547604 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda +sha256: 752fdaac5d58ed863bbf685bb6f98092fe1a488ea8ebb7ed7b606ccfce08637a +md5: 7bbe9a0cc0df0ac5f5a8ad6d6a11af2f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxi >=1.7.10,<2.0a0 +license: MIT +license_family: MIT +size: 32808 +timestamp: 1727964811275 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 +md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 +depends: +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 601375 +timestamp: 1764777111296 diff --git a/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt new file mode 100644 index 0000000..cdc434c --- /dev/null +++ b/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt @@ -0,0 +1,769 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-aarch64: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 +md5: 468fd3bb9e1f671d36c2cbc677e56f1d +depends: +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28926 +timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda +sha256: ea2233e2db9908c2e5f29d3ca420a546b4583253f4f70abb5494cdd676866d42 +md5: 4a98cbc4ade694520227402ff8880630 +depends: +- libgcc >=14 +license: LGPL-2.1-or-later +license_family: GPL +size: 615729 +timestamp: 1768327548407 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c +md5: 840d8fc0d7b3209be93080bc20e07f2d +depends: +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 192412 +timestamp: 1771350241232 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda +sha256: 675db823f3d6fb6bf747fab3b0170ba99b269a07cf6df1e49fff2f9972be9cd1 +md5: 043c13ed3a18396994be9b4fab6572ad +depends: +- fontconfig >=2.15.0,<3.0a0 +- fonts-conda-ecosystem +- icu >=78.1,<79.0a0 +- libexpat >=2.7.3,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libglib >=2.86.3,<3.0a0 +- libpng >=1.6.53,<1.7.0a0 +- libstdcxx >=14 +- libxcb >=1.17.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pixman >=0.46.4,<1.0a0 +- xorg-libice >=1.1.2,<2.0a0 +- xorg-libsm >=1.2.6,<2.0a0 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: LGPL-2.1-only or MPL-1.1 +size: 927045 +timestamp: 1766416003626 +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c +md5: c9f6a4b12229f7331f79c9a00dd6e240 +depends: +- font-ttf-dejavu-sans-mono +- fontconfig +- openjdk >=8.0.144 +- perl +license: GPL >=3 +size: 11664291 +timestamp: 1677946722445 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +sha256: 835aff8615dd8d8fff377679710ce81b8a2c47b6404e21a92fb349fda193a15c +md5: 0fed1ff55f4938a65907f3ecf62609db +depends: +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 279044 +timestamp: 1771382728182 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 +md5: fee5683a3f04bd15cbd8318b096a27ab +depends: +- fonts-conda-forge +license: BSD-3-Clause +license_family: BSD +size: 3667 +timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda +sha256: a79dc3bd54c4fb1f249942ee2d5b601a76ecf9614774a4cff9af49adfa458db2 +md5: 2f809afaf0ba1ea4135dce158169efac +depends: +- libgcc-ng >=12 +license: MIT +license_family: MIT +size: 82124 +timestamp: 1712692444545 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda +sha256: c9b1781fe329e0b77c5addd741e58600f50bef39321cae75eba72f2f381374b7 +md5: 4aa540e9541cc9d6581ab23ff2043f13 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: LGPL-2.0-or-later +license_family: LGPL +size: 102400 +timestamp: 1755102000043 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda +sha256: e22f485fddaaea3ff4b6cae98e0197b9dccd2ed2770337ad6ff38a92afe04e59 +md5: 05d65a2cf410adc331c9ea61f59f1013 +depends: +- cairo >=1.18.4,<2.0a0 +- graphite2 >=1.3.14,<2.0a0 +- icu >=78.3,<79.0a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.2 +- libfreetype6 >=2.14.2 +- libgcc >=14 +- libglib >=2.86.4,<3.0a0 +- libstdcxx >=14 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 2345732 +timestamp: 1774281448329 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +sha256: 49ba6aed2c6b482bb0ba41078057555d29764299bc947b990708617712ef6406 +md5: 546da38c2fa9efacf203e2ad3f987c59 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12837286 +timestamp: 1773822650615 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda +sha256: 5ce830ca274b67de11a7075430a72020c1fb7d486161a82839be15c2b84e9988 +md5: e7df0aab10b9cbb73ab2a467ebfaf8c7 +depends: +- libgcc >=13 +license: LGPL-2.1-or-later +size: 129048 +timestamp: 1754906002667 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda +sha256: b53999d888dda53c506b264e8c02b5f5c8e022c781eda0718f007339e6bc90ba +md5: d9ca108bd680ea86a963104b6b3e95ca +depends: +- keyutils >=1.6.3,<2.0a0 +- libedit >=3.1.20250104,<3.2.0a0 +- libedit >=3.1.20250104,<4.0a0 +- libgcc >=14 +- libstdcxx >=14 +- openssl >=3.5.5,<4.0a0 +license: MIT +license_family: MIT +size: 1517436 +timestamp: 1769773395215 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +sha256: 379ef5e91a587137391a6149755d0e929f1a007d2dcb211318ac670a46c8596f +md5: bb960f01525b5e001608afef9d47b79c +depends: +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 293039 +timestamp: 1768184778398 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +sha256: 8957fd460c1c132c8031f65fd5f56ec3807fd71b7cab2c5e2b0937b13404ab36 +md5: d13423b06447113a90b5b1366d4da171 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 240444 +timestamp: 1773114901155 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda +sha256: 41b04f995c9f63af8c4065a35931e46cbc2fdd6b9bf7e4c19f90d53cbb2bc8e5 +md5: 67828c963b17db7dc989fe5d509ef04a +depends: +- krb5 >=1.22.2,<1.23.0a0 +- libgcc >=14 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +license: Apache-2.0 +license_family: Apache +size: 4553739 +timestamp: 1770903929794 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 +md5: a9138815598fe6b91a1d6782ca657b0c +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 71117 +timestamp: 1761979776756 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda +sha256: c0b27546aa3a23d47919226b3a1635fccdb4f24b94e72e206a751b33f46fd8d6 +md5: fb640d776fc92b682a14e001980825b1 +depends: +- ncurses +- libgcc >=13 +- ncurses >=6.5,<7.0a0 +license: BSD-2-Clause +license_family: BSD +size: 148125 +timestamp: 1738479808948 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 +md5: 57f3b3da02a50a1be2a6fe847515417d +depends: +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76564 +timestamp: 1771259530958 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 +md5: 2f364feefb6a7c00423e80dcb12db62a +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 55952 +timestamp: 1769456078358 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a +md5: a229e22d4d8814a07702b0919d8e6701 +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8125 +timestamp: 1774301094057 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c +md5: b99ed99e42dafb27889483b3098cace7 +depends: +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 422941 +timestamp: 1774301093473 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +sha256: 43df385bedc1cab11993c4369e1f3b04b4ca5d0ea16cba6a0e7f18dbc129fcc9 +md5: 552567ea2b61e3a3035759b2fdb3f9a6 +depends: +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 622900 +timestamp: 1771378128706 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +sha256: 83bb0415f59634dccfa8335d4163d1f6db00a27b36666736f9842b650b92cf2f +md5: 4feebd0fbf61075a1a9c2e9b3936c257 +depends: +- libgcc 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27568 +timestamp: 1771378136019 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda +sha256: afc503dbd04a5bf2709aa9d8318a03a8c4edb389f661ff280c3494bfef4341ec +md5: 4ac4372fc4d7f20630a91314cdac8afd +depends: +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- libiconv >=1.18,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pcre2 >=10.47,<10.48.0a0 +constrains: +- glib 2.86.4 *_1 +license: LGPL-2.1-or-later +size: 4512186 +timestamp: 1771863220969 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +sha256: fc716f11a6a8525e27a5d332ef6a689210b0d2a4dd1133edc0f530659aa9faa6 +md5: 4faa39bf919939602e594253bd673958 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 588060 +timestamp: 1771378040807 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda +sha256: 1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9 +md5: 5a86bf847b9b926f3a4f203339748d78 +depends: +- libgcc >=14 +license: LGPL-2.1-only +size: 791226 +timestamp: 1754910975665 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +sha256: 84064c7c53a64291a585d7215fe95ec42df74203a5bf7615d33d49a3b0f08bb6 +md5: 5109d7f837a3dfdf5c60f60e311b041f +depends: +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 691818 +timestamp: 1762094728337 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +sha256: 843c46e20519651a3e357a8928352b16c5b94f4cd3d5481acc48be2e93e8f6a3 +md5: 96944e3c92386a12755b94619bae0b35 +depends: +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 125916 +timestamp: 1768754941722 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +sha256: c7378c6b79de4d571d00ad1caf0a4c19d43c9c94077a761abb6ead44d891f907 +md5: be4088903b94ea297975689b3c3aeb27 +depends: +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 340156 +timestamp: 1770691477245 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +sha256: 31fdb9ffafad106a213192d8319b9f810e05abca9c5436b60e507afb35a6bc40 +md5: f56573d05e3b735cb03efeb64a15f388 +depends: +- libgcc 15.2.0 h8acb6b2_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5541411 +timestamp: 1771378162499 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 +md5: 8c6fd84f9c87ac00636007c6131e457d +depends: +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 488407 +timestamp: 1762022048105 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 +md5: cf2861212053d05f27ec49c3784ff8bb +depends: +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 43453 +timestamp: 1766271546875 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 +md5: 24e92d0942c799db387f5c9d7b81f1af +depends: +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 359496 +timestamp: 1752160685488 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b +md5: cd14ee5cca2464a425b1dbfc24d90db2 +depends: +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 397493 +timestamp: 1727280745441 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda +sha256: 6b46c397644091b8a26a3048636d10b989b1bf266d4be5e9474bf763f828f41f +md5: b4df5d7d4b63579d081fd3a4cf99740e +depends: +- libgcc-ng >=12 +license: LGPL-2.1-or-later +size: 114269 +timestamp: 1702724369203 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f +md5: 502006882cf5461adced436e410046d1 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 69833 +timestamp: 1774072605429 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468 +md5: 182afabe009dc78d8b73100255ee6868 +depends: +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 926034 +timestamp: 1738196018799 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda +sha256: 6fd2c872b275fa5d42a61a4b6dc28a819cde29f9048adb547363597432e0720e +md5: 27fdd5d67e235c20d23b2d66406497d3 +depends: +- xorg-libx11 +- xorg-libxext +- xorg-libxi +- xorg-libxrender +- xorg-libxtst +- libstdcxx >=14 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +- xorg-libxtst >=1.2.5,<2.0a0 +- libpng >=1.6.55,<1.7.0a0 +- alsa-lib >=1.2.15.3,<1.3.0a0 +- xorg-libx11 >=1.8.13,<2.0a0 +- xorg-libxi >=1.8.2,<2.0a0 +- xorg-libxrandr >=1.5.5,<2.0a0 +- lcms2 >=2.18,<3.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +- libcups >=2.3.3,<2.4.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- harfbuzz >=12.3.2 +- xorg-libxext >=1.3.7,<2.0a0 +- giflib >=5.2.2,<5.3.0a0 +- xorg-libxt >=1.3.1,<2.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- fontconfig >=2.17.1,<3.0a0 +- fonts-conda-ecosystem +license: GPL-2.0-or-later WITH Classpath-exception-2.0 +license_family: GPL +size: 106988620 +timestamp: 1771443741031 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +sha256: 7f8048c0e75b2620254218d72b4ae7f14136f1981c5eb555ef61645a9344505f +md5: 25f5885f11e8b1f075bccf4a2da91c60 +depends: +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3692030 +timestamp: 1769557678657 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda +sha256: 04df2cee95feba440387f33f878e9f655521e69f4be33a0cd637f07d3d81f0f9 +md5: 1a30c42e32ca0ea216bd0bfe6f842f0b +depends: +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 1166552 +timestamp: 1763655534263 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda +build_number: 7 +sha256: d78296134263b5bf476cad838ded65451e7162db756f9997c5d06b08122572ed +md5: 17d019cb2a6c72073c344e98e40dfd61 +depends: +- libgcc-ng >=12 +- libxcrypt >=4.4.36 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 13338804 +timestamp: 1703310557094 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda +sha256: e6b0846a998f2263629cfeac7bca73565c35af13251969f45d385db537a514e4 +md5: 1587081d537bd4ae77d1c0635d465ba5 +depends: +- libgcc >=14 +- libstdcxx >=14 +- libgcc >=14 +license: MIT +license_family: MIT +size: 357913 +timestamp: 1754665583353 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 +md5: ab7288cc39545556d1bc5e71ab2df9a9 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 636733 +timestamp: 1769712412683 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba +md5: bb5a90c93e3bac3d5690acf76b4a6386 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 8342 +timestamp: 1726803319942 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda +sha256: a2ba1864403c7eb4194dacbfe2777acf3d596feae43aada8d1b478617ce45031 +md5: c8d8ec3e00cd0fd8a231789b91a7c5b7 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 60433 +timestamp: 1734229908988 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda +sha256: b86a819cd16f90c01d9d81892155126d01555a20dabd5f3091da59d6309afd0a +md5: 2d1409c50882819cb1af2de82e2b7208 +depends: +- libgcc >=13 +- libuuid >=2.38.1,<3.0a0 +- xorg-libice >=1.1.2,<2.0a0 +license: MIT +license_family: MIT +size: 28701 +timestamp: 1741897678254 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda +sha256: cf886160e2ff580d77f7eb8ec1a77c41c2c5b05343e329bc35f0ddf40b8d92ab +md5: 22dd10425ef181e80e130db50675d615 +depends: +- libgcc >=14 +- libxcb >=1.17.0,<2.0a0 +license: MIT +license_family: MIT +size: 869058 +timestamp: 1770819244991 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 +md5: 1c246e1105000c3660558459e2fd6d43 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 16317 +timestamp: 1762977521691 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1 +md5: bff06dcde4a707339d66d45d96ceb2e2 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 21039 +timestamp: 1762979038025 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda +sha256: db2188bc0d844d4e9747bac7f6c1d067e390bd769c5ad897c93f1df759dc5dba +md5: fb42b683034619915863d68dd9df03a3 +depends: +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 52409 +timestamp: 1769446753771 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda +sha256: 8cb9c88e25c57e47419e98f04f9ef3154ad96b9f858c88c570c7b91216a64d0e +md5: e8b4056544341daf1d415eaeae7a040c +depends: +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 20704 +timestamp: 1759284028146 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda +sha256: 7b587407ecb9ccd2bbaf0fb94c5dbdde4d015346df063e9502dc0ce2b682fb5e +md5: eeee3bdb31c6acde2b81ad1b8c287087 +depends: +- libgcc >=13 +- xorg-libx11 >=1.8.9,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxfixes >=6.0.1,<7.0a0 +license: MIT +license_family: MIT +size: 48197 +timestamp: 1727801059062 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda +sha256: 9f5196665a8d72f4f119c40dcc4bafeb0b540b102cc7b8b299c2abf599e7919f +md5: 1f64c613f0b8d67e9fb0e165d898fb6b +depends: +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: MIT +license_family: MIT +size: 31122 +timestamp: 1769445286951 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda +sha256: ffd77ee860c9635a28cfda46163dcfe9224dc6248c62404c544ae6b564a0be1f +md5: ae2c2dd0e2d38d249887727db2af960e +depends: +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 33649 +timestamp: 1734229123157 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda +sha256: 7c109792b60720809a580612aba7f8eb2a0bd425b9fc078748a9d6ffc97cbfa8 +md5: a9e4852c8e0b68ee783e7240030b696f +depends: +- libgcc >=13 +- xorg-libice >=1.1.1,<2.0a0 +- xorg-libsm >=1.2.4,<2.0a0 +- xorg-libx11 >=1.8.9,<2.0a0 +license: MIT +license_family: MIT +size: 384752 +timestamp: 1731860572314 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda +sha256: 6eaffce5a34fc0a16a21ddeaefb597e792a263b1b0c387c1ce46b0a967d558e1 +md5: c05698071b5c8e0da82a282085845860 +depends: +- libgcc >=13 +- xorg-libx11 >=1.8.9,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxi >=1.7.10,<2.0a0 +license: MIT +license_family: MIT +size: 33786 +timestamp: 1727964907993 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 +md5: c3655f82dcea2aa179b291e7099c1fcc +depends: +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 614429 +timestamp: 1764777145593 diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 23e1663..1085126 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -1,37 +1,40 @@ process FASTQC { tag "${meta.id}" - label 'process_medium' + label 'process_low' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' : - 'biocontainers/fastqc:0.12.1--hdfd78af_0' }" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' + : 'quay.io/biocontainers/fastqc:0.12.1--hdfd78af_0'}" input: - tuple val(meta), path(reads) + tuple val(meta), path(reads, stageAs: '?/*') output: tuple val(meta), path("*.html"), emit: html - tuple val(meta), path("*.zip") , emit: zip - path "versions.yml" , emit: versions + tuple val(meta), path("*.zip"), emit: zip + tuple val("${task.process}"), val('fastqc'), eval('fastqc --version | sed "/FastQC v/!d; s/.*v//"'), emit: versions_fastqc, topic: versions when: task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" // Make list of old name and new name pairs to use for renaming in the bash while loop - def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } - def rename_to = old_new_pairs*.join(' ').join(' ') - def renamed_files = old_new_pairs.collect{ _old_name, new_name -> new_name }.join(' ') + def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[reads, "${prefix}.${reads.extension}"]] : reads.withIndex().collect { entry, index -> [entry, "${prefix}_${index + 1}.${entry.extension}"] } + def rename_to = old_new_pairs*.join(' ').join(' ') + def renamed_files = old_new_pairs.collect { _old_name, new_name -> new_name }.join(' ') // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 - // Dividing the task.memory by task.cpu allows to stick to requested amount of RAM in the label - def memory_in_mb = task.memory ? task.memory.toUnit('MB') / task.cpus : null + // Dividing the task.memory by task.cpus allows to stick to requested amount of RAM in the label + def memory_in_mb = task.memory + ? (task.memory.toUnit('MB') / task.cpus).intValue() + : null // FastQC memory value allowed range (100 - 10000) def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) + def fastqc_memory_arg = fastqc_memory ? "--memory ${fastqc_memory}" : '' """ printf "%s %s\\n" ${rename_to} | while read old_name new_name; do @@ -41,13 +44,8 @@ process FASTQC { fastqc \\ ${args} \\ --threads ${task.cpus} \\ - --memory ${fastqc_memory} \\ + ${fastqc_memory_arg} \\ ${renamed_files} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) - END_VERSIONS """ stub: @@ -55,10 +53,5 @@ process FASTQC { """ touch ${prefix}.html touch ${prefix}.zip - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) - END_VERSIONS """ } diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml index c8d9d02..2f6cfef 100644 --- a/modules/nf-core/fastqc/meta.yml +++ b/modules/nf-core/fastqc/meta.yml @@ -53,13 +53,28 @@ output: description: FastQC report archive pattern: "*_{fastqc.zip}" ontologies: [] + versions_fastqc: + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool authors: - "@drpatelh" - "@grst" @@ -70,3 +85,27 @@ maintainers: - "@grst" - "@ewels" - "@FelixKrueger" +containers: + docker: + linux/arm64: + name: community.wave.seqera.io/library/fastqc:0.12.1--e455e32f745abe68 + build_id: bd-e455e32f745abe68_1 + scan_id: sc-f102f736465af88c_1 + linux/amd64: + name: community.wave.seqera.io/library/fastqc:0.12.1--5cb1a2fa2f18c7c2 + build_id: bd-5cb1a2fa2f18c7c2_1 + scan_id: sc-0c0466326b6b77d2_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--5c4bd442468d75dd + build_id: bd-5c4bd442468d75dd_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/f2/f20b021476d1d87658820f971ebecc1e8cdbde0f338eb0d9cea2b0a8fc54a54b/data + linux/arm64: + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--127a87fc06499035 + build_id: bd-127a87fc06499035_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/46/46daf2dad0169afd2ae047c3e50ed3776259f664bf07e5e06b045dc23449e994/data + conda: + linux/amd64: + lock_file: modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt + linux/arm64: + lock_file: modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test index e9d79a0..66c44da 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test +++ b/modules/nf-core/fastqc/tests/main.nf.test @@ -30,7 +30,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -58,7 +58,7 @@ nextflow_process { { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -82,7 +82,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -106,7 +106,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -142,7 +142,7 @@ nextflow_process { { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -166,7 +166,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap index d5db309..c8ee120 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test.snap +++ b/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -1,15 +1,21 @@ { "sarscov2 custom_prefix": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:16.374038" + "timestamp": "2025-10-28T16:39:14.518503" }, "sarscov2 single-end [fastq] - stub": { "content": [ @@ -33,7 +39,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -44,8 +54,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -59,10 +73,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:24.993809" + "timestamp": "2025-10-28T16:39:19.309008" }, "sarscov2 custom_prefix - stub": { "content": [ @@ -86,7 +100,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -97,8 +115,12 @@ "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -112,58 +134,82 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:03:10.93942" + "timestamp": "2025-10-28T16:39:44.94888" }, "sarscov2 interleaved [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:42.355718" + "timestamp": "2025-10-28T16:38:45.168496" }, "sarscov2 paired-end [bam]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:53.276274" + "timestamp": "2025-10-28T16:38:53.268919" }, "sarscov2 multiple [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:05.527626" + "timestamp": "2025-10-28T16:39:05.050305" }, "sarscov2 paired-end [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:31.188871" + "timestamp": "2025-10-28T16:38:37.2373" }, "sarscov2 paired-end [fastq] - stub": { "content": [ @@ -187,7 +233,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -198,8 +248,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -213,10 +267,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:34.273566" + "timestamp": "2025-10-28T16:39:24.450398" }, "sarscov2 multiple [fastq] - stub": { "content": [ @@ -240,7 +294,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -251,8 +309,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -266,22 +328,28 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:03:02.304411" + "timestamp": "2025-10-28T16:39:39.758762" }, "sarscov2 single-end [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:19.095607" + "timestamp": "2025-10-28T16:38:29.555068" }, "sarscov2 interleaved [fastq] - stub": { "content": [ @@ -305,7 +373,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -316,8 +388,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -331,10 +407,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:44.640184" + "timestamp": "2025-10-28T16:39:29.193136" }, "sarscov2 paired-end [bam] - stub": { "content": [ @@ -358,7 +434,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -369,8 +449,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -384,9 +468,9 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:53.550742" + "timestamp": "2025-10-28T16:39:34.144919" } } \ No newline at end of file diff --git a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt new file mode 100644 index 0000000..7619030 --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt @@ -0,0 +1,1552 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-64: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py314h2b28147_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.1.1-py314h8ec4b1a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.39.3-py310hffdcd12_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.39.3-py310hbcd5346_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py314h2e6c369_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.2.28-py314h5bd0f2a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.52.0-h04a0ce9_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 +md5: a9f577daf3de00bca7c3c76c0ecbd1de +depends: +- __glibc >=2.17,<3.0.a0 +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28948 +timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 +md5: aaa2a381ccc56eac91d63b6c1240312f +depends: +- cpython +- python-gil +license: MIT +license_family: MIT +size: 8191 +timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 +md5: 2934f256a8acfe48f6ebb4fce6cde29c +depends: +- python >=3.9 +- typing-extensions >=4.0.0 +license: MIT +license_family: MIT +size: 18074 +timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab +md5: c6b0543676ecb1fb2d7643941fe375f2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 64927 +timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +noarch: generic +sha256: c31ab719d256bc6f89926131e88ecd0f0c5d003fe8481852c6424f4ec6c7eb29 +md5: a2ac7763a9ac75055b68f325d3255265 +depends: +- python >=3.14 +license: BSD-3-Clause AND MIT AND EPL-2.0 +size: 7514 +timestamp: 1767044983590 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda +sha256: 3ad3500bff54a781c29f16ce1b288b36606e2189d0b0ef2f67036554f47f12b0 +md5: 8910d2c46f7e7b519129f486e0fe927a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- libbrotlicommon 1.2.0 hb03c661_1 +license: MIT +license_family: MIT +size: 367376 +timestamp: 1764017265553 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 +md5: d2ffd7602c02f2b316fd921d39876885 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 260182 +timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda +sha256: a6b118fd1ed6099dc4fc03f9c492b88882a780fadaef4ed4f93dc70757713656 +md5: 765c4d97e877cdbbb88ff33152b86125 +depends: +- python >=3.10 +license: ISC +size: 151445 +timestamp: 1772001170301 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda +sha256: d86dfd428b2e3c364fa90e07437c8405d635aa4ef54b25ab51d9c712be4112a5 +md5: 49ee13eb9b8f44d63879c69b8a40a74b +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 58510 +timestamp: 1773660086450 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715 +md5: ea8a6c3256897cc31263de9f455e25d9 +depends: +- python >=3.10 +- __unix +- python +license: BSD-3-Clause +license_family: BSD +size: 97676 +timestamp: 1764518652276 +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 +md5: b866ff7007b934d564961066c8195983 +depends: +- humanfriendly >=9.1 +- python >=3.9 +license: MIT +license_family: MIT +size: 43758 +timestamp: 1733928076798 +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +sha256: 59c9e29800b483b390467f90e82b0da3a4fbf0612efe1c90813fca232780e160 +md5: 071cf7b0ce333c81718b054066c15102 +depends: +- networkx >=2.0 +- numpy +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 39326 +timestamp: 1735759976140 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +noarch: generic +sha256: 91b06300879df746214f7363d6c27c2489c80732e46a369eb2afc234bcafb44c +md5: 3bb89e4f795e5414addaa531d6b1500a +depends: +- python >=3.14,<3.15.0a0 +- python_abi * *_cp314 +license: Python-2.0 +size: 50078 +timestamp: 1770674447292 +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda +sha256: 0cc345e4dead417996ce9a1f088b28d858f03d113d43c1963d29194366dcce27 +md5: a0535741a4934b3e386051065c58761a +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat 2.7.4 hecca717_0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 145274 +timestamp: 1771259434699 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +sha256: aa4a44dba97151221100a637c7f4bde619567afade9c0265f8e1c8eed8d7bd8c +md5: 867127763fbe935bab59815b6e0b7b5c +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 270705 +timestamp: 1771382710863 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 +md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 +depends: +- python >=3.10 +- hyperframe >=6.1,<7 +- hpack >=4.1,<5 +- python +license: MIT +license_family: MIT +size: 95967 +timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba +md5: 0a802cb9888dd14eeefc611f05c40b6e +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 30731 +timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d +md5: 7fe569c10905402ed47024fc481bb371 +depends: +- __unix +- python >=3.9 +license: MIT +license_family: MIT +size: 73563 +timestamp: 1733928021866 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +sha256: 6c4343b376d0b12a4c75ab992640970d36c933cad1fd924f6a1181fa91710e80 +md5: daddf757c3ecd6067b9af1df1f25d89e +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 67994 +timestamp: 1766267728652 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 +md5: 8e6923fc12f1fe8f8c4e5c9f343256ac +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 17397 +timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a +md5: c80d8a3b84358cb967fa81e7075fbc8a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12723451 +timestamp: 1773822285671 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda +sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 +md5: 53abe63df7e10a6ba605dc5f9f961d36 +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 50721 +timestamp: 1760286526795 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 +md5: 080594bf4493e6bae2607e65390c520a +depends: +- python >=3.10 +- zipp >=3.20 +- python +license: Apache-2.0 +license_family: APACHE +size: 34387 +timestamp: 1773931568510 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b +md5: 04558c96691bed63104678757beb4f8d +depends: +- markupsafe >=2.0 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 120685 +timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 +md5: ada41c863af263cc4c5fcbaff7c3e4dc +depends: +- attrs >=22.2.0 +- jsonschema-specifications >=2023.3.6 +- python >=3.10 +- referencing >=0.28.4 +- rpds-py >=0.25.0 +- python +license: MIT +license_family: MIT +size: 82356 +timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 +md5: 439cd0f567d697b20a8f45cb70a1005a +depends: +- python >=3.10 +- referencing >=0.31.0 +- python +license: MIT +license_family: MIT +size: 19236 +timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2 +sha256: 7f243680ca03eba7457b7a48f93a9440ba8181a8eac20a3eb5ef165ab6c96664 +md5: b3723b235b0758abaae8c82ce4d80146 +depends: +- __glibc >=2.17,<3.0.a0 +- expat >=2.2.10,<3.0.0a0 +- fontconfig +- fonts-conda-forge +- libgcc-ng >=9.3.0 +- mathjax 2.7.* +- nspr >=4.29,<5.0a0 +- nss >=3.62,<4.0a0 +- sqlite >=3.34.0,<4.0a0 +license: MIT +license_family: MIT +size: 62099926 +timestamp: 1615199463039 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +sha256: 836ec4b895352110335b9fdcfa83a8dcdbe6c5fb7c06c4929130600caea91c0a +md5: 6f2e2c8f58160147c4d1c6f4c14cbac4 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 249959 +timestamp: 1768184673131 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda +sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c +md5: 18335a698559cdbcd86150a48bf54ba6 +depends: +- __glibc >=2.17,<3.0.a0 +- zstd >=1.5.7,<1.6.0a0 +constrains: +- binutils_impl_linux-64 2.45.1 +license: GPL-3.0-only +license_family: GPL +size: 728002 +timestamp: 1774197446916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +sha256: f84cb54782f7e9cea95e810ea8fef186e0652d0fa73d3009914fa2c1262594e1 +md5: a752488c68f2e7c456bcbd8f16eec275 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 261513 +timestamp: 1773113328888 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda +build_number: 5 +sha256: 18c72545080b86739352482ba14ba2c4815e19e26a7417ca21a95b76ec8da24c +md5: c160954f7418d7b6e87eaf05a8913fa9 +depends: +- libopenblas >=0.3.30,<0.3.31.0a0 +- libopenblas >=0.3.30,<1.0a0 +constrains: +- mkl <2026 +- liblapack 3.11.0 5*_openblas +- libcblas 3.11.0 5*_openblas +- blas 2.305 openblas +- liblapacke 3.11.0 5*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18213 +timestamp: 1765818813880 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda +build_number: 5 +sha256: 0cbdcc67901e02dc17f1d19e1f9170610bd828100dc207de4d5b6b8ad1ae7ad8 +md5: 6636a2b6f1a87572df2970d3ebc87cc0 +depends: +- libblas 3.11.0 5_h4a7cf45_openblas +constrains: +- liblapacke 3.11.0 5*_openblas +- blas 2.305 openblas +- liblapack 3.11.0 5*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18194 +timestamp: 1765818837135 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 +md5: 6c77a605a7a689d17d4819c0f8ac9a00 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 73490 +timestamp: 1761979956660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 +md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76798 +timestamp: 1771259418166 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 +md5: a360c33a5abe61c07959e449fa1453eb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 58592 +timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 +md5: e289f3d17880e44b633ba911d57a321b +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8049 +timestamp: 1774298163029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d +md5: fb16b4b69e3f1dcfe79d80db8fd0c55d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 384575 +timestamp: 1774298162622 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 +md5: 0aa00f03f9e39fb9876085dee11a85d4 +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1041788 +timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 +md5: d5e96b1ed75ca01906b3d2469b4ce493 +depends: +- libgcc 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27526 +timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda +sha256: d2c9fad338fd85e4487424865da8e74006ab2e2475bd788f624d7a39b2a72aee +md5: 9063115da5bc35fdc3e1002e69b9ef6e +depends: +- libgfortran5 15.2.0 h68bc16d_18 +constrains: +- libgfortran-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27523 +timestamp: 1771378269450 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda +sha256: 539b57cf50ec85509a94ba9949b7e30717839e4d694bc94f30d41c9d34de2d12 +md5: 646855f357199a12f02a87382d429b75 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=15.2.0 +constrains: +- libgfortran 15.2.0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 2482475 +timestamp: 1771378241063 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 +md5: 239c5e9546c38a1e884d69effcf4c882 +depends: +- __glibc >=2.17,<3.0.a0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 603262 +timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32 +md5: 8397539e3a0bbd1695584fb4f927485a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 633710 +timestamp: 1762094827865 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda +build_number: 5 +sha256: c723b6599fcd4c6c75dee728359ef418307280fa3e2ee376e14e85e5bbdda053 +md5: b38076eb5c8e40d0106beda6f95d7609 +depends: +- libblas 3.11.0 5_h4a7cf45_openblas +constrains: +- blas 2.305 openblas +- liblapacke 3.11.0 5*_openblas +- libcblas 3.11.0 5*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18200 +timestamp: 1765818857876 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb +md5: c7c83eecbb72d88b940c249af56c8b17 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 113207 +timestamp: 1768752626120 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda +sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 +md5: 2c21e66f50753a083cbe6b80f38268fa +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-2-Clause +license_family: BSD +size: 92400 +timestamp: 1769482286018 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda +sha256: 199d79c237afb0d4780ccd2fbf829cea80743df60df4705202558675e07dd2c5 +md5: be43915efc66345cccb3c310b6ed0374 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libgfortran +- libgfortran5 >=14.3.0 +constrains: +- openblas >=0.3.30,<0.3.31.0a0 +license: BSD-3-Clause +license_family: BSD +size: 5927939 +timestamp: 1763114673331 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +sha256: 36ade759122cdf0f16e2a2562a19746d96cf9c863ffaa812f2f5071ebbe9c03c +md5: 5f13ffc7d30ffec87864e678df9957b4 +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 317669 +timestamp: 1770691470744 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda +sha256: d716847b7deca293d2e49ed1c8ab9e4b9e04b9d780aea49a97c26925b28a7993 +md5: fd893f6a3002a635b5e50ceb9dd2c0f4 +depends: +- __glibc >=2.17,<3.0.a0 +- icu >=78.2,<79.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: blessing +size: 951405 +timestamp: 1772818874251 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e +md5: 1b08cd684f34175e4514474793d44bcb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc 15.2.0 he0feb66_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5852330 +timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 +md5: cd5a90476766d53e901500df9215e927 +depends: +- __glibc >=2.17,<3.0.a0 +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 435273 +timestamp: 1762022005702 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee +md5: db409b7c1720428638e7c0d509d3e1b5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 40311 +timestamp: 1766271528534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b +md5: aea31d2e5b1091feca96fcfe945c3cf9 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 429011 +timestamp: 1752159441324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa +md5: 92ed62436b625154323d40d5f2f11dd7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 395888 +timestamp: 1727278577118 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 +md5: d87ff7921124eccd67248aa483c23fec +depends: +- __glibc >=2.17,<3.0.a0 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 63629 +timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +sha256: 20e0892592a3e7c683e3d66df704a9425d731486a97c34fc56af4da1106b2b6b +md5: ba0a9221ce1063f31692c07370d062f3 +depends: +- importlib-metadata >=4.4 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 85893 +timestamp: 1770694658918 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e +md5: 5b5203189eb668f042ac2b0826244964 +depends: +- mdurl >=0.1,<1 +- python >=3.10 +license: MIT +license_family: MIT +size: 64736 +timestamp: 1754951288511 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda +sha256: c279be85b59a62d5c52f5dd9a4cd43ebd08933809a8416c22c3131595607d4cf +md5: 9a17c4307d23318476d7fbf0fedc0cde +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- jinja2 >=3.0.0 +license: BSD-3-Clause +license_family: BSD +size: 27424 +timestamp: 1772445227915 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2 +sha256: 02fef69bde69db264a12f21386612262f545b6e3e68d8f1ccec19f3eaae58edf +md5: 86e69bd82c2a2c6fd29f5ab7e02b3691 +license: Apache-2.0 +license_family: Apache +size: 22281629 +timestamp: 1662784498331 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 +md5: 592132998493b3ff25fd7479396e8351 +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 14465 +timestamp: 1733255681319 +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda +sha256: f005760b13093362fc9c997d603dd487de32ab2e821a3cbce52a42bcb8136517 +md5: 698a8a27c2b9d8a542c70cb47099a75e +depends: +- click +- coloredlogs +- humanize +- importlib-metadata +- jinja2 >=3.0.0 +- jsonschema +- markdown +- natsort +- numpy +- packaging +- pillow >=10.2.0 +- plotly >=5.18 +- polars-lts-cpu +- pyaml-env +- pydantic >=2.7.1 +- python >=3.8,!=3.14.1 +- python-dotenv +- python-kaleido 0.2.1 +- pyyaml >=4 +- requests +- rich >=10 +- rich-click +- spectra >=0.0.10 +- tiktoken +- tqdm +- typeguard +license: GPL-3.0-or-later +license_family: GPL3 +size: 4198799 +timestamp: 1765300743879 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +sha256: 541fd4390a0687228b8578247f1536a821d9261389a65585af9d1a6f2a14e1e0 +md5: 30bec5e8f4c3969e2b1bd407c5e52afb +depends: +- python >=3.10 +- python +license: MIT +size: 280459 +timestamp: 1774380620329 +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 +md5: e941e85e273121222580723010bd4fa2 +depends: +- python >=3.9 +- python +license: MIT +license_family: MIT +size: 39262 +timestamp: 1770905275632 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 +md5: 47e340acb35de30501a76c7c799c41d7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 891641 +timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 +md5: a2c1eeadae7a309daed9d62c96012a2b +depends: +- python >=3.11 +- python +constrains: +- numpy >=1.25 +- scipy >=1.11.2 +- matplotlib-base >=3.8 +- pandas >=2.0 +license: BSD-3-Clause +license_family: BSD +size: 1587439 +timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda +sha256: e3664264bd936c357523b55c71ed5a30263c6ba278d726a75b1eb112e6fb0b64 +md5: e235d5566c9cc8970eb2798dd4ecf62f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: MPL-2.0 +license_family: MOZILLA +size: 228588 +timestamp: 1762348634537 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda +sha256: 44dd98ffeac859d84a6dcba79a2096193a42fc10b29b28a5115687a680dd6aea +md5: 567fbeed956c200c1db5782a424e58ee +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libsqlite >=3.51.0,<4.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- nspr >=4.38,<5.0a0 +license: MPL-2.0 +license_family: MOZILLA +size: 2057773 +timestamp: 1763485556350 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py314h2b28147_0.conda +sha256: f2ba8cb0d86a6461a6bcf0d315c80c7076083f72c6733c9290086640723f79ec +md5: 36f5b7eb328bdc204954a2225cf908e2 +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +- libcblas >=3.9.0,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- libblas >=3.9.0,<4.0a0 +constrains: +- numpy-base <0a0 +license: BSD-3-Clause +license_family: BSD +size: 8927860 +timestamp: 1773839233468 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda +sha256: 3900f9f2dbbf4129cf3ad6acf4e4b6f7101390b53843591c53b00f034343bc4d +md5: 11b3379b191f63139e29c0d19dee24cd +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.50,<1.7.0a0 +- libstdcxx >=14 +- libtiff >=4.7.1,<4.8.0a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-2-Clause +license_family: BSD +size: 355400 +timestamp: 1758489294972 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c +md5: f61eb8cd60ff9057122a3d338b99c00f +depends: +- __glibc >=2.17,<3.0.a0 +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3164551 +timestamp: 1769555830639 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda +sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 +md5: b76541e68fea4d511b1ac46a28dcd2c6 +depends: +- python >=3.8 +- python +license: Apache-2.0 +license_family: APACHE +size: 72010 +timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.1.1-py314h8ec4b1a_0.conda +sha256: 9e6ec8f3213e8b7d64b0ad45f84c51a2c9eba4398efda31e196c9a56186133ee +md5: 79678378ae235e24b3aa83cee1b38207 +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libwebp-base >=1.6.0,<2.0a0 +- zlib-ng >=2.3.3,<2.4.0a0 +- python_abi 3.14.* *_cp314 +- tk >=8.6.13,<8.7.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libxcb >=1.17.0,<2.0a0 +- openjpeg >=2.5.4,<3.0a0 +- lcms2 >=2.18,<3.0a0 +- libtiff >=4.7.1,<4.8.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +license: HPND +size: 1073026 +timestamp: 1770794002408 +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 +md5: 3e9427ee186846052e81fadde8ebe96a +depends: +- narwhals >=1.15.1 +- packaging +- python >=3.10 +constrains: +- ipywidgets >=7.6 +license: MIT +license_family: MIT +size: 5251872 +timestamp: 1772628857717 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda +sha256: d332c2d5002fc440ae37ed9679ffc21b552f18d20232390005d1dd3bce0888d3 +md5: d5a4e013a30dd8dfde9ab39f45aaf9c1 +depends: +- polars-runtime-32 ==1.39.3 +- python >=3.10 +- python +constrains: +- numpy >=1.16.0 +- pyarrow >=7.0.0 +- fastexcel >=0.9 +- openpyxl >=3.0.0 +- xlsx2csv >=0.8.0 +- connectorx >=0.3.2 +- deltalake >=1.0.0 +- pyiceberg >=0.7.1 +- altair >=5.4.0 +- great_tables >=0.8.0 +- polars-runtime-32 ==1.39.3 +- polars-runtime-64 ==1.39.3 +- polars-runtime-compat ==1.39.3 +license: MIT +license_family: MIT +size: 533495 +timestamp: 1774207987966 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda +sha256: e466fb31f67ba9bde18deafeb34263ca5eb25807f39ead0e9d753a8e82c4c4f4 +md5: ef0340e75068ac8ff96462749b5c98e7 +depends: +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 +license: MIT +license_family: MIT +size: 3902 +timestamp: 1760206808444 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.39.3-py310hffdcd12_1.conda +noarch: python +sha256: 9744f8086bb0832998f5b01076f57ddc9efbe460e493b14303c3567dc4f401e7 +md5: f9327f9f2cfc4215f55b613e64afd3ba +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 37570276 +timestamp: 1774207987966 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.39.3-py310hbcd5346_1.conda +noarch: python +sha256: bf0b932713f0f27924f42159c98426e0073bb6145ed796eaa4cec79ca05363c7 +md5: 4b9b312453eebd6fbdbbe2a88fa1b5c4 +depends: +- python +- libgcc >=14 +- libstdcxx >=14 +- __glibc >=2.17,<3.0.a0 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 37224264 +timestamp: 1774207985377 +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d +md5: f2c23a77b25efcad57d377b34bd84941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 593603 +timestamp: 1769710381284 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 +md5: b3c17d95b5a10c6e64a21fa17573e70e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 8252 +timestamp: 1726802366959 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +sha256: 58994e0d2ea8584cb399546e6f6896d771995e6121d1a7b6a2c9948388358932 +md5: e17be1016bcc3516827b836cd3e4d9dc +depends: +- python >=3.9 +- pyyaml >=5.0,<=7.0 +license: MIT +license_family: MIT +size: 14645 +timestamp: 1736766960536 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda +sha256: 868569d9505b7fe246c880c11e2c44924d7613a8cdcc1f6ef85d5375e892f13d +md5: c3946ed24acdb28db1b5d63321dbca7d +depends: +- typing-inspection >=0.4.2 +- typing_extensions >=4.14.1 +- python >=3.10 +- typing-extensions >=4.6.1 +- annotated-types >=0.6.0 +- pydantic-core ==2.41.5 +- python +license: MIT +license_family: MIT +size: 340482 +timestamp: 1764434463101 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py314h2e6c369_1.conda +sha256: 7e0ae379796e28a429f8e48f2fe22a0f232979d65ec455e91f8dac689247d39f +md5: 432b0716a1dfac69b86aa38fdd59b7e6 +depends: +- python +- typing-extensions >=4.6.0,!=4.7.0 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 1943088 +timestamp: 1762988995556 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a +md5: 6b6ece66ebcae2d5f326c77ef2c5a066 +depends: +- python >=3.9 +license: BSD-2-Clause +license_family: BSD +size: 889287 +timestamp: 1750615908735 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 +md5: 461219d1a5bd61342293efa2c0c90eac +depends: +- __unix +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 21085 +timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda +build_number: 101 +sha256: cb0628c5f1732f889f53a877484da98f5a0e0f47326622671396fb4f2b0cd6bd +md5: c014ad06e60441661737121d3eae8a60 +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- ld_impl_linux-64 >=2.36.1 +- libexpat >=2.7.3,<3.0a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- liblzma >=5.8.2,<6.0a0 +- libmpdec >=4.0.0,<5.0a0 +- libsqlite >=3.51.2,<4.0a0 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +- openssl >=3.5.5,<4.0a0 +- python_abi 3.14.* *_cp314 +- readline >=8.3,<9.0a0 +- tk >=8.6.13,<8.7.0a0 +- tzdata +- zstd >=1.5.7,<1.6.0a0 +license: Python-2.0 +size: 36702440 +timestamp: 1770675584356 +python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 +md5: 130584ad9f3a513cdd71b1fdc1244e9c +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 27848 +timestamp: 1772388605021 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +sha256: 233aebd94c704ac112afefbb29cf4170b7bc606e22958906f2672081bc50638a +md5: 235765e4ea0d0301c75965985163b5a1 +depends: +- cpython 3.14.3.* +- python_abi * *_cp314 +license: Python-2.0 +size: 50062 +timestamp: 1770674497152 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 +md5: 310259a5b03ff02289d7705f39e2b1d2 +depends: +- kaleido-core 0.2.1.* +- python >=3.5 +license: MIT +license_family: MIT +size: 18320 +timestamp: 1615204747600 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +build_number: 8 +sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 +md5: 0539938c55b6b1a59b560e843ad864a4 +constrains: +- python 3.14.* *_cp314 +license: BSD-3-Clause +license_family: BSD +size: 6989 +timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda +sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d +md5: 2035f68f96be30dc60a5dfd7452c7941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- yaml >=0.2.5,<0.3.0a0 +license: MIT +license_family: MIT +size: 202391 +timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda +sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 +md5: d7d95fc8287ea7bf33e0e7116d2b95ec +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-3.0-only +license_family: GPL +size: 345073 +timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 +md5: 870293df500ca7e18bedefa5838a22ab +depends: +- attrs >=22.2.0 +- python >=3.10 +- rpds-py >=0.7.0 +- typing_extensions >=4.4.0 +- python +license: MIT +license_family: MIT +size: 51788 +timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.2.28-py314h5bd0f2a_0.conda +sha256: e085e336f1446f5263a3ec9747df8c719b6996753901181add50dc4fdd8bb2e8 +md5: 3c8b6a8c4d0ff5a264e9831eac4941f4 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +license: Apache-2.0 AND CNRI-Python +license_family: PSF +size: 411924 +timestamp: 1772255161535 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda +sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5 +md5: c65df89a0b2e321045a9e01d1337b182 +depends: +- python >=3.10 +- certifi >=2017.4.17 +- charset-normalizer >=2,<4 +- idna >=2.5,<4 +- urllib3 >=1.21.1,<3 +- python +constrains: +- chardet >=3.0.2,<6 +license: Apache-2.0 +license_family: APACHE +size: 63602 +timestamp: 1766926974520 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +sha256: b06ce84d6a10c266811a7d3adbfa1c11f13393b91cc6f8a5b468277d90be9590 +md5: 7a6289c50631d620652f5045a63eb573 +depends: +- markdown-it-py >=2.2.0 +- pygments >=2.13.0,<3.0.0 +- python >=3.10 +- typing_extensions >=4.0.0,<5.0.0 +- python +license: MIT +license_family: MIT +size: 208472 +timestamp: 1771572730357 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 +md5: 0c20a8ebcddb24a45da89d5e917e6cb9 +depends: +- python >=3.10 +- rich >=12 +- click >=8 +- typing-extensions >=4 +- __unix +- python +license: MIT +license_family: MIT +size: 64356 +timestamp: 1769850479089 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda +sha256: e53b0cbf3b324eaa03ca1fe1a688fdf4ab42cea9c25270b0a7307d8aaaa4f446 +md5: c1c368b5437b0d1a68f372ccf01cb133 +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 376121 +timestamp: 1764543122774 +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +sha256: 7c65782d2511738e62c70462e89d65da4fa54d5a7e47c46667bcd27a59f81876 +md5: 472239e4eb7b5a84bb96b3ed7e3a596a +depends: +- colormath >=3.0.0 +- python >=3.9 +license: MIT +license_family: MIT +size: 22284 +timestamp: 1735770589188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.52.0-h04a0ce9_0.conda +sha256: c9af81e7830d9c4b67a7f48e512d060df2676b29cac59e3b31f09dbfcee29c58 +md5: 7d9d7efe9541d4bb71b5934e8ee348ea +depends: +- __glibc >=2.17,<3.0.a0 +- icu >=78.2,<79.0a0 +- libgcc >=14 +- libsqlite 3.52.0 hf4e2dac_0 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +- readline >=8.3,<9.0a0 +license: blessing +size: 203641 +timestamp: 1772818888368 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda +sha256: 7e395d67fd249d901beb1ae269057763c0d8c3ee5f7a348694bdb16d158a37d9 +md5: d705f9d8a1185a2b01cced191177a028 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- regex >=2022.1.18 +- requests >=2.26.0 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 939648 +timestamp: 1764028306357 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda +sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac +md5: cffd3bdd58090148f4cfcd831f4b26ab +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +constrains: +- xorg-libx11 >=1.8.12,<2.0a0 +license: TCL +license_family: BSD +size: 3301196 +timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 +md5: e5ce43272193b38c2e9037446c1d9206 +depends: +- python >=3.10 +- __unix +- python +license: MPL-2.0 and MIT +size: 94132 +timestamp: 1770153424136 +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +sha256: 39d8ae33c43cdb8f771373e149b0b4fae5a08960ac58dcca95b2f1642bb17448 +md5: 260af1b0a94f719de76b4e14094e9a3b +depends: +- importlib-metadata >=3.6 +- python >=3.10 +- typing-extensions >=4.10.0 +- typing_extensions >=4.14.0 +constrains: +- pytest >=7 +license: MIT +license_family: MIT +size: 36838 +timestamp: 1771532971545 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c +md5: edd329d7d3a4ab45dcf905899a7a6115 +depends: +- typing_extensions ==4.15.0 pyhcf101f3_0 +license: PSF-2.0 +license_family: PSF +size: 91383 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +sha256: 70db27de58a97aeb7ba7448366c9853f91b21137492e0b4430251a1870aa8ff4 +md5: a0a4a3035667fc34f29bfbd5c190baa6 +depends: +- python >=3.10 +- typing_extensions >=4.12.0 +license: MIT +license_family: MIT +size: 18923 +timestamp: 1764158430324 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 +md5: 0caa1af407ecff61170c9437a808404d +depends: +- python >=3.10 +- python +license: PSF-2.0 +license_family: PSF +size: 51692 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c +md5: ad659d0a2b3e47e38d829aa8cad2d610 +license: LicenseRef-Public-Domain +size: 119135 +timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a +md5: 9272daa869e03efe68833e3dc7a02130 +depends: +- backports.zstd >=1.0.0 +- brotli-python >=1.2.0 +- h2 >=4,<5 +- pysocks >=1.5.6,<2.0,!=1.5.7 +- python >=3.10 +license: MIT +license_family: MIT +size: 103172 +timestamp: 1767817860341 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b +md5: b2895afaf55bf96a8c8282a2e47a5de0 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 15321 +timestamp: 1762976464266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 +md5: 1dafce8548e38671bea82e3f5c6ce22f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 20591 +timestamp: 1762976546182 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda +sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad +md5: a77f85f77be52ff59391544bfe73390a +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +license: MIT +license_family: MIT +size: 85189 +timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae +md5: 30cd29cb87d819caead4d55184c1d115 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 24194 +timestamp: 1764460141901 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda +sha256: ea4e50c465d70236408cb0bfe0115609fd14db1adcd8bd30d8918e0291f8a75f +md5: 2aadb0d17215603a82a2a6b0afd9a4cb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Zlib +license_family: Other +size: 122618 +timestamp: 1770167931827 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 +md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 +depends: +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 601375 +timestamp: 1764777111296 diff --git a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt new file mode 100644 index 0000000..a55a4d4 --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt @@ -0,0 +1,126 @@ + +# This file may be used to create an environment using: +# $ conda create --name --file +# platform: linux-64 +@EXPLICIT +https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda#239c5e9546c38a1e884d69effcf4c882 +https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda#a9f577daf3de00bca7c3c76c0ecbd1de +https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda#0aa00f03f9e39fb9876085dee11a85d4 +https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda#d2ffd7602c02f2b316fd921d39876885 +https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda#d87ff7921124eccd67248aa483c23fec +https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda#4a13eeac0b5c8e5b8ab496e6c4ddd829 +https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda#18335a698559cdbcd86150a48bf54ba6 +https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda#49f570f3bc4c874a06ea69b7225753af +https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda#a360c33a5abe61c07959e449fa1453eb +https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda#b88d90cad08e6bc8ad540cb310a761fb +https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda#2c21e66f50753a083cbe6b80f38268fa +https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda#1b08cd684f34175e4514474793d44bcb +https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda#c80d8a3b84358cb967fa81e7075fbc8a +https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.0-hf4e2dac_0.conda#810d83373448da85c3f673fbcb7ad3a3 +https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda#38ffe67b78c9d4de527be8315e5ada2c +https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda#47e340acb35de30501a76c7c799c41d7 +https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda#e18ad67cf881dcadee8b8d9e2f8e5f73 +https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda#da1b85b6a87e141f5140bb9924cecab0 +https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda#0539938c55b6b1a59b560e843ad864a4 +https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda#d7d95fc8287ea7bf33e0e7116d2b95ec +https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda#cffd3bdd58090148f4cfcd831f4b26ab +https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda#ad659d0a2b3e47e38d829aa8cad2d610 +https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda#a443f87920815d41bfe611296e507995 +https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda#f111d4cfaf1fe9496f386bc98ae94452 +https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda#e4e60721757979d01d3964122f674959 +https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda#aaa2a381ccc56eac91d63b6c1240312f +https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda#0caa1af407ecff61170c9437a808404d +https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda#edd329d7d3a4ab45dcf905899a7a6115 +https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda#2934f256a8acfe48f6ebb4fce6cde29c +https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda#c6b0543676ecb1fb2d7643941fe375f2 +https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda#a2ac7763a9ac75055b68f325d3255265 +https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda#8910d2c46f7e7b519129f486e0fe927a +https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda#929471569c93acefb30282a22060dcd5 +https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda#a9167b9571f3baa9d448faa2139d1089 +https://conda.anaconda.org/conda-forge/noarch/click-8.3.2-pyhc90fa1f_0.conda#4d18bc3af7cfcea97bd817164672a08c +https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda#7fe569c10905402ed47024fc481bb371 +https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda#b866ff7007b934d564961066c8195983 +https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda#a2c1eeadae7a309daed9d62c96012a2b +https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda#646855f357199a12f02a87382d429b75 +https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda#9063115da5bc35fdc3e1002e69b9ef6e +https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda#89d61bc91d3f39fda0ca10fcd3c68594 +https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda#6d6d225559bfa6e2f3c90ee9c03d4e2e +https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda#36ae340a916635b97ac8a0655ace2a35 +https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-6_h47877c9_openblas.conda#881d801569b201c2e753f03c84b85e15 +https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py314h2b28147_0.conda#36f5b7eb328bdc204954a2225cf908e2 +https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda#071cf7b0ce333c81718b054066c15102 +https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.5-hecca717_0.conda#7de50d165039df32d38be74c1b34a910 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2#0c96522c6bdaed4b1566d11387caaf45 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2#34893075a5c9e55cdafac56607368fc6 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2#4d59c254e01d9cde7957100457e2d5fb +https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda#49023d73832ef61042f6a237cb2687e7 +https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda#eba48a68a1a2b9d3c0d9511548db85db +https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda#fb16b4b69e3f1dcfe79d80db8fd0c55d +https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda#e289f3d17880e44b633ba911d57a321b +https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda#867127763fbe935bab59815b6e0b7b5c +https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda#a7970cd949a077b7cb9696379d338681 +https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda#0a802cb9888dd14eeefc611f05c40b6e +https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda#8e6923fc12f1fe8f8c4e5c9f343256ac +https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda#164fc43f0b53b6e3a7bc7dce5e4f1dc9 +https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda#daddf757c3ecd6067b9af1df1f25d89e +https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda#fb7130c190f9b4ec91219840a05ba3ac +https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda#e1c36c6121a7c9c76f2f148f1e83b983 +https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda#080594bf4493e6bae2607e65390c520a +https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda#9a17c4307d23318476d7fbf0fedc0cde +https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda#04558c96691bed63104678757beb4f8d +https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda#c1c368b5437b0d1a68f372ccf01cb133 +https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda#870293df500ca7e18bedefa5838a22ab +https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda#439cd0f567d697b20a8f45cb70a1005a +https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda#ada41c863af263cc4c5fcbaff7c3e4dc +https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda#d5e96b1ed75ca01906b3d2469b4ce493 +https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2#86e69bd82c2a2c6fd29f5ab7e02b3691 +https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda#e235d5566c9cc8970eb2798dd4ecf62f +https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda#567fbeed956c200c1db5782a424e58ee +https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.0-h04a0ce9_0.conda#dc540e5bd5616d83a1ec46af8315ff98 +https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2#b3723b235b0758abaae8c82ce4d80146 +https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda#6178c6f2fb254558238ef4e6c56fb782 +https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda#a752488c68f2e7c456bcbd8f16eec275 +https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda#6c77a605a7a689d17d4819c0f8ac9a00 +https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda#aea31d2e5b1091feca96fcfe945c3cf9 +https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda#cd5a90476766d53e901500df9215e927 +https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda#6f2e2c8f58160147c4d1c6f4c14cbac4 +https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda#b3c17d95b5a10c6e64a21fa17573e70e +https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda#b2895afaf55bf96a8c8282a2e47a5de0 +https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda#1dafce8548e38671bea82e3f5c6ce22f +https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda#92ed62436b625154323d40d5f2f11dd7 +https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda#ba0a9221ce1063f31692c07370d062f3 +https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda#592132998493b3ff25fd7479396e8351 +https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda#5b5203189eb668f042ac2b0826244964 +https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda#e941e85e273121222580723010bd4fa2 +https://conda.anaconda.org/conda-forge/noarch/packaging-26.1-pyhc364b38_0.conda#b8ae38639d323d808da535fb71e31be8 +https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda#11b3379b191f63139e29c0d19dee24cd +https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda#2aadb0d17215603a82a2a6b0afd9a4cb +https://conda.anaconda.org/conda-forge/linux-64/pillow-12.2.0-py314h8ec4b1a_0.conda#76c4757c0ec9d11f969e8eb44899307b +https://conda.anaconda.org/conda-forge/noarch/narwhals-2.20.0-pyhcf101f3_0.conda#6cac1a50359219d786453c6fef819f98 +https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda#3e9427ee186846052e81fadde8ebe96a +https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.40.0-py310hffdcd12_0.conda#8eacf9ff4d4e1ca1b52f8f3ba3e0c993 +https://conda.anaconda.org/conda-forge/noarch/polars-1.40.0-pyh58ad624_0.conda#fd16be490f5403adfbf27dd4901bbe34 +https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.40.0-py310hbcd5346_0.conda#03a6899e17bb731c8e21b08212f1a64c +https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda#ef0340e75068ac8ff96462749b5c98e7 +https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda#a77f85f77be52ff59391544bfe73390a +https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda#2035f68f96be30dc60a5dfd7452c7941 +https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda#e17be1016bcc3516827b836cd3e4d9dc +https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.3-py314h2e6c369_0.conda#1f3fd537f929b8d3236f9f0f0e7f7a32 +https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda#a0a4a3035667fc34f29bfbd5c190baa6 +https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.3-pyhcf101f3_0.conda#f690e6f204efd2e5c06b57518a383d98 +https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda#130584ad9f3a513cdd71b1fdc1244e9c +https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2#310259a5b03ff02289d7705f39e2b1d2 +https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda#461219d1a5bd61342293efa2c0c90eac +https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda#9272daa869e03efe68833e3dc7a02130 +https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda#10afbb4dbf06ff959ad25a92ccee6e59 +https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda#16c18772b340887160c79a6acc022db0 +https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda#0242025a3c804966bf71aa04eee82f66 +https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda#0c20a8ebcddb24a45da89d5e917e6cb9 +https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda#472239e4eb7b5a84bb96b3ed7e3a596a +https://conda.anaconda.org/conda-forge/linux-64/regex-2026.4.4-py314h5bd0f2a_0.conda#4ffb42385183c854564f1f9adcf80a63 +https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda#d705f9d8a1185a2b01cced191177a028 +https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda#e5ce43272193b38c2e9037446c1d9206 +https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda#260af1b0a94f719de76b4e14094e9a3b +https://conda.anaconda.org/bioconda/noarch/multiqc-1.34-pyhdfd78af_0.conda#a7111ab9a6a6146b40cbce16655ac873 +https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh145f28c_0.conda#09a970fbf75e8ed1aa633827ded6aa4f +https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda#f2c23a77b25efcad57d377b34bd84941 diff --git a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt new file mode 100644 index 0000000..a58231a --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt @@ -0,0 +1,1502 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-aarch64: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.7.4-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py314haac167e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.1.1-py314hac3e5ec_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.39.3-py310hff09b76_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.39.3-py310hf00a4a2_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.41.5-py314h451b6cc_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.2.28-py314h51f160d_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.52.0-hf1c7be2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 +md5: 468fd3bb9e1f671d36c2cbc677e56f1d +depends: +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28926 +timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 +md5: aaa2a381ccc56eac91d63b6c1240312f +depends: +- cpython +- python-gil +license: MIT +license_family: MIT +size: 8191 +timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 +md5: 2934f256a8acfe48f6ebb4fce6cde29c +depends: +- python >=3.9 +- typing-extensions >=4.0.0 +license: MIT +license_family: MIT +size: 18074 +timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab +md5: c6b0543676ecb1fb2d7643941fe375f2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 64927 +timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +noarch: generic +sha256: c31ab719d256bc6f89926131e88ecd0f0c5d003fe8481852c6424f4ec6c7eb29 +md5: a2ac7763a9ac75055b68f325d3255265 +depends: +- python >=3.14 +license: BSD-3-Clause AND MIT AND EPL-2.0 +size: 7514 +timestamp: 1767044983590 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda +sha256: 5a5b0cdcd7ed89c6a8fb830924967f6314a2b71944bc1ebc2c105781ba97aa75 +md5: a1b5c571a0923a205d663d8678df4792 +depends: +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +constrains: +- libbrotlicommon 1.2.0 he30d5cf_1 +license: MIT +license_family: MIT +size: 373193 +timestamp: 1764017486851 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c +md5: 840d8fc0d7b3209be93080bc20e07f2d +depends: +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 192412 +timestamp: 1771350241232 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda +sha256: a6b118fd1ed6099dc4fc03f9c492b88882a780fadaef4ed4f93dc70757713656 +md5: 765c4d97e877cdbbb88ff33152b86125 +depends: +- python >=3.10 +license: ISC +size: 151445 +timestamp: 1772001170301 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda +sha256: d86dfd428b2e3c364fa90e07437c8405d635aa4ef54b25ab51d9c712be4112a5 +md5: 49ee13eb9b8f44d63879c69b8a40a74b +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 58510 +timestamp: 1773660086450 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715 +md5: ea8a6c3256897cc31263de9f455e25d9 +depends: +- python >=3.10 +- __unix +- python +license: BSD-3-Clause +license_family: BSD +size: 97676 +timestamp: 1764518652276 +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 +md5: b866ff7007b934d564961066c8195983 +depends: +- humanfriendly >=9.1 +- python >=3.9 +license: MIT +license_family: MIT +size: 43758 +timestamp: 1733928076798 +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +sha256: 59c9e29800b483b390467f90e82b0da3a4fbf0612efe1c90813fca232780e160 +md5: 071cf7b0ce333c81718b054066c15102 +depends: +- networkx >=2.0 +- numpy +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 39326 +timestamp: 1735759976140 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +noarch: generic +sha256: 91b06300879df746214f7363d6c27c2489c80732e46a369eb2afc234bcafb44c +md5: 3bb89e4f795e5414addaa531d6b1500a +depends: +- python >=3.14,<3.15.0a0 +- python_abi * *_cp314 +license: Python-2.0 +size: 50078 +timestamp: 1770674447292 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.7.4-hfae3067_0.conda +sha256: 5f087bef054c681edcaae84a8c2230585b938691e371ff92957a30707b7fcdf7 +md5: b304307db639831ad7caabd2eac6fca6 +depends: +- libexpat 2.7.4 hfae3067_0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 137701 +timestamp: 1771259543650 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +sha256: 835aff8615dd8d8fff377679710ce81b8a2c47b6404e21a92fb349fda193a15c +md5: 0fed1ff55f4938a65907f3ecf62609db +depends: +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 279044 +timestamp: 1771382728182 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 +md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 +depends: +- python >=3.10 +- hyperframe >=6.1,<7 +- hpack >=4.1,<5 +- python +license: MIT +license_family: MIT +size: 95967 +timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba +md5: 0a802cb9888dd14eeefc611f05c40b6e +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 30731 +timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d +md5: 7fe569c10905402ed47024fc481bb371 +depends: +- __unix +- python >=3.9 +license: MIT +license_family: MIT +size: 73563 +timestamp: 1733928021866 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +sha256: 6c4343b376d0b12a4c75ab992640970d36c933cad1fd924f6a1181fa91710e80 +md5: daddf757c3ecd6067b9af1df1f25d89e +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 67994 +timestamp: 1766267728652 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 +md5: 8e6923fc12f1fe8f8c4e5c9f343256ac +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 17397 +timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +sha256: 49ba6aed2c6b482bb0ba41078057555d29764299bc947b990708617712ef6406 +md5: 546da38c2fa9efacf203e2ad3f987c59 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12837286 +timestamp: 1773822650615 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda +sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 +md5: 53abe63df7e10a6ba605dc5f9f961d36 +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 50721 +timestamp: 1760286526795 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 +md5: 080594bf4493e6bae2607e65390c520a +depends: +- python >=3.10 +- zipp >=3.20 +- python +license: Apache-2.0 +license_family: APACHE +size: 34387 +timestamp: 1773931568510 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b +md5: 04558c96691bed63104678757beb4f8d +depends: +- markupsafe >=2.0 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 120685 +timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 +md5: ada41c863af263cc4c5fcbaff7c3e4dc +depends: +- attrs >=22.2.0 +- jsonschema-specifications >=2023.3.6 +- python >=3.10 +- referencing >=0.28.4 +- rpds-py >=0.25.0 +- python +license: MIT +license_family: MIT +size: 82356 +timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 +md5: 439cd0f567d697b20a8f45cb70a1005a +depends: +- python >=3.10 +- referencing >=0.31.0 +- python +license: MIT +license_family: MIT +size: 19236 +timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2 +sha256: d3c7f4797566e6f983d16c2a87063a18e4b2d819a66230190a21584d70042755 +md5: 4f0d284f5d11e04277b552eb1c172c7f +depends: +- __glibc >=2.17,<3.0.a0 +- expat >=2.2.10,<3.0.0a0 +- fontconfig +- fonts-conda-forge +- libgcc-ng >=9.3.0 +- mathjax 2.7.* +- nspr >=4.29,<5.0a0 +- nss >=3.62,<4.0a0 +- sqlite >=3.34.0,<4.0a0 +license: MIT +license_family: MIT +size: 65750397 +timestamp: 1615199465742 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +sha256: 379ef5e91a587137391a6149755d0e929f1a007d2dcb211318ac670a46c8596f +md5: bb960f01525b5e001608afef9d47b79c +depends: +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 293039 +timestamp: 1768184778398 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda +sha256: 7abd913d81a9bf00abb699e8987966baa2065f5132e37e815f92d90fc6bba530 +md5: a21644fc4a83da26452a718dc9468d5f +depends: +- zstd >=1.5.7,<1.6.0a0 +constrains: +- binutils_impl_linux-aarch64 2.45.1 +license: GPL-3.0-only +license_family: GPL +size: 875596 +timestamp: 1774197520746 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +sha256: 8957fd460c1c132c8031f65fd5f56ec3807fd71b7cab2c5e2b0937b13404ab36 +md5: d13423b06447113a90b5b1366d4da171 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 240444 +timestamp: 1773114901155 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda +build_number: 5 +sha256: 700f3c03d0fba8e687a345404a45fbabe781c1cf92242382f62cef2948745ec4 +md5: 5afcea37a46f76ec1322943b3c4dfdc0 +depends: +- libopenblas >=0.3.30,<0.3.31.0a0 +- libopenblas >=0.3.30,<1.0a0 +constrains: +- mkl <2026 +- libcblas 3.11.0 5*_openblas +- liblapack 3.11.0 5*_openblas +- liblapacke 3.11.0 5*_openblas +- blas 2.305 openblas +license: BSD-3-Clause +license_family: BSD +size: 18369 +timestamp: 1765818610617 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda +build_number: 5 +sha256: 3fad5c9de161dccb4e42c8b1ae8eccb33f4ed56bccbcced9cbb0956ae7869e61 +md5: 0b2f1143ae2d0aa4c991959d0daaf256 +depends: +- libblas 3.11.0 5_haddc8a3_openblas +constrains: +- liblapack 3.11.0 5*_openblas +- liblapacke 3.11.0 5*_openblas +- blas 2.305 openblas +license: BSD-3-Clause +license_family: BSD +size: 18371 +timestamp: 1765818618899 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 +md5: a9138815598fe6b91a1d6782ca657b0c +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 71117 +timestamp: 1761979776756 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 +md5: 57f3b3da02a50a1be2a6fe847515417d +depends: +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76564 +timestamp: 1771259530958 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 +md5: 2f364feefb6a7c00423e80dcb12db62a +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 55952 +timestamp: 1769456078358 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a +md5: a229e22d4d8814a07702b0919d8e6701 +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8125 +timestamp: 1774301094057 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c +md5: b99ed99e42dafb27889483b3098cace7 +depends: +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 422941 +timestamp: 1774301093473 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +sha256: 43df385bedc1cab11993c4369e1f3b04b4ca5d0ea16cba6a0e7f18dbc129fcc9 +md5: 552567ea2b61e3a3035759b2fdb3f9a6 +depends: +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 622900 +timestamp: 1771378128706 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +sha256: 83bb0415f59634dccfa8335d4163d1f6db00a27b36666736f9842b650b92cf2f +md5: 4feebd0fbf61075a1a9c2e9b3936c257 +depends: +- libgcc 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27568 +timestamp: 1771378136019 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda +sha256: 7dcd7dff2505d56fd5272a6e712ec912f50a46bf07dc6873a7e853694304e6e4 +md5: 41f261f5e4e2e8cbd236c2f1f15dae1b +depends: +- libgfortran5 15.2.0 h1b7bec0_18 +constrains: +- libgfortran-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27587 +timestamp: 1771378169244 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda +sha256: 85347670dfb4a8d4c13cd7cae54138dcf2b1606b6bede42eef5507bf5f9660c6 +md5: 574d88ce3348331e962cfa5ed451b247 +depends: +- libgcc >=15.2.0 +constrains: +- libgfortran 15.2.0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1486341 +timestamp: 1771378148102 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +sha256: fc716f11a6a8525e27a5d332ef6a689210b0d2a4dd1133edc0f530659aa9faa6 +md5: 4faa39bf919939602e594253bd673958 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 588060 +timestamp: 1771378040807 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +sha256: 84064c7c53a64291a585d7215fe95ec42df74203a5bf7615d33d49a3b0f08bb6 +md5: 5109d7f837a3dfdf5c60f60e311b041f +depends: +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 691818 +timestamp: 1762094728337 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda +build_number: 5 +sha256: 692222d186d3ffbc99eaf04b5b20181fd26aee1edec1106435a0a755c57cce86 +md5: 88d1e4133d1182522b403e9ba7435f04 +depends: +- libblas 3.11.0 5_haddc8a3_openblas +constrains: +- liblapacke 3.11.0 5*_openblas +- blas 2.305 openblas +- libcblas 3.11.0 5*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18392 +timestamp: 1765818627104 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +sha256: 843c46e20519651a3e357a8928352b16c5b94f4cd3d5481acc48be2e93e8f6a3 +md5: 96944e3c92386a12755b94619bae0b35 +depends: +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 125916 +timestamp: 1768754941722 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda +sha256: 57c0dd12d506e84541c4e877898bd2a59cca141df493d34036f18b2751e0a453 +md5: 7b9813e885482e3ccb1fa212b86d7fd0 +depends: +- libgcc >=14 +license: BSD-2-Clause +license_family: BSD +size: 114056 +timestamp: 1769482343003 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda +sha256: 794a7270ea049ec931537874cd8d2de0ef4b3cef71c055cfd8b4be6d2f4228b0 +md5: 11d7d57b7bdd01da745bbf2b67020b2e +depends: +- libgcc >=14 +- libgfortran +- libgfortran5 >=14.3.0 +constrains: +- openblas >=0.3.30,<0.3.31.0a0 +license: BSD-3-Clause +license_family: BSD +size: 4959359 +timestamp: 1763114173544 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +sha256: c7378c6b79de4d571d00ad1caf0a4c19d43c9c94077a761abb6ead44d891f907 +md5: be4088903b94ea297975689b3c3aeb27 +depends: +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 340156 +timestamp: 1770691477245 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda +sha256: 1ddaf91b44fae83856276f4cb7ce544ffe41d4b55c1e346b504c6b45f19098d6 +md5: 77891484f18eca74b8ad83694da9815e +depends: +- icu >=78.2,<79.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: blessing +size: 952296 +timestamp: 1772818881550 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +sha256: 31fdb9ffafad106a213192d8319b9f810e05abca9c5436b60e507afb35a6bc40 +md5: f56573d05e3b735cb03efeb64a15f388 +depends: +- libgcc 15.2.0 h8acb6b2_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5541411 +timestamp: 1771378162499 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 +md5: 8c6fd84f9c87ac00636007c6131e457d +depends: +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 488407 +timestamp: 1762022048105 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 +md5: cf2861212053d05f27ec49c3784ff8bb +depends: +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 43453 +timestamp: 1766271546875 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 +md5: 24e92d0942c799db387f5c9d7b81f1af +depends: +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 359496 +timestamp: 1752160685488 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b +md5: cd14ee5cca2464a425b1dbfc24d90db2 +depends: +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 397493 +timestamp: 1727280745441 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f +md5: 502006882cf5461adced436e410046d1 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 69833 +timestamp: 1774072605429 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +sha256: 20e0892592a3e7c683e3d66df704a9425d731486a97c34fc56af4da1106b2b6b +md5: ba0a9221ce1063f31692c07370d062f3 +depends: +- importlib-metadata >=4.4 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 85893 +timestamp: 1770694658918 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e +md5: 5b5203189eb668f042ac2b0826244964 +depends: +- mdurl >=0.1,<1 +- python >=3.10 +license: MIT +license_family: MIT +size: 64736 +timestamp: 1754951288511 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda +sha256: 383c188496d13a55658c06e61e7d4cdff2c9f9d5a0648769fca8250bece7e0ef +md5: e5de3c36dd548b35ff2a8aa49208dcb3 +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- jinja2 >=3.0.0 +license: BSD-3-Clause +license_family: BSD +size: 27913 +timestamp: 1772446407659 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2 +sha256: 8fd4c79d6eda3d4cba73783114305a53a154ada4d1e334d4e02cb3521429599b +md5: 7b08314a6867a9d5648a1c3265e9eb8e +license: Apache-2.0 +license_family: Apache +size: 22257008 +timestamp: 1662784555011 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 +md5: 592132998493b3ff25fd7479396e8351 +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 14465 +timestamp: 1733255681319 +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda +sha256: f005760b13093362fc9c997d603dd487de32ab2e821a3cbce52a42bcb8136517 +md5: 698a8a27c2b9d8a542c70cb47099a75e +depends: +- click +- coloredlogs +- humanize +- importlib-metadata +- jinja2 >=3.0.0 +- jsonschema +- markdown +- natsort +- numpy +- packaging +- pillow >=10.2.0 +- plotly >=5.18 +- polars-lts-cpu +- pyaml-env +- pydantic >=2.7.1 +- python >=3.8,!=3.14.1 +- python-dotenv +- python-kaleido 0.2.1 +- pyyaml >=4 +- requests +- rich >=10 +- rich-click +- spectra >=0.0.10 +- tiktoken +- tqdm +- typeguard +license: GPL-3.0-or-later +license_family: GPL3 +size: 4198799 +timestamp: 1765300743879 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +sha256: 541fd4390a0687228b8578247f1536a821d9261389a65585af9d1a6f2a14e1e0 +md5: 30bec5e8f4c3969e2b1bd407c5e52afb +depends: +- python >=3.10 +- python +license: MIT +size: 280459 +timestamp: 1774380620329 +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 +md5: e941e85e273121222580723010bd4fa2 +depends: +- python >=3.9 +- python +license: MIT +license_family: MIT +size: 39262 +timestamp: 1770905275632 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468 +md5: 182afabe009dc78d8b73100255ee6868 +depends: +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 926034 +timestamp: 1738196018799 +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 +md5: a2c1eeadae7a309daed9d62c96012a2b +depends: +- python >=3.11 +- python +constrains: +- numpy >=1.25 +- scipy >=1.11.2 +- matplotlib-base >=3.8 +- pandas >=2.0 +license: BSD-3-Clause +license_family: BSD +size: 1587439 +timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda +sha256: 78a06e89285fef242e272998b292c1e621e3ee3dd4fba62ec014e503c7ec118f +md5: 6dd4f07147774bf720075a210f8026b9 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: MPL-2.0 +license_family: MOZILLA +size: 235140 +timestamp: 1762350120355 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda +sha256: 48942696889367ffd448f8dccfc080fb7e130b9938a4a3b6b20ef8e6af856463 +md5: 4540f9570d12db2150f42ba036154552 +depends: +- libgcc >=14 +- libsqlite >=3.51.0,<4.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- nspr >=4.38,<5.0a0 +license: MPL-2.0 +license_family: MOZILLA +size: 2061869 +timestamp: 1763490303490 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py314haac167e_0.conda +sha256: a6d42fd88afc57c3b0a57b21a12eff7492dfc419bb61ee3f74e9ba6261dabc88 +md5: 25d896c331481145720a21e5145fad65 +depends: +- python +- libgcc >=14 +- python 3.14.* *_cp314 +- libstdcxx >=14 +- libcblas >=3.9.0,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- python_abi 3.14.* *_cp314 +- libblas >=3.9.0,<4.0a0 +constrains: +- numpy-base <0a0 +license: BSD-3-Clause +license_family: BSD +size: 8008045 +timestamp: 1773839355275 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda +sha256: bd1bc8bdde5e6c5cbac42d462b939694e40b59be6d0698f668515908640c77b8 +md5: cea962410e327262346d48d01f05936c +depends: +- libgcc >=14 +- libpng >=1.6.50,<1.7.0a0 +- libstdcxx >=14 +- libtiff >=4.7.1,<4.8.0a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-2-Clause +license_family: BSD +size: 392636 +timestamp: 1758489353577 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +sha256: 7f8048c0e75b2620254218d72b4ae7f14136f1981c5eb555ef61645a9344505f +md5: 25f5885f11e8b1f075bccf4a2da91c60 +depends: +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3692030 +timestamp: 1769557678657 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda +sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 +md5: b76541e68fea4d511b1ac46a28dcd2c6 +depends: +- python >=3.8 +- python +license: Apache-2.0 +license_family: APACHE +size: 72010 +timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.1.1-py314hac3e5ec_0.conda +sha256: 1ca2d1616baad9bccb7ebc425ef2dcd6cebe742fbe91edf226fb606ad371ca0f +md5: d3c959c7efe560b2d7da459d69121fe9 +depends: +- python +- python 3.14.* *_cp314 +- libgcc >=14 +- zlib-ng >=2.3.3,<2.4.0a0 +- libwebp-base >=1.6.0,<2.0a0 +- tk >=8.6.13,<8.7.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libtiff >=4.7.1,<4.8.0a0 +- lcms2 >=2.18,<3.0a0 +- python_abi 3.14.* *_cp314 +- openjpeg >=2.5.4,<3.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libxcb >=1.17.0,<2.0a0 +license: HPND +size: 1051828 +timestamp: 1770794010335 +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 +md5: 3e9427ee186846052e81fadde8ebe96a +depends: +- narwhals >=1.15.1 +- packaging +- python >=3.10 +constrains: +- ipywidgets >=7.6 +license: MIT +license_family: MIT +size: 5251872 +timestamp: 1772628857717 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda +sha256: d332c2d5002fc440ae37ed9679ffc21b552f18d20232390005d1dd3bce0888d3 +md5: d5a4e013a30dd8dfde9ab39f45aaf9c1 +depends: +- polars-runtime-32 ==1.39.3 +- python >=3.10 +- python +constrains: +- numpy >=1.16.0 +- pyarrow >=7.0.0 +- fastexcel >=0.9 +- openpyxl >=3.0.0 +- xlsx2csv >=0.8.0 +- connectorx >=0.3.2 +- deltalake >=1.0.0 +- pyiceberg >=0.7.1 +- altair >=5.4.0 +- great_tables >=0.8.0 +- polars-runtime-32 ==1.39.3 +- polars-runtime-64 ==1.39.3 +- polars-runtime-compat ==1.39.3 +license: MIT +license_family: MIT +size: 533495 +timestamp: 1774207987966 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda +sha256: e466fb31f67ba9bde18deafeb34263ca5eb25807f39ead0e9d753a8e82c4c4f4 +md5: ef0340e75068ac8ff96462749b5c98e7 +depends: +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 +license: MIT +license_family: MIT +size: 3902 +timestamp: 1760206808444 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.39.3-py310hff09b76_1.conda +noarch: python +sha256: c070be507c5a90df397a47ae0299660be437d5546d68f1bc0fa4402c9f07d59e +md5: 3c1a7c6b4ba8b9fb773ace9723f8a5db +depends: +- python +- libgcc >=14 +- libstdcxx >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 34785466 +timestamp: 1774207998285 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.39.3-py310hf00a4a2_1.conda +noarch: python +sha256: 683315f1a49e47ce72bf9462419733b40b588b2b3106552d95fd4cd994e174de +md5: dd3464e2132dc3a783e76e5078870c76 +depends: +- python +- libgcc >=14 +- libstdcxx >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 34652491 +timestamp: 1774207996879 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 +md5: ab7288cc39545556d1bc5e71ab2df9a9 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 636733 +timestamp: 1769712412683 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba +md5: bb5a90c93e3bac3d5690acf76b4a6386 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 8342 +timestamp: 1726803319942 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +sha256: 58994e0d2ea8584cb399546e6f6896d771995e6121d1a7b6a2c9948388358932 +md5: e17be1016bcc3516827b836cd3e4d9dc +depends: +- python >=3.9 +- pyyaml >=5.0,<=7.0 +license: MIT +license_family: MIT +size: 14645 +timestamp: 1736766960536 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda +sha256: 868569d9505b7fe246c880c11e2c44924d7613a8cdcc1f6ef85d5375e892f13d +md5: c3946ed24acdb28db1b5d63321dbca7d +depends: +- typing-inspection >=0.4.2 +- typing_extensions >=4.14.1 +- python >=3.10 +- typing-extensions >=4.6.1 +- annotated-types >=0.6.0 +- pydantic-core ==2.41.5 +- python +license: MIT +license_family: MIT +size: 340482 +timestamp: 1764434463101 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.41.5-py314h451b6cc_1.conda +sha256: f8acb2d03ebe80fed0032b9a989fc9acfb6735e3cd3f8c704b72728cb31868f6 +md5: 28f5027a1e04d67aa13fac1c5ba79693 +depends: +- python +- typing-extensions >=4.6.0,!=4.7.0 +- libgcc >=14 +- python 3.14.* *_cp314 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 1828339 +timestamp: 1762989038561 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a +md5: 6b6ece66ebcae2d5f326c77ef2c5a066 +depends: +- python >=3.9 +license: BSD-2-Clause +license_family: BSD +size: 889287 +timestamp: 1750615908735 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 +md5: 461219d1a5bd61342293efa2c0c90eac +depends: +- __unix +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 21085 +timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda +build_number: 101 +sha256: 87e9dff5646aba87cecfbc08789634c855871a7325169299d749040b0923a356 +md5: 205011b36899ff0edf41b3db0eda5a44 +depends: +- bzip2 >=1.0.8,<2.0a0 +- ld_impl_linux-aarch64 >=2.36.1 +- libexpat >=2.7.3,<3.0a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- liblzma >=5.8.2,<6.0a0 +- libmpdec >=4.0.0,<5.0a0 +- libsqlite >=3.51.2,<4.0a0 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +- openssl >=3.5.5,<4.0a0 +- python_abi 3.14.* *_cp314 +- readline >=8.3,<9.0a0 +- tk >=8.6.13,<8.7.0a0 +- tzdata +- zstd >=1.5.7,<1.6.0a0 +license: Python-2.0 +size: 37305578 +timestamp: 1770674395875 +python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 +md5: 130584ad9f3a513cdd71b1fdc1244e9c +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 27848 +timestamp: 1772388605021 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +sha256: 233aebd94c704ac112afefbb29cf4170b7bc606e22958906f2672081bc50638a +md5: 235765e4ea0d0301c75965985163b5a1 +depends: +- cpython 3.14.3.* +- python_abi * *_cp314 +license: Python-2.0 +size: 50062 +timestamp: 1770674497152 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 +md5: 310259a5b03ff02289d7705f39e2b1d2 +depends: +- kaleido-core 0.2.1.* +- python >=3.5 +license: MIT +license_family: MIT +size: 18320 +timestamp: 1615204747600 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +build_number: 8 +sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 +md5: 0539938c55b6b1a59b560e843ad864a4 +constrains: +- python 3.14.* *_cp314 +license: BSD-3-Clause +license_family: BSD +size: 6989 +timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda +sha256: 496b5e65dfdd0aaaaa5de0dcaaf3bceea00fcb4398acf152f89e567c82ec1046 +md5: 9ae2c92975118058bd720e9ba2bb7c58 +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +- yaml >=0.2.5,<0.3.0a0 +license: MIT +license_family: MIT +size: 195678 +timestamp: 1770223441816 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda +sha256: fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216 +md5: 3d49cad61f829f4f0e0611547a9cda12 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-3.0-only +license_family: GPL +size: 357597 +timestamp: 1765815673644 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 +md5: 870293df500ca7e18bedefa5838a22ab +depends: +- attrs >=22.2.0 +- python >=3.10 +- rpds-py >=0.7.0 +- typing_extensions >=4.4.0 +- python +license: MIT +license_family: MIT +size: 51788 +timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.2.28-py314h51f160d_0.conda +sha256: 2080ecea825e1ef91a2422cc0bc63e85db9e38908ed17657fb8f41de7a6eee71 +md5: 818aa2c9f6b3c808da5e7be22a9a424c +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +license: Apache-2.0 AND CNRI-Python +license_family: PSF +size: 408097 +timestamp: 1772255205521 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda +sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5 +md5: c65df89a0b2e321045a9e01d1337b182 +depends: +- python >=3.10 +- certifi >=2017.4.17 +- charset-normalizer >=2,<4 +- idna >=2.5,<4 +- urllib3 >=1.21.1,<3 +- python +constrains: +- chardet >=3.0.2,<6 +license: Apache-2.0 +license_family: APACHE +size: 63602 +timestamp: 1766926974520 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +sha256: b06ce84d6a10c266811a7d3adbfa1c11f13393b91cc6f8a5b468277d90be9590 +md5: 7a6289c50631d620652f5045a63eb573 +depends: +- markdown-it-py >=2.2.0 +- pygments >=2.13.0,<3.0.0 +- python >=3.10 +- typing_extensions >=4.0.0,<5.0.0 +- python +license: MIT +license_family: MIT +size: 208472 +timestamp: 1771572730357 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 +md5: 0c20a8ebcddb24a45da89d5e917e6cb9 +depends: +- python >=3.10 +- rich >=12 +- click >=8 +- typing-extensions >=4 +- __unix +- python +license: MIT +license_family: MIT +size: 64356 +timestamp: 1769850479089 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda +sha256: a587240f16eac7c6a80f9585cef679cd1cb9a287b8dfcdd36dcef1f7e7db15dc +md5: e7f6ed9e60043bb5cbcc527764897f0d +depends: +- python +- libgcc >=14 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 376332 +timestamp: 1764543345455 +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +sha256: 7c65782d2511738e62c70462e89d65da4fa54d5a7e47c46667bcd27a59f81876 +md5: 472239e4eb7b5a84bb96b3ed7e3a596a +depends: +- colormath >=3.0.0 +- python >=3.9 +license: MIT +license_family: MIT +size: 22284 +timestamp: 1735770589188 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.52.0-hf1c7be2_0.conda +sha256: 4f8523f5341f0d9e1547085206c6c1f71f9fc7c277443ca363a8cf98add8fc01 +md5: d9634079df93a65ee045b3c75f35cae1 +depends: +- icu >=78.2,<79.0a0 +- libgcc >=14 +- libsqlite 3.52.0 h10b116e_0 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +- readline >=8.3,<9.0a0 +license: blessing +size: 209416 +timestamp: 1772818891689 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda +sha256: c1da41c79262b27efa168407cfecc47b20270e5fc071a8307f95a2c85fb94170 +md5: 55bf7b559202236157b14323b40f19e6 +depends: +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- regex >=2022.1.18 +- requests >=2.26.0 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 914402 +timestamp: 1764030357702 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda +sha256: e25c314b52764219f842b41aea2c98a059f06437392268f09b03561e4f6e5309 +md5: 7fc6affb9b01e567d2ef1d05b84aa6ed +depends: +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +constrains: +- xorg-libx11 >=1.8.12,<2.0a0 +license: TCL +license_family: BSD +size: 3368666 +timestamp: 1769464148928 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 +md5: e5ce43272193b38c2e9037446c1d9206 +depends: +- python >=3.10 +- __unix +- python +license: MPL-2.0 and MIT +size: 94132 +timestamp: 1770153424136 +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +sha256: 39d8ae33c43cdb8f771373e149b0b4fae5a08960ac58dcca95b2f1642bb17448 +md5: 260af1b0a94f719de76b4e14094e9a3b +depends: +- importlib-metadata >=3.6 +- python >=3.10 +- typing-extensions >=4.10.0 +- typing_extensions >=4.14.0 +constrains: +- pytest >=7 +license: MIT +license_family: MIT +size: 36838 +timestamp: 1771532971545 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c +md5: edd329d7d3a4ab45dcf905899a7a6115 +depends: +- typing_extensions ==4.15.0 pyhcf101f3_0 +license: PSF-2.0 +license_family: PSF +size: 91383 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +sha256: 70db27de58a97aeb7ba7448366c9853f91b21137492e0b4430251a1870aa8ff4 +md5: a0a4a3035667fc34f29bfbd5c190baa6 +depends: +- python >=3.10 +- typing_extensions >=4.12.0 +license: MIT +license_family: MIT +size: 18923 +timestamp: 1764158430324 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 +md5: 0caa1af407ecff61170c9437a808404d +depends: +- python >=3.10 +- python +license: PSF-2.0 +license_family: PSF +size: 51692 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c +md5: ad659d0a2b3e47e38d829aa8cad2d610 +license: LicenseRef-Public-Domain +size: 119135 +timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a +md5: 9272daa869e03efe68833e3dc7a02130 +depends: +- backports.zstd >=1.0.0 +- brotli-python >=1.2.0 +- h2 >=4,<5 +- pysocks >=1.5.6,<2.0,!=1.5.7 +- python >=3.10 +license: MIT +license_family: MIT +size: 103172 +timestamp: 1767817860341 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 +md5: 1c246e1105000c3660558459e2fd6d43 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 16317 +timestamp: 1762977521691 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1 +md5: bff06dcde4a707339d66d45d96ceb2e2 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 21039 +timestamp: 1762979038025 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda +sha256: 66265e943f32ce02396ad214e27cb35f5b0490b3bd4f064446390f9d67fa5d88 +md5: 032d8030e4a24fe1f72c74423a46fb88 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 88088 +timestamp: 1753484092643 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae +md5: 30cd29cb87d819caead4d55184c1d115 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 24194 +timestamp: 1764460141901 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda +sha256: 638a3a41a4fbfed52d3c60c8ef5a3693b3f12a5b1a3f58fa29f5698d0a0702e2 +md5: f731af71c723065d91b4c01bb822641b +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Zlib +license_family: Other +size: 121046 +timestamp: 1770167944449 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 +md5: c3655f82dcea2aa179b291e7099c1fcc +depends: +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 614429 +timestamp: 1764777145593 diff --git a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt new file mode 100644 index 0000000..f787dbe --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt @@ -0,0 +1,125 @@ + +# This file may be used to create an environment using: +# $ conda create --name --file +# platform: linux-aarch64 +@EXPLICIT +https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda#4faa39bf919939602e594253bd673958 +https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda#468fd3bb9e1f671d36c2cbc677e56f1d +https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda#552567ea2b61e3a3035759b2fdb3f9a6 +https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda#840d8fc0d7b3209be93080bc20e07f2d +https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda#502006882cf5461adced436e410046d1 +https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda#c3655f82dcea2aa179b291e7099c1fcc +https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda#a21644fc4a83da26452a718dc9468d5f +https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.5-hfae3067_0.conda#05d1e0b30acd816a192c03dc6e164f4d +https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda#2f364feefb6a7c00423e80dcb12db62a +https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda#76298a9e6d71ee6e832a8d0d7373b261 +https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda#7b9813e885482e3ccb1fa212b86d7fd0 +https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.0-h022381a_0.conda#86db4036fd08bf34e991bf48a8af405d +https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42-h1022ec0_0.conda#a0b5de740d01c390bdbb46d7503c9fab +https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda#182afabe009dc78d8b73100255ee6868 +https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda#e18ad67cf881dcadee8b8d9e2f8e5f73 +https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda#3b129669089e4d6a5c6871dbb4669b99 +https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda#0539938c55b6b1a59b560e843ad864a4 +https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda#3d49cad61f829f4f0e0611547a9cda12 +https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda#7fc6affb9b01e567d2ef1d05b84aa6ed +https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda#ad659d0a2b3e47e38d829aa8cad2d610 +https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.4-hfd9ac0a_100_cp314.conda#3cfbe780f0f51cc8cba41db9f8a28bfe +https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda#f111d4cfaf1fe9496f386bc98ae94452 +https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda#e4e60721757979d01d3964122f674959 +https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda#aaa2a381ccc56eac91d63b6c1240312f +https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda#0caa1af407ecff61170c9437a808404d +https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda#edd329d7d3a4ab45dcf905899a7a6115 +https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda#2934f256a8acfe48f6ebb4fce6cde29c +https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda#c6b0543676ecb1fb2d7643941fe375f2 +https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda#a2ac7763a9ac75055b68f325d3255265 +https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda#f56573d05e3b735cb03efeb64a15f388 +https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda#a1b5c571a0923a205d663d8678df4792 +https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda#929471569c93acefb30282a22060dcd5 +https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda#a9167b9571f3baa9d448faa2139d1089 +https://conda.anaconda.org/conda-forge/noarch/click-8.3.2-pyhc90fa1f_0.conda#4d18bc3af7cfcea97bd817164672a08c +https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda#7fe569c10905402ed47024fc481bb371 +https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda#b866ff7007b934d564961066c8195983 +https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda#a2c1eeadae7a309daed9d62c96012a2b +https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda#574d88ce3348331e962cfa5ed451b247 +https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda#41f261f5e4e2e8cbd236c2f1f15dae1b +https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.32-pthreads_h9d3fd7e_0.conda#5d2ce5cf40443d055ec6d33840192265 +https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-6_haddc8a3_openblas.conda#652bb20bb4618cacd11e17ae070f47ce +https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-6_hd72aa62_openblas.conda#939e300b110db241a96a1bed438c315b +https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-6_h88aeb00_openblas.conda#e23a27b52fb320687239e2c5ae4d7540 +https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py314haac167e_0.conda#25d896c331481145720a21e5145fad65 +https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda#071cf7b0ce333c81718b054066c15102 +https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.7.5-hfae3067_0.conda#d2bb0c889d94f2fdc5856392c3002976 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2#0c96522c6bdaed4b1566d11387caaf45 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2#34893075a5c9e55cdafac56607368fc6 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2#4d59c254e01d9cde7957100457e2d5fb +https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda#49023d73832ef61042f6a237cb2687e7 +https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda#f51503ac45a4888bce71af9027a2ecc9 +https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda#b99ed99e42dafb27889483b3098cace7 +https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda#a229e22d4d8814a07702b0919d8e6701 +https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda#0fed1ff55f4938a65907f3ecf62609db +https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda#a7970cd949a077b7cb9696379d338681 +https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda#0a802cb9888dd14eeefc611f05c40b6e +https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda#8e6923fc12f1fe8f8c4e5c9f343256ac +https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda#164fc43f0b53b6e3a7bc7dce5e4f1dc9 +https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda#daddf757c3ecd6067b9af1df1f25d89e +https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda#fb7130c190f9b4ec91219840a05ba3ac +https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda#e1c36c6121a7c9c76f2f148f1e83b983 +https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda#080594bf4493e6bae2607e65390c520a +https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda#e5de3c36dd548b35ff2a8aa49208dcb3 +https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda#04558c96691bed63104678757beb4f8d +https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda#e7f6ed9e60043bb5cbcc527764897f0d +https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda#870293df500ca7e18bedefa5838a22ab +https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda#439cd0f567d697b20a8f45cb70a1005a +https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda#ada41c863af263cc4c5fcbaff7c3e4dc +https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda#4feebd0fbf61075a1a9c2e9b3936c257 +https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2#7b08314a6867a9d5648a1c3265e9eb8e +https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda#6dd4f07147774bf720075a210f8026b9 +https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda#4540f9570d12db2150f42ba036154552 +https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.0-he8854b5_0.conda#ad8164bdeece883b825c50639c0c4725 +https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2#4f0d284f5d11e04277b552eb1c172c7f +https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda#a85ba48648f6868016f2741fd9170250 +https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda#d13423b06447113a90b5b1366d4da171 +https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda#a9138815598fe6b91a1d6782ca657b0c +https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda#24e92d0942c799db387f5c9d7b81f1af +https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda#8c6fd84f9c87ac00636007c6131e457d +https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda#bb960f01525b5e001608afef9d47b79c +https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda#bb5a90c93e3bac3d5690acf76b4a6386 +https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda#1c246e1105000c3660558459e2fd6d43 +https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda#bff06dcde4a707339d66d45d96ceb2e2 +https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda#cd14ee5cca2464a425b1dbfc24d90db2 +https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda#ba0a9221ce1063f31692c07370d062f3 +https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda#592132998493b3ff25fd7479396e8351 +https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda#5b5203189eb668f042ac2b0826244964 +https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda#e941e85e273121222580723010bd4fa2 +https://conda.anaconda.org/conda-forge/noarch/packaging-26.1-pyhc364b38_0.conda#b8ae38639d323d808da535fb71e31be8 +https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda#cea962410e327262346d48d01f05936c +https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda#f731af71c723065d91b4c01bb822641b +https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.2.0-py314hac3e5ec_0.conda#87d58d103b47c4a8567b3d7666647684 +https://conda.anaconda.org/conda-forge/noarch/narwhals-2.20.0-pyhcf101f3_0.conda#6cac1a50359219d786453c6fef819f98 +https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda#3e9427ee186846052e81fadde8ebe96a +https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.40.0-py310hff09b76_0.conda#d5628a33ce7652511e38fc98643dc910 +https://conda.anaconda.org/conda-forge/noarch/polars-1.40.0-pyh58ad624_0.conda#fd16be490f5403adfbf27dd4901bbe34 +https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.40.0-py310hf00a4a2_0.conda#a82af0fcbb72db253dc89a7a45279372 +https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda#ef0340e75068ac8ff96462749b5c98e7 +https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda#032d8030e4a24fe1f72c74423a46fb88 +https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda#9ae2c92975118058bd720e9ba2bb7c58 +https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda#e17be1016bcc3516827b836cd3e4d9dc +https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.46.3-py314h451b6cc_0.conda#1a2cb55be9a153ad6203bff6b787c240 +https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda#a0a4a3035667fc34f29bfbd5c190baa6 +https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.3-pyhcf101f3_0.conda#f690e6f204efd2e5c06b57518a383d98 +https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda#130584ad9f3a513cdd71b1fdc1244e9c +https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2#310259a5b03ff02289d7705f39e2b1d2 +https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda#461219d1a5bd61342293efa2c0c90eac +https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda#9272daa869e03efe68833e3dc7a02130 +https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda#10afbb4dbf06ff959ad25a92ccee6e59 +https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda#16c18772b340887160c79a6acc022db0 +https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda#0242025a3c804966bf71aa04eee82f66 +https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda#0c20a8ebcddb24a45da89d5e917e6cb9 +https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda#472239e4eb7b5a84bb96b3ed7e3a596a +https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.4.4-py314h51f160d_0.conda#88a3dbd279e6b1faf0cddb8397866864 +https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda#55bf7b559202236157b14323b40f19e6 +https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda#e5ce43272193b38c2e9037446c1d9206 +https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda#260af1b0a94f719de76b4e14094e9a3b +https://conda.anaconda.org/bioconda/noarch/multiqc-1.34-pyhdfd78af_0.conda#a7111ab9a6a6146b40cbce16655ac873 +https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh145f28c_0.conda#09a970fbf75e8ed1aa633827ded6aa4f +https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda#ab7288cc39545556d1bc5e71ab2df9a9 diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index 812fc4c..37e7612 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.29 + - bioconda::multiqc=1.34 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 0ac3c36..e80e8cd 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,24 +1,21 @@ process MULTIQC { + tag "${meta.id}" label 'process_single' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.29--pyhdfd78af_0' : - 'biocontainers/multiqc:1.29--pyhdfd78af_0' }" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data' + : 'community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6'}" input: - path multiqc_files, stageAs: "?/*" - path(multiqc_config) - path(extra_multiqc_config) - path(multiqc_logo) - path(replace_names) - path(sample_names) + tuple val(meta), path(multiqc_files, stageAs: "?/*"), path(multiqc_config, stageAs: "?/*"), path(multiqc_logo), path(replace_names), path(sample_names) output: - path "*multiqc_report.html", emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - path "versions.yml" , emit: versions + tuple val(meta), path("*.html"), emit: report + tuple val(meta), path("*_data"), emit: data + tuple val(meta), path("*_plots"), emit: plots, optional: true + // MultiQC should not push its versions to the `versions` topic. Its input depends on the versions topic to be resolved thus outputting to the topic will let the pipeline hang forever + tuple val("${task.process}"), val('multiqc'), eval('multiqc --version | sed "s/.* //g"'), emit: versions when: task.ext.when == null || task.ext.when @@ -26,38 +23,28 @@ process MULTIQC { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' - def config = multiqc_config ? "--config $multiqc_config" : '' - def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + def config = multiqc_config ? multiqc_config instanceof List ? "--config ${multiqc_config.join(' --config ')}" : "--config ${multiqc_config}" : "" def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' def replace = replace_names ? "--replace-names ${replace_names}" : '' def samples = sample_names ? "--sample-names ${sample_names}" : '' """ multiqc \\ --force \\ - $args \\ - $config \\ - $prefix \\ - $extra_config \\ - $logo \\ - $replace \\ - $samples \\ + ${args} \\ + ${config} \\ + ${prefix} \\ + ${logo} \\ + ${replace} \\ + ${samples} \\ . - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ stub: """ mkdir multiqc_data + touch multiqc_data/.stub mkdir multiqc_plots + touch multiqc_plots/.stub touch multiqc_report.html - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ } diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index ce30eb7..2facc62 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -1,6 +1,6 @@ name: multiqc -description: Aggregate results from bioinformatics analyses across many samples into - a single report +description: Aggregate results from bioinformatics analyses across many samples + into a single report keywords: - QC - bioinformatics tools @@ -12,74 +12,91 @@ tools: It's a general use tool, perfect for summarising the output from numerous bioinformatics tools. homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ - licence: ["GPL-3.0-or-later"] + licence: + - "GPL-3.0-or-later" identifier: biotools:multiqc input: - - multiqc_files: - type: file - description: | - List of reports / files recognised by MultiQC, for example the html and zip output of FastQC - ontologies: [] - - multiqc_config: - type: file - description: Optional config yml for MultiQC - pattern: "*.{yml,yaml}" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML - - extra_multiqc_config: - type: file - description: Second optional config yml for MultiQC. Will override common sections - in multiqc_config. - pattern: "*.{yml,yaml}" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML - - multiqc_logo: - type: file - description: Optional logo file for MultiQC - pattern: "*.{png}" - ontologies: [] - - replace_names: - type: file - description: | - Optional two-column sample renaming file. First column a set of - patterns, second column a set of corresponding replacements. Passed via - MultiQC's `--replace-names` option. - pattern: "*.{tsv}" - ontologies: - - edam: http://edamontology.org/format_3475 # TSV - - sample_names: - type: file - description: | - Optional TSV file with headers, passed to the MultiQC --sample_names - argument. - pattern: "*.{tsv}" - ontologies: - - edam: http://edamontology.org/format_3475 # TSV -output: - report: - - "*multiqc_report.html": + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - multiqc_files: type: file - description: MultiQC report file - pattern: "multiqc_report.html" + description: | + List of reports / files recognised by MultiQC, for example the html and zip output of FastQC ontologies: [] - data: - - "*_data": - type: directory - description: MultiQC data dir - pattern: "multiqc_data" - plots: - - "*_plots": + - multiqc_config: + type: file + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + ontologies: + - edam: http://edamontology.org/format_3750 + - multiqc_logo: type: file - description: Plots created by MultiQC - pattern: "*_data" + description: Optional logo file for MultiQC + pattern: "*.{png}" ontologies: [] - versions: - - versions.yml: + - replace_names: + type: file + description: | + Optional two-column sample renaming file. First column a set of + patterns, second column a set of corresponding replacements. Passed via + MultiQC's `--replace-names` option. + pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 + - sample_names: type: file - description: File containing software versions - pattern: "versions.yml" + description: | + Optional TSV file with headers, passed to the MultiQC --sample_names + argument. + pattern: "*.{tsv}" ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - edam: http://edamontology.org/format_3475 +output: + report: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*.html": + type: file + description: MultiQC report file + pattern: ".html" + ontologies: [] + data: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*_data": + type: directory + description: MultiQC data dir + pattern: "multiqc_data" + plots: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*_plots": + type: file + description: Plots created by MultiQC + pattern: "*_plots" + ontologies: [] + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - multiqc: + type: string + description: The tool name + - multiqc --version | sed "s/.* //g": + type: eval + description: The expression to obtain the version of the tool authors: - "@abhi18av" - "@bunop" @@ -90,3 +107,27 @@ maintainers: - "@bunop" - "@drpatelh" - "@jfy133" +containers: + conda: + linux/amd64: + lock_file: modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt + linux/arm64: + lock_file: modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt + docker: + linux/amd64: + name: community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6 + build_id: bd-db7c73dae76bc9e6_1 + scan_id: sc-66fc7138dbf1cf48_1 + linux/arm64: + name: community.wave.seqera.io/library/multiqc:1.34--d167b8012595a136 + build_id: bd-d167b8012595a136_1 + scan_id: sc-ac701dfa631a2af9_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/multiqc:1.34--4fc8657c816047c0 + build_id: bd-4fc8657c816047c0_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data + linux/arm64: + name: oras://community.wave.seqera.io/library/multiqc:1.34--7fbd82d945c06726 + build_id: bd-7fbd82d945c06726_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/9a/9a1fec9662a152683e6fcae440d0ce20920b3b89dc62d1e3a52e73f92eba0969/data diff --git a/modules/nf-core/multiqc/tests/custom_prefix.config b/modules/nf-core/multiqc/tests/custom_prefix.config new file mode 100644 index 0000000..b30b135 --- /dev/null +++ b/modules/nf-core/multiqc/tests/custom_prefix.config @@ -0,0 +1,5 @@ +process { + withName: 'MULTIQC' { + ext.prefix = "custom_prefix" + } +} diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test index 33316a7..4cbdb95 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -15,25 +15,84 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = [] - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) """ } } then { - assertAll( - { assert process.success }, - { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, - { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_single") } - ) + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } + } + + test("sarscov2 single-end [fastqc] - custom prefix") { + config "./custom_prefix.config" + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) + """ + } } + then { + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } } test("sarscov2 single-end [fastqc] [config]") { @@ -41,23 +100,85 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true), + [], + [], + [] + ]) """ } } then { - assertAll( - { assert process.success }, - { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, - { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_config") } - ) + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } + } + + test("sarscov2 single-end [fastqc] [multiple configs]") { + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [ + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true), + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true) + ], + [], + [], + [] + ]) + """ + } + } + + then { + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() } } @@ -68,25 +189,23 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = [] - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) """ } } then { + assert process.success assertAll( - { assert process.success }, - { assert snapshot(process.out.report.collect { file(it).getName() } + - process.out.data.collect { file(it).getName() } + - process.out.plots.collect { file(it).getName() } + - process.out.versions ).match("multiqc_stub") } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } - } } diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index 88e9057..7c2f370 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -1,41 +1,422 @@ { - "multiqc_versions_single": { + "sarscov2 single-end [fastqc] [multiple configs]": { "content": [ - [ - "versions.yml:md5,c1fe644a37468f6dae548d98bc72c2c1" - ] + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } ], + "timestamp": "2026-03-17T16:15:42.577775492", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.2" - }, - "timestamp": "2025-05-22T11:50:41.182332996" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, - "multiqc_stub": { + "sarscov2 single-end [fastqc]": { "content": [ - [ - "multiqc_report.html", - "multiqc_data", - "multiqc_plots", - "versions.yml:md5,c1fe644a37468f6dae548d98bc72c2c1" - ] + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_software_versions.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } ], + "timestamp": "2026-03-17T16:21:17.072841555", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.2" - }, - "timestamp": "2025-05-22T11:51:22.448739369" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, - "multiqc_versions_config": { + "sarscov2 single-end [fastqc] - stub": { "content": [ - [ - "versions.yml:md5,c1fe644a37468f6dae548d98bc72c2c1" - ] + { + "data": [ + [ + { + "id": "FASTQC" + }, + [ + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "plots": [ + [ + { + "id": "FASTQC" + }, + [ + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "report": [ + [ + { + "id": "FASTQC" + }, + "multiqc_report.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } ], + "timestamp": "2026-02-26T15:14:39.789193051", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.2" - }, - "timestamp": "2025-05-22T11:51:06.198928424" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "sarscov2 single-end [fastqc] [config]": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:30.372239611", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "sarscov2 single-end [fastqc] - custom prefix": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_software_versions.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "custom_prefix.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:18.189023981", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } } } \ No newline at end of file diff --git a/modules/nf-core/multiqc/tests/nextflow.config b/modules/nf-core/multiqc/tests/nextflow.config index c537a6a..374dfef 100644 --- a/modules/nf-core/multiqc/tests/nextflow.config +++ b/modules/nf-core/multiqc/tests/nextflow.config @@ -1,5 +1,6 @@ process { withName: 'MULTIQC' { ext.prefix = null + ext.args = '-p' } } diff --git a/modules/nf-core/multiqc/tests/tags.yml b/modules/nf-core/multiqc/tests/tags.yml deleted file mode 100644 index bea6c0d..0000000 --- a/modules/nf-core/multiqc/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -multiqc: - - modules/nf-core/multiqc/** diff --git a/nextflow.config b/nextflow.config index 63b7fc3..1b1ea2e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -32,13 +32,14 @@ params { email_on_fail = null plaintext_email = false monochrome_logs = false - hook_url = null help = false help_full = false show_hidden = false version = false pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' - trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss')// Config options + trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') + + // Config options config_profile_name = null config_profile_description = null @@ -51,6 +52,10 @@ params { validate_params = true } +// Backwards compatibility for publishDir syntax +outputDir = params.outdir +workflow.output.mode = params.publish_dir_mode + // Load base.config by default for all pipelines includeConfig 'conf/base.config' @@ -91,7 +96,18 @@ profiles { apptainer.enabled = false docker.runOptions = '-u $(id -u):$(id -g)' } - arm { + arm64 { + process.arch = 'arm64' + // TODO https://github.com/nf-core/modules/issues/6694 + // For now if you're using arm64 you have to use wave for the sake of the maintainers + // wave profile + apptainer.ociAutoPull = true + singularity.ociAutoPull = true + wave.enabled = true + wave.freeze = true + wave.strategy = 'conda,container' + } + emulate_amd64 { docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' } singularity { @@ -148,18 +164,6 @@ profiles { wave.freeze = true wave.strategy = 'conda,container' } - gitpod { - executor.name = 'local' - executor.cpus = 4 - executor.memory = 8.GB - process { - resourceLimits = [ - memory: 8.GB, - cpus : 4, - time : 1.h - ] - } - } gpu { docker.runOptions = '-u $(id -u):$(id -g) --gpus all' apptainer.runOptions = '--nv' @@ -250,47 +254,19 @@ manifest { description = """A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.""" mainScript = 'main.nf' defaultBranch = 'main' - nextflowVersion = '!>=24.10.5' + nextflowVersion = '!>=25.10.4' version = '1.0dev' doi = '' } // Nextflow plugins plugins { - id 'nf-schema@2.4.2' // Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-schema@2.5.1' // Validation of pipeline parameters and creation of an input channel from a sample sheet } validation { defaultIgnoreParams = ["genomes"] monochromeLogs = params.monochrome_logs - help { - enabled = true - command = "nextflow run nf-core/datasync -profile --input samplesheet.csv --outdir " - fullParameter = "help_full" - showHiddenParameter = "show_hidden" - beforeText = """ --\033[2m----------------------------------------------------\033[0m- - \033[0;32m,--.\033[0;30m/\033[0;32m,-.\033[0m -\033[0;34m ___ __ __ __ ___ \033[0;32m/,-._.--~\'\033[0m -\033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m -\033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m - \033[0;32m`._,._,\'\033[0m -\033[0;35m nf-core/datasync ${manifest.version}\033[0m --\033[2m----------------------------------------------------\033[0m- -""" - afterText = """${manifest.doi ? "\n* The pipeline\n" : ""}${manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${manifest.doi ? "\n" : ""} -* The nf-core framework - https://doi.org/10.1038/s41587-020-0439-x - -* Software dependencies - https://github.com/nf-core/datasync/blob/main/CITATIONS.md -""" - } - summary { - beforeText = validation.help.beforeText - afterText = validation.help.afterText - } } - // Load modules.config for DSL2 module specific options includeConfig 'conf/modules.config' diff --git a/nextflow_schema.json b/nextflow_schema.json index a0b283e..10b92c1 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -74,7 +74,6 @@ }, "igenomes_base": { "type": "string", - "format": "directory-path", "description": "The base path to the igenomes reference files", "fa_icon": "fas fa-ban", "hidden": true, @@ -180,13 +179,6 @@ "fa_icon": "fas fa-palette", "hidden": true }, - "hook_url": { - "type": "string", - "description": "Incoming hook URL for messaging service", - "fa_icon": "fas fa-people-group", - "help_text": "Incoming hook URL for messaging service. Currently, MS Teams and Slack are supported.", - "hidden": true - }, "multiqc_config": { "type": "string", "format": "file-path", @@ -224,6 +216,18 @@ "fa_icon": "far calendar", "description": "Suffix to add to the trace report filename. Default is the date and time in the format yyyy-MM-dd_HH-mm-ss.", "hidden": true + }, + "help": { + "type": ["boolean", "string"], + "description": "Display the help message." + }, + "help_full": { + "type": "boolean", + "description": "Display the full detailed help message." + }, + "show_hidden": { + "type": "boolean", + "description": "Display hidden parameters in the help message (only works when --help or --help_full are provided)." } } } diff --git a/nf-test.config b/nf-test.config index 3a1fff5..f7aaeb4 100644 --- a/nf-test.config +++ b/nf-test.config @@ -1,21 +1,35 @@ config { // location for all nf-test tests - testsDir "." + testsDir = "." // nf-test directory including temporary files for each test - workDir System.getenv("NFT_WORKDIR") ?: ".nf-test" + workDir = System.getenv("NFT_WORKDIR") ?: ".nf-test" // location of an optional nextflow.config file specific for executing tests - configFile "tests/nextflow.config" + configFile = "tests/nextflow.config" // ignore tests coming from the nf-core/modules repo - ignore 'modules/nf-core/**/tests/*', 'subworkflows/nf-core/**/tests/*' + ignore = [ + 'modules/nf-core/**/tests/*', + 'subworkflows/nf-core/**/tests/*', + ] // run all test with defined profile(s) from the main nextflow.config - profile "test" + 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' + triggers = [ + '.github/actions/nf-test/action.yml', + '.github/workflows/nf-test.yml', + 'assets/schema_input.json', + 'bin/*', + 'conf/test.config', + 'nextflow.config', + 'nextflow_schema.json', + 'nf-test.config', + 'tests/.nftignore', + 'tests/nextflow.config', + ] // load the necessary plugins plugins { diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index e13b950..04f2590 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -22,8 +22,8 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "InProgress", - "datePublished": "2026-06-12T18:40:42+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "datePublished": "2026-06-12T18:45:30+00:00", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.0.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/4.0.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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#2ee1040b-6496-408f-a4f1-da9334861141" + "@id": "#2c001518-824a-4160-8d1f-e11499988ea4" } ], "name": "nf-core/datasync" @@ -126,13 +126,13 @@ "SoftwareSourceCode", "ComputationalWorkflow" ], - "creator": [ + "contributor": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], "dateCreated": "", - "dateModified": "2026-06-12T18:40:42Z", + "dateModified": "2026-06-12T18:45:30Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": [ "nf-core", @@ -141,11 +141,6 @@ "license": [ "MIT" ], - "maintainer": [ - { - "@id": "https://orcid.org/0000-0002-6503-2180" - } - ], "name": [ "nf-core/datasync" ], @@ -173,14 +168,14 @@ "url": { "@id": "https://www.nextflow.io/" }, - "version": "!>=24.10.5" + "version": "!>=25.10.4" }, { - "@id": "#2ee1040b-6496-408f-a4f1-da9334861141", + "@id": "#2c001518-824a-4160-8d1f-e11499988ea4", "@type": "TestSuite", "instance": [ { - "@id": "#b2bb2540-4adb-49b2-a272-31ef8ae53dba" + "@id": "#fc0f8ad7-7ff6-496e-a10a-f0951ddbd5a6" } ], "mainEntity": { @@ -189,7 +184,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#b2bb2540-4adb-49b2-a272-31ef8ae53dba", + "@id": "#fc0f8ad7-7ff6-496e-a10a-f0951ddbd5a6", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/nf-test.yml", diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index e65bbf3..e9e92f3 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -11,9 +11,9 @@ include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' include { paramsSummaryMap } from 'plugin/nf-schema' include { samplesheetToList } from 'plugin/nf-schema' +include { paramsHelp } from 'plugin/nf-schema' include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' -include { imNotification } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' @@ -32,10 +32,13 @@ workflow PIPELINE_INITIALISATION { nextflow_cli_args // array: List of positional nextflow CLI args outdir // string: The output directory where the results will be saved input // string: Path to input samplesheet + help // boolean: Display help message and exit + help_full // boolean: Show the full help message + show_hidden // boolean: Show hidden parameters in the help message main: - ch_versions = Channel.empty() + ch_versions = channel.empty() // // Print version and exit if required and dump pipeline parameters to JSON file @@ -50,10 +53,42 @@ workflow PIPELINE_INITIALISATION { // // Validate parameters and generate parameter summary to stdout // + + def before_text = "" + def after_text = "" + before_text = """ +-\033[2m----------------------------------------------------\033[0m- + \033[0;32m,--.\033[0;30m/\033[0;32m,-.\033[0m +\033[0;34m ___ __ __ __ ___ \033[0;32m/,-._.--~\'\033[0m +\033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m +\033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m + \033[0;32m`._,._,\'\033[0m +\033[0;35m nf-core/datasync ${workflow.manifest.version}\033[0m +-\033[2m----------------------------------------------------\033[0m- +""" + after_text = """${workflow.manifest.doi ? "\n* The pipeline\n" : ""}${workflow.manifest.doi.tokenize(",").collect { doi -> " https://doi.org/${doi.trim().replace('https://doi.org/','')}"}.join("\n")}${workflow.manifest.doi ? "\n" : ""} +* The nf-core framework + https://doi.org/10.1038/s41587-020-0439-x + +* Software dependencies + https://github.com/nf-core/datasync/blob/main/CITATIONS.md +""" + if (monochrome_logs) { + before_text = before_text.replaceAll(/\033\[[0-9;]*m/, '') + } + + command = "nextflow run ${workflow.manifest.name} -profile --input samplesheet.csv --outdir " + UTILS_NFSCHEMA_PLUGIN ( workflow, validate_params, - null + null, + help, + help_full, + show_hidden, + before_text, + after_text, + command ) // @@ -72,8 +107,8 @@ workflow PIPELINE_INITIALISATION { // Create channel from input file provided through params.input // - Channel - .fromList(samplesheetToList(params.input, "${projectDir}/assets/schema_input.json")) + channel + .fromList(samplesheetToList(input, "${projectDir}/assets/schema_input.json")) .map { meta, fastq_1, fastq_2 -> if (!fastq_2) { @@ -111,7 +146,6 @@ workflow PIPELINE_COMPLETION { plaintext_email // boolean: Send plain-text email instead of HTML outdir // path: Path to output directory where results will be published monochrome_logs // boolean: Disable ANSI colour codes in log output - hook_url // string: hook URL for notifications multiqc_report // string: Path to MultiQC report main: @@ -135,13 +169,11 @@ workflow PIPELINE_COMPLETION { } completionSummary(monochrome_logs) - if (hook_url) { - imNotification(summary_params, hook_url) - } + } workflow.onError { - log.error "Pipeline failed. Please refer to troubleshooting docs: https://nf-co.re/docs/usage/troubleshooting" + log.error "Pipeline failed. Please refer to troubleshooting docs for common issues: https://nf-co.re/docs/running/troubleshooting" } } diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml b/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml deleted file mode 100644 index f847611..0000000 --- a/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -subworkflows/utils_nextflow_pipeline: - - subworkflows/nf-core/utils_nextflow_pipeline/** diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index bfd2587..afca543 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -17,7 +17,7 @@ workflow UTILS_NFCORE_PIPELINE { checkProfileProvided(nextflow_cli_args) emit: - valid_config + valid_config = valid_config } /* @@ -98,7 +98,7 @@ def workflowVersionToYAML() { // Get channel of software versions used in pipeline in YAML format // def softwareVersionsToYAML(ch_versions) { - return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(Channel.of(workflowVersionToYAML())) + return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(channel.of(workflowVersionToYAML())) } // @@ -353,67 +353,3 @@ def completionSummary(monochrome_logs=true) { log.info("-${colors.purple}[${workflow.manifest.name}]${colors.red} Pipeline completed with errors${colors.reset}-") } } - -// -// Construct and send a notification to a web server as JSON e.g. Microsoft Teams and Slack -// -def imNotification(summary_params, hook_url) { - def summary = [:] - summary_params - .keySet() - .sort() - .each { group -> - summary << summary_params[group] - } - - def misc_fields = [:] - misc_fields['start'] = workflow.start - misc_fields['complete'] = workflow.complete - misc_fields['scriptfile'] = workflow.scriptFile - misc_fields['scriptid'] = workflow.scriptId - if (workflow.repository) { - misc_fields['repository'] = workflow.repository - } - if (workflow.commitId) { - misc_fields['commitid'] = workflow.commitId - } - if (workflow.revision) { - misc_fields['revision'] = workflow.revision - } - misc_fields['nxf_version'] = workflow.nextflow.version - misc_fields['nxf_build'] = workflow.nextflow.build - misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp - - def msg_fields = [:] - msg_fields['version'] = getWorkflowVersion() - msg_fields['runName'] = workflow.runName - msg_fields['success'] = workflow.success - msg_fields['dateComplete'] = workflow.complete - msg_fields['duration'] = workflow.duration - msg_fields['exitStatus'] = workflow.exitStatus - msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') - msg_fields['errorReport'] = (workflow.errorReport ?: 'None') - msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "") - msg_fields['projectDir'] = workflow.projectDir - msg_fields['summary'] = summary << misc_fields - - // Render the JSON template - def engine = new groovy.text.GStringTemplateEngine() - // Different JSON depending on the service provider - // Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format - def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json" - def hf = new File("${workflow.projectDir}/assets/${json_path}") - def json_template = engine.createTemplate(hf).make(msg_fields) - def json_message = json_template.toString() - - // POST - def post = new URL(hook_url).openConnection() - post.setRequestMethod("POST") - post.setDoOutput(true) - post.setRequestProperty("Content-Type", "application/json") - post.getOutputStream().write(json_message.getBytes("UTF-8")) - def postRC = post.getResponseCode() - if (!postRC.equals(200)) { - log.warn(post.getErrorStream().getText()) - } -} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test new file mode 100644 index 0000000..8940d32 --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test @@ -0,0 +1,29 @@ +nextflow_workflow { + + name "Test Workflow UTILS_NFCORE_PIPELINE" + script "../main.nf" + config "subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config" + workflow "UTILS_NFCORE_PIPELINE" + tag "subworkflows" + tag "subworkflows_nfcore" + tag "utils_nfcore_pipeline" + tag "subworkflows/utils_nfcore_pipeline" + + test("Should run without failures") { + + when { + workflow { + """ + input[0] = [] + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out).match() } + ) + } + } +} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap new file mode 100644 index 0000000..859d103 --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap @@ -0,0 +1,19 @@ +{ + "Should run without failures": { + "content": [ + { + "0": [ + true + ], + "valid_config": [ + true + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:25.726491" + } +} \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml b/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml deleted file mode 100644 index ac8523c..0000000 --- a/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -subworkflows/utils_nfcore_pipeline: - - subworkflows/nf-core/utils_nfcore_pipeline/** diff --git a/subworkflows/nf-core/utils_nfschema_plugin/main.nf b/subworkflows/nf-core/utils_nfschema_plugin/main.nf index 4994303..1df8b76 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/main.nf +++ b/subworkflows/nf-core/utils_nfschema_plugin/main.nf @@ -4,6 +4,7 @@ include { paramsSummaryLog } from 'plugin/nf-schema' include { validateParameters } from 'plugin/nf-schema' +include { paramsHelp } from 'plugin/nf-schema' workflow UTILS_NFSCHEMA_PLUGIN { @@ -15,32 +16,58 @@ workflow UTILS_NFSCHEMA_PLUGIN { // when this input is empty it will automatically use the configured schema or // "${projectDir}/nextflow_schema.json" as default. This input should not be empty // for meta pipelines + help // boolean: show help message + help_full // boolean: show full help message + show_hidden // boolean: show hidden parameters in help message + before_text // string: text to show before the help message and parameters summary + after_text // string: text to show after the help message and parameters summary + command // string: an example command of the pipeline main: + if(help || help_full) { + help_options = [ + beforeText: before_text, + afterText: after_text, + command: command, + showHidden: show_hidden, + fullHelp: help_full, + ] + if(parameters_schema) { + help_options << [parametersSchema: parameters_schema] + } + log.info paramsHelp( + help_options, + (params.help instanceof String && params.help != "true") ? params.help : "", + ) + exit 0 + } + // // Print parameter summary to stdout. This will display the parameters // that differ from the default given in the JSON schema // + + summary_options = [:] if(parameters_schema) { - log.info paramsSummaryLog(input_workflow, parameters_schema:parameters_schema) - } else { - log.info paramsSummaryLog(input_workflow) + summary_options << [parametersSchema: parameters_schema] } + log.info before_text + log.info paramsSummaryLog(summary_options, input_workflow) + log.info after_text // // Validate the parameters using nextflow_schema.json or the schema // given via the validation.parametersSchema configuration option // if(validate_params) { + validateOptions = [:] if(parameters_schema) { - validateParameters(parameters_schema:parameters_schema) - } else { - validateParameters() + validateOptions << [parametersSchema: parameters_schema] } + validateParameters(validateOptions) } emit: dummy_emit = true } - diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test index 8fb3016..c977917 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test @@ -25,6 +25,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -51,6 +57,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -77,6 +89,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -103,6 +121,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -114,4 +138,36 @@ nextflow_workflow { ) } } + + test("Should create a help message") { + + when { + + params { + test_data = '' + outdir = null + } + + workflow { + """ + validate_params = true + input[0] = workflow + input[1] = validate_params + input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + input[3] = true + input[4] = false + input[5] = false + input[6] = "Before" + input[7] = "After" + input[8] = "nextflow run test/test" + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config index 09ef842..f6537cc 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config @@ -1,8 +1,8 @@ plugins { - id "nf-schema@2.4.2" + id "nf-schema@2.6.1" } validation { parametersSchema = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" monochromeLogs = true -} \ No newline at end of file +} diff --git a/tests/.nftignore b/tests/.nftignore index 158c83c..e128a12 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -1,10 +1,11 @@ .DS_Store multiqc/multiqc_data/fastqc_top_overrepresented_sequences_table.txt -multiqc/multiqc_data/BETA-multiqc.parquet +multiqc/multiqc_data/multiqc.parquet multiqc/multiqc_data/multiqc.log multiqc/multiqc_data/multiqc_data.json multiqc/multiqc_data/multiqc_sources.txt multiqc/multiqc_data/multiqc_software_versions.txt +multiqc/multiqc_data/llms-full.txt multiqc/multiqc_plots/{svg,pdf,png}/*.{svg,pdf,png} multiqc/multiqc_report.html fastqc/*_fastqc.{html,zip} diff --git a/tests/default.nf.test b/tests/default.nf.test index 43cf2c9..7576e53 100644 --- a/tests/default.nf.test +++ b/tests/default.nf.test @@ -13,21 +13,19 @@ nextflow_pipeline { } 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 = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + // stable_path: All files + folders in ${params.outdir}/ with a stable path (including file name) + def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_content: All files in ${params.outdir}/ with stable content + def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + assert workflow.success 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 test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), // All stable path name, with a relative path - stable_name, + stable_path, // All files with stable contents - stable_path + stable_content ).match() } ) } diff --git a/tests/nextflow.config b/tests/nextflow.config index 247cc7f..da48321 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -8,7 +8,7 @@ // Or any resources requirements params { modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' - pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync' + pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/' } aws.client.anonymous = true // fixes S3 access issues on self-hosted runners diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 6905242..7d12501 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -20,74 +20,78 @@ workflow DATASYNC { take: ch_samplesheet // channel: samplesheet read in from --input + multiqc_config + multiqc_logo + multiqc_methods_description + outdir + main: - ch_versions = Channel.empty() - ch_multiqc_files = Channel.empty() + def ch_versions = channel.empty() + def ch_multiqc_files = channel.empty() // // MODULE: Run FastQC // - FASTQC ( - ch_samplesheet - ) - ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}) - ch_versions = ch_versions.mix(FASTQC.out.versions.first()) + FASTQC(ch_samplesheet) + ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.map{ _meta, file -> file }) // // Collate and save software versions // - softwareVersionsToYAML(ch_versions) + def topic_versions = channel.topic("versions") + .distinct() + .branch { entry -> + versions_file: entry instanceof Path + versions_tuple: true + } + + def topic_versions_string = topic_versions.versions_tuple + .map { process, tool, version -> + [ process[process.lastIndexOf(':')+1..-1], " ${tool}: ${version}" ] + } + .groupTuple(by:0) + .map { process, tool_versions -> + tool_versions.unique().sort() + "${process}:\n${tool_versions.join('\n')}" + } + + def ch_collated_versions = softwareVersionsToYAML(ch_versions.mix(topic_versions.versions_file)) + .mix(topic_versions_string) .collectFile( - storeDir: "${params.outdir}/pipeline_info", + storeDir: "${outdir}/pipeline_info", name: 'nf_core_' + 'datasync_software_' + 'mqc_' + 'versions.yml', sort: true, newLine: true - ).set { ch_collated_versions } - + ) // // MODULE: MultiQC // - ch_multiqc_config = Channel.fromPath( - "$projectDir/assets/multiqc_config.yml", checkIfExists: true) - ch_multiqc_custom_config = params.multiqc_config ? - Channel.fromPath(params.multiqc_config, checkIfExists: true) : - Channel.empty() - ch_multiqc_logo = params.multiqc_logo ? - Channel.fromPath(params.multiqc_logo, checkIfExists: true) : - Channel.empty() - - summary_params = paramsSummaryMap( - workflow, parameters_schema: "nextflow_schema.json") - ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) - ch_multiqc_files = ch_multiqc_files.mix( - ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) - ch_multiqc_custom_methods_description = params.multiqc_methods_description ? - file(params.multiqc_methods_description, checkIfExists: true) : - file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) - ch_methods_description = Channel.value( - methodsDescriptionText(ch_multiqc_custom_methods_description)) - ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) - ch_multiqc_files = ch_multiqc_files.mix( - ch_methods_description.collectFile( - name: 'methods_description_mqc.yaml', - sort: true - ) - ) - - MULTIQC ( - ch_multiqc_files.collect(), - ch_multiqc_config.toList(), - ch_multiqc_custom_config.toList(), - ch_multiqc_logo.toList(), - [], - [] + def ch_summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") + def ch_workflow_summary = channel.value(paramsSummaryMultiqc(ch_summary_params)) + ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) + def ch_multiqc_custom_methods_description = multiqc_methods_description + ? file(multiqc_methods_description, checkIfExists: true) + : file("${projectDir}/assets/methods_description_template.yml", checkIfExists: true) + def ch_methods_description = channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) + ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml', sort: true)) + MULTIQC( + ch_multiqc_files.flatten().collect().map { files -> + [ + [id: 'datasync'], + files, + multiqc_config + ? file(multiqc_config, checkIfExists: true) + : file("${projectDir}/assets/multiqc_config.yml", checkIfExists: true), + multiqc_logo ? file(multiqc_logo, checkIfExists: true) : [], + [], + [], + ] + } ) - - emit:multiqc_report = MULTIQC.out.report.toList() // channel: /path/to/multiqc_report.html + emit:multiqc_report = MULTIQC.out.report.map { _meta, report -> [report] }.toList() // channel: /path/to/multiqc_report.html versions = ch_versions // channel: [ path(versions.yml) ] - } /* From 2fb4ab631613879d9007241a5ca17d22dd9458cb Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 18:48:42 +0000 Subject: [PATCH 025/334] merge template changes --- workflows/datasync.nf | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index db1b052..ee20e12 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -61,29 +61,6 @@ workflow DATASYNC { // // MODULE: MultiQC // -<<<<<<< HEAD - ch_multiqc_config = channel.fromPath( - "$projectDir/assets/multiqc_config.yml", checkIfExists: true) - ch_multiqc_custom_config = params.multiqc_config ? - channel.fromPath(params.multiqc_config, checkIfExists: true) : - channel.empty() - ch_multiqc_logo = params.multiqc_logo ? - channel.fromPath(params.multiqc_logo, checkIfExists: true) : - channel.empty() - - summary_params = paramsSummaryMap( - workflow, parameters_schema: "nextflow_schema.json") - ch_workflow_summary = channel.value(paramsSummaryMultiqc(summary_params)) - ch_multiqc_files = ch_multiqc_files.mix( - ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) - ch_multiqc_custom_methods_description = params.multiqc_methods_description ? - file(params.multiqc_methods_description, checkIfExists: true) : - file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) - ch_methods_description = channel.value( - methodsDescriptionText(ch_multiqc_custom_methods_description)) - -======= ->>>>>>> TEMPLATE ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) def ch_summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") def ch_workflow_summary = channel.value(paramsSummaryMultiqc(ch_summary_params)) From e6c418cf75c0bbc65c319cf69984115b07b6f3cd Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 18:50:33 +0000 Subject: [PATCH 026/334] nf-core pipelines lint --- ro-crate-metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 04f2590..af84031 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "InProgress", "datePublished": "2026-06-12T18:45:30+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.0.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/4.0.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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.0.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/4.0.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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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[WIP] WORK IN PROGRESS AND NOT YET STABLE - DO NOT USE FOR PRODUCTIVE SETTINGS YET\n\n**nf-core/datasync** is a system operation pipeline that provides several workflows for handling system operation / automation tasks that are commonly helpful for various tasks in large data processing / analysis facilities. This includes:\n\n- Data Synchronization & Checksum generation\n - Configurable: Can provide YAML file which files to include or exclude from sync\n - Checksum backend: Can configure which backend to use for checksum generation (e.g. sha256sum, md5, ...)\n - Configurable whether to include (sub-) folders in the sync or not (search for checkpoint files, e.g. has to have DEMUX_DONE that signals a demultiplexing run was finished & successfully copied)\n- Data Integrity validation\n - Provided with a directory to check, can validate that file(s) found are matching checksums from Synchronization subworkflow\n- Data Archival & Deletion\n - Can check source and target location for existence of file(s) and decide based on user configurable rules whether files can be considered archived\n - Timestamp older than X days\n - Checksums match Integrity validation report\n - Create empty files to make it obvious that archival was performed\n - Optionally: Delete files or create list of files to be deleted for manual deletion process\n\nThe pipeline can be configured by users to execute any of the aforementioned subworkflows and then produces a report using MultiQC custom content that also serves as a report of _what_ was done by the pipeline for documentation purposes.\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n --sync\n --sync_backend 'sha256'\n --sync_done true #Creates SYNC_DONE file when done in each folder\n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" From 8afa8889c0adfa73007e5e500eb2fe16e16b68c1 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 18:51:22 +0000 Subject: [PATCH 027/334] fix linting --- conf/containers_conda_lock_files_amd64.config | 1 - conf/containers_conda_lock_files_arm64.config | 1 - conf/containers_docker_amd64.config | 1 - conf/containers_docker_arm64.config | 1 - conf/containers_singularity_https_amd64.config | 1 - conf/containers_singularity_https_arm64.config | 1 - conf/containers_singularity_oras_amd64.config | 1 - conf/containers_singularity_oras_arm64.config | 1 - 8 files changed, 8 deletions(-) diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index d3ee1b4..f487ba4 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1,2 +1 @@ -process { withName: 'FASTQC' { container = 'modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt' } } process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index 2b90ac4..e9a3fed 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1,2 +1 @@ -process { withName: 'FASTQC' { container = 'modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt' } } process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt' } } diff --git a/conf/containers_docker_amd64.config b/conf/containers_docker_amd64.config index 65f1814..01b59df 100644 --- a/conf/containers_docker_amd64.config +++ b/conf/containers_docker_amd64.config @@ -1,2 +1 @@ -process { withName: 'FASTQC' { container = 'community.wave.seqera.io/library/fastqc:0.12.1--5cb1a2fa2f18c7c2' } } process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6' } } diff --git a/conf/containers_docker_arm64.config b/conf/containers_docker_arm64.config index 6c845ba..7785cb1 100644 --- a/conf/containers_docker_arm64.config +++ b/conf/containers_docker_arm64.config @@ -1,2 +1 @@ -process { withName: 'FASTQC' { container = 'community.wave.seqera.io/library/fastqc:0.12.1--e455e32f745abe68' } } process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.34--d167b8012595a136' } } diff --git a/conf/containers_singularity_https_amd64.config b/conf/containers_singularity_https_amd64.config index 838f248..754821b 100644 --- a/conf/containers_singularity_https_amd64.config +++ b/conf/containers_singularity_https_amd64.config @@ -1,2 +1 @@ -process { withName: 'FASTQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/f2/f20b021476d1d87658820f971ebecc1e8cdbde0f338eb0d9cea2b0a8fc54a54b/data' } } process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data' } } diff --git a/conf/containers_singularity_https_arm64.config b/conf/containers_singularity_https_arm64.config index 090173b..93071de 100644 --- a/conf/containers_singularity_https_arm64.config +++ b/conf/containers_singularity_https_arm64.config @@ -1,2 +1 @@ -process { withName: 'FASTQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/46/46daf2dad0169afd2ae047c3e50ed3776259f664bf07e5e06b045dc23449e994/data' } } process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/9a/9a1fec9662a152683e6fcae440d0ce20920b3b89dc62d1e3a52e73f92eba0969/data' } } diff --git a/conf/containers_singularity_oras_amd64.config b/conf/containers_singularity_oras_amd64.config index 773f369..952881d 100644 --- a/conf/containers_singularity_oras_amd64.config +++ b/conf/containers_singularity_oras_amd64.config @@ -1,2 +1 @@ -process { withName: 'FASTQC' { container = 'oras://community.wave.seqera.io/library/fastqc:0.12.1--5c4bd442468d75dd' } } process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.34--4fc8657c816047c0' } } diff --git a/conf/containers_singularity_oras_arm64.config b/conf/containers_singularity_oras_arm64.config index 798cc63..498ec50 100644 --- a/conf/containers_singularity_oras_arm64.config +++ b/conf/containers_singularity_oras_arm64.config @@ -1,2 +1 @@ -process { withName: 'FASTQC' { container = 'oras://community.wave.seqera.io/library/fastqc:0.12.1--127a87fc06499035' } } process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.34--7fbd82d945c06726' } } From 41b67a302fce9a2436a971f9415b8136eea90e85 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 18:59:02 +0000 Subject: [PATCH 028/334] fix nextflow lint issues --- subworkflows/local/utils_nfcore_datasync_pipeline/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 6246c13..e9e92f3 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -28,7 +28,7 @@ workflow PIPELINE_INITIALISATION { take: version // boolean: Display version and exit validate_params // boolean: Boolean whether to validate parameters against the schema at runtime - _monochrome_logs // boolean: Do not use coloured log outputs + monochrome_logs // boolean: Do not use coloured log outputs nextflow_cli_args // array: List of positional nextflow CLI args outdir // string: The output directory where the results will be saved input // string: Path to input samplesheet From 0f9d5862731b6c58a80441d9b1162a13652c808a Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:02:13 +0000 Subject: [PATCH 029/334] update snapshot --- tests/default.nf.test.snap | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 634e59a..466aab7 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -1,7 +1,6 @@ { "-profile test": { "content": [ - 1, { "Workflow": { "nf-core/datasync": "v1.0dev" @@ -10,7 +9,9 @@ [ "multiqc", "multiqc/multiqc_data", + "multiqc/multiqc_data/llms-full.txt", "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc.parquet", "multiqc/multiqc_data/multiqc_citations.txt", "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_software_versions.txt", @@ -25,8 +26,8 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nextflow": "26.04.3" }, - "timestamp": "2026-06-12T16:23:53.372790566" + "timestamp": "2026-06-12T19:01:37.766797147" } } \ No newline at end of file From 6c6a97f221aa5c975fed8b5c031984a44f5f437f Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:06:41 +0000 Subject: [PATCH 030/334] main to master fix linting --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 87aab4d..d43c74d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). From 1ca0c5d212a31d983c045fb2b1580e9a554b0117 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 12 Jun 2026 19:51:51 +0000 Subject: [PATCH 031/334] Install checksum modules from nf-core --- modules.json | 10 + modules/nf-core/md5sum/environment.yml | 12 + modules/nf-core/md5sum/main.nf | 55 ++++ modules/nf-core/md5sum/meta.yml | 68 ++++ modules/nf-core/md5sum/tests/main.nf.test | 180 +++++++++++ .../nf-core/md5sum/tests/main.nf.test.snap | 301 ++++++++++++++++++ modules/nf-core/md5sum/tests/nextflow.config | 2 + modules/nf-core/shasum/environment.yml | 12 + modules/nf-core/shasum/main.nf | 33 ++ modules/nf-core/shasum/meta.yml | 62 ++++ modules/nf-core/shasum/tests/main.nf.test | 58 ++++ .../nf-core/shasum/tests/main.nf.test.snap | 56 ++++ workflows/datasync.nf | 2 + 13 files changed, 851 insertions(+) create mode 100644 modules/nf-core/md5sum/environment.yml create mode 100644 modules/nf-core/md5sum/main.nf create mode 100644 modules/nf-core/md5sum/meta.yml create mode 100644 modules/nf-core/md5sum/tests/main.nf.test create mode 100644 modules/nf-core/md5sum/tests/main.nf.test.snap create mode 100644 modules/nf-core/md5sum/tests/nextflow.config create mode 100644 modules/nf-core/shasum/environment.yml create mode 100644 modules/nf-core/shasum/main.nf create mode 100644 modules/nf-core/shasum/meta.yml create mode 100644 modules/nf-core/shasum/tests/main.nf.test create mode 100644 modules/nf-core/shasum/tests/main.nf.test.snap diff --git a/modules.json b/modules.json index 578acbb..13a67eb 100644 --- a/modules.json +++ b/modules.json @@ -10,10 +10,20 @@ "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", "installed_by": ["modules"] }, + "md5sum": { + "branch": "master", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", + "installed_by": ["modules"] + }, "multiqc": { "branch": "master", "git_sha": "008f9d3e61209bf995edac3ba531f54e269e1215", "installed_by": ["modules"] + }, + "shasum": { + "branch": "master", + "git_sha": "ef2ee0358c7d03231834aeac816991aeb20debd7", + "installed_by": ["modules"] } } }, diff --git a/modules/nf-core/md5sum/environment.yml b/modules/nf-core/md5sum/environment.yml new file mode 100644 index 0000000..9b926b1 --- /dev/null +++ b/modules/nf-core/md5sum/environment.yml @@ -0,0 +1,12 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::coreutils=9.5 + - conda-forge::grep=3.11 + - conda-forge::gzip=1.13 + - conda-forge::lbzip2=2.5 + - conda-forge::sed=4.8 + - conda-forge::tar=1.34 diff --git a/modules/nf-core/md5sum/main.nf b/modules/nf-core/md5sum/main.nf new file mode 100644 index 0000000..7dafd75 --- /dev/null +++ b/modules/nf-core/md5sum/main.nf @@ -0,0 +1,55 @@ +process MD5SUM { + tag "${meta.id}" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/52/52ccce28d2ab928ab862e25aae26314d69c8e38bd41ca9431c67ef05221348aa/data' + : 'community.wave.seqera.io/library/coreutils_grep_gzip_lbzip2_pruned:838ba80435a629f8'}" + + input: + tuple val(meta), path(files) + val as_separate_files + + output: + tuple val(meta), path("*.md5"), emit: checksum + tuple val("${task.process}"), val('md5sum'), eval("md5sum --version | sed '1!d; s/.* //'"), topic: versions, emit: versions_md5sum + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + // will only use when as_separate_files = false + if (as_separate_files) { + """ + find -L * -maxdepth 0 -type f \\ + ! -name '*.md5' \\ + -exec sh -c 'md5sum ${args} "\$1" > "\$1.md5"' _ "{}" \\; + """ + } + else { + """ + find -L * -type f \\ + ! -name '*.md5' \\ + -exec md5sum ${args} "{}" + \\ + > ${prefix}.md5 + """ + } + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + if (as_separate_files) { + """ + find -L * -type f \\ + ! -name '*.md5' \\ + -exec sh -c 'touch "\$1.md5"' _ "{}" \\; + """ + } + else { + """ + touch ${prefix}.md5 + """ + } +} diff --git a/modules/nf-core/md5sum/meta.yml b/modules/nf-core/md5sum/meta.yml new file mode 100644 index 0000000..71066a8 --- /dev/null +++ b/modules/nf-core/md5sum/meta.yml @@ -0,0 +1,68 @@ +name: "md5sum" +description: Create MD5 (128-bit) checksums +keywords: + - checksum + - MD5 + - 128 bit +tools: + - "md5sum": + description: Create MD5 (128-bit) checksums for each file + homepage: "https://www.gnu.org" + documentation: "https://man7.org/linux/man-pages/man1/md5sum.1.html" + licence: + - "GPL-3.0-or-later" + identifier: "" +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - files: + type: file + description: Any number of files. One md5sum file will be generated for + each. + pattern: "*.*" + ontologies: [] + - as_separate_files: + type: boolean + description: | + If true, each file will have its own md5sum file. If false, all files will be + checksummed into a single md5sum file. +output: + checksum: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.md5": + type: file + description: File containing checksum + pattern: "*.md5" + ontologies: [] + versions_md5sum: + - - ${task.process}: + type: string + description: The name of the process + - md5sum: + type: string + description: The name of the tool + - md5sum --version | sed '1!d; s/.* //': + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - md5sum: + type: string + description: The name of the tool + - md5sum --version | sed '1!d; s/.* //': + type: eval + description: The expression to obtain the version of the tool +authors: + - "@matthdsm" +maintainers: + - "@matthdsm" diff --git a/modules/nf-core/md5sum/tests/main.nf.test b/modules/nf-core/md5sum/tests/main.nf.test new file mode 100644 index 0000000..a6f7cf8 --- /dev/null +++ b/modules/nf-core/md5sum/tests/main.nf.test @@ -0,0 +1,180 @@ +nextflow_process { + + name "Test Process MD5SUM" + script "../main.nf" + process "MD5SUM" + + tag "modules" + tag "modules_nfcore" + tag "md5sum" + + test("md5sum on hello.txt") { + + when { + process { + """ + input[0] = [ + [ id: 'hello' ], + [ file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true) ] + ] + input[1] = true + """ + } + } + + then { + assertAll { + { assert process.success } + { assert snapshot(process.out).match() } + } + } + } + + test("md5sum on hello.txt (BSD-style)") { + + config './nextflow.config' + + when { + process { + """ + input[0] = [ + [ id: 'hello' ], + [ file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true) ] + ] + input[1] = true + """ + } + } + + then { + assertAll { + { assert process.success } + { assert snapshot(process.out).match() } + } + } + } + + test("md5sum on hello.txt - stub") { + options "-stub" + when { + process { + """ + input[0] = [ + [ id: 'hello' ], + [ file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true) ] + ] + input[1] = true + """ + } + } + + then { + assertAll { + { assert process.success } + { assert snapshot(process.out).match() } + } + } + } + + test("md5sum on paired fastq, combined") { + + when { + process { + """ + input[0] = [ + [ id: 'test' ], + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = false + """ + } + } + + then { + assertAll { + { assert process.success } + { assert snapshot(process.out).match() } + } + } + } + + test("md5sum on paired fastq, combined - stub") { + options "-stub" + when { + process { + """ + input[0] = [ + [ id: 'test' ], + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = false + """ + } + } + + then { + assertAll { + { assert process.success } + { assert snapshot(process.out).match() } + } + } + } + + + test("md5sum on paired fastq, separate") { + + when { + process { + """ + input[0] = [ + [ id: 'test' ], + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = true + """ + } + } + + then { + assertAll { + { assert process.success } + { assert snapshot(process.out).match() } + } + } + } + + test("md5sum on paired fastq, separate - stub") { + options "-stub" + when { + process { + """ + input[0] = [ + [ id: 'test' ], + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = true + """ + } + } + + then { + assertAll { + { assert process.success } + { assert snapshot(process.out).match() } + } + } + } + +} diff --git a/modules/nf-core/md5sum/tests/main.nf.test.snap b/modules/nf-core/md5sum/tests/main.nf.test.snap new file mode 100644 index 0000000..bf78c29 --- /dev/null +++ b/modules/nf-core/md5sum/tests/main.nf.test.snap @@ -0,0 +1,301 @@ +{ + "md5sum on paired fastq, separate - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + [ + "test_1.fastq.gz.md5:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_2.fastq.gz.md5:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "1": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ], + "checksum": [ + [ + { + "id": "test" + }, + [ + "test_1.fastq.gz.md5:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_2.fastq.gz.md5:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "versions_md5sum": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-02-18T14:31:17.339668", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "md5sum on paired fastq, separate": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + [ + "test_1.fastq.gz.md5:md5,63a3f187d06ae5cffe77fcd39bbdd63a", + "test_2.fastq.gz.md5:md5,055dc46636836dbd1d9ede2e6ce8cd4e" + ] + ] + ], + "1": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ], + "checksum": [ + [ + { + "id": "test" + }, + [ + "test_1.fastq.gz.md5:md5,63a3f187d06ae5cffe77fcd39bbdd63a", + "test_2.fastq.gz.md5:md5,055dc46636836dbd1d9ede2e6ce8cd4e" + ] + ] + ], + "versions_md5sum": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-02-18T14:31:11.522274", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "md5sum on hello.txt - stub": { + "content": [ + { + "0": [ + [ + { + "id": "hello" + }, + "hello.txt.md5:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ], + "checksum": [ + [ + { + "id": "hello" + }, + "hello.txt.md5:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_md5sum": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-02-18T14:30:52.301881", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "md5sum on hello.txt": { + "content": [ + { + "0": [ + [ + { + "id": "hello" + }, + "hello.txt.md5:md5,5c18e1db5460fb32fed66966483165fd" + ] + ], + "1": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ], + "checksum": [ + [ + { + "id": "hello" + }, + "hello.txt.md5:md5,5c18e1db5460fb32fed66966483165fd" + ] + ], + "versions_md5sum": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-02-18T14:30:41.089186", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "md5sum on paired fastq, combined": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.md5:md5,dfb98e45cbb77a9a63ae7029aee38bd1" + ] + ], + "1": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ], + "checksum": [ + [ + { + "id": "test" + }, + "test.md5:md5,dfb98e45cbb77a9a63ae7029aee38bd1" + ] + ], + "versions_md5sum": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-02-18T14:30:58.611754", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "md5sum on paired fastq, combined - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.md5:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ], + "checksum": [ + [ + { + "id": "test" + }, + "test.md5:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_md5sum": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-02-18T14:31:06.064053", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "md5sum on hello.txt (BSD-style)": { + "content": [ + { + "0": [ + [ + { + "id": "hello" + }, + "hello.txt.md5:md5,152a03f5dc7aa8db6612f63154ecbca2" + ] + ], + "1": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ], + "checksum": [ + [ + { + "id": "hello" + }, + "hello.txt.md5:md5,152a03f5dc7aa8db6612f63154ecbca2" + ] + ], + "versions_md5sum": [ + [ + "MD5SUM", + "md5sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-02-18T14:30:46.389675", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/md5sum/tests/nextflow.config b/modules/nf-core/md5sum/tests/nextflow.config new file mode 100644 index 0000000..4acada5 --- /dev/null +++ b/modules/nf-core/md5sum/tests/nextflow.config @@ -0,0 +1,2 @@ + +process.ext.args = '--tag' diff --git a/modules/nf-core/shasum/environment.yml b/modules/nf-core/shasum/environment.yml new file mode 100644 index 0000000..9b926b1 --- /dev/null +++ b/modules/nf-core/shasum/environment.yml @@ -0,0 +1,12 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::coreutils=9.5 + - conda-forge::grep=3.11 + - conda-forge::gzip=1.13 + - conda-forge::lbzip2=2.5 + - conda-forge::sed=4.8 + - conda-forge::tar=1.34 diff --git a/modules/nf-core/shasum/main.nf b/modules/nf-core/shasum/main.nf new file mode 100644 index 0000000..2fa689d --- /dev/null +++ b/modules/nf-core/shasum/main.nf @@ -0,0 +1,33 @@ +process SHASUM { + tag "${meta.id}" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/52/52ccce28d2ab928ab862e25aae26314d69c8e38bd41ca9431c67ef05221348aa/data' + : 'community.wave.seqera.io/library/coreutils_grep_gzip_lbzip2_pruned:838ba80435a629f8'}" + + input: + tuple val(meta), path(file) + + output: + tuple val(meta), path("*.sha256"), emit: checksum + tuple val("${task.process}"), val('sha256sum'), eval("sha256sum --version 2>&1 | head -n 1 | sed 's/.* //'"), emit: versions_sha256sum, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + sha256sum \\ + ${args} \\ + ${file} \\ + > ${file}.sha256 + """ + + stub: + """ + touch ${file}.sha256 + """ +} diff --git a/modules/nf-core/shasum/meta.yml b/modules/nf-core/shasum/meta.yml new file mode 100644 index 0000000..327a4f0 --- /dev/null +++ b/modules/nf-core/shasum/meta.yml @@ -0,0 +1,62 @@ +name: "shasum" +description: Print SHA256 (256-bit) checksums. +keywords: + - checksum + - sha256 + - 256 bit +tools: + - "md5sum": + description: Create an SHA256 (256-bit) checksum. + homepage: "https://www.gnu.org" + documentation: "https://linux.die.net/man/1/shasum" + licence: + - "GPLv3+" + identifier: "" +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - file: + type: file + description: Any file + pattern: "*.*" + ontologies: [] +output: + checksum: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.sha256": + type: file + description: File containing checksum + pattern: "*.sha256" + ontologies: [] + versions_sha256sum: + - - ${task.process}: + type: string + description: Process name + - sha256sum: + type: string + description: Tool name + - "sha256sum --version 2>&1 | head -n 1 | sed 's/.* //'": + type: eval + description: Software version +topics: + versions: + - - ${task.process}: + type: string + description: Process name + - sha256sum: + type: string + description: Tool name + - "sha256sum --version 2>&1 | head -n 1 | sed 's/.* //'": + type: eval + description: Software version +authors: + - "@matthdsm" +maintainers: + - "@matthdsm" diff --git a/modules/nf-core/shasum/tests/main.nf.test b/modules/nf-core/shasum/tests/main.nf.test new file mode 100644 index 0000000..02d2ac0 --- /dev/null +++ b/modules/nf-core/shasum/tests/main.nf.test @@ -0,0 +1,58 @@ + +nextflow_process { + + name "Test Process SHASUM" + script "../main.nf" + process "SHASUM" + + tag "modules" + tag "modules_nfcore" + tag "shasum" + + test("test-shasum") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true) + ] + + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out)).match() } + ) + } + } + + test("test-shasum - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true) + ] + + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out)).match() } + ) + } + } + +} diff --git a/modules/nf-core/shasum/tests/main.nf.test.snap b/modules/nf-core/shasum/tests/main.nf.test.snap new file mode 100644 index 0000000..a86583b --- /dev/null +++ b/modules/nf-core/shasum/tests/main.nf.test.snap @@ -0,0 +1,56 @@ +{ + "test-shasum": { + "content": [ + { + "checksum": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.bam.sha256:md5,138a19e100f09fc975ea1b717da9b6dd" + ] + ], + "versions_sha256sum": [ + [ + "SHASUM", + "sha256sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-05-03T20:43:40.688253838", + "meta": { + "nf-test": "0.9.5", + "nextflow": "24.10.4" + } + }, + "test-shasum - stub": { + "content": [ + { + "checksum": [ + [ + { + "id": "test", + "single_end": false + }, + "test.paired_end.bam.sha256:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_sha256sum": [ + [ + "SHASUM", + "sha256sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-05-03T20:43:46.125782074", + "meta": { + "nf-test": "0.9.5", + "nextflow": "24.10.4" + } + } +} \ No newline at end of file diff --git a/workflows/datasync.nf b/workflows/datasync.nf index ee20e12..597e4a2 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -3,7 +3,9 @@ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +include { MD5SUM } from '../modules/nf-core/md5sum/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' +include { SHASUM } from '../modules/nf-core/shasum/main' include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' From fa023804a9ced6454ccfd3b3517fed92aedda60d Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 12 Jun 2026 21:54:40 +0200 Subject: [PATCH 032/334] Ignore nf-test files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cc2b1a7..5516a06 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ testing* *.pyc null/ .lineage/ +.nf-test* From cbf23f5adb4f6c5c2a28fe5b9338f828f082295a Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 16 Jun 2026 17:28:29 +0200 Subject: [PATCH 033/334] Implement checksum validation and update test samplesheet --- assets/samplesheet.csv | 6 ++-- assets/schema_input.json | 17 +++------- conf/test.config | 2 +- .../utils_nfcore_datasync_pipeline/main.nf | 32 ++++--------------- workflows/datasync.nf | 9 ++++++ 5 files changed, 23 insertions(+), 43 deletions(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 5f653ab..5af06dd 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,3 @@ -sample,fastq_1,fastq_2 -SAMPLE_PAIRED_END,/path/to/fastq/files/AEG588A1_S1_L002_R1_001.fastq.gz,/path/to/fastq/files/AEG588A1_S1_L002_R2_001.fastq.gz -SAMPLE_SINGLE_END,/path/to/fastq/files/AEG588A4_S4_L003_R1_001.fastq.gz, +sample,input +human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/ +test_fastq,https://github.com/nf-core/test-datasets/blob/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz diff --git a/assets/schema_input.json b/assets/schema_input.json index 248b66e..4afb584 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -13,21 +13,12 @@ "errorMessage": "Sample name must be provided and cannot contain spaces", "meta": ["id"] }, - "fastq_1": { + "input": { "type": "string", - "format": "file-path", - "exists": true, - "pattern": "^([\\S\\s]*\\/)?[^\\s\\/]+\\.f(ast)?q\\.gz$", - "errorMessage": "FastQ file for reads 1 must be provided, cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" - }, - "fastq_2": { - "type": "string", - "format": "file-path", - "exists": true, - "pattern": "^([\\S\\s]*\\/)?[^\\s\\/]+\\.f(ast)?q\\.gz$", - "errorMessage": "FastQ file for reads 2 cannot contain spaces and must have extension '.fq.gz' or '.fastq.gz'" + "pattern": "^\\S+$", + "errorMessage": "Input path must be provided and cannot contain spaces" } }, - "required": ["sample", "fastq_1"] + "required": ["sample", "input"] } } diff --git a/conf/test.config b/conf/test.config index 7b7af9e..3f62cb0 100644 --- a/conf/test.config +++ b/conf/test.config @@ -25,6 +25,6 @@ params { // Input data // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_test_illumina_amplicon.csv'// Genome references + input = "${projectDir}/assets/samplesheet.csv" genome = 'R64-1-1' } diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index e9e92f3..db1f6d4 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -110,21 +110,15 @@ workflow PIPELINE_INITIALISATION { channel .fromList(samplesheetToList(input, "${projectDir}/assets/schema_input.json")) .map { - meta, fastq_1, fastq_2 -> - if (!fastq_2) { - return [ meta.id, meta + [ single_end:true ], [ fastq_1 ] ] + meta, input_path -> + def target = file(input_path) + if (target.isDirectory()) { + def all_files = files("${input_path}/**", type: 'file') + [meta, all_files] } else { - return [ meta.id, meta + [ single_end:false ], [ fastq_1, fastq_2 ] ] + [meta, [target]] } } - .groupTuple() - .map { samplesheet -> - validateInputSamplesheet(samplesheet) - } - .map { - meta, fastqs -> - return [ meta, fastqs.flatten() ] - } .set { ch_samplesheet } emit: @@ -189,20 +183,6 @@ def validateInputParameters() { genomeExistsError() } -// -// Validate channels from input samplesheet -// -def validateInputSamplesheet(input) { - def (metas, fastqs) = input[1..2] - - // Check that multiple runs of the same sample are of the same datatype i.e. single-end / paired-end - def endedness_ok = metas.collect{ meta -> meta.single_end }.unique().size == 1 - if (!endedness_ok) { - error("Please check input samplesheet -> Multiple runs of a sample must be of the same datatype i.e. single-end or paired-end: ${metas[0].id}") - } - - return [ metas[0], fastqs ] -} // // Get attribute from genome config file e.g. fasta // diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 597e4a2..6e6c910 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -31,6 +31,15 @@ workflow DATASYNC { ch_versions = channel.empty() ch_multiqc_files = channel.empty() + MD5SUM( + ch_samplesheet, + false + ) + + SHASUM( + ch_samplesheet.transpose() + ) + // // Collate and save software versions // From 9326e613ab57f47459bdf780f95420c8b0cdf543 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 16 Jun 2026 17:31:43 +0200 Subject: [PATCH 034/334] Update test --- tests/default.nf.test.snap | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 466aab7..a717f94 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -2,11 +2,20 @@ "-profile test": { "content": [ { + "MD5SUM": { + "md5sum": 9.5 + }, + "SHASUM": { + "sha256sum": 9.5 + }, "Workflow": { "nf-core/datasync": "v1.0dev" } }, [ + "md5sum", + "md5sum/human_grch38_sequence.md5", + "md5sum/test_fastq.md5", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", @@ -18,16 +27,33 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_report.html", "pipeline_info", - "pipeline_info/nf_core_datasync_software_mqc_versions.yml" + "pipeline_info/nf_core_datasync_software_mqc_versions.yml", + "shasum", + "shasum/GenomeSize.xml.old.sha256", + "shasum/GenomeSize.xml.sha256", + "shasum/genome.dict.old.sha256", + "shasum/genome.dict.sha256", + "shasum/genome.fa.fai.sha256", + "shasum/genome.fa.sha256", + "shasum/test2_1.fastq.gz.sha256" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + "human_grch38_sequence.md5:md5,0547c2f89caeb0e8e7d67da583e09d90", + "test_fastq.md5:md5,0ff44f0431e9fe66e5df9fa93ba3e675", + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "GenomeSize.xml.old.sha256:md5,068e91cdcc084710caf61a0859ac2be9", + "GenomeSize.xml.sha256:md5,e7a175f04cab11ce0a245133d70de9fb", + "genome.dict.old.sha256:md5,77492c77f911887b269de347e157d4ca", + "genome.dict.sha256:md5,0021eaba625d4dc9fcec55eb7384426e", + "genome.fa.fai.sha256:md5,99f227079c0fd354f272c0046482ff1a", + "genome.fa.sha256:md5,9bdb272c4b51342a0f139fbc14d0a57e", + "test2_1.fastq.gz.sha256:md5,1cc66562f32a8a74d6f8a908a80d312e" ] ], + "timestamp": "2026-06-16T17:30:38.905202155", "meta": { - "nf-test": "0.9.2", - "nextflow": "26.04.3" - }, - "timestamp": "2026-06-12T19:01:37.766797147" + "nf-test": "0.9.5", + "nextflow": "26.04.1" + } } } \ No newline at end of file From 0abcdcab90dd24e01c814c4b02bcdfdee9010903 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 16 Jun 2026 18:06:22 +0200 Subject: [PATCH 035/334] Fix path to input file and update test snapshot --- assets/samplesheet.csv | 2 +- tests/default.nf.test.snap | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 5af06dd..55cd8f9 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,3 @@ sample,input human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/ -test_fastq,https://github.com/nf-core/test-datasets/blob/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz +test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index a717f94..f48ad94 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -39,7 +39,7 @@ ], [ "human_grch38_sequence.md5:md5,0547c2f89caeb0e8e7d67da583e09d90", - "test_fastq.md5:md5,0ff44f0431e9fe66e5df9fa93ba3e675", + "test_fastq.md5:md5,145df327e566f16b545fbca236f9bb62", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "GenomeSize.xml.old.sha256:md5,068e91cdcc084710caf61a0859ac2be9", "GenomeSize.xml.sha256:md5,e7a175f04cab11ce0a245133d70de9fb", @@ -47,10 +47,10 @@ "genome.dict.sha256:md5,0021eaba625d4dc9fcec55eb7384426e", "genome.fa.fai.sha256:md5,99f227079c0fd354f272c0046482ff1a", "genome.fa.sha256:md5,9bdb272c4b51342a0f139fbc14d0a57e", - "test2_1.fastq.gz.sha256:md5,1cc66562f32a8a74d6f8a908a80d312e" + "test2_1.fastq.gz.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" ] ], - "timestamp": "2026-06-16T17:30:38.905202155", + "timestamp": "2026-06-16T18:04:56.374326627", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From de0572a65b9af8a4caaa5ddef47b385073368781 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 16 Jun 2026 14:04:21 -0300 Subject: [PATCH 036/334] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60dad40..36d6f40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` +- [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). + ### `Fixed` ### `Dependencies` From 6eff885a08a3390384cef7bfb9940bccab2e9a3a Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 18 Jun 2026 02:38:18 +0000 Subject: [PATCH 037/334] create and apply test dataset --- assets/samplesheet.csv | 5 ++--- workflows/datasync.nf | 13 +++++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 55cd8f9..9ed843e 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,2 @@ -sample,input -human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/ -test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz +sample,input,checksum_md5,checksum_sha +demultiplex,s3://nf-core-awsmegatests/demultiplex/results-fbec8e442f0599f8b74876e62263af05b9a41d33/,checksum_md5.tsv,checksum_sha.tsv diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 6e6c910..663fcc0 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -31,11 +31,20 @@ workflow DATASYNC { ch_versions = channel.empty() ch_multiqc_files = channel.empty() + ch_samplesheet_without_md5 = ch_samplesheet.map { meta, files -> + def filtered_files = files.findAll { file -> + !file.name.endsWith('.md5') + } + + tuple(meta, filtered_files) + } MD5SUM( - ch_samplesheet, - false + ch_samplesheet_without_md5.transpose(), + true ) + MD5SUM.output.checksum.view() + SHASUM( ch_samplesheet.transpose() ) From 7ebf53e998a2ae8174521e47853b8d7644938a50 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 18 Jun 2026 02:48:40 +0000 Subject: [PATCH 038/334] separate minimal test profile and full test profile --- assets/samplesheet.csv | 5 +++-- assets/samplesheet_full.csv | 2 ++ conf/test_full.config | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 assets/samplesheet_full.csv diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 9ed843e..82e35fd 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,2 +1,3 @@ -sample,input,checksum_md5,checksum_sha -demultiplex,s3://nf-core-awsmegatests/demultiplex/results-fbec8e442f0599f8b74876e62263af05b9a41d33/,checksum_md5.tsv,checksum_sha.tsv +sample,input +human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/ +test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz \ No newline at end of file diff --git a/assets/samplesheet_full.csv b/assets/samplesheet_full.csv new file mode 100644 index 0000000..9ed843e --- /dev/null +++ b/assets/samplesheet_full.csv @@ -0,0 +1,2 @@ +sample,input,checksum_md5,checksum_sha +demultiplex,s3://nf-core-awsmegatests/demultiplex/results-fbec8e442f0599f8b74876e62263af05b9a41d33/,checksum_md5.tsv,checksum_sha.tsv diff --git a/conf/test_full.config b/conf/test_full.config index f11bc7e..b75f98c 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,7 +17,7 @@ params { // Input data for full size test // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = params.pipelines_testdata_base_path + 'viralrecon/samplesheet/samplesheet_full_illumina_amplicon.csv' + input = "${projectDir}/assets/samplesheet_full.csv" // Genome references genome = 'R64-1-1' From ebf569de75bd48e29411a127e58b0e8ff6edaa1b Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 18 Jun 2026 03:06:02 +0000 Subject: [PATCH 039/334] update snapshot --- tests/default.nf.test.snap | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index f48ad94..a20e40d 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -14,8 +14,13 @@ }, [ "md5sum", - "md5sum/human_grch38_sequence.md5", - "md5sum/test_fastq.md5", + "md5sum/GenomeSize.xml.md5", + "md5sum/GenomeSize.xml.old.md5", + "md5sum/genome.dict.md5", + "md5sum/genome.dict.old.md5", + "md5sum/genome.fa.fai.md5", + "md5sum/genome.fa.md5", + "md5sum/test2_1.fastq.gz.md5", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", @@ -38,8 +43,13 @@ "shasum/test2_1.fastq.gz.sha256" ], [ - "human_grch38_sequence.md5:md5,0547c2f89caeb0e8e7d67da583e09d90", - "test_fastq.md5:md5,145df327e566f16b545fbca236f9bb62", + "GenomeSize.xml.md5:md5,0c1c07f13ddcd6f479f8312b0c7d9843", + "GenomeSize.xml.old.md5:md5,8273ac6aa130edf9e628cf0cf2566855", + "genome.dict.md5:md5,cf34a65ce7a3e827c66eadb2d5522551", + "genome.dict.old.md5:md5,4dfbb85cd00197e03f43f999b39addab", + "genome.fa.fai.md5:md5,8fc26b8f3ce6b83f9860ae9a2347d046", + "genome.fa.md5:md5,cca9026fcc32a789c00d9070edac5809", + "test2_1.fastq.gz.md5:md5,145df327e566f16b545fbca236f9bb62", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "GenomeSize.xml.old.sha256:md5,068e91cdcc084710caf61a0859ac2be9", "GenomeSize.xml.sha256:md5,e7a175f04cab11ce0a245133d70de9fb", @@ -50,10 +60,10 @@ "test2_1.fastq.gz.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" ] ], - "timestamp": "2026-06-16T18:04:56.374326627", + "timestamp": "2026-06-18T03:05:43.540206333", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.4" } } } \ No newline at end of file From 4d7e3c8799db643e31d22abbd8370f2eedfdbb0f Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 18 Jun 2026 03:07:50 +0000 Subject: [PATCH 040/334] fix: run prettier --- assets/samplesheet.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 82e35fd..55cd8f9 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,3 @@ sample,input human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/ -test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz \ No newline at end of file +test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz From f9abbf75ef99e0a4f43e6a89da4159f1b5f3240b Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 18 Jun 2026 20:54:20 +0200 Subject: [PATCH 041/334] Remove fastqc --- conf/modules.config | 4 - modules.json | 5 - .../linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt | 822 ------------------ .../linux_arm64-bd-e455e32f745abe68_1.txt | 769 ---------------- modules/nf-core/fastqc/environment.yml | 7 - modules/nf-core/fastqc/main.nf | 57 -- modules/nf-core/fastqc/meta.yml | 111 --- modules/nf-core/fastqc/tests/main.nf.test | 309 ------- .../nf-core/fastqc/tests/main.nf.test.snap | 476 ---------- 9 files changed, 2560 deletions(-) delete mode 100644 modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt delete mode 100644 modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt delete mode 100644 modules/nf-core/fastqc/environment.yml delete mode 100644 modules/nf-core/fastqc/main.nf delete mode 100644 modules/nf-core/fastqc/meta.yml delete mode 100644 modules/nf-core/fastqc/tests/main.nf.test delete mode 100644 modules/nf-core/fastqc/tests/main.nf.test.snap diff --git a/conf/modules.config b/conf/modules.config index d203d2b..f0b0d55 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,10 +18,6 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] - withName: FASTQC { - ext.args = '--quiet' - } - withName: 'MULTIQC' { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ diff --git a/modules.json b/modules.json index 13a67eb..a6c41ad 100644 --- a/modules.json +++ b/modules.json @@ -5,11 +5,6 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { - "fastqc": { - "branch": "master", - "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", - "installed_by": ["modules"] - }, "md5sum": { "branch": "master", "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", diff --git a/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt deleted file mode 100644 index 7770ccd..0000000 --- a/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt +++ /dev/null @@ -1,822 +0,0 @@ - -version: 6 -environments: -default: -channels: -- url: https://conda.anaconda.org/conda-forge/ -- url: https://conda.anaconda.org/bioconda/ -- url: https://conda.anaconda.org/bioconda/ -options: -pypi-prerelease-mode: if-necessary-or-explicit -packages: -linux-64: -- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda -- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda -packages: -- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda -build_number: 20 -sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 -md5: a9f577daf3de00bca7c3c76c0ecbd1de -depends: -- __glibc >=2.17,<3.0.a0 -- libgomp >=7.5.0 -constrains: -- openmp_impl <0.0a0 -license: BSD-3-Clause -license_family: BSD -size: 28948 -timestamp: 1770939786096 -- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda -sha256: d88aa7ae766cf584e180996e92fef2aa7d8e0a0a5ab1d4d49c32390c1b5fff31 -md5: dcdc58c15961dbf17a0621312b01f5cb -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: LGPL-2.1-or-later -license_family: GPL -size: 584660 -timestamp: 1768327524772 -- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda -sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 -md5: d2ffd7602c02f2b316fd921d39876885 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: bzip2-1.0.6 -license_family: BSD -size: 260182 -timestamp: 1771350215188 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc -md5: 4492fd26db29495f0ba23f146cd5638d -depends: -- __unix -license: ISC -size: 147413 -timestamp: 1772006283803 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda -sha256: 06525fa0c4e4f56e771a3b986d0fdf0f0fc5a3270830ee47e127a5105bde1b9a -md5: bb6c4808bfa69d6f7f6b07e5846ced37 -depends: -- __glibc >=2.17,<3.0.a0 -- fontconfig >=2.15.0,<3.0a0 -- fonts-conda-ecosystem -- icu >=78.1,<79.0a0 -- libexpat >=2.7.3,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- libgcc >=14 -- libglib >=2.86.3,<3.0a0 -- libpng >=1.6.53,<1.7.0a0 -- libstdcxx >=14 -- libxcb >=1.17.0,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- pixman >=0.46.4,<1.0a0 -- xorg-libice >=1.1.2,<2.0a0 -- xorg-libsm >=1.2.6,<2.0a0 -- xorg-libx11 >=1.8.12,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -license: LGPL-2.1-only or MPL-1.1 -size: 989514 -timestamp: 1766415934926 -- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 -sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c -md5: c9f6a4b12229f7331f79c9a00dd6e240 -depends: -- font-ttf-dejavu-sans-mono -- fontconfig -- openjdk >=8.0.144 -- perl -license: GPL >=3 -size: 11664291 -timestamp: 1677946722445 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 -sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b -md5: 0c96522c6bdaed4b1566d11387caaf45 -license: BSD-3-Clause -license_family: BSD -size: 397370 -timestamp: 1566932522327 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 -sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c -md5: 34893075a5c9e55cdafac56607368fc6 -license: OFL-1.1 -license_family: Other -size: 96530 -timestamp: 1620479909603 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 -sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 -md5: 4d59c254e01d9cde7957100457e2d5fb -license: OFL-1.1 -license_family: Other -size: 700814 -timestamp: 1620479612257 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 -md5: 49023d73832ef61042f6a237cb2687e7 -license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 -license_family: Other -size: 1620504 -timestamp: 1727511233259 -- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda -sha256: aa4a44dba97151221100a637c7f4bde619567afade9c0265f8e1c8eed8d7bd8c -md5: 867127763fbe935bab59815b6e0b7b5c -depends: -- __glibc >=2.17,<3.0.a0 -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- libgcc >=14 -- libuuid >=2.41.3,<3.0a0 -- libzlib >=1.3.1,<2.0a0 -license: MIT -license_family: MIT -size: 270705 -timestamp: 1771382710863 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 -sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 -md5: fee5683a3f04bd15cbd8318b096a27ab -depends: -- fonts-conda-forge -license: BSD-3-Clause -license_family: BSD -size: 3667 -timestamp: 1566974674465 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda -sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 -md5: a7970cd949a077b7cb9696379d338681 -depends: -- font-ttf-ubuntu -- font-ttf-inconsolata -- font-ttf-dejavu-sans-mono -- font-ttf-source-code-pro -license: BSD-3-Clause -license_family: BSD -size: 4059 -timestamp: 1762351264405 -- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda -sha256: aac402a8298f0c0cc528664249170372ef6b37ac39fdc92b40601a6aed1e32ff -md5: 3bf7b9fd5a7136126e0234db4b87c8b6 -depends: -- libgcc-ng >=12 -license: MIT -license_family: MIT -size: 77248 -timestamp: 1712692454246 -- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda -sha256: 25ba37da5c39697a77fce2c9a15e48cf0a84f1464ad2aafbe53d8357a9f6cc8c -md5: 2cd94587f3a401ae05e03a6caf09539d -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libstdcxx >=14 -license: LGPL-2.0-or-later -license_family: LGPL -size: 99596 -timestamp: 1755102025473 -- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda -sha256: 477f2c553f72165020d3c56740ba354be916c2f0b76fd9f535e83d698277d5ec -md5: 14470902326beee192e33719a2e8bb7f -depends: -- __glibc >=2.17,<3.0.a0 -- cairo >=1.18.4,<2.0a0 -- graphite2 >=1.3.14,<2.0a0 -- icu >=78.3,<79.0a0 -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.2 -- libfreetype6 >=2.14.2 -- libgcc >=14 -- libglib >=2.86.4,<3.0a0 -- libstdcxx >=14 -- libzlib >=1.3.2,<2.0a0 -license: MIT -license_family: MIT -size: 2384060 -timestamp: 1774276284520 -- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda -sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a -md5: c80d8a3b84358cb967fa81e7075fbc8a -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libstdcxx >=14 -license: MIT -license_family: MIT -size: 12723451 -timestamp: 1773822285671 -- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda -sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 -md5: b38117a3c920364aff79f870c984b4a3 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -license: LGPL-2.1-or-later -size: 134088 -timestamp: 1754905959823 -- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda -sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 -md5: fb53fb07ce46a575c5d004bbc96032c2 -depends: -- __glibc >=2.17,<3.0.a0 -- keyutils >=1.6.3,<2.0a0 -- libedit >=3.1.20250104,<3.2.0a0 -- libedit >=3.1.20250104,<4.0a0 -- libgcc >=14 -- libstdcxx >=14 -- openssl >=3.5.5,<4.0a0 -license: MIT -license_family: MIT -size: 1386730 -timestamp: 1769769569681 -- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda -sha256: 836ec4b895352110335b9fdcfa83a8dcdbe6c5fb7c06c4929130600caea91c0a -md5: 6f2e2c8f58160147c4d1c6f4c14cbac4 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libjpeg-turbo >=3.1.2,<4.0a0 -- libtiff >=4.7.1,<4.8.0a0 -license: MIT -license_family: MIT -size: 249959 -timestamp: 1768184673131 -- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda -sha256: f84cb54782f7e9cea95e810ea8fef186e0652d0fa73d3009914fa2c1262594e1 -md5: a752488c68f2e7c456bcbd8f16eec275 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libstdcxx >=14 -license: Apache-2.0 -license_family: Apache -size: 261513 -timestamp: 1773113328888 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda -sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c -md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 -depends: -- __glibc >=2.17,<3.0.a0 -- krb5 >=1.22.2,<1.23.0a0 -- libgcc >=14 -- libstdcxx >=14 -- libzlib >=1.3.1,<2.0a0 -license: Apache-2.0 -license_family: Apache -size: 4518030 -timestamp: 1770902209173 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda -sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 -md5: 6c77a605a7a689d17d4819c0f8ac9a00 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: MIT -license_family: MIT -size: 73490 -timestamp: 1761979956660 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda -sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 -md5: c277e0a4d549b03ac1e9d6cbbe3d017b -depends: -- ncurses -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- ncurses >=6.5,<7.0a0 -license: BSD-2-Clause -license_family: BSD -size: 134676 -timestamp: 1738479519902 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda -sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 -md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -constrains: -- expat 2.7.4.* -license: MIT -license_family: MIT -size: 76798 -timestamp: 1771259418166 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda -sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 -md5: a360c33a5abe61c07959e449fa1453eb -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: MIT -license_family: MIT -size: 58592 -timestamp: 1769456073053 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda -sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 -md5: e289f3d17880e44b633ba911d57a321b -depends: -- libfreetype6 >=2.14.3 -license: GPL-2.0-only OR FTL -size: 8049 -timestamp: 1774298163029 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda -sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d -md5: fb16b4b69e3f1dcfe79d80db8fd0c55d -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libpng >=1.6.55,<1.7.0a0 -- libzlib >=1.3.2,<2.0a0 -constrains: -- freetype >=2.14.3 -license: GPL-2.0-only OR FTL -size: 384575 -timestamp: 1774298162622 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda -sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 -md5: 0aa00f03f9e39fb9876085dee11a85d4 -depends: -- __glibc >=2.17,<3.0.a0 -- _openmp_mutex >=4.5 -constrains: -- libgcc-ng ==15.2.0=*_18 -- libgomp 15.2.0 he0feb66_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 1041788 -timestamp: 1771378212382 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda -sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 -md5: d5e96b1ed75ca01906b3d2469b4ce493 -depends: -- libgcc 15.2.0 he0feb66_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 27526 -timestamp: 1771378224552 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda -sha256: a27e44168a1240b15659888ce0d9b938ed4bdb49e9ea68a7c1ff27bcea8b55ce -md5: bb26456332b07f68bf3b7622ed71c0da -depends: -- __glibc >=2.17,<3.0.a0 -- libffi >=3.5.2,<3.6.0a0 -- libgcc >=14 -- libiconv >=1.18,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- pcre2 >=10.47,<10.48.0a0 -constrains: -- glib 2.86.4 *_1 -license: LGPL-2.1-or-later -size: 4398701 -timestamp: 1771863239578 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda -sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 -md5: 239c5e9546c38a1e884d69effcf4c882 -depends: -- __glibc >=2.17,<3.0.a0 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 603262 -timestamp: 1771378117851 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda -sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f -md5: 915f5995e94f60e9a4826e0b0920ee88 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: LGPL-2.1-only -size: 790176 -timestamp: 1754908768807 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda -sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32 -md5: 8397539e3a0bbd1695584fb4f927485a -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -constrains: -- jpeg <0.0.0a -license: IJG AND BSD-3-Clause AND Zlib -size: 633710 -timestamp: 1762094827865 -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda -sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb -md5: c7c83eecbb72d88b940c249af56c8b17 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -constrains: -- xz 5.8.2.* -license: 0BSD -size: 113207 -timestamp: 1768752626120 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda -sha256: 36ade759122cdf0f16e2a2562a19746d96cf9c863ffaa812f2f5071ebbe9c03c -md5: 5f13ffc7d30ffec87864e678df9957b4 -depends: -- libgcc >=14 -- __glibc >=2.17,<3.0.a0 -- libzlib >=1.3.1,<2.0a0 -license: zlib-acknowledgement -size: 317669 -timestamp: 1770691470744 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda -sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e -md5: 1b08cd684f34175e4514474793d44bcb -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc 15.2.0 he0feb66_18 -constrains: -- libstdcxx-ng ==15.2.0=*_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 5852330 -timestamp: 1771378262446 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda -sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 -md5: cd5a90476766d53e901500df9215e927 -depends: -- __glibc >=2.17,<3.0.a0 -- lerc >=4.0.0,<5.0a0 -- libdeflate >=1.25,<1.26.0a0 -- libgcc >=14 -- libjpeg-turbo >=3.1.0,<4.0a0 -- liblzma >=5.8.1,<6.0a0 -- libstdcxx >=14 -- libwebp-base >=1.6.0,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- zstd >=1.5.7,<1.6.0a0 -license: HPND -size: 435273 -timestamp: 1762022005702 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda -sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee -md5: db409b7c1720428638e7c0d509d3e1b5 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: BSD-3-Clause -license_family: BSD -size: 40311 -timestamp: 1766271528534 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda -sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b -md5: aea31d2e5b1091feca96fcfe945c3cf9 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -constrains: -- libwebp 1.6.0 -license: BSD-3-Clause -license_family: BSD -size: 429011 -timestamp: 1752159441324 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda -sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa -md5: 92ed62436b625154323d40d5f2f11dd7 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- pthread-stubs -- xorg-libxau >=1.0.11,<2.0a0 -- xorg-libxdmcp -license: MIT -license_family: MIT -size: 395888 -timestamp: 1727278577118 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda -sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c -md5: 5aa797f8787fe7a17d1b0821485b5adc -depends: -- libgcc-ng >=12 -license: LGPL-2.1-or-later -size: 100393 -timestamp: 1702724383534 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda -sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 -md5: d87ff7921124eccd67248aa483c23fec -depends: -- __glibc >=2.17,<3.0.a0 -constrains: -- zlib 1.3.2 *_2 -license: Zlib -license_family: Other -size: 63629 -timestamp: 1774072609062 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda -sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 -md5: 47e340acb35de30501a76c7c799c41d7 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -license: X11 AND BSD-3-Clause -size: 891641 -timestamp: 1738195959188 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda -sha256: 3825a4c84676a8a5cc23b397a2911e4efa4a805daf2af764153bd904e142ec41 -md5: a41092b0177362dbe5eb2a18501e86c0 -depends: -- xorg-libx11 -- xorg-libxext -- xorg-libxi -- xorg-libxrender -- xorg-libxtst -- libstdcxx >=14 -- libgcc >=14 -- __glibc >=2.17,<3.0.a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- xorg-libxrender >=0.9.12,<0.10.0a0 -- libjpeg-turbo >=3.1.2,<4.0a0 -- giflib >=5.2.2,<5.3.0a0 -- xorg-libxrandr >=1.5.5,<2.0a0 -- harfbuzz >=12.3.2 -- fontconfig >=2.17.1,<3.0a0 -- fonts-conda-ecosystem -- xorg-libxtst >=1.2.5,<2.0a0 -- xorg-libxi >=1.8.2,<2.0a0 -- lcms2 >=2.18,<3.0a0 -- alsa-lib >=1.2.15.3,<1.3.0a0 -- libpng >=1.6.55,<1.7.0a0 -- xorg-libxt >=1.3.1,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- xorg-libxext >=1.3.7,<2.0a0 -- xorg-libx11 >=1.8.13,<2.0a0 -- libcups >=2.3.3,<2.4.0a0 -license: GPL-2.0-or-later WITH Classpath-exception-2.0 -license_family: GPL -size: 122465031 -timestamp: 1771443671180 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda -sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c -md5: f61eb8cd60ff9057122a3d338b99c00f -depends: -- __glibc >=2.17,<3.0.a0 -- ca-certificates -- libgcc >=14 -license: Apache-2.0 -license_family: Apache -size: 3164551 -timestamp: 1769555830639 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda -sha256: 5e6f7d161356fefd981948bea5139c5aa0436767751a6930cb1ca801ebb113ff -md5: 7a3bff861a6583f1889021facefc08b1 -depends: -- __glibc >=2.17,<3.0.a0 -- bzip2 >=1.0.8,<2.0a0 -- libgcc >=14 -- libzlib >=1.3.1,<2.0a0 -license: BSD-3-Clause -license_family: BSD -size: 1222481 -timestamp: 1763655398280 -- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda -build_number: 7 -sha256: 9ec32b6936b0e37bcb0ed34f22ec3116e75b3c0964f9f50ecea5f58734ed6ce9 -md5: f2cfec9406850991f4e3d960cc9e3321 -depends: -- libgcc-ng >=12 -- libxcrypt >=4.4.36 -license: GPL-1.0-or-later OR Artistic-1.0-Perl -size: 13344463 -timestamp: 1703310653947 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda -sha256: 43d37bc9ca3b257c5dd7bf76a8426addbdec381f6786ff441dc90b1a49143b6a -md5: c01af13bdc553d1a8fbfff6e8db075f0 -depends: -- libgcc >=14 -- libstdcxx >=14 -- libgcc >=14 -- __glibc >=2.17,<3.0.a0 -license: MIT -license_family: MIT -size: 450960 -timestamp: 1754665235234 -- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda -sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d -md5: f2c23a77b25efcad57d377b34bd84941 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- ncurses >=6.5,<7.0a0 -license: GPL-2.0-or-later AND LGPL-2.0-or-later -license_family: GPL -size: 593603 -timestamp: 1769710381284 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda -sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 -md5: b3c17d95b5a10c6e64a21fa17573e70e -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -license: MIT -license_family: MIT -size: 8252 -timestamp: 1726802366959 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda -sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b -md5: fb901ff28063514abb6046c9ec2c4a45 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -license: MIT -license_family: MIT -size: 58628 -timestamp: 1734227592886 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda -sha256: 277841c43a39f738927145930ff963c5ce4c4dacf66637a3d95d802a64173250 -md5: 1c74ff8c35dcadf952a16f752ca5aa49 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- libuuid >=2.38.1,<3.0a0 -- xorg-libice >=1.1.2,<2.0a0 -license: MIT -license_family: MIT -size: 27590 -timestamp: 1741896361728 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda -sha256: 516d4060139dbb4de49a4dcdc6317a9353fb39ebd47789c14e6fe52de0deee42 -md5: 861fb6ccbc677bb9a9fb2468430b9c6a -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libxcb >=1.17.0,<2.0a0 -license: MIT -license_family: MIT -size: 839652 -timestamp: 1770819209719 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda -sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b -md5: b2895afaf55bf96a8c8282a2e47a5de0 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: MIT -license_family: MIT -size: 15321 -timestamp: 1762976464266 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda -sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 -md5: 1dafce8548e38671bea82e3f5c6ce22f -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: MIT -license_family: MIT -size: 20591 -timestamp: 1762976546182 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda -sha256: 79c60fc6acfd3d713d6340d3b4e296836a0f8c51602327b32794625826bd052f -md5: 34e54f03dfea3e7a2dcf1453a85f1085 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -license: MIT -license_family: MIT -size: 50326 -timestamp: 1769445253162 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda -sha256: 83c4c99d60b8784a611351220452a0a85b080668188dce5dfa394b723d7b64f4 -md5: ba231da7fccf9ea1e768caf5c7099b84 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -license: MIT -license_family: MIT -size: 20071 -timestamp: 1759282564045 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda -sha256: 1a724b47d98d7880f26da40e45f01728e7638e6ec69f35a3e11f92acd05f9e7a -md5: 17dcc85db3c7886650b8908b183d6876 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- xorg-libx11 >=1.8.10,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxfixes >=6.0.1,<7.0a0 -license: MIT -license_family: MIT -size: 47179 -timestamp: 1727799254088 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda -sha256: 80ed047a5cb30632c3dc5804c7716131d767089f65877813d4ae855ee5c9d343 -md5: e192019153591938acf7322b6459d36e -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -license: MIT -license_family: MIT -size: 30456 -timestamp: 1769445263457 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda -sha256: 044c7b3153c224c6cedd4484dd91b389d2d7fd9c776ad0f4a34f099b3389f4a1 -md5: 96d57aba173e878a2089d5638016dc5e -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- xorg-libx11 >=1.8.10,<2.0a0 -license: MIT -license_family: MIT -size: 33005 -timestamp: 1734229037766 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda -sha256: a8afba4a55b7b530eb5c8ad89737d60d60bc151a03fbef7a2182461256953f0e -md5: 279b0de5f6ba95457190a1c459a64e31 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- xorg-libice >=1.1.1,<2.0a0 -- xorg-libsm >=1.2.4,<2.0a0 -- xorg-libx11 >=1.8.10,<2.0a0 -license: MIT -license_family: MIT -size: 379686 -timestamp: 1731860547604 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda -sha256: 752fdaac5d58ed863bbf685bb6f98092fe1a488ea8ebb7ed7b606ccfce08637a -md5: 7bbe9a0cc0df0ac5f5a8ad6d6a11af2f -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- xorg-libx11 >=1.8.10,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxi >=1.7.10,<2.0a0 -license: MIT -license_family: MIT -size: 32808 -timestamp: 1727964811275 -- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda -sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 -md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 -depends: -- __glibc >=2.17,<3.0.a0 -- libzlib >=1.3.1,<2.0a0 -license: BSD-3-Clause -license_family: BSD -size: 601375 -timestamp: 1764777111296 diff --git a/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt deleted file mode 100644 index cdc434c..0000000 --- a/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt +++ /dev/null @@ -1,769 +0,0 @@ - -version: 6 -environments: -default: -channels: -- url: https://conda.anaconda.org/conda-forge/ -- url: https://conda.anaconda.org/bioconda/ -- url: https://conda.anaconda.org/bioconda/ -options: -pypi-prerelease-mode: if-necessary-or-explicit -packages: -linux-aarch64: -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda -- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda -packages: -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda -build_number: 20 -sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 -md5: 468fd3bb9e1f671d36c2cbc677e56f1d -depends: -- libgomp >=7.5.0 -constrains: -- openmp_impl <0.0a0 -license: BSD-3-Clause -license_family: BSD -size: 28926 -timestamp: 1770939656741 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda -sha256: ea2233e2db9908c2e5f29d3ca420a546b4583253f4f70abb5494cdd676866d42 -md5: 4a98cbc4ade694520227402ff8880630 -depends: -- libgcc >=14 -license: LGPL-2.1-or-later -license_family: GPL -size: 615729 -timestamp: 1768327548407 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda -sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c -md5: 840d8fc0d7b3209be93080bc20e07f2d -depends: -- libgcc >=14 -license: bzip2-1.0.6 -license_family: BSD -size: 192412 -timestamp: 1771350241232 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc -md5: 4492fd26db29495f0ba23f146cd5638d -depends: -- __unix -license: ISC -size: 147413 -timestamp: 1772006283803 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda -sha256: 675db823f3d6fb6bf747fab3b0170ba99b269a07cf6df1e49fff2f9972be9cd1 -md5: 043c13ed3a18396994be9b4fab6572ad -depends: -- fontconfig >=2.15.0,<3.0a0 -- fonts-conda-ecosystem -- icu >=78.1,<79.0a0 -- libexpat >=2.7.3,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- libgcc >=14 -- libglib >=2.86.3,<3.0a0 -- libpng >=1.6.53,<1.7.0a0 -- libstdcxx >=14 -- libxcb >=1.17.0,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- pixman >=0.46.4,<1.0a0 -- xorg-libice >=1.1.2,<2.0a0 -- xorg-libsm >=1.2.6,<2.0a0 -- xorg-libx11 >=1.8.12,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -license: LGPL-2.1-only or MPL-1.1 -size: 927045 -timestamp: 1766416003626 -- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 -sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c -md5: c9f6a4b12229f7331f79c9a00dd6e240 -depends: -- font-ttf-dejavu-sans-mono -- fontconfig -- openjdk >=8.0.144 -- perl -license: GPL >=3 -size: 11664291 -timestamp: 1677946722445 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 -sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b -md5: 0c96522c6bdaed4b1566d11387caaf45 -license: BSD-3-Clause -license_family: BSD -size: 397370 -timestamp: 1566932522327 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 -sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c -md5: 34893075a5c9e55cdafac56607368fc6 -license: OFL-1.1 -license_family: Other -size: 96530 -timestamp: 1620479909603 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 -sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 -md5: 4d59c254e01d9cde7957100457e2d5fb -license: OFL-1.1 -license_family: Other -size: 700814 -timestamp: 1620479612257 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 -md5: 49023d73832ef61042f6a237cb2687e7 -license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 -license_family: Other -size: 1620504 -timestamp: 1727511233259 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda -sha256: 835aff8615dd8d8fff377679710ce81b8a2c47b6404e21a92fb349fda193a15c -md5: 0fed1ff55f4938a65907f3ecf62609db -depends: -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- libgcc >=14 -- libuuid >=2.41.3,<3.0a0 -- libzlib >=1.3.1,<2.0a0 -license: MIT -license_family: MIT -size: 279044 -timestamp: 1771382728182 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 -sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 -md5: fee5683a3f04bd15cbd8318b096a27ab -depends: -- fonts-conda-forge -license: BSD-3-Clause -license_family: BSD -size: 3667 -timestamp: 1566974674465 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda -sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 -md5: a7970cd949a077b7cb9696379d338681 -depends: -- font-ttf-ubuntu -- font-ttf-inconsolata -- font-ttf-dejavu-sans-mono -- font-ttf-source-code-pro -license: BSD-3-Clause -license_family: BSD -size: 4059 -timestamp: 1762351264405 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda -sha256: a79dc3bd54c4fb1f249942ee2d5b601a76ecf9614774a4cff9af49adfa458db2 -md5: 2f809afaf0ba1ea4135dce158169efac -depends: -- libgcc-ng >=12 -license: MIT -license_family: MIT -size: 82124 -timestamp: 1712692444545 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda -sha256: c9b1781fe329e0b77c5addd741e58600f50bef39321cae75eba72f2f381374b7 -md5: 4aa540e9541cc9d6581ab23ff2043f13 -depends: -- libgcc >=14 -- libstdcxx >=14 -license: LGPL-2.0-or-later -license_family: LGPL -size: 102400 -timestamp: 1755102000043 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda -sha256: e22f485fddaaea3ff4b6cae98e0197b9dccd2ed2770337ad6ff38a92afe04e59 -md5: 05d65a2cf410adc331c9ea61f59f1013 -depends: -- cairo >=1.18.4,<2.0a0 -- graphite2 >=1.3.14,<2.0a0 -- icu >=78.3,<79.0a0 -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.2 -- libfreetype6 >=2.14.2 -- libgcc >=14 -- libglib >=2.86.4,<3.0a0 -- libstdcxx >=14 -- libzlib >=1.3.2,<2.0a0 -license: MIT -license_family: MIT -size: 2345732 -timestamp: 1774281448329 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda -sha256: 49ba6aed2c6b482bb0ba41078057555d29764299bc947b990708617712ef6406 -md5: 546da38c2fa9efacf203e2ad3f987c59 -depends: -- libgcc >=14 -- libstdcxx >=14 -license: MIT -license_family: MIT -size: 12837286 -timestamp: 1773822650615 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda -sha256: 5ce830ca274b67de11a7075430a72020c1fb7d486161a82839be15c2b84e9988 -md5: e7df0aab10b9cbb73ab2a467ebfaf8c7 -depends: -- libgcc >=13 -license: LGPL-2.1-or-later -size: 129048 -timestamp: 1754906002667 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda -sha256: b53999d888dda53c506b264e8c02b5f5c8e022c781eda0718f007339e6bc90ba -md5: d9ca108bd680ea86a963104b6b3e95ca -depends: -- keyutils >=1.6.3,<2.0a0 -- libedit >=3.1.20250104,<3.2.0a0 -- libedit >=3.1.20250104,<4.0a0 -- libgcc >=14 -- libstdcxx >=14 -- openssl >=3.5.5,<4.0a0 -license: MIT -license_family: MIT -size: 1517436 -timestamp: 1769773395215 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda -sha256: 379ef5e91a587137391a6149755d0e929f1a007d2dcb211318ac670a46c8596f -md5: bb960f01525b5e001608afef9d47b79c -depends: -- libgcc >=14 -- libjpeg-turbo >=3.1.2,<4.0a0 -- libtiff >=4.7.1,<4.8.0a0 -license: MIT -license_family: MIT -size: 293039 -timestamp: 1768184778398 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda -sha256: 8957fd460c1c132c8031f65fd5f56ec3807fd71b7cab2c5e2b0937b13404ab36 -md5: d13423b06447113a90b5b1366d4da171 -depends: -- libgcc >=14 -- libstdcxx >=14 -license: Apache-2.0 -license_family: Apache -size: 240444 -timestamp: 1773114901155 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda -sha256: 41b04f995c9f63af8c4065a35931e46cbc2fdd6b9bf7e4c19f90d53cbb2bc8e5 -md5: 67828c963b17db7dc989fe5d509ef04a -depends: -- krb5 >=1.22.2,<1.23.0a0 -- libgcc >=14 -- libstdcxx >=14 -- libzlib >=1.3.1,<2.0a0 -license: Apache-2.0 -license_family: Apache -size: 4553739 -timestamp: 1770903929794 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda -sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 -md5: a9138815598fe6b91a1d6782ca657b0c -depends: -- libgcc >=14 -license: MIT -license_family: MIT -size: 71117 -timestamp: 1761979776756 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda -sha256: c0b27546aa3a23d47919226b3a1635fccdb4f24b94e72e206a751b33f46fd8d6 -md5: fb640d776fc92b682a14e001980825b1 -depends: -- ncurses -- libgcc >=13 -- ncurses >=6.5,<7.0a0 -license: BSD-2-Clause -license_family: BSD -size: 148125 -timestamp: 1738479808948 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda -sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 -md5: 57f3b3da02a50a1be2a6fe847515417d -depends: -- libgcc >=14 -constrains: -- expat 2.7.4.* -license: MIT -license_family: MIT -size: 76564 -timestamp: 1771259530958 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda -sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 -md5: 2f364feefb6a7c00423e80dcb12db62a -depends: -- libgcc >=14 -license: MIT -license_family: MIT -size: 55952 -timestamp: 1769456078358 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda -sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a -md5: a229e22d4d8814a07702b0919d8e6701 -depends: -- libfreetype6 >=2.14.3 -license: GPL-2.0-only OR FTL -size: 8125 -timestamp: 1774301094057 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda -sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c -md5: b99ed99e42dafb27889483b3098cace7 -depends: -- libgcc >=14 -- libpng >=1.6.55,<1.7.0a0 -- libzlib >=1.3.2,<2.0a0 -constrains: -- freetype >=2.14.3 -license: GPL-2.0-only OR FTL -size: 422941 -timestamp: 1774301093473 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda -sha256: 43df385bedc1cab11993c4369e1f3b04b4ca5d0ea16cba6a0e7f18dbc129fcc9 -md5: 552567ea2b61e3a3035759b2fdb3f9a6 -depends: -- _openmp_mutex >=4.5 -constrains: -- libgcc-ng ==15.2.0=*_18 -- libgomp 15.2.0 h8acb6b2_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 622900 -timestamp: 1771378128706 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda -sha256: 83bb0415f59634dccfa8335d4163d1f6db00a27b36666736f9842b650b92cf2f -md5: 4feebd0fbf61075a1a9c2e9b3936c257 -depends: -- libgcc 15.2.0 h8acb6b2_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 27568 -timestamp: 1771378136019 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda -sha256: afc503dbd04a5bf2709aa9d8318a03a8c4edb389f661ff280c3494bfef4341ec -md5: 4ac4372fc4d7f20630a91314cdac8afd -depends: -- libffi >=3.5.2,<3.6.0a0 -- libgcc >=14 -- libiconv >=1.18,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- pcre2 >=10.47,<10.48.0a0 -constrains: -- glib 2.86.4 *_1 -license: LGPL-2.1-or-later -size: 4512186 -timestamp: 1771863220969 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda -sha256: fc716f11a6a8525e27a5d332ef6a689210b0d2a4dd1133edc0f530659aa9faa6 -md5: 4faa39bf919939602e594253bd673958 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 588060 -timestamp: 1771378040807 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda -sha256: 1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9 -md5: 5a86bf847b9b926f3a4f203339748d78 -depends: -- libgcc >=14 -license: LGPL-2.1-only -size: 791226 -timestamp: 1754910975665 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda -sha256: 84064c7c53a64291a585d7215fe95ec42df74203a5bf7615d33d49a3b0f08bb6 -md5: 5109d7f837a3dfdf5c60f60e311b041f -depends: -- libgcc >=14 -constrains: -- jpeg <0.0.0a -license: IJG AND BSD-3-Clause AND Zlib -size: 691818 -timestamp: 1762094728337 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda -sha256: 843c46e20519651a3e357a8928352b16c5b94f4cd3d5481acc48be2e93e8f6a3 -md5: 96944e3c92386a12755b94619bae0b35 -depends: -- libgcc >=14 -constrains: -- xz 5.8.2.* -license: 0BSD -size: 125916 -timestamp: 1768754941722 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda -sha256: c7378c6b79de4d571d00ad1caf0a4c19d43c9c94077a761abb6ead44d891f907 -md5: be4088903b94ea297975689b3c3aeb27 -depends: -- libgcc >=14 -- libzlib >=1.3.1,<2.0a0 -license: zlib-acknowledgement -size: 340156 -timestamp: 1770691477245 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda -sha256: 31fdb9ffafad106a213192d8319b9f810e05abca9c5436b60e507afb35a6bc40 -md5: f56573d05e3b735cb03efeb64a15f388 -depends: -- libgcc 15.2.0 h8acb6b2_18 -constrains: -- libstdcxx-ng ==15.2.0=*_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 5541411 -timestamp: 1771378162499 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda -sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 -md5: 8c6fd84f9c87ac00636007c6131e457d -depends: -- lerc >=4.0.0,<5.0a0 -- libdeflate >=1.25,<1.26.0a0 -- libgcc >=14 -- libjpeg-turbo >=3.1.0,<4.0a0 -- liblzma >=5.8.1,<6.0a0 -- libstdcxx >=14 -- libwebp-base >=1.6.0,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- zstd >=1.5.7,<1.6.0a0 -license: HPND -size: 488407 -timestamp: 1762022048105 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda -sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 -md5: cf2861212053d05f27ec49c3784ff8bb -depends: -- libgcc >=14 -license: BSD-3-Clause -license_family: BSD -size: 43453 -timestamp: 1766271546875 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda -sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 -md5: 24e92d0942c799db387f5c9d7b81f1af -depends: -- libgcc >=14 -constrains: -- libwebp 1.6.0 -license: BSD-3-Clause -license_family: BSD -size: 359496 -timestamp: 1752160685488 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda -sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b -md5: cd14ee5cca2464a425b1dbfc24d90db2 -depends: -- libgcc >=13 -- pthread-stubs -- xorg-libxau >=1.0.11,<2.0a0 -- xorg-libxdmcp -license: MIT -license_family: MIT -size: 397493 -timestamp: 1727280745441 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda -sha256: 6b46c397644091b8a26a3048636d10b989b1bf266d4be5e9474bf763f828f41f -md5: b4df5d7d4b63579d081fd3a4cf99740e -depends: -- libgcc-ng >=12 -license: LGPL-2.1-or-later -size: 114269 -timestamp: 1702724369203 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda -sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f -md5: 502006882cf5461adced436e410046d1 -constrains: -- zlib 1.3.2 *_2 -license: Zlib -license_family: Other -size: 69833 -timestamp: 1774072605429 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda -sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468 -md5: 182afabe009dc78d8b73100255ee6868 -depends: -- libgcc >=13 -license: X11 AND BSD-3-Clause -size: 926034 -timestamp: 1738196018799 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda -sha256: 6fd2c872b275fa5d42a61a4b6dc28a819cde29f9048adb547363597432e0720e -md5: 27fdd5d67e235c20d23b2d66406497d3 -depends: -- xorg-libx11 -- xorg-libxext -- xorg-libxi -- xorg-libxrender -- xorg-libxtst -- libstdcxx >=14 -- libgcc >=14 -- libzlib >=1.3.1,<2.0a0 -- xorg-libxtst >=1.2.5,<2.0a0 -- libpng >=1.6.55,<1.7.0a0 -- alsa-lib >=1.2.15.3,<1.3.0a0 -- xorg-libx11 >=1.8.13,<2.0a0 -- xorg-libxi >=1.8.2,<2.0a0 -- xorg-libxrandr >=1.5.5,<2.0a0 -- lcms2 >=2.18,<3.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -- libcups >=2.3.3,<2.4.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- harfbuzz >=12.3.2 -- xorg-libxext >=1.3.7,<2.0a0 -- giflib >=5.2.2,<5.3.0a0 -- xorg-libxt >=1.3.1,<2.0a0 -- libjpeg-turbo >=3.1.2,<4.0a0 -- fontconfig >=2.17.1,<3.0a0 -- fonts-conda-ecosystem -license: GPL-2.0-or-later WITH Classpath-exception-2.0 -license_family: GPL -size: 106988620 -timestamp: 1771443741031 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda -sha256: 7f8048c0e75b2620254218d72b4ae7f14136f1981c5eb555ef61645a9344505f -md5: 25f5885f11e8b1f075bccf4a2da91c60 -depends: -- ca-certificates -- libgcc >=14 -license: Apache-2.0 -license_family: Apache -size: 3692030 -timestamp: 1769557678657 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda -sha256: 04df2cee95feba440387f33f878e9f655521e69f4be33a0cd637f07d3d81f0f9 -md5: 1a30c42e32ca0ea216bd0bfe6f842f0b -depends: -- bzip2 >=1.0.8,<2.0a0 -- libgcc >=14 -- libzlib >=1.3.1,<2.0a0 -license: BSD-3-Clause -license_family: BSD -size: 1166552 -timestamp: 1763655534263 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda -build_number: 7 -sha256: d78296134263b5bf476cad838ded65451e7162db756f9997c5d06b08122572ed -md5: 17d019cb2a6c72073c344e98e40dfd61 -depends: -- libgcc-ng >=12 -- libxcrypt >=4.4.36 -license: GPL-1.0-or-later OR Artistic-1.0-Perl -size: 13338804 -timestamp: 1703310557094 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda -sha256: e6b0846a998f2263629cfeac7bca73565c35af13251969f45d385db537a514e4 -md5: 1587081d537bd4ae77d1c0635d465ba5 -depends: -- libgcc >=14 -- libstdcxx >=14 -- libgcc >=14 -license: MIT -license_family: MIT -size: 357913 -timestamp: 1754665583353 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda -sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 -md5: ab7288cc39545556d1bc5e71ab2df9a9 -depends: -- libgcc >=14 -- ncurses >=6.5,<7.0a0 -license: GPL-2.0-or-later AND LGPL-2.0-or-later -license_family: GPL -size: 636733 -timestamp: 1769712412683 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda -sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba -md5: bb5a90c93e3bac3d5690acf76b4a6386 -depends: -- libgcc >=13 -license: MIT -license_family: MIT -size: 8342 -timestamp: 1726803319942 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda -sha256: a2ba1864403c7eb4194dacbfe2777acf3d596feae43aada8d1b478617ce45031 -md5: c8d8ec3e00cd0fd8a231789b91a7c5b7 -depends: -- libgcc >=13 -license: MIT -license_family: MIT -size: 60433 -timestamp: 1734229908988 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda -sha256: b86a819cd16f90c01d9d81892155126d01555a20dabd5f3091da59d6309afd0a -md5: 2d1409c50882819cb1af2de82e2b7208 -depends: -- libgcc >=13 -- libuuid >=2.38.1,<3.0a0 -- xorg-libice >=1.1.2,<2.0a0 -license: MIT -license_family: MIT -size: 28701 -timestamp: 1741897678254 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda -sha256: cf886160e2ff580d77f7eb8ec1a77c41c2c5b05343e329bc35f0ddf40b8d92ab -md5: 22dd10425ef181e80e130db50675d615 -depends: -- libgcc >=14 -- libxcb >=1.17.0,<2.0a0 -license: MIT -license_family: MIT -size: 869058 -timestamp: 1770819244991 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda -sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 -md5: 1c246e1105000c3660558459e2fd6d43 -depends: -- libgcc >=14 -license: MIT -license_family: MIT -size: 16317 -timestamp: 1762977521691 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda -sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1 -md5: bff06dcde4a707339d66d45d96ceb2e2 -depends: -- libgcc >=14 -license: MIT -license_family: MIT -size: 21039 -timestamp: 1762979038025 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda -sha256: db2188bc0d844d4e9747bac7f6c1d067e390bd769c5ad897c93f1df759dc5dba -md5: fb42b683034619915863d68dd9df03a3 -depends: -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -license: MIT -license_family: MIT -size: 52409 -timestamp: 1769446753771 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda -sha256: 8cb9c88e25c57e47419e98f04f9ef3154ad96b9f858c88c570c7b91216a64d0e -md5: e8b4056544341daf1d415eaeae7a040c -depends: -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -license: MIT -license_family: MIT -size: 20704 -timestamp: 1759284028146 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda -sha256: 7b587407ecb9ccd2bbaf0fb94c5dbdde4d015346df063e9502dc0ce2b682fb5e -md5: eeee3bdb31c6acde2b81ad1b8c287087 -depends: -- libgcc >=13 -- xorg-libx11 >=1.8.9,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxfixes >=6.0.1,<7.0a0 -license: MIT -license_family: MIT -size: 48197 -timestamp: 1727801059062 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda -sha256: 9f5196665a8d72f4f119c40dcc4bafeb0b540b102cc7b8b299c2abf599e7919f -md5: 1f64c613f0b8d67e9fb0e165d898fb6b -depends: -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -license: MIT -license_family: MIT -size: 31122 -timestamp: 1769445286951 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda -sha256: ffd77ee860c9635a28cfda46163dcfe9224dc6248c62404c544ae6b564a0be1f -md5: ae2c2dd0e2d38d249887727db2af960e -depends: -- libgcc >=13 -- xorg-libx11 >=1.8.10,<2.0a0 -license: MIT -license_family: MIT -size: 33649 -timestamp: 1734229123157 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda -sha256: 7c109792b60720809a580612aba7f8eb2a0bd425b9fc078748a9d6ffc97cbfa8 -md5: a9e4852c8e0b68ee783e7240030b696f -depends: -- libgcc >=13 -- xorg-libice >=1.1.1,<2.0a0 -- xorg-libsm >=1.2.4,<2.0a0 -- xorg-libx11 >=1.8.9,<2.0a0 -license: MIT -license_family: MIT -size: 384752 -timestamp: 1731860572314 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda -sha256: 6eaffce5a34fc0a16a21ddeaefb597e792a263b1b0c387c1ce46b0a967d558e1 -md5: c05698071b5c8e0da82a282085845860 -depends: -- libgcc >=13 -- xorg-libx11 >=1.8.9,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxi >=1.7.10,<2.0a0 -license: MIT -license_family: MIT -size: 33786 -timestamp: 1727964907993 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda -sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 -md5: c3655f82dcea2aa179b291e7099c1fcc -depends: -- libzlib >=1.3.1,<2.0a0 -license: BSD-3-Clause -license_family: BSD -size: 614429 -timestamp: 1764777145593 diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml deleted file mode 100644 index f9f54ee..0000000 --- a/modules/nf-core/fastqc/environment.yml +++ /dev/null @@ -1,7 +0,0 @@ ---- -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json -channels: - - conda-forge - - bioconda -dependencies: - - bioconda::fastqc=0.12.1 diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf deleted file mode 100644 index 1085126..0000000 --- a/modules/nf-core/fastqc/main.nf +++ /dev/null @@ -1,57 +0,0 @@ -process FASTQC { - tag "${meta.id}" - label 'process_low' - - conda "${moduleDir}/environment.yml" - container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container - ? 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' - : 'quay.io/biocontainers/fastqc:0.12.1--hdfd78af_0'}" - - input: - tuple val(meta), path(reads, stageAs: '?/*') - - output: - tuple val(meta), path("*.html"), emit: html - tuple val(meta), path("*.zip"), emit: zip - tuple val("${task.process}"), val('fastqc'), eval('fastqc --version | sed "/FastQC v/!d; s/.*v//"'), emit: versions_fastqc, topic: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" - // Make list of old name and new name pairs to use for renaming in the bash while loop - def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[reads, "${prefix}.${reads.extension}"]] : reads.withIndex().collect { entry, index -> [entry, "${prefix}_${index + 1}.${entry.extension}"] } - def rename_to = old_new_pairs*.join(' ').join(' ') - def renamed_files = old_new_pairs.collect { _old_name, new_name -> new_name }.join(' ') - - // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) - // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 - // Dividing the task.memory by task.cpus allows to stick to requested amount of RAM in the label - def memory_in_mb = task.memory - ? (task.memory.toUnit('MB') / task.cpus).intValue() - : null - // FastQC memory value allowed range (100 - 10000) - def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) - def fastqc_memory_arg = fastqc_memory ? "--memory ${fastqc_memory}" : '' - - """ - printf "%s %s\\n" ${rename_to} | while read old_name new_name; do - [ -f "\${new_name}" ] || ln -s \$old_name \$new_name - done - - fastqc \\ - ${args} \\ - --threads ${task.cpus} \\ - ${fastqc_memory_arg} \\ - ${renamed_files} - """ - - stub: - def prefix = task.ext.prefix ?: "${meta.id}" - """ - touch ${prefix}.html - touch ${prefix}.zip - """ -} diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml deleted file mode 100644 index 2f6cfef..0000000 --- a/modules/nf-core/fastqc/meta.yml +++ /dev/null @@ -1,111 +0,0 @@ -name: fastqc -description: Run FastQC on sequenced reads -keywords: - - quality control - - qc - - adapters - - fastq -tools: - - fastqc: - description: | - FastQC gives general quality metrics about your reads. - It provides information about the quality score distribution - across your reads, the per base sequence content (%A/C/G/T). - - You get information about adapter contamination and other - overrepresented sequences. - homepage: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/ - documentation: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/ - licence: ["GPL-2.0-only"] - identifier: biotools:fastqc -input: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - reads: - type: file - description: | - List of input FastQ files of size 1 and 2 for single-end and paired-end data, - respectively. - ontologies: [] -output: - html: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - "*.html": - type: file - description: FastQC report - pattern: "*_{fastqc.html}" - ontologies: [] - zip: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - "*.zip": - type: file - description: FastQC report archive - pattern: "*_{fastqc.zip}" - ontologies: [] - versions_fastqc: - - - ${task.process}: - type: string - description: The process the versions were collected from - - fastqc: - type: string - description: The tool name - - fastqc --version | sed "/FastQC v/!d; s/.*v//": - type: eval - description: The expression to obtain the version of the tool - -topics: - versions: - - - ${task.process}: - type: string - description: The process the versions were collected from - - fastqc: - type: string - description: The tool name - - fastqc --version | sed "/FastQC v/!d; s/.*v//": - type: eval - description: The expression to obtain the version of the tool -authors: - - "@drpatelh" - - "@grst" - - "@ewels" - - "@FelixKrueger" -maintainers: - - "@drpatelh" - - "@grst" - - "@ewels" - - "@FelixKrueger" -containers: - docker: - linux/arm64: - name: community.wave.seqera.io/library/fastqc:0.12.1--e455e32f745abe68 - build_id: bd-e455e32f745abe68_1 - scan_id: sc-f102f736465af88c_1 - linux/amd64: - name: community.wave.seqera.io/library/fastqc:0.12.1--5cb1a2fa2f18c7c2 - build_id: bd-5cb1a2fa2f18c7c2_1 - scan_id: sc-0c0466326b6b77d2_1 - singularity: - linux/amd64: - name: oras://community.wave.seqera.io/library/fastqc:0.12.1--5c4bd442468d75dd - build_id: bd-5c4bd442468d75dd_1 - https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/f2/f20b021476d1d87658820f971ebecc1e8cdbde0f338eb0d9cea2b0a8fc54a54b/data - linux/arm64: - name: oras://community.wave.seqera.io/library/fastqc:0.12.1--127a87fc06499035 - build_id: bd-127a87fc06499035_1 - https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/46/46daf2dad0169afd2ae047c3e50ed3776259f664bf07e5e06b045dc23449e994/data - conda: - linux/amd64: - lock_file: modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt - linux/arm64: - lock_file: modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test deleted file mode 100644 index 66c44da..0000000 --- a/modules/nf-core/fastqc/tests/main.nf.test +++ /dev/null @@ -1,309 +0,0 @@ -nextflow_process { - - name "Test Process FASTQC" - script "../main.nf" - process "FASTQC" - - tag "modules" - tag "modules_nfcore" - tag "fastqc" - - test("sarscov2 single-end [fastq]") { - - when { - process { - """ - input[0] = Channel.of([ - [ id: 'test', single_end:true ], - [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. - // looks like this:
    Mon 2 Oct 2023
    test.gz
    - // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 - { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } - ) - } - } - - test("sarscov2 paired-end [fastq]") { - - when { - process { - """ - input[0] = Channel.of([ - [id: 'test', single_end: false], // meta map - [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, - { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, - { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, - { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, - { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } - ) - } - } - - test("sarscov2 interleaved [fastq]") { - - when { - process { - """ - input[0] = Channel.of([ - [id: 'test', single_end: false], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } - ) - } - } - - test("sarscov2 paired-end [bam]") { - - when { - process { - """ - input[0] = Channel.of([ - [id: 'test', single_end: false], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } - ) - } - } - - test("sarscov2 multiple [fastq]") { - - when { - process { - """ - input[0] = Channel.of([ - [id: 'test', single_end: false], // meta map - [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, - { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, - { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, - { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, - { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, - { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, - { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, - { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, - { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, - { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } - ) - } - } - - test("sarscov2 custom_prefix") { - - when { - process { - """ - input[0] = Channel.of([ - [ id:'mysample', single_end:true ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } - ) - } - } - - test("sarscov2 single-end [fastq] - stub") { - - options "-stub" - when { - process { - """ - input[0] = Channel.of([ - [ id: 'test', single_end:true ], - [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) ] - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - } - - test("sarscov2 paired-end [fastq] - stub") { - - options "-stub" - when { - process { - """ - input[0] = Channel.of([ - [id: 'test', single_end: false], // meta map - [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - } - - test("sarscov2 interleaved [fastq] - stub") { - - options "-stub" - when { - process { - """ - input[0] = Channel.of([ - [id: 'test', single_end: false], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - } - - test("sarscov2 paired-end [bam] - stub") { - - options "-stub" - when { - process { - """ - input[0] = Channel.of([ - [id: 'test', single_end: false], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - } - - test("sarscov2 multiple [fastq] - stub") { - - options "-stub" - when { - process { - """ - input[0] = Channel.of([ - [id: 'test', single_end: false], // meta map - [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - } - - test("sarscov2 custom_prefix - stub") { - - options "-stub" - when { - process { - """ - input[0] = Channel.of([ - [ id:'mysample', single_end:true ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) - ]) - """ - } - } - - then { - assertAll ( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - } -} diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap deleted file mode 100644 index c8ee120..0000000 --- a/modules/nf-core/fastqc/tests/main.nf.test.snap +++ /dev/null @@ -1,476 +0,0 @@ -{ - "sarscov2 custom_prefix": { - "content": [ - { - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:39:14.518503" - }, - "sarscov2 single-end [fastq] - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test", - "single_end": true - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - { - "id": "test", - "single_end": true - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "2": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "html": [ - [ - { - "id": "test", - "single_end": true - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "zip": [ - [ - { - "id": "test", - "single_end": true - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:39:19.309008" - }, - "sarscov2 custom_prefix - stub": { - "content": [ - { - "0": [ - [ - { - "id": "mysample", - "single_end": true - }, - "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - { - "id": "mysample", - "single_end": true - }, - "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "2": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "html": [ - [ - { - "id": "mysample", - "single_end": true - }, - "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "zip": [ - [ - { - "id": "mysample", - "single_end": true - }, - "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:39:44.94888" - }, - "sarscov2 interleaved [fastq]": { - "content": [ - { - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:38:45.168496" - }, - "sarscov2 paired-end [bam]": { - "content": [ - { - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:38:53.268919" - }, - "sarscov2 multiple [fastq]": { - "content": [ - { - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:39:05.050305" - }, - "sarscov2 paired-end [fastq]": { - "content": [ - { - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:38:37.2373" - }, - "sarscov2 paired-end [fastq] - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test", - "single_end": false - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - { - "id": "test", - "single_end": false - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "2": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "html": [ - [ - { - "id": "test", - "single_end": false - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "zip": [ - [ - { - "id": "test", - "single_end": false - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:39:24.450398" - }, - "sarscov2 multiple [fastq] - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test", - "single_end": false - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - { - "id": "test", - "single_end": false - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "2": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "html": [ - [ - { - "id": "test", - "single_end": false - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "zip": [ - [ - { - "id": "test", - "single_end": false - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:39:39.758762" - }, - "sarscov2 single-end [fastq]": { - "content": [ - { - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:38:29.555068" - }, - "sarscov2 interleaved [fastq] - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test", - "single_end": false - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - { - "id": "test", - "single_end": false - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "2": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "html": [ - [ - { - "id": "test", - "single_end": false - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "zip": [ - [ - { - "id": "test", - "single_end": false - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:39:29.193136" - }, - "sarscov2 paired-end [bam] - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test", - "single_end": false - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - { - "id": "test", - "single_end": false - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "2": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "html": [ - [ - { - "id": "test", - "single_end": false - }, - "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_fastqc": [ - [ - "FASTQC", - "fastqc", - "0.12.1" - ] - ], - "zip": [ - [ - { - "id": "test", - "single_end": false - }, - "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ] - } - ], - "meta": { - "nf-test": "0.9.2", - "nextflow": "25.10.0" - }, - "timestamp": "2025-10-28T16:39:34.144919" - } -} \ No newline at end of file From a4651fe348767e969d8d294e7dc35374115d1d46 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 18 Jun 2026 23:11:53 +0200 Subject: [PATCH 042/334] Stage whole directory instead of individual files to keep path structures --- .../local/utils_nfcore_datasync_pipeline/main.nf | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index db1f6d4..b3ce127 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -109,16 +109,6 @@ workflow PIPELINE_INITIALISATION { channel .fromList(samplesheetToList(input, "${projectDir}/assets/schema_input.json")) - .map { - meta, input_path -> - def target = file(input_path) - if (target.isDirectory()) { - def all_files = files("${input_path}/**", type: 'file') - [meta, all_files] - } else { - [meta, [target]] - } - } .set { ch_samplesheet } emit: From 7ea385303402d0ec4c4ca7e3c620d7c6fcb813b3 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 18 Jun 2026 23:13:32 +0200 Subject: [PATCH 043/334] Add checksum column and adapt samplesheet channel --- assets/checksum.md5 | 21 +++++++++++++++++++++ assets/samplesheet.csv | 6 +++--- assets/schema_input.json | 19 ++++++++++++++++++- workflows/datasync.nf | 18 ++++++++++++++++-- 4 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 assets/checksum.md5 diff --git a/assets/checksum.md5 b/assets/checksum.md5 new file mode 100644 index 0000000..b851672 --- /dev/null +++ b/assets/checksum.md5 @@ -0,0 +1,21 @@ +6cae999421b3107d31aaee312a67b2b4 BWAIndex/genome.fa.pac +dee21a414c8c9435c516ce51453eac69 BWAIndex/genome.fa.ann +a6da8681616c05eb542f1d91606a7b2f BWAIndex/genome.fa +6cae999421b3107d31aaee312a67b2b4 BWAIndex/version0.6.0/genome.fa.pac +dee21a414c8c9435c516ce51453eac69 BWAIndex/version0.6.0/genome.fa.ann +a6da8681616c05eb542f1d91606a7b2f BWAIndex/version0.6.0/genome.fa +b5666883af79e600563852fbd6db60ff BWAIndex/version0.6.0/genome.fa.sa +54d052dc82eee7a34465b8e8a8989631 BWAIndex/version0.6.0/genome.fa.amb +88712af9626d5cbba82007cf8e3f90b2 BWAIndex/version0.6.0/genome.fa.bwt +6cae999421b3107d31aaee312a67b2b4 BWAIndex/version0.5.x/genome.fa.pac +dee21a414c8c9435c516ce51453eac69 BWAIndex/version0.5.x/genome.fa.ann +a6da8681616c05eb542f1d91606a7b2f BWAIndex/version0.5.x/genome.fa +826ca9f3dd61da0e50e869ead26edd99 BWAIndex/version0.5.x/genome.fa.rpac +08b6a8da1dae3f4d22e2e78887ddc9e4 BWAIndex/version0.5.x/genome.fa.rsa +456ac470698ac3ce1bb56110f00ac732 BWAIndex/version0.5.x/genome.fa.sa +54d052dc82eee7a34465b8e8a8989631 BWAIndex/version0.5.x/genome.fa.amb +d48c35964b0817176190aab0c8270e5d BWAIndex/version0.5.x/genome.fa.rbwt +9177d5f8c71ec47f65ccf0ab189ab408 BWAIndex/version0.5.x/genome.fa.bwt +b5666883af79e600563852fbd6db60ff BWAIndex/genome.fa.sa +54d052dc82eee7a34465b8e8a8989631 BWAIndex/genome.fa.amb +88712af9626d5cbba82007cf8e3f90b2 BWAIndex/genome.fa.bwt diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 55cd8f9..e4ef522 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,3 @@ -sample,input -human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/ -test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz +sample,input,checksum_md5 +human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/,assets/checksum.md5 +test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz,f06e81ce1eb2d5424f88ca7f345ec0d1 diff --git a/assets/schema_input.json b/assets/schema_input.json index 4afb584..e26e491 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -17,8 +17,25 @@ "type": "string", "pattern": "^\\S+$", "errorMessage": "Input path must be provided and cannot contain spaces" + }, + "checksum_md5": { + "type": "string", + "pattern": "^\\S+$", + "errorMessage": "Checksum_md5 cannot contain spaces" + }, + "checksum_sha": { + "type": "string", + "pattern": "^\\S+$", + "errorMessage": "Checksum_sha cannot contain spaces" } }, - "required": ["sample", "input"] + "required": [ + "sample", + "input" + ], + "oneOf": [ + { "required" : ["checksum_md5"] }, + { "required" : ["checksum_sha"] } + ] } } diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 6e6c910..afa1194 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -31,13 +31,27 @@ workflow DATASYNC { ch_versions = channel.empty() ch_multiqc_files = channel.empty() + ch_samplesheet = ch_samplesheet.multiMap { + meta, input_path, md5, sha -> + input: [ meta, input_path ] + checksum: [ meta, md5, sha ] + } + + ch_checksum = ch_samplesheet.checksum.branch { + meta, md5, sha -> + md5: !md5.isEmpty() + return [ meta, md5 ] + sha: !sha.isEmpty() + return [ meta, sha ] + } + MD5SUM( - ch_samplesheet, + ch_samplesheet.input, false ) SHASUM( - ch_samplesheet.transpose() + ch_samplesheet.input ) // From 47f68bd1095d4fc2996f4924657f6bc60ea66de7 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 18 Jun 2026 23:14:07 +0200 Subject: [PATCH 044/334] Modify shasum to work with multiple files --- modules/nf-core/shasum/main.nf | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/nf-core/shasum/main.nf b/modules/nf-core/shasum/main.nf index 2fa689d..b79d387 100644 --- a/modules/nf-core/shasum/main.nf +++ b/modules/nf-core/shasum/main.nf @@ -8,7 +8,7 @@ process SHASUM { : 'community.wave.seqera.io/library/coreutils_grep_gzip_lbzip2_pruned:838ba80435a629f8'}" input: - tuple val(meta), path(file) + tuple val(meta), path(files) output: tuple val(meta), path("*.sha256"), emit: checksum @@ -19,15 +19,17 @@ process SHASUM { script: def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" """ - sha256sum \\ - ${args} \\ - ${file} \\ - > ${file}.sha256 + find -L * -type f \\ + ! -name '*.sha256' \\ + -exec sha256sum ${args} "{}" + \\ + > ${prefix}.sha256 """ stub: + def prefix = task.ext.prefix ?: "${meta.id}" """ - touch ${file}.sha256 + touch ${prefix}.sha256 """ } From 513fad882b4a4968827798656eb6aaf888c0a42a Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 19 Jun 2026 14:20:42 +0000 Subject: [PATCH 045/334] Update shasum module --- modules.json | 2 +- modules/nf-core/shasum/main.nf | 38 +++++++++++++---- modules/nf-core/shasum/meta.yml | 9 +++- modules/nf-core/shasum/tests/main.nf.test | 33 ++++++++++++++- .../nf-core/shasum/tests/main.nf.test.snap | 42 ++++++++++++++++--- workflows/datasync.nf | 3 +- 6 files changed, 106 insertions(+), 21 deletions(-) diff --git a/modules.json b/modules.json index a6c41ad..711f257 100644 --- a/modules.json +++ b/modules.json @@ -17,7 +17,7 @@ }, "shasum": { "branch": "master", - "git_sha": "ef2ee0358c7d03231834aeac816991aeb20debd7", + "git_sha": "429d56ab5b5879549f71bf9905104f39d0c3bff4", "installed_by": ["modules"] } } diff --git a/modules/nf-core/shasum/main.nf b/modules/nf-core/shasum/main.nf index b79d387..65dffad 100644 --- a/modules/nf-core/shasum/main.nf +++ b/modules/nf-core/shasum/main.nf @@ -9,6 +9,7 @@ process SHASUM { input: tuple val(meta), path(files) + val as_separate_files output: tuple val(meta), path("*.sha256"), emit: checksum @@ -20,16 +21,35 @@ process SHASUM { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - """ - find -L * -type f \\ - ! -name '*.sha256' \\ - -exec sha256sum ${args} "{}" + \\ - > ${prefix}.sha256 - """ + // will only use when as_separate_files = false + if (as_separate_files) { + """ + find -L * -maxdepth 0 -type f \\ + ! -name '*.sha256' \\ + -exec sh -c 'sha256sum ${args} "\$1" > "\$1.sha256"' _ "{}" \\; + """ + } + else { + """ + find -L * -type f \\ + ! -name '*.sha256' \\ + -exec sha256sum ${args} "{}" + \\ + > ${prefix}.sha256 + """ + } stub: def prefix = task.ext.prefix ?: "${meta.id}" - """ - touch ${prefix}.sha256 - """ + if (as_separate_files) { + """ + find -L * -type f \\ + ! -name '*.sha256' \\ + -exec sh -c 'touch "\$1.sha256"' _ "{}" \\; + """ + } + else { + """ + touch ${prefix}.sha256 + """ + } } diff --git a/modules/nf-core/shasum/meta.yml b/modules/nf-core/shasum/meta.yml index 327a4f0..e4b7648 100644 --- a/modules/nf-core/shasum/meta.yml +++ b/modules/nf-core/shasum/meta.yml @@ -18,11 +18,16 @@ input: description: | Groovy Map containing sample information e.g. [ id:'test', single_end:false ] - - file: + - files: type: file - description: Any file + description: Any number of files pattern: "*.*" ontologies: [] + - as_separate_files: + type: boolean + description: | + If true, each file will have its own shasum file. If false, all files will be + checksummed into a single shasum file. output: checksum: - - meta: diff --git a/modules/nf-core/shasum/tests/main.nf.test b/modules/nf-core/shasum/tests/main.nf.test index 02d2ac0..6e2d413 100644 --- a/modules/nf-core/shasum/tests/main.nf.test +++ b/modules/nf-core/shasum/tests/main.nf.test @@ -9,16 +9,44 @@ nextflow_process { tag "modules_nfcore" tag "shasum" - test("test-shasum") { + test("test-shasum, separate") { when { process { """ input[0] = [ [ id:'test', single_end:false ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true) + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] ] + input[1] = true + """ + } + } + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out)).match() } + ) + } + } + + test("test-shasum, combined") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = false """ } } @@ -42,6 +70,7 @@ nextflow_process { [ id:'test', single_end:false ], // meta map file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true) ] + input[1] = true """ } diff --git a/modules/nf-core/shasum/tests/main.nf.test.snap b/modules/nf-core/shasum/tests/main.nf.test.snap index a86583b..df3986f 100644 --- a/modules/nf-core/shasum/tests/main.nf.test.snap +++ b/modules/nf-core/shasum/tests/main.nf.test.snap @@ -1,5 +1,5 @@ { - "test-shasum": { + "test-shasum, combined": { "content": [ { "checksum": [ @@ -8,7 +8,7 @@ "id": "test", "single_end": false }, - "test.paired_end.bam.sha256:md5,138a19e100f09fc975ea1b717da9b6dd" + "test.sha256:md5,cbe368d92c146935e6d72a00c2c2c804" ] ], "versions_sha256sum": [ @@ -20,10 +20,10 @@ ] } ], - "timestamp": "2026-05-03T20:43:40.688253838", + "timestamp": "2026-06-19T13:40:52.588704139", "meta": { "nf-test": "0.9.5", - "nextflow": "24.10.4" + "nextflow": "26.04.4" } }, "test-shasum - stub": { @@ -47,10 +47,40 @@ ] } ], - "timestamp": "2026-05-03T20:43:46.125782074", + "timestamp": "2026-06-19T13:40:59.232985121", "meta": { "nf-test": "0.9.5", - "nextflow": "24.10.4" + "nextflow": "26.04.4" + } + }, + "test-shasum, separate": { + "content": [ + { + "checksum": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastq.gz.sha256:md5,d200e9d01dfc874b9c5efe894181b430", + "test_2.fastq.gz.sha256:md5,0035d52e9b642206858b826f2b49d7a3" + ] + ] + ], + "versions_sha256sum": [ + [ + "SHASUM", + "sha256sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-06-19T13:40:45.551657784", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.4" } } } \ No newline at end of file diff --git a/workflows/datasync.nf b/workflows/datasync.nf index c9370be..03718ba 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -53,7 +53,8 @@ workflow DATASYNC { MD5SUM.output.checksum.view() SHASUM( - ch_samplesheet.input + ch_samplesheet.input, + false ) // From 4976eb9776252d31076e00f137ff3c1d4b99ad16 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 19 Jun 2026 18:45:50 +0000 Subject: [PATCH 046/334] include test full --- conf/test_full.config | 2 +- tests/main_full.nf.test | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/main_full.nf.test diff --git a/conf/test_full.config b/conf/test_full.config index b75f98c..af7be2f 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,7 +17,7 @@ params { // Input data for full size test // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = "${projectDir}/assets/samplesheet_full.csv" + input = "https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/samplesheet.csv" // Genome references genome = 'R64-1-1' diff --git a/tests/main_full.nf.test b/tests/main_full.nf.test new file mode 100644 index 0000000..47558e6 --- /dev/null +++ b/tests/main_full.nf.test @@ -0,0 +1,33 @@ +nextflow_pipeline { + + name "Test pipeline" + script "../main.nf" + tag "pipeline" + + test("-profile test_full") { + + when { + params { + outdir = "$outputDir" + } + } + + then { + // stable_path: All files + folders in ${params.outdir}/ with a stable path (including file name) + def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_content: All files in ${params.outdir}/ with stable content + def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + assert workflow.success + assertAll( + { assert snapshot( + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_path, + // All files with stable contents + stable_content + ).match() } + ) + } + } +} From a0543f16d66cd1ff91f3af3c1d9e90e3ea90942b Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 19 Jun 2026 18:46:10 +0000 Subject: [PATCH 047/334] remove debug print --- workflows/datasync.nf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index c9370be..a184b77 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -44,14 +44,12 @@ workflow DATASYNC { sha: !sha.isEmpty() return [ meta, sha ] } - + MD5SUM( ch_samplesheet.input, false ) - MD5SUM.output.checksum.view() - SHASUM( ch_samplesheet.input ) From a26b66b492d9273cc7f24149615c8efe41cd6854 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 19 Jun 2026 18:46:21 +0000 Subject: [PATCH 048/334] fix schema --- assets/schema_input.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/schema_input.json b/assets/schema_input.json index e26e491..7dfd8d2 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -33,7 +33,7 @@ "sample", "input" ], - "oneOf": [ + "anyOf": [ { "required" : ["checksum_md5"] }, { "required" : ["checksum_sha"] } ] From b14919e43d3a27b092f6f39aa30d0a498d873f9b Mon Sep 17 00:00:00 2001 From: zxBIB Date: Fri, 19 Jun 2026 20:57:35 +0200 Subject: [PATCH 049/334] create main_full snapshot --- tests/main_full.nf.test.snap | 49 ++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 tests/main_full.nf.test.snap diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap new file mode 100644 index 0000000..5a799b3 --- /dev/null +++ b/tests/main_full.nf.test.snap @@ -0,0 +1,49 @@ +{ + "-profile test_full": { + "content": [ + { + "MD5SUM": { + "md5sum": 9.5 + }, + "SHASUM": { + "sha256sum": 9.5 + }, + "Workflow": { + "nf-core/datasync": "v1.0dev" + } + }, + [ + "md5sum", + "md5sum/human_grch38_sequence.md5", + "md5sum/test_fastq.md5", + "multiqc", + "multiqc/multiqc_data", + "multiqc/multiqc_data/llms-full.txt", + "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc.parquet", + "multiqc/multiqc_data/multiqc_citations.txt", + "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_datasync_software_mqc_versions.yml", + "shasum", + "shasum/human_grch38_sequence.sha256", + "shasum/test_fastq.sha256" + ], + [ + "human_grch38_sequence.md5:md5,4dd34e25c530b2c6e4637014711acc44", + "test_fastq.md5:md5,145df327e566f16b545fbca236f9bb62", + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "human_grch38_sequence.sha256:md5,e3d6d2705970f75961eff5d5c09ce4d8", + "test_fastq.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-06-19T20:54:12.524244888" + } +} \ No newline at end of file From f628854a534a7347778a7f08f7d02bda77b5163e Mon Sep 17 00:00:00 2001 From: zxBIB Date: Fri, 19 Jun 2026 21:12:45 +0200 Subject: [PATCH 050/334] update default snapshot --- tests/default.nf.test.snap | 44 +++++++++++--------------------------- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index a20e40d..b45596b 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -14,13 +14,8 @@ }, [ "md5sum", - "md5sum/GenomeSize.xml.md5", - "md5sum/GenomeSize.xml.old.md5", - "md5sum/genome.dict.md5", - "md5sum/genome.dict.old.md5", - "md5sum/genome.fa.fai.md5", - "md5sum/genome.fa.md5", - "md5sum/test2_1.fastq.gz.md5", + "md5sum/human_grch38_sequence.md5", + "md5sum/test_fastq.md5", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", @@ -34,36 +29,21 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "shasum", - "shasum/GenomeSize.xml.old.sha256", - "shasum/GenomeSize.xml.sha256", - "shasum/genome.dict.old.sha256", - "shasum/genome.dict.sha256", - "shasum/genome.fa.fai.sha256", - "shasum/genome.fa.sha256", - "shasum/test2_1.fastq.gz.sha256" + "shasum/human_grch38_sequence.sha256", + "shasum/test_fastq.sha256" ], [ - "GenomeSize.xml.md5:md5,0c1c07f13ddcd6f479f8312b0c7d9843", - "GenomeSize.xml.old.md5:md5,8273ac6aa130edf9e628cf0cf2566855", - "genome.dict.md5:md5,cf34a65ce7a3e827c66eadb2d5522551", - "genome.dict.old.md5:md5,4dfbb85cd00197e03f43f999b39addab", - "genome.fa.fai.md5:md5,8fc26b8f3ce6b83f9860ae9a2347d046", - "genome.fa.md5:md5,cca9026fcc32a789c00d9070edac5809", - "test2_1.fastq.gz.md5:md5,145df327e566f16b545fbca236f9bb62", + "human_grch38_sequence.md5:md5,4dd34e25c530b2c6e4637014711acc44", + "test_fastq.md5:md5,145df327e566f16b545fbca236f9bb62", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "GenomeSize.xml.old.sha256:md5,068e91cdcc084710caf61a0859ac2be9", - "GenomeSize.xml.sha256:md5,e7a175f04cab11ce0a245133d70de9fb", - "genome.dict.old.sha256:md5,77492c77f911887b269de347e157d4ca", - "genome.dict.sha256:md5,0021eaba625d4dc9fcec55eb7384426e", - "genome.fa.fai.sha256:md5,99f227079c0fd354f272c0046482ff1a", - "genome.fa.sha256:md5,9bdb272c4b51342a0f139fbc14d0a57e", - "test2_1.fastq.gz.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" + "human_grch38_sequence.sha256:md5,e3d6d2705970f75961eff5d5c09ce4d8", + "test_fastq.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" ] ], - "timestamp": "2026-06-18T03:05:43.540206333", "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.4" - } + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-06-19T21:05:19.976503457" } } \ No newline at end of file From f5708cd0e00be0e73ca60330a7b9b7608ddfbf3a Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 22 Jun 2026 16:46:42 +0200 Subject: [PATCH 051/334] Fix linting in schema_input.json --- assets/schema_input.json | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/assets/schema_input.json b/assets/schema_input.json index e26e491..2656a6a 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -29,13 +29,7 @@ "errorMessage": "Checksum_sha cannot contain spaces" } }, - "required": [ - "sample", - "input" - ], - "oneOf": [ - { "required" : ["checksum_md5"] }, - { "required" : ["checksum_sha"] } - ] + "required": ["sample", "input"], + "oneOf": [{ "required": ["checksum_md5"] }, { "required": ["checksum_sha"] }] } } From 5444dd7b9f738f066a6dbc5acc059800d2ddca3d Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Mon, 22 Jun 2026 20:56:28 +0000 Subject: [PATCH 052/334] remove pipeline tag --- tests/main_full.nf.test | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/main_full.nf.test b/tests/main_full.nf.test index 47558e6..4d57d71 100644 --- a/tests/main_full.nf.test +++ b/tests/main_full.nf.test @@ -2,7 +2,6 @@ nextflow_pipeline { name "Test pipeline" script "../main.nf" - tag "pipeline" test("-profile test_full") { From 8c73c57419b3fd1566e949117ca656e1b8b15aaf Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Mon, 22 Jun 2026 20:57:06 +0000 Subject: [PATCH 053/334] fix: use test data base path param --- conf/test_full.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test_full.config b/conf/test_full.config index af7be2f..770e4ff 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,7 +17,7 @@ params { // Input data for full size test // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = "https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/samplesheet.csv" + input = params.pipelines_testdata_base_path + "datasync/test-data/samplesheet.csv" // Genome references genome = 'R64-1-1' From 70ba6535139b0d86e8d0337980601a96ea8f1651 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 23 Jun 2026 02:08:12 +0200 Subject: [PATCH 054/334] Add comparechecksum module and compare input md5 and shasums against the generated --- modules/local/comparechecksum/environment.yml | 9 ++ modules/local/comparechecksum/main.nf | 36 +++++ modules/local/comparechecksum/meta.yml | 57 ++++++++ .../templates/comparechecksum.R | 125 ++++++++++++++++++ .../local/comparechecksum/tests/main.nf.test | 73 ++++++++++ modules/local/comparechecksum/tests/tags.yml | 2 + .../utils_nfcore_datasync_pipeline/main.nf | 13 ++ workflows/datasync.nf | 32 +++-- 8 files changed, 337 insertions(+), 10 deletions(-) create mode 100644 modules/local/comparechecksum/environment.yml create mode 100644 modules/local/comparechecksum/main.nf create mode 100644 modules/local/comparechecksum/meta.yml create mode 100644 modules/local/comparechecksum/templates/comparechecksum.R create mode 100644 modules/local/comparechecksum/tests/main.nf.test create mode 100644 modules/local/comparechecksum/tests/tags.yml diff --git a/modules/local/comparechecksum/environment.yml b/modules/local/comparechecksum/environment.yml new file mode 100644 index 0000000..bc58e27 --- /dev/null +++ b/modules/local/comparechecksum/environment.yml @@ -0,0 +1,9 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +name: "comparechecksum" +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - "YOUR-TOOL-HERE" diff --git a/modules/local/comparechecksum/main.nf b/modules/local/comparechecksum/main.nf new file mode 100644 index 0000000..f89355c --- /dev/null +++ b/modules/local/comparechecksum/main.nf @@ -0,0 +1,36 @@ +process COMPARECHECKSUM { + tag "$meta.id" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/f7/f7934a95be2b2e704032cadba8f19685f32d1cebc8febad71e20b43c4f896a7f/data': + 'community.wave.seqera.io/library/bioconductor-anndatar_bioconductor-rhdf5_r-base_r-leidenbase_pruned:4e3c0f41d63a217a' }" + + input: + tuple val(meta), path(input_checksum), path(generated_checksum) + + output: + tuple val(meta), path("*.csv"), emit: report + path "versions.yml" , emit: versions_comparechecksum, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + template 'comparechecksum.R' + + stub: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}.csv + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + r-base: \$(Rscript -e "cat(as.character(getRversion()))") + END_VERSIONS + """ +} diff --git a/modules/local/comparechecksum/meta.yml b/modules/local/comparechecksum/meta.yml new file mode 100644 index 0000000..a7e2049 --- /dev/null +++ b/modules/local/comparechecksum/meta.yml @@ -0,0 +1,57 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "comparechecksum" +## TODO nf-core: Add a description of the module and list keywords +description: write your description here +keywords: + - sort + - example + - genomics +tools: + - "comparechecksum": + ## TODO nf-core: Add a description and other details for the software below + description: "" + homepage: "" + documentation: "" + tool_dev_url: "" + doi: "" + licence: + +## TODO nf-core: Add a description of all of the variables used as input +input: + # Only when we have meta + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + + ## TODO nf-core: Delete / customise this example input + - bam: + type: file + description: Sorted BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + +## TODO nf-core: Add a description of all of the variables used as output +output: + #Only when we have meta + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + + - versions: + type: file + description: File containing software versions + pattern: "versions.yml" + ## TODO nf-core: Delete / customise this example output + - bam: + type: file + description: Sorted BAM/CRAM/SAM file + pattern: "*.{bam,cram,sam}" + +authors: + - "@delfiterradas" +maintainers: + - "@delfiterradas" diff --git a/modules/local/comparechecksum/templates/comparechecksum.R b/modules/local/comparechecksum/templates/comparechecksum.R new file mode 100644 index 0000000..4f7d7be --- /dev/null +++ b/modules/local/comparechecksum/templates/comparechecksum.R @@ -0,0 +1,125 @@ +#!/usr/bin/env Rscript + +# Template-interpolated by Nextflow +input_checksum <- "${input_checksum}" +generated_checksum <- "${generated_checksum}" +prefix <- "${prefix}" +md5sum <- "${meta.md5}" +shasum <- "${meta.sha}" + +read_checksum_file <- function(path) { + + x <- read.table( + path, + stringsAsFactors = FALSE, + fill = TRUE, + col.names = c("checksum", "file") + ) + + x +} + +# Read generated checksums +generated <- read_checksum_file(generated_checksum) + +# Case 1: expected checksum file provided +if (!is.na(input_checksum) && file.exists(input_checksum)) { + expected <- read_checksum_file(input_checksum) + + report <- merge( + expected, + generated, + by = "file", + all = TRUE, + suffixes = c("_expected", "_observed") + ) + + report\$status <- ifelse( + is.na(report\$checksum_expected), + "UNEXPECTED", + ifelse( + is.na(report\$checksum_observed), + "MISSING", + ifelse( + report\$checksum_expected == report\$checksum_observed, + "MATCH", + "MISMATCH" + ) + ) + ) + +# Case 2: use checksum stored in metadata +} else { + expected_checksum <- NULL + + if (!is.na(md5sum)) { + expected_checksum <- md5sum + } else if (!is.na(shasum)) { + expected_checksum <- shasum + } else { + stop( + "No checksum file provided and neither meta.md5 nor meta.sha are available" + ) + } + + if (nrow(generated) != 1) { + stop( + paste( + "Metadata checksum provided but generated checksum file contains", + nrow(generated), + "entries. Expected exactly one." + ) + ) + } + + report <- data.frame( + file = generated\$file, + checksum_expected = expected_checksum, + checksum_observed = generated\$checksum, + status = ifelse( + generated\$checksum == expected_checksum, + "MATCH", + "MISMATCH" + ), + stringsAsFactors = FALSE + ) +} + +# Write detailed report +write.csv( + report, + paste0(prefix, ".checksum_validation.csv"), + row.names = FALSE +) + +# Write summary report +summary_df <- as.data.frame(table(report\$status)) +colnames(summary_df) <- c("status", "count") + +write.csv( + summary_df, + paste0(prefix, ".checksum_summary.csv"), + row.names = FALSE +) + +# ------------------------------------------------------------ +# Versions file +# ------------------------------------------------------------ + +versions <- c( + "\"${task.process}\":", + paste0(" r-base: ", getRversion()), + paste0(" comparechecksum: ", getRversion()) +) + +writeLines( + versions, + "versions.yml" +) + +# ------------------------------------------------------------ +# Console summary +# ------------------------------------------------------------ + +cat("\nChecksum comparison complete\n") +print(table(report\$status)) \ No newline at end of file diff --git a/modules/local/comparechecksum/tests/main.nf.test b/modules/local/comparechecksum/tests/main.nf.test new file mode 100644 index 0000000..2cdc573 --- /dev/null +++ b/modules/local/comparechecksum/tests/main.nf.test @@ -0,0 +1,73 @@ +// TODO nf-core: Once you have added the required tests, please run the following command to build this file: +// nf-core modules test comparechecksum +nextflow_process { + + name "Test Process COMPARECHECKSUM" + script "../main.nf" + process "COMPARECHECKSUM" + + tag "modules" + tag "modules_nfcore" + tag "comparechecksum" + + // TODO nf-core: Change the test name preferably indicating the test-data and file-format used + test("sarscov2 - bam") { + + // TODO nf-core: If you are created a test for a chained module + // (the module requires running more than one process to generate the required output) + // add the 'setup' method here. + // You can find more information about how to use a 'setup' method in the docs (https://nf-co.re/docs/contributing/modules#steps-for-creating-nf-test-for-chained-modules). + + when { + process { + """ + // TODO nf-core: define inputs of the process here. Example: + + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.test_data['sarscov2']['illumina']['test_paired_end_bam'], checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + //TODO nf-core: Add all required assertions to verify the test output. + // See https://nf-co.re/docs/contributing/tutorials/nf-test_assertions for more information and examples. + ) + } + + } + + // TODO nf-core: Change the test name preferably indicating the test-data and file-format used but keep the " - stub" suffix. + test("sarscov2 - bam - stub") { + + options "-stub" + + when { + process { + """ + // TODO nf-core: define inputs of the process here. Example: + + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.test_data['sarscov2']['illumina']['test_paired_end_bam'], checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + //TODO nf-core: Add all required assertions to verify the test output. + ) + } + + } + +} diff --git a/modules/local/comparechecksum/tests/tags.yml b/modules/local/comparechecksum/tests/tags.yml new file mode 100644 index 0000000..b8eada6 --- /dev/null +++ b/modules/local/comparechecksum/tests/tags.yml @@ -0,0 +1,2 @@ +comparechecksum: + - "modules/nf-core/comparechecksum/**" diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index b3ce127..9eb9375 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -109,6 +109,19 @@ workflow PIPELINE_INITIALISATION { channel .fromList(samplesheetToList(input, "${projectDir}/assets/schema_input.json")) + .map { meta, input_path, checksum_md5, checksum_sha -> + def md5 = checksum_md5 ? checksum_md5.toString() : "" + def sha = checksum_sha ? checksum_sha.toString() : "" + if (md5.contains(".")) { + [ meta, input_path, file(checksum_md5), [] ] + } else if (sha.contains(".")) { + [ meta, input_path, [], file(checksum_sha) ] + } else if (!sha.isEmpty()) { + [ meta + [sha: sha], input_path, [], [] ] + } else if (!md5.isEmpty()) { + [ meta + [md5: md5], input_path, [], [] ] + } + } .set { ch_samplesheet } emit: diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 03718ba..7de4fa1 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -3,6 +3,7 @@ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +include { COMPARECHECKSUM } from '../modules/local/comparechecksum/main' include { MD5SUM } from '../modules/nf-core/md5sum/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' include { SHASUM } from '../modules/nf-core/shasum/main' @@ -37,26 +38,37 @@ workflow DATASYNC { checksum: [ meta, md5, sha ] } - ch_checksum = ch_samplesheet.checksum.branch { - meta, md5, sha -> - md5: !md5.isEmpty() - return [ meta, md5 ] - sha: !sha.isEmpty() - return [ meta, sha ] - } - MD5SUM( ch_samplesheet.input, false ) - MD5SUM.output.checksum.view() - SHASUM( ch_samplesheet.input, false ) + // Group input md5sum/shasum with their respective generated checksum + ch_checksum = ch_samplesheet.checksum + .join(MD5SUM.out.checksum) + .join(SHASUM.out.checksum) + .flatMap { meta, md5, sha, out_md5, out_sha -> + def checksum_tuple = [] + // If checksum is empty it will read the md5/shasum from meta + if (md5) { + checksum_tuple << tuple(meta, md5, out_md5) + } else if (sha) { + checksum_tuple << tuple(meta, sha, out_sha) + } else if (meta.md5) { + checksum_tuple << tuple(meta, md5, out_md5) + } else if (meta.sha) { + checksum_tuple << tuple(meta, sha, out_sha) + } + return checksum_tuple + } + + COMPARECHECKSUM(ch_checksum) + // // Collate and save software versions // From a361637056a79d7ff2a66f68f3524ff1f5409382 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 23 Jun 2026 02:14:41 +0200 Subject: [PATCH 055/334] Fix linting errors --- modules/local/comparechecksum/meta.yml | 8 +++----- modules/local/comparechecksum/templates/comparechecksum.R | 7 ------- modules/local/comparechecksum/tests/main.nf.test | 4 ++-- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/modules/local/comparechecksum/meta.yml b/modules/local/comparechecksum/meta.yml index a7e2049..d775233 100644 --- a/modules/local/comparechecksum/meta.yml +++ b/modules/local/comparechecksum/meta.yml @@ -1,5 +1,3 @@ ---- -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json name: "comparechecksum" ## TODO nf-core: Add a description of the module and list keywords description: write your description here @@ -15,7 +13,7 @@ tools: documentation: "" tool_dev_url: "" doi: "" - licence: + licence: ## TODO nf-core: Add a description of all of the variables used as input input: @@ -25,7 +23,7 @@ input: description: | Groovy Map containing sample information e.g. `[ id:'sample1', single_end:false ]` - + ## TODO nf-core: Delete / customise this example input - bam: type: file @@ -40,7 +38,7 @@ output: description: | Groovy Map containing sample information e.g. `[ id:'sample1', single_end:false ]` - + - versions: type: file description: File containing software versions diff --git a/modules/local/comparechecksum/templates/comparechecksum.R b/modules/local/comparechecksum/templates/comparechecksum.R index 4f7d7be..a47a761 100644 --- a/modules/local/comparechecksum/templates/comparechecksum.R +++ b/modules/local/comparechecksum/templates/comparechecksum.R @@ -116,10 +116,3 @@ writeLines( versions, "versions.yml" ) - -# ------------------------------------------------------------ -# Console summary -# ------------------------------------------------------------ - -cat("\nChecksum comparison complete\n") -print(table(report\$status)) \ No newline at end of file diff --git a/modules/local/comparechecksum/tests/main.nf.test b/modules/local/comparechecksum/tests/main.nf.test index 2cdc573..5c8648c 100644 --- a/modules/local/comparechecksum/tests/main.nf.test +++ b/modules/local/comparechecksum/tests/main.nf.test @@ -22,7 +22,7 @@ nextflow_process { process { """ // TODO nf-core: define inputs of the process here. Example: - + input[0] = [ [ id:'test', single_end:false ], // meta map file(params.test_data['sarscov2']['illumina']['test_paired_end_bam'], checkIfExists: true) @@ -51,7 +51,7 @@ nextflow_process { process { """ // TODO nf-core: define inputs of the process here. Example: - + input[0] = [ [ id:'test', single_end:false ], // meta map file(params.test_data['sarscov2']['illumina']['test_paired_end_bam'], checkIfExists: true) From 44499b95c4cc852fe5fd55f530dc34ac52813526 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:00:44 +0000 Subject: [PATCH 056/334] fix test_data base path --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 1b1ea2e..c383076 100644 --- a/nextflow.config +++ b/nextflow.config @@ -36,7 +36,7 @@ params { help_full = false show_hidden = false version = false - pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' + pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/datasync/' trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') // Config options From d4e0a4b9a42a1aa52c6906b531b46795f3fd94e1 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:00:57 +0000 Subject: [PATCH 057/334] remove debug print --- workflows/datasync.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index a184b77..82d05b0 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -44,7 +44,6 @@ workflow DATASYNC { sha: !sha.isEmpty() return [ meta, sha ] } - MD5SUM( ch_samplesheet.input, false From 9ba6d19999acb2e41d6f6710c4d424305c63b804 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:01:13 +0000 Subject: [PATCH 058/334] update test_full test --- tests/main_full.nf.test | 1 + tests/main_full.nf.test.snap | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/main_full.nf.test.snap diff --git a/tests/main_full.nf.test b/tests/main_full.nf.test index 47558e6..640485d 100644 --- a/tests/main_full.nf.test +++ b/tests/main_full.nf.test @@ -3,6 +3,7 @@ nextflow_pipeline { name "Test pipeline" script "../main.nf" tag "pipeline" + profile "test_full" test("-profile test_full") { diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap new file mode 100644 index 0000000..b8c1577 --- /dev/null +++ b/tests/main_full.nf.test.snap @@ -0,0 +1,45 @@ +{ + "-profile test_full": { + "content": [ + { + "MD5SUM": { + "md5sum": 9.5 + }, + "SHASUM": { + "sha256sum": 9.5 + }, + "Workflow": { + "nf-core/datasync": "v1.0dev" + } + }, + [ + "md5sum", + "md5sum/demultiplex.md5", + "multiqc", + "multiqc/multiqc_data", + "multiqc/multiqc_data/llms-full.txt", + "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc.parquet", + "multiqc/multiqc_data/multiqc_citations.txt", + "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_datasync_software_mqc_versions.yml", + "shasum", + "shasum/demultiplex.sha256" + ], + [ + "demultiplex.md5:md5,d949186254af955f49ad9c8c0ea2a33c", + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "demultiplex.sha256:md5,db74d30dff39da108b2f9dc0cdc90779" + ] + ], + "timestamp": "2026-06-23T15:41:43.847937556", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.4" + } + } +} \ No newline at end of file From a2922fe8451c60797e34415122e5f3892061c92c Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:01:27 +0000 Subject: [PATCH 059/334] make validation columns optional --- assets/schema_input.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/assets/schema_input.json b/assets/schema_input.json index 7dfd8d2..2a3472b 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -32,10 +32,6 @@ "required": [ "sample", "input" - ], - "anyOf": [ - { "required" : ["checksum_md5"] }, - { "required" : ["checksum_sha"] } ] } } From 00c6505f487d0b1e4a56e6ed690d44066880d5b0 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:01:46 +0000 Subject: [PATCH 060/334] fix samplesheet input path --- conf/test_full.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/test_full.config b/conf/test_full.config index af7be2f..b6ad8f0 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,7 +17,7 @@ params { // Input data for full size test // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = "https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/samplesheet.csv" + input = params.pipelines_testdata_base_path + "test-data/samplesheet.csv" // Genome references genome = 'R64-1-1' From f2114d4858f590b31fe7f22d019aef959ad6e65e Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:02:01 +0000 Subject: [PATCH 061/334] remove md5 test file --- assets/checksum.md5 | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 assets/checksum.md5 diff --git a/assets/checksum.md5 b/assets/checksum.md5 deleted file mode 100644 index b851672..0000000 --- a/assets/checksum.md5 +++ /dev/null @@ -1,21 +0,0 @@ -6cae999421b3107d31aaee312a67b2b4 BWAIndex/genome.fa.pac -dee21a414c8c9435c516ce51453eac69 BWAIndex/genome.fa.ann -a6da8681616c05eb542f1d91606a7b2f BWAIndex/genome.fa -6cae999421b3107d31aaee312a67b2b4 BWAIndex/version0.6.0/genome.fa.pac -dee21a414c8c9435c516ce51453eac69 BWAIndex/version0.6.0/genome.fa.ann -a6da8681616c05eb542f1d91606a7b2f BWAIndex/version0.6.0/genome.fa -b5666883af79e600563852fbd6db60ff BWAIndex/version0.6.0/genome.fa.sa -54d052dc82eee7a34465b8e8a8989631 BWAIndex/version0.6.0/genome.fa.amb -88712af9626d5cbba82007cf8e3f90b2 BWAIndex/version0.6.0/genome.fa.bwt -6cae999421b3107d31aaee312a67b2b4 BWAIndex/version0.5.x/genome.fa.pac -dee21a414c8c9435c516ce51453eac69 BWAIndex/version0.5.x/genome.fa.ann -a6da8681616c05eb542f1d91606a7b2f BWAIndex/version0.5.x/genome.fa -826ca9f3dd61da0e50e869ead26edd99 BWAIndex/version0.5.x/genome.fa.rpac -08b6a8da1dae3f4d22e2e78887ddc9e4 BWAIndex/version0.5.x/genome.fa.rsa -456ac470698ac3ce1bb56110f00ac732 BWAIndex/version0.5.x/genome.fa.sa -54d052dc82eee7a34465b8e8a8989631 BWAIndex/version0.5.x/genome.fa.amb -d48c35964b0817176190aab0c8270e5d BWAIndex/version0.5.x/genome.fa.rbwt -9177d5f8c71ec47f65ccf0ab189ab408 BWAIndex/version0.5.x/genome.fa.bwt -b5666883af79e600563852fbd6db60ff BWAIndex/genome.fa.sa -54d052dc82eee7a34465b8e8a8989631 BWAIndex/genome.fa.amb -88712af9626d5cbba82007cf8e3f90b2 BWAIndex/genome.fa.bwt From 7d62585022e78236e33519756cd269b56abb28f3 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:02:18 +0000 Subject: [PATCH 062/334] replace for original samplesheet --- assets/samplesheet.csv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index e4ef522..82e35fd 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,3 @@ -sample,input,checksum_md5 -human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/,assets/checksum.md5 -test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz,f06e81ce1eb2d5424f88ca7f345ec0d1 +sample,input +human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/ +test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz \ No newline at end of file From bff43f77774dc84fe082824e72fe11eb235619a9 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:22:58 +0000 Subject: [PATCH 063/334] update default snapshot --- tests/default.nf.test.snap | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index a20e40d..5ac94b6 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -14,13 +14,8 @@ }, [ "md5sum", - "md5sum/GenomeSize.xml.md5", - "md5sum/GenomeSize.xml.old.md5", - "md5sum/genome.dict.md5", - "md5sum/genome.dict.old.md5", - "md5sum/genome.fa.fai.md5", - "md5sum/genome.fa.md5", - "md5sum/test2_1.fastq.gz.md5", + "md5sum/human_grch38_sequence.md5", + "md5sum/test_fastq.md5", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", @@ -34,33 +29,18 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "shasum", - "shasum/GenomeSize.xml.old.sha256", - "shasum/GenomeSize.xml.sha256", - "shasum/genome.dict.old.sha256", - "shasum/genome.dict.sha256", - "shasum/genome.fa.fai.sha256", - "shasum/genome.fa.sha256", - "shasum/test2_1.fastq.gz.sha256" + "shasum/human_grch38_sequence.sha256", + "shasum/test_fastq.sha256" ], [ - "GenomeSize.xml.md5:md5,0c1c07f13ddcd6f479f8312b0c7d9843", - "GenomeSize.xml.old.md5:md5,8273ac6aa130edf9e628cf0cf2566855", - "genome.dict.md5:md5,cf34a65ce7a3e827c66eadb2d5522551", - "genome.dict.old.md5:md5,4dfbb85cd00197e03f43f999b39addab", - "genome.fa.fai.md5:md5,8fc26b8f3ce6b83f9860ae9a2347d046", - "genome.fa.md5:md5,cca9026fcc32a789c00d9070edac5809", - "test2_1.fastq.gz.md5:md5,145df327e566f16b545fbca236f9bb62", + "human_grch38_sequence.md5:md5,9a8b3f1bfffd9f0d4ff90c03851dae64", + "test_fastq.md5:md5,145df327e566f16b545fbca236f9bb62", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "GenomeSize.xml.old.sha256:md5,068e91cdcc084710caf61a0859ac2be9", - "GenomeSize.xml.sha256:md5,e7a175f04cab11ce0a245133d70de9fb", - "genome.dict.old.sha256:md5,77492c77f911887b269de347e157d4ca", - "genome.dict.sha256:md5,0021eaba625d4dc9fcec55eb7384426e", - "genome.fa.fai.sha256:md5,99f227079c0fd354f272c0046482ff1a", - "genome.fa.sha256:md5,9bdb272c4b51342a0f139fbc14d0a57e", - "test2_1.fastq.gz.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" + "human_grch38_sequence.sha256:md5,809eee5059df78f56a9201ef1af8367b", + "test_fastq.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" ] ], - "timestamp": "2026-06-18T03:05:43.540206333", + "timestamp": "2026-06-23T16:22:23.074516015", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.4" From e6ce004840dfc8aa3463ae978a2b34856c2f32c7 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:44:49 +0000 Subject: [PATCH 064/334] run pre commit --- assets/samplesheet.csv | 2 +- assets/schema_input.json | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 82e35fd..55cd8f9 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,3 @@ sample,input human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/ -test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz \ No newline at end of file +test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz diff --git a/assets/schema_input.json b/assets/schema_input.json index 2a3472b..b2c4ddf 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -29,9 +29,6 @@ "errorMessage": "Checksum_sha cannot contain spaces" } }, - "required": [ - "sample", - "input" - ] + "required": ["sample", "input"] } } From 68e00d2dec7cbb4d87a6e39d861d8b47111f82df Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 23 Jun 2026 16:57:17 +0000 Subject: [PATCH 065/334] update default snapshot --- tests/default.nf.test.snap | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index e7ca513..0ef2a23 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -16,8 +16,6 @@ "md5sum", "md5sum/human_grch38_sequence.md5", "md5sum/test_fastq.md5", - "md5sum/human_grch38_sequence.md5", - "md5sum/test_fastq.md5", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", @@ -33,8 +31,6 @@ "shasum", "shasum/human_grch38_sequence.sha256", "shasum/test_fastq.sha256" - "shasum/human_grch38_sequence.sha256", - "shasum/test_fastq.sha256" ], [ "human_grch38_sequence.md5:md5,9a8b3f1bfffd9f0d4ff90c03851dae64", @@ -44,11 +40,10 @@ "test_fastq.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" ] ], - "timestamp": "2026-06-23T16:22:23.074516015", + "timestamp": "2026-06-23T16:56:56.622054559", "meta": { - "nf-test": "0.9.3", - "nextflow": "25.10.4" - }, - "timestamp": "2026-06-19T21:05:19.976503457" + "nf-test": "0.9.5", + "nextflow": "26.04.4" + } } } \ No newline at end of file From 24acf68ab5427eaacf4570746023f4e17088bd3d Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Tue, 23 Jun 2026 17:46:02 +0000 Subject: [PATCH 066/334] update test data base paht in schema --- nextflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 10b92c1..75bee3d 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -208,7 +208,7 @@ "type": "string", "fa_icon": "far fa-check-circle", "description": "Base URL or local path to location of pipeline test dataset files", - "default": "https://raw.githubusercontent.com/nf-core/test-datasets/", + "default": "https://raw.githubusercontent.com/nf-core/test-datasets/datasync/", "hidden": true }, "trace_report_suffix": { From 128044cb49d65034364a18bfe7517288095c3b84 Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Tue, 23 Jun 2026 17:46:14 +0000 Subject: [PATCH 067/334] update snapshot --- tests/main_full.nf.test.snap | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index b8c1577..d308a81 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -31,15 +31,15 @@ "shasum/demultiplex.sha256" ], [ - "demultiplex.md5:md5,d949186254af955f49ad9c8c0ea2a33c", + "demultiplex.md5:md5,ab5b41890200d7aed339157e7a898667", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "demultiplex.sha256:md5,db74d30dff39da108b2f9dc0cdc90779" + "demultiplex.sha256:md5,ee93070f17fc2392309c9b411958ca76" ] ], - "timestamp": "2026-06-23T15:41:43.847937556", + "timestamp": "2026-06-23T17:43:27.311534744", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.4" + "nextflow": "25.10.4" } } } \ No newline at end of file From f02371fee942085d70eeed2da5eaf8d0a0680bef Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Tue, 23 Jun 2026 17:54:21 +0000 Subject: [PATCH 068/334] update default snapshot --- tests/default.nf.test.snap | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 0ef2a23..1476e51 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -33,17 +33,17 @@ "shasum/test_fastq.sha256" ], [ - "human_grch38_sequence.md5:md5,9a8b3f1bfffd9f0d4ff90c03851dae64", + "human_grch38_sequence.md5:md5,5bfe720bd56b2849fe80c5f4e19b828d", "test_fastq.md5:md5,145df327e566f16b545fbca236f9bb62", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "human_grch38_sequence.sha256:md5,809eee5059df78f56a9201ef1af8367b", + "human_grch38_sequence.sha256:md5,977284c71f44223095224aba476805eb", "test_fastq.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" ] ], - "timestamp": "2026-06-23T16:56:56.622054559", + "timestamp": "2026-06-23T17:52:29.444424755", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.4" + "nextflow": "25.10.4" } } } \ No newline at end of file From 0b468d0d3668c7c5f97edbb73f748fbe4502a626 Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Tue, 23 Jun 2026 19:33:56 +0000 Subject: [PATCH 069/334] ignore md5 and sha unstable results --- tests/.nftignore | 2 ++ tests/default.nf.test.snap | 8 ++------ tests/main_full.nf.test.snap | 6 ++---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/.nftignore b/tests/.nftignore index e128a12..912a033 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -10,3 +10,5 @@ multiqc/multiqc_plots/{svg,pdf,png}/*.{svg,pdf,png} multiqc/multiqc_report.html fastqc/*_fastqc.{html,zip} pipeline_info/*.{html,json,txt,yml} +md5sum/** +shasum/** \ No newline at end of file diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 1476e51..2c00759 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -33,14 +33,10 @@ "shasum/test_fastq.sha256" ], [ - "human_grch38_sequence.md5:md5,5bfe720bd56b2849fe80c5f4e19b828d", - "test_fastq.md5:md5,145df327e566f16b545fbca236f9bb62", - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "human_grch38_sequence.sha256:md5,977284c71f44223095224aba476805eb", - "test_fastq.sha256:md5,3407e7acd19b8bb0f0b731a046e7943f" + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-23T17:52:29.444424755", + "timestamp": "2026-06-23T19:18:17.852339994", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index d308a81..0f54dbb 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -31,12 +31,10 @@ "shasum/demultiplex.sha256" ], [ - "demultiplex.md5:md5,ab5b41890200d7aed339157e7a898667", - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "demultiplex.sha256:md5,ee93070f17fc2392309c9b411958ca76" + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-23T17:43:27.311534744", + "timestamp": "2026-06-23T19:32:18.469702006", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" From 8a3e5d634a2d38891e87cd0514f212d2a4fef10e Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Tue, 23 Jun 2026 19:36:18 +0000 Subject: [PATCH 070/334] fix: add new line at the end of file --- tests/.nftignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/.nftignore b/tests/.nftignore index 912a033..18b80cb 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -11,4 +11,4 @@ multiqc/multiqc_report.html fastqc/*_fastqc.{html,zip} pipeline_info/*.{html,json,txt,yml} md5sum/** -shasum/** \ No newline at end of file +shasum/** From 27e038ce0a274c43c0d54971229d50db50f20152 Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Tue, 23 Jun 2026 19:57:25 +0000 Subject: [PATCH 071/334] update shasum module --- modules.json | 2 +- modules/nf-core/shasum/main.nf | 38 +++++++++++++---- modules/nf-core/shasum/meta.yml | 9 +++- modules/nf-core/shasum/tests/main.nf.test | 33 ++++++++++++++- .../nf-core/shasum/tests/main.nf.test.snap | 42 ++++++++++++++++--- 5 files changed, 104 insertions(+), 20 deletions(-) diff --git a/modules.json b/modules.json index a6c41ad..711f257 100644 --- a/modules.json +++ b/modules.json @@ -17,7 +17,7 @@ }, "shasum": { "branch": "master", - "git_sha": "ef2ee0358c7d03231834aeac816991aeb20debd7", + "git_sha": "429d56ab5b5879549f71bf9905104f39d0c3bff4", "installed_by": ["modules"] } } diff --git a/modules/nf-core/shasum/main.nf b/modules/nf-core/shasum/main.nf index b79d387..65dffad 100644 --- a/modules/nf-core/shasum/main.nf +++ b/modules/nf-core/shasum/main.nf @@ -9,6 +9,7 @@ process SHASUM { input: tuple val(meta), path(files) + val as_separate_files output: tuple val(meta), path("*.sha256"), emit: checksum @@ -20,16 +21,35 @@ process SHASUM { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - """ - find -L * -type f \\ - ! -name '*.sha256' \\ - -exec sha256sum ${args} "{}" + \\ - > ${prefix}.sha256 - """ + // will only use when as_separate_files = false + if (as_separate_files) { + """ + find -L * -maxdepth 0 -type f \\ + ! -name '*.sha256' \\ + -exec sh -c 'sha256sum ${args} "\$1" > "\$1.sha256"' _ "{}" \\; + """ + } + else { + """ + find -L * -type f \\ + ! -name '*.sha256' \\ + -exec sha256sum ${args} "{}" + \\ + > ${prefix}.sha256 + """ + } stub: def prefix = task.ext.prefix ?: "${meta.id}" - """ - touch ${prefix}.sha256 - """ + if (as_separate_files) { + """ + find -L * -type f \\ + ! -name '*.sha256' \\ + -exec sh -c 'touch "\$1.sha256"' _ "{}" \\; + """ + } + else { + """ + touch ${prefix}.sha256 + """ + } } diff --git a/modules/nf-core/shasum/meta.yml b/modules/nf-core/shasum/meta.yml index 327a4f0..e4b7648 100644 --- a/modules/nf-core/shasum/meta.yml +++ b/modules/nf-core/shasum/meta.yml @@ -18,11 +18,16 @@ input: description: | Groovy Map containing sample information e.g. [ id:'test', single_end:false ] - - file: + - files: type: file - description: Any file + description: Any number of files pattern: "*.*" ontologies: [] + - as_separate_files: + type: boolean + description: | + If true, each file will have its own shasum file. If false, all files will be + checksummed into a single shasum file. output: checksum: - - meta: diff --git a/modules/nf-core/shasum/tests/main.nf.test b/modules/nf-core/shasum/tests/main.nf.test index 02d2ac0..6e2d413 100644 --- a/modules/nf-core/shasum/tests/main.nf.test +++ b/modules/nf-core/shasum/tests/main.nf.test @@ -9,16 +9,44 @@ nextflow_process { tag "modules_nfcore" tag "shasum" - test("test-shasum") { + test("test-shasum, separate") { when { process { """ input[0] = [ [ id:'test', single_end:false ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true) + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] ] + input[1] = true + """ + } + } + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out)).match() } + ) + } + } + + test("test-shasum, combined") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) + ] + ] + input[1] = false """ } } @@ -42,6 +70,7 @@ nextflow_process { [ id:'test', single_end:false ], // meta map file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true) ] + input[1] = true """ } diff --git a/modules/nf-core/shasum/tests/main.nf.test.snap b/modules/nf-core/shasum/tests/main.nf.test.snap index a86583b..df3986f 100644 --- a/modules/nf-core/shasum/tests/main.nf.test.snap +++ b/modules/nf-core/shasum/tests/main.nf.test.snap @@ -1,5 +1,5 @@ { - "test-shasum": { + "test-shasum, combined": { "content": [ { "checksum": [ @@ -8,7 +8,7 @@ "id": "test", "single_end": false }, - "test.paired_end.bam.sha256:md5,138a19e100f09fc975ea1b717da9b6dd" + "test.sha256:md5,cbe368d92c146935e6d72a00c2c2c804" ] ], "versions_sha256sum": [ @@ -20,10 +20,10 @@ ] } ], - "timestamp": "2026-05-03T20:43:40.688253838", + "timestamp": "2026-06-19T13:40:52.588704139", "meta": { "nf-test": "0.9.5", - "nextflow": "24.10.4" + "nextflow": "26.04.4" } }, "test-shasum - stub": { @@ -47,10 +47,40 @@ ] } ], - "timestamp": "2026-05-03T20:43:46.125782074", + "timestamp": "2026-06-19T13:40:59.232985121", "meta": { "nf-test": "0.9.5", - "nextflow": "24.10.4" + "nextflow": "26.04.4" + } + }, + "test-shasum, separate": { + "content": [ + { + "checksum": [ + [ + { + "id": "test", + "single_end": false + }, + [ + "test_1.fastq.gz.sha256:md5,d200e9d01dfc874b9c5efe894181b430", + "test_2.fastq.gz.sha256:md5,0035d52e9b642206858b826f2b49d7a3" + ] + ] + ], + "versions_sha256sum": [ + [ + "SHASUM", + "sha256sum", + "9.5" + ] + ] + } + ], + "timestamp": "2026-06-19T13:40:45.551657784", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.4" } } } \ No newline at end of file From dd9afc4442e0b43b6a7e1209ef2f4a20a36c233c Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Tue, 23 Jun 2026 20:04:06 +0000 Subject: [PATCH 072/334] fix: update shasum input --- workflows/datasync.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 82d05b0..cb4d985 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -50,7 +50,8 @@ workflow DATASYNC { ) SHASUM( - ch_samplesheet.input + ch_samplesheet.input, + false ) // From d9e811c98c3c4705694771f38af5b53e30836913 Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Tue, 23 Jun 2026 21:51:28 +0000 Subject: [PATCH 073/334] feat: implement rclone module for data syncing - Add RCLONE process to copy data from source to output path - Preserve source structure (files and folders) at destination - Add output_path parameter to nextflow_schema.json - Integrate rclone module into datasync workflow - Create supporting environment and metadata files --- AGENTS.md | 1 + main.nf | 1 + modules/nf-core/rclone/environment.yml | 7 ++++ modules/nf-core/rclone/main.nf | 46 ++++++++++++++++++++++++ modules/nf-core/rclone/meta.yml | 49 ++++++++++++++++++++++++++ nextflow_schema.json | 6 ++++ workflows/datasync.nf | 10 ++++++ 7 files changed, 120 insertions(+) create mode 120000 AGENTS.md create mode 100644 modules/nf-core/rclone/environment.yml create mode 100644 modules/nf-core/rclone/main.nf create mode 100644 modules/nf-core/rclone/meta.yml diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 0000000..2a61453 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +/home/as32149/agents/AGENTS.md \ No newline at end of file diff --git a/main.nf b/main.nf index 637723e..6e3d2d8 100644 --- a/main.nf +++ b/main.nf @@ -56,6 +56,7 @@ workflow NFCORE_DATASYNC { params.multiqc_logo, params.multiqc_methods_description, params.outdir, + params.rclone_output_path, ) emit: multiqc_report = DATASYNC.out.multiqc_report // channel: /path/to/multiqc_report.html diff --git a/modules/nf-core/rclone/environment.yml b/modules/nf-core/rclone/environment.yml new file mode 100644 index 0000000..d6f401d --- /dev/null +++ b/modules/nf-core/rclone/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::rclone=1.65.0 diff --git a/modules/nf-core/rclone/main.nf b/modules/nf-core/rclone/main.nf new file mode 100644 index 0000000..f151729 --- /dev/null +++ b/modules/nf-core/rclone/main.nf @@ -0,0 +1,46 @@ +process RCLONE { + tag "${meta.id}" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/6d/6d2dd2b3b0c1b1c6c8f7d5e3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4/data' + : 'rclone/rclone:latest'}" + + input: + tuple val(meta), path(source_path) + val destination_path + + output: + tuple val(meta), env(COPY_STATUS), emit: copy_status + tuple val("${task.process}"), val('rclone'), env(RCLONE_VERSION), topic: versions, emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '--verbose' + """ + # Get rclone version + RCLONE_VERSION=\$(rclone version | head -n1 | sed 's/rclone v//') + + # Prepare destination with same structure as source + DEST="${destination_path}/\$(basename ${source_path})" + + # Run rclone copy command + rclone copy ${args} "${source_path}" "\${DEST}" + + # Set status + if [ \$? -eq 0 ]; then + COPY_STATUS="success" + else + COPY_STATUS="failed" + fi + """ + + stub: + """ + RCLONE_VERSION="1.65.0" + COPY_STATUS="success" + """ +} diff --git a/modules/nf-core/rclone/meta.yml b/modules/nf-core/rclone/meta.yml new file mode 100644 index 0000000..3aea592 --- /dev/null +++ b/modules/nf-core/rclone/meta.yml @@ -0,0 +1,49 @@ +name: "rclone" +description: Copy data using Rclone to a specified output path +keywords: + - rclone + - copy + - sync + - data-transfer +tools: + - "rclone": + description: Rclone is a command line program to manage files on cloud storage + homepage: "https://rclone.org/" + documentation: "https://rclone.org/docs/" + licence: + - "MIT" + identifier: "" +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - source_path: + type: path + description: Source path to copy from (can be local or remote path) + - destination_path: + type: string + description: | + Destination base path where data will be copied to. Sample ID will be appended. + Can be local path or remote storage path (s3://, gs://, etc.) +output: + copy_status: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - copy_status: + type: string + description: Status of the copy operation (success/failed) + versions: + - - ${task.process}: + type: string + description: The name of the process + - rclone: + type: string + description: The name of the tool + - "*.version.txt": + type: file + description: File containing software version diff --git a/nextflow_schema.json b/nextflow_schema.json index 10b92c1..b68abc4 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -40,6 +40,12 @@ "type": "string", "description": "MultiQC report title. Printed as page header, used for filename if not otherwise specified.", "fa_icon": "fas fa-file-signature" + }, + "rclone_output_path": { + "type": "string", + "description": "Output path for Rclone data copying. Can be local path or remote storage path (s3://, gs://, etc.).", + "help_text": "Specify the destination path where data from the samplesheet will be copied to using Rclone. Sample IDs will be appended to this path. Supports local paths and cloud storage paths.", + "fa_icon": "fas fa-cloud-upload-alt" } } }, diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 6e6c910..258b673 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -5,6 +5,7 @@ */ include { MD5SUM } from '../modules/nf-core/md5sum/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' +include { RCLONE } from '../modules/nf-core/rclone/main' include { SHASUM } from '../modules/nf-core/shasum/main' include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' @@ -25,6 +26,7 @@ workflow DATASYNC { multiqc_logo multiqc_methods_description outdir + rclone_output_path main: @@ -40,6 +42,14 @@ workflow DATASYNC { ch_samplesheet.transpose() ) + // + // MODULE: Rclone data copying + // + RCLONE( + ch_samplesheet.input, + rclone_output_path + ) + // // Collate and save software versions // From f4c8a7faab00bf31d5e9cffc0162afc7f44f7cdc Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 24 Jun 2026 17:57:52 +0200 Subject: [PATCH 074/334] Accept only checksum files --- assets/{checksum.md5 => BWAIndex.tsv} | 0 assets/fastq.tsv | 1 + assets/samplesheet.csv | 4 ++-- assets/schema_input.json | 8 +++++--- .../local/utils_nfcore_datasync_pipeline/main.nf | 13 ------------- workflows/datasync.nf | 8 +++----- 6 files changed, 11 insertions(+), 23 deletions(-) rename assets/{checksum.md5 => BWAIndex.tsv} (100%) create mode 100644 assets/fastq.tsv diff --git a/assets/checksum.md5 b/assets/BWAIndex.tsv similarity index 100% rename from assets/checksum.md5 rename to assets/BWAIndex.tsv diff --git a/assets/fastq.tsv b/assets/fastq.tsv new file mode 100644 index 0000000..f7bfbcc --- /dev/null +++ b/assets/fastq.tsv @@ -0,0 +1 @@ +f06e81ce1eb2d5424f88ca7f345ec0d1 test2_1.fastq.gz \ No newline at end of file diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index e4ef522..49d1849 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,3 @@ sample,input,checksum_md5 -human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/,assets/checksum.md5 -test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz,f06e81ce1eb2d5424f88ca7f345ec0d1 +human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/,assets/BWAIndex.tsv +test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz,assets/fastq.tsv diff --git a/assets/schema_input.json b/assets/schema_input.json index 2656a6a..dab918f 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -20,16 +20,18 @@ }, "checksum_md5": { "type": "string", - "pattern": "^\\S+$", + "format": "file-path", + "pattern": "^\\S+\\.(csv|tsv)$", "errorMessage": "Checksum_md5 cannot contain spaces" }, "checksum_sha": { "type": "string", - "pattern": "^\\S+$", + "format": "file-path", + "pattern": "^\\S+\\.(csv|tsv)$", "errorMessage": "Checksum_sha cannot contain spaces" } }, "required": ["sample", "input"], - "oneOf": [{ "required": ["checksum_md5"] }, { "required": ["checksum_sha"] }] + "anyOf": [{ "required": ["checksum_md5"] }, { "required": ["checksum_sha"] }] } } diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 9eb9375..b3ce127 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -109,19 +109,6 @@ workflow PIPELINE_INITIALISATION { channel .fromList(samplesheetToList(input, "${projectDir}/assets/schema_input.json")) - .map { meta, input_path, checksum_md5, checksum_sha -> - def md5 = checksum_md5 ? checksum_md5.toString() : "" - def sha = checksum_sha ? checksum_sha.toString() : "" - if (md5.contains(".")) { - [ meta, input_path, file(checksum_md5), [] ] - } else if (sha.contains(".")) { - [ meta, input_path, [], file(checksum_sha) ] - } else if (!sha.isEmpty()) { - [ meta + [sha: sha], input_path, [], [] ] - } else if (!md5.isEmpty()) { - [ meta + [md5: md5], input_path, [], [] ] - } - } .set { ch_samplesheet } emit: diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 7de4fa1..c21837d 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -57,13 +57,11 @@ workflow DATASYNC { // If checksum is empty it will read the md5/shasum from meta if (md5) { checksum_tuple << tuple(meta, md5, out_md5) - } else if (sha) { - checksum_tuple << tuple(meta, sha, out_sha) - } else if (meta.md5) { - checksum_tuple << tuple(meta, md5, out_md5) - } else if (meta.sha) { + } + if (sha) { checksum_tuple << tuple(meta, sha, out_sha) } + return checksum_tuple } From 6d07ecc6bf2214f0a352b646bacc8a4d1cdbb4f0 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 24 Jun 2026 17:58:45 +0200 Subject: [PATCH 075/334] Update custom module's image --- modules/local/comparechecksum/environment.yml | 2 +- modules/local/comparechecksum/main.nf | 4 +- .../templates/comparechecksum.R | 78 +++++-------------- 3 files changed, 21 insertions(+), 63 deletions(-) diff --git a/modules/local/comparechecksum/environment.yml b/modules/local/comparechecksum/environment.yml index bc58e27..8ac9fde 100644 --- a/modules/local/comparechecksum/environment.yml +++ b/modules/local/comparechecksum/environment.yml @@ -6,4 +6,4 @@ channels: - bioconda - defaults dependencies: - - "YOUR-TOOL-HERE" + - conda-forge::r-base=4.2.1 diff --git a/modules/local/comparechecksum/main.nf b/modules/local/comparechecksum/main.nf index f89355c..f098859 100644 --- a/modules/local/comparechecksum/main.nf +++ b/modules/local/comparechecksum/main.nf @@ -4,8 +4,8 @@ process COMPARECHECKSUM { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/f7/f7934a95be2b2e704032cadba8f19685f32d1cebc8febad71e20b43c4f896a7f/data': - 'community.wave.seqera.io/library/bioconductor-anndatar_bioconductor-rhdf5_r-base_r-leidenbase_pruned:4e3c0f41d63a217a' }" + 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/48/483e9d9b3b07e5658792d579e230ad40ed18daf7b9ebfb4323c08570f92fd1d5/data': + 'community.wave.seqera.io/library/r-base:4.2.1--b0b5476e2e7a0872' }" input: tuple val(meta), path(input_checksum), path(generated_checksum) diff --git a/modules/local/comparechecksum/templates/comparechecksum.R b/modules/local/comparechecksum/templates/comparechecksum.R index a47a761..418bf67 100644 --- a/modules/local/comparechecksum/templates/comparechecksum.R +++ b/modules/local/comparechecksum/templates/comparechecksum.R @@ -4,8 +4,6 @@ input_checksum <- "${input_checksum}" generated_checksum <- "${generated_checksum}" prefix <- "${prefix}" -md5sum <- "${meta.md5}" -shasum <- "${meta.sha}" read_checksum_file <- function(path) { @@ -21,69 +19,29 @@ read_checksum_file <- function(path) { # Read generated checksums generated <- read_checksum_file(generated_checksum) +expected <- read_checksum_file(input_checksum) + +report <- merge( + expected, + generated, + by = "file", + all = TRUE, + suffixes = c("_expected", "_observed") +) -# Case 1: expected checksum file provided -if (!is.na(input_checksum) && file.exists(input_checksum)) { - expected <- read_checksum_file(input_checksum) - - report <- merge( - expected, - generated, - by = "file", - all = TRUE, - suffixes = c("_expected", "_observed") - ) - - report\$status <- ifelse( - is.na(report\$checksum_expected), - "UNEXPECTED", +report\$status <- ifelse( + is.na(report\$checksum_expected), + "UNEXPECTED", + ifelse( + is.na(report\$checksum_observed), + "MISSING", ifelse( - is.na(report\$checksum_observed), - "MISSING", - ifelse( - report\$checksum_expected == report\$checksum_observed, - "MATCH", - "MISMATCH" - ) - ) - ) - -# Case 2: use checksum stored in metadata -} else { - expected_checksum <- NULL - - if (!is.na(md5sum)) { - expected_checksum <- md5sum - } else if (!is.na(shasum)) { - expected_checksum <- shasum - } else { - stop( - "No checksum file provided and neither meta.md5 nor meta.sha are available" - ) - } - - if (nrow(generated) != 1) { - stop( - paste( - "Metadata checksum provided but generated checksum file contains", - nrow(generated), - "entries. Expected exactly one." - ) - ) - } - - report <- data.frame( - file = generated\$file, - checksum_expected = expected_checksum, - checksum_observed = generated\$checksum, - status = ifelse( - generated\$checksum == expected_checksum, + report\$checksum_expected == report\$checksum_observed, "MATCH", "MISMATCH" - ), - stringsAsFactors = FALSE + ) ) -} +) # Write detailed report write.csv( From 3ce943a7a524c6c0d574d5656ccd8505a6048976 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 25 Jun 2026 14:53:42 +0200 Subject: [PATCH 076/334] Add test profile for default test --- tests/default.nf.test | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/default.nf.test b/tests/default.nf.test index 7576e53..666d370 100644 --- a/tests/default.nf.test +++ b/tests/default.nf.test @@ -3,6 +3,7 @@ nextflow_pipeline { name "Test pipeline" script "../main.nf" tag "pipeline" + profile "test" test("-profile test") { From f1f792826cb314a06d8c296e70dc0b971daf1c6f Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 25 Jun 2026 18:45:17 +0200 Subject: [PATCH 077/334] Fix linting error --- assets/fastq.tsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/fastq.tsv b/assets/fastq.tsv index f7bfbcc..9d70186 100644 --- a/assets/fastq.tsv +++ b/assets/fastq.tsv @@ -1 +1 @@ -f06e81ce1eb2d5424f88ca7f345ec0d1 test2_1.fastq.gz \ No newline at end of file +f06e81ce1eb2d5424f88ca7f345ec0d1 test2_1.fastq.gz From a6bd1c27ac1dc6a0854e7d2f70fbb1fed180208a Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 26 Jun 2026 23:16:34 +0200 Subject: [PATCH 078/334] Remove test files from assets and update input paths in test profiles --- assets/BWAIndex.tsv | 21 --------------------- assets/fastq.tsv | 1 - assets/samplesheet.csv | 3 +-- conf/test.config | 2 +- conf/test_full.config | 2 +- 5 files changed, 3 insertions(+), 26 deletions(-) delete mode 100644 assets/BWAIndex.tsv delete mode 100644 assets/fastq.tsv diff --git a/assets/BWAIndex.tsv b/assets/BWAIndex.tsv deleted file mode 100644 index b851672..0000000 --- a/assets/BWAIndex.tsv +++ /dev/null @@ -1,21 +0,0 @@ -6cae999421b3107d31aaee312a67b2b4 BWAIndex/genome.fa.pac -dee21a414c8c9435c516ce51453eac69 BWAIndex/genome.fa.ann -a6da8681616c05eb542f1d91606a7b2f BWAIndex/genome.fa -6cae999421b3107d31aaee312a67b2b4 BWAIndex/version0.6.0/genome.fa.pac -dee21a414c8c9435c516ce51453eac69 BWAIndex/version0.6.0/genome.fa.ann -a6da8681616c05eb542f1d91606a7b2f BWAIndex/version0.6.0/genome.fa -b5666883af79e600563852fbd6db60ff BWAIndex/version0.6.0/genome.fa.sa -54d052dc82eee7a34465b8e8a8989631 BWAIndex/version0.6.0/genome.fa.amb -88712af9626d5cbba82007cf8e3f90b2 BWAIndex/version0.6.0/genome.fa.bwt -6cae999421b3107d31aaee312a67b2b4 BWAIndex/version0.5.x/genome.fa.pac -dee21a414c8c9435c516ce51453eac69 BWAIndex/version0.5.x/genome.fa.ann -a6da8681616c05eb542f1d91606a7b2f BWAIndex/version0.5.x/genome.fa -826ca9f3dd61da0e50e869ead26edd99 BWAIndex/version0.5.x/genome.fa.rpac -08b6a8da1dae3f4d22e2e78887ddc9e4 BWAIndex/version0.5.x/genome.fa.rsa -456ac470698ac3ce1bb56110f00ac732 BWAIndex/version0.5.x/genome.fa.sa -54d052dc82eee7a34465b8e8a8989631 BWAIndex/version0.5.x/genome.fa.amb -d48c35964b0817176190aab0c8270e5d BWAIndex/version0.5.x/genome.fa.rbwt -9177d5f8c71ec47f65ccf0ab189ab408 BWAIndex/version0.5.x/genome.fa.bwt -b5666883af79e600563852fbd6db60ff BWAIndex/genome.fa.sa -54d052dc82eee7a34465b8e8a8989631 BWAIndex/genome.fa.amb -88712af9626d5cbba82007cf8e3f90b2 BWAIndex/genome.fa.bwt diff --git a/assets/fastq.tsv b/assets/fastq.tsv deleted file mode 100644 index 9d70186..0000000 --- a/assets/fastq.tsv +++ /dev/null @@ -1 +0,0 @@ -f06e81ce1eb2d5424f88ca7f345ec0d1 test2_1.fastq.gz diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 49d1849..f61475a 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,3 +1,2 @@ sample,input,checksum_md5 -human_grch38_sequence,s3://ngi-igenomes/igenomes/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/,assets/BWAIndex.tsv -test_fastq,https://github.com/nf-core/test-datasets/raw/71ac9e72555f901d2864ccb27d534933411e3ed4/data/genomics/sarscov2/illumina/fastq/test2_1.fastq.gz,assets/fastq.tsv +sample,path/to/file,path/to/file diff --git a/conf/test.config b/conf/test.config index 3f62cb0..880dd04 100644 --- a/conf/test.config +++ b/conf/test.config @@ -25,6 +25,6 @@ params { // Input data // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = "${projectDir}/assets/samplesheet.csv" + input = params.pipelines_testdata_base_path + "test-data/samplesheet.csv" genome = 'R64-1-1' } diff --git a/conf/test_full.config b/conf/test_full.config index b6ad8f0..ae44f01 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -17,7 +17,7 @@ params { // Input data for full size test // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed - input = params.pipelines_testdata_base_path + "test-data/samplesheet.csv" + input = params.pipelines_testdata_base_path + "test-data/samplesheet_full.csv" // Genome references genome = 'R64-1-1' From 3e6ddf77f305ea8a5f0e747f1b5086ef54925dae Mon Sep 17 00:00:00 2001 From: zxBIB Date: Sun, 28 Jun 2026 22:22:39 +0200 Subject: [PATCH 079/334] Include external rclone external config --- main.nf | 1 + nextflow_schema.json | 8 ++++++++ workflows/datasync.nf | 9 ++++++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/main.nf b/main.nf index 6e3d2d8..de8ddc9 100644 --- a/main.nf +++ b/main.nf @@ -57,6 +57,7 @@ workflow NFCORE_DATASYNC { params.multiqc_methods_description, params.outdir, params.rclone_output_path, + params.rclone_config ) emit: multiqc_report = DATASYNC.out.multiqc_report // channel: /path/to/multiqc_report.html diff --git a/nextflow_schema.json b/nextflow_schema.json index f05354b..13d1e17 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -46,6 +46,14 @@ "description": "Output path for Rclone data copying. Can be local path or remote storage path (s3://, gs://, etc.).", "help_text": "Specify the destination path where data from the samplesheet will be copied to using Rclone. Sample IDs will be appended to this path. Supports local paths and cloud storage paths.", "fa_icon": "fas fa-cloud-upload-alt" + }, + "rclone_config": { + "type": "string", + "format": "file-path", + "exists": true, + "description": "Path to the rclone config file used for cloud storage authentication.", + "help_text": "Provide an rclone config file to support cloud providers such as AWS S3 or Azure Blob Storage. This file is loaded by rclone when copying data.", + "fa_icon": "fas fa-file" } } }, diff --git a/workflows/datasync.nf b/workflows/datasync.nf index eb0437a..23503c4 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -27,6 +27,7 @@ workflow DATASYNC { multiqc_methods_description outdir rclone_output_path + rclone_config main: @@ -35,7 +36,8 @@ workflow DATASYNC { ch_samplesheet = ch_samplesheet.multiMap { meta, input_path, md5, sha -> - input: [ meta, input_path ] + input: [ meta, input_path ] // staged input for MD5SUM / SHASUM + rclone: [ meta, input_path.toString() ] // raw URI for rclone checksum: [ meta, md5, sha ] } @@ -60,8 +62,9 @@ workflow DATASYNC { // MODULE: Rclone data copying // RCLONE( - ch_samplesheet.input, - rclone_output_path + ch_samplesheet.rclone, + rclone_output_path, + rclone_config ? file(rclone_config, checkIfExists: true) : null ) // From 110bb371856b07b022d6ceaf69ff86ae899ca5be Mon Sep 17 00:00:00 2001 From: zxBIB Date: Sun, 28 Jun 2026 22:25:39 +0200 Subject: [PATCH 080/334] Include Rclone ext args --- conf/modules.config | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/conf/modules.config b/conf/modules.config index f0b0d55..0ba18c5 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,6 +18,10 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] + withName: 'RCLONE' { + ext.args = '--transfers 16 --checkers 8 --s3-chunk-size 64M --no-check-certificate' + } + withName: 'MULTIQC' { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ From e0b452429d5f9b81a389bd6835a9a118d70c4e06 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Sun, 28 Jun 2026 22:28:13 +0200 Subject: [PATCH 081/334] update rclone module --- modules/nf-core/rclone/main.nf | 57 ++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/modules/nf-core/rclone/main.nf b/modules/nf-core/rclone/main.nf index f151729..00434d4 100644 --- a/modules/nf-core/rclone/main.nf +++ b/modules/nf-core/rclone/main.nf @@ -1,46 +1,55 @@ process RCLONE { + tag "${meta.id}" label 'process_low' conda "${moduleDir}/environment.yml" container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/6d/6d2dd2b3b0c1b1c6c8f7d5e3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4/data' - : 'rclone/rclone:latest'}" + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' + : 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be'}" input: - tuple val(meta), path(source_path) + tuple val(meta), val(source_path) val destination_path + path rclone_config output: - tuple val(meta), env(COPY_STATUS), emit: copy_status - tuple val("${task.process}"), val('rclone'), env(RCLONE_VERSION), topic: versions, emit: versions + tuple val(meta), path("rclone-copy.log"), emit: log + tuple val("${task.process}"), val('rclone'), eval("rclone version | head -n1 | sed 's/rclone v//'"), topic: versions, emit: versions when: task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '--verbose' - """ - # Get rclone version - RCLONE_VERSION=\$(rclone version | head -n1 | sed 's/rclone v//') - - # Prepare destination with same structure as source - DEST="${destination_path}/\$(basename ${source_path})" + def args = task.ext.args ?: '' + def configArg = rclone_config ? "--config '${rclone_config}'" : '' - # Run rclone copy command - rclone copy ${args} "${source_path}" "\${DEST}" - - # Set status - if [ \$? -eq 0 ]; then - COPY_STATUS="success" - else - COPY_STATUS="failed" - fi + """ + to_rclone_path() { + case "\$1" in + s3://*) echo "s3:\${1#s3://}" ;; + *) echo "\$1" ;; + esac + } + + SRC=\$(to_rclone_path "${source_path}") + DEST_BASE=\$(to_rclone_path "${destination_path}") + + SRC_CLEAN="\${SRC%/}" + DEST="\${DEST_BASE%/}/\$(basename "\${SRC_CLEAN}")" + + rclone ${configArg} copy ${args} \\ + --log-file rclone-copy.log \\ + --log-level INFO \\ + --stats 30s \\ + --stats-one-line \\ + --stats-log-level INFO \\ + --s3-env-auth \\ + "\${SRC}" "\${DEST}" """ stub: """ - RCLONE_VERSION="1.65.0" - COPY_STATUS="success" + touch rclone-copy.log """ -} +} \ No newline at end of file From bb37c5b3c897503781d1fbe755954d4e24a2fa79 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 29 Jun 2026 17:17:44 +0200 Subject: [PATCH 082/334] Update test snapshots --- tests/default.nf.test.snap | 23 +++++++++++++++++++++-- tests/main_full.nf.test.snap | 13 +++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 2c00759..5701727 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -2,6 +2,10 @@ "-profile test": { "content": [ { + "COMPARECHECKSUM": { + "r-base": "4.2.1", + "comparechecksum": "4.2.1" + }, "MD5SUM": { "md5sum": 9.5 }, @@ -13,7 +17,15 @@ } }, [ + "comparechecksum", + "comparechecksum/benchmark_bed.checksum_summary.csv", + "comparechecksum/benchmark_bed.checksum_validation.csv", + "comparechecksum/human_grch38_sequence.checksum_summary.csv", + "comparechecksum/human_grch38_sequence.checksum_validation.csv", + "comparechecksum/test_fastq.checksum_summary.csv", + "comparechecksum/test_fastq.checksum_validation.csv", "md5sum", + "md5sum/benchmark_bed.md5", "md5sum/human_grch38_sequence.md5", "md5sum/test_fastq.md5", "multiqc", @@ -29,17 +41,24 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "shasum", + "shasum/benchmark_bed.sha256", "shasum/human_grch38_sequence.sha256", "shasum/test_fastq.sha256" ], [ + "benchmark_bed.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", + "benchmark_bed.checksum_validation.csv:md5,d1e7087446c6138dba9929099787c5c9", + "human_grch38_sequence.checksum_summary.csv:md5,0a9cabfdbcf1ef9525e8a8582fdaedc7", + "human_grch38_sequence.checksum_validation.csv:md5,8ceee48b8cdae45ac8ea555fe122304f", + "test_fastq.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", + "test_fastq.checksum_validation.csv:md5,9f72112e05dc478eee7d3d56a6364cd0", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-23T19:18:17.852339994", + "timestamp": "2026-06-29T17:14:19.165257039", "meta": { "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 0f54dbb..4e66501 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -2,6 +2,10 @@ "-profile test_full": { "content": [ { + "COMPARECHECKSUM": { + "r-base": "4.2.1", + "comparechecksum": "4.2.1" + }, "MD5SUM": { "md5sum": 9.5 }, @@ -13,6 +17,9 @@ } }, [ + "comparechecksum", + "comparechecksum/demultiplex.checksum_summary.csv", + "comparechecksum/demultiplex.checksum_validation.csv", "md5sum", "md5sum/demultiplex.md5", "multiqc", @@ -31,13 +38,15 @@ "shasum/demultiplex.sha256" ], [ + "demultiplex.checksum_summary.csv:md5,13fc2d64b33a06bf80694b06998ba7c1", + "demultiplex.checksum_validation.csv:md5,205760aabd99d02b7b61c250677f0b32", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-23T19:32:18.469702006", + "timestamp": "2026-06-29T17:16:26.763106224", "meta": { "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nextflow": "26.04.1" } } } \ No newline at end of file From 1a1511877eb136b1be842760a8f2c9650099867f Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 29 Jun 2026 17:30:54 +0200 Subject: [PATCH 083/334] Delete test for comparechecksum and split output into two channels --- modules/local/comparechecksum/main.nf | 1 + .../local/comparechecksum/tests/main.nf.test | 73 ------------------- modules/local/comparechecksum/tests/tags.yml | 2 - 3 files changed, 1 insertion(+), 75 deletions(-) delete mode 100644 modules/local/comparechecksum/tests/main.nf.test delete mode 100644 modules/local/comparechecksum/tests/tags.yml diff --git a/modules/local/comparechecksum/main.nf b/modules/local/comparechecksum/main.nf index f098859..9fba4fc 100644 --- a/modules/local/comparechecksum/main.nf +++ b/modules/local/comparechecksum/main.nf @@ -12,6 +12,7 @@ process COMPARECHECKSUM { output: tuple val(meta), path("*.csv"), emit: report + tuple val(meta), path("*.csv"), emit: summary_report path "versions.yml" , emit: versions_comparechecksum, topic: versions when: diff --git a/modules/local/comparechecksum/tests/main.nf.test b/modules/local/comparechecksum/tests/main.nf.test deleted file mode 100644 index 5c8648c..0000000 --- a/modules/local/comparechecksum/tests/main.nf.test +++ /dev/null @@ -1,73 +0,0 @@ -// TODO nf-core: Once you have added the required tests, please run the following command to build this file: -// nf-core modules test comparechecksum -nextflow_process { - - name "Test Process COMPARECHECKSUM" - script "../main.nf" - process "COMPARECHECKSUM" - - tag "modules" - tag "modules_nfcore" - tag "comparechecksum" - - // TODO nf-core: Change the test name preferably indicating the test-data and file-format used - test("sarscov2 - bam") { - - // TODO nf-core: If you are created a test for a chained module - // (the module requires running more than one process to generate the required output) - // add the 'setup' method here. - // You can find more information about how to use a 'setup' method in the docs (https://nf-co.re/docs/contributing/modules#steps-for-creating-nf-test-for-chained-modules). - - when { - process { - """ - // TODO nf-core: define inputs of the process here. Example: - - input[0] = [ - [ id:'test', single_end:false ], // meta map - file(params.test_data['sarscov2']['illumina']['test_paired_end_bam'], checkIfExists: true) - ] - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - //TODO nf-core: Add all required assertions to verify the test output. - // See https://nf-co.re/docs/contributing/tutorials/nf-test_assertions for more information and examples. - ) - } - - } - - // TODO nf-core: Change the test name preferably indicating the test-data and file-format used but keep the " - stub" suffix. - test("sarscov2 - bam - stub") { - - options "-stub" - - when { - process { - """ - // TODO nf-core: define inputs of the process here. Example: - - input[0] = [ - [ id:'test', single_end:false ], // meta map - file(params.test_data['sarscov2']['illumina']['test_paired_end_bam'], checkIfExists: true) - ] - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - //TODO nf-core: Add all required assertions to verify the test output. - ) - } - - } - -} diff --git a/modules/local/comparechecksum/tests/tags.yml b/modules/local/comparechecksum/tests/tags.yml deleted file mode 100644 index b8eada6..0000000 --- a/modules/local/comparechecksum/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -comparechecksum: - - "modules/nf-core/comparechecksum/**" From 4a0eece8b0e2e685e5b0fde8540dae226e986f09 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 29 Jun 2026 18:11:22 +0200 Subject: [PATCH 084/334] Update snapshot --- tests/main_full.nf.test.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 4e66501..aafe5ec 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -38,12 +38,12 @@ "shasum/demultiplex.sha256" ], [ - "demultiplex.checksum_summary.csv:md5,13fc2d64b33a06bf80694b06998ba7c1", + "demultiplex.checksum_summary.csv:md5,5ab7359b25dcb4e6c6f5a7eb1687a2dc", "demultiplex.checksum_validation.csv:md5,205760aabd99d02b7b61c250677f0b32", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-29T17:16:26.763106224", + "timestamp": "2026-06-29T18:09:37.827179822", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From 675ad035489c4f1c108dd1cca45704d8a86e0830 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 29 Jun 2026 20:12:46 +0200 Subject: [PATCH 085/334] Update default test snapshot --- tests/default.nf.test.snap | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 5701727..07b62a1 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -18,15 +18,15 @@ }, [ "comparechecksum", + "comparechecksum/Illumina_annotation.checksum_summary.csv", + "comparechecksum/Illumina_annotation.checksum_validation.csv", "comparechecksum/benchmark_bed.checksum_summary.csv", "comparechecksum/benchmark_bed.checksum_validation.csv", - "comparechecksum/human_grch38_sequence.checksum_summary.csv", - "comparechecksum/human_grch38_sequence.checksum_validation.csv", "comparechecksum/test_fastq.checksum_summary.csv", "comparechecksum/test_fastq.checksum_validation.csv", "md5sum", + "md5sum/Illumina_annotation.md5", "md5sum/benchmark_bed.md5", - "md5sum/human_grch38_sequence.md5", "md5sum/test_fastq.md5", "multiqc", "multiqc/multiqc_data", @@ -41,21 +41,21 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "shasum", + "shasum/Illumina_annotation.sha256", "shasum/benchmark_bed.sha256", - "shasum/human_grch38_sequence.sha256", "shasum/test_fastq.sha256" ], [ + "Illumina_annotation.checksum_summary.csv:md5,da71db43566c677ddc32186e53d4f30e", + "Illumina_annotation.checksum_validation.csv:md5,9032cc5084168ca56d501269fc1021e8", "benchmark_bed.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", "benchmark_bed.checksum_validation.csv:md5,d1e7087446c6138dba9929099787c5c9", - "human_grch38_sequence.checksum_summary.csv:md5,0a9cabfdbcf1ef9525e8a8582fdaedc7", - "human_grch38_sequence.checksum_validation.csv:md5,8ceee48b8cdae45ac8ea555fe122304f", "test_fastq.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", "test_fastq.checksum_validation.csv:md5,9f72112e05dc478eee7d3d56a6364cd0", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-29T17:14:19.165257039", + "timestamp": "2026-06-29T20:12:22.962884142", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From da29b06fc6804c0fc1874d56247cc0625263756d Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 29 Jun 2026 20:34:38 +0200 Subject: [PATCH 086/334] Sort output in comparechecksum --- modules/local/comparechecksum/templates/comparechecksum.R | 4 ++-- tests/main_full.nf.test.snap | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/local/comparechecksum/templates/comparechecksum.R b/modules/local/comparechecksum/templates/comparechecksum.R index 418bf67..9d323a3 100644 --- a/modules/local/comparechecksum/templates/comparechecksum.R +++ b/modules/local/comparechecksum/templates/comparechecksum.R @@ -45,7 +45,7 @@ report\$status <- ifelse( # Write detailed report write.csv( - report, + report[order(report\$file), ], paste0(prefix, ".checksum_validation.csv"), row.names = FALSE ) @@ -55,7 +55,7 @@ summary_df <- as.data.frame(table(report\$status)) colnames(summary_df) <- c("status", "count") write.csv( - summary_df, + summary_df[order(summary_df\$status), ], paste0(prefix, ".checksum_summary.csv"), row.names = FALSE ) diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index aafe5ec..17eb5e3 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -38,12 +38,12 @@ "shasum/demultiplex.sha256" ], [ - "demultiplex.checksum_summary.csv:md5,5ab7359b25dcb4e6c6f5a7eb1687a2dc", - "demultiplex.checksum_validation.csv:md5,205760aabd99d02b7b61c250677f0b32", + "demultiplex.checksum_summary.csv:md5,13fc2d64b33a06bf80694b06998ba7c1", + "demultiplex.checksum_validation.csv:md5,e5d57d106f96b536608e1ff06552df09", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-29T18:09:37.827179822", + "timestamp": "2026-06-29T20:22:24.028086784", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From 7ff2d287454d58dc0855e51f079f58c5ceb6da97 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 29 Jun 2026 21:08:59 +0200 Subject: [PATCH 087/334] Update meta and apply suggestions to comparechecksum module --- modules/local/comparechecksum/environment.yml | 1 - modules/local/comparechecksum/meta.yml | 101 ++++++++++-------- .../templates/comparechecksum.R | 3 +- 3 files changed, 59 insertions(+), 46 deletions(-) diff --git a/modules/local/comparechecksum/environment.yml b/modules/local/comparechecksum/environment.yml index 8ac9fde..56563a9 100644 --- a/modules/local/comparechecksum/environment.yml +++ b/modules/local/comparechecksum/environment.yml @@ -4,6 +4,5 @@ name: "comparechecksum" channels: - conda-forge - bioconda - - defaults dependencies: - conda-forge::r-base=4.2.1 diff --git a/modules/local/comparechecksum/meta.yml b/modules/local/comparechecksum/meta.yml index d775233..0d50b52 100644 --- a/modules/local/comparechecksum/meta.yml +++ b/modules/local/comparechecksum/meta.yml @@ -1,53 +1,68 @@ name: "comparechecksum" -## TODO nf-core: Add a description of the module and list keywords -description: write your description here +description: | + Compare expected checksums against generated checksums and produce + a per-file validation report and a summary count of MATCH/MISMATCH/MISSING/UNEXPECTED statuses. keywords: - - sort - - example - - genomics + - checksum + - validation + - integrity + - md5 + - sha256 tools: - - "comparechecksum": - ## TODO nf-core: Add a description and other details for the software below - description: "" - homepage: "" - documentation: "" - tool_dev_url: "" - doi: "" - licence: + - "r-base": + description: "R statistical computing language used to run the comparison logic" + homepage: "https://www.r-project.org/" + documentation: "https://cran.r-project.org/manuals.html" + licence: ["GPL-2.0-or-later"] -## TODO nf-core: Add a description of all of the variables used as input input: - # Only when we have meta - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'sample1', single_end:false ]` + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - input_checksum: + type: file + description: | + File containing expected checksums (two-column, space-separated: + checksum and filename). + pattern: "*.{md5,sha256,tsv,txt}" + - generated_checksum: + type: file + description: | + File containing observed/generated checksums in the same format + as input_checksum. + pattern: "*.{md5,sha256,tsv,txt}" - ## TODO nf-core: Delete / customise this example input - - bam: - type: file - description: Sorted BAM/CRAM/SAM file - pattern: "*.{bam,cram,sam}" - -## TODO nf-core: Add a description of all of the variables used as output output: - #Only when we have meta - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'sample1', single_end:false ]` - - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" - ## TODO nf-core: Delete / customise this example output - - bam: - type: file - description: Sorted BAM/CRAM/SAM file - pattern: "*.{bam,cram,sam}" + - report: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - "*.csv": + type: file + description: | + Per-file validation report (checksum_validation.csv) and summary + report (checksum_summary.csv). + pattern: "*.csv" + - summary_report: + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - "*.csv": + type: file + description: | + Per-file validation report and summary report (same glob as report channel). + pattern: "*.csv" + - versions_comparechecksum: + - "versions.yml": + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@delfiterradas" diff --git a/modules/local/comparechecksum/templates/comparechecksum.R b/modules/local/comparechecksum/templates/comparechecksum.R index 9d323a3..31636e3 100644 --- a/modules/local/comparechecksum/templates/comparechecksum.R +++ b/modules/local/comparechecksum/templates/comparechecksum.R @@ -66,8 +66,7 @@ write.csv( versions <- c( "\"${task.process}\":", - paste0(" r-base: ", getRversion()), - paste0(" comparechecksum: ", getRversion()) + paste0(" r-base: ", getRversion()) ) writeLines( From 372614eaad01e766548ec746efb68a880a45bf94 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 29 Jun 2026 21:17:39 +0200 Subject: [PATCH 088/334] Update snapshots --- tests/default.nf.test.snap | 5 ++--- tests/main_full.nf.test.snap | 9 ++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 07b62a1..01e1954 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -3,8 +3,7 @@ "content": [ { "COMPARECHECKSUM": { - "r-base": "4.2.1", - "comparechecksum": "4.2.1" + "r-base": "4.2.1" }, "MD5SUM": { "md5sum": 9.5 @@ -55,7 +54,7 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-29T20:12:22.962884142", + "timestamp": "2026-06-29T21:12:58.023076335", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 17eb5e3..c8636b2 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -3,8 +3,7 @@ "content": [ { "COMPARECHECKSUM": { - "r-base": "4.2.1", - "comparechecksum": "4.2.1" + "r-base": "4.2.1" }, "MD5SUM": { "md5sum": 9.5 @@ -38,12 +37,12 @@ "shasum/demultiplex.sha256" ], [ - "demultiplex.checksum_summary.csv:md5,13fc2d64b33a06bf80694b06998ba7c1", - "demultiplex.checksum_validation.csv:md5,e5d57d106f96b536608e1ff06552df09", + "demultiplex.checksum_summary.csv:md5,5ab7359b25dcb4e6c6f5a7eb1687a2dc", + "demultiplex.checksum_validation.csv:md5,205760aabd99d02b7b61c250677f0b32", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-29T20:22:24.028086784", + "timestamp": "2026-06-29T21:15:25.735838624", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From 06c9398aaab9c5ff7b9efb46fac6d6c4eec9b387 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Mon, 29 Jun 2026 16:20:50 -0300 Subject: [PATCH 089/334] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36d6f40..235f35e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` - [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). +- - [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). ### `Fixed` From 6e03867b3f1c4664e80b46949de8d298b61b98ed Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Mon, 29 Jun 2026 16:21:02 -0300 Subject: [PATCH 090/334] Fix formatting in CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 235f35e..132fb4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` - [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- - [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). +- [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). ### `Fixed` From 755f9a130e176008118c27cbf04f8717b6212cb6 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 30 Jun 2026 17:17:36 +0200 Subject: [PATCH 091/334] Include compare checksum tables to multiqc report --- assets/multiqc_config.yml | 18 ++++++++++++++++++ modules/local/comparechecksum/main.nf | 4 ++-- .../templates/comparechecksum.R | 1 + workflows/datasync.nf | 15 +++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index dc1af56..e7c0dcc 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -13,3 +13,21 @@ report_section_order: export_plots: true disable_version_detection: true + +custom_data: + checksum_summary: + section_name: "Checksum Summary" + description: "Summary of checksum validation" + plot_type: "table" + file_format: "csv" + checksum_report: + section_name: "Checksum Report" + description: "Checksum validation report" + plot_type: "table" + file_format: "csv" + +sp: + checksum_summary: + fn: "*.checksum_summary.csv" + checksum_report: + fn: "*.checksum_validation.csv" diff --git a/modules/local/comparechecksum/main.nf b/modules/local/comparechecksum/main.nf index 9fba4fc..38e047b 100644 --- a/modules/local/comparechecksum/main.nf +++ b/modules/local/comparechecksum/main.nf @@ -11,8 +11,8 @@ process COMPARECHECKSUM { tuple val(meta), path(input_checksum), path(generated_checksum) output: - tuple val(meta), path("*.csv"), emit: report - tuple val(meta), path("*.csv"), emit: summary_report + tuple val(meta), path("*checksum_validation.csv"), emit: report + tuple val(meta), path("*checksum_summary.csv"), emit: summary_report path "versions.yml" , emit: versions_comparechecksum, topic: versions when: diff --git a/modules/local/comparechecksum/templates/comparechecksum.R b/modules/local/comparechecksum/templates/comparechecksum.R index 31636e3..1d939d9 100644 --- a/modules/local/comparechecksum/templates/comparechecksum.R +++ b/modules/local/comparechecksum/templates/comparechecksum.R @@ -53,6 +53,7 @@ write.csv( # Write summary report summary_df <- as.data.frame(table(report\$status)) colnames(summary_df) <- c("status", "count") +summary_df <- cbind(sample = prefix, summary_df) write.csv( summary_df[order(summary_df\$status), ], diff --git a/workflows/datasync.nf b/workflows/datasync.nf index c21837d..81513c0 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -66,6 +66,8 @@ workflow DATASYNC { } COMPARECHECKSUM(ch_checksum) + ch_multiqc_files = ch_multiqc_files.mix(COMPARECHECKSUM.out.report.map { meta, report -> report }) + ch_multiqc_files = ch_multiqc_files.mix(COMPARECHECKSUM.out.summary_report.map { meta, summary -> summary }) // // Collate and save software versions @@ -108,6 +110,19 @@ workflow DATASYNC { : file("${projectDir}/assets/methods_description_template.yml", checkIfExists: true) def ch_methods_description = channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml', sort: true)) + ch_multiqc_files.view() + ch_multiqc_files.flatten().collect().map { files -> + [ + [id: 'datasync'], + files, + multiqc_config + ? file(multiqc_config, checkIfExists: true) + : file("${projectDir}/assets/multiqc_config.yml", checkIfExists: true), + multiqc_logo ? file(multiqc_logo, checkIfExists: true) : [], + [], + [], + ] + }.view() MULTIQC( ch_multiqc_files.flatten().collect().map { files -> [ From 6826b447f6c5de3ab662acd4b8c12170f7bbf60a Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 30 Jun 2026 17:18:42 +0200 Subject: [PATCH 092/334] Remove view statements --- workflows/datasync.nf | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 81513c0..1c446e9 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -110,19 +110,6 @@ workflow DATASYNC { : file("${projectDir}/assets/methods_description_template.yml", checkIfExists: true) def ch_methods_description = channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml', sort: true)) - ch_multiqc_files.view() - ch_multiqc_files.flatten().collect().map { files -> - [ - [id: 'datasync'], - files, - multiqc_config - ? file(multiqc_config, checkIfExists: true) - : file("${projectDir}/assets/multiqc_config.yml", checkIfExists: true), - multiqc_logo ? file(multiqc_logo, checkIfExists: true) : [], - [], - [], - ] - }.view() MULTIQC( ch_multiqc_files.flatten().collect().map { files -> [ From cdfa39045ace00e465f21c25707e794e3fac0499 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 30 Jun 2026 17:32:43 +0200 Subject: [PATCH 093/334] Update meta.yml --- modules/local/comparechecksum/meta.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/local/comparechecksum/meta.yml b/modules/local/comparechecksum/meta.yml index 0d50b52..5f7b938 100644 --- a/modules/local/comparechecksum/meta.yml +++ b/modules/local/comparechecksum/meta.yml @@ -44,9 +44,8 @@ output: - "*.csv": type: file description: | - Per-file validation report (checksum_validation.csv) and summary - report (checksum_summary.csv). - pattern: "*.csv" + Per-file validation report. + pattern: "*checksum_validation.csv" - summary_report: - meta: type: map @@ -56,8 +55,8 @@ output: - "*.csv": type: file description: | - Per-file validation report and summary report (same glob as report channel). - pattern: "*.csv" + Per-file summary report. + pattern: "*checksum_summary.csv" - versions_comparechecksum: - "versions.yml": type: file From 7ea10271ae3f10d3d405fb80c7b10f2fc05c5177 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 30 Jun 2026 22:23:21 +0200 Subject: [PATCH 094/334] Separate report for sha and md5 checksums and modify summary report in module --- assets/multiqc_config.yml | 50 +++++++++++++++---- conf/modules.config | 4 ++ .../templates/comparechecksum.R | 17 ++++++- workflows/datasync.nf | 4 +- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index e7c0dcc..287b74a 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -15,19 +15,49 @@ export_plots: true disable_version_detection: true custom_data: - checksum_summary: - section_name: "Checksum Summary" - description: "Summary of checksum validation" + md5_checksum_summary: + section_name: "MD5 Checksum Summary" + description: "Summary of MD5 checksum validation" plot_type: "table" file_format: "csv" - checksum_report: - section_name: "Checksum Report" - description: "Checksum validation report" + + sha_checksum_summary: + section_name: "SHA Checksum Summary" + description: "Summary of SHA checksum validation" + plot_type: "table" + file_format: "csv" + + md5_checksum_report: + section_name: "MD5 Checksum Report" + description: "Detailed MD5 checksum validation report" + plot_type: "table" + file_format: "csv" + + headers: + file: + title: File + checksum_expected: + title: Expected checksum + checksum_observed: + title: Observed checksum + status: + title: Status + + sha_checksum_report: + section_name: "SHA Checksum Report" + description: "Detailed SHA checksum validation report" plot_type: "table" file_format: "csv" sp: - checksum_summary: - fn: "*.checksum_summary.csv" - checksum_report: - fn: "*.checksum_validation.csv" + md5_checksum_summary: + fn: "*_md5.checksum_summary.csv" + + sha_checksum_summary: + fn: "*_sha.checksum_summary.csv" + + md5_checksum_report: + fn: "*_md5.checksum_validation.csv" + + sha_checksum_report: + fn: "*_sha.checksum_validation.csv" diff --git a/conf/modules.config b/conf/modules.config index f0b0d55..83bb02c 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,6 +18,10 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] + withName: 'COMPARECHECKSUM' { + ext.prefix = { "${meta.id}_${meta.check_format}" } + } + withName: 'MULTIQC' { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ diff --git a/modules/local/comparechecksum/templates/comparechecksum.R b/modules/local/comparechecksum/templates/comparechecksum.R index 1d939d9..9f83c34 100644 --- a/modules/local/comparechecksum/templates/comparechecksum.R +++ b/modules/local/comparechecksum/templates/comparechecksum.R @@ -54,9 +54,24 @@ write.csv( summary_df <- as.data.frame(table(report\$status)) colnames(summary_df) <- c("status", "count") summary_df <- cbind(sample = prefix, summary_df) +status_counts <- table( + factor( + report\$status, + levels = c("MATCH", "MISMATCH", "MISSING", "UNEXPECTED") + ) +) + +summary_df <- data.frame( + sample = prefix, + MATCH = unname(status_counts["MATCH"]), + MISMATCH = unname(status_counts["MISMATCH"]), + MISSING = unname(status_counts["MISSING"]), + UNEXPECTED = unname(status_counts["UNEXPECTED"]), + check.names = FALSE +) write.csv( - summary_df[order(summary_df\$status), ], + summary_df, paste0(prefix, ".checksum_summary.csv"), row.names = FALSE ) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 1c446e9..b0fd99e 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -56,10 +56,10 @@ workflow DATASYNC { def checksum_tuple = [] // If checksum is empty it will read the md5/shasum from meta if (md5) { - checksum_tuple << tuple(meta, md5, out_md5) + checksum_tuple << tuple(meta + [check_format: "md5"], md5, out_md5) } if (sha) { - checksum_tuple << tuple(meta, sha, out_sha) + checksum_tuple << tuple(meta + [check_format: "sha"], sha, out_sha) } return checksum_tuple From 30d56a60c7ff703a0040fc98a331568f6fe2d27a Mon Sep 17 00:00:00 2001 From: zxBIB Date: Wed, 1 Jul 2026 17:02:40 +0200 Subject: [PATCH 095/334] update nextflow version --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index c383076..6123532 100644 --- a/nextflow.config +++ b/nextflow.config @@ -254,7 +254,7 @@ manifest { description = """A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.""" mainScript = 'main.nf' defaultBranch = 'main' - nextflowVersion = '!>=25.10.4' + nextflowVersion = '!>=25.10.2' version = '1.0dev' doi = '' } From acb63631eb82da5e648c2152105ef5c2a8f5ae46 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 1 Jul 2026 20:33:23 +0200 Subject: [PATCH 096/334] Remove unnecessary params --- conf/test.config | 1 - conf/test_full.config | 3 --- nextflow.config | 5 ----- nextflow_schema.json | 41 ----------------------------------------- 4 files changed, 50 deletions(-) diff --git a/conf/test.config b/conf/test.config index 880dd04..471f18b 100644 --- a/conf/test.config +++ b/conf/test.config @@ -26,5 +26,4 @@ params { // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets // TODO nf-core: Give any required params for the test so that command line flags are not needed input = params.pipelines_testdata_base_path + "test-data/samplesheet.csv" - genome = 'R64-1-1' } diff --git a/conf/test_full.config b/conf/test_full.config index ae44f01..e3be437 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -18,7 +18,4 @@ params { // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) // TODO nf-core: Give any required params for the test so that command line flags are not needed input = params.pipelines_testdata_base_path + "test-data/samplesheet_full.csv" - - // Genome references - genome = 'R64-1-1' } diff --git a/nextflow.config b/nextflow.config index c383076..bfb3803 100644 --- a/nextflow.config +++ b/nextflow.config @@ -13,11 +13,6 @@ params { // Input options input = null - // References - genome = null - igenomes_base = 's3://ngi-igenomes/igenomes/' - igenomes_ignore = false - // MultiQC options multiqc_config = null multiqc_title = null diff --git a/nextflow_schema.json b/nextflow_schema.json index 75bee3d..1e41073 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -43,44 +43,6 @@ } } }, - "reference_genome_options": { - "title": "Reference genome options", - "type": "object", - "fa_icon": "fas fa-dna", - "description": "Reference genome related files and options required for the workflow.", - "properties": { - "genome": { - "type": "string", - "description": "Name of iGenomes reference.", - "fa_icon": "fas fa-book", - "help_text": "If using a reference genome configured in the pipeline using iGenomes, use this parameter to give the ID for the reference. This is then used to build the full paths for all required reference genome files e.g. `--genome GRCh38`. \n\nSee the [nf-core website docs](https://nf-co.re/usage/reference_genomes) for more details." - }, - "fasta": { - "type": "string", - "format": "file-path", - "exists": true, - "mimetype": "text/plain", - "pattern": "^\\S+\\.fn?a(sta)?(\\.gz)?$", - "description": "Path to FASTA genome file.", - "help_text": "This parameter is *mandatory* if `--genome` is not specified. If you don't have a BWA index available this will be generated for you automatically. Combine with `--save_reference` to save BWA index for future runs.", - "fa_icon": "far fa-file-code" - }, - "igenomes_ignore": { - "type": "boolean", - "description": "Do not load the iGenomes reference config.", - "fa_icon": "fas fa-ban", - "hidden": true, - "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`." - }, - "igenomes_base": { - "type": "string", - "description": "The base path to the igenomes reference files", - "fa_icon": "fas fa-ban", - "hidden": true, - "default": "s3://ngi-igenomes/igenomes/" - } - } - }, "institutional_config_options": { "title": "Institutional config options", "type": "object", @@ -236,9 +198,6 @@ { "$ref": "#/$defs/input_output_options" }, - { - "$ref": "#/$defs/reference_genome_options" - }, { "$ref": "#/$defs/institutional_config_options" }, From b1ea5662b719fa1b3c4117a5f0aeb6e5232bf48d Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 1 Jul 2026 20:39:47 +0200 Subject: [PATCH 097/334] Avoid generating violin plots for large tables and other minor changes --- assets/multiqc_config.yml | 17 ++++++++++- .../templates/comparechecksum.R | 28 +++++++++---------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 287b74a..1c9aa09 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -32,9 +32,11 @@ custom_data: description: "Detailed MD5 checksum validation report" plot_type: "table" file_format: "csv" + pconfig: + no_violin: true headers: - file: + File: title: File checksum_expected: title: Expected checksum @@ -48,6 +50,19 @@ custom_data: description: "Detailed SHA checksum validation report" plot_type: "table" file_format: "csv" + pconfig: + no_violin: true + + headers: + File: + title: File + checksum_expected: + title: Expected checksum + checksum_observed: + title: Observed checksum + status: + title: Status + sp: md5_checksum_summary: diff --git a/modules/local/comparechecksum/templates/comparechecksum.R b/modules/local/comparechecksum/templates/comparechecksum.R index 9f83c34..5bea92f 100644 --- a/modules/local/comparechecksum/templates/comparechecksum.R +++ b/modules/local/comparechecksum/templates/comparechecksum.R @@ -11,7 +11,7 @@ read_checksum_file <- function(path) { path, stringsAsFactors = FALSE, fill = TRUE, - col.names = c("checksum", "file") + col.names = c("checksum", "File") ) x @@ -24,28 +24,28 @@ expected <- read_checksum_file(input_checksum) report <- merge( expected, generated, - by = "file", + by = "File", all = TRUE, suffixes = c("_expected", "_observed") ) report\$status <- ifelse( is.na(report\$checksum_expected), - "UNEXPECTED", + "Unexpected", ifelse( is.na(report\$checksum_observed), - "MISSING", + "Missing", ifelse( report\$checksum_expected == report\$checksum_observed, - "MATCH", - "MISMATCH" + "Match", + "Mismatch" ) ) ) # Write detailed report write.csv( - report[order(report\$file), ], + report[order(report\$File), ], paste0(prefix, ".checksum_validation.csv"), row.names = FALSE ) @@ -53,20 +53,20 @@ write.csv( # Write summary report summary_df <- as.data.frame(table(report\$status)) colnames(summary_df) <- c("status", "count") -summary_df <- cbind(sample = prefix, summary_df) +summary_df <- cbind(Sample = prefix, summary_df) status_counts <- table( factor( report\$status, - levels = c("MATCH", "MISMATCH", "MISSING", "UNEXPECTED") + levels = c("Match", "Mismatch", "Missing", "Unexpected") ) ) summary_df <- data.frame( - sample = prefix, - MATCH = unname(status_counts["MATCH"]), - MISMATCH = unname(status_counts["MISMATCH"]), - MISSING = unname(status_counts["MISSING"]), - UNEXPECTED = unname(status_counts["UNEXPECTED"]), + Sample = prefix, + Match = unname(status_counts["Match"]), + Mismatch = unname(status_counts["Mismatch"]), + Missing = unname(status_counts["Missing"]), + Unexpected = unname(status_counts["Unexpected"]), check.names = FALSE ) From d3fa2dc04542a8cbe77143bc9ff37e821d4c1fd9 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 1 Jul 2026 22:38:37 +0200 Subject: [PATCH 098/334] Remove fasta param and igenomes config --- conf/igenomes.config | 440 ------------------ conf/igenomes_ignored.config | 9 - main.nf | 12 - nextflow.config | 4 - .../utils_nfcore_datasync_pipeline/main.nf | 25 - 5 files changed, 490 deletions(-) delete mode 100644 conf/igenomes.config delete mode 100644 conf/igenomes_ignored.config diff --git a/conf/igenomes.config b/conf/igenomes.config deleted file mode 100644 index 3f11437..0000000 --- a/conf/igenomes.config +++ /dev/null @@ -1,440 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for iGenomes paths -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines reference genomes using iGenome paths. - Can be used by any config that customises the base path using: - $params.igenomes_base / --igenomes_base ----------------------------------------------------------------------------------------- -*/ - -params { - // illumina iGenomes reference file paths - genomes { - 'GRCh37' { - fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" - } - 'GRCh38' { - fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'CHM13' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAIndex/" - bwamem2 = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAmem2Index/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/CHM13/Annotation/Genes/genes.gtf" - gff = "ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/009/914/755/GCF_009914755.1_T2T-CHM13v2.0/GCF_009914755.1_T2T-CHM13v2.0_genomic.gff.gz" - mito_name = "chrM" - } - 'GRCm38' { - fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" - } - 'TAIR10' { - fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" - mito_name = "Mt" - } - 'EB2' { - fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" - } - 'UMD3.1' { - fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" - mito_name = "MT" - } - 'WBcel235' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" - mito_name = "MtDNA" - macs_gsize = "9e7" - } - 'CanFam3.1' { - fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" - mito_name = "MT" - } - 'GRCz10' { - fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'BDGP6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" - mito_name = "M" - macs_gsize = "1.2e8" - } - 'EquCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" - mito_name = "MT" - } - 'EB1' { - fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" - } - 'Galgal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Gm01' { - fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" - } - 'Mmul_1' { - fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" - mito_name = "MT" - } - 'IRGSP-1.0' { - fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'CHIMP2.1.4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" - mito_name = "MT" - } - 'Rnor_5.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Rnor_6.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'R64-1-1' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" - mito_name = "MT" - macs_gsize = "1.2e7" - } - 'EF2' { - fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.21e7" - } - 'Sbi1' { - fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" - } - 'Sscrofa10.2' { - fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" - mito_name = "MT" - } - 'AGPv3' { - fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'hg38' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'hg19' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" - } - 'mm10' { - fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" - } - 'bosTau8' { - fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'ce10' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "9e7" - } - 'canFam3' { - fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" - mito_name = "chrM" - } - 'danRer10' { - fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.37e9" - } - 'dm6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.2e8" - } - 'equCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" - mito_name = "chrM" - } - 'galGal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" - mito_name = "chrM" - } - 'panTro4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" - mito_name = "chrM" - } - 'rn6' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'sacCer3' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" - readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.2e7" - } - 'susScr3' { - fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" - mito_name = "chrM" - } - } -} diff --git a/conf/igenomes_ignored.config b/conf/igenomes_ignored.config deleted file mode 100644 index b4034d8..0000000 --- a/conf/igenomes_ignored.config +++ /dev/null @@ -1,9 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for iGenomes paths -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Empty genomes dictionary to use when igenomes is ignored. ----------------------------------------------------------------------------------------- -*/ - -params.genomes = [:] diff --git a/main.nf b/main.nf index 637723e..865554a 100644 --- a/main.nf +++ b/main.nf @@ -18,18 +18,6 @@ include { DATASYNC } from './workflows/datasync' include { PIPELINE_INITIALISATION } from './subworkflows/local/utils_nfcore_datasync_pipeline' include { PIPELINE_COMPLETION } from './subworkflows/local/utils_nfcore_datasync_pipeline' -include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_datasync_pipeline' - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - GENOME PARAMETER VALUES -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -// TODO nf-core: Remove this line if you don't need a FASTA file -// This is an example of how to use getGenomeAttribute() to fetch parameters -// from igenomes.config using `--genome` -params.fasta = getGenomeAttribute('fasta') /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/nextflow.config b/nextflow.config index bfb3803..6065068 100644 --- a/nextflow.config +++ b/nextflow.config @@ -188,9 +188,6 @@ podman.registry = 'quay.io' singularity.registry = 'quay.io' charliecloud.registry = 'quay.io' -// Load igenomes.config if required -includeConfig !params.igenomes_ignore ? 'conf/igenomes.config' : 'conf/igenomes_ignored.config' - // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. @@ -260,7 +257,6 @@ plugins { } validation { - defaultIgnoreParams = ["genomes"] monochromeLogs = params.monochrome_logs } // Load modules.config for DSL2 module specific options diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index b3ce127..959f28d 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -173,31 +173,6 @@ def validateInputParameters() { genomeExistsError() } -// -// Get attribute from genome config file e.g. fasta -// -def getGenomeAttribute(attribute) { - if (params.genomes && params.genome && params.genomes.containsKey(params.genome)) { - if (params.genomes[ params.genome ].containsKey(attribute)) { - return params.genomes[ params.genome ][ attribute ] - } - } - return null -} - -// -// Exit pipeline if incorrect --genome key provided -// -def genomeExistsError() { - if (params.genomes && params.genome && !params.genomes.containsKey(params.genome)) { - def error_string = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " Genome '${params.genome}' not found in any config files provided to the pipeline.\n" + - " Currently, the available genome keys are:\n" + - " ${params.genomes.keySet().join(", ")}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - error(error_string) - } -} // // Generate methods description for MultiQC // From 824e4513526b50b8b6460ff3af8887514f00e8c7 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 1 Jul 2026 22:40:09 +0200 Subject: [PATCH 099/334] Remove validation for genome --- subworkflows/local/utils_nfcore_datasync_pipeline/main.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 959f28d..36e6680 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -170,7 +170,6 @@ workflow PIPELINE_COMPLETION { // Check and validate pipeline parameters // def validateInputParameters() { - genomeExistsError() } // From 4860d7c443dd464dea13812c5080902232a2bc91 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 1 Jul 2026 22:47:42 +0200 Subject: [PATCH 100/334] Update snapshot --- tests/default.nf.test.snap | 42 ++++++++++++++++++++++++------------ tests/main_full.nf.test.snap | 40 ++++++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 01e1954..b5dc798 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -17,12 +17,12 @@ }, [ "comparechecksum", - "comparechecksum/Illumina_annotation.checksum_summary.csv", - "comparechecksum/Illumina_annotation.checksum_validation.csv", - "comparechecksum/benchmark_bed.checksum_summary.csv", - "comparechecksum/benchmark_bed.checksum_validation.csv", - "comparechecksum/test_fastq.checksum_summary.csv", - "comparechecksum/test_fastq.checksum_validation.csv", + "comparechecksum/Illumina_annotation_md5.checksum_summary.csv", + "comparechecksum/Illumina_annotation_md5.checksum_validation.csv", + "comparechecksum/benchmark_bed_md5.checksum_summary.csv", + "comparechecksum/benchmark_bed_md5.checksum_validation.csv", + "comparechecksum/test_fastq_md5.checksum_summary.csv", + "comparechecksum/test_fastq_md5.checksum_validation.csv", "md5sum", "md5sum/Illumina_annotation.md5", "md5sum/benchmark_bed.md5", @@ -34,8 +34,20 @@ "multiqc/multiqc_data/multiqc.parquet", "multiqc/multiqc_data/multiqc_citations.txt", "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_md5_checksum_report.txt", + "multiqc/multiqc_data/multiqc_md5_checksum_summary.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_plots", + "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/md5_checksum_report.pdf", + "multiqc/multiqc_plots/pdf/md5_checksum_summary.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/md5_checksum_report.png", + "multiqc/multiqc_plots/png/md5_checksum_summary.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/md5_checksum_report.svg", + "multiqc/multiqc_plots/svg/md5_checksum_summary.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", @@ -45,16 +57,18 @@ "shasum/test_fastq.sha256" ], [ - "Illumina_annotation.checksum_summary.csv:md5,da71db43566c677ddc32186e53d4f30e", - "Illumina_annotation.checksum_validation.csv:md5,9032cc5084168ca56d501269fc1021e8", - "benchmark_bed.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", - "benchmark_bed.checksum_validation.csv:md5,d1e7087446c6138dba9929099787c5c9", - "test_fastq.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", - "test_fastq.checksum_validation.csv:md5,9f72112e05dc478eee7d3d56a6364cd0", - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + "Illumina_annotation_md5.checksum_summary.csv:md5,eaff8b778f802026d8013d004a9aa00f", + "Illumina_annotation_md5.checksum_validation.csv:md5,ce382d06839523dd9c390e3b34881be0", + "benchmark_bed_md5.checksum_summary.csv:md5,266bcbba1edbc6720508aa392387c566", + "benchmark_bed_md5.checksum_validation.csv:md5,b528bcd09ff8e6bf3c51e72d3e4ebe8f", + "test_fastq_md5.checksum_summary.csv:md5,6904f7c475eb219bee74f013a1870caf", + "test_fastq_md5.checksum_validation.csv:md5,4c94e3b3362f854c42941fc67b226ac2", + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "multiqc_md5_checksum_report.txt:md5,39147d72a414c399614f139354e36a86", + "multiqc_md5_checksum_summary.txt:md5,d8c3b87b26251d4d6cb1aca315f0f531" ] ], - "timestamp": "2026-06-29T21:12:58.023076335", + "timestamp": "2026-07-01T22:40:25.11618923", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index c8636b2..e01af4b 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -17,8 +17,10 @@ }, [ "comparechecksum", - "comparechecksum/demultiplex.checksum_summary.csv", - "comparechecksum/demultiplex.checksum_validation.csv", + "comparechecksum/demultiplex_md5.checksum_summary.csv", + "comparechecksum/demultiplex_md5.checksum_validation.csv", + "comparechecksum/demultiplex_sha.checksum_summary.csv", + "comparechecksum/demultiplex_sha.checksum_validation.csv", "md5sum", "md5sum/demultiplex.md5", "multiqc", @@ -28,8 +30,28 @@ "multiqc/multiqc_data/multiqc.parquet", "multiqc/multiqc_data/multiqc_citations.txt", "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_md5_checksum_report.txt", + "multiqc/multiqc_data/multiqc_md5_checksum_summary.txt", + "multiqc/multiqc_data/multiqc_sha_checksum_report.txt", + "multiqc/multiqc_data/multiqc_sha_checksum_summary.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_plots", + "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/md5_checksum_report.pdf", + "multiqc/multiqc_plots/pdf/md5_checksum_summary.pdf", + "multiqc/multiqc_plots/pdf/sha_checksum_report.pdf", + "multiqc/multiqc_plots/pdf/sha_checksum_summary.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/md5_checksum_report.png", + "multiqc/multiqc_plots/png/md5_checksum_summary.png", + "multiqc/multiqc_plots/png/sha_checksum_report.png", + "multiqc/multiqc_plots/png/sha_checksum_summary.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/md5_checksum_report.svg", + "multiqc/multiqc_plots/svg/md5_checksum_summary.svg", + "multiqc/multiqc_plots/svg/sha_checksum_report.svg", + "multiqc/multiqc_plots/svg/sha_checksum_summary.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", @@ -37,12 +59,18 @@ "shasum/demultiplex.sha256" ], [ - "demultiplex.checksum_summary.csv:md5,5ab7359b25dcb4e6c6f5a7eb1687a2dc", - "demultiplex.checksum_validation.csv:md5,205760aabd99d02b7b61c250677f0b32", - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + "demultiplex_md5.checksum_summary.csv:md5,23b0f0d7d74706e07f249ed30bbb34a6", + "demultiplex_md5.checksum_validation.csv:md5,743eef23f7d1ddc87bcd3b901b65cae7", + "demultiplex_sha.checksum_summary.csv:md5,24f4d1d614fd57980b7484231f4855b9", + "demultiplex_sha.checksum_validation.csv:md5,96f322a237447d90d68131fb85ce76be", + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "multiqc_md5_checksum_report.txt:md5,8d84f5711d802cd908cf5780f1fd029e", + "multiqc_md5_checksum_summary.txt:md5,14a9c197093f8cd187833a11e13a3c58", + "multiqc_sha_checksum_report.txt:md5,52c4bffaf0a94c59d4c2111fc62c074d", + "multiqc_sha_checksum_summary.txt:md5,78a00f0c20054c0f1853ceac0fcc0172" ] ], - "timestamp": "2026-06-29T21:15:25.735838624", + "timestamp": "2026-07-01T22:44:40.088234608", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From 31797b2460a746065ae2c37d347864f591d68738 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Wed, 1 Jul 2026 17:53:11 -0300 Subject: [PATCH 101/334] Remove empty lines --- assets/multiqc_config.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 1c9aa09..db9d1ce 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -20,13 +20,11 @@ custom_data: description: "Summary of MD5 checksum validation" plot_type: "table" file_format: "csv" - sha_checksum_summary: section_name: "SHA Checksum Summary" description: "Summary of SHA checksum validation" plot_type: "table" file_format: "csv" - md5_checksum_report: section_name: "MD5 Checksum Report" description: "Detailed MD5 checksum validation report" @@ -34,7 +32,6 @@ custom_data: file_format: "csv" pconfig: no_violin: true - headers: File: title: File @@ -44,7 +41,6 @@ custom_data: title: Observed checksum status: title: Status - sha_checksum_report: section_name: "SHA Checksum Report" description: "Detailed SHA checksum validation report" @@ -52,7 +48,6 @@ custom_data: file_format: "csv" pconfig: no_violin: true - headers: File: title: File @@ -63,16 +58,12 @@ custom_data: status: title: Status - sp: md5_checksum_summary: fn: "*_md5.checksum_summary.csv" - sha_checksum_summary: fn: "*_sha.checksum_summary.csv" - md5_checksum_report: fn: "*_md5.checksum_validation.csv" - sha_checksum_report: fn: "*_sha.checksum_validation.csv" From 20fed3702453d9fe28a95387513b97f312822671 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Thu, 2 Jul 2026 23:00:43 +0200 Subject: [PATCH 102/334] rename rclone to rclone_copy + update meta.yml --- modules/nf-core/rclone/meta.yml | 49 -------------- .../{rclone => rclone_copy}/environment.yml | 0 .../nf-core/{rclone => rclone_copy}/main.nf | 33 +++------- modules/nf-core/rclone_copy/meta.yml | 65 +++++++++++++++++++ workflows/datasync.nf | 35 ++++++---- 5 files changed, 98 insertions(+), 84 deletions(-) delete mode 100644 modules/nf-core/rclone/meta.yml rename modules/nf-core/{rclone => rclone_copy}/environment.yml (100%) rename modules/nf-core/{rclone => rclone_copy}/main.nf (60%) create mode 100644 modules/nf-core/rclone_copy/meta.yml diff --git a/modules/nf-core/rclone/meta.yml b/modules/nf-core/rclone/meta.yml deleted file mode 100644 index 3aea592..0000000 --- a/modules/nf-core/rclone/meta.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: "rclone" -description: Copy data using Rclone to a specified output path -keywords: - - rclone - - copy - - sync - - data-transfer -tools: - - "rclone": - description: Rclone is a command line program to manage files on cloud storage - homepage: "https://rclone.org/" - documentation: "https://rclone.org/docs/" - licence: - - "MIT" - identifier: "" -input: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - source_path: - type: path - description: Source path to copy from (can be local or remote path) - - destination_path: - type: string - description: | - Destination base path where data will be copied to. Sample ID will be appended. - Can be local path or remote storage path (s3://, gs://, etc.) -output: - copy_status: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - copy_status: - type: string - description: Status of the copy operation (success/failed) - versions: - - - ${task.process}: - type: string - description: The name of the process - - rclone: - type: string - description: The name of the tool - - "*.version.txt": - type: file - description: File containing software version diff --git a/modules/nf-core/rclone/environment.yml b/modules/nf-core/rclone_copy/environment.yml similarity index 100% rename from modules/nf-core/rclone/environment.yml rename to modules/nf-core/rclone_copy/environment.yml diff --git a/modules/nf-core/rclone/main.nf b/modules/nf-core/rclone_copy/main.nf similarity index 60% rename from modules/nf-core/rclone/main.nf rename to modules/nf-core/rclone_copy/main.nf index 00434d4..acd4c2c 100644 --- a/modules/nf-core/rclone/main.nf +++ b/modules/nf-core/rclone_copy/main.nf @@ -1,4 +1,4 @@ -process RCLONE { +process RCLONE_COPY { tag "${meta.id}" label 'process_low' @@ -9,8 +9,7 @@ process RCLONE { : 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be'}" input: - tuple val(meta), val(source_path) - val destination_path + tuple val(meta), val(source_path), val(destination_path) path rclone_config output: @@ -22,30 +21,16 @@ process RCLONE { script: def args = task.ext.args ?: '' - def configArg = rclone_config ? "--config '${rclone_config}'" : '' + def configArg = rclone_config ? "--config '${rclone_config}'" : error("RCLONE_COPY requires an rclone config file") + def transfers = task.ext.transfers ?: task.cpus + def checkers = task.ext.checkers ?: task.cpus """ - to_rclone_path() { - case "\$1" in - s3://*) echo "s3:\${1#s3://}" ;; - *) echo "\$1" ;; - esac - } - - SRC=\$(to_rclone_path "${source_path}") - DEST_BASE=\$(to_rclone_path "${destination_path}") - - SRC_CLEAN="\${SRC%/}" - DEST="\${DEST_BASE%/}/\$(basename "\${SRC_CLEAN}")" - rclone ${configArg} copy ${args} \\ - --log-file rclone-copy.log \\ - --log-level INFO \\ - --stats 30s \\ - --stats-one-line \\ - --stats-log-level INFO \\ - --s3-env-auth \\ - "\${SRC}" "\${DEST}" + --transfers ${transfers} \\ + --checkers ${checkers} \\ + "${source_path}" \\ + "${destination_path}" """ stub: diff --git a/modules/nf-core/rclone_copy/meta.yml b/modules/nf-core/rclone_copy/meta.yml new file mode 100644 index 0000000..039a786 --- /dev/null +++ b/modules/nf-core/rclone_copy/meta.yml @@ -0,0 +1,65 @@ +name: "rclone_copy" +description: Copy files or directories between local and/or remote storage using Rclone +keywords: + - rclone + - copy + - sync + - data-transfer +tools: + - "rclone": + description: "Rclone is a command line program to manage files on cloud storage" + homepage: "https://rclone.org/" + documentation: "https://rclone.org/docs/" + licence: + - "MIT" + identifier: "" + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information. + e.g. [ id:'test', single_end:false ] + - source_path: + type: string + description: | + Source path to copy from. This should be a path understood by Rclone, + such as a local path or a configured remote path. + Examples: `data/input`, `s3:bucket/path`, `gs:bucket/path`, + `remote:path/to/data`. + - destination_path: + type: string + description: | + Destination path to copy to. This should be the fully resolved target + path understood by Rclone, such as a local path or a configured remote + path. The module does not append sample IDs, basenames, or modify this + path internally. + Examples: `results/output`, `s3:bucket/output`, `gs:bucket/output`, + `remote:path/to/output`. + - rclone_config: + type: file + description: | + Rclone configuration file defining the remotes used by source_path and/or + destination_path. Authentication and remote-specific options should be + configured in this file where possible. + +output: + log: + - - meta: + type: map + description: | + Groovy Map containing sample information. + e.g. [ id:'test', single_end:false ] + - "rclone-copy.log": + type: file + description: Rclone log file generated during the copy operation. + versions: + - - ${task.process}: + type: string + description: The name of the process. + - rclone: + type: string + description: The name of the tool. + - version: + type: string + description: The version of Rclone used. \ No newline at end of file diff --git a/workflows/datasync.nf b/workflows/datasync.nf index d5175cd..733b299 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -3,15 +3,15 @@ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { COMPARECHECKSUM } from '../modules/local/comparechecksum/main' -include { MD5SUM } from '../modules/nf-core/md5sum/main' -include { MULTIQC } from '../modules/nf-core/multiqc/main' -include { RCLONE } from '../modules/nf-core/rclone/main' -include { SHASUM } from '../modules/nf-core/shasum/main' -include { paramsSummaryMap } from 'plugin/nf-schema' -include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' -include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' -include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_datasync_pipeline' +include { COMPARECHECKSUM } from '../modules/local/comparechecksum/main' +include { MD5SUM } from '../modules/nf-core/md5sum/main' +include { MULTIQC } from '../modules/nf-core/multiqc/main' +include { RCLONE_COPY } from '../modules/nf-core/rclone_copy/main' +include { SHASUM } from '../modules/nf-core/shasum/main' +include { paramsSummaryMap } from 'plugin/nf-schema' +include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' +include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' +include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_datasync_pipeline' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -37,8 +37,21 @@ workflow DATASYNC { ch_samplesheet = ch_samplesheet.multiMap { meta, input_path, md5, sha -> - input: [ meta, input_path ] // staged input for MD5SUM / SHASUM - rclone: [ meta, input_path.toString() ] // raw URI for rclone + + def source_string = input_path.toString() + + def rclone_source = source_string + .replaceFirst('^s3://', 's3:') + + def source_name = rclone_source + .replaceAll('/+$', '') + .tokenize('/') + .last() + + def rclone_destination = "${rclone_output_path.toString().replaceAll('/+$', '')}/${source_name}" + + input: [ meta, input_path ] + rclone: [ meta, rclone_source, rclone_destination ] checksum: [ meta, md5, sha ] } From e778740ef2321db4ab07ed313e5f79e29f15df97 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Thu, 2 Jul 2026 23:01:21 +0200 Subject: [PATCH 103/334] move log args to ext args --- conf/modules.config | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 0ba18c5..d03dd6b 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,8 +18,16 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] - withName: 'RCLONE' { - ext.args = '--transfers 16 --checkers 8 --s3-chunk-size 64M --no-check-certificate' + withName: 'RCLONE_COPY' { + ext.args = [ + '--log-file rclone-copy.log', + '--log-level INFO', + '--stats 30s', + '--stats-one-line', + '--stats-log-level INFO', + '--s3-chunk-size 64M', + '--no-check-certificate' + ].join(' ') } withName: 'MULTIQC' { From 015893b390e4fbf472249cd16573fcd3aa755d70 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 2 Jul 2026 18:06:26 -0300 Subject: [PATCH 104/334] Delete AGENTS.md --- AGENTS.md | 1 - 1 file changed, 1 deletion(-) delete mode 120000 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md deleted file mode 120000 index 2a61453..0000000 --- a/AGENTS.md +++ /dev/null @@ -1 +0,0 @@ -/home/as32149/agents/AGENTS.md \ No newline at end of file From caf4be0e63b5db43cbfa6175bd54e6ed8532f66f Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 00:48:14 +0200 Subject: [PATCH 105/334] remove rclone output path as param --- main.nf | 1 - 1 file changed, 1 deletion(-) diff --git a/main.nf b/main.nf index de8ddc9..3e854e4 100644 --- a/main.nf +++ b/main.nf @@ -56,7 +56,6 @@ workflow NFCORE_DATASYNC { params.multiqc_logo, params.multiqc_methods_description, params.outdir, - params.rclone_output_path, params.rclone_config ) emit: From bf109ebb9da303ade66cd38da96914ec8a84ec38 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 00:48:33 +0200 Subject: [PATCH 106/334] define rclone config param --- nextflow.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nextflow.config b/nextflow.config index 6123532..379a0a9 100644 --- a/nextflow.config +++ b/nextflow.config @@ -25,6 +25,9 @@ params { max_multiqc_email_size = '25.MB' multiqc_methods_description = null + // Rclone options + rclone_config = null + // Boilerplate options outdir = null publish_dir_mode = 'copy' From be832cb7fd17fae3964c2a0e28d8b14cae11d781 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 00:48:54 +0200 Subject: [PATCH 107/334] include output path in input schema --- assets/schema_input.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/assets/schema_input.json b/assets/schema_input.json index dab918f..5985ddb 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -18,6 +18,11 @@ "pattern": "^\\S+$", "errorMessage": "Input path must be provided and cannot contain spaces" }, + "output_path": { + "type": "string", + "pattern": "^\\S+$", + "errorMessage": "Output path for rclone copy must be provided and cannot contain spaces" + }, "checksum_md5": { "type": "string", "format": "file-path", @@ -31,7 +36,7 @@ "errorMessage": "Checksum_sha cannot contain spaces" } }, - "required": ["sample", "input"], + "required": ["sample", "input", "output_path"], "anyOf": [{ "required": ["checksum_md5"] }, { "required": ["checksum_sha"] }] } } From 43be5b3ccac82cac8fdf63a1214d8cdae119a44e Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 00:49:35 +0200 Subject: [PATCH 108/334] include http handling --- conf/modules.config | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index d03dd6b..7335fdf 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,16 +18,22 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] + withName: 'RCLONE_COPY' { - ext.args = [ - '--log-file rclone-copy.log', - '--log-level INFO', - '--stats 30s', - '--stats-one-line', - '--stats-log-level INFO', - '--s3-chunk-size 64M', - '--no-check-certificate' - ].join(' ') + ext.args = { + def base_args = [ + '--log-level INFO', + '--stats 30s', + '--stats-one-line', + '--stats-log-level INFO', + '--s3-chunk-size 64M', + '--no-check-certificate' + ] + if (meta.http_url) { + base_args.add(0, meta.http_url) + } + base_args.join(' ') + } } withName: 'MULTIQC' { From c98256746aadb7a0de78518157c0c23efc95e2be Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 00:49:51 +0200 Subject: [PATCH 109/334] make rclone config an optional input --- modules/nf-core/rclone_copy/main.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/nf-core/rclone_copy/main.nf b/modules/nf-core/rclone_copy/main.nf index acd4c2c..86d800c 100644 --- a/modules/nf-core/rclone_copy/main.nf +++ b/modules/nf-core/rclone_copy/main.nf @@ -21,12 +21,13 @@ process RCLONE_COPY { script: def args = task.ext.args ?: '' - def configArg = rclone_config ? "--config '${rclone_config}'" : error("RCLONE_COPY requires an rclone config file") + def configArg = rclone_config ? "--config '${rclone_config}'" : '' def transfers = task.ext.transfers ?: task.cpus def checkers = task.ext.checkers ?: task.cpus """ rclone ${configArg} copy ${args} \\ + --log-file rclone-copy.log \\ --transfers ${transfers} \\ --checkers ${checkers} \\ "${source_path}" \\ From d52ff846e64055230518b4dfc8ff6148c2e80afe Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 00:50:54 +0200 Subject: [PATCH 110/334] include rclone in nf test --- tests/default.nf.test.snap | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 01e1954..7a60697 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -8,6 +8,9 @@ "MD5SUM": { "md5sum": 9.5 }, + "RCLONE_COPY": { + "rclone": "1.65.0-DEV" + }, "SHASUM": { "sha256sum": 9.5 }, @@ -39,25 +42,28 @@ "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", + "rclone", + "rclone/rclone-copy.log", "shasum", "shasum/Illumina_annotation.sha256", "shasum/benchmark_bed.sha256", "shasum/test_fastq.sha256" ], [ - "Illumina_annotation.checksum_summary.csv:md5,da71db43566c677ddc32186e53d4f30e", - "Illumina_annotation.checksum_validation.csv:md5,9032cc5084168ca56d501269fc1021e8", - "benchmark_bed.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", - "benchmark_bed.checksum_validation.csv:md5,d1e7087446c6138dba9929099787c5c9", - "test_fastq.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", - "test_fastq.checksum_validation.csv:md5,9f72112e05dc478eee7d3d56a6364cd0", - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + "Illumina_annotation.checksum_summary.csv:md5,7bd3942b0dcc63b26ef412696cf9daf3", + "Illumina_annotation.checksum_validation.csv:md5,17dc3989f455f3eea21f0229735ea8a2", + "benchmark_bed.checksum_summary.csv:md5,68e7706826f0d6cd71884db5a50b5eed", + "benchmark_bed.checksum_validation.csv:md5,e4124b2aa278c7e0f6c9fee49f2d791f", + "test_fastq.checksum_summary.csv:md5,68e7706826f0d6cd71884db5a50b5eed", + "test_fastq.checksum_validation.csv:md5,cbb5e7132b8177707dee1b0d79022538", + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "rclone-copy.log:md5,500fd4169d86d2ccfb70bd5b339d04e7" ] ], - "timestamp": "2026-06-29T21:12:58.023076335", + "timestamp": "2026-07-06T00:39:04.952249206", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "25.04.6" } } } \ No newline at end of file From 36c1d2f1d0a7c28a20b6a97eb93dd9a1b93874aa Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 00:51:12 +0200 Subject: [PATCH 111/334] include rclone dry run in nf test config --- tests/nextflow.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/nextflow.config b/tests/nextflow.config index da48321..0bb5b95 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -12,3 +12,9 @@ params { } aws.client.anonymous = true // fixes S3 access issues on self-hosted runners + +process { + withName: 'RCLONE_COPY' { + ext.args = '--dry-run --verbose' + } +} From 9aaa7df34c4b477bc9ea95d55ccfba9436a0bea0 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 00:52:22 +0200 Subject: [PATCH 112/334] add output path to input samplesheet + make rclone conf optional input --- workflows/datasync.nf | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 733b299..3cc0227 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -27,7 +27,6 @@ workflow DATASYNC { multiqc_logo multiqc_methods_description outdir - rclone_output_path rclone_config main: @@ -36,22 +35,32 @@ workflow DATASYNC { ch_multiqc_files = channel.empty() ch_samplesheet = ch_samplesheet.multiMap { - meta, input_path, md5, sha -> + meta, input_path, output_path, md5, sha -> def source_string = input_path.toString() - def rclone_source = source_string - .replaceFirst('^s3://', 's3:') + def rclone_source + def rclone_http_url = '' + + if (source_string ==~ /^https?:\/\/.*/) { + // HTTP: split into --http-url base and :http:path + def matcher = (source_string =~ /^(https?:\/\/[^\/]+)(\/.*)$/) + rclone_http_url = "--http-url '${matcher[0][1]}'" + rclone_source = ":http:${matcher[0][2].replaceFirst('^/', '')}" + } else { + // Cloud remotes (s3://, gs://, az://): strip :// to : + rclone_source = source_string.replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') + } - def source_name = rclone_source + def source_name = source_string .replaceAll('/+$', '') .tokenize('/') .last() - def rclone_destination = "${rclone_output_path.toString().replaceAll('/+$', '')}/${source_name}" + def rclone_destination = "${output_path.toString().replaceAll('/+$', '')}/${source_name}" input: [ meta, input_path ] - rclone: [ meta, rclone_source, rclone_destination ] + rclone: [ meta + [http_url: rclone_http_url], rclone_source, rclone_destination ] checksum: [ meta, md5, sha ] } @@ -87,10 +96,9 @@ workflow DATASYNC { // // MODULE: Rclone data copying // - RCLONE( + RCLONE_COPY( ch_samplesheet.rclone, - rclone_output_path, - rclone_config ? file(rclone_config, checkIfExists: true) : null + rclone_config ? file(rclone_config, checkIfExists: true) : [] ) // From aafb97b1673e2bdbd7acd4706beced842eea1f58 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 19:07:33 +0200 Subject: [PATCH 113/334] include rclone --dry-run as a parameter --- conf/test.config | 2 ++ conf/test_full.config | 4 ++++ nextflow.config | 8 +++++--- nextflow_schema.json | 12 ++++++------ tests/nextflow.config | 6 ------ 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/conf/test.config b/conf/test.config index 880dd04..cbdca47 100644 --- a/conf/test.config +++ b/conf/test.config @@ -27,4 +27,6 @@ params { // TODO nf-core: Give any required params for the test so that command line flags are not needed input = params.pipelines_testdata_base_path + "test-data/samplesheet.csv" genome = 'R64-1-1' + rclone_config = params.pipelines_testdata_base_path + "test-data/rclone.conf" + rclone_dry_run = true } diff --git a/conf/test_full.config b/conf/test_full.config index ae44f01..64ee5b7 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -21,4 +21,8 @@ params { // Genome references genome = 'R64-1-1' + + //Rclone options + rclone_config = params.pipelines_testdata_base_path + "test-data/rclone.conf" + rclone_dry_run = true } diff --git a/nextflow.config b/nextflow.config index 379a0a9..ac4c316 100644 --- a/nextflow.config +++ b/nextflow.config @@ -27,6 +27,7 @@ params { // Rclone options rclone_config = null + rclone_dry_run = false // Boilerplate options outdir = null @@ -61,6 +62,8 @@ workflow.output.mode = params.publish_dir_mode // Load base.config by default for all pipelines includeConfig 'conf/base.config' +// Load modules.config for DSL2 module specific options +includeConfig 'conf/modules.config' profiles { debug { @@ -257,7 +260,7 @@ manifest { description = """A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.""" mainScript = 'main.nf' defaultBranch = 'main' - nextflowVersion = '!>=25.10.2' + nextflowVersion = '!>=25.04.6' version = '1.0dev' doi = '' } @@ -271,5 +274,4 @@ validation { defaultIgnoreParams = ["genomes"] monochromeLogs = params.monochrome_logs } -// Load modules.config for DSL2 module specific options -includeConfig 'conf/modules.config' + diff --git a/nextflow_schema.json b/nextflow_schema.json index 13d1e17..4ecd1f5 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -41,12 +41,6 @@ "description": "MultiQC report title. Printed as page header, used for filename if not otherwise specified.", "fa_icon": "fas fa-file-signature" }, - "rclone_output_path": { - "type": "string", - "description": "Output path for Rclone data copying. Can be local path or remote storage path (s3://, gs://, etc.).", - "help_text": "Specify the destination path where data from the samplesheet will be copied to using Rclone. Sample IDs will be appended to this path. Supports local paths and cloud storage paths.", - "fa_icon": "fas fa-cloud-upload-alt" - }, "rclone_config": { "type": "string", "format": "file-path", @@ -54,6 +48,12 @@ "description": "Path to the rclone config file used for cloud storage authentication.", "help_text": "Provide an rclone config file to support cloud providers such as AWS S3 or Azure Blob Storage. This file is loaded by rclone when copying data.", "fa_icon": "fas fa-file" + }, + "rclone_dry_run": { + "type": "boolean", + "description": "Perform a dry run of the rclone copy command.", + "fa_icon": "fas fa-eye", + "help_text": "If set, the pipeline will not actually copy any files to the destination. Instead, it will print out what would have been copied. This is useful for testing and debugging." } } }, diff --git a/tests/nextflow.config b/tests/nextflow.config index 0bb5b95..da48321 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -12,9 +12,3 @@ params { } aws.client.anonymous = true // fixes S3 access issues on self-hosted runners - -process { - withName: 'RCLONE_COPY' { - ext.args = '--dry-run --verbose' - } -} From 5897bc267fb235559a762fd9eee5289af02de6f1 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 19:07:50 +0200 Subject: [PATCH 114/334] ignore rclone log file --- tests/.nftignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/.nftignore b/tests/.nftignore index 18b80cb..38c8c59 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -12,3 +12,4 @@ fastqc/*_fastqc.{html,zip} pipeline_info/*.{html,json,txt,yml} md5sum/** shasum/** +rclone/*.log From a4516c8b2b97339c018900af8d5c204c95379b09 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 19:08:22 +0200 Subject: [PATCH 115/334] include rclone --dry-run as a parameter --- conf/modules.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/modules.config b/conf/modules.config index 7335fdf..1059b2b 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -32,6 +32,9 @@ process { if (meta.http_url) { base_args.add(0, meta.http_url) } + if (params.rclone_dry_run) { + base_args.add('--dry-run') + } base_args.join(' ') } } From e5a01578a1c8e7996f6a78b84e48ae4c020c833c Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 19:08:58 +0200 Subject: [PATCH 116/334] update tests snapshots --- tests/default.nf.test.snap | 17 ++++++++--------- tests/main_full.nf.test.snap | 9 +++++++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 7a60697..9d40477 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -50,17 +50,16 @@ "shasum/test_fastq.sha256" ], [ - "Illumina_annotation.checksum_summary.csv:md5,7bd3942b0dcc63b26ef412696cf9daf3", - "Illumina_annotation.checksum_validation.csv:md5,17dc3989f455f3eea21f0229735ea8a2", - "benchmark_bed.checksum_summary.csv:md5,68e7706826f0d6cd71884db5a50b5eed", - "benchmark_bed.checksum_validation.csv:md5,e4124b2aa278c7e0f6c9fee49f2d791f", - "test_fastq.checksum_summary.csv:md5,68e7706826f0d6cd71884db5a50b5eed", - "test_fastq.checksum_validation.csv:md5,cbb5e7132b8177707dee1b0d79022538", - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "rclone-copy.log:md5,500fd4169d86d2ccfb70bd5b339d04e7" + "Illumina_annotation.checksum_summary.csv:md5,da71db43566c677ddc32186e53d4f30e", + "Illumina_annotation.checksum_validation.csv:md5,9032cc5084168ca56d501269fc1021e8", + "benchmark_bed.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", + "benchmark_bed.checksum_validation.csv:md5,d1e7087446c6138dba9929099787c5c9", + "test_fastq.checksum_summary.csv:md5,79bca6fd02a7888f38a493591289fbb5", + "test_fastq.checksum_validation.csv:md5,9f72112e05dc478eee7d3d56a6364cd0", + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-07-06T00:39:04.952249206", + "timestamp": "2026-07-06T19:01:01.083839406", "meta": { "nf-test": "0.9.5", "nextflow": "25.04.6" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index c8636b2..ae6034d 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -8,6 +8,9 @@ "MD5SUM": { "md5sum": 9.5 }, + "RCLONE_COPY": { + "rclone": "1.65.0-DEV" + }, "SHASUM": { "sha256sum": 9.5 }, @@ -33,6 +36,8 @@ "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", + "rclone", + "rclone/rclone-copy.log", "shasum", "shasum/demultiplex.sha256" ], @@ -42,10 +47,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-06-29T21:15:25.735838624", + "timestamp": "2026-07-06T19:05:22.28116912", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "25.04.6" } } } \ No newline at end of file From 6a5d7afde87de0d3e47e7e1bfdfd8eeb949e67a1 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Mon, 6 Jul 2026 22:04:57 +0200 Subject: [PATCH 117/334] update samplesheet format --- assets/samplesheet.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index f61475a..6d48fd6 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,2 +1,2 @@ -sample,input,checksum_md5 -sample,path/to/file,path/to/file +sample,input,output_path,checksum_md5 +sample,path/to/file,output_path,path/to/file From eecb805020eec274d6df4d9bee1634063a256571 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 6 Jul 2026 22:09:58 +0200 Subject: [PATCH 118/334] Add input samplesheet to report and add description --- assets/multiqc_config.yml | 48 +++++++++++++++++++++++++++++++++++++++ workflows/datasync.nf | 1 + 2 files changed, 49 insertions(+) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index db9d1ce..1a4260f 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -15,16 +15,52 @@ export_plots: true disable_version_detection: true custom_data: + samplesheet: + section_name: "Input Samplesheet" + plot_type: "table" + file_format: "csv" + headers: + sample: + title: Sample ID + input: + title: Path to copy + checksum_md5: + title: MD5 checksum file + checksum_sha: + title: Sha256 checksum file + output_path: + title: Destination path + md5_checksum_summary: section_name: "MD5 Checksum Summary" description: "Summary of MD5 checksum validation" plot_type: "table" file_format: "csv" + headers: + Match: + description: "Number of files whose output checksum matches the expected checksum." + Mismatch: + description: "Number of files whose output checksum differs from the expected checksum." + Missing: + description: "Number of expected input files that are missing from the output." + Unexpected: + description: "Number of output files that were not present in the input checksum list." + sha_checksum_summary: section_name: "SHA Checksum Summary" description: "Summary of SHA checksum validation" plot_type: "table" file_format: "csv" + headers: + Match: + description: "Number of files whose output checksum matches the expected checksum." + Mismatch: + description: "Number of files whose output checksum differs from the expected checksum." + Missing: + description: "Number of expected input files that are missing from the output." + Unexpected: + description: "Number of output files that were not present in the input checksum list." + md5_checksum_report: section_name: "MD5 Checksum Report" description: "Detailed MD5 checksum validation report" @@ -35,12 +71,17 @@ custom_data: headers: File: title: File + description: "Path to the file being validated." checksum_expected: title: Expected checksum + description: "Checksum recorded for the input file before processing." checksum_observed: title: Observed checksum + description: "Checksum calculated for the corresponding output file after processing." status: title: Status + description: "Comparison result between the expected and observed checksums." + sha_checksum_report: section_name: "SHA Checksum Report" description: "Detailed SHA checksum validation report" @@ -51,14 +92,21 @@ custom_data: headers: File: title: File + description: "Path to the file being validated." checksum_expected: title: Expected checksum + description: "Checksum recorded for the input file before processing." checksum_observed: title: Observed checksum + description: "Checksum calculated for the corresponding output file after processing." status: title: Status + description: "Comparison result between the expected and observed checksums." sp: + samplesheet: + fn: "samplesheet.csv" + md5_checksum_summary: fn: "*_md5.checksum_summary.csv" sha_checksum_summary: diff --git a/workflows/datasync.nf b/workflows/datasync.nf index b0fd99e..f347d39 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -101,6 +101,7 @@ workflow DATASYNC { // // MODULE: MultiQC // + ch_multiqc_files = ch_multiqc_files.mix(Channel.fromPath(params.input).collectFile(name: 'samplesheet.csv', newLine: true)) ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) def ch_summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") def ch_workflow_summary = channel.value(paramsSummaryMultiqc(ch_summary_params)) From 8a7632a1b617f700903ca84da7d9ac81f63793ea Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 6 Jul 2026 22:10:45 +0200 Subject: [PATCH 119/334] Add citation text --- .../local/utils_nfcore_datasync_pipeline/main.nf | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 36e6680..818902c 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -181,8 +181,10 @@ def toolCitationText() { // Uncomment function in methodsDescriptionText to render in MultiQC report def citation_text = [ "Tools used in the workflow included:", - "FastQC (Andrews 2010),", - "MultiQC (Ewels et al. 2016)", + "Files were transferred to the specified destination using Rclone (Nick Craig-Wood, https://rclone.org), which supports data movement across local and cloud storage backends.", + "File integrity was validated by computing cryptographic checksums using md5sum and shasum.", + "Expected and observed checksum files were compared using the pipeline's local comparechecksum module, implemented in R.", + "Pipeline results were summarised with MultiQC (Ewels et al. 2016)", "." ].join(' ').trim() @@ -194,8 +196,7 @@ def toolBibliographyText() { // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "
  • Author (2023) Pub name, Journal, DOI
  • " : "", // Uncomment function in methodsDescriptionText to render in MultiQC report def reference_text = [ - "
  • Andrews S, (2010) FastQC, URL: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/).
  • ", - "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics , 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " + "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics, 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " ].join(' ').trim() return reference_text @@ -219,15 +220,15 @@ def methodsDescriptionText(mqc_methods_yaml) { } meta["doi_text"] = temp_doi_ref.substring(0, temp_doi_ref.length() - 2) } else meta["doi_text"] = "" - meta["nodoi_text"] = meta.manifest_map.doi ? "" : "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " + meta["nodoi_text"] = meta.manifest_map.doi ?: "" // Tool references meta["tool_citations"] = "" meta["tool_bibliography"] = "" // TODO nf-core: Only uncomment below if logic in toolCitationText/toolBibliographyText has been filled! - // meta["tool_citations"] = toolCitationText().replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") - // meta["tool_bibliography"] = toolBibliographyText() + meta["tool_citations"] = toolCitationText().replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") + meta["tool_bibliography"] = toolBibliographyText() def methods_text = mqc_methods_yaml.text From d45029e7510b7c4d7e7e8a4be1716cb9f439e371 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Mon, 6 Jul 2026 20:59:19 +0000 Subject: [PATCH 120/334] move rclone to local folder --- .../rclone_copy-260706205833}/environment.yml | 0 .../rclone_copy => local/rclone_copy-260706205833}/main.nf | 0 .../rclone_copy => local/rclone_copy-260706205833}/meta.yml | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename modules/{nf-core/rclone_copy => local/rclone_copy-260706205833}/environment.yml (100%) rename modules/{nf-core/rclone_copy => local/rclone_copy-260706205833}/main.nf (100%) rename modules/{nf-core/rclone_copy => local/rclone_copy-260706205833}/meta.yml (100%) diff --git a/modules/nf-core/rclone_copy/environment.yml b/modules/local/rclone_copy-260706205833/environment.yml similarity index 100% rename from modules/nf-core/rclone_copy/environment.yml rename to modules/local/rclone_copy-260706205833/environment.yml diff --git a/modules/nf-core/rclone_copy/main.nf b/modules/local/rclone_copy-260706205833/main.nf similarity index 100% rename from modules/nf-core/rclone_copy/main.nf rename to modules/local/rclone_copy-260706205833/main.nf diff --git a/modules/nf-core/rclone_copy/meta.yml b/modules/local/rclone_copy-260706205833/meta.yml similarity index 100% rename from modules/nf-core/rclone_copy/meta.yml rename to modules/local/rclone_copy-260706205833/meta.yml From f70feecff4b97fb74d7379eada816380c181da91 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Mon, 6 Jul 2026 21:02:52 +0000 Subject: [PATCH 121/334] run commit fix --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d43c74d..87aab4d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). From 5513e6482913ee26f5d3ef7721e8f8fb9625542c Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Mon, 6 Jul 2026 21:03:01 +0000 Subject: [PATCH 122/334] update nextflow version --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index ac4c316..f95a8bf 100644 --- a/nextflow.config +++ b/nextflow.config @@ -260,7 +260,7 @@ manifest { description = """A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.""" mainScript = 'main.nf' defaultBranch = 'main' - nextflowVersion = '!>=25.04.6' + nextflowVersion = '!>=25.10.4' version = '1.0dev' doi = '' } From 3a98fc62f29975ca94aeda9e4aa9a05b0e210ee7 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Mon, 6 Jul 2026 21:41:52 +0000 Subject: [PATCH 123/334] move rclone to local folder --- .../{rclone_copy-260706205833 => rclone_copy}/environment.yml | 0 modules/local/{rclone_copy-260706205833 => rclone_copy}/main.nf | 0 .../local/{rclone_copy-260706205833 => rclone_copy}/meta.yml | 0 workflows/datasync.nf | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) rename modules/local/{rclone_copy-260706205833 => rclone_copy}/environment.yml (100%) rename modules/local/{rclone_copy-260706205833 => rclone_copy}/main.nf (100%) rename modules/local/{rclone_copy-260706205833 => rclone_copy}/meta.yml (100%) diff --git a/modules/local/rclone_copy-260706205833/environment.yml b/modules/local/rclone_copy/environment.yml similarity index 100% rename from modules/local/rclone_copy-260706205833/environment.yml rename to modules/local/rclone_copy/environment.yml diff --git a/modules/local/rclone_copy-260706205833/main.nf b/modules/local/rclone_copy/main.nf similarity index 100% rename from modules/local/rclone_copy-260706205833/main.nf rename to modules/local/rclone_copy/main.nf diff --git a/modules/local/rclone_copy-260706205833/meta.yml b/modules/local/rclone_copy/meta.yml similarity index 100% rename from modules/local/rclone_copy-260706205833/meta.yml rename to modules/local/rclone_copy/meta.yml diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 3cc0227..882155d 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -6,7 +6,7 @@ include { COMPARECHECKSUM } from '../modules/local/comparechecksum/main' include { MD5SUM } from '../modules/nf-core/md5sum/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' -include { RCLONE_COPY } from '../modules/nf-core/rclone_copy/main' +include { RCLONE_COPY } from '../modules/local/rclone_copy/main' include { SHASUM } from '../modules/nf-core/shasum/main' include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' From 80b09cac2463f24515be4a7ee9ca0b26e32fee79 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Mon, 6 Jul 2026 21:47:04 +0000 Subject: [PATCH 124/334] run fix lint --- modules/local/rclone_copy/main.nf | 2 +- modules/local/rclone_copy/meta.yml | 2 +- nextflow.config | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/local/rclone_copy/main.nf b/modules/local/rclone_copy/main.nf index 86d800c..e76d5d4 100644 --- a/modules/local/rclone_copy/main.nf +++ b/modules/local/rclone_copy/main.nf @@ -38,4 +38,4 @@ process RCLONE_COPY { """ touch rclone-copy.log """ -} \ No newline at end of file +} diff --git a/modules/local/rclone_copy/meta.yml b/modules/local/rclone_copy/meta.yml index 039a786..f3ad059 100644 --- a/modules/local/rclone_copy/meta.yml +++ b/modules/local/rclone_copy/meta.yml @@ -62,4 +62,4 @@ output: description: The name of the tool. - version: type: string - description: The version of Rclone used. \ No newline at end of file + description: The version of Rclone used. diff --git a/nextflow.config b/nextflow.config index f95a8bf..bcb1627 100644 --- a/nextflow.config +++ b/nextflow.config @@ -274,4 +274,3 @@ validation { defaultIgnoreParams = ["genomes"] monochromeLogs = params.monochrome_logs } - From 03a79a30190d5f08001e4d22d733cf62a17ee7bf Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Mon, 6 Jul 2026 21:51:13 +0000 Subject: [PATCH 125/334] fix --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 87aab4d..d43c74d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). From db581e8ec418bc1c9e3746d692a20879751f9ac8 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 7 Jul 2026 09:50:55 -0300 Subject: [PATCH 126/334] Update CHANGELOG with new features and fixes --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 132fb4c..5cc972f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). +- [[#29]](https://github.com/nf-core/datasync/pull/38)] - Implement Rclone module. ([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)) ### `Fixed` From 7da1d5a7dd2fa21feb95969c90789573687bd3e2 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 7 Jul 2026 15:33:42 +0200 Subject: [PATCH 127/334] Do not expert plots for multiqc and update snapshots --- assets/multiqc_config.yml | 6 +++--- tests/default.nf.test.snap | 18 +++++------------- tests/main_full.nf.test.snap | 22 ++++------------------ workflows/datasync.nf | 2 +- 4 files changed, 13 insertions(+), 35 deletions(-) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 1a4260f..693d656 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -10,7 +10,7 @@ report_section_order: "nf-core-datasync-summary": order: -1002 -export_plots: true +export_plots: false disable_version_detection: true @@ -24,12 +24,12 @@ custom_data: title: Sample ID input: title: Path to copy + output_path: + title: Destination path checksum_md5: title: MD5 checksum file checksum_sha: title: Sha256 checksum file - output_path: - title: Destination path md5_checksum_summary: section_name: "MD5 Checksum Summary" diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 89f57f8..aaa0996 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -39,18 +39,9 @@ "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_md5_checksum_report.txt", "multiqc/multiqc_data/multiqc_md5_checksum_summary.txt", + "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_plots", - "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/md5_checksum_report.pdf", - "multiqc/multiqc_plots/pdf/md5_checksum_summary.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/md5_checksum_report.png", - "multiqc/multiqc_plots/png/md5_checksum_summary.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/md5_checksum_report.svg", - "multiqc/multiqc_plots/svg/md5_checksum_summary.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", @@ -70,13 +61,14 @@ "test_fastq_md5.checksum_validation.csv:md5,4c94e3b3362f854c42941fc67b226ac2", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_md5_checksum_report.txt:md5,39147d72a414c399614f139354e36a86", - "multiqc_md5_checksum_summary.txt:md5,d8c3b87b26251d4d6cb1aca315f0f531" + "multiqc_md5_checksum_summary.txt:md5,d8c3b87b26251d4d6cb1aca315f0f531", + "multiqc_samplesheet.txt:md5,3cc1e0340101fe132e7ce466187f3c4b" ] ], - "timestamp": "2026-07-06T19:01:01.083839406", + "timestamp": "2026-07-07T15:28:47.101399362", "meta": { "nf-test": "0.9.5", - "nextflow": "25.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 1ab4830..a5a2652 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -35,26 +35,11 @@ "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_md5_checksum_report.txt", "multiqc/multiqc_data/multiqc_md5_checksum_summary.txt", + "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_sha_checksum_report.txt", "multiqc/multiqc_data/multiqc_sha_checksum_summary.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_plots", - "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/md5_checksum_report.pdf", - "multiqc/multiqc_plots/pdf/md5_checksum_summary.pdf", - "multiqc/multiqc_plots/pdf/sha_checksum_report.pdf", - "multiqc/multiqc_plots/pdf/sha_checksum_summary.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/md5_checksum_report.png", - "multiqc/multiqc_plots/png/md5_checksum_summary.png", - "multiqc/multiqc_plots/png/sha_checksum_report.png", - "multiqc/multiqc_plots/png/sha_checksum_summary.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/md5_checksum_report.svg", - "multiqc/multiqc_plots/svg/md5_checksum_summary.svg", - "multiqc/multiqc_plots/svg/sha_checksum_report.svg", - "multiqc/multiqc_plots/svg/sha_checksum_summary.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", @@ -71,14 +56,15 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_md5_checksum_report.txt:md5,8d84f5711d802cd908cf5780f1fd029e", "multiqc_md5_checksum_summary.txt:md5,14a9c197093f8cd187833a11e13a3c58", + "multiqc_samplesheet.txt:md5,95d11730dbbf9fee3ca00f2792330c63", "multiqc_sha_checksum_report.txt:md5,52c4bffaf0a94c59d4c2111fc62c074d", "multiqc_sha_checksum_summary.txt:md5,78a00f0c20054c0f1853ceac0fcc0172" ] ], - "timestamp": "2026-07-06T19:05:22.28116912", + "timestamp": "2026-07-07T15:30:52.986332849", "meta": { "nf-test": "0.9.5", - "nextflow": "25.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 64e5e96..d949873 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -135,7 +135,7 @@ workflow DATASYNC { // // MODULE: MultiQC // - ch_multiqc_files = ch_multiqc_files.mix(Channel.fromPath(params.input).collectFile(name: 'samplesheet.csv', newLine: true)) + ch_multiqc_files = ch_multiqc_files.mix(Channel.fromPath(params.input).collectFile(name: 'samplesheet.csv')) ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) def ch_summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") def ch_workflow_summary = channel.value(paramsSummaryMultiqc(ch_summary_params)) From b55010830d14289377bf04b9a3ee10616cec9829 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 7 Jul 2026 19:19:55 +0000 Subject: [PATCH 128/334] Ignore linting for multiqc_config file --- .nf-core.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.nf-core.yml b/.nf-core.yml index 0f562d9..cf24bd7 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -10,3 +10,5 @@ template: org: nf-core outdir: . version: 1.0dev +lint: + multiqc_config: false From 018e1afb89d0aeee395c4011c3b95f06b6333800 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 7 Jul 2026 19:26:00 +0000 Subject: [PATCH 129/334] Remove notes from report --- assets/methods_description_template.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml index b7c9849..b03e887 100644 --- a/assets/methods_description_template.yml +++ b/assets/methods_description_template.yml @@ -19,11 +19,3 @@ data: |
  • da Veiga Leprevost, F., Grüning, B. A., Alves Aflitos, S., Röst, H. L., Uszkoreit, J., Barsnes, H., Vaudel, M., Moreno, P., Gatto, L., Weber, J., Bai, M., Jimenez, R. C., Sachsenberg, T., Pfeuffer, J., Vera Alvarez, R., Griss, J., Nesvizhskii, A. I., & Perez-Riverol, Y. (2017). BioContainers: an open-source and community-driven framework for software standardization. Bioinformatics (Oxford, England), 33(16), 2580–2582. doi: 10.1093/bioinformatics/btx192
  • ${tool_bibliography} -
    -
    Notes:
    -
      - ${nodoi_text} -
    • The command above does not include parameters contained in any configs or profiles that may have been used. Ensure the config file is also uploaded with your publication!
    • -
    • You should also cite all software used within this run. Check the "Software Versions" of this report to get version information.
    • -
    -
    From c8891744b4b803bbddd7f444ba176bfbcee53c5e Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 7 Jul 2026 20:20:12 +0000 Subject: [PATCH 130/334] Update multiqc module --- conf/containers_conda_lock_files_amd64.config | 2 +- conf/containers_conda_lock_files_arm64.config | 2 +- conf/containers_docker_amd64.config | 2 +- conf/containers_docker_arm64.config | 2 +- .../containers_singularity_https_amd64.config | 2 +- .../containers_singularity_https_arm64.config | 2 +- conf/containers_singularity_oras_amd64.config | 2 +- conf/containers_singularity_oras_arm64.config | 2 +- modules.json | 2 +- ... => linux_amd64-bd-c17fb751507e9dfc_1.txt} | 806 +++++++++--------- .../linux_amd64-bd-db7c73dae76bc9e6_1.txt | 126 --- ... => linux_arm64-bd-5c84a5000a226ab5_1.txt} | 804 +++++++++-------- .../linux_arm64-bd-d167b8012595a136_1.txt | 125 --- modules/nf-core/multiqc/environment.yml | 2 +- modules/nf-core/multiqc/main.nf | 4 +- modules/nf-core/multiqc/meta.yml | 28 +- .../nf-core/multiqc/tests/main.nf.test.snap | 10 +- 17 files changed, 810 insertions(+), 1113 deletions(-) rename modules/nf-core/multiqc/.conda-lock/{linux_amd64-bd-c1f4a7982b743963_1.txt => linux_amd64-bd-c17fb751507e9dfc_1.txt} (75%) delete mode 100644 modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt rename modules/nf-core/multiqc/.conda-lock/{linux_arm64-bd-40bf3b435e89dc22_1.txt => linux_arm64-bd-5c84a5000a226ab5_1.txt} (74%) delete mode 100644 modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index f487ba4..01cc545 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1 +1 @@ -process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt' } } +process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index e9a3fed..6864e0b 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1 +1 @@ -process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt' } } +process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } diff --git a/conf/containers_docker_amd64.config b/conf/containers_docker_amd64.config index 01b59df..ea18c3f 100644 --- a/conf/containers_docker_amd64.config +++ b/conf/containers_docker_amd64.config @@ -1 +1 @@ -process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6' } } +process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc' } } diff --git a/conf/containers_docker_arm64.config b/conf/containers_docker_arm64.config index 7785cb1..369f743 100644 --- a/conf/containers_docker_arm64.config +++ b/conf/containers_docker_arm64.config @@ -1 +1 @@ -process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.34--d167b8012595a136' } } +process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--5c84a5000a226ab5' } } diff --git a/conf/containers_singularity_https_amd64.config b/conf/containers_singularity_https_amd64.config index 754821b..932fc7c 100644 --- a/conf/containers_singularity_https_amd64.config +++ b/conf/containers_singularity_https_amd64.config @@ -1 +1 @@ -process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data' } } +process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' } } diff --git a/conf/containers_singularity_https_arm64.config b/conf/containers_singularity_https_arm64.config index 93071de..4f79532 100644 --- a/conf/containers_singularity_https_arm64.config +++ b/conf/containers_singularity_https_arm64.config @@ -1 +1 @@ -process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/9a/9a1fec9662a152683e6fcae440d0ce20920b3b89dc62d1e3a52e73f92eba0969/data' } } +process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e4/e48aa28aebc881254a499b24c3e1ce77b8df1b85a5432699ed6f72eb17ac7fb5/data' } } diff --git a/conf/containers_singularity_oras_amd64.config b/conf/containers_singularity_oras_amd64.config index 952881d..2fa065b 100644 --- a/conf/containers_singularity_oras_amd64.config +++ b/conf/containers_singularity_oras_amd64.config @@ -1 +1 @@ -process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.34--4fc8657c816047c0' } } +process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2' } } diff --git a/conf/containers_singularity_oras_arm64.config b/conf/containers_singularity_oras_arm64.config index 498ec50..84f0792 100644 --- a/conf/containers_singularity_oras_arm64.config +++ b/conf/containers_singularity_oras_arm64.config @@ -1 +1 @@ -process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.34--7fbd82d945c06726' } } +process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c0468833d65b2f81' } } diff --git a/modules.json b/modules.json index 711f257..68a6e9b 100644 --- a/modules.json +++ b/modules.json @@ -12,7 +12,7 @@ }, "multiqc": { "branch": "master", - "git_sha": "008f9d3e61209bf995edac3ba531f54e269e1215", + "git_sha": "98403d15b0e50edae1f3fec5eae5e24982f1fade", "installed_by": ["modules"] }, "shasum": { diff --git a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt similarity index 75% rename from modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt rename to modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt index 7619030..2a91c22 100644 --- a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt +++ b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt @@ -14,120 +14,118 @@ linux-64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.0-h27c8c51_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda -- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py314h2b28147_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.6-py314h2b28147_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.1.1-py314h8ec4b1a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.2.0-py314h8ec4b1a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.39.3-py310hffdcd12_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.39.3-py310hbcd5346_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.41.0-py310h49dadd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.41.0-py310hcbd6021_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py314h2e6c369_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.4-py314h2e6c369_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.5-habeac84_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.2.28-py314h5bd0f2a_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.5.9-py314h5bd0f2a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.52.0-h04a0ce9_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.1-hbc0de68_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda packages: @@ -174,15 +172,15 @@ license: MIT license_family: MIT size: 64927 timestamp: 1773935801332 -- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda noarch: generic -sha256: c31ab719d256bc6f89926131e88ecd0f0c5d003fe8481852c6424f4ec6c7eb29 -md5: a2ac7763a9ac75055b68f325d3255265 +sha256: a1c97297e867776760489537bc5ae36fa83a154be30e3b79385a39ca4cb058fe +md5: 1133126d840e75287d83947be3fc3e71 depends: - python >=3.14 license: BSD-3-Clause AND MIT AND EPL-2.0 -size: 7514 -timestamp: 1767044983590 +size: 7533 +timestamp: 1778594057496 - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda sha256: 3ad3500bff54a781c29f16ce1b288b36606e2189d0b0ef2f67036554f47f12b0 md5: 8910d2c46f7e7b519129f486e0fe927a @@ -208,42 +206,42 @@ license: bzip2-1.0.6 license_family: BSD size: 260182 timestamp: 1771350215188 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc -md5: 4492fd26db29495f0ba23f146cd5638d +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +sha256: 9812a303a1395e1dafbd92e5bc8a1ff6013bcbba0a09c7f03a8d23e43560aa9b +md5: 489b8e97e666c93f68fdb35c3c9b957f depends: - __unix license: ISC -size: 147413 -timestamp: 1772006283803 -- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda -sha256: a6b118fd1ed6099dc4fc03f9c492b88882a780fadaef4ed4f93dc70757713656 -md5: 765c4d97e877cdbbb88ff33152b86125 +size: 129868 +timestamp: 1779289852439 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +sha256: 645655a3510e38e625da136595f3f16f2130c3263630cc3bc8f60f619ddbe490 +md5: 9fefff2f745ea1cc2ef15211a20c054a depends: - python >=3.10 license: ISC -size: 151445 -timestamp: 1772001170301 -- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda -sha256: d86dfd428b2e3c364fa90e07437c8405d635aa4ef54b25ab51d9c712be4112a5 -md5: 49ee13eb9b8f44d63879c69b8a40a74b +size: 134201 +timestamp: 1779285131141 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +sha256: 3f9483d62ce24ecd063f8a5a714448445dc8d9e201147c46699fc0033e824457 +md5: a9167b9571f3baa9d448faa2139d1089 depends: - python >=3.10 license: MIT license_family: MIT -size: 58510 -timestamp: 1773660086450 -- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda -sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715 -md5: ea8a6c3256897cc31263de9f455e25d9 +size: 58872 +timestamp: 1775127203018 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +sha256: 99ab8ef815c4520cce3a7482c2513f377c14348206857661d84c76a55e030f97 +md5: 003767c47f1f0a474c4de268b57839c3 depends: -- python >=3.10 - __unix - python +- python >=3.10 license: BSD-3-Clause license_family: BSD -size: 97676 -timestamp: 1764518652276 +size: 104631 +timestamp: 1779108494556 - conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 md5: b866ff7007b934d564961066c8195983 @@ -265,27 +263,27 @@ license: BSD-3-Clause license_family: BSD size: 39326 timestamp: 1735759976140 -- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda noarch: generic -sha256: 91b06300879df746214f7363d6c27c2489c80732e46a369eb2afc234bcafb44c -md5: 3bb89e4f795e5414addaa531d6b1500a +sha256: 777882d2685f368417f31bbe1b28f73687fc6c8f6a5768bda20ffeefa6b07f5b +md5: a749029ce5d0632a913db19d17f944ab depends: - python >=3.14,<3.15.0a0 - python_abi * *_cp314 license: Python-2.0 -size: 50078 -timestamp: 1770674447292 -- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda -sha256: 0cc345e4dead417996ce9a1f088b28d858f03d113d43c1963d29194366dcce27 -md5: a0535741a4934b3e386051065c58761a +size: 50212 +timestamp: 1779236682725 +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_0.conda +sha256: 29a10599d56d93bd750914888ebe6822d47722070762b4647b34d12df9f4476e +md5: d0757fd84af06f065eba49d39af6c546 depends: - __glibc >=2.17,<3.0.a0 -- libexpat 2.7.4 hecca717_0 +- libexpat 2.8.1 hecca717_0 - libgcc >=14 license: MIT license_family: MIT -size: 145274 -timestamp: 1771259434699 +size: 148238 +timestamp: 1779278694477 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b md5: 0c96522c6bdaed4b1566d11387caaf45 @@ -314,21 +312,21 @@ license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 license_family: Other size: 1620504 timestamp: 1727511233259 -- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda -sha256: aa4a44dba97151221100a637c7f4bde619567afade9c0265f8e1c8eed8d7bd8c -md5: 867127763fbe935bab59815b6e0b7b5c +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.0-h27c8c51_0.conda +sha256: e798086d8a65d55dc4c51f5746705639c9a5f2eeb0b8fc50e6152cfc0d69a4e8 +md5: 06965b2f9854d0b15e0443ee81fe83dc depends: - __glibc >=2.17,<3.0.a0 -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 +- libexpat >=2.8.1,<3.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 - libgcc >=14 -- libuuid >=2.41.3,<3.0a0 -- libzlib >=1.3.1,<2.0a0 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 license: MIT license_family: MIT -size: 270705 -timestamp: 1771382710863 +size: 280882 +timestamp: 1779421631622 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 md5: a7970cd949a077b7cb9696379d338681 @@ -390,37 +388,26 @@ license: MIT license_family: MIT size: 17397 timestamp: 1737618427549 -- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda -sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a -md5: c80d8a3b84358cb967fa81e7075fbc8a -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libstdcxx >=14 -license: MIT -license_family: MIT -size: 12723451 -timestamp: 1773822285671 -- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda -sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 -md5: 53abe63df7e10a6ba605dc5f9f961d36 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +sha256: 3d25f9f6f7ab3e1ce6429fc8c8aae0335cf446692e715068488536d220cc43de +md5: 1b9083b7f00609605d1483dbc6071a81 depends: - python >=3.10 +- python license: BSD-3-Clause license_family: BSD -size: 50721 -timestamp: 1760286526795 -- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda -sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 -md5: 080594bf4493e6bae2607e65390c520a +size: 62642 +timestamp: 1779294335905 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +sha256: 43e2a5497cad1598ff88a3e69f69bc88b7b8f141fa63c60eab5db296317318b8 +md5: ffc17e785d64e12fc311af9184221839 depends: - python >=3.10 - zipp >=3.20 - python license: Apache-2.0 -license_family: APACHE -size: 34387 -timestamp: 1773931568510 +size: 34766 +timestamp: 1779714582554 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b md5: 04558c96691bed63104678757beb4f8d @@ -474,18 +461,18 @@ license: MIT license_family: MIT size: 62099926 timestamp: 1615199463039 -- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda -sha256: 836ec4b895352110335b9fdcfa83a8dcdbe6c5fb7c06c4929130600caea91c0a -md5: 6f2e2c8f58160147c4d1c6f4c14cbac4 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_0.conda +sha256: eb89c6c39f2f6a93db55723dbb2f6bba8c8e63e6312bf1abf13e6e9ff45849c8 +md5: f92f984b558e6e6204014b16d212b271 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 -- libjpeg-turbo >=3.1.2,<4.0a0 +- libjpeg-turbo >=3.1.4.1,<4.0a0 - libtiff >=4.7.1,<4.8.0a0 license: MIT license_family: MIT -size: 249959 -timestamp: 1768184673131 +size: 251086 +timestamp: 1778079286384 - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c md5: 18335a698559cdbcd86150a48bf54ba6 @@ -509,37 +496,37 @@ license: Apache-2.0 license_family: Apache size: 261513 timestamp: 1773113328888 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda -build_number: 5 -sha256: 18c72545080b86739352482ba14ba2c4815e19e26a7417ca21a95b76ec8da24c -md5: c160954f7418d7b6e87eaf05a8913fa9 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda +build_number: 7 +sha256: 081c850f99bc355821fac9c6e3727d40b3f8ce3beb50a5437cf03726b611ff39 +md5: 955b44e8b00b7f7ef4ce0130cef12394 depends: -- libopenblas >=0.3.30,<0.3.31.0a0 -- libopenblas >=0.3.30,<1.0a0 +- libopenblas >=0.3.33,<0.3.34.0a0 +- libopenblas >=0.3.33,<1.0a0 constrains: -- mkl <2026 -- liblapack 3.11.0 5*_openblas -- libcblas 3.11.0 5*_openblas -- blas 2.305 openblas -- liblapacke 3.11.0 5*_openblas +- libcblas 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapack 3.11.0 7*_openblas +- liblapacke 3.11.0 7*_openblas +- mkl <2027 license: BSD-3-Clause license_family: BSD -size: 18213 -timestamp: 1765818813880 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda -build_number: 5 -sha256: 0cbdcc67901e02dc17f1d19e1f9170610bd828100dc207de4d5b6b8ad1ae7ad8 -md5: 6636a2b6f1a87572df2970d3ebc87cc0 -depends: -- libblas 3.11.0 5_h4a7cf45_openblas +size: 18716 +timestamp: 1778489854108 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda +build_number: 7 +sha256: 956ae0bb1ec8b0c3663d75b151aceb0521b54e513bf97f621a035f9c87037970 +md5: 0675639dc24cb0032f199e7ff68e4633 +depends: +- libblas 3.11.0 7_h4a7cf45_openblas constrains: -- liblapacke 3.11.0 5*_openblas -- blas 2.305 openblas -- liblapack 3.11.0 5*_openblas +- liblapacke 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapack 3.11.0 7*_openblas license: BSD-3-Clause license_family: BSD -size: 18194 -timestamp: 1765818837135 +size: 18675 +timestamp: 1778489861559 - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 md5: 6c77a605a7a689d17d4819c0f8ac9a00 @@ -550,18 +537,18 @@ license: MIT license_family: MIT size: 73490 timestamp: 1761979956660 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda -sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 -md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda +sha256: 363018b25fdb5534c79783d912bd4b685a3547f4fc5996357ad548899b0ee8e7 +md5: 93764a5ca80616e9c10106cdaec92f74 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 constrains: -- expat 2.7.4.* +- expat 2.8.1.* license: MIT license_family: MIT -size: 76798 -timestamp: 1771259418166 +size: 77294 +timestamp: 1779278686680 - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 md5: a360c33a5abe61c07959e449fa1453eb @@ -593,42 +580,42 @@ constrains: license: GPL-2.0-only OR FTL size: 384575 timestamp: 1774298162622 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda -sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 -md5: 0aa00f03f9e39fb9876085dee11a85d4 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +sha256: 8e0a3b5e41272e5678499b5dfc4cddb673f9e935de01eb0767ce857001229f46 +md5: 57736f29cc2b0ec0b6c2952d3f101b6a depends: - __glibc >=2.17,<3.0.a0 - _openmp_mutex >=4.5 constrains: -- libgcc-ng ==15.2.0=*_18 -- libgomp 15.2.0 he0feb66_18 +- libgcc-ng ==15.2.0=*_19 +- libgomp 15.2.0 he0feb66_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 1041788 -timestamp: 1771378212382 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda -sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 -md5: d5e96b1ed75ca01906b3d2469b4ce493 +size: 1041084 +timestamp: 1778269013026 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda +sha256: 9dcf54adfaa5e861123c2da4f2f0451a685464ea7e5a41ad91cf67b31d658d98 +md5: 331ee9b72b9dff570d56b1302c5ab37d depends: -- libgcc 15.2.0 he0feb66_18 +- libgcc 15.2.0 he0feb66_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 27526 -timestamp: 1771378224552 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda -sha256: d2c9fad338fd85e4487424865da8e74006ab2e2475bd788f624d7a39b2a72aee -md5: 9063115da5bc35fdc3e1002e69b9ef6e +size: 27694 +timestamp: 1778269016987 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda +sha256: 561a42758ef25b9ce308c4e2cf56daee4f06138385a17e29a492cd928e00be6f +md5: 42bf7eca1a951735fa06c0e3c0d5c8e6 depends: -- libgfortran5 15.2.0 h68bc16d_18 +- libgfortran5 15.2.0 h68bc16d_19 constrains: -- libgfortran-ng ==15.2.0=*_18 +- libgfortran-ng ==15.2.0=*_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 27523 -timestamp: 1771378269450 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda -sha256: 539b57cf50ec85509a94ba9949b7e30717839e4d694bc94f30d41c9d34de2d12 -md5: 646855f357199a12f02a87382d429b75 +size: 27655 +timestamp: 1778269042954 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda +sha256: 057978bb69fea29ed715a9b98adf71015c31baecc4aeb2bfc20d4fd5d83579d4 +md5: 85072b0ad177c966294f129b7c04a2d5 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=15.2.0 @@ -636,53 +623,53 @@ constrains: - libgfortran 15.2.0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 2482475 -timestamp: 1771378241063 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda -sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 -md5: 239c5e9546c38a1e884d69effcf4c882 +size: 2483673 +timestamp: 1778269025089 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +sha256: 5abe4ab9d93f6c9757d654f1969ae2267d4505315c1f2f8fe705fd60af084f1b +md5: faac990cb7aedc7f3a2224f2c9b0c26c depends: - __glibc >=2.17,<3.0.a0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 603262 -timestamp: 1771378117851 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda -sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32 -md5: 8397539e3a0bbd1695584fb4f927485a +size: 603817 +timestamp: 1778268942614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda +sha256: 10056646c28115b174de81a44e23e3a0a3b95b5347d2e6c45cc6d49d35294256 +md5: 6178c6f2fb254558238ef4e6c56fb782 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 constrains: - jpeg <0.0.0a license: IJG AND BSD-3-Clause AND Zlib -size: 633710 -timestamp: 1762094827865 -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda -build_number: 5 -sha256: c723b6599fcd4c6c75dee728359ef418307280fa3e2ee376e14e85e5bbdda053 -md5: b38076eb5c8e40d0106beda6f95d7609 -depends: -- libblas 3.11.0 5_h4a7cf45_openblas +size: 633831 +timestamp: 1775962768273 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda +build_number: 7 +sha256: 96962084921f197c9ad13fb7f8b324f2351d50ff3d8d962148751ad532f54a01 +md5: 6569b4f273740e25dc0dc7e3232c2a6c +depends: +- libblas 3.11.0 7_h4a7cf45_openblas constrains: -- blas 2.305 openblas -- liblapacke 3.11.0 5*_openblas -- libcblas 3.11.0 5*_openblas +- liblapacke 3.11.0 7*_openblas +- libcblas 3.11.0 7*_openblas +- blas 2.307 openblas license: BSD-3-Clause license_family: BSD -size: 18200 -timestamp: 1765818857876 -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda -sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb -md5: c7c83eecbb72d88b940c249af56c8b17 +size: 18694 +timestamp: 1778489869038 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda +sha256: ec30e52a3c1bf7d0425380a189d209a52baa03f22fb66dd3eb587acaa765bd6d +md5: b88d90cad08e6bc8ad540cb310a761fb depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 constrains: -- xz 5.8.2.* +- xz 5.8.3.* license: 0BSD -size: 113207 -timestamp: 1768752626120 +size: 113478 +timestamp: 1775825492909 - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 md5: 2c21e66f50753a083cbe6b80f38268fa @@ -693,53 +680,52 @@ license: BSD-2-Clause license_family: BSD size: 92400 timestamp: 1769482286018 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda -sha256: 199d79c237afb0d4780ccd2fbf829cea80743df60df4705202558675e07dd2c5 -md5: be43915efc66345cccb3c310b6ed0374 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda +sha256: 3d9aa85648e5e18a6d66db98b8c4317cc426721ad7a220aa86330d1ccedc8903 +md5: 2d3278b721e40468295ca755c3b84070 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 - libgfortran - libgfortran5 >=14.3.0 constrains: -- openblas >=0.3.30,<0.3.31.0a0 +- openblas >=0.3.33,<0.3.34.0a0 license: BSD-3-Clause license_family: BSD -size: 5927939 -timestamp: 1763114673331 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda -sha256: 36ade759122cdf0f16e2a2562a19746d96cf9c863ffaa812f2f5071ebbe9c03c -md5: 5f13ffc7d30ffec87864e678df9957b4 +size: 5931919 +timestamp: 1776993658641 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda +sha256: 377cfe037f3eeb3b1bf3ad333f724a64d32f315ee1958581fc671891d63d3f89 +md5: eba48a68a1a2b9d3c0d9511548db85db depends: -- libgcc >=14 - __glibc >=2.17,<3.0.a0 -- libzlib >=1.3.1,<2.0a0 +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 license: zlib-acknowledgement -size: 317669 -timestamp: 1770691470744 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda -sha256: d716847b7deca293d2e49ed1c8ab9e4b9e04b9d780aea49a97c26925b28a7993 -md5: fd893f6a3002a635b5e50ceb9dd2c0f4 +size: 317729 +timestamp: 1776315175087 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda +sha256: 54cdcd3214313b62c2a8ee277e6f42150d9b748264c1b70d958bf735e420ef8d +md5: 7dc38adcbf71e6b38748e919e16e0dce depends: - __glibc >=2.17,<3.0.a0 -- icu >=78.2,<79.0a0 - libgcc >=14 -- libzlib >=1.3.1,<2.0a0 +- libzlib >=1.3.2,<2.0a0 license: blessing -size: 951405 -timestamp: 1772818874251 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda -sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e -md5: 1b08cd684f34175e4514474793d44bcb +size: 954962 +timestamp: 1777986471789 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda +sha256: dff1058c76ec6b8759e41cefa2508162d00e4a5e6721aa68ec3fd10094e702dc +md5: 5794b3bdc38177caf969dabd3af08549 depends: - __glibc >=2.17,<3.0.a0 -- libgcc 15.2.0 he0feb66_18 +- libgcc 15.2.0 he0feb66_19 constrains: -- libstdcxx-ng ==15.2.0=*_18 +- libstdcxx-ng ==15.2.0=*_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 5852330 -timestamp: 1771378262446 +size: 5852044 +timestamp: 1778269036376 - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 md5: cd5a90476766d53e901500df9215e927 @@ -757,16 +743,16 @@ depends: license: HPND size: 435273 timestamp: 1762022005702 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda -sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee -md5: db409b7c1720428638e7c0d509d3e1b5 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda +sha256: 3f0edf1280e2f6684a986f821eaa3e123d2694a00b31b96ca0d4a4c12c129231 +md5: 7d0a66598195ef00b6efc55aefc7453b depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: BSD-3-Clause license_family: BSD -size: 40311 -timestamp: 1766271528534 +size: 40163 +timestamp: 1779118517630 - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b md5: aea31d2e5b1091feca96fcfe945c3cf9 @@ -814,16 +800,16 @@ license: BSD-3-Clause license_family: BSD size: 85893 timestamp: 1770694658918 -- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda -sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e -md5: 5b5203189eb668f042ac2b0826244964 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +sha256: 0c4c35376fe920714390d46e4b8d31c876d65f18e1655899e0763ec25f2a902f +md5: 6d03368f2b2b0a5fb6839df53b2eb5e0 depends: - mdurl >=0.1,<1 - python >=3.10 license: MIT license_family: MIT -size: 64736 -timestamp: 1754951288511 +size: 69017 +timestamp: 1778169663339 - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda sha256: c279be85b59a62d5c52f5dd9a4cd43ebd08933809a8416c22c3131595607d4cf md5: 9a17c4307d23318476d7fbf0fedc0cde @@ -854,9 +840,9 @@ license: MIT license_family: MIT size: 14465 timestamp: 1733255681319 -- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda -sha256: f005760b13093362fc9c997d603dd487de32ab2e821a3cbce52a42bcb8136517 -md5: 698a8a27c2b9d8a542c70cb47099a75e +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +sha256: e86033aa55a9e915e2d0957e770bdb81e3feb26a227d1adb17f9d6c528da6a71 +md5: cdb20309681ba3ce8f52c110e214d4f3 depends: - click - coloredlogs @@ -870,10 +856,11 @@ depends: - packaging - pillow >=10.2.0 - plotly >=5.18 -- polars-lts-cpu +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 - pyaml-env - pydantic >=2.7.1 -- python >=3.8,!=3.14.1 +- python >=3.9,!=3.14.1 - python-dotenv - python-kaleido 0.2.1 - pyyaml >=4 @@ -883,20 +870,21 @@ depends: - spectra >=0.0.10 - tiktoken - tqdm -- typeguard +- typeguard >=4 license: GPL-3.0-or-later license_family: GPL3 -size: 4198799 -timestamp: 1765300743879 -- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda -sha256: 541fd4390a0687228b8578247f1536a821d9261389a65585af9d1a6f2a14e1e0 -md5: 30bec5e8f4c3969e2b1bd407c5e52afb +size: 4282188 +timestamp: 1779465338806 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +sha256: 70f43d62450927d51673eecd8823e14f5b3cfebdb43cda1d502eba97162bab42 +md5: 6687827c332121727ce383919e1ec8c2 depends: - python >=3.10 - python license: MIT -size: 280459 -timestamp: 1774380620329 +license_family: MIT +size: 284323 +timestamp: 1778929680962 - conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 md5: e941e85e273121222580723010bd4fa2 @@ -907,15 +895,15 @@ license: MIT license_family: MIT size: 39262 timestamp: 1770905275632 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda -sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 -md5: 47e340acb35de30501a76c7c799c41d7 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda +sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 +md5: fc21868a1a5aacc937e7a18747acb8a5 depends: - __glibc >=2.17,<3.0.a0 -- libgcc >=13 +- libgcc >=14 license: X11 AND BSD-3-Clause -size: 891641 -timestamp: 1738195959188 +size: 918956 +timestamp: 1777422145199 - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 md5: a2c1eeadae7a309daed9d62c96012a2b @@ -956,24 +944,24 @@ license: MPL-2.0 license_family: MOZILLA size: 2057773 timestamp: 1763485556350 -- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py314h2b28147_0.conda -sha256: f2ba8cb0d86a6461a6bcf0d315c80c7076083f72c6733c9290086640723f79ec -md5: 36f5b7eb328bdc204954a2225cf908e2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.6-py314h2b28147_0.conda +sha256: bc61ae892973751a6b0e6ecea57ed6d7053224bddcb007165d6ceb1d7344ad47 +md5: f49b5f950379e0b97c35ca97682f7c6a depends: - python - libstdcxx >=14 - libgcc >=14 - __glibc >=2.17,<3.0.a0 -- python_abi 3.14.* *_cp314 -- libcblas >=3.9.0,<4.0a0 - liblapack >=3.9.0,<4.0a0 +- python_abi 3.14.* *_cp314 - libblas >=3.9.0,<4.0a0 +- libcblas >=3.9.0,<4.0a0 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD -size: 8927860 -timestamp: 1773839233468 +size: 8928909 +timestamp: 1779169198391 - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda sha256: 3900f9f2dbbf4129cf3ad6acf4e4b6f7101390b53843591c53b00f034343bc4d md5: 11b3379b191f63139e29c0d19dee24cd @@ -988,48 +976,48 @@ license: BSD-2-Clause license_family: BSD size: 355400 timestamp: 1758489294972 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda -sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c -md5: f61eb8cd60ff9057122a3d338b99c00f +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda +sha256: c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb +md5: da1b85b6a87e141f5140bb9924cecab0 depends: - __glibc >=2.17,<3.0.a0 - ca-certificates - libgcc >=14 license: Apache-2.0 license_family: Apache -size: 3164551 -timestamp: 1769555830639 -- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda -sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 -md5: b76541e68fea4d511b1ac46a28dcd2c6 +size: 3167099 +timestamp: 1775587756857 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 +md5: 4c06a92e74452cfa53623a81592e8934 depends: - python >=3.8 - python license: Apache-2.0 license_family: APACHE -size: 72010 -timestamp: 1769093650580 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.1.1-py314h8ec4b1a_0.conda -sha256: 9e6ec8f3213e8b7d64b0ad45f84c51a2c9eba4398efda31e196c9a56186133ee -md5: 79678378ae235e24b3aa83cee1b38207 +size: 91574 +timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.2.0-py314h8ec4b1a_0.conda +sha256: 123d8a7c16c88658b4f29e9f115a047598c941708dade74fbaff373a32dbec5e +md5: 76c4757c0ec9d11f969e8eb44899307b depends: - python - libgcc >=14 - __glibc >=2.17,<3.0.a0 +- libtiff >=4.7.1,<4.8.0a0 +- openjpeg >=2.5.4,<3.0a0 +- libxcb >=1.17.0,<2.0a0 - libwebp-base >=1.6.0,<2.0a0 - zlib-ng >=2.3.3,<2.4.0a0 -- python_abi 3.14.* *_cp314 -- tk >=8.6.13,<8.7.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 -- libxcb >=1.17.0,<2.0a0 -- openjpeg >=2.5.4,<3.0a0 +- python_abi 3.14.* *_cp314 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 - lcms2 >=2.18,<3.0a0 -- libtiff >=4.7.1,<4.8.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 +- tk >=8.6.13,<8.7.0a0 license: HPND -size: 1073026 -timestamp: 1770794002408 +size: 1082797 +timestamp: 1775060059882 - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 md5: 3e9427ee186846052e81fadde8ebe96a @@ -1043,11 +1031,11 @@ license: MIT license_family: MIT size: 5251872 timestamp: 1772628857717 -- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda -sha256: d332c2d5002fc440ae37ed9679ffc21b552f18d20232390005d1dd3bce0888d3 -md5: d5a4e013a30dd8dfde9ab39f45aaf9c1 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +sha256: 70fc56877c4a095ee658d61924d8019768fbae4a48437058d181fc94b0a7c4d8 +md5: 25a883fed9f1f3f21ff317a3e7c92ac4 depends: -- polars-runtime-32 ==1.39.3 +- polars-runtime-32 ==1.41.0 - python >=3.10 - python constrains: @@ -1061,57 +1049,44 @@ constrains: - pyiceberg >=0.7.1 - altair >=5.4.0 - great_tables >=0.8.0 -- polars-runtime-32 ==1.39.3 -- polars-runtime-64 ==1.39.3 -- polars-runtime-compat ==1.39.3 +- polars-runtime-32 ==1.41.0 +- polars-runtime-64 ==1.41.0 +- polars-runtime-compat ==1.41.0 license: MIT -license_family: MIT -size: 533495 -timestamp: 1774207987966 -- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda -sha256: e466fb31f67ba9bde18deafeb34263ca5eb25807f39ead0e9d753a8e82c4c4f4 -md5: ef0340e75068ac8ff96462749b5c98e7 -depends: -- polars >=1.34.0 -- polars-runtime-compat >=1.34.0 -license: MIT -license_family: MIT -size: 3902 -timestamp: 1760206808444 -- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.39.3-py310hffdcd12_1.conda +size: 539656 +timestamp: 1779630790562 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.41.0-py310h49dadd8_0.conda noarch: python -sha256: 9744f8086bb0832998f5b01076f57ddc9efbe460e493b14303c3567dc4f401e7 -md5: f9327f9f2cfc4215f55b613e64afd3ba +sha256: e51ee3fe5259f2e115b2f78f8fbe3554e419c7c82b0c110878e12a5ff95ce3ab +md5: 7682765a1588e5ac887c99736d297c93 depends: - python +- __glibc >=2.17,<3.0.a0 - libstdcxx >=14 - libgcc >=14 -- __glibc >=2.17,<3.0.a0 - _python_abi3_support 1.* - cpython >=3.10 constrains: - __glibc >=2.17 license: MIT -license_family: MIT -size: 37570276 -timestamp: 1774207987966 -- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.39.3-py310hbcd5346_1.conda +size: 42578921 +timestamp: 1779630790562 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.41.0-py310hcbd6021_0.conda noarch: python -sha256: bf0b932713f0f27924f42159c98426e0073bb6145ed796eaa4cec79ca05363c7 -md5: 4b9b312453eebd6fbdbbe2a88fa1b5c4 +sha256: 29c3831c92394af11d9f7d04882dda9479ffbb76a3d36ba155d52159d67805fa +md5: cb0b620c9914a07a9022cb8b183ea9ee depends: - python -- libgcc >=14 - libstdcxx >=14 +- libgcc >=14 - __glibc >=2.17,<3.0.a0 - _python_abi3_support 1.* - cpython >=3.10 constrains: - __glibc >=2.17 license: MIT -license_family: MIT -size: 37224264 -timestamp: 1774207985377 +size: 41864944 +timestamp: 1779630722548 - conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d md5: f2c23a77b25efcad57d377b34bd84941 @@ -1143,24 +1118,23 @@ license: MIT license_family: MIT size: 14645 timestamp: 1736766960536 -- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda -sha256: 868569d9505b7fe246c880c11e2c44924d7613a8cdcc1f6ef85d5375e892f13d -md5: c3946ed24acdb28db1b5d63321dbca7d +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +sha256: 69700e31165df070e9716315e042196aa92525dae5deb5107785847ab9f4189f +md5: 729843edafc0899b3348bd3f19525b9d depends: - typing-inspection >=0.4.2 - typing_extensions >=4.14.1 - python >=3.10 -- typing-extensions >=4.6.1 - annotated-types >=0.6.0 -- pydantic-core ==2.41.5 +- pydantic-core ==2.46.4 - python license: MIT license_family: MIT -size: 340482 -timestamp: 1764434463101 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py314h2e6c369_1.conda -sha256: 7e0ae379796e28a429f8e48f2fe22a0f232979d65ec455e91f8dac689247d39f -md5: 432b0716a1dfac69b86aa38fdd59b7e6 +size: 346511 +timestamp: 1778103405862 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.4-py314h2e6c369_0.conda +sha256: 802e216c39f1359aed60823b6e11d8ccd812b0ae1c81ae5ac1c81f99446409ab +md5: 0c96993dbeadf3a277cf757b9f1c9412 depends: - python - typing-extensions >=4.6.0,!=4.7.0 @@ -1171,17 +1145,17 @@ constrains: - __glibc >=2.17 license: MIT license_family: MIT -size: 1943088 -timestamp: 1762988995556 -- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda -sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a -md5: 6b6ece66ebcae2d5f326c77ef2c5a066 +size: 1895020 +timestamp: 1778084229247 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 +md5: 16c18772b340887160c79a6acc022db0 depends: -- python >=3.9 +- python >=3.10 license: BSD-2-Clause license_family: BSD -size: 889287 -timestamp: 1750615908735 +size: 893031 +timestamp: 1774796815820 - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 md5: 461219d1a5bd61342293efa2c0c90eac @@ -1192,32 +1166,32 @@ license: BSD-3-Clause license_family: BSD size: 21085 timestamp: 1733217331982 -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda -build_number: 101 -sha256: cb0628c5f1732f889f53a877484da98f5a0e0f47326622671396fb4f2b0cd6bd -md5: c014ad06e60441661737121d3eae8a60 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.5-habeac84_100_cp314.conda +build_number: 100 +sha256: 55eed9bf2a3f6e90311276f0834737fe7c2d9ec3e5e2e557507858df4c7521e6 +md5: da92e59ff92f2d5ede4f612af20f583f depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-64 >=2.36.1 -- libexpat >=2.7.3,<3.0a0 +- libexpat >=2.8.0,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 -- liblzma >=5.8.2,<6.0a0 +- liblzma >=5.8.3,<6.0a0 - libmpdec >=4.0.0,<5.0a0 -- libsqlite >=3.51.2,<4.0a0 -- libuuid >=2.41.3,<3.0a0 -- libzlib >=1.3.1,<2.0a0 -- ncurses >=6.5,<7.0a0 -- openssl >=3.5.5,<4.0a0 +- libsqlite >=3.53.1,<4.0a0 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- openssl >=3.5.6,<4.0a0 - python_abi 3.14.* *_cp314 - readline >=8.3,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata - zstd >=1.5.7,<1.6.0a0 license: Python-2.0 -size: 36702440 -timestamp: 1770675584356 +size: 36745188 +timestamp: 1779236923603 python_site_packages_path: lib/python3.14/site-packages - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 @@ -1228,15 +1202,15 @@ license: BSD-3-Clause license_family: BSD size: 27848 timestamp: 1772388605021 -- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda -sha256: 233aebd94c704ac112afefbb29cf4170b7bc606e22958906f2672081bc50638a -md5: 235765e4ea0d0301c75965985163b5a1 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +sha256: 41dd7da285d71d519257fa7dacb1cae060d5ebfaa5f92cba5994899d2978e943 +md5: 41954747ba952ec4b01e16c2c9e8d8ff depends: -- cpython 3.14.3.* +- cpython 3.14.5.* - python_abi * *_cp314 license: Python-2.0 -size: 50062 -timestamp: 1770674497152 +size: 50212 +timestamp: 1779236703009 - conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 md5: 310259a5b03ff02289d7705f39e2b1d2 @@ -1294,9 +1268,9 @@ license: MIT license_family: MIT size: 51788 timestamp: 1760379115194 -- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.2.28-py314h5bd0f2a_0.conda -sha256: e085e336f1446f5263a3ec9747df8c719b6996753901181add50dc4fdd8bb2e8 -md5: 3c8b6a8c4d0ff5a264e9831eac4941f4 +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.5.9-py314h5bd0f2a_0.conda +sha256: c7a4aca4977c15c82d053b06cbc676460974c1b25757cfeea8a9a2497ac911f8 +md5: 9dd235b6ac69a0198080dac39f9891aa depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -1304,27 +1278,27 @@ depends: - python_abi 3.14.* *_cp314 license: Apache-2.0 AND CNRI-Python license_family: PSF -size: 411924 -timestamp: 1772255161535 -- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda -sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5 -md5: c65df89a0b2e321045a9e01d1337b182 +size: 413611 +timestamp: 1778374155646 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +sha256: 1715246b19c9f85ee022933b4845f2fc14ac9184981b7b7d9b728bec8e9588da +md5: 4a85203c1d80c1059086ae860836ffb9 depends: - python >=3.10 -- certifi >=2017.4.17 +- certifi >=2023.5.7 - charset-normalizer >=2,<4 - idna >=2.5,<4 -- urllib3 >=1.21.1,<3 +- urllib3 >=1.26,<3 - python constrains: -- chardet >=3.0.2,<6 +- chardet >=3.0.2,<8 license: Apache-2.0 license_family: APACHE -size: 63602 -timestamp: 1766926974520 -- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda -sha256: b06ce84d6a10c266811a7d3adbfa1c11f13393b91cc6f8a5b468277d90be9590 -md5: 7a6289c50631d620652f5045a63eb573 +size: 68709 +timestamp: 1778851103479 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +sha256: 3d6ba2c0fcdac3196ba2f0615b4104e532525ffa1335b50a2878be5ff488814a +md5: 0242025a3c804966bf71aa04eee82f66 depends: - markdown-it-py >=2.2.0 - pygments >=2.13.0,<3.0.0 @@ -1333,8 +1307,8 @@ depends: - python license: MIT license_family: MIT -size: 208472 -timestamp: 1771572730357 +size: 208577 +timestamp: 1775991661559 - conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 md5: 0c20a8ebcddb24a45da89d5e917e6cb9 @@ -1373,20 +1347,19 @@ license: MIT license_family: MIT size: 22284 timestamp: 1735770589188 -- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.52.0-h04a0ce9_0.conda -sha256: c9af81e7830d9c4b67a7f48e512d060df2676b29cac59e3b31f09dbfcee29c58 -md5: 7d9d7efe9541d4bb71b5934e8ee348ea +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.1-hbc0de68_0.conda +sha256: d167fa92781bcdcd3b9aaa6bb1cd50c5b108f6190c170098a118b5cf5df2f881 +md5: 8e0b8654ead18e50af552e54b5a08a61 depends: - __glibc >=2.17,<3.0.a0 -- icu >=78.2,<79.0a0 - libgcc >=14 -- libsqlite 3.52.0 hf4e2dac_0 -- libzlib >=1.3.1,<2.0a0 -- ncurses >=6.5,<7.0a0 +- libsqlite 3.53.1 h0c1763c_0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 - readline >=8.3,<9.0a0 license: blessing -size: 203641 -timestamp: 1772818888368 +size: 205399 +timestamp: 1777986477546 - conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda sha256: 7e395d67fd249d901beb1ae269057763c0d8c3ee5f7a348694bdb16d158a37d9 md5: d705f9d8a1185a2b01cced191177a028 @@ -1427,20 +1400,20 @@ depends: license: MPL-2.0 and MIT size: 94132 timestamp: 1770153424136 -- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda -sha256: 39d8ae33c43cdb8f771373e149b0b4fae5a08960ac58dcca95b2f1642bb17448 -md5: 260af1b0a94f719de76b4e14094e9a3b +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +sha256: 59d7851d32fddb5b510272e6557aa982edeb927d349648dac27f5bf01d18bb26 +md5: 4460f039b7dedf15f7df086446ca75ae depends: -- importlib-metadata >=3.6 -- python >=3.10 -- typing-extensions >=4.10.0 - typing_extensions >=4.14.0 +- python >=3.10 +- importlib-metadata >=3.6 +- python constrains: - pytest >=7 license: MIT license_family: MIT -size: 36838 -timestamp: 1771532971545 +size: 38297 +timestamp: 1778779291237 - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c md5: edd329d7d3a4ab45dcf905899a7a6115 @@ -1450,16 +1423,17 @@ license: PSF-2.0 license_family: PSF size: 91383 timestamp: 1756220668932 -- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda -sha256: 70db27de58a97aeb7ba7448366c9853f91b21137492e0b4430251a1870aa8ff4 -md5: a0a4a3035667fc34f29bfbd5c190baa6 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +sha256: 8b90d2f19f9458b8c58a55e1fcdc1d90c1603a847a47654d8a454549413ba60a +md5: 53f5409c5cfd6c5a66417d68e3f0a864 depends: - python >=3.10 - typing_extensions >=4.12.0 +- python license: MIT license_family: MIT -size: 18923 -timestamp: 1764158430324 +size: 20935 +timestamp: 1777105465795 - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 md5: 0caa1af407ecff61170c9437a808404d @@ -1476,9 +1450,9 @@ md5: ad659d0a2b3e47e38d829aa8cad2d610 license: LicenseRef-Public-Domain size: 119135 timestamp: 1767016325805 -- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda -sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a -md5: 9272daa869e03efe68833e3dc7a02130 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 +md5: cbb88288f74dbe6ada1c6c7d0a97223e depends: - backports.zstd >=1.0.0 - brotli-python >=1.2.0 @@ -1487,8 +1461,8 @@ depends: - python >=3.10 license: MIT license_family: MIT -size: 103172 -timestamp: 1767817860341 +size: 103560 +timestamp: 1778188657149 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b md5: b2895afaf55bf96a8c8282a2e47a5de0 @@ -1519,16 +1493,16 @@ license: MIT license_family: MIT size: 85189 timestamp: 1753484064210 -- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda -sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae -md5: 30cd29cb87d819caead4d55184c1d115 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +sha256: 210bd31c22bb88f5e2a167df24c95bb5f152b2ada7502f9b8c49d1f5366db423 +md5: ba3dcdc8584155c97c648ae9c044b7a3 depends: - python >=3.10 - python license: MIT license_family: MIT -size: 24194 -timestamp: 1764460141901 +size: 24190 +timestamp: 1779159948016 - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda sha256: ea4e50c465d70236408cb0bfe0115609fd14db1adcd8bd30d8918e0291f8a75f md5: 2aadb0d17215603a82a2a6b0afd9a4cb diff --git a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt deleted file mode 100644 index a55a4d4..0000000 --- a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt +++ /dev/null @@ -1,126 +0,0 @@ - -# This file may be used to create an environment using: -# $ conda create --name --file -# platform: linux-64 -@EXPLICIT -https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda#239c5e9546c38a1e884d69effcf4c882 -https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda#a9f577daf3de00bca7c3c76c0ecbd1de -https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda#0aa00f03f9e39fb9876085dee11a85d4 -https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda#d2ffd7602c02f2b316fd921d39876885 -https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda#d87ff7921124eccd67248aa483c23fec -https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda#4a13eeac0b5c8e5b8ab496e6c4ddd829 -https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda#18335a698559cdbcd86150a48bf54ba6 -https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda#49f570f3bc4c874a06ea69b7225753af -https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda#a360c33a5abe61c07959e449fa1453eb -https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda#b88d90cad08e6bc8ad540cb310a761fb -https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda#2c21e66f50753a083cbe6b80f38268fa -https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda#1b08cd684f34175e4514474793d44bcb -https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda#c80d8a3b84358cb967fa81e7075fbc8a -https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.0-hf4e2dac_0.conda#810d83373448da85c3f673fbcb7ad3a3 -https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda#38ffe67b78c9d4de527be8315e5ada2c -https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda#47e340acb35de30501a76c7c799c41d7 -https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda#e18ad67cf881dcadee8b8d9e2f8e5f73 -https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda#da1b85b6a87e141f5140bb9924cecab0 -https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda#0539938c55b6b1a59b560e843ad864a4 -https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda#d7d95fc8287ea7bf33e0e7116d2b95ec -https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda#cffd3bdd58090148f4cfcd831f4b26ab -https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda#ad659d0a2b3e47e38d829aa8cad2d610 -https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda#a443f87920815d41bfe611296e507995 -https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda#f111d4cfaf1fe9496f386bc98ae94452 -https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda#e4e60721757979d01d3964122f674959 -https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda#aaa2a381ccc56eac91d63b6c1240312f -https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda#0caa1af407ecff61170c9437a808404d -https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda#edd329d7d3a4ab45dcf905899a7a6115 -https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda#2934f256a8acfe48f6ebb4fce6cde29c -https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda#c6b0543676ecb1fb2d7643941fe375f2 -https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda#a2ac7763a9ac75055b68f325d3255265 -https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda#8910d2c46f7e7b519129f486e0fe927a -https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda#929471569c93acefb30282a22060dcd5 -https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda#a9167b9571f3baa9d448faa2139d1089 -https://conda.anaconda.org/conda-forge/noarch/click-8.3.2-pyhc90fa1f_0.conda#4d18bc3af7cfcea97bd817164672a08c -https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda#7fe569c10905402ed47024fc481bb371 -https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda#b866ff7007b934d564961066c8195983 -https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda#a2c1eeadae7a309daed9d62c96012a2b -https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda#646855f357199a12f02a87382d429b75 -https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda#9063115da5bc35fdc3e1002e69b9ef6e -https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda#89d61bc91d3f39fda0ca10fcd3c68594 -https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda#6d6d225559bfa6e2f3c90ee9c03d4e2e -https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda#36ae340a916635b97ac8a0655ace2a35 -https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-6_h47877c9_openblas.conda#881d801569b201c2e753f03c84b85e15 -https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py314h2b28147_0.conda#36f5b7eb328bdc204954a2225cf908e2 -https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda#071cf7b0ce333c81718b054066c15102 -https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.5-hecca717_0.conda#7de50d165039df32d38be74c1b34a910 -https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2#0c96522c6bdaed4b1566d11387caaf45 -https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2#34893075a5c9e55cdafac56607368fc6 -https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2#4d59c254e01d9cde7957100457e2d5fb -https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda#49023d73832ef61042f6a237cb2687e7 -https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda#eba48a68a1a2b9d3c0d9511548db85db -https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda#fb16b4b69e3f1dcfe79d80db8fd0c55d -https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda#e289f3d17880e44b633ba911d57a321b -https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda#867127763fbe935bab59815b6e0b7b5c -https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda#a7970cd949a077b7cb9696379d338681 -https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda#0a802cb9888dd14eeefc611f05c40b6e -https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda#8e6923fc12f1fe8f8c4e5c9f343256ac -https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda#164fc43f0b53b6e3a7bc7dce5e4f1dc9 -https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda#daddf757c3ecd6067b9af1df1f25d89e -https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda#fb7130c190f9b4ec91219840a05ba3ac -https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda#e1c36c6121a7c9c76f2f148f1e83b983 -https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda#080594bf4493e6bae2607e65390c520a -https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda#9a17c4307d23318476d7fbf0fedc0cde -https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda#04558c96691bed63104678757beb4f8d -https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda#c1c368b5437b0d1a68f372ccf01cb133 -https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda#870293df500ca7e18bedefa5838a22ab -https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda#439cd0f567d697b20a8f45cb70a1005a -https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda#ada41c863af263cc4c5fcbaff7c3e4dc -https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda#d5e96b1ed75ca01906b3d2469b4ce493 -https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2#86e69bd82c2a2c6fd29f5ab7e02b3691 -https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda#e235d5566c9cc8970eb2798dd4ecf62f -https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda#567fbeed956c200c1db5782a424e58ee -https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.0-h04a0ce9_0.conda#dc540e5bd5616d83a1ec46af8315ff98 -https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2#b3723b235b0758abaae8c82ce4d80146 -https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda#6178c6f2fb254558238ef4e6c56fb782 -https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda#a752488c68f2e7c456bcbd8f16eec275 -https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda#6c77a605a7a689d17d4819c0f8ac9a00 -https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda#aea31d2e5b1091feca96fcfe945c3cf9 -https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda#cd5a90476766d53e901500df9215e927 -https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda#6f2e2c8f58160147c4d1c6f4c14cbac4 -https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda#b3c17d95b5a10c6e64a21fa17573e70e -https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda#b2895afaf55bf96a8c8282a2e47a5de0 -https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda#1dafce8548e38671bea82e3f5c6ce22f -https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda#92ed62436b625154323d40d5f2f11dd7 -https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda#ba0a9221ce1063f31692c07370d062f3 -https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda#592132998493b3ff25fd7479396e8351 -https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda#5b5203189eb668f042ac2b0826244964 -https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda#e941e85e273121222580723010bd4fa2 -https://conda.anaconda.org/conda-forge/noarch/packaging-26.1-pyhc364b38_0.conda#b8ae38639d323d808da535fb71e31be8 -https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda#11b3379b191f63139e29c0d19dee24cd -https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda#2aadb0d17215603a82a2a6b0afd9a4cb -https://conda.anaconda.org/conda-forge/linux-64/pillow-12.2.0-py314h8ec4b1a_0.conda#76c4757c0ec9d11f969e8eb44899307b -https://conda.anaconda.org/conda-forge/noarch/narwhals-2.20.0-pyhcf101f3_0.conda#6cac1a50359219d786453c6fef819f98 -https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda#3e9427ee186846052e81fadde8ebe96a -https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.40.0-py310hffdcd12_0.conda#8eacf9ff4d4e1ca1b52f8f3ba3e0c993 -https://conda.anaconda.org/conda-forge/noarch/polars-1.40.0-pyh58ad624_0.conda#fd16be490f5403adfbf27dd4901bbe34 -https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.40.0-py310hbcd5346_0.conda#03a6899e17bb731c8e21b08212f1a64c -https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda#ef0340e75068ac8ff96462749b5c98e7 -https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda#a77f85f77be52ff59391544bfe73390a -https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda#2035f68f96be30dc60a5dfd7452c7941 -https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda#e17be1016bcc3516827b836cd3e4d9dc -https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.3-py314h2e6c369_0.conda#1f3fd537f929b8d3236f9f0f0e7f7a32 -https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda#a0a4a3035667fc34f29bfbd5c190baa6 -https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.3-pyhcf101f3_0.conda#f690e6f204efd2e5c06b57518a383d98 -https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda#130584ad9f3a513cdd71b1fdc1244e9c -https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2#310259a5b03ff02289d7705f39e2b1d2 -https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda#461219d1a5bd61342293efa2c0c90eac -https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda#9272daa869e03efe68833e3dc7a02130 -https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda#10afbb4dbf06ff959ad25a92ccee6e59 -https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda#16c18772b340887160c79a6acc022db0 -https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda#0242025a3c804966bf71aa04eee82f66 -https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda#0c20a8ebcddb24a45da89d5e917e6cb9 -https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda#472239e4eb7b5a84bb96b3ed7e3a596a -https://conda.anaconda.org/conda-forge/linux-64/regex-2026.4.4-py314h5bd0f2a_0.conda#4ffb42385183c854564f1f9adcf80a63 -https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda#d705f9d8a1185a2b01cced191177a028 -https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda#e5ce43272193b38c2e9037446c1d9206 -https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda#260af1b0a94f719de76b4e14094e9a3b -https://conda.anaconda.org/bioconda/noarch/multiqc-1.34-pyhdfd78af_0.conda#a7111ab9a6a6146b40cbce16655ac873 -https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh145f28c_0.conda#09a970fbf75e8ed1aa633827ded6aa4f -https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda#f2c23a77b25efcad57d377b34bd84941 diff --git a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt similarity index 74% rename from modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt rename to modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt index a58231a..3d5b93d 100644 --- a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt +++ b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt @@ -14,120 +14,118 @@ linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.7.4-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.18.0-hba86a56_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.19.1-h9d5b58d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-7_haddc8a3_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-7_hd72aa62_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-7_h88aeb00_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.33-pthreads_h9d3fd7e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.1-h022381a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda -- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py314haac167e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.6-py314he1698a1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.1.1-py314hac3e5ec_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.2.0-py314hac3e5ec_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.39.3-py310hff09b76_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.39.3-py310hf00a4a2_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.41.0-py310h32c7c23_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.41.0-py310hc0e61be_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.41.5-py314h451b6cc_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.46.4-py314h451b6cc_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.5-hfd9ac0a_100_cp314.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.2.28-py314h51f160d_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.5.9-py314h51f160d_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.52.0-hf1c7be2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.1-he8854b5_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda packages: @@ -173,15 +171,15 @@ license: MIT license_family: MIT size: 64927 timestamp: 1773935801332 -- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda noarch: generic -sha256: c31ab719d256bc6f89926131e88ecd0f0c5d003fe8481852c6424f4ec6c7eb29 -md5: a2ac7763a9ac75055b68f325d3255265 +sha256: a1c97297e867776760489537bc5ae36fa83a154be30e3b79385a39ca4cb058fe +md5: 1133126d840e75287d83947be3fc3e71 depends: - python >=3.14 license: BSD-3-Clause AND MIT AND EPL-2.0 -size: 7514 -timestamp: 1767044983590 +size: 7533 +timestamp: 1778594057496 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda sha256: 5a5b0cdcd7ed89c6a8fb830924967f6314a2b71944bc1ebc2c105781ba97aa75 md5: a1b5c571a0923a205d663d8678df4792 @@ -206,42 +204,42 @@ license: bzip2-1.0.6 license_family: BSD size: 192412 timestamp: 1771350241232 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc -md5: 4492fd26db29495f0ba23f146cd5638d +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +sha256: 9812a303a1395e1dafbd92e5bc8a1ff6013bcbba0a09c7f03a8d23e43560aa9b +md5: 489b8e97e666c93f68fdb35c3c9b957f depends: - __unix license: ISC -size: 147413 -timestamp: 1772006283803 -- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda -sha256: a6b118fd1ed6099dc4fc03f9c492b88882a780fadaef4ed4f93dc70757713656 -md5: 765c4d97e877cdbbb88ff33152b86125 +size: 129868 +timestamp: 1779289852439 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +sha256: 645655a3510e38e625da136595f3f16f2130c3263630cc3bc8f60f619ddbe490 +md5: 9fefff2f745ea1cc2ef15211a20c054a depends: - python >=3.10 license: ISC -size: 151445 -timestamp: 1772001170301 -- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda -sha256: d86dfd428b2e3c364fa90e07437c8405d635aa4ef54b25ab51d9c712be4112a5 -md5: 49ee13eb9b8f44d63879c69b8a40a74b +size: 134201 +timestamp: 1779285131141 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +sha256: 3f9483d62ce24ecd063f8a5a714448445dc8d9e201147c46699fc0033e824457 +md5: a9167b9571f3baa9d448faa2139d1089 depends: - python >=3.10 license: MIT license_family: MIT -size: 58510 -timestamp: 1773660086450 -- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda -sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715 -md5: ea8a6c3256897cc31263de9f455e25d9 +size: 58872 +timestamp: 1775127203018 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +sha256: 99ab8ef815c4520cce3a7482c2513f377c14348206857661d84c76a55e030f97 +md5: 003767c47f1f0a474c4de268b57839c3 depends: -- python >=3.10 - __unix - python +- python >=3.10 license: BSD-3-Clause license_family: BSD -size: 97676 -timestamp: 1764518652276 +size: 104631 +timestamp: 1779108494556 - conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 md5: b866ff7007b934d564961066c8195983 @@ -263,26 +261,26 @@ license: BSD-3-Clause license_family: BSD size: 39326 timestamp: 1735759976140 -- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda noarch: generic -sha256: 91b06300879df746214f7363d6c27c2489c80732e46a369eb2afc234bcafb44c -md5: 3bb89e4f795e5414addaa531d6b1500a +sha256: 777882d2685f368417f31bbe1b28f73687fc6c8f6a5768bda20ffeefa6b07f5b +md5: a749029ce5d0632a913db19d17f944ab depends: - python >=3.14,<3.15.0a0 - python_abi * *_cp314 license: Python-2.0 -size: 50078 -timestamp: 1770674447292 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.7.4-hfae3067_0.conda -sha256: 5f087bef054c681edcaae84a8c2230585b938691e371ff92957a30707b7fcdf7 -md5: b304307db639831ad7caabd2eac6fca6 +size: 50212 +timestamp: 1779236682725 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_0.conda +sha256: a9cd5eb1700e11cc39acc36630a2d72a4e317943bd7c5695cd8804419f04ff42 +md5: 89f0247b3cea528d8ad1a6664a313153 depends: -- libexpat 2.7.4 hfae3067_0 +- libexpat 2.8.1 hfae3067_0 - libgcc >=14 license: MIT license_family: MIT -size: 137701 -timestamp: 1771259543650 +size: 140114 +timestamp: 1779278679081 - conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b md5: 0c96522c6bdaed4b1566d11387caaf45 @@ -311,20 +309,20 @@ license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 license_family: Other size: 1620504 timestamp: 1727511233259 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda -sha256: 835aff8615dd8d8fff377679710ce81b8a2c47b6404e21a92fb349fda193a15c -md5: 0fed1ff55f4938a65907f3ecf62609db +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.18.0-hba86a56_0.conda +sha256: 1805f4ab3d9e1734a5a17abccc2cb0fdade51d4d5f29bdc410600ea0115ec050 +md5: b660d59a9d0fb3297327418624acaec3 depends: -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 +- libexpat >=2.8.1,<3.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 - libgcc >=14 -- libuuid >=2.41.3,<3.0a0 -- libzlib >=1.3.1,<2.0a0 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 license: MIT license_family: MIT -size: 279044 -timestamp: 1771382728182 +size: 293348 +timestamp: 1779421661332 - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 md5: a7970cd949a077b7cb9696379d338681 @@ -386,36 +384,26 @@ license: MIT license_family: MIT size: 17397 timestamp: 1737618427549 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda -sha256: 49ba6aed2c6b482bb0ba41078057555d29764299bc947b990708617712ef6406 -md5: 546da38c2fa9efacf203e2ad3f987c59 -depends: -- libgcc >=14 -- libstdcxx >=14 -license: MIT -license_family: MIT -size: 12837286 -timestamp: 1773822650615 -- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda -sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 -md5: 53abe63df7e10a6ba605dc5f9f961d36 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +sha256: 3d25f9f6f7ab3e1ce6429fc8c8aae0335cf446692e715068488536d220cc43de +md5: 1b9083b7f00609605d1483dbc6071a81 depends: - python >=3.10 +- python license: BSD-3-Clause license_family: BSD -size: 50721 -timestamp: 1760286526795 -- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda -sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 -md5: 080594bf4493e6bae2607e65390c520a +size: 62642 +timestamp: 1779294335905 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +sha256: 43e2a5497cad1598ff88a3e69f69bc88b7b8f141fa63c60eab5db296317318b8 +md5: ffc17e785d64e12fc311af9184221839 depends: - python >=3.10 - zipp >=3.20 - python license: Apache-2.0 -license_family: APACHE -size: 34387 -timestamp: 1773931568510 +size: 34766 +timestamp: 1779714582554 - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b md5: 04558c96691bed63104678757beb4f8d @@ -469,17 +457,17 @@ license: MIT license_family: MIT size: 65750397 timestamp: 1615199465742 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda -sha256: 379ef5e91a587137391a6149755d0e929f1a007d2dcb211318ac670a46c8596f -md5: bb960f01525b5e001608afef9d47b79c +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.19.1-h9d5b58d_0.conda +sha256: 1e5f68e4b36a0e1a278c6dc026bc3d7775518a15832cbc9d7fc1c0e4c47784b1 +md5: b1f8bee3c53a6d2c103fb4a1ae44f5c4 depends: - libgcc >=14 -- libjpeg-turbo >=3.1.2,<4.0a0 +- libjpeg-turbo >=3.1.4.1,<4.0a0 - libtiff >=4.7.1,<4.8.0a0 license: MIT license_family: MIT -size: 293039 -timestamp: 1768184778398 +size: 296899 +timestamp: 1778079402392 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda sha256: 7abd913d81a9bf00abb699e8987966baa2065f5132e37e815f92d90fc6bba530 md5: a21644fc4a83da26452a718dc9468d5f @@ -501,37 +489,37 @@ license: Apache-2.0 license_family: Apache size: 240444 timestamp: 1773114901155 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda -build_number: 5 -sha256: 700f3c03d0fba8e687a345404a45fbabe781c1cf92242382f62cef2948745ec4 -md5: 5afcea37a46f76ec1322943b3c4dfdc0 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-7_haddc8a3_openblas.conda +build_number: 7 +sha256: f27ba323c2f1e1731b5e880fe520f178f55047f25be94f77e649605b2343c066 +md5: e8d07b777f6ff1fab69665336561910b depends: -- libopenblas >=0.3.30,<0.3.31.0a0 -- libopenblas >=0.3.30,<1.0a0 +- libopenblas >=0.3.33,<0.3.34.0a0 +- libopenblas >=0.3.33,<1.0a0 constrains: -- mkl <2026 -- libcblas 3.11.0 5*_openblas -- liblapack 3.11.0 5*_openblas -- liblapacke 3.11.0 5*_openblas -- blas 2.305 openblas +- liblapack 3.11.0 7*_openblas +- libcblas 3.11.0 7*_openblas +- mkl <2027 +- blas 2.307 openblas +- liblapacke 3.11.0 7*_openblas license: BSD-3-Clause license_family: BSD -size: 18369 -timestamp: 1765818610617 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda -build_number: 5 -sha256: 3fad5c9de161dccb4e42c8b1ae8eccb33f4ed56bccbcced9cbb0956ae7869e61 -md5: 0b2f1143ae2d0aa4c991959d0daaf256 -depends: -- libblas 3.11.0 5_haddc8a3_openblas +size: 18696 +timestamp: 1778489796402 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-7_hd72aa62_openblas.conda +build_number: 7 +sha256: c8f0192362966df0828419f042d6f94c079e5df00ad6bd05b5e84c12b42f8cc7 +md5: 90ac57b82c055faa9be25031864b7d8f +depends: +- libblas 3.11.0 7_haddc8a3_openblas constrains: -- liblapack 3.11.0 5*_openblas -- liblapacke 3.11.0 5*_openblas -- blas 2.305 openblas +- liblapack 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapacke 3.11.0 7*_openblas license: BSD-3-Clause license_family: BSD -size: 18371 -timestamp: 1765818618899 +size: 18664 +timestamp: 1778489802790 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 md5: a9138815598fe6b91a1d6782ca657b0c @@ -541,17 +529,17 @@ license: MIT license_family: MIT size: 71117 timestamp: 1761979776756 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda -sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 -md5: 57f3b3da02a50a1be2a6fe847515417d +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda +sha256: 1fc392b997c6ee2bd3226a7cd870d0edbcbb367e25f9f18dd4a7025fced6efc0 +md5: 513dd884361dfb8a554298ed69b58823 depends: - libgcc >=14 constrains: -- expat 2.7.4.* +- expat 2.8.1.* license: MIT license_family: MIT -size: 76564 -timestamp: 1771259530958 +size: 77140 +timestamp: 1779278671302 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 md5: 2f364feefb6a7c00423e80dcb12db62a @@ -581,90 +569,90 @@ constrains: license: GPL-2.0-only OR FTL size: 422941 timestamp: 1774301093473 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda -sha256: 43df385bedc1cab11993c4369e1f3b04b4ca5d0ea16cba6a0e7f18dbc129fcc9 -md5: 552567ea2b61e3a3035759b2fdb3f9a6 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda +sha256: 4592b096e553f67799ae70d4b6167eeda3ec74587d68c7aecbf4e7b1df136681 +md5: f35b3f52d0a2ec4ffe3c89ba135cdb9a depends: - _openmp_mutex >=4.5 constrains: -- libgcc-ng ==15.2.0=*_18 -- libgomp 15.2.0 h8acb6b2_18 +- libgomp 15.2.0 h8acb6b2_19 +- libgcc-ng ==15.2.0=*_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 622900 -timestamp: 1771378128706 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda -sha256: 83bb0415f59634dccfa8335d4163d1f6db00a27b36666736f9842b650b92cf2f -md5: 4feebd0fbf61075a1a9c2e9b3936c257 +size: 622462 +timestamp: 1778268755949 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda +sha256: 1137f93f477f56199ded24117430045a0c02cbe8b10031beac3b9ad2138539d3 +md5: 770cf892e5530f43e63cadc673e85653 depends: -- libgcc 15.2.0 h8acb6b2_18 +- libgcc 15.2.0 h8acb6b2_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 27568 -timestamp: 1771378136019 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda -sha256: 7dcd7dff2505d56fd5272a6e712ec912f50a46bf07dc6873a7e853694304e6e4 -md5: 41f261f5e4e2e8cbd236c2f1f15dae1b +size: 27738 +timestamp: 1778268759211 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_19.conda +sha256: e5ad94be72634233510b33ba792a3339921bd468f0b8bc6961ea05eded251d9b +md5: c7a5b5decf969ead5ecada83654164cf depends: -- libgfortran5 15.2.0 h1b7bec0_18 +- libgfortran5 15.2.0 h1b7bec0_19 constrains: -- libgfortran-ng ==15.2.0=*_18 +- libgfortran-ng ==15.2.0=*_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 27587 -timestamp: 1771378169244 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda -sha256: 85347670dfb4a8d4c13cd7cae54138dcf2b1606b6bede42eef5507bf5f9660c6 -md5: 574d88ce3348331e962cfa5ed451b247 +size: 27728 +timestamp: 1778268784621 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_19.conda +sha256: af8e9bdcaa77f133a8ee4c1ef57ef564d9c45aa262abf9f5ef9b50eb99d96407 +md5: 779dbb494de6d3d6477cab52eb34285a depends: - libgcc >=15.2.0 constrains: - libgfortran 15.2.0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 1486341 -timestamp: 1771378148102 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda -sha256: fc716f11a6a8525e27a5d332ef6a689210b0d2a4dd1133edc0f530659aa9faa6 -md5: 4faa39bf919939602e594253bd673958 +size: 1487244 +timestamp: 1778268767295 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda +sha256: 2370ef0ffcbae5bede3c4bf136add4abc257245eb91f724c99bb4a43116c5a83 +md5: c5e8a379c4a2ec2aea4ba22758c001d9 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 588060 -timestamp: 1771378040807 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda -sha256: 84064c7c53a64291a585d7215fe95ec42df74203a5bf7615d33d49a3b0f08bb6 -md5: 5109d7f837a3dfdf5c60f60e311b041f +size: 587387 +timestamp: 1778268674393 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda +sha256: e97ec2af5f09f8f6ea8ecd550055c95ae80fae22015fcfadaa94eafe025c9ccc +md5: a85ba48648f6868016f2741fd9170250 depends: - libgcc >=14 constrains: - jpeg <0.0.0a license: IJG AND BSD-3-Clause AND Zlib -size: 691818 -timestamp: 1762094728337 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda -build_number: 5 -sha256: 692222d186d3ffbc99eaf04b5b20181fd26aee1edec1106435a0a755c57cce86 -md5: 88d1e4133d1182522b403e9ba7435f04 -depends: -- libblas 3.11.0 5_haddc8a3_openblas +size: 693143 +timestamp: 1775962625956 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-7_h88aeb00_openblas.conda +build_number: 7 +sha256: 20b38a0156200ac65f597bf0a93914c565435f2cc58b1042581854231a99ac35 +md5: 5899cbd743cc74fd655c1ed2af7120f3 +depends: +- libblas 3.11.0 7_haddc8a3_openblas constrains: -- liblapacke 3.11.0 5*_openblas -- blas 2.305 openblas -- libcblas 3.11.0 5*_openblas +- libcblas 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapacke 3.11.0 7*_openblas license: BSD-3-Clause license_family: BSD -size: 18392 -timestamp: 1765818627104 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda -sha256: 843c46e20519651a3e357a8928352b16c5b94f4cd3d5481acc48be2e93e8f6a3 -md5: 96944e3c92386a12755b94619bae0b35 +size: 18685 +timestamp: 1778489809140 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda +sha256: d61962b9cd54c3554361550203c64d5b65b71e3058a285b66e4b04b9769f0a5c +md5: 76298a9e6d71ee6e832a8d0d7373b261 depends: - libgcc >=14 constrains: -- xz 5.8.2.* +- xz 5.8.3.* license: 0BSD -size: 125916 -timestamp: 1768754941722 +size: 126102 +timestamp: 1775828008518 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda sha256: 57c0dd12d506e84541c4e877898bd2a59cca141df493d34036f18b2751e0a453 md5: 7b9813e885482e3ccb1fa212b86d7fd0 @@ -674,49 +662,48 @@ license: BSD-2-Clause license_family: BSD size: 114056 timestamp: 1769482343003 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda -sha256: 794a7270ea049ec931537874cd8d2de0ef4b3cef71c055cfd8b4be6d2f4228b0 -md5: 11d7d57b7bdd01da745bbf2b67020b2e +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.33-pthreads_h9d3fd7e_0.conda +sha256: b018ecfb05e75a8eea3f21f6b5c5c2a54b5178bdcf19e2e2df2735740214a8c8 +md5: 58a66cd95e9692f08abe89f55a6f3f12 depends: - libgcc >=14 - libgfortran - libgfortran5 >=14.3.0 constrains: -- openblas >=0.3.30,<0.3.31.0a0 +- openblas >=0.3.33,<0.3.34.0a0 license: BSD-3-Clause license_family: BSD -size: 4959359 -timestamp: 1763114173544 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda -sha256: c7378c6b79de4d571d00ad1caf0a4c19d43c9c94077a761abb6ead44d891f907 -md5: be4088903b94ea297975689b3c3aeb27 +size: 5121336 +timestamp: 1776993423004 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda +sha256: 483eaa53da40a6a3e558709d9f7b1ca388735364ae21a1ba58cf942514649c92 +md5: f51503ac45a4888bce71af9027a2ecc9 depends: - libgcc >=14 -- libzlib >=1.3.1,<2.0a0 +- libzlib >=1.3.2,<2.0a0 license: zlib-acknowledgement -size: 340156 -timestamp: 1770691477245 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda -sha256: 1ddaf91b44fae83856276f4cb7ce544ffe41d4b55c1e346b504c6b45f19098d6 -md5: 77891484f18eca74b8ad83694da9815e +size: 341202 +timestamp: 1776315188425 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.1-h022381a_0.conda +sha256: ad03b7d8e4d08001f0df88ee7a56108bb35bae4795a42b9a04cc1abfa822bd07 +md5: 2ec1119217d8f0d086e9a62f3cb0e5ea depends: -- icu >=78.2,<79.0a0 - libgcc >=14 -- libzlib >=1.3.1,<2.0a0 +- libzlib >=1.3.2,<2.0a0 license: blessing -size: 952296 -timestamp: 1772818881550 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda -sha256: 31fdb9ffafad106a213192d8319b9f810e05abca9c5436b60e507afb35a6bc40 -md5: f56573d05e3b735cb03efeb64a15f388 +size: 955361 +timestamp: 1777986487553 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda +sha256: 1dadc45e599f510dd5f97141dddcdbb9844d9f1430c1f3a38075cf1c58f87b4e +md5: 543fbc8d71f2a0baf04cf88ce96cb8bb depends: -- libgcc 15.2.0 h8acb6b2_18 +- libgcc 15.2.0 h8acb6b2_19 constrains: -- libstdcxx-ng ==15.2.0=*_18 +- libstdcxx-ng ==15.2.0=*_19 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL -size: 5541411 -timestamp: 1771378162499 +size: 5546559 +timestamp: 1778268777463 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 md5: 8c6fd84f9c87ac00636007c6131e457d @@ -733,15 +720,15 @@ depends: license: HPND size: 488407 timestamp: 1762022048105 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda -sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 -md5: cf2861212053d05f27ec49c3784ff8bb +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda +sha256: 1628839b062e98b2192857d4da8496ac9ac6b0dbb77aa040c34efc9192c440ee +md5: 0f42f9fedd2a32d798de95a7f65c456f depends: - libgcc >=14 license: BSD-3-Clause license_family: BSD size: 43453 -timestamp: 1766271546875 +timestamp: 1779118526838 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 md5: 24e92d0942c799db387f5c9d7b81f1af @@ -785,16 +772,16 @@ license: BSD-3-Clause license_family: BSD size: 85893 timestamp: 1770694658918 -- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda -sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e -md5: 5b5203189eb668f042ac2b0826244964 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +sha256: 0c4c35376fe920714390d46e4b8d31c876d65f18e1655899e0763ec25f2a902f +md5: 6d03368f2b2b0a5fb6839df53b2eb5e0 depends: - mdurl >=0.1,<1 - python >=3.10 license: MIT license_family: MIT -size: 64736 -timestamp: 1754951288511 +size: 69017 +timestamp: 1778169663339 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda sha256: 383c188496d13a55658c06e61e7d4cdff2c9f9d5a0648769fca8250bece7e0ef md5: e5de3c36dd548b35ff2a8aa49208dcb3 @@ -824,9 +811,9 @@ license: MIT license_family: MIT size: 14465 timestamp: 1733255681319 -- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda -sha256: f005760b13093362fc9c997d603dd487de32ab2e821a3cbce52a42bcb8136517 -md5: 698a8a27c2b9d8a542c70cb47099a75e +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +sha256: e86033aa55a9e915e2d0957e770bdb81e3feb26a227d1adb17f9d6c528da6a71 +md5: cdb20309681ba3ce8f52c110e214d4f3 depends: - click - coloredlogs @@ -840,10 +827,11 @@ depends: - packaging - pillow >=10.2.0 - plotly >=5.18 -- polars-lts-cpu +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 - pyaml-env - pydantic >=2.7.1 -- python >=3.8,!=3.14.1 +- python >=3.9,!=3.14.1 - python-dotenv - python-kaleido 0.2.1 - pyyaml >=4 @@ -853,20 +841,21 @@ depends: - spectra >=0.0.10 - tiktoken - tqdm -- typeguard +- typeguard >=4 license: GPL-3.0-or-later license_family: GPL3 -size: 4198799 -timestamp: 1765300743879 -- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda -sha256: 541fd4390a0687228b8578247f1536a821d9261389a65585af9d1a6f2a14e1e0 -md5: 30bec5e8f4c3969e2b1bd407c5e52afb +size: 4282188 +timestamp: 1779465338806 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +sha256: 70f43d62450927d51673eecd8823e14f5b3cfebdb43cda1d502eba97162bab42 +md5: 6687827c332121727ce383919e1ec8c2 depends: - python >=3.10 - python license: MIT -size: 280459 -timestamp: 1774380620329 +license_family: MIT +size: 284323 +timestamp: 1778929680962 - conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 md5: e941e85e273121222580723010bd4fa2 @@ -877,14 +866,14 @@ license: MIT license_family: MIT size: 39262 timestamp: 1770905275632 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda -sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468 -md5: 182afabe009dc78d8b73100255ee6868 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda +sha256: 369db85c5cd8d99dde364ce70725d76511d9c8199e5b820c740414091bf5bcca +md5: b2a43456aa56fe80c2477a5094899eff depends: -- libgcc >=13 +- libgcc >=14 license: X11 AND BSD-3-Clause -size: 926034 -timestamp: 1738196018799 +size: 960036 +timestamp: 1777422174534 - conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 md5: a2c1eeadae7a309daed9d62c96012a2b @@ -923,24 +912,23 @@ license: MPL-2.0 license_family: MOZILLA size: 2061869 timestamp: 1763490303490 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py314haac167e_0.conda -sha256: a6d42fd88afc57c3b0a57b21a12eff7492dfc419bb61ee3f74e9ba6261dabc88 -md5: 25d896c331481145720a21e5145fad65 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.6-py314he1698a1_0.conda +sha256: 04af718b911f8a3a0095481c7e283aa081a175fe626eccbc2c5644bcb2aba9a1 +md5: 8b173772deea177b45d2a133b509b3f7 depends: - python -- libgcc >=14 -- python 3.14.* *_cp314 - libstdcxx >=14 -- libcblas >=3.9.0,<4.0a0 -- liblapack >=3.9.0,<4.0a0 +- libgcc >=14 - python_abi 3.14.* *_cp314 - libblas >=3.9.0,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- libcblas >=3.9.0,<4.0a0 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD -size: 8008045 -timestamp: 1773839355275 +size: 8002900 +timestamp: 1779169206742 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda sha256: bd1bc8bdde5e6c5cbac42d462b939694e40b59be6d0698f668515908640c77b8 md5: cea962410e327262346d48d01f05936c @@ -954,47 +942,47 @@ license: BSD-2-Clause license_family: BSD size: 392636 timestamp: 1758489353577 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda -sha256: 7f8048c0e75b2620254218d72b4ae7f14136f1981c5eb555ef61645a9344505f -md5: 25f5885f11e8b1f075bccf4a2da91c60 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda +sha256: 348cb74c1530ac241215d047ef65d134cf797af935c97a68655319362b7e6a01 +md5: 3b129669089e4d6a5c6871dbb4669b99 depends: - ca-certificates - libgcc >=14 license: Apache-2.0 license_family: Apache -size: 3692030 -timestamp: 1769557678657 -- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda -sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 -md5: b76541e68fea4d511b1ac46a28dcd2c6 +size: 3706406 +timestamp: 1775589602258 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 +md5: 4c06a92e74452cfa53623a81592e8934 depends: - python >=3.8 - python license: Apache-2.0 license_family: APACHE -size: 72010 -timestamp: 1769093650580 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.1.1-py314hac3e5ec_0.conda -sha256: 1ca2d1616baad9bccb7ebc425ef2dcd6cebe742fbe91edf226fb606ad371ca0f -md5: d3c959c7efe560b2d7da459d69121fe9 +size: 91574 +timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.2.0-py314hac3e5ec_0.conda +sha256: 96b26c2657275ffe84ab510edf0865e21999d791485d12794edd4a71b837beb6 +md5: 87d58d103b47c4a8567b3d7666647684 depends: - python -- python 3.14.* *_cp314 - libgcc >=14 -- zlib-ng >=2.3.3,<2.4.0a0 +- python 3.14.* *_cp314 +- openjpeg >=2.5.4,<3.0a0 +- libxcb >=1.17.0,<2.0a0 - libwebp-base >=1.6.0,<2.0a0 +- zlib-ng >=2.3.3,<2.4.0a0 +- python_abi 3.14.* *_cp314 +- lcms2 >=2.18,<3.0a0 - tk >=8.6.13,<8.7.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 - libtiff >=4.7.1,<4.8.0a0 -- lcms2 >=2.18,<3.0a0 -- python_abi 3.14.* *_cp314 -- openjpeg >=2.5.4,<3.0a0 - libjpeg-turbo >=3.1.2,<4.0a0 -- libxcb >=1.17.0,<2.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 license: HPND -size: 1051828 -timestamp: 1770794010335 +size: 1062080 +timestamp: 1775060067775 - conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 md5: 3e9427ee186846052e81fadde8ebe96a @@ -1008,11 +996,11 @@ license: MIT license_family: MIT size: 5251872 timestamp: 1772628857717 -- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda -sha256: d332c2d5002fc440ae37ed9679ffc21b552f18d20232390005d1dd3bce0888d3 -md5: d5a4e013a30dd8dfde9ab39f45aaf9c1 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +sha256: 70fc56877c4a095ee658d61924d8019768fbae4a48437058d181fc94b0a7c4d8 +md5: 25a883fed9f1f3f21ff317a3e7c92ac4 depends: -- polars-runtime-32 ==1.39.3 +- polars-runtime-32 ==1.41.0 - python >=3.10 - python constrains: @@ -1026,27 +1014,16 @@ constrains: - pyiceberg >=0.7.1 - altair >=5.4.0 - great_tables >=0.8.0 -- polars-runtime-32 ==1.39.3 -- polars-runtime-64 ==1.39.3 -- polars-runtime-compat ==1.39.3 +- polars-runtime-32 ==1.41.0 +- polars-runtime-64 ==1.41.0 +- polars-runtime-compat ==1.41.0 license: MIT -license_family: MIT -size: 533495 -timestamp: 1774207987966 -- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda -sha256: e466fb31f67ba9bde18deafeb34263ca5eb25807f39ead0e9d753a8e82c4c4f4 -md5: ef0340e75068ac8ff96462749b5c98e7 -depends: -- polars >=1.34.0 -- polars-runtime-compat >=1.34.0 -license: MIT -license_family: MIT -size: 3902 -timestamp: 1760206808444 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.39.3-py310hff09b76_1.conda +size: 539656 +timestamp: 1779630790562 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.41.0-py310h32c7c23_0.conda noarch: python -sha256: c070be507c5a90df397a47ae0299660be437d5546d68f1bc0fa4402c9f07d59e -md5: 3c1a7c6b4ba8b9fb773ace9723f8a5db +sha256: d903b774ec09189e164207328aac157eee82fed8cc5c9ace46aeb5d1c15cb5b3 +md5: 8c08c506ed1ea8ce0ca37af5e918c58d depends: - python - libgcc >=14 @@ -1056,25 +1033,23 @@ depends: constrains: - __glibc >=2.17 license: MIT -license_family: MIT -size: 34785466 -timestamp: 1774207998285 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.39.3-py310hf00a4a2_1.conda +size: 38704429 +timestamp: 1779630794932 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.41.0-py310hc0e61be_0.conda noarch: python -sha256: 683315f1a49e47ce72bf9462419733b40b588b2b3106552d95fd4cd994e174de -md5: dd3464e2132dc3a783e76e5078870c76 +sha256: 101696adff43a654146376c62ef9611bf7946b95fa46f604fe247d77eefc6267 +md5: 65b73e4260677ee5162bdbb252e28e06 depends: - python -- libgcc >=14 - libstdcxx >=14 +- libgcc >=14 - _python_abi3_support 1.* - cpython >=3.10 constrains: - __glibc >=2.17 license: MIT -license_family: MIT -size: 34652491 -timestamp: 1774207996879 +size: 38651498 +timestamp: 1779630714016 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 md5: ab7288cc39545556d1bc5e71ab2df9a9 @@ -1104,24 +1079,23 @@ license: MIT license_family: MIT size: 14645 timestamp: 1736766960536 -- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda -sha256: 868569d9505b7fe246c880c11e2c44924d7613a8cdcc1f6ef85d5375e892f13d -md5: c3946ed24acdb28db1b5d63321dbca7d +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +sha256: 69700e31165df070e9716315e042196aa92525dae5deb5107785847ab9f4189f +md5: 729843edafc0899b3348bd3f19525b9d depends: - typing-inspection >=0.4.2 - typing_extensions >=4.14.1 - python >=3.10 -- typing-extensions >=4.6.1 - annotated-types >=0.6.0 -- pydantic-core ==2.41.5 +- pydantic-core ==2.46.4 - python license: MIT license_family: MIT -size: 340482 -timestamp: 1764434463101 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.41.5-py314h451b6cc_1.conda -sha256: f8acb2d03ebe80fed0032b9a989fc9acfb6735e3cd3f8c704b72728cb31868f6 -md5: 28f5027a1e04d67aa13fac1c5ba79693 +size: 346511 +timestamp: 1778103405862 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.46.4-py314h451b6cc_0.conda +sha256: 1a7c6b18e404c13c4d959888ecb48a9ed9de0e41be2872932b83a35278088df0 +md5: 9c3ace6aba6df14b943256095ac1281e depends: - python - typing-extensions >=4.6.0,!=4.7.0 @@ -1132,17 +1106,17 @@ constrains: - __glibc >=2.17 license: MIT license_family: MIT -size: 1828339 -timestamp: 1762989038561 -- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda -sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a -md5: 6b6ece66ebcae2d5f326c77ef2c5a066 +size: 1780773 +timestamp: 1778084251775 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 +md5: 16c18772b340887160c79a6acc022db0 depends: -- python >=3.9 +- python >=3.10 license: BSD-2-Clause license_family: BSD -size: 889287 -timestamp: 1750615908735 +size: 893031 +timestamp: 1774796815820 - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 md5: 461219d1a5bd61342293efa2c0c90eac @@ -1153,31 +1127,31 @@ license: BSD-3-Clause license_family: BSD size: 21085 timestamp: 1733217331982 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda -build_number: 101 -sha256: 87e9dff5646aba87cecfbc08789634c855871a7325169299d749040b0923a356 -md5: 205011b36899ff0edf41b3db0eda5a44 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.5-hfd9ac0a_100_cp314.conda +build_number: 100 +sha256: d37bad5447365346166c72950ea8f49689aa49cecc1b0623d00458427627b8df +md5: d956e09feb806f5974675ce92ad81d45 depends: - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-aarch64 >=2.36.1 -- libexpat >=2.7.3,<3.0a0 +- libexpat >=2.8.0,<3.0a0 - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 -- liblzma >=5.8.2,<6.0a0 +- liblzma >=5.8.3,<6.0a0 - libmpdec >=4.0.0,<5.0a0 -- libsqlite >=3.51.2,<4.0a0 -- libuuid >=2.41.3,<3.0a0 -- libzlib >=1.3.1,<2.0a0 -- ncurses >=6.5,<7.0a0 -- openssl >=3.5.5,<4.0a0 +- libsqlite >=3.53.1,<4.0a0 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- openssl >=3.5.6,<4.0a0 - python_abi 3.14.* *_cp314 - readline >=8.3,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata - zstd >=1.5.7,<1.6.0a0 license: Python-2.0 -size: 37305578 -timestamp: 1770674395875 +size: 37510439 +timestamp: 1779236267040 python_site_packages_path: lib/python3.14/site-packages - conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 @@ -1188,15 +1162,15 @@ license: BSD-3-Clause license_family: BSD size: 27848 timestamp: 1772388605021 -- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda -sha256: 233aebd94c704ac112afefbb29cf4170b7bc606e22958906f2672081bc50638a -md5: 235765e4ea0d0301c75965985163b5a1 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +sha256: 41dd7da285d71d519257fa7dacb1cae060d5ebfaa5f92cba5994899d2978e943 +md5: 41954747ba952ec4b01e16c2c9e8d8ff depends: -- cpython 3.14.3.* +- cpython 3.14.5.* - python_abi * *_cp314 license: Python-2.0 -size: 50062 -timestamp: 1770674497152 +size: 50212 +timestamp: 1779236703009 - conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 md5: 310259a5b03ff02289d7705f39e2b1d2 @@ -1253,9 +1227,9 @@ license: MIT license_family: MIT size: 51788 timestamp: 1760379115194 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.2.28-py314h51f160d_0.conda -sha256: 2080ecea825e1ef91a2422cc0bc63e85db9e38908ed17657fb8f41de7a6eee71 -md5: 818aa2c9f6b3c808da5e7be22a9a424c +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.5.9-py314h51f160d_0.conda +sha256: 05ef55f09f31eabd0a205f6b065e13fc746675f41924620977692ef0ffe5aad8 +md5: 34ed7bc9febeca70f55b757ca09c354d depends: - libgcc >=14 - python >=3.14,<3.15.0a0 @@ -1263,27 +1237,27 @@ depends: - python_abi 3.14.* *_cp314 license: Apache-2.0 AND CNRI-Python license_family: PSF -size: 408097 -timestamp: 1772255205521 -- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda -sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5 -md5: c65df89a0b2e321045a9e01d1337b182 +size: 409780 +timestamp: 1778374195988 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +sha256: 1715246b19c9f85ee022933b4845f2fc14ac9184981b7b7d9b728bec8e9588da +md5: 4a85203c1d80c1059086ae860836ffb9 depends: - python >=3.10 -- certifi >=2017.4.17 +- certifi >=2023.5.7 - charset-normalizer >=2,<4 - idna >=2.5,<4 -- urllib3 >=1.21.1,<3 +- urllib3 >=1.26,<3 - python constrains: -- chardet >=3.0.2,<6 +- chardet >=3.0.2,<8 license: Apache-2.0 license_family: APACHE -size: 63602 -timestamp: 1766926974520 -- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda -sha256: b06ce84d6a10c266811a7d3adbfa1c11f13393b91cc6f8a5b468277d90be9590 -md5: 7a6289c50631d620652f5045a63eb573 +size: 68709 +timestamp: 1778851103479 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +sha256: 3d6ba2c0fcdac3196ba2f0615b4104e532525ffa1335b50a2878be5ff488814a +md5: 0242025a3c804966bf71aa04eee82f66 depends: - markdown-it-py >=2.2.0 - pygments >=2.13.0,<3.0.0 @@ -1292,8 +1266,8 @@ depends: - python license: MIT license_family: MIT -size: 208472 -timestamp: 1771572730357 +size: 208577 +timestamp: 1775991661559 - conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 md5: 0c20a8ebcddb24a45da89d5e917e6cb9 @@ -1331,19 +1305,18 @@ license: MIT license_family: MIT size: 22284 timestamp: 1735770589188 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.52.0-hf1c7be2_0.conda -sha256: 4f8523f5341f0d9e1547085206c6c1f71f9fc7c277443ca363a8cf98add8fc01 -md5: d9634079df93a65ee045b3c75f35cae1 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.1-he8854b5_0.conda +sha256: 27467e4bfb0681546f149718c33b806fec078185fbaa6a4d17d440bc8f56185c +md5: 46009bdca2315a99e0a3a7d0ba1af3b9 depends: -- icu >=78.2,<79.0a0 - libgcc >=14 -- libsqlite 3.52.0 h10b116e_0 -- libzlib >=1.3.1,<2.0a0 -- ncurses >=6.5,<7.0a0 +- libsqlite 3.53.1 h022381a_0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 - readline >=8.3,<9.0a0 license: blessing -size: 209416 -timestamp: 1772818891689 +size: 209964 +timestamp: 1777986493350 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda sha256: c1da41c79262b27efa168407cfecc47b20270e5fc071a8307f95a2c85fb94170 md5: 55bf7b559202236157b14323b40f19e6 @@ -1382,20 +1355,20 @@ depends: license: MPL-2.0 and MIT size: 94132 timestamp: 1770153424136 -- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda -sha256: 39d8ae33c43cdb8f771373e149b0b4fae5a08960ac58dcca95b2f1642bb17448 -md5: 260af1b0a94f719de76b4e14094e9a3b +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +sha256: 59d7851d32fddb5b510272e6557aa982edeb927d349648dac27f5bf01d18bb26 +md5: 4460f039b7dedf15f7df086446ca75ae depends: -- importlib-metadata >=3.6 -- python >=3.10 -- typing-extensions >=4.10.0 - typing_extensions >=4.14.0 +- python >=3.10 +- importlib-metadata >=3.6 +- python constrains: - pytest >=7 license: MIT license_family: MIT -size: 36838 -timestamp: 1771532971545 +size: 38297 +timestamp: 1778779291237 - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c md5: edd329d7d3a4ab45dcf905899a7a6115 @@ -1405,16 +1378,17 @@ license: PSF-2.0 license_family: PSF size: 91383 timestamp: 1756220668932 -- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda -sha256: 70db27de58a97aeb7ba7448366c9853f91b21137492e0b4430251a1870aa8ff4 -md5: a0a4a3035667fc34f29bfbd5c190baa6 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +sha256: 8b90d2f19f9458b8c58a55e1fcdc1d90c1603a847a47654d8a454549413ba60a +md5: 53f5409c5cfd6c5a66417d68e3f0a864 depends: - python >=3.10 - typing_extensions >=4.12.0 +- python license: MIT license_family: MIT -size: 18923 -timestamp: 1764158430324 +size: 20935 +timestamp: 1777105465795 - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 md5: 0caa1af407ecff61170c9437a808404d @@ -1431,9 +1405,9 @@ md5: ad659d0a2b3e47e38d829aa8cad2d610 license: LicenseRef-Public-Domain size: 119135 timestamp: 1767016325805 -- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda -sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a -md5: 9272daa869e03efe68833e3dc7a02130 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 +md5: cbb88288f74dbe6ada1c6c7d0a97223e depends: - backports.zstd >=1.0.0 - brotli-python >=1.2.0 @@ -1442,8 +1416,8 @@ depends: - python >=3.10 license: MIT license_family: MIT -size: 103172 -timestamp: 1767817860341 +size: 103560 +timestamp: 1778188657149 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 md5: 1c246e1105000c3660558459e2fd6d43 @@ -1471,16 +1445,16 @@ license: MIT license_family: MIT size: 88088 timestamp: 1753484092643 -- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda -sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae -md5: 30cd29cb87d819caead4d55184c1d115 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +sha256: 210bd31c22bb88f5e2a167df24c95bb5f152b2ada7502f9b8c49d1f5366db423 +md5: ba3dcdc8584155c97c648ae9c044b7a3 depends: - python >=3.10 - python license: MIT license_family: MIT -size: 24194 -timestamp: 1764460141901 +size: 24190 +timestamp: 1779159948016 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda sha256: 638a3a41a4fbfed52d3c60c8ef5a3693b3f12a5b1a3f58fa29f5698d0a0702e2 md5: f731af71c723065d91b4c01bb822641b diff --git a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt deleted file mode 100644 index f787dbe..0000000 --- a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt +++ /dev/null @@ -1,125 +0,0 @@ - -# This file may be used to create an environment using: -# $ conda create --name --file -# platform: linux-aarch64 -@EXPLICIT -https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda#4faa39bf919939602e594253bd673958 -https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda#468fd3bb9e1f671d36c2cbc677e56f1d -https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda#552567ea2b61e3a3035759b2fdb3f9a6 -https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda#840d8fc0d7b3209be93080bc20e07f2d -https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda#502006882cf5461adced436e410046d1 -https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda#c3655f82dcea2aa179b291e7099c1fcc -https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda#a21644fc4a83da26452a718dc9468d5f -https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.5-hfae3067_0.conda#05d1e0b30acd816a192c03dc6e164f4d -https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda#2f364feefb6a7c00423e80dcb12db62a -https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda#76298a9e6d71ee6e832a8d0d7373b261 -https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda#7b9813e885482e3ccb1fa212b86d7fd0 -https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.0-h022381a_0.conda#86db4036fd08bf34e991bf48a8af405d -https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42-h1022ec0_0.conda#a0b5de740d01c390bdbb46d7503c9fab -https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda#182afabe009dc78d8b73100255ee6868 -https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda#e18ad67cf881dcadee8b8d9e2f8e5f73 -https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda#3b129669089e4d6a5c6871dbb4669b99 -https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda#0539938c55b6b1a59b560e843ad864a4 -https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda#3d49cad61f829f4f0e0611547a9cda12 -https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda#7fc6affb9b01e567d2ef1d05b84aa6ed -https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda#ad659d0a2b3e47e38d829aa8cad2d610 -https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.4-hfd9ac0a_100_cp314.conda#3cfbe780f0f51cc8cba41db9f8a28bfe -https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda#f111d4cfaf1fe9496f386bc98ae94452 -https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda#e4e60721757979d01d3964122f674959 -https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda#aaa2a381ccc56eac91d63b6c1240312f -https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda#0caa1af407ecff61170c9437a808404d -https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda#edd329d7d3a4ab45dcf905899a7a6115 -https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda#2934f256a8acfe48f6ebb4fce6cde29c -https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda#c6b0543676ecb1fb2d7643941fe375f2 -https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda#a2ac7763a9ac75055b68f325d3255265 -https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda#f56573d05e3b735cb03efeb64a15f388 -https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda#a1b5c571a0923a205d663d8678df4792 -https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda#929471569c93acefb30282a22060dcd5 -https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda#a9167b9571f3baa9d448faa2139d1089 -https://conda.anaconda.org/conda-forge/noarch/click-8.3.2-pyhc90fa1f_0.conda#4d18bc3af7cfcea97bd817164672a08c -https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda#7fe569c10905402ed47024fc481bb371 -https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda#b866ff7007b934d564961066c8195983 -https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda#a2c1eeadae7a309daed9d62c96012a2b -https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda#574d88ce3348331e962cfa5ed451b247 -https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda#41f261f5e4e2e8cbd236c2f1f15dae1b -https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.32-pthreads_h9d3fd7e_0.conda#5d2ce5cf40443d055ec6d33840192265 -https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-6_haddc8a3_openblas.conda#652bb20bb4618cacd11e17ae070f47ce -https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-6_hd72aa62_openblas.conda#939e300b110db241a96a1bed438c315b -https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-6_h88aeb00_openblas.conda#e23a27b52fb320687239e2c5ae4d7540 -https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py314haac167e_0.conda#25d896c331481145720a21e5145fad65 -https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda#071cf7b0ce333c81718b054066c15102 -https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.7.5-hfae3067_0.conda#d2bb0c889d94f2fdc5856392c3002976 -https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2#0c96522c6bdaed4b1566d11387caaf45 -https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2#34893075a5c9e55cdafac56607368fc6 -https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2#4d59c254e01d9cde7957100457e2d5fb -https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda#49023d73832ef61042f6a237cb2687e7 -https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda#f51503ac45a4888bce71af9027a2ecc9 -https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda#b99ed99e42dafb27889483b3098cace7 -https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda#a229e22d4d8814a07702b0919d8e6701 -https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda#0fed1ff55f4938a65907f3ecf62609db -https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda#a7970cd949a077b7cb9696379d338681 -https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda#0a802cb9888dd14eeefc611f05c40b6e -https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda#8e6923fc12f1fe8f8c4e5c9f343256ac -https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda#164fc43f0b53b6e3a7bc7dce5e4f1dc9 -https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda#daddf757c3ecd6067b9af1df1f25d89e -https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda#fb7130c190f9b4ec91219840a05ba3ac -https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda#e1c36c6121a7c9c76f2f148f1e83b983 -https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda#080594bf4493e6bae2607e65390c520a -https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda#e5de3c36dd548b35ff2a8aa49208dcb3 -https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda#04558c96691bed63104678757beb4f8d -https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda#e7f6ed9e60043bb5cbcc527764897f0d -https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda#870293df500ca7e18bedefa5838a22ab -https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda#439cd0f567d697b20a8f45cb70a1005a -https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda#ada41c863af263cc4c5fcbaff7c3e4dc -https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda#4feebd0fbf61075a1a9c2e9b3936c257 -https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2#7b08314a6867a9d5648a1c3265e9eb8e -https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda#6dd4f07147774bf720075a210f8026b9 -https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda#4540f9570d12db2150f42ba036154552 -https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.0-he8854b5_0.conda#ad8164bdeece883b825c50639c0c4725 -https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2#4f0d284f5d11e04277b552eb1c172c7f -https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda#a85ba48648f6868016f2741fd9170250 -https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda#d13423b06447113a90b5b1366d4da171 -https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda#a9138815598fe6b91a1d6782ca657b0c -https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda#24e92d0942c799db387f5c9d7b81f1af -https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda#8c6fd84f9c87ac00636007c6131e457d -https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda#bb960f01525b5e001608afef9d47b79c -https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda#bb5a90c93e3bac3d5690acf76b4a6386 -https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda#1c246e1105000c3660558459e2fd6d43 -https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda#bff06dcde4a707339d66d45d96ceb2e2 -https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda#cd14ee5cca2464a425b1dbfc24d90db2 -https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda#ba0a9221ce1063f31692c07370d062f3 -https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda#592132998493b3ff25fd7479396e8351 -https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda#5b5203189eb668f042ac2b0826244964 -https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda#e941e85e273121222580723010bd4fa2 -https://conda.anaconda.org/conda-forge/noarch/packaging-26.1-pyhc364b38_0.conda#b8ae38639d323d808da535fb71e31be8 -https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda#cea962410e327262346d48d01f05936c -https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda#f731af71c723065d91b4c01bb822641b -https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.2.0-py314hac3e5ec_0.conda#87d58d103b47c4a8567b3d7666647684 -https://conda.anaconda.org/conda-forge/noarch/narwhals-2.20.0-pyhcf101f3_0.conda#6cac1a50359219d786453c6fef819f98 -https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda#3e9427ee186846052e81fadde8ebe96a -https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.40.0-py310hff09b76_0.conda#d5628a33ce7652511e38fc98643dc910 -https://conda.anaconda.org/conda-forge/noarch/polars-1.40.0-pyh58ad624_0.conda#fd16be490f5403adfbf27dd4901bbe34 -https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.40.0-py310hf00a4a2_0.conda#a82af0fcbb72db253dc89a7a45279372 -https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda#ef0340e75068ac8ff96462749b5c98e7 -https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda#032d8030e4a24fe1f72c74423a46fb88 -https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda#9ae2c92975118058bd720e9ba2bb7c58 -https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda#e17be1016bcc3516827b836cd3e4d9dc -https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.46.3-py314h451b6cc_0.conda#1a2cb55be9a153ad6203bff6b787c240 -https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda#a0a4a3035667fc34f29bfbd5c190baa6 -https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.3-pyhcf101f3_0.conda#f690e6f204efd2e5c06b57518a383d98 -https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda#130584ad9f3a513cdd71b1fdc1244e9c -https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2#310259a5b03ff02289d7705f39e2b1d2 -https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda#461219d1a5bd61342293efa2c0c90eac -https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda#9272daa869e03efe68833e3dc7a02130 -https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda#10afbb4dbf06ff959ad25a92ccee6e59 -https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda#16c18772b340887160c79a6acc022db0 -https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda#0242025a3c804966bf71aa04eee82f66 -https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda#0c20a8ebcddb24a45da89d5e917e6cb9 -https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda#472239e4eb7b5a84bb96b3ed7e3a596a -https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.4.4-py314h51f160d_0.conda#88a3dbd279e6b1faf0cddb8397866864 -https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda#55bf7b559202236157b14323b40f19e6 -https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda#e5ce43272193b38c2e9037446c1d9206 -https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda#260af1b0a94f719de76b4e14094e9a3b -https://conda.anaconda.org/bioconda/noarch/multiqc-1.34-pyhdfd78af_0.conda#a7111ab9a6a6146b40cbce16655ac873 -https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh145f28c_0.conda#09a970fbf75e8ed1aa633827ded6aa4f -https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda#ab7288cc39545556d1bc5e71ab2df9a9 diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index 37e7612..7a970e2 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.34 + - bioconda::multiqc=1.35 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index e80e8cd..c4bc715 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -4,8 +4,8 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data' - : 'community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6'}" + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' + : 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc'}" input: tuple val(meta), path(multiqc_files, stageAs: "?/*"), path(multiqc_config, stageAs: "?/*"), path(multiqc_logo), path(replace_names), path(sample_names) diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index 2facc62..27ce18d 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -110,24 +110,24 @@ maintainers: containers: conda: linux/amd64: - lock_file: modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt + lock_file: modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt linux/arm64: - lock_file: modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt + lock_file: modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt docker: linux/amd64: - name: community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6 - build_id: bd-db7c73dae76bc9e6_1 - scan_id: sc-66fc7138dbf1cf48_1 + name: community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc + build_id: bd-c17fb751507e9dfc_1 + scan_id: sc-3b1b3932f9846892_1 linux/arm64: - name: community.wave.seqera.io/library/multiqc:1.34--d167b8012595a136 - build_id: bd-d167b8012595a136_1 - scan_id: sc-ac701dfa631a2af9_1 + name: community.wave.seqera.io/library/multiqc:1.35--5c84a5000a226ab5 + build_id: bd-5c84a5000a226ab5_1 + scan_id: sc-0d39df41e9737bbd_1 singularity: linux/amd64: - name: oras://community.wave.seqera.io/library/multiqc:1.34--4fc8657c816047c0 - build_id: bd-4fc8657c816047c0_1 - https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data + name: oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2 + build_id: bd-c680f2aea25ccec2_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data linux/arm64: - name: oras://community.wave.seqera.io/library/multiqc:1.34--7fbd82d945c06726 - build_id: bd-7fbd82d945c06726_1 - https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/9a/9a1fec9662a152683e6fcae440d0ce20920b3b89dc62d1e3a52e73f92eba0969/data + name: oras://community.wave.seqera.io/library/multiqc:1.35--c0468833d65b2f81 + build_id: bd-c0468833d65b2f81_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e4/e48aa28aebc881254a499b24c3e1ce77b8df1b85a5432699ed6f72eb17ac7fb5/data diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index 7c2f370..4489921 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -81,7 +81,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } @@ -175,7 +175,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } @@ -221,7 +221,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } @@ -314,7 +314,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } @@ -408,7 +408,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } From a7d6b58378d1f90e867cd253e05d7af1525e3c28 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 7 Jul 2026 20:26:43 +0000 Subject: [PATCH 131/334] Update citations --- CITATIONS.md | 12 +++++++++--- .../local/utils_nfcore_datasync_pipeline/main.nf | 6 ++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CITATIONS.md b/CITATIONS.md index 3032c6f..aaca6d9 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -10,13 +10,19 @@ ## Pipeline tools -- [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) +- [Rclone](https://rclone.org) -> Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. + > Craig-Wood, N. (2023). Rclone: Rsync for cloud storage (Vers. 1.65.0). Computer software. Web. - [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) -> Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. + > Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. + +## R packages + +- [R](https://www.R-project.org/) + + > R Core Team (2017). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. ## Software packaging/containerisation tools diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 818902c..a425b39 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -181,9 +181,9 @@ def toolCitationText() { // Uncomment function in methodsDescriptionText to render in MultiQC report def citation_text = [ "Tools used in the workflow included:", - "Files were transferred to the specified destination using Rclone (Nick Craig-Wood, https://rclone.org), which supports data movement across local and cloud storage backends.", + "Files were transferred to the specified destination using Rclone (Craig-Wood, 2023), which supports data movement across local and cloud storage backends.", "File integrity was validated by computing cryptographic checksums using md5sum and shasum.", - "Expected and observed checksum files were compared using the pipeline's local comparechecksum module, implemented in R.", + "Expected and observed checksum files were compared using the pipeline's local comparechecksum module, implemented in R (R Core Team, 2017).", "Pipeline results were summarised with MultiQC (Ewels et al. 2016)", "." ].join(' ').trim() @@ -196,6 +196,8 @@ def toolBibliographyText() { // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "
  • Author (2023) Pub name, Journal, DOI
  • " : "", // Uncomment function in methodsDescriptionText to render in MultiQC report def reference_text = [ + "
  • Craig-Wood, N. (2023). Rclone: Rsync for cloud storage (Vers. 1.65.0). Computer software. https://rclone.org
  • ", + "
  • R Core Team (2017). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. https://www.R-project.org/
  • ", "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics, 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " ].join(' ').trim() From 27c8a9e409c1488f07c7c0fe801d50aa7f7d97f9 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 7 Jul 2026 22:48:23 -0300 Subject: [PATCH 132/334] Update CHANGELOG --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cc972f..78212a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#29]](https://github.com/nf-core/datasync/pull/38)] - Implement Rclone module. ([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)) +- [[#29](https://github.com/nf-core/datasync/pull/38)] - Implement Rclone module ([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). +- [[#41](https://github.com/nf-core/datasync/pull/41)] - Generate MultiQC Report with comparechecksum tables and input samplesheet ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). ### `Fixed` From 45535958c8d34f40f20155efdae276932dd788f9 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 14 Jul 2026 19:16:52 +0000 Subject: [PATCH 133/334] import rclone_copy from nf core --- conf/modules.config | 3 - modules.json | 5 ++ modules/local/rclone_copy/main.nf | 41 ------------- .../rclone/copy}/environment.yml | 0 modules/nf-core/rclone/copy/main.nf | 55 +++++++++++++++++ .../rclone/copy}/meta.yml | 58 +++++++++++++++--- .../nf-core/rclone/copy/tests/main.nf.test | 61 +++++++++++++++++++ .../rclone/copy/tests/main.nf.test.snap | 54 ++++++++++++++++ .../nf-core/rclone/copy/tests/nextflow.config | 7 +++ workflows/datasync.nf | 22 ++----- 10 files changed, 239 insertions(+), 67 deletions(-) delete mode 100644 modules/local/rclone_copy/main.nf rename modules/{local/rclone_copy => nf-core/rclone/copy}/environment.yml (100%) create mode 100644 modules/nf-core/rclone/copy/main.nf rename modules/{local/rclone_copy => nf-core/rclone/copy}/meta.yml (50%) create mode 100644 modules/nf-core/rclone/copy/tests/main.nf.test create mode 100644 modules/nf-core/rclone/copy/tests/main.nf.test.snap create mode 100644 modules/nf-core/rclone/copy/tests/nextflow.config diff --git a/conf/modules.config b/conf/modules.config index 089b748..0f6532c 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -32,9 +32,6 @@ process { '--s3-chunk-size 64M', '--no-check-certificate' ] - if (meta.http_url) { - base_args.add(0, meta.http_url) - } if (params.rclone_dry_run) { base_args.add('--dry-run') } diff --git a/modules.json b/modules.json index 68a6e9b..ea936d1 100644 --- a/modules.json +++ b/modules.json @@ -15,6 +15,11 @@ "git_sha": "98403d15b0e50edae1f3fec5eae5e24982f1fade", "installed_by": ["modules"] }, + "rclone/copy": { + "branch": "master", + "git_sha": "6bb93c2adec5f390eb1976a59b7fe4a4b0cbb2a5", + "installed_by": ["modules"] + }, "shasum": { "branch": "master", "git_sha": "429d56ab5b5879549f71bf9905104f39d0c3bff4", diff --git a/modules/local/rclone_copy/main.nf b/modules/local/rclone_copy/main.nf deleted file mode 100644 index e76d5d4..0000000 --- a/modules/local/rclone_copy/main.nf +++ /dev/null @@ -1,41 +0,0 @@ -process RCLONE_COPY { - - tag "${meta.id}" - label 'process_low' - - conda "${moduleDir}/environment.yml" - container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' - : 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be'}" - - input: - tuple val(meta), val(source_path), val(destination_path) - path rclone_config - - output: - tuple val(meta), path("rclone-copy.log"), emit: log - tuple val("${task.process}"), val('rclone'), eval("rclone version | head -n1 | sed 's/rclone v//'"), topic: versions, emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def configArg = rclone_config ? "--config '${rclone_config}'" : '' - def transfers = task.ext.transfers ?: task.cpus - def checkers = task.ext.checkers ?: task.cpus - - """ - rclone ${configArg} copy ${args} \\ - --log-file rclone-copy.log \\ - --transfers ${transfers} \\ - --checkers ${checkers} \\ - "${source_path}" \\ - "${destination_path}" - """ - - stub: - """ - touch rclone-copy.log - """ -} diff --git a/modules/local/rclone_copy/environment.yml b/modules/nf-core/rclone/copy/environment.yml similarity index 100% rename from modules/local/rclone_copy/environment.yml rename to modules/nf-core/rclone/copy/environment.yml diff --git a/modules/nf-core/rclone/copy/main.nf b/modules/nf-core/rclone/copy/main.nf new file mode 100644 index 0000000..2c97b43 --- /dev/null +++ b/modules/nf-core/rclone/copy/main.nf @@ -0,0 +1,55 @@ +process RCLONE_COPY { + tag "${meta.id}" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' + : 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be'}" + + input: + tuple val(meta), val(source_path), val(destination_path) + path rclone_config + + output: + tuple val(meta), path("*rclone-copy.log"), emit: log + tuple val("${task.process}"), val('rclone'), eval("rclone --version | sed -n '1s/^rclone v//p'"), topic: versions, emit: versions_rclone + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def configArg = rclone_config ? "--config '${rclone_config}'" : '' + def transfers = Math.max(1, task.cpus.intdiv(2)) + def checkers = task.cpus + + // Handle HTTP URLs: split into --http-url base and :http:relative_path + def source_string = source_path.toString() + def rclone_source + def http_url_arg = '' + + if (source_string ==~ /^https?:\/\/.*/) { + def matcher = (source_string =~ /^(https?:\/\/[^\/]+)(\/.*)$/) + http_url_arg = "--http-url '${matcher[0][1]}'" + rclone_source = ":http:${matcher[0][2].replaceFirst('^/', '')}" + } else { + rclone_source = source_string.replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') + } + + """ + rclone ${configArg} copy \\ + ${http_url_arg} \\ + ${args} \\ + --log-file "${meta.id}-rclone-copy.log" \\ + --transfers ${transfers} \\ + --checkers ${checkers} \\ + "${rclone_source}" \\ + "${destination_path}" + """ + + stub: + """ + touch rclone-copy.log + """ +} diff --git a/modules/local/rclone_copy/meta.yml b/modules/nf-core/rclone/copy/meta.yml similarity index 50% rename from modules/local/rclone_copy/meta.yml rename to modules/nf-core/rclone/copy/meta.yml index f3ad059..4a9072f 100644 --- a/modules/local/rclone_copy/meta.yml +++ b/modules/nf-core/rclone/copy/meta.yml @@ -42,7 +42,8 @@ input: Rclone configuration file defining the remotes used by source_path and/or destination_path. Authentication and remote-specific options should be configured in this file where possible. - + pattern: "*.conf" + ontologies: [] output: log: - - meta: @@ -50,16 +51,59 @@ output: description: | Groovy Map containing sample information. e.g. [ id:'test', single_end:false ] - - "rclone-copy.log": + - rclone-copy.log: type: file description: Rclone log file generated during the copy operation. - versions: + pattern: "rclone-copy.log" + ontologies: [] + versions_rclone: - - ${task.process}: type: string - description: The name of the process. + description: The name of the process - rclone: type: string - description: The name of the tool. - - version: + description: The name of the tool + - rclone --version | sed -n '1s/^rclone v//p': + type: eval + description: The expression to obtain the version of the tool + +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - rclone: type: string - description: The version of Rclone used. + description: The name of the tool + - rclone --version | sed -n '1s/^rclone v//p': + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@antoniasaracco" +maintainers: + - "@antoniasaracco" +containers: + docker: + linux/amd64: + name: community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be + build_id: bd-ff88b2e0040147be_1 + scan_id: sc-ff88b2e0040147be_1 + linux/arm64: + name: community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be + build_id: bd-ff88b2e0040147be_1 + scan_id: sc-ff88b2e0040147be_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be + build_id: bd-ff88b2e0040147be_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data + linux/arm64: + name: oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be + build_id: bd-ff88b2e0040147be_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data + conda: + linux/amd64: + lock_file: modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt + linux/arm64: + lock_file: modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt diff --git a/modules/nf-core/rclone/copy/tests/main.nf.test b/modules/nf-core/rclone/copy/tests/main.nf.test new file mode 100644 index 0000000..14d79cb --- /dev/null +++ b/modules/nf-core/rclone/copy/tests/main.nf.test @@ -0,0 +1,61 @@ +nextflow_process { + + name "Test RCLONE_COPY" + script "../main.nf" + process "RCLONE_COPY" + + tag "modules" + tag "modules_nfcore" + tag "rclone" + tag "rclone/copy" + + test("homo_sapiens - gvcf - copy from https - dry-run") { + + config "./nextflow.config" + + when { + process { + """ + input[0] = [ + [ id:'test' ], + params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf.gz', + '/tmp/test.genome.vcf.gz' + ] + input[1] = [] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["log"])).match() } + ) + } + } + + test("homo_sapiens - gvcf - copy from https - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], + params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf.gz', + '/tmp/test.genome.vcf.gz' + ] + input[1] = [] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot(sanitizeOutput(process.out)).match() } + ) + } + } +} diff --git a/modules/nf-core/rclone/copy/tests/main.nf.test.snap b/modules/nf-core/rclone/copy/tests/main.nf.test.snap new file mode 100644 index 0000000..60d464e --- /dev/null +++ b/modules/nf-core/rclone/copy/tests/main.nf.test.snap @@ -0,0 +1,54 @@ +{ + "homo_sapiens - gvcf - copy from https - stub": { + "content": [ + { + "log": [ + [ + { + "id": "test" + }, + "rclone-copy.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_rclone": [ + [ + "RCLONE_COPY", + "rclone", + "1.65.0-DEV" + ] + ] + } + ], + "timestamp": "2026-07-13T23:23:37.720920849", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.4" + } + }, + "homo_sapiens - gvcf - copy from https - dry-run": { + "content": [ + { + "log": [ + [ + { + "id": "test" + }, + "rclone-copy.log" + ] + ], + "versions_rclone": [ + [ + "RCLONE_COPY", + "rclone", + "1.65.0-DEV" + ] + ] + } + ], + "timestamp": "2026-07-13T23:23:31.914171479", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.4" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/rclone/copy/tests/nextflow.config b/modules/nf-core/rclone/copy/tests/nextflow.config new file mode 100644 index 0000000..0e911db --- /dev/null +++ b/modules/nf-core/rclone/copy/tests/nextflow.config @@ -0,0 +1,7 @@ +process { + withName: 'RCLONE_COPY' { + ext.args = { + "--dry-run --no-check-certificate" + } + } +} diff --git a/workflows/datasync.nf b/workflows/datasync.nf index d949873..a275f5c 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -6,7 +6,7 @@ include { COMPARECHECKSUM } from '../modules/local/comparechecksum/main' include { MD5SUM } from '../modules/nf-core/md5sum/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' -include { RCLONE_COPY } from '../modules/local/rclone_copy/main' +include { RCLONE_COPY } from '../modules/nf-core/rclone/copy/main' include { SHASUM } from '../modules/nf-core/shasum/main' include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' @@ -39,28 +39,18 @@ workflow DATASYNC { def source_string = input_path.toString() - def rclone_source - def rclone_http_url = '' - - if (source_string ==~ /^https?:\/\/.*/) { - // HTTP: split into --http-url base and :http:path - def matcher = (source_string =~ /^(https?:\/\/[^\/]+)(\/.*)$/) - rclone_http_url = "--http-url '${matcher[0][1]}'" - rclone_source = ":http:${matcher[0][2].replaceFirst('^/', '')}" - } else { - // Cloud remotes (s3://, gs://, az://): strip :// to : - rclone_source = source_string.replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') - } - def source_name = source_string .replaceAll('/+$', '') .tokenize('/') .last() - def rclone_destination = "${output_path.toString().replaceAll('/+$', '')}/${source_name}" + def is_file = source_name.contains('.') + def rclone_destination = is_file + ? output_path.toString().replaceAll('/+$', '') + : "${output_path.toString().replaceAll('/+$', '')}/${source_name}" input: [ meta, input_path ] - rclone: [ meta + [http_url: rclone_http_url], rclone_source, rclone_destination ] + rclone: [ meta, source_string, rclone_destination ] checksum: [ meta, md5, sha ] } From 23d9d029785ea89034350acf610aec66d7312bac Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 14 Jul 2026 19:19:10 +0000 Subject: [PATCH 134/334] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78212a5..58ce463 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#29](https://github.com/nf-core/datasync/pull/38)] - Implement Rclone module ([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). +- [[#45](https://github.com/nf-core/datasync/pull/46)] - Import Rclone module from nf-core([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#41](https://github.com/nf-core/datasync/pull/41)] - Generate MultiQC Report with comparechecksum tables and input samplesheet ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). ### `Fixed` From 69b94fad927391d424eca70b987bf281d8eb575a Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 15 Jul 2026 02:57:46 +0200 Subject: [PATCH 135/334] Add local rclone modules --- modules/local/rclone/check/main.nf | 56 ++++++++++++++++++++++++++ modules/local/rclone/checksum/main.nf | 57 +++++++++++++++++++++++++++ modules/local/rclone_copy/main.nf | 28 +++++++++---- 3 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 modules/local/rclone/check/main.nf create mode 100644 modules/local/rclone/checksum/main.nf diff --git a/modules/local/rclone/check/main.nf b/modules/local/rclone/check/main.nf new file mode 100644 index 0000000..8d2cd79 --- /dev/null +++ b/modules/local/rclone/check/main.nf @@ -0,0 +1,56 @@ +process RCLONE_CHECK { + tag "${meta.id}" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data' + : 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' }" + + input: + tuple val(meta), path(source, stageAs: 'source/*'), path(destination, stageAs: 'destination/*') + + output: + tuple val(meta), path("${prefix}.combined.txt") , emit: combined , optional: true + tuple val(meta), path("${prefix}.differ.txt") , emit: differ , optional: true + tuple val(meta), path("${prefix}.missing_on_dst.txt") , emit: missing_on_dst, optional: true + tuple val(meta), path("${prefix}.missing_on_src.txt") , emit: missing_on_src, optional: true + tuple val(meta), path("${prefix}.match.txt") , emit: match , optional: true + tuple val(meta), path("${prefix}.error.txt") , emit: error , optional: true + tuple val("${task.process}"), val('rclone'), eval("rclone --version | sed -n '1s/^rclone v//p'"), topic: versions, emit: versions_rclone + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + + """ + rclone check \\ + --copy-links \\ + $args \\ + --combined ${prefix}.combined.txt \\ + --differ ${prefix}.differ.txt \\ + --missing-on-dst ${prefix}.missing_on_dst.txt \\ + --missing-on-src ${prefix}.missing_on_src.txt \\ + --match ${prefix}.match.txt \\ + --error ${prefix}.error.txt \\ + --checkers $task.cpus \\ + source \\ + destination || true + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + + """ + touch \\ + ${prefix}.combined.txt \\ + ${prefix}.differ.txt \\ + ${prefix}.missing_on_dst.txt \\ + ${prefix}.missing_on_src.txt \\ + ${prefix}.match.txt \\ + ${prefix}.error.txt + """ +} \ No newline at end of file diff --git a/modules/local/rclone/checksum/main.nf b/modules/local/rclone/checksum/main.nf new file mode 100644 index 0000000..4fcf838 --- /dev/null +++ b/modules/local/rclone/checksum/main.nf @@ -0,0 +1,57 @@ +process RCLONE_CHECKSUM { + tag "${meta.id}" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data' + : 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' }" + + input: + tuple val(meta), path(sumfile), val(hash), path(destination, stageAs: 'destination/*') + + output: + tuple val(meta), path("${prefix}.combined.txt") , emit: combined , optional: true + tuple val(meta), path("${prefix}.differ.txt") , emit: differ , optional: true + tuple val(meta), path("${prefix}.missing_on_dst.txt") , emit: missing_on_dst, optional: true + tuple val(meta), path("${prefix}.missing_on_src.txt") , emit: missing_on_src, optional: true + tuple val(meta), path("${prefix}.match.txt") , emit: match , optional: true + tuple val(meta), path("${prefix}.error.txt") , emit: error , optional: true + tuple val("${task.process}"), val('rclone'), eval("rclone --version | sed -n '1s/^rclone v//p'"), topic: versions, emit: versions_rclone + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + + """ + rclone checksum \\ + --copy-links \\ + $args \\ + --combined ${prefix}.combined.txt \\ + --differ ${prefix}.differ.txt \\ + --missing-on-dst ${prefix}.missing_on_dst.txt \\ + --missing-on-src ${prefix}.missing_on_src.txt \\ + --match ${prefix}.match.txt \\ + --error ${prefix}.error.txt \\ + --checkers $task.cpus \\ + $hash \\ + $sumfile \\ + destination || true + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + + """ + touch \\ + ${prefix}.combined.txt \\ + ${prefix}.differ.txt \\ + ${prefix}.missing_on_dst.txt \\ + ${prefix}.missing_on_src.txt \\ + ${prefix}.match.txt \\ + ${prefix}.error.txt + """ +} \ No newline at end of file diff --git a/modules/local/rclone_copy/main.nf b/modules/local/rclone_copy/main.nf index e76d5d4..accad23 100644 --- a/modules/local/rclone_copy/main.nf +++ b/modules/local/rclone_copy/main.nf @@ -1,5 +1,4 @@ process RCLONE_COPY { - tag "${meta.id}" label 'process_low' @@ -14,7 +13,7 @@ process RCLONE_COPY { output: tuple val(meta), path("rclone-copy.log"), emit: log - tuple val("${task.process}"), val('rclone'), eval("rclone version | head -n1 | sed 's/rclone v//'"), topic: versions, emit: versions + tuple val("${task.process}"), val('rclone'), eval("rclone --version | sed -n '1s/^rclone v//p'"), topic: versions, emit: versions_rclone when: task.ext.when == null || task.ext.when @@ -22,15 +21,30 @@ process RCLONE_COPY { script: def args = task.ext.args ?: '' def configArg = rclone_config ? "--config '${rclone_config}'" : '' - def transfers = task.ext.transfers ?: task.cpus - def checkers = task.ext.checkers ?: task.cpus + def transfers = Math.max(1, task.cpus.intdiv(2)) + def checkers = task.cpus + + // Handle HTTP URLs: split into --http-url base and :http:relative_path + def source_string = source_path.toString() + def rclone_source + def http_url_arg = '' + + if (source_string ==~ /^https?:\/\/.*/) { + def matcher = (source_string =~ /^(https?:\/\/[^\/]+)(\/.*)$/) + http_url_arg = "--http-url '${matcher[0][1]}'" + rclone_source = ":http:${matcher[0][2].replaceFirst('^/', '')}" + } else { + rclone_source = source_string.replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') + } """ - rclone ${configArg} copy ${args} \\ + rclone ${configArg} copy \\ + ${http_url_arg} \\ + ${args} \\ --log-file rclone-copy.log \\ --transfers ${transfers} \\ --checkers ${checkers} \\ - "${source_path}" \\ + "${rclone_source}" \\ "${destination_path}" """ @@ -38,4 +52,4 @@ process RCLONE_COPY { """ touch rclone-copy.log """ -} +} \ No newline at end of file From 2f48fbf1cd6636ec4e89977d84e71584f6c5d603 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 15 Jul 2026 02:59:39 +0200 Subject: [PATCH 136/334] Switch to use rclone modules --- conf/modules.config | 13 +++-- workflows/datasync.nf | 121 +++++++++++++++++++++++++++++------------- 2 files changed, 93 insertions(+), 41 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 089b748..c981ac6 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -32,9 +32,6 @@ process { '--s3-chunk-size 64M', '--no-check-certificate' ] - if (meta.http_url) { - base_args.add(0, meta.http_url) - } if (params.rclone_dry_run) { base_args.add('--dry-run') } @@ -42,6 +39,16 @@ process { } } + withName: 'RCLONE_CHECK' { + ext.args = { + def base_args = [ + '--no-check-certificate', + '--one-way' + ] + base_args.join(' ') + } + } + withName: 'MULTIQC' { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ diff --git a/workflows/datasync.nf b/workflows/datasync.nf index d949873..4c3eb8b 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -3,11 +3,10 @@ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { COMPARECHECKSUM } from '../modules/local/comparechecksum/main' -include { MD5SUM } from '../modules/nf-core/md5sum/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' include { RCLONE_COPY } from '../modules/local/rclone_copy/main' -include { SHASUM } from '../modules/nf-core/shasum/main' +include { RCLONE_CHECK } from '../modules/local/rclone/check/main' +include { RCLONE_CHECKSUM } from '../modules/local/rclone/checksum/main' include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' @@ -39,61 +38,68 @@ workflow DATASYNC { def source_string = input_path.toString() - def rclone_source - def rclone_http_url = '' - - if (source_string ==~ /^https?:\/\/.*/) { - // HTTP: split into --http-url base and :http:path - def matcher = (source_string =~ /^(https?:\/\/[^\/]+)(\/.*)$/) - rclone_http_url = "--http-url '${matcher[0][1]}'" - rclone_source = ":http:${matcher[0][2].replaceFirst('^/', '')}" - } else { - // Cloud remotes (s3://, gs://, az://): strip :// to : - rclone_source = source_string.replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') - } - def source_name = source_string .replaceAll('/+$', '') .tokenize('/') .last() - def rclone_destination = "${output_path.toString().replaceAll('/+$', '')}/${source_name}" + def is_file = source_name.contains('.') + def rclone_destination = is_file + ? output_path.toString().replaceAll('/+$', '') + : "${output_path.toString().replaceAll('/+$', '')}/${source_name}" + + def rclone_check = "${output_path.toString().replaceAll('/+$', '')}/${source_name}" input: [ meta, input_path ] - rclone: [ meta + [http_url: rclone_http_url], rclone_source, rclone_destination ] - checksum: [ meta, md5, sha ] + rclone: [ meta, input_path, rclone_destination ] + checksum: [ meta, md5, sha, file(input_path) ] + check : [ meta, file(input_path), file(rclone_check) ] } - MD5SUM( - ch_samplesheet.input, - false - ) - - SHASUM( - ch_samplesheet.input, - false - ) - // Group input md5sum/shasum with their respective generated checksum ch_checksum = ch_samplesheet.checksum - .join(MD5SUM.out.checksum) - .join(SHASUM.out.checksum) - .flatMap { meta, md5, sha, out_md5, out_sha -> + .flatMap { meta, md5, sha, input -> def checksum_tuple = [] - // If checksum is empty it will read the md5/shasum from meta if (md5) { - checksum_tuple << tuple(meta + [check_format: "md5"], md5, out_md5) + checksum_tuple << tuple(meta + [check_format: "md5"], md5, 'MD5', input) } if (sha) { - checksum_tuple << tuple(meta + [check_format: "sha"], sha, out_sha) + checksum_tuple << tuple(meta + [check_format: "sha"], sha, "SHA256", input) } return checksum_tuple } - COMPARECHECKSUM(ch_checksum) - ch_multiqc_files = ch_multiqc_files.mix(COMPARECHECKSUM.out.report.map { meta, report -> report }) - ch_multiqc_files = ch_multiqc_files.mix(COMPARECHECKSUM.out.summary_report.map { meta, summary -> summary }) + RCLONE_CHECKSUM( + ch_checksum + ) + + ch_multiqc_files = ch_multiqc_files.mix(RCLONE_CHECKSUM.out.combined + .flatMap { meta, check_file -> + check_file.readLines() + .findAll { it.trim() } + .collect { line -> + def fields = line.split(/ /, 2) + def status_map = [ + '=': 'Match', + '-': 'Missing in source', + '+': 'Missing in destination', + '*': 'Mismatch', + '!': 'Error' + ] + + def status = status_map.get(fields[0], fields[0]) + + [ meta, "${fields[1]}\t${meta.id}\t${status}\n" ] + } + } + .collectFile( + seed: "File\tSample\tStatus\n", + sort: false + ) { meta, checksum -> + return [ "${meta.id}_${meta.check_format}_rclone_checksum_mqc.tsv", checksum ] + } + ) // // MODULE: Rclone data copying @@ -103,6 +109,45 @@ workflow DATASYNC { rclone_config ? file(rclone_config, checkIfExists: true) : [] ) + // + // File transfer validation + // + // Wait for file copy to finish before running RCLONE_CHECK + ch_rclone_check = ch_samplesheet.check + .join(RCLONE_COPY.out.log) + .map { meta, input, output, log -> [ meta, input, output ]} + + RCLONE_CHECK( + ch_rclone_check + ) + + ch_multiqc_files = ch_multiqc_files.mix(RCLONE_CHECK.out.combined + .flatMap { meta, check_file -> + check_file.readLines() + .findAll { it.trim() } + .collect { line -> + def fields = line.split(/ /, 2) + def status_map = [ + '=': 'Match', + '-': 'Missing in source', + '+': 'Missing in destination', + '*': 'Mismatch', + '!': 'Error' + ] + + def status = status_map.get(fields[0], fields[0]) + + [ meta, "${fields[1]}\t${meta.id}\t${status}\n" ] + } + } + .collectFile( + seed: "File\tSample\tStatus\n", + sort: false + ) { meta, check -> + return [ "${meta.id}_rclone_check_mqc.tsv", check ] + } + ) + // // Collate and save software versions // From 35e2f222fc5a91cc531e5c58c17dd900bb6c824f Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 15 Jul 2026 03:00:13 +0200 Subject: [PATCH 137/334] Use rclone outputs in multiqc report --- assets/multiqc_config.yml | 91 +++++++++------------------------------ 1 file changed, 20 insertions(+), 71 deletions(-) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 693d656..20e26ab 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -31,87 +31,36 @@ custom_data: checksum_sha: title: Sha256 checksum file - md5_checksum_summary: - section_name: "MD5 Checksum Summary" - description: "Summary of MD5 checksum validation" + rclone_checksum_md5: + section_name: "RClone MD5 Checksum Report" + description: "MD5 input checksum validation" plot_type: "table" - file_format: "csv" - headers: - Match: - description: "Number of files whose output checksum matches the expected checksum." - Mismatch: - description: "Number of files whose output checksum differs from the expected checksum." - Missing: - description: "Number of expected input files that are missing from the output." - Unexpected: - description: "Number of output files that were not present in the input checksum list." - - sha_checksum_summary: - section_name: "SHA Checksum Summary" - description: "Summary of SHA checksum validation" - plot_type: "table" - file_format: "csv" - headers: - Match: - description: "Number of files whose output checksum matches the expected checksum." - Mismatch: - description: "Number of files whose output checksum differs from the expected checksum." - Missing: - description: "Number of expected input files that are missing from the output." - Unexpected: - description: "Number of output files that were not present in the input checksum list." + file_format: "tsv" + pconfig: + no_violin: true - md5_checksum_report: - section_name: "MD5 Checksum Report" - description: "Detailed MD5 checksum validation report" + rclone_checksum_sha: + section_name: "RClone SHA Checksum Report" + description: "SHA input checksum validation" plot_type: "table" - file_format: "csv" + file_format: "tsv" pconfig: no_violin: true - headers: - File: - title: File - description: "Path to the file being validated." - checksum_expected: - title: Expected checksum - description: "Checksum recorded for the input file before processing." - checksum_observed: - title: Observed checksum - description: "Checksum calculated for the corresponding output file after processing." - status: - title: Status - description: "Comparison result between the expected and observed checksums." - sha_checksum_report: - section_name: "SHA Checksum Report" - description: "Detailed SHA checksum validation report" + rclone_check: + section_name: "Final RClone Check Report" + description: "Validation of copied files" plot_type: "table" - file_format: "csv" + file_format: "tsv" pconfig: no_violin: true - headers: - File: - title: File - description: "Path to the file being validated." - checksum_expected: - title: Expected checksum - description: "Checksum recorded for the input file before processing." - checksum_observed: - title: Observed checksum - description: "Checksum calculated for the corresponding output file after processing." - status: - title: Status - description: "Comparison result between the expected and observed checksums." sp: samplesheet: fn: "samplesheet.csv" - - md5_checksum_summary: - fn: "*_md5.checksum_summary.csv" - sha_checksum_summary: - fn: "*_sha.checksum_summary.csv" - md5_checksum_report: - fn: "*_md5.checksum_validation.csv" - sha_checksum_report: - fn: "*_sha.checksum_validation.csv" + rclone_checksum_md5: + fn: "*_md5_rclone_checksum_mqc.tsv" + rclone_checksum_sha: + fn: "*_sha_rclone_checksum_mqc.tsv" + rclone_check: + fn: "*_rclone_check_mqc.tsv" From e7ef374f2b7641bae70bfc1101f2db3f0690907d Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 15 Jul 2026 03:51:56 +0200 Subject: [PATCH 138/334] Update snapshots --- tests/.nftignore | 3 +- tests/default.nf.test.snap | 62 ++++++++++++++++-------------------- tests/main_full.nf.test.snap | 50 +++++++++++------------------ 3 files changed, 48 insertions(+), 67 deletions(-) diff --git a/tests/.nftignore b/tests/.nftignore index 38c8c59..f6d171f 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -10,6 +10,5 @@ multiqc/multiqc_plots/{svg,pdf,png}/*.{svg,pdf,png} multiqc/multiqc_report.html fastqc/*_fastqc.{html,zip} pipeline_info/*.{html,json,txt,yml} -md5sum/** -shasum/** +rclone/*.txt rclone/*.log diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index aaa0996..60a5e58 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -2,34 +2,20 @@ "-profile test": { "content": [ { - "COMPARECHECKSUM": { - "r-base": "4.2.1" + "RCLONE_CHECK": { + "rclone": "1.74.3-DEV" }, - "MD5SUM": { - "md5sum": 9.5 + "RCLONE_CHECKSUM": { + "rclone": "1.74.3-DEV" }, "RCLONE_COPY": { "rclone": "1.65.0-DEV" }, - "SHASUM": { - "sha256sum": 9.5 - }, "Workflow": { "nf-core/datasync": "v1.0dev" } }, [ - "comparechecksum", - "comparechecksum/Illumina_annotation_md5.checksum_summary.csv", - "comparechecksum/Illumina_annotation_md5.checksum_validation.csv", - "comparechecksum/benchmark_bed_md5.checksum_summary.csv", - "comparechecksum/benchmark_bed_md5.checksum_validation.csv", - "comparechecksum/test_fastq_md5.checksum_summary.csv", - "comparechecksum/test_fastq_md5.checksum_validation.csv", - "md5sum", - "md5sum/Illumina_annotation.md5", - "md5sum/benchmark_bed.md5", - "md5sum/test_fastq.md5", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", @@ -37,8 +23,8 @@ "multiqc/multiqc_data/multiqc.parquet", "multiqc/multiqc_data/multiqc_citations.txt", "multiqc/multiqc_data/multiqc_data.json", - "multiqc/multiqc_data/multiqc_md5_checksum_report.txt", - "multiqc/multiqc_data/multiqc_md5_checksum_summary.txt", + "multiqc/multiqc_data/multiqc_rclone_check.txt", + "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -46,26 +32,34 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", + "rclone/Illumina_annotation.combined.txt", + "rclone/Illumina_annotation.differ.txt", + "rclone/Illumina_annotation.error.txt", + "rclone/Illumina_annotation.match.txt", + "rclone/Illumina_annotation.missing_on_dst.txt", + "rclone/Illumina_annotation.missing_on_src.txt", + "rclone/benchmark_bed.combined.txt", + "rclone/benchmark_bed.differ.txt", + "rclone/benchmark_bed.error.txt", + "rclone/benchmark_bed.match.txt", + "rclone/benchmark_bed.missing_on_dst.txt", + "rclone/benchmark_bed.missing_on_src.txt", "rclone/rclone-copy.log", - "shasum", - "shasum/Illumina_annotation.sha256", - "shasum/benchmark_bed.sha256", - "shasum/test_fastq.sha256" + "rclone/test_fastq.combined.txt", + "rclone/test_fastq.differ.txt", + "rclone/test_fastq.error.txt", + "rclone/test_fastq.match.txt", + "rclone/test_fastq.missing_on_dst.txt", + "rclone/test_fastq.missing_on_src.txt" ], [ - "Illumina_annotation_md5.checksum_summary.csv:md5,eaff8b778f802026d8013d004a9aa00f", - "Illumina_annotation_md5.checksum_validation.csv:md5,ce382d06839523dd9c390e3b34881be0", - "benchmark_bed_md5.checksum_summary.csv:md5,266bcbba1edbc6720508aa392387c566", - "benchmark_bed_md5.checksum_validation.csv:md5,b528bcd09ff8e6bf3c51e72d3e4ebe8f", - "test_fastq_md5.checksum_summary.csv:md5,6904f7c475eb219bee74f013a1870caf", - "test_fastq_md5.checksum_validation.csv:md5,4c94e3b3362f854c42941fc67b226ac2", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_md5_checksum_report.txt:md5,39147d72a414c399614f139354e36a86", - "multiqc_md5_checksum_summary.txt:md5,d8c3b87b26251d4d6cb1aca315f0f531", - "multiqc_samplesheet.txt:md5,3cc1e0340101fe132e7ce466187f3c4b" + "multiqc_rclone_check.txt:md5,b6ea8bb50b08e6a31b02de80f15cba83", + "multiqc_rclone_checksum_md5.txt:md5,b6ea8bb50b08e6a31b02de80f15cba83", + "multiqc_samplesheet.txt:md5,608c07d7a768f3d66b44f8daddcec95e" ] ], - "timestamp": "2026-07-07T15:28:47.101399362", + "timestamp": "2026-07-15T03:46:47.848763259", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index a5a2652..f44be10 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -2,30 +2,20 @@ "-profile test_full": { "content": [ { - "COMPARECHECKSUM": { - "r-base": "4.2.1" + "RCLONE_CHECK": { + "rclone": "1.74.3-DEV" }, - "MD5SUM": { - "md5sum": 9.5 + "RCLONE_CHECKSUM": { + "rclone": "1.74.3-DEV" }, "RCLONE_COPY": { "rclone": "1.65.0-DEV" }, - "SHASUM": { - "sha256sum": 9.5 - }, "Workflow": { "nf-core/datasync": "v1.0dev" } }, [ - "comparechecksum", - "comparechecksum/demultiplex_md5.checksum_summary.csv", - "comparechecksum/demultiplex_md5.checksum_validation.csv", - "comparechecksum/demultiplex_sha.checksum_summary.csv", - "comparechecksum/demultiplex_sha.checksum_validation.csv", - "md5sum", - "md5sum/demultiplex.md5", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", @@ -33,35 +23,33 @@ "multiqc/multiqc_data/multiqc.parquet", "multiqc/multiqc_data/multiqc_citations.txt", "multiqc/multiqc_data/multiqc_data.json", - "multiqc/multiqc_data/multiqc_md5_checksum_report.txt", - "multiqc/multiqc_data/multiqc_md5_checksum_summary.txt", + "multiqc/multiqc_data/multiqc_rclone_check.txt", + "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", + "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", - "multiqc/multiqc_data/multiqc_sha_checksum_report.txt", - "multiqc/multiqc_data/multiqc_sha_checksum_summary.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", - "rclone/rclone-copy.log", - "shasum", - "shasum/demultiplex.sha256" + "rclone/demultiplex.combined.txt", + "rclone/demultiplex.differ.txt", + "rclone/demultiplex.error.txt", + "rclone/demultiplex.match.txt", + "rclone/demultiplex.missing_on_dst.txt", + "rclone/demultiplex.missing_on_src.txt", + "rclone/rclone-copy.log" ], [ - "demultiplex_md5.checksum_summary.csv:md5,23b0f0d7d74706e07f249ed30bbb34a6", - "demultiplex_md5.checksum_validation.csv:md5,743eef23f7d1ddc87bcd3b901b65cae7", - "demultiplex_sha.checksum_summary.csv:md5,24f4d1d614fd57980b7484231f4855b9", - "demultiplex_sha.checksum_validation.csv:md5,96f322a237447d90d68131fb85ce76be", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_md5_checksum_report.txt:md5,8d84f5711d802cd908cf5780f1fd029e", - "multiqc_md5_checksum_summary.txt:md5,14a9c197093f8cd187833a11e13a3c58", - "multiqc_samplesheet.txt:md5,95d11730dbbf9fee3ca00f2792330c63", - "multiqc_sha_checksum_report.txt:md5,52c4bffaf0a94c59d4c2111fc62c074d", - "multiqc_sha_checksum_summary.txt:md5,78a00f0c20054c0f1853ceac0fcc0172" + "multiqc_rclone_check.txt:md5,034d1d633f567288c33f2c5e2b917962", + "multiqc_rclone_checksum_md5.txt:md5,dda2aa574568eb99f579fca2a1b19207", + "multiqc_rclone_checksum_sha.txt:md5,034d1d633f567288c33f2c5e2b917962", + "multiqc_samplesheet.txt:md5,29fbce9d1ffcdb97cb2ae32606e7145d" ] ], - "timestamp": "2026-07-07T15:30:52.986332849", + "timestamp": "2026-07-15T03:49:57.234615558", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From 272e80cca356f6ffa1464caba48a41e1b1b357f9 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 15 Jul 2026 03:53:49 +0200 Subject: [PATCH 139/334] Uninstall md5 and checkusm modules and delete local comparechecksum module --- modules.json | 10 - modules/local/comparechecksum/environment.yml | 8 - modules/local/comparechecksum/main.nf | 37 --- modules/local/comparechecksum/meta.yml | 69 ---- .../templates/comparechecksum.R | 91 ------ modules/nf-core/md5sum/environment.yml | 12 - modules/nf-core/md5sum/main.nf | 55 ---- modules/nf-core/md5sum/meta.yml | 68 ---- modules/nf-core/md5sum/tests/main.nf.test | 180 ----------- .../nf-core/md5sum/tests/main.nf.test.snap | 301 ------------------ modules/nf-core/md5sum/tests/nextflow.config | 2 - modules/nf-core/shasum/environment.yml | 12 - modules/nf-core/shasum/main.nf | 55 ---- modules/nf-core/shasum/meta.yml | 67 ---- modules/nf-core/shasum/tests/main.nf.test | 87 ----- .../nf-core/shasum/tests/main.nf.test.snap | 86 ----- 16 files changed, 1140 deletions(-) delete mode 100644 modules/local/comparechecksum/environment.yml delete mode 100644 modules/local/comparechecksum/main.nf delete mode 100644 modules/local/comparechecksum/meta.yml delete mode 100644 modules/local/comparechecksum/templates/comparechecksum.R delete mode 100644 modules/nf-core/md5sum/environment.yml delete mode 100644 modules/nf-core/md5sum/main.nf delete mode 100644 modules/nf-core/md5sum/meta.yml delete mode 100644 modules/nf-core/md5sum/tests/main.nf.test delete mode 100644 modules/nf-core/md5sum/tests/main.nf.test.snap delete mode 100644 modules/nf-core/md5sum/tests/nextflow.config delete mode 100644 modules/nf-core/shasum/environment.yml delete mode 100644 modules/nf-core/shasum/main.nf delete mode 100644 modules/nf-core/shasum/meta.yml delete mode 100644 modules/nf-core/shasum/tests/main.nf.test delete mode 100644 modules/nf-core/shasum/tests/main.nf.test.snap diff --git a/modules.json b/modules.json index 68a6e9b..e0b90ff 100644 --- a/modules.json +++ b/modules.json @@ -5,20 +5,10 @@ "https://github.com/nf-core/modules.git": { "modules": { "nf-core": { - "md5sum": { - "branch": "master", - "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", - "installed_by": ["modules"] - }, "multiqc": { "branch": "master", "git_sha": "98403d15b0e50edae1f3fec5eae5e24982f1fade", "installed_by": ["modules"] - }, - "shasum": { - "branch": "master", - "git_sha": "429d56ab5b5879549f71bf9905104f39d0c3bff4", - "installed_by": ["modules"] } } }, diff --git a/modules/local/comparechecksum/environment.yml b/modules/local/comparechecksum/environment.yml deleted file mode 100644 index 56563a9..0000000 --- a/modules/local/comparechecksum/environment.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json -name: "comparechecksum" -channels: - - conda-forge - - bioconda -dependencies: - - conda-forge::r-base=4.2.1 diff --git a/modules/local/comparechecksum/main.nf b/modules/local/comparechecksum/main.nf deleted file mode 100644 index 38e047b..0000000 --- a/modules/local/comparechecksum/main.nf +++ /dev/null @@ -1,37 +0,0 @@ -process COMPARECHECKSUM { - tag "$meta.id" - label 'process_single' - - conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/48/483e9d9b3b07e5658792d579e230ad40ed18daf7b9ebfb4323c08570f92fd1d5/data': - 'community.wave.seqera.io/library/r-base:4.2.1--b0b5476e2e7a0872' }" - - input: - tuple val(meta), path(input_checksum), path(generated_checksum) - - output: - tuple val(meta), path("*checksum_validation.csv"), emit: report - tuple val(meta), path("*checksum_summary.csv"), emit: summary_report - path "versions.yml" , emit: versions_comparechecksum, topic: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - prefix = task.ext.prefix ?: "${meta.id}" - template 'comparechecksum.R' - - stub: - def args = task.ext.args ?: '' - prefix = task.ext.prefix ?: "${meta.id}" - """ - touch ${prefix}.csv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - r-base: \$(Rscript -e "cat(as.character(getRversion()))") - END_VERSIONS - """ -} diff --git a/modules/local/comparechecksum/meta.yml b/modules/local/comparechecksum/meta.yml deleted file mode 100644 index 5f7b938..0000000 --- a/modules/local/comparechecksum/meta.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: "comparechecksum" -description: | - Compare expected checksums against generated checksums and produce - a per-file validation report and a summary count of MATCH/MISMATCH/MISSING/UNEXPECTED statuses. -keywords: - - checksum - - validation - - integrity - - md5 - - sha256 -tools: - - "r-base": - description: "R statistical computing language used to run the comparison logic" - homepage: "https://www.r-project.org/" - documentation: "https://cran.r-project.org/manuals.html" - licence: ["GPL-2.0-or-later"] - -input: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'sample1' ]` - - input_checksum: - type: file - description: | - File containing expected checksums (two-column, space-separated: - checksum and filename). - pattern: "*.{md5,sha256,tsv,txt}" - - generated_checksum: - type: file - description: | - File containing observed/generated checksums in the same format - as input_checksum. - pattern: "*.{md5,sha256,tsv,txt}" - -output: - - report: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'sample1' ]` - - "*.csv": - type: file - description: | - Per-file validation report. - pattern: "*checksum_validation.csv" - - summary_report: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'sample1' ]` - - "*.csv": - type: file - description: | - Per-file summary report. - pattern: "*checksum_summary.csv" - - versions_comparechecksum: - - "versions.yml": - type: file - description: File containing software versions - pattern: "versions.yml" - -authors: - - "@delfiterradas" -maintainers: - - "@delfiterradas" diff --git a/modules/local/comparechecksum/templates/comparechecksum.R b/modules/local/comparechecksum/templates/comparechecksum.R deleted file mode 100644 index 5bea92f..0000000 --- a/modules/local/comparechecksum/templates/comparechecksum.R +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env Rscript - -# Template-interpolated by Nextflow -input_checksum <- "${input_checksum}" -generated_checksum <- "${generated_checksum}" -prefix <- "${prefix}" - -read_checksum_file <- function(path) { - - x <- read.table( - path, - stringsAsFactors = FALSE, - fill = TRUE, - col.names = c("checksum", "File") - ) - - x -} - -# Read generated checksums -generated <- read_checksum_file(generated_checksum) -expected <- read_checksum_file(input_checksum) - -report <- merge( - expected, - generated, - by = "File", - all = TRUE, - suffixes = c("_expected", "_observed") -) - -report\$status <- ifelse( - is.na(report\$checksum_expected), - "Unexpected", - ifelse( - is.na(report\$checksum_observed), - "Missing", - ifelse( - report\$checksum_expected == report\$checksum_observed, - "Match", - "Mismatch" - ) - ) -) - -# Write detailed report -write.csv( - report[order(report\$File), ], - paste0(prefix, ".checksum_validation.csv"), - row.names = FALSE -) - -# Write summary report -summary_df <- as.data.frame(table(report\$status)) -colnames(summary_df) <- c("status", "count") -summary_df <- cbind(Sample = prefix, summary_df) -status_counts <- table( - factor( - report\$status, - levels = c("Match", "Mismatch", "Missing", "Unexpected") - ) -) - -summary_df <- data.frame( - Sample = prefix, - Match = unname(status_counts["Match"]), - Mismatch = unname(status_counts["Mismatch"]), - Missing = unname(status_counts["Missing"]), - Unexpected = unname(status_counts["Unexpected"]), - check.names = FALSE -) - -write.csv( - summary_df, - paste0(prefix, ".checksum_summary.csv"), - row.names = FALSE -) - -# ------------------------------------------------------------ -# Versions file -# ------------------------------------------------------------ - -versions <- c( - "\"${task.process}\":", - paste0(" r-base: ", getRversion()) -) - -writeLines( - versions, - "versions.yml" -) diff --git a/modules/nf-core/md5sum/environment.yml b/modules/nf-core/md5sum/environment.yml deleted file mode 100644 index 9b926b1..0000000 --- a/modules/nf-core/md5sum/environment.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json -channels: - - conda-forge - - bioconda -dependencies: - - conda-forge::coreutils=9.5 - - conda-forge::grep=3.11 - - conda-forge::gzip=1.13 - - conda-forge::lbzip2=2.5 - - conda-forge::sed=4.8 - - conda-forge::tar=1.34 diff --git a/modules/nf-core/md5sum/main.nf b/modules/nf-core/md5sum/main.nf deleted file mode 100644 index 7dafd75..0000000 --- a/modules/nf-core/md5sum/main.nf +++ /dev/null @@ -1,55 +0,0 @@ -process MD5SUM { - tag "${meta.id}" - label 'process_single' - - conda "${moduleDir}/environment.yml" - container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/52/52ccce28d2ab928ab862e25aae26314d69c8e38bd41ca9431c67ef05221348aa/data' - : 'community.wave.seqera.io/library/coreutils_grep_gzip_lbzip2_pruned:838ba80435a629f8'}" - - input: - tuple val(meta), path(files) - val as_separate_files - - output: - tuple val(meta), path("*.md5"), emit: checksum - tuple val("${task.process}"), val('md5sum'), eval("md5sum --version | sed '1!d; s/.* //'"), topic: versions, emit: versions_md5sum - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" - // will only use when as_separate_files = false - if (as_separate_files) { - """ - find -L * -maxdepth 0 -type f \\ - ! -name '*.md5' \\ - -exec sh -c 'md5sum ${args} "\$1" > "\$1.md5"' _ "{}" \\; - """ - } - else { - """ - find -L * -type f \\ - ! -name '*.md5' \\ - -exec md5sum ${args} "{}" + \\ - > ${prefix}.md5 - """ - } - - stub: - def prefix = task.ext.prefix ?: "${meta.id}" - if (as_separate_files) { - """ - find -L * -type f \\ - ! -name '*.md5' \\ - -exec sh -c 'touch "\$1.md5"' _ "{}" \\; - """ - } - else { - """ - touch ${prefix}.md5 - """ - } -} diff --git a/modules/nf-core/md5sum/meta.yml b/modules/nf-core/md5sum/meta.yml deleted file mode 100644 index 71066a8..0000000 --- a/modules/nf-core/md5sum/meta.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: "md5sum" -description: Create MD5 (128-bit) checksums -keywords: - - checksum - - MD5 - - 128 bit -tools: - - "md5sum": - description: Create MD5 (128-bit) checksums for each file - homepage: "https://www.gnu.org" - documentation: "https://man7.org/linux/man-pages/man1/md5sum.1.html" - licence: - - "GPL-3.0-or-later" - identifier: "" -input: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - files: - type: file - description: Any number of files. One md5sum file will be generated for - each. - pattern: "*.*" - ontologies: [] - - as_separate_files: - type: boolean - description: | - If true, each file will have its own md5sum file. If false, all files will be - checksummed into a single md5sum file. -output: - checksum: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - "*.md5": - type: file - description: File containing checksum - pattern: "*.md5" - ontologies: [] - versions_md5sum: - - - ${task.process}: - type: string - description: The name of the process - - md5sum: - type: string - description: The name of the tool - - md5sum --version | sed '1!d; s/.* //': - type: eval - description: The expression to obtain the version of the tool -topics: - versions: - - - ${task.process}: - type: string - description: The name of the process - - md5sum: - type: string - description: The name of the tool - - md5sum --version | sed '1!d; s/.* //': - type: eval - description: The expression to obtain the version of the tool -authors: - - "@matthdsm" -maintainers: - - "@matthdsm" diff --git a/modules/nf-core/md5sum/tests/main.nf.test b/modules/nf-core/md5sum/tests/main.nf.test deleted file mode 100644 index a6f7cf8..0000000 --- a/modules/nf-core/md5sum/tests/main.nf.test +++ /dev/null @@ -1,180 +0,0 @@ -nextflow_process { - - name "Test Process MD5SUM" - script "../main.nf" - process "MD5SUM" - - tag "modules" - tag "modules_nfcore" - tag "md5sum" - - test("md5sum on hello.txt") { - - when { - process { - """ - input[0] = [ - [ id: 'hello' ], - [ file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true) ] - ] - input[1] = true - """ - } - } - - then { - assertAll { - { assert process.success } - { assert snapshot(process.out).match() } - } - } - } - - test("md5sum on hello.txt (BSD-style)") { - - config './nextflow.config' - - when { - process { - """ - input[0] = [ - [ id: 'hello' ], - [ file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true) ] - ] - input[1] = true - """ - } - } - - then { - assertAll { - { assert process.success } - { assert snapshot(process.out).match() } - } - } - } - - test("md5sum on hello.txt - stub") { - options "-stub" - when { - process { - """ - input[0] = [ - [ id: 'hello' ], - [ file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true) ] - ] - input[1] = true - """ - } - } - - then { - assertAll { - { assert process.success } - { assert snapshot(process.out).match() } - } - } - } - - test("md5sum on paired fastq, combined") { - - when { - process { - """ - input[0] = [ - [ id: 'test' ], - [ - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) - ] - ] - input[1] = false - """ - } - } - - then { - assertAll { - { assert process.success } - { assert snapshot(process.out).match() } - } - } - } - - test("md5sum on paired fastq, combined - stub") { - options "-stub" - when { - process { - """ - input[0] = [ - [ id: 'test' ], - [ - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) - ] - ] - input[1] = false - """ - } - } - - then { - assertAll { - { assert process.success } - { assert snapshot(process.out).match() } - } - } - } - - - test("md5sum on paired fastq, separate") { - - when { - process { - """ - input[0] = [ - [ id: 'test' ], - [ - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) - ] - ] - input[1] = true - """ - } - } - - then { - assertAll { - { assert process.success } - { assert snapshot(process.out).match() } - } - } - } - - test("md5sum on paired fastq, separate - stub") { - options "-stub" - when { - process { - """ - input[0] = [ - [ id: 'test' ], - [ - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) - ] - ] - input[1] = true - """ - } - } - - then { - assertAll { - { assert process.success } - { assert snapshot(process.out).match() } - } - } - } - -} diff --git a/modules/nf-core/md5sum/tests/main.nf.test.snap b/modules/nf-core/md5sum/tests/main.nf.test.snap deleted file mode 100644 index bf78c29..0000000 --- a/modules/nf-core/md5sum/tests/main.nf.test.snap +++ /dev/null @@ -1,301 +0,0 @@ -{ - "md5sum on paired fastq, separate - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - [ - "test_1.fastq.gz.md5:md5,d41d8cd98f00b204e9800998ecf8427e", - "test_2.fastq.gz.md5:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ] - ], - "1": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ], - "checksum": [ - [ - { - "id": "test" - }, - [ - "test_1.fastq.gz.md5:md5,d41d8cd98f00b204e9800998ecf8427e", - "test_2.fastq.gz.md5:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ] - ], - "versions_md5sum": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-02-18T14:31:17.339668", - "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.4" - } - }, - "md5sum on paired fastq, separate": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - [ - "test_1.fastq.gz.md5:md5,63a3f187d06ae5cffe77fcd39bbdd63a", - "test_2.fastq.gz.md5:md5,055dc46636836dbd1d9ede2e6ce8cd4e" - ] - ] - ], - "1": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ], - "checksum": [ - [ - { - "id": "test" - }, - [ - "test_1.fastq.gz.md5:md5,63a3f187d06ae5cffe77fcd39bbdd63a", - "test_2.fastq.gz.md5:md5,055dc46636836dbd1d9ede2e6ce8cd4e" - ] - ] - ], - "versions_md5sum": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-02-18T14:31:11.522274", - "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.4" - } - }, - "md5sum on hello.txt - stub": { - "content": [ - { - "0": [ - [ - { - "id": "hello" - }, - "hello.txt.md5:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ], - "checksum": [ - [ - { - "id": "hello" - }, - "hello.txt.md5:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_md5sum": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-02-18T14:30:52.301881", - "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.4" - } - }, - "md5sum on hello.txt": { - "content": [ - { - "0": [ - [ - { - "id": "hello" - }, - "hello.txt.md5:md5,5c18e1db5460fb32fed66966483165fd" - ] - ], - "1": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ], - "checksum": [ - [ - { - "id": "hello" - }, - "hello.txt.md5:md5,5c18e1db5460fb32fed66966483165fd" - ] - ], - "versions_md5sum": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-02-18T14:30:41.089186", - "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.4" - } - }, - "md5sum on paired fastq, combined": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.md5:md5,dfb98e45cbb77a9a63ae7029aee38bd1" - ] - ], - "1": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ], - "checksum": [ - [ - { - "id": "test" - }, - "test.md5:md5,dfb98e45cbb77a9a63ae7029aee38bd1" - ] - ], - "versions_md5sum": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-02-18T14:30:58.611754", - "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.4" - } - }, - "md5sum on paired fastq, combined - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.md5:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ], - "checksum": [ - [ - { - "id": "test" - }, - "test.md5:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_md5sum": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-02-18T14:31:06.064053", - "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.4" - } - }, - "md5sum on hello.txt (BSD-style)": { - "content": [ - { - "0": [ - [ - { - "id": "hello" - }, - "hello.txt.md5:md5,152a03f5dc7aa8db6612f63154ecbca2" - ] - ], - "1": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ], - "checksum": [ - [ - { - "id": "hello" - }, - "hello.txt.md5:md5,152a03f5dc7aa8db6612f63154ecbca2" - ] - ], - "versions_md5sum": [ - [ - "MD5SUM", - "md5sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-02-18T14:30:46.389675", - "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.4" - } - } -} \ No newline at end of file diff --git a/modules/nf-core/md5sum/tests/nextflow.config b/modules/nf-core/md5sum/tests/nextflow.config deleted file mode 100644 index 4acada5..0000000 --- a/modules/nf-core/md5sum/tests/nextflow.config +++ /dev/null @@ -1,2 +0,0 @@ - -process.ext.args = '--tag' diff --git a/modules/nf-core/shasum/environment.yml b/modules/nf-core/shasum/environment.yml deleted file mode 100644 index 9b926b1..0000000 --- a/modules/nf-core/shasum/environment.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json -channels: - - conda-forge - - bioconda -dependencies: - - conda-forge::coreutils=9.5 - - conda-forge::grep=3.11 - - conda-forge::gzip=1.13 - - conda-forge::lbzip2=2.5 - - conda-forge::sed=4.8 - - conda-forge::tar=1.34 diff --git a/modules/nf-core/shasum/main.nf b/modules/nf-core/shasum/main.nf deleted file mode 100644 index 65dffad..0000000 --- a/modules/nf-core/shasum/main.nf +++ /dev/null @@ -1,55 +0,0 @@ -process SHASUM { - tag "${meta.id}" - label 'process_low' - - conda "${moduleDir}/environment.yml" - container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/52/52ccce28d2ab928ab862e25aae26314d69c8e38bd41ca9431c67ef05221348aa/data' - : 'community.wave.seqera.io/library/coreutils_grep_gzip_lbzip2_pruned:838ba80435a629f8'}" - - input: - tuple val(meta), path(files) - val as_separate_files - - output: - tuple val(meta), path("*.sha256"), emit: checksum - tuple val("${task.process}"), val('sha256sum'), eval("sha256sum --version 2>&1 | head -n 1 | sed 's/.* //'"), emit: versions_sha256sum, topic: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" - // will only use when as_separate_files = false - if (as_separate_files) { - """ - find -L * -maxdepth 0 -type f \\ - ! -name '*.sha256' \\ - -exec sh -c 'sha256sum ${args} "\$1" > "\$1.sha256"' _ "{}" \\; - """ - } - else { - """ - find -L * -type f \\ - ! -name '*.sha256' \\ - -exec sha256sum ${args} "{}" + \\ - > ${prefix}.sha256 - """ - } - - stub: - def prefix = task.ext.prefix ?: "${meta.id}" - if (as_separate_files) { - """ - find -L * -type f \\ - ! -name '*.sha256' \\ - -exec sh -c 'touch "\$1.sha256"' _ "{}" \\; - """ - } - else { - """ - touch ${prefix}.sha256 - """ - } -} diff --git a/modules/nf-core/shasum/meta.yml b/modules/nf-core/shasum/meta.yml deleted file mode 100644 index e4b7648..0000000 --- a/modules/nf-core/shasum/meta.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: "shasum" -description: Print SHA256 (256-bit) checksums. -keywords: - - checksum - - sha256 - - 256 bit -tools: - - "md5sum": - description: Create an SHA256 (256-bit) checksum. - homepage: "https://www.gnu.org" - documentation: "https://linux.die.net/man/1/shasum" - licence: - - "GPLv3+" - identifier: "" -input: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - files: - type: file - description: Any number of files - pattern: "*.*" - ontologies: [] - - as_separate_files: - type: boolean - description: | - If true, each file will have its own shasum file. If false, all files will be - checksummed into a single shasum file. -output: - checksum: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - "*.sha256": - type: file - description: File containing checksum - pattern: "*.sha256" - ontologies: [] - versions_sha256sum: - - - ${task.process}: - type: string - description: Process name - - sha256sum: - type: string - description: Tool name - - "sha256sum --version 2>&1 | head -n 1 | sed 's/.* //'": - type: eval - description: Software version -topics: - versions: - - - ${task.process}: - type: string - description: Process name - - sha256sum: - type: string - description: Tool name - - "sha256sum --version 2>&1 | head -n 1 | sed 's/.* //'": - type: eval - description: Software version -authors: - - "@matthdsm" -maintainers: - - "@matthdsm" diff --git a/modules/nf-core/shasum/tests/main.nf.test b/modules/nf-core/shasum/tests/main.nf.test deleted file mode 100644 index 6e2d413..0000000 --- a/modules/nf-core/shasum/tests/main.nf.test +++ /dev/null @@ -1,87 +0,0 @@ - -nextflow_process { - - name "Test Process SHASUM" - script "../main.nf" - process "SHASUM" - - tag "modules" - tag "modules_nfcore" - tag "shasum" - - test("test-shasum, separate") { - - when { - process { - """ - input[0] = [ - [ id:'test', single_end:false ], // meta map - [ - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) - ] - ] - input[1] = true - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(sanitizeOutput(process.out)).match() } - ) - } - } - - test("test-shasum, combined") { - - when { - process { - """ - input[0] = [ - [ id:'test', single_end:false ], // meta map - [ - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) - ] - ] - input[1] = false - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(sanitizeOutput(process.out)).match() } - ) - } - } - - test("test-shasum - stub") { - - options "-stub" - - when { - process { - """ - input[0] = [ - [ id:'test', single_end:false ], // meta map - file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.bam', checkIfExists: true) - ] - input[1] = true - - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(sanitizeOutput(process.out)).match() } - ) - } - } - -} diff --git a/modules/nf-core/shasum/tests/main.nf.test.snap b/modules/nf-core/shasum/tests/main.nf.test.snap deleted file mode 100644 index df3986f..0000000 --- a/modules/nf-core/shasum/tests/main.nf.test.snap +++ /dev/null @@ -1,86 +0,0 @@ -{ - "test-shasum, combined": { - "content": [ - { - "checksum": [ - [ - { - "id": "test", - "single_end": false - }, - "test.sha256:md5,cbe368d92c146935e6d72a00c2c2c804" - ] - ], - "versions_sha256sum": [ - [ - "SHASUM", - "sha256sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-06-19T13:40:52.588704139", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.4" - } - }, - "test-shasum - stub": { - "content": [ - { - "checksum": [ - [ - { - "id": "test", - "single_end": false - }, - "test.paired_end.bam.sha256:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions_sha256sum": [ - [ - "SHASUM", - "sha256sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-06-19T13:40:59.232985121", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.4" - } - }, - "test-shasum, separate": { - "content": [ - { - "checksum": [ - [ - { - "id": "test", - "single_end": false - }, - [ - "test_1.fastq.gz.sha256:md5,d200e9d01dfc874b9c5efe894181b430", - "test_2.fastq.gz.sha256:md5,0035d52e9b642206858b826f2b49d7a3" - ] - ] - ], - "versions_sha256sum": [ - [ - "SHASUM", - "sha256sum", - "9.5" - ] - ] - } - ], - "timestamp": "2026-06-19T13:40:45.551657784", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.4" - } - } -} \ No newline at end of file From 5be95847252d61e787fd75846e7f2023cd6dd035 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 15 Jul 2026 14:31:54 +0200 Subject: [PATCH 140/334] Fix linting --- conf/modules.config | 4 ---- modules/local/rclone/check/main.nf | 2 +- modules/local/rclone/checksum/main.nf | 2 +- modules/local/rclone_copy/main.nf | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index c981ac6..be5c307 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,10 +18,6 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] - withName: 'COMPARECHECKSUM' { - ext.prefix = { "${meta.id}_${meta.check_format}" } - } - withName: 'RCLONE_COPY' { ext.args = { def base_args = [ diff --git a/modules/local/rclone/check/main.nf b/modules/local/rclone/check/main.nf index 8d2cd79..56b2a67 100644 --- a/modules/local/rclone/check/main.nf +++ b/modules/local/rclone/check/main.nf @@ -53,4 +53,4 @@ process RCLONE_CHECK { ${prefix}.match.txt \\ ${prefix}.error.txt """ -} \ No newline at end of file +} diff --git a/modules/local/rclone/checksum/main.nf b/modules/local/rclone/checksum/main.nf index 4fcf838..71a21f1 100644 --- a/modules/local/rclone/checksum/main.nf +++ b/modules/local/rclone/checksum/main.nf @@ -54,4 +54,4 @@ process RCLONE_CHECKSUM { ${prefix}.match.txt \\ ${prefix}.error.txt """ -} \ No newline at end of file +} diff --git a/modules/local/rclone_copy/main.nf b/modules/local/rclone_copy/main.nf index accad23..2014e4e 100644 --- a/modules/local/rclone_copy/main.nf +++ b/modules/local/rclone_copy/main.nf @@ -52,4 +52,4 @@ process RCLONE_COPY { """ touch rclone-copy.log """ -} \ No newline at end of file +} From 6d6f22d50f3826ab7fb3d5300fd0d1eabb743c38 Mon Sep 17 00:00:00 2001 From: zxBIB Date: Thu, 16 Jul 2026 14:27:57 +0200 Subject: [PATCH 141/334] improve samplesheet parsing --- workflows/datasync.nf | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index a275f5c..d399df5 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -37,20 +37,16 @@ workflow DATASYNC { ch_samplesheet = ch_samplesheet.multiMap { meta, input_path, output_path, md5, sha -> - def source_string = input_path.toString() + def source = file(input_path) - def source_name = source_string - .replaceAll('/+$', '') - .tokenize('/') - .last() - - def is_file = source_name.contains('.') - def rclone_destination = is_file + def source_uri = source.toUriString() + + def rclone_destination = source.isFile() ? output_path.toString().replaceAll('/+$', '') - : "${output_path.toString().replaceAll('/+$', '')}/${source_name}" + : "${output_path.toString().replaceAll('/+$', '')}/${source.name}" input: [ meta, input_path ] - rclone: [ meta, source_string, rclone_destination ] + rclone: [ meta, source_uri, rclone_destination ] checksum: [ meta, md5, sha ] } From c2446776db9e8492de93c06971021d216fe404e2 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Thu, 16 Jul 2026 13:23:00 +0000 Subject: [PATCH 142/334] Install `rclone` modules from nf-core --- conf/containers_conda_lock_files_amd64.config | 4 + conf/containers_conda_lock_files_arm64.config | 4 + conf/containers_docker_amd64.config | 4 + conf/containers_docker_arm64.config | 4 + .../containers_singularity_https_amd64.config | 4 + .../containers_singularity_https_arm64.config | 4 + conf/containers_singularity_oras_amd64.config | 4 + conf/containers_singularity_oras_arm64.config | 4 + modules.json | 15 + .../linux_amd64-bd-2ef33c5b9132aa97_1.txt | 81 ++++++ .../linux_arm64-bd-351f8e39202b129a_1.txt | 75 +++++ modules/nf-core/rclone/check/environment.yml | 6 + .../{local => nf-core}/rclone/check/main.nf | 0 modules/nf-core/rclone/check/meta.yml | 156 ++++++++++ .../nf-core/rclone/check/tests/main.nf.test | 81 ++++++ .../rclone/check/tests/main.nf.test.snap | 266 ++++++++++++++++++ .../nf-core/rclone/checksum/environment.yml | 6 + .../rclone/checksum/main.nf | 0 modules/nf-core/rclone/checksum/meta.yml | 161 +++++++++++ .../rclone/checksum/tests/main.nf.test | 89 ++++++ .../rclone/checksum/tests/main.nf.test.snap | 266 ++++++++++++++++++ .../rclone/copy}/environment.yml | 0 .../rclone/copy}/main.nf | 4 +- .../rclone/copy}/meta.yml | 58 +++- .../nf-core/rclone/copy/tests/main.nf.test | 61 ++++ .../rclone/copy/tests/main.nf.test.snap | 54 ++++ .../nf-core/rclone/copy/tests/nextflow.config | 7 + workflows/datasync.nf | 23 +- 28 files changed, 1417 insertions(+), 24 deletions(-) create mode 100644 modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt create mode 100644 modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt create mode 100644 modules/nf-core/rclone/check/environment.yml rename modules/{local => nf-core}/rclone/check/main.nf (100%) create mode 100644 modules/nf-core/rclone/check/meta.yml create mode 100644 modules/nf-core/rclone/check/tests/main.nf.test create mode 100644 modules/nf-core/rclone/check/tests/main.nf.test.snap create mode 100644 modules/nf-core/rclone/checksum/environment.yml rename modules/{local => nf-core}/rclone/checksum/main.nf (100%) create mode 100644 modules/nf-core/rclone/checksum/meta.yml create mode 100644 modules/nf-core/rclone/checksum/tests/main.nf.test create mode 100644 modules/nf-core/rclone/checksum/tests/main.nf.test.snap rename modules/{local/rclone_copy => nf-core/rclone/copy}/environment.yml (100%) rename modules/{local/rclone_copy => nf-core/rclone/copy}/main.nf (94%) rename modules/{local/rclone_copy => nf-core/rclone/copy}/meta.yml (50%) create mode 100644 modules/nf-core/rclone/copy/tests/main.nf.test create mode 100644 modules/nf-core/rclone/copy/tests/main.nf.test.snap create mode 100644 modules/nf-core/rclone/copy/tests/nextflow.config diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index 01cc545..7f28595 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1 +1,5 @@ process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } +process { withName: 'RCLONE/COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } +process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } +process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index 6864e0b..e8c2fa8 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1 +1,5 @@ process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } +process { withName: 'RCLONE/COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } +process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } +process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_docker_amd64.config b/conf/containers_docker_amd64.config index ea18c3f..08e28fb 100644 --- a/conf/containers_docker_amd64.config +++ b/conf/containers_docker_amd64.config @@ -1 +1,5 @@ process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc' } } +process { withName: 'RCLONE/COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } +process { withName: 'RCLONE_CHECK' { container = 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' } } +process { withName: 'RCLONE_COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_docker_arm64.config b/conf/containers_docker_arm64.config index 369f743..66d0e33 100644 --- a/conf/containers_docker_arm64.config +++ b/conf/containers_docker_arm64.config @@ -1 +1,5 @@ process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--5c84a5000a226ab5' } } +process { withName: 'RCLONE/COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } +process { withName: 'RCLONE_CHECK' { container = 'community.wave.seqera.io/library/rclone:1.74.3--351f8e39202b129a' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'community.wave.seqera.io/library/rclone:1.74.3--351f8e39202b129a' } } +process { withName: 'RCLONE_COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_singularity_https_amd64.config b/conf/containers_singularity_https_amd64.config index 932fc7c..f842eeb 100644 --- a/conf/containers_singularity_https_amd64.config +++ b/conf/containers_singularity_https_amd64.config @@ -1 +1,5 @@ process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' } } +process { withName: 'RCLONE/COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } +process { withName: 'RCLONE_CHECK' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data' } } +process { withName: 'RCLONE_COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } diff --git a/conf/containers_singularity_https_arm64.config b/conf/containers_singularity_https_arm64.config index 4f79532..eb5dcb0 100644 --- a/conf/containers_singularity_https_arm64.config +++ b/conf/containers_singularity_https_arm64.config @@ -1 +1,5 @@ process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e4/e48aa28aebc881254a499b24c3e1ce77b8df1b85a5432699ed6f72eb17ac7fb5/data' } } +process { withName: 'RCLONE/COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } +process { withName: 'RCLONE_CHECK' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/de/de06d232599f015aa253f63b84ba2e257bb542810dc11714b88ca9b4045b80ea/data' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/de/de06d232599f015aa253f63b84ba2e257bb542810dc11714b88ca9b4045b80ea/data' } } +process { withName: 'RCLONE_COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } diff --git a/conf/containers_singularity_oras_amd64.config b/conf/containers_singularity_oras_amd64.config index 2fa065b..ce8e915 100644 --- a/conf/containers_singularity_oras_amd64.config +++ b/conf/containers_singularity_oras_amd64.config @@ -1 +1,5 @@ process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2' } } +process { withName: 'RCLONE/COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } +process { withName: 'RCLONE_CHECK' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--af6486c6ac506f82' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--af6486c6ac506f82' } } +process { withName: 'RCLONE_COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_singularity_oras_arm64.config b/conf/containers_singularity_oras_arm64.config index 84f0792..9f12eb6 100644 --- a/conf/containers_singularity_oras_arm64.config +++ b/conf/containers_singularity_oras_arm64.config @@ -1 +1,5 @@ process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c0468833d65b2f81' } } +process { withName: 'RCLONE/COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } +process { withName: 'RCLONE_CHECK' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--49a53709aa05d28d' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--49a53709aa05d28d' } } +process { withName: 'RCLONE_COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/modules.json b/modules.json index e0b90ff..36c8de3 100644 --- a/modules.json +++ b/modules.json @@ -9,6 +9,21 @@ "branch": "master", "git_sha": "98403d15b0e50edae1f3fec5eae5e24982f1fade", "installed_by": ["modules"] + }, + "rclone/check": { + "branch": "master", + "git_sha": "0983b1ef5f0729946953d921100af925f86fafb0", + "installed_by": ["modules"] + }, + "rclone/checksum": { + "branch": "master", + "git_sha": "0983b1ef5f0729946953d921100af925f86fafb0", + "installed_by": ["modules"] + }, + "rclone/copy": { + "branch": "master", + "git_sha": "969013a2a91dc8152ca537bbd4dd4feaa15c13a7", + "installed_by": ["modules"] } } }, diff --git a/modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt b/modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt new file mode 100644 index 0000000..d9222c8 --- /dev/null +++ b/modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt @@ -0,0 +1,81 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/conda-forge/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-64: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/rclone-1.74.3-h519d9b9_0.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 +md5: a9f577daf3de00bca7c3c76c0ecbd1de +depends: +- __glibc >=2.17,<3.0.a0 +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28948 +timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +sha256: 8e0a3b5e41272e5678499b5dfc4cddb673f9e935de01eb0767ce857001229f46 +md5: 57736f29cc2b0ec0b6c2952d3f101b6a +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_19 +- libgomp 15.2.0 he0feb66_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1041084 +timestamp: 1778269013026 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +sha256: 5abe4ab9d93f6c9757d654f1969ae2267d4505315c1f2f8fe705fd60af084f1b +md5: faac990cb7aedc7f3a2224f2c9b0c26c +depends: +- __glibc >=2.17,<3.0.a0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 603817 +timestamp: 1778268942614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda +sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 +md5: fc21868a1a5aacc937e7a18747acb8a5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: X11 AND BSD-3-Clause +size: 918956 +timestamp: 1777422145199 +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d +md5: f2c23a77b25efcad57d377b34bd84941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 593603 +timestamp: 1769710381284 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rclone-1.74.3-h519d9b9_0.conda +sha256: 74a49ffb12e8c974519e856e5cb19d2a3c0aa9538847fa616149a4e7576a8106 +md5: df1b9c8554e9fdb3e7610cde037b0757 +license: MIT +license_family: MIT +size: 45039813 +timestamp: 1780709814295 diff --git a/modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt b/modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt new file mode 100644 index 0000000..d8994c6 --- /dev/null +++ b/modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt @@ -0,0 +1,75 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/conda-forge/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-aarch64: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rclone-1.74.3-h8f1e559_0.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 +md5: 468fd3bb9e1f671d36c2cbc677e56f1d +depends: +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28926 +timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda +sha256: 4592b096e553f67799ae70d4b6167eeda3ec74587d68c7aecbf4e7b1df136681 +md5: f35b3f52d0a2ec4ffe3c89ba135cdb9a +depends: +- _openmp_mutex >=4.5 +constrains: +- libgomp 15.2.0 h8acb6b2_19 +- libgcc-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 622462 +timestamp: 1778268755949 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda +sha256: 2370ef0ffcbae5bede3c4bf136add4abc257245eb91f724c99bb4a43116c5a83 +md5: c5e8a379c4a2ec2aea4ba22758c001d9 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 587387 +timestamp: 1778268674393 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda +sha256: 369db85c5cd8d99dde364ce70725d76511d9c8199e5b820c740414091bf5bcca +md5: b2a43456aa56fe80c2477a5094899eff +depends: +- libgcc >=14 +license: X11 AND BSD-3-Clause +size: 960036 +timestamp: 1777422174534 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 +md5: ab7288cc39545556d1bc5e71ab2df9a9 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 636733 +timestamp: 1769712412683 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rclone-1.74.3-h8f1e559_0.conda +sha256: 6aef9a68af8b200db69a915073ba2285e01e95e363626921497074588fbd8493 +md5: d63c4d8337e3a0128716f6f515a1ed05 +license: MIT +license_family: MIT +size: 41497679 +timestamp: 1780709811705 diff --git a/modules/nf-core/rclone/check/environment.yml b/modules/nf-core/rclone/check/environment.yml new file mode 100644 index 0000000..ea96315 --- /dev/null +++ b/modules/nf-core/rclone/check/environment.yml @@ -0,0 +1,6 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge +dependencies: + - "conda-forge::rclone=1.74.3" diff --git a/modules/local/rclone/check/main.nf b/modules/nf-core/rclone/check/main.nf similarity index 100% rename from modules/local/rclone/check/main.nf rename to modules/nf-core/rclone/check/main.nf diff --git a/modules/nf-core/rclone/check/meta.yml b/modules/nf-core/rclone/check/meta.yml new file mode 100644 index 0000000..05766b3 --- /dev/null +++ b/modules/nf-core/rclone/check/meta.yml @@ -0,0 +1,156 @@ +name: "rclone_check" +description: Check that files in source and destination paths match +keywords: + - check + - checksum + - cloud + - sync +tools: + - "rclone": + description: "Rclone is a command-line program to manage files on cloud storage." + homepage: "https://rclone.org/" + documentation: "https://rclone.org/commands/rclone_check/" + tool_dev_url: "https://github.com/rclone/rclone" + licence: + - "MIT" + +input: + - - meta: + type: map + description: | + Groovy Map containing source information + e.g. [ id:'test' ] + - source: + type: file + description: File or directory containing source files to compare. + pattern: "" + ontologies: + - edam: "http://edamontology.org/data_0006" + - destination: + type: file + description: File or directory containing destination files to compare. + pattern: "" + ontologies: + - edam: "http://edamontology.org/data_0006" +output: + combined: + - - meta: + type: map + description: | + Groovy Map containing source information + e.g. [ id:'test' ] + - ${prefix}.combined.txt: + type: file + description: Combined report of matching, missing, differing, and error paths. + pattern: "*.combined.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + differ: + - - meta: + type: map + description: | + Groovy Map containing source information + e.g. [ id:'test' ] + - ${prefix}.differ.txt: + type: file + description: Report of paths present in both source and destination but different. + pattern: "*.differ.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + missing_on_dst: + - - meta: + type: map + description: | + Groovy Map containing source information + e.g. [ id:'test' ] + - ${prefix}.missing_on_dst.txt: + type: file + description: Report of paths present in source but missing from destination. + pattern: "*.missing_on_dst.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + missing_on_src: + - - meta: + type: map + description: | + Groovy Map containing source information + e.g. [ id:'test' ] + - ${prefix}.missing_on_src.txt: + type: file + description: Report of paths present in destination but missing from source. + pattern: "*.missing_on_src.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + match: + - - meta: + type: map + description: | + Groovy Map containing source information + e.g. [ id:'test' ] + - ${prefix}.match.txt: + type: file + description: Report of matching paths. + pattern: "*.match.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + error: + - - meta: + type: map + description: | + Groovy Map containing source information + e.g. [ id:'test' ] + - ${prefix}.error.txt: + type: file + description: Report of paths with read or hash errors. + pattern: "*.error.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + versions_rclone: + - - ${task.process}: + type: string + description: The name of the process + - rclone: + type: string + description: The name of the tool + - rclone --version | sed -n '1s/^rclone v//p': + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - rclone: + type: string + description: The name of the tool + - rclone --version | sed -n '1s/^rclone v//p': + type: eval + description: The expression to obtain the version of the tool +authors: + - "@atrigila" +maintainers: + - "@atrigila" +containers: + docker: + linux/arm64: + name: community.wave.seqera.io/library/rclone:1.74.3--351f8e39202b129a + build_id: bd-351f8e39202b129a_1 + scan_id: sc-0e6358c70409ff39_1 + linux/amd64: + name: community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97 + build_id: bd-2ef33c5b9132aa97_1 + scan_id: sc-2cbce8a89ac463aa_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/rclone:1.74.3--af6486c6ac506f82 + build_id: bd-af6486c6ac506f82_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data + linux/arm64: + name: oras://community.wave.seqera.io/library/rclone:1.74.3--49a53709aa05d28d + build_id: bd-49a53709aa05d28d_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/de/de06d232599f015aa253f63b84ba2e257bb542810dc11714b88ca9b4045b80ea/data + conda: + linux/amd64: + lock_file: modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt + linux/arm64: + lock_file: modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt diff --git a/modules/nf-core/rclone/check/tests/main.nf.test b/modules/nf-core/rclone/check/tests/main.nf.test new file mode 100644 index 0000000..093265e --- /dev/null +++ b/modules/nf-core/rclone/check/tests/main.nf.test @@ -0,0 +1,81 @@ +nextflow_process { + + name "Test Process RCLONE_CHECK" + script "../main.nf" + process "RCLONE_CHECK" + + tag "modules" + tag "modules_nfcore" + tag "rclone" + tag "rclone/check" + + test("sarscov2 - fastq") { + when { + process { + """ + input[0] = [[id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "missing_on_dst", "missing_on_src", "error"])).match() } + ) + } + } + + test("sarscov2 - fastq - stub") { + options "-stub" + + when { + process { + """ + input[0] = [[id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "match", "differ", "missing_on_dst", "missing_on_src", "error"])).match() } + ) + } + } + + test("different files - fails") { + when { + process { + """ + input[0] = [[id:'test'], file(params.modules_testdata_base_path + 'delete_me/aracne3/README.md', checkIfExists: true), file(params.modules_testdata_base_path + 'delete_me/binette_checkm2/README.md', checkIfExists: true)] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "match", "missing_on_dst", "missing_on_src", "error"])).match() } + ) + } + } + + test("destination subset - partial match and missing") { + when { + process { + """ + input[0] = [[id:'test'], [file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "missing_on_src", "error"])).match() } + ) + } + } +} diff --git a/modules/nf-core/rclone/check/tests/main.nf.test.snap b/modules/nf-core/rclone/check/tests/main.nf.test.snap new file mode 100644 index 0000000..5d14e75 --- /dev/null +++ b/modules/nf-core/rclone/check/tests/main.nf.test.snap @@ -0,0 +1,266 @@ +{ + "sarscov2 - fastq - stub": { + "content": [ + { + "combined": [ + [ + { + "id": "test" + }, + "test.combined.txt" + ] + ], + "differ": [ + [ + { + "id": "test" + }, + "test.differ.txt" + ] + ], + "error": [ + [ + { + "id": "test" + }, + "test.error.txt" + ] + ], + "match": [ + [ + { + "id": "test" + }, + "test.match.txt" + ] + ], + "missing_on_dst": [ + [ + { + "id": "test" + }, + "test.missing_on_dst.txt" + ] + ], + "missing_on_src": [ + [ + { + "id": "test" + }, + "test.missing_on_src.txt" + ] + ], + "versions_rclone": [ + [ + "RCLONE_CHECK", + "rclone", + "1.74.3-DEV" + ] + ] + } + ], + "timestamp": "2026-07-10T21:39:36.202209966", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + }, + "different files - fails": { + "content": [ + { + "combined": [ + [ + { + "id": "test" + }, + "test.combined.txt" + ] + ], + "differ": [ + [ + { + "id": "test" + }, + "test.differ.txt:md5,ac036608c5c402f92926505d0f0ab0e4" + ] + ], + "error": [ + [ + { + "id": "test" + }, + "test.error.txt" + ] + ], + "match": [ + [ + { + "id": "test" + }, + "test.match.txt" + ] + ], + "missing_on_dst": [ + [ + { + "id": "test" + }, + "test.missing_on_dst.txt" + ] + ], + "missing_on_src": [ + [ + { + "id": "test" + }, + "test.missing_on_src.txt" + ] + ], + "versions_rclone": [ + [ + "RCLONE_CHECK", + "rclone", + "1.74.3-DEV" + ] + ] + } + ], + "timestamp": "2026-07-10T21:39:43.336064968", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + }, + "sarscov2 - fastq": { + "content": [ + { + "combined": [ + [ + { + "id": "test" + }, + "test.combined.txt" + ] + ], + "differ": [ + [ + { + "id": "test" + }, + "test.differ.txt" + ] + ], + "error": [ + [ + { + "id": "test" + }, + "test.error.txt" + ] + ], + "match": [ + [ + { + "id": "test" + }, + "test.match.txt:md5,6f2d815bc8fe93026183cc59946ffc46" + ] + ], + "missing_on_dst": [ + [ + { + "id": "test" + }, + "test.missing_on_dst.txt" + ] + ], + "missing_on_src": [ + [ + { + "id": "test" + }, + "test.missing_on_src.txt" + ] + ], + "versions_rclone": [ + [ + "RCLONE_CHECK", + "rclone", + "1.74.3-DEV" + ] + ] + } + ], + "timestamp": "2026-07-10T21:39:29.273416483", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + }, + "destination subset - partial match and missing": { + "content": [ + { + "combined": [ + [ + { + "id": "test" + }, + "test.combined.txt" + ] + ], + "differ": [ + [ + { + "id": "test" + }, + "test.differ.txt" + ] + ], + "error": [ + [ + { + "id": "test" + }, + "test.error.txt" + ] + ], + "match": [ + [ + { + "id": "test" + }, + "test.match.txt:md5,6f2d815bc8fe93026183cc59946ffc46" + ] + ], + "missing_on_dst": [ + [ + { + "id": "test" + }, + "test.missing_on_dst.txt:md5,827cbdd053152d88295a331ab8bae87c" + ] + ], + "missing_on_src": [ + [ + { + "id": "test" + }, + "test.missing_on_src.txt" + ] + ], + "versions_rclone": [ + [ + "RCLONE_CHECK", + "rclone", + "1.74.3-DEV" + ] + ] + } + ], + "timestamp": "2026-07-13T17:42:54.497150157", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/rclone/checksum/environment.yml b/modules/nf-core/rclone/checksum/environment.yml new file mode 100644 index 0000000..ea96315 --- /dev/null +++ b/modules/nf-core/rclone/checksum/environment.yml @@ -0,0 +1,6 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge +dependencies: + - "conda-forge::rclone=1.74.3" diff --git a/modules/local/rclone/checksum/main.nf b/modules/nf-core/rclone/checksum/main.nf similarity index 100% rename from modules/local/rclone/checksum/main.nf rename to modules/nf-core/rclone/checksum/main.nf diff --git a/modules/nf-core/rclone/checksum/meta.yml b/modules/nf-core/rclone/checksum/meta.yml new file mode 100644 index 0000000..8239375 --- /dev/null +++ b/modules/nf-core/rclone/checksum/meta.yml @@ -0,0 +1,161 @@ +name: "rclone_checksum" +description: Check files in a destination path against a checksum SUM file +keywords: + - checksum + - md5 + - sha1 + - cloud + - sync +tools: + - "rclone": + description: "Rclone is a command-line program to manage files on cloud storage." + homepage: "https://rclone.org/" + documentation: "https://rclone.org/commands/rclone_checksum/" + tool_dev_url: "https://github.com/rclone/rclone" + licence: + - "MIT" + identifier: "" + +input: + - - meta: + type: map + description: | + Groovy Map containing checksum source information + e.g. [ id:'test' ] + - sumfile: + type: file + description: Checksum SUM file containing hashes and destination paths to verify. + pattern: "*.{md5,sha1,sha256,sum,txt}" + ontologies: + - edam: "http://edamontology.org/data_3671" + - hash: + type: string + description: Hash type to check, for example MD5, SHA1, or SHA256. + - destination: + type: file + description: File or directory containing destination files to check against the SUM file. + pattern: "" + ontologies: + - edam: "http://edamontology.org/data_0006" +output: + combined: + - - meta: + type: map + description: | + Groovy Map containing checksum source information + e.g. [ id:'test' ] + - ${prefix}.combined.txt: + type: file + description: Combined report of matching, missing, differing, and error paths. + pattern: "*.combined.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + differ: + - - meta: + type: map + description: | + Groovy Map containing checksum source information + e.g. [ id:'test' ] + - ${prefix}.differ.txt: + type: file + description: Report of paths present in both source SUM file and destination but different. + pattern: "*.differ.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + missing_on_dst: + - - meta: + type: map + description: | + Groovy Map containing checksum source information + e.g. [ id:'test' ] + - ${prefix}.missing_on_dst.txt: + type: file + description: Report of paths present in the SUM file but missing from the destination. + pattern: "*.missing_on_dst.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + missing_on_src: + - - meta: + type: map + description: | + Groovy Map containing checksum source information + e.g. [ id:'test' ] + - ${prefix}.missing_on_src.txt: + type: file + description: Report of paths present in the destination but missing from the SUM file. + pattern: "*.missing_on_src.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + match: + - - meta: + type: map + description: | + Groovy Map containing checksum source information + e.g. [ id:'test' ] + - ${prefix}.match.txt: + type: file + description: Report of matching paths. + pattern: "*.match.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + error: + - - meta: + type: map + description: | + Groovy Map containing checksum source information + e.g. [ id:'test' ] + - ${prefix}.error.txt: + type: file + description: Report of paths with read or hash errors. + pattern: "*.error.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" + versions_rclone: + - - ${task.process}: + type: string + description: The name of the process + - rclone: + type: string + description: The name of the tool + - rclone --version | sed -n '1s/^rclone v//p': + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - rclone: + type: string + description: The name of the tool + - rclone --version | sed -n '1s/^rclone v//p': + type: eval + description: The expression to obtain the version of the tool +authors: + - "@atrigila" +maintainers: + - "@atrigila" +containers: + docker: + linux/arm64: + name: community.wave.seqera.io/library/rclone:1.74.3--351f8e39202b129a + build_id: bd-351f8e39202b129a_1 + scan_id: sc-0e6358c70409ff39_1 + linux/amd64: + name: community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97 + build_id: bd-2ef33c5b9132aa97_1 + scan_id: sc-2cbce8a89ac463aa_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/rclone:1.74.3--af6486c6ac506f82 + build_id: bd-af6486c6ac506f82_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data + linux/arm64: + name: oras://community.wave.seqera.io/library/rclone:1.74.3--49a53709aa05d28d + build_id: bd-49a53709aa05d28d_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/de/de06d232599f015aa253f63b84ba2e257bb542810dc11714b88ca9b4045b80ea/data + conda: + linux/amd64: + lock_file: modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt + linux/arm64: + lock_file: modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt diff --git a/modules/nf-core/rclone/checksum/tests/main.nf.test b/modules/nf-core/rclone/checksum/tests/main.nf.test new file mode 100644 index 0000000..2d833de --- /dev/null +++ b/modules/nf-core/rclone/checksum/tests/main.nf.test @@ -0,0 +1,89 @@ +nextflow_process { + + name "Test Process RCLONE_CHECKSUM" + script "../main.nf" + process "RCLONE_CHECKSUM" + + tag "modules" + tag "modules_nfcore" + tag "rclone" + tag "rclone/checksum" + + test("hello - md5") { + when { + process { + """ + file('hello.md5').text = 'e59ff97941044f85df5297e1c302d260 hello.txt\\n' + + input[0] = [[id:'test'], file('hello.md5'), 'MD5', file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "missing_on_dst", "missing_on_src", "error"]) ).match() } + ) + } + } + + test("hello - md5 - stub") { + options "-stub" + + when { + process { + """ + file('hello.md5').text = 'e59ff97941044f85df5297e1c302d260 hello.txt\\n' + + input[0] = [[id:'test'], file('hello.md5'), 'MD5', file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["match", "combined", "differ", "missing_on_dst", "missing_on_src", "error"]) ).match() } + ) + } + } + + test("hello - differs") { + when { + process { + """ + file('hello_bad.md5').text = '00000000000000000000000000000000 hello.txt\\n' + + input[0] = [[id:'test'], file('hello_bad.md5'), 'MD5', file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "match", "missing_on_dst", "missing_on_src", "error"]) ).match() } + ) + } + } + + test("missing destination") { + when { + process { + """ + file('missing.md5').text = 'e59ff97941044f85df5297e1c302d260 missing.txt\\n' + + input[0] = [[id:'test'], file('missing.md5'), 'MD5', file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "match", "missing_on_src", "error"])).match() } + ) + } + } +} diff --git a/modules/nf-core/rclone/checksum/tests/main.nf.test.snap b/modules/nf-core/rclone/checksum/tests/main.nf.test.snap new file mode 100644 index 0000000..57ba70b --- /dev/null +++ b/modules/nf-core/rclone/checksum/tests/main.nf.test.snap @@ -0,0 +1,266 @@ +{ + "missing destination": { + "content": [ + { + "combined": [ + [ + { + "id": "test" + }, + "test.combined.txt" + ] + ], + "differ": [ + [ + { + "id": "test" + }, + "test.differ.txt" + ] + ], + "error": [ + [ + { + "id": "test" + }, + "test.error.txt" + ] + ], + "match": [ + [ + { + "id": "test" + }, + "test.match.txt" + ] + ], + "missing_on_dst": [ + [ + { + "id": "test" + }, + "test.missing_on_dst.txt:md5,9ddf8bbca47985a064c1d7163d0235da" + ] + ], + "missing_on_src": [ + [ + { + "id": "test" + }, + "test.missing_on_src.txt" + ] + ], + "versions_rclone": [ + [ + "RCLONE_CHECKSUM", + "rclone", + "1.74.3-DEV" + ] + ] + } + ], + "timestamp": "2026-07-10T21:34:34.881758203", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + }, + "hello - md5 - stub": { + "content": [ + { + "combined": [ + [ + { + "id": "test" + }, + "test.combined.txt" + ] + ], + "differ": [ + [ + { + "id": "test" + }, + "test.differ.txt" + ] + ], + "error": [ + [ + { + "id": "test" + }, + "test.error.txt" + ] + ], + "match": [ + [ + { + "id": "test" + }, + "test.match.txt" + ] + ], + "missing_on_dst": [ + [ + { + "id": "test" + }, + "test.missing_on_dst.txt" + ] + ], + "missing_on_src": [ + [ + { + "id": "test" + }, + "test.missing_on_src.txt" + ] + ], + "versions_rclone": [ + [ + "RCLONE_CHECKSUM", + "rclone", + "1.74.3-DEV" + ] + ] + } + ], + "timestamp": "2026-07-10T21:34:20.471038214", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + }, + "hello - md5": { + "content": [ + { + "combined": [ + [ + { + "id": "test" + }, + "test.combined.txt" + ] + ], + "differ": [ + [ + { + "id": "test" + }, + "test.differ.txt" + ] + ], + "error": [ + [ + { + "id": "test" + }, + "test.error.txt" + ] + ], + "match": [ + [ + { + "id": "test" + }, + "test.match.txt:md5,a438474115db37daf9d8e1307c06eb4a" + ] + ], + "missing_on_dst": [ + [ + { + "id": "test" + }, + "test.missing_on_dst.txt" + ] + ], + "missing_on_src": [ + [ + { + "id": "test" + }, + "test.missing_on_src.txt" + ] + ], + "versions_rclone": [ + [ + "RCLONE_CHECKSUM", + "rclone", + "1.74.3-DEV" + ] + ] + } + ], + "timestamp": "2026-07-10T21:34:13.264088794", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + }, + "hello - differs": { + "content": [ + { + "combined": [ + [ + { + "id": "test" + }, + "test.combined.txt" + ] + ], + "differ": [ + [ + { + "id": "test" + }, + "test.differ.txt:md5,a438474115db37daf9d8e1307c06eb4a" + ] + ], + "error": [ + [ + { + "id": "test" + }, + "test.error.txt" + ] + ], + "match": [ + [ + { + "id": "test" + }, + "test.match.txt" + ] + ], + "missing_on_dst": [ + [ + { + "id": "test" + }, + "test.missing_on_dst.txt" + ] + ], + "missing_on_src": [ + [ + { + "id": "test" + }, + "test.missing_on_src.txt" + ] + ], + "versions_rclone": [ + [ + "RCLONE_CHECKSUM", + "rclone", + "1.74.3-DEV" + ] + ] + } + ], + "timestamp": "2026-07-10T21:34:27.556428476", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file diff --git a/modules/local/rclone_copy/environment.yml b/modules/nf-core/rclone/copy/environment.yml similarity index 100% rename from modules/local/rclone_copy/environment.yml rename to modules/nf-core/rclone/copy/environment.yml diff --git a/modules/local/rclone_copy/main.nf b/modules/nf-core/rclone/copy/main.nf similarity index 94% rename from modules/local/rclone_copy/main.nf rename to modules/nf-core/rclone/copy/main.nf index 2014e4e..2c97b43 100644 --- a/modules/local/rclone_copy/main.nf +++ b/modules/nf-core/rclone/copy/main.nf @@ -12,7 +12,7 @@ process RCLONE_COPY { path rclone_config output: - tuple val(meta), path("rclone-copy.log"), emit: log + tuple val(meta), path("*rclone-copy.log"), emit: log tuple val("${task.process}"), val('rclone'), eval("rclone --version | sed -n '1s/^rclone v//p'"), topic: versions, emit: versions_rclone when: @@ -41,7 +41,7 @@ process RCLONE_COPY { rclone ${configArg} copy \\ ${http_url_arg} \\ ${args} \\ - --log-file rclone-copy.log \\ + --log-file "${meta.id}-rclone-copy.log" \\ --transfers ${transfers} \\ --checkers ${checkers} \\ "${rclone_source}" \\ diff --git a/modules/local/rclone_copy/meta.yml b/modules/nf-core/rclone/copy/meta.yml similarity index 50% rename from modules/local/rclone_copy/meta.yml rename to modules/nf-core/rclone/copy/meta.yml index f3ad059..93ed4f9 100644 --- a/modules/local/rclone_copy/meta.yml +++ b/modules/nf-core/rclone/copy/meta.yml @@ -42,7 +42,8 @@ input: Rclone configuration file defining the remotes used by source_path and/or destination_path. Authentication and remote-specific options should be configured in this file where possible. - + pattern: "*.conf" + ontologies: [] output: log: - - meta: @@ -50,16 +51,59 @@ output: description: | Groovy Map containing sample information. e.g. [ id:'test', single_end:false ] - - "rclone-copy.log": + - "*rclone-copy.log": type: file description: Rclone log file generated during the copy operation. - versions: + pattern: "*rclone-copy.log" + ontologies: [] + versions_rclone: - - ${task.process}: type: string - description: The name of the process. + description: The name of the process - rclone: type: string - description: The name of the tool. - - version: + description: The name of the tool + - rclone --version | sed -n '1s/^rclone v//p': + type: eval + description: The expression to obtain the version of the tool + +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - rclone: type: string - description: The version of Rclone used. + description: The name of the tool + - rclone --version | sed -n '1s/^rclone v//p': + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@antoniasaracco" +maintainers: + - "@antoniasaracco" +containers: + docker: + linux/amd64: + name: community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be + build_id: bd-ff88b2e0040147be_1 + scan_id: sc-ff88b2e0040147be_1 + linux/arm64: + name: community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be + build_id: bd-ff88b2e0040147be_1 + scan_id: sc-ff88b2e0040147be_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be + build_id: bd-ff88b2e0040147be_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data + linux/arm64: + name: oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be + build_id: bd-ff88b2e0040147be_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data + conda: + linux/amd64: + lock_file: modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt + linux/arm64: + lock_file: modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt diff --git a/modules/nf-core/rclone/copy/tests/main.nf.test b/modules/nf-core/rclone/copy/tests/main.nf.test new file mode 100644 index 0000000..14d79cb --- /dev/null +++ b/modules/nf-core/rclone/copy/tests/main.nf.test @@ -0,0 +1,61 @@ +nextflow_process { + + name "Test RCLONE_COPY" + script "../main.nf" + process "RCLONE_COPY" + + tag "modules" + tag "modules_nfcore" + tag "rclone" + tag "rclone/copy" + + test("homo_sapiens - gvcf - copy from https - dry-run") { + + config "./nextflow.config" + + when { + process { + """ + input[0] = [ + [ id:'test' ], + params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf.gz', + '/tmp/test.genome.vcf.gz' + ] + input[1] = [] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["log"])).match() } + ) + } + } + + test("homo_sapiens - gvcf - copy from https - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], + params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf.gz', + '/tmp/test.genome.vcf.gz' + ] + input[1] = [] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot(sanitizeOutput(process.out)).match() } + ) + } + } +} diff --git a/modules/nf-core/rclone/copy/tests/main.nf.test.snap b/modules/nf-core/rclone/copy/tests/main.nf.test.snap new file mode 100644 index 0000000..eeaef63 --- /dev/null +++ b/modules/nf-core/rclone/copy/tests/main.nf.test.snap @@ -0,0 +1,54 @@ +{ + "homo_sapiens - gvcf - copy from https - stub": { + "content": [ + { + "log": [ + [ + { + "id": "test" + }, + "rclone-copy.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_rclone": [ + [ + "RCLONE_COPY", + "rclone", + "1.65.0-DEV" + ] + ] + } + ], + "timestamp": "2026-07-13T23:23:37.720920849", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.4" + } + }, + "homo_sapiens - gvcf - copy from https - dry-run": { + "content": [ + { + "log": [ + [ + { + "id": "test" + }, + "test-rclone-copy.log" + ] + ], + "versions_rclone": [ + [ + "RCLONE_COPY", + "rclone", + "1.65.0-DEV" + ] + ] + } + ], + "timestamp": "2026-07-15T14:53:00.158291805", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/rclone/copy/tests/nextflow.config b/modules/nf-core/rclone/copy/tests/nextflow.config new file mode 100644 index 0000000..0e911db --- /dev/null +++ b/modules/nf-core/rclone/copy/tests/nextflow.config @@ -0,0 +1,7 @@ +process { + withName: 'RCLONE_COPY' { + ext.args = { + "--dry-run --no-check-certificate" + } + } +} diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 4c3eb8b..eb89728 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -4,9 +4,9 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ include { MULTIQC } from '../modules/nf-core/multiqc/main' -include { RCLONE_COPY } from '../modules/local/rclone_copy/main' -include { RCLONE_CHECK } from '../modules/local/rclone/check/main' -include { RCLONE_CHECKSUM } from '../modules/local/rclone/checksum/main' +include { RCLONE_COPY } from '../modules/nf-core/rclone/copy/main' +include { RCLONE_CHECK } from '../modules/nf-core/rclone/check/main' +include { RCLONE_CHECKSUM } from '../modules/nf-core/rclone/checksum/main' include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' @@ -36,19 +36,12 @@ workflow DATASYNC { ch_samplesheet = ch_samplesheet.multiMap { meta, input_path, output_path, md5, sha -> - def source_string = input_path.toString() - - def source_name = source_string - .replaceAll('/+$', '') - .tokenize('/') - .last() - - def is_file = source_name.contains('.') - def rclone_destination = is_file + def source = file(input_path) + + def rclone_destination = source.isFile() ? output_path.toString().replaceAll('/+$', '') - : "${output_path.toString().replaceAll('/+$', '')}/${source_name}" - - def rclone_check = "${output_path.toString().replaceAll('/+$', '')}/${source_name}" + : "${output_path.toString().replaceAll('/+$', '')}/${source.name}" + def rclone_check = "${output_path.toString().replaceAll('/+$', '')}/${source.name}" input: [ meta, input_path ] rclone: [ meta, input_path, rclone_destination ] From 6b2e34b3f4928845551276263516dfb026438669 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 16 Jul 2026 16:36:45 +0200 Subject: [PATCH 143/334] Revert changes made to conf containers --- conf/containers_conda_lock_files_amd64.config | 4 ---- conf/containers_conda_lock_files_arm64.config | 4 ---- conf/containers_docker_amd64.config | 4 ---- conf/containers_docker_arm64.config | 4 ---- conf/containers_singularity_https_amd64.config | 4 ---- conf/containers_singularity_https_arm64.config | 4 ---- conf/containers_singularity_oras_amd64.config | 4 ---- conf/containers_singularity_oras_arm64.config | 4 ---- 8 files changed, 32 deletions(-) diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index 7f28595..01cc545 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1,5 +1 @@ process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } -process { withName: 'RCLONE/COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } -process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } -process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index e8c2fa8..6864e0b 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1,5 +1 @@ process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } -process { withName: 'RCLONE/COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } -process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } -process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_docker_amd64.config b/conf/containers_docker_amd64.config index 08e28fb..ea18c3f 100644 --- a/conf/containers_docker_amd64.config +++ b/conf/containers_docker_amd64.config @@ -1,5 +1 @@ process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc' } } -process { withName: 'RCLONE/COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } -process { withName: 'RCLONE_CHECK' { container = 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' } } -process { withName: 'RCLONE_COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_docker_arm64.config b/conf/containers_docker_arm64.config index 66d0e33..369f743 100644 --- a/conf/containers_docker_arm64.config +++ b/conf/containers_docker_arm64.config @@ -1,5 +1 @@ process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--5c84a5000a226ab5' } } -process { withName: 'RCLONE/COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } -process { withName: 'RCLONE_CHECK' { container = 'community.wave.seqera.io/library/rclone:1.74.3--351f8e39202b129a' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'community.wave.seqera.io/library/rclone:1.74.3--351f8e39202b129a' } } -process { withName: 'RCLONE_COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_singularity_https_amd64.config b/conf/containers_singularity_https_amd64.config index f842eeb..932fc7c 100644 --- a/conf/containers_singularity_https_amd64.config +++ b/conf/containers_singularity_https_amd64.config @@ -1,5 +1 @@ process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' } } -process { withName: 'RCLONE/COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } -process { withName: 'RCLONE_CHECK' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data' } } -process { withName: 'RCLONE_COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } diff --git a/conf/containers_singularity_https_arm64.config b/conf/containers_singularity_https_arm64.config index eb5dcb0..4f79532 100644 --- a/conf/containers_singularity_https_arm64.config +++ b/conf/containers_singularity_https_arm64.config @@ -1,5 +1 @@ process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e4/e48aa28aebc881254a499b24c3e1ce77b8df1b85a5432699ed6f72eb17ac7fb5/data' } } -process { withName: 'RCLONE/COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } -process { withName: 'RCLONE_CHECK' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/de/de06d232599f015aa253f63b84ba2e257bb542810dc11714b88ca9b4045b80ea/data' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/de/de06d232599f015aa253f63b84ba2e257bb542810dc11714b88ca9b4045b80ea/data' } } -process { withName: 'RCLONE_COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } diff --git a/conf/containers_singularity_oras_amd64.config b/conf/containers_singularity_oras_amd64.config index ce8e915..2fa065b 100644 --- a/conf/containers_singularity_oras_amd64.config +++ b/conf/containers_singularity_oras_amd64.config @@ -1,5 +1 @@ process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2' } } -process { withName: 'RCLONE/COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } -process { withName: 'RCLONE_CHECK' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--af6486c6ac506f82' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--af6486c6ac506f82' } } -process { withName: 'RCLONE_COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_singularity_oras_arm64.config b/conf/containers_singularity_oras_arm64.config index 9f12eb6..84f0792 100644 --- a/conf/containers_singularity_oras_arm64.config +++ b/conf/containers_singularity_oras_arm64.config @@ -1,5 +1 @@ process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c0468833d65b2f81' } } -process { withName: 'RCLONE/COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } -process { withName: 'RCLONE_CHECK' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--49a53709aa05d28d' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--49a53709aa05d28d' } } -process { withName: 'RCLONE_COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } From 1e0b28daca1c50ab2cf0498eda7d6652caacd5c7 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 16 Jul 2026 16:37:37 +0200 Subject: [PATCH 144/334] Remove whitespace --- workflows/datasync.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index eb89728..b0b53e4 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -37,7 +37,7 @@ workflow DATASYNC { meta, input_path, output_path, md5, sha -> def source = file(input_path) - + def rclone_destination = source.isFile() ? output_path.toString().replaceAll('/+$', '') : "${output_path.toString().replaceAll('/+$', '')}/${source.name}" From e9456f29f5353dc5af31e2b986a7b2bcff02a642 Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Thu, 16 Jul 2026 14:53:57 +0000 Subject: [PATCH 145/334] update snapshots --- tests/default.nf.test.snap | 10 ++++++---- tests/main_full.nf.test.snap | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index aaa0996..913b9c6 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -46,7 +46,9 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", - "rclone/rclone-copy.log", + "rclone/Illumina_annotation-rclone-copy.log", + "rclone/benchmark_bed-rclone-copy.log", + "rclone/test_fastq-rclone-copy.log", "shasum", "shasum/Illumina_annotation.sha256", "shasum/benchmark_bed.sha256", @@ -62,13 +64,13 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_md5_checksum_report.txt:md5,39147d72a414c399614f139354e36a86", "multiqc_md5_checksum_summary.txt:md5,d8c3b87b26251d4d6cb1aca315f0f531", - "multiqc_samplesheet.txt:md5,3cc1e0340101fe132e7ce466187f3c4b" + "multiqc_samplesheet.txt:md5,608c07d7a768f3d66b44f8daddcec95e" ] ], - "timestamp": "2026-07-07T15:28:47.101399362", + "timestamp": "2026-07-16T14:51:23.39330236", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index a5a2652..08450ae 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -44,7 +44,7 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", - "rclone/rclone-copy.log", + "rclone/demultiplex-rclone-copy.log", "shasum", "shasum/demultiplex.sha256" ], @@ -56,15 +56,15 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_md5_checksum_report.txt:md5,8d84f5711d802cd908cf5780f1fd029e", "multiqc_md5_checksum_summary.txt:md5,14a9c197093f8cd187833a11e13a3c58", - "multiqc_samplesheet.txt:md5,95d11730dbbf9fee3ca00f2792330c63", + "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca", "multiqc_sha_checksum_report.txt:md5,52c4bffaf0a94c59d4c2111fc62c074d", "multiqc_sha_checksum_summary.txt:md5,78a00f0c20054c0f1853ceac0fcc0172" ] ], - "timestamp": "2026-07-07T15:30:52.986332849", + "timestamp": "2026-07-16T14:42:21.246036308", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "25.10.4" } } } \ No newline at end of file From 9ad475ca1018f7ed975f48c8b40cf3706844562e Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Thu, 16 Jul 2026 15:04:30 +0000 Subject: [PATCH 146/334] update rclone copy --- modules.json | 2 +- modules/nf-core/rclone/copy/meta.yml | 4 ++-- modules/nf-core/rclone/copy/tests/main.nf.test.snap | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules.json b/modules.json index ea936d1..3a55d6b 100644 --- a/modules.json +++ b/modules.json @@ -17,7 +17,7 @@ }, "rclone/copy": { "branch": "master", - "git_sha": "6bb93c2adec5f390eb1976a59b7fe4a4b0cbb2a5", + "git_sha": "969013a2a91dc8152ca537bbd4dd4feaa15c13a7", "installed_by": ["modules"] }, "shasum": { diff --git a/modules/nf-core/rclone/copy/meta.yml b/modules/nf-core/rclone/copy/meta.yml index 4a9072f..93ed4f9 100644 --- a/modules/nf-core/rclone/copy/meta.yml +++ b/modules/nf-core/rclone/copy/meta.yml @@ -51,10 +51,10 @@ output: description: | Groovy Map containing sample information. e.g. [ id:'test', single_end:false ] - - rclone-copy.log: + - "*rclone-copy.log": type: file description: Rclone log file generated during the copy operation. - pattern: "rclone-copy.log" + pattern: "*rclone-copy.log" ontologies: [] versions_rclone: - - ${task.process}: diff --git a/modules/nf-core/rclone/copy/tests/main.nf.test.snap b/modules/nf-core/rclone/copy/tests/main.nf.test.snap index 60d464e..eeaef63 100644 --- a/modules/nf-core/rclone/copy/tests/main.nf.test.snap +++ b/modules/nf-core/rclone/copy/tests/main.nf.test.snap @@ -33,7 +33,7 @@ { "id": "test" }, - "rclone-copy.log" + "test-rclone-copy.log" ] ], "versions_rclone": [ @@ -45,10 +45,10 @@ ] } ], - "timestamp": "2026-07-13T23:23:31.914171479", + "timestamp": "2026-07-15T14:53:00.158291805", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.4" + "nextflow": "25.10.4" } } } \ No newline at end of file From f3a4727ab679f286a0cc7dece826b7bd237e02ae Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Thu, 16 Jul 2026 16:01:00 +0000 Subject: [PATCH 147/334] update containers files --- conf/containers_conda_lock_files_amd64.config | 1 + conf/containers_conda_lock_files_arm64.config | 1 + conf/containers_docker_amd64.config | 1 + conf/containers_docker_arm64.config | 1 + conf/containers_singularity_https_amd64.config | 1 + conf/containers_singularity_https_arm64.config | 1 + conf/containers_singularity_oras_amd64.config | 1 + conf/containers_singularity_oras_arm64.config | 1 + 8 files changed, 8 insertions(+) diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index 01cc545..ac3187b 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1 +1,2 @@ process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } +process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index 6864e0b..7d32c6c 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1 +1,2 @@ process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } +process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_docker_amd64.config b/conf/containers_docker_amd64.config index ea18c3f..53163be 100644 --- a/conf/containers_docker_amd64.config +++ b/conf/containers_docker_amd64.config @@ -1 +1,2 @@ process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc' } } +process { withName: 'RCLONE_COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_docker_arm64.config b/conf/containers_docker_arm64.config index 369f743..b6269e6 100644 --- a/conf/containers_docker_arm64.config +++ b/conf/containers_docker_arm64.config @@ -1 +1,2 @@ process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--5c84a5000a226ab5' } } +process { withName: 'RCLONE_COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_singularity_https_amd64.config b/conf/containers_singularity_https_amd64.config index 932fc7c..4a67ace 100644 --- a/conf/containers_singularity_https_amd64.config +++ b/conf/containers_singularity_https_amd64.config @@ -1 +1,2 @@ process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' } } +process { withName: 'RCLONE_COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } diff --git a/conf/containers_singularity_https_arm64.config b/conf/containers_singularity_https_arm64.config index 4f79532..2604ce0 100644 --- a/conf/containers_singularity_https_arm64.config +++ b/conf/containers_singularity_https_arm64.config @@ -1 +1,2 @@ process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e4/e48aa28aebc881254a499b24c3e1ce77b8df1b85a5432699ed6f72eb17ac7fb5/data' } } +process { withName: 'RCLONE_COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } diff --git a/conf/containers_singularity_oras_amd64.config b/conf/containers_singularity_oras_amd64.config index 2fa065b..c15ebf9 100644 --- a/conf/containers_singularity_oras_amd64.config +++ b/conf/containers_singularity_oras_amd64.config @@ -1 +1,2 @@ process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2' } } +process { withName: 'RCLONE_COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_singularity_oras_arm64.config b/conf/containers_singularity_oras_arm64.config index 84f0792..ff17a4f 100644 --- a/conf/containers_singularity_oras_arm64.config +++ b/conf/containers_singularity_oras_arm64.config @@ -1 +1,2 @@ process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c0468833d65b2f81' } } +process { withName: 'RCLONE_COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } From e294dee95ac4c8d7a3fc053a9c8a0b5f27839111 Mon Sep 17 00:00:00 2001 From: Antonia Saracco Date: Thu, 16 Jul 2026 16:07:10 +0000 Subject: [PATCH 148/334] remove withespace --- workflows/datasync.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index d399df5..cfb02aa 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -40,7 +40,7 @@ workflow DATASYNC { def source = file(input_path) def source_uri = source.toUriString() - + def rclone_destination = source.isFile() ? output_path.toString().replaceAll('/+$', '') : "${output_path.toString().replaceAll('/+$', '')}/${source.name}" From 684bdfd7c9dc44507aa2f379f03a0dd0fdcbca3b Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Thu, 16 Jul 2026 13:17:09 -0300 Subject: [PATCH 149/334] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58ce463..daaffc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#45](https://github.com/nf-core/datasync/pull/46)] - Import Rclone module from nf-core([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). +- [[#46](https://github.com/nf-core/datasync/pull/46)] - Import Rclone module from nf-core([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#41](https://github.com/nf-core/datasync/pull/41)] - Generate MultiQC Report with comparechecksum tables and input samplesheet ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). ### `Fixed` From 27eed24eb609f6cd66d92865d830cb2f8c006d11 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 16 Jul 2026 18:31:56 +0200 Subject: [PATCH 150/334] Update snapshots --- tests/default.nf.test.snap | 6 ++++-- tests/main_full.nf.test.snap | 8 ++++---- workflows/datasync.nf | 11 ++++++----- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 60a5e58..3d0c593 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -32,19 +32,21 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", + "rclone/Illumina_annotation-rclone-copy.log", "rclone/Illumina_annotation.combined.txt", "rclone/Illumina_annotation.differ.txt", "rclone/Illumina_annotation.error.txt", "rclone/Illumina_annotation.match.txt", "rclone/Illumina_annotation.missing_on_dst.txt", "rclone/Illumina_annotation.missing_on_src.txt", + "rclone/benchmark_bed-rclone-copy.log", "rclone/benchmark_bed.combined.txt", "rclone/benchmark_bed.differ.txt", "rclone/benchmark_bed.error.txt", "rclone/benchmark_bed.match.txt", "rclone/benchmark_bed.missing_on_dst.txt", "rclone/benchmark_bed.missing_on_src.txt", - "rclone/rclone-copy.log", + "rclone/test_fastq-rclone-copy.log", "rclone/test_fastq.combined.txt", "rclone/test_fastq.differ.txt", "rclone/test_fastq.error.txt", @@ -59,7 +61,7 @@ "multiqc_samplesheet.txt:md5,608c07d7a768f3d66b44f8daddcec95e" ] ], - "timestamp": "2026-07-15T03:46:47.848763259", + "timestamp": "2026-07-16T18:16:30.402815144", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index f44be10..eb928ff 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -33,23 +33,23 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", + "rclone/demultiplex-rclone-copy.log", "rclone/demultiplex.combined.txt", "rclone/demultiplex.differ.txt", "rclone/demultiplex.error.txt", "rclone/demultiplex.match.txt", "rclone/demultiplex.missing_on_dst.txt", - "rclone/demultiplex.missing_on_src.txt", - "rclone/rclone-copy.log" + "rclone/demultiplex.missing_on_src.txt" ], [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,034d1d633f567288c33f2c5e2b917962", "multiqc_rclone_checksum_md5.txt:md5,dda2aa574568eb99f579fca2a1b19207", "multiqc_rclone_checksum_sha.txt:md5,034d1d633f567288c33f2c5e2b917962", - "multiqc_samplesheet.txt:md5,29fbce9d1ffcdb97cb2ae32606e7145d" + "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" ] ], - "timestamp": "2026-07-15T03:49:57.234615558", + "timestamp": "2026-07-16T18:18:10.503592311", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/workflows/datasync.nf b/workflows/datasync.nf index b0b53e4..05a94f1 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -38,20 +38,21 @@ workflow DATASYNC { def source = file(input_path) + def source_uri = source.toUriString() + def rclone_destination = source.isFile() ? output_path.toString().replaceAll('/+$', '') : "${output_path.toString().replaceAll('/+$', '')}/${source.name}" def rclone_check = "${output_path.toString().replaceAll('/+$', '')}/${source.name}" - input: [ meta, input_path ] - rclone: [ meta, input_path, rclone_destination ] - checksum: [ meta, md5, sha, file(input_path) ] - check : [ meta, file(input_path), file(rclone_check) ] + rclone: [ meta, source_uri, rclone_destination ] + checksum: [ meta, md5, sha, source ] + check : [ meta, source, file(rclone_check) ] } // Group input md5sum/shasum with their respective generated checksum ch_checksum = ch_samplesheet.checksum - .flatMap { meta, md5, sha, input -> + .flatMap { meta, md5, sha, input -> def checksum_tuple = [] if (md5) { checksum_tuple << tuple(meta + [check_format: "md5"], md5, 'MD5', input) From ce562472c7f43bfe4132d15c6104d826b2925509 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Thu, 16 Jul 2026 17:11:15 +0000 Subject: [PATCH 151/334] Fix container config files --- conf/containers_conda_lock_files_amd64.config | 2 ++ conf/containers_conda_lock_files_arm64.config | 2 ++ conf/containers_docker_amd64.config | 2 ++ conf/containers_docker_arm64.config | 2 ++ conf/containers_singularity_https_amd64.config | 2 ++ conf/containers_singularity_https_arm64.config | 2 ++ conf/containers_singularity_oras_amd64.config | 2 ++ conf/containers_singularity_oras_arm64.config | 2 ++ 8 files changed, 16 insertions(+) diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index ac3187b..fbe762b 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1,2 +1,4 @@ process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } +process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index 7d32c6c..b425a8d 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1,2 +1,4 @@ process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } +process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_docker_amd64.config b/conf/containers_docker_amd64.config index 53163be..79d0789 100644 --- a/conf/containers_docker_amd64.config +++ b/conf/containers_docker_amd64.config @@ -1,2 +1,4 @@ process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc' } } +process { withName: 'RCLONE_CHECK' { container = 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' } } process { withName: 'RCLONE_COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_docker_arm64.config b/conf/containers_docker_arm64.config index b6269e6..921367a 100644 --- a/conf/containers_docker_arm64.config +++ b/conf/containers_docker_arm64.config @@ -1,2 +1,4 @@ process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--5c84a5000a226ab5' } } +process { withName: 'RCLONE_CHECK' { container = 'community.wave.seqera.io/library/rclone:1.74.3--351f8e39202b129a' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'community.wave.seqera.io/library/rclone:1.74.3--351f8e39202b129a' } } process { withName: 'RCLONE_COPY' { container = 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_singularity_https_amd64.config b/conf/containers_singularity_https_amd64.config index 4a67ace..0c31c94 100644 --- a/conf/containers_singularity_https_amd64.config +++ b/conf/containers_singularity_https_amd64.config @@ -1,2 +1,4 @@ process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' } } +process { withName: 'RCLONE_CHECK' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data' } } process { withName: 'RCLONE_COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } diff --git a/conf/containers_singularity_https_arm64.config b/conf/containers_singularity_https_arm64.config index 2604ce0..f480fe7 100644 --- a/conf/containers_singularity_https_arm64.config +++ b/conf/containers_singularity_https_arm64.config @@ -1,2 +1,4 @@ process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e4/e48aa28aebc881254a499b24c3e1ce77b8df1b85a5432699ed6f72eb17ac7fb5/data' } } +process { withName: 'RCLONE_CHECK' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/de/de06d232599f015aa253f63b84ba2e257bb542810dc11714b88ca9b4045b80ea/data' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/de/de06d232599f015aa253f63b84ba2e257bb542810dc11714b88ca9b4045b80ea/data' } } process { withName: 'RCLONE_COPY' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' } } diff --git a/conf/containers_singularity_oras_amd64.config b/conf/containers_singularity_oras_amd64.config index c15ebf9..2cf2119 100644 --- a/conf/containers_singularity_oras_amd64.config +++ b/conf/containers_singularity_oras_amd64.config @@ -1,2 +1,4 @@ process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2' } } +process { withName: 'RCLONE_CHECK' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--af6486c6ac506f82' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--af6486c6ac506f82' } } process { withName: 'RCLONE_COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } diff --git a/conf/containers_singularity_oras_arm64.config b/conf/containers_singularity_oras_arm64.config index ff17a4f..026fe86 100644 --- a/conf/containers_singularity_oras_arm64.config +++ b/conf/containers_singularity_oras_arm64.config @@ -1,2 +1,4 @@ process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c0468833d65b2f81' } } +process { withName: 'RCLONE_CHECK' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--49a53709aa05d28d' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'oras://community.wave.seqera.io/library/rclone:1.74.3--49a53709aa05d28d' } } process { withName: 'RCLONE_COPY' { container = 'oras://community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be' } } From 6624c41945806773e2ad103d2dcd345328bb2051 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Thu, 16 Jul 2026 15:18:44 -0300 Subject: [PATCH 152/334] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index daaffc6..63b7419 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#46](https://github.com/nf-core/datasync/pull/46)] - Import Rclone module from nf-core([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#41](https://github.com/nf-core/datasync/pull/41)] - Generate MultiQC Report with comparechecksum tables and input samplesheet ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). +- [[#49](https://github.com/nf-core/datasync/pull/49)] - Install `RCLONE_CHECK` and `RCLONE_CHECKSUM` modules from nf-core ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). + ### `Fixed` From 36491b260368a4178009565d301fb671ac6a83d4 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Thu, 16 Jul 2026 15:25:26 -0300 Subject: [PATCH 153/334] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63b7419..1b9f2c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,6 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#41](https://github.com/nf-core/datasync/pull/41)] - Generate MultiQC Report with comparechecksum tables and input samplesheet ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#49](https://github.com/nf-core/datasync/pull/49)] - Install `RCLONE_CHECK` and `RCLONE_CHECKSUM` modules from nf-core ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - ### `Fixed` ### `Dependencies` From a185ae86b29a781ba21875ddc2dbed45eeb71405 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 16 Jul 2026 21:49:32 +0200 Subject: [PATCH 154/334] Make report descriptions clearer --- assets/multiqc_config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 20e26ab..19ebdb6 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -32,24 +32,24 @@ custom_data: title: Sha256 checksum file rclone_checksum_md5: - section_name: "RClone MD5 Checksum Report" - description: "MD5 input checksum validation" + section_name: "MD5sum Input Validation" + description: "Comparison of the expected MD5 checksums provided in the samplesheet with the observed MD5 checksums of the file(s) found at the specified source path." plot_type: "table" file_format: "tsv" pconfig: no_violin: true rclone_checksum_sha: - section_name: "RClone SHA Checksum Report" - description: "SHA input checksum validation" + section_name: "SHAsum Input Validation" + description: "Comparison of the expected SHA-256 checksums provided in the samplesheet with the observed SHA-256 checksums of the file(s) found at the specified source path." plot_type: "table" file_format: "tsv" pconfig: no_violin: true rclone_check: - section_name: "Final RClone Check Report" - description: "Validation of copied files" + section_name: "Source–Destination Checksum Validation" + description: "Comparison of the checksums of corresponding file(s) in the source input path and the output destination to confirm data integrity following file transfer." plot_type: "table" file_format: "tsv" pconfig: From 97909c7808488ebddc647509473a91bc261e18ff Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 16 Jul 2026 21:50:09 +0200 Subject: [PATCH 155/334] Update methods description --- subworkflows/local/utils_nfcore_datasync_pipeline/main.nf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index a425b39..6a3d59d 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -182,8 +182,7 @@ def toolCitationText() { def citation_text = [ "Tools used in the workflow included:", "Files were transferred to the specified destination using Rclone (Craig-Wood, 2023), which supports data movement across local and cloud storage backends.", - "File integrity was validated by computing cryptographic checksums using md5sum and shasum.", - "Expected and observed checksum files were compared using the pipeline's local comparechecksum module, implemented in R (R Core Team, 2017).", + "File integrity was validated by computing cryptographic checksums with Rclone.", "Pipeline results were summarised with MultiQC (Ewels et al. 2016)", "." ].join(' ').trim() @@ -197,7 +196,6 @@ def toolBibliographyText() { // Uncomment function in methodsDescriptionText to render in MultiQC report def reference_text = [ "
  • Craig-Wood, N. (2023). Rclone: Rsync for cloud storage (Vers. 1.65.0). Computer software. https://rclone.org
  • ", - "
  • R Core Team (2017). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. https://www.R-project.org/
  • ", "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics, 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " ].join(' ').trim() From 5981d68c3c23dcf5a7699b72cc795bc4dcaefdae Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 16 Jul 2026 21:50:48 +0200 Subject: [PATCH 156/334] Create helper function to parse rclone output --- .../utils_nfcore_datasync_pipeline/main.nf | 22 ++++++++++++ workflows/datasync.nf | 35 ++----------------- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 6a3d59d..010ffc2 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -172,6 +172,28 @@ workflow PIPELINE_COMPLETION { def validateInputParameters() { } +// +// Parse Rclone check and checksum combined.txt file +// +def parseRcloneCheck(meta, check_file) { + def status_map = [ + '=': 'Match', + '-': 'Missing in source', + '+': 'Missing in destination', + '*': 'Mismatch', + '!': 'Error' + ] + + return check_file.readLines() + .findAll { it.trim() } + .collect { line -> + def fields = line.split(/ /, 2) + def status = status_map.get(fields[0], fields[0]) + + [ meta, "${fields[1]}\t${meta.id}\t${status}\n" ] + } +} + // // Generate methods description for MultiQC // diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 05a94f1..742bbac 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -11,6 +11,7 @@ include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_datasync_pipeline' +include { parseRcloneCheck } from '../subworkflows/local/utils_nfcore_datasync_pipeline' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -70,22 +71,7 @@ workflow DATASYNC { ch_multiqc_files = ch_multiqc_files.mix(RCLONE_CHECKSUM.out.combined .flatMap { meta, check_file -> - check_file.readLines() - .findAll { it.trim() } - .collect { line -> - def fields = line.split(/ /, 2) - def status_map = [ - '=': 'Match', - '-': 'Missing in source', - '+': 'Missing in destination', - '*': 'Mismatch', - '!': 'Error' - ] - - def status = status_map.get(fields[0], fields[0]) - - [ meta, "${fields[1]}\t${meta.id}\t${status}\n" ] - } + parseRcloneCheck(meta, check_file) } .collectFile( seed: "File\tSample\tStatus\n", @@ -117,22 +103,7 @@ workflow DATASYNC { ch_multiqc_files = ch_multiqc_files.mix(RCLONE_CHECK.out.combined .flatMap { meta, check_file -> - check_file.readLines() - .findAll { it.trim() } - .collect { line -> - def fields = line.split(/ /, 2) - def status_map = [ - '=': 'Match', - '-': 'Missing in source', - '+': 'Missing in destination', - '*': 'Mismatch', - '!': 'Error' - ] - - def status = status_map.get(fields[0], fields[0]) - - [ meta, "${fields[1]}\t${meta.id}\t${status}\n" ] - } + parseRcloneCheck(meta, check_file) } .collectFile( seed: "File\tSample\tStatus\n", From 4b960acc4cf43fbcf972213cca37a2beedba4dce Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 16 Jul 2026 21:53:22 +0200 Subject: [PATCH 157/334] Fix typo --- assets/multiqc_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 19ebdb6..6a2f444 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -48,7 +48,7 @@ custom_data: no_violin: true rclone_check: - section_name: "Source–Destination Checksum Validation" + section_name: "Source-Destination Checksum Validation" description: "Comparison of the checksums of corresponding file(s) in the source input path and the output destination to confirm data integrity following file transfer." plot_type: "table" file_format: "tsv" From 25c08ecb6bede547f9cb1d61514ee43b4a03592a Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 17 Jul 2026 16:53:43 +0000 Subject: [PATCH 158/334] add color to multiqc report --- CHANGELOG.md | 1 + assets/multiqc_config.yml | 105 ++++++++++++++++++ assets/multiqc_custom.css | 33 ++++++ conf/modules.config | 8 +- .../utils_nfcore_datasync_pipeline/main.nf | 10 +- tests/default.nf.test.snap | 8 +- tests/main_full.nf.test.snap | 10 +- workflows/datasync.nf | 5 +- 8 files changed, 167 insertions(+), 13 deletions(-) create mode 100644 assets/multiqc_custom.css diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b9f2c2..e2e3ada 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` +- [[#31](https://github.com/nf-core/datasync/pull/31)] - Add colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#46](https://github.com/nf-core/datasync/pull/46)] - Import Rclone module from nf-core([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 6a2f444..7cc43a3 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -36,24 +36,129 @@ custom_data: description: "Comparison of the expected MD5 checksums provided in the samplesheet with the observed MD5 checksums of the file(s) found at the specified source path." plot_type: "table" file_format: "tsv" + headers: + Status: + title: Result + description: "= Match; - Missing in source; + Missing in destination; * Mismatch; ! Error" + cond_formatting_rules: + match: + - s_eq: "=" + - s_eq: "Match" + missing_source: + - s_eq: "-" + - s_eq: "Missing in source" + missing_destination: + - s_eq: "+" + - s_eq: "Missing in destination" + mismatch: + - s_eq: "*" + - s_eq: "Mismatch" + error: + - s_eq: "!" + - s_eq: "Error" + cond_formatting_colours: + - match: "#5cb85c" + - missing_source: "#f0ad4e" + - missing_destination: "#5bc0de" + - mismatch: "#d9534f" + - error: "#8b0000" + File: + title: File + description: "File checked by rclone" + Priority: + title: Priority + hidden: true pconfig: no_violin: true + defaultsort: + - column: Priority + direction: asc rclone_checksum_sha: section_name: "SHAsum Input Validation" description: "Comparison of the expected SHA-256 checksums provided in the samplesheet with the observed SHA-256 checksums of the file(s) found at the specified source path." plot_type: "table" file_format: "tsv" + headers: + Status: + title: Result + description: "= Match; - Missing in source; + Missing in destination; * Mismatch; ! Error" + cond_formatting_rules: + match: + - s_eq: "=" + - s_eq: "Match" + missing_source: + - s_eq: "-" + - s_eq: "Missing in source" + missing_destination: + - s_eq: "+" + - s_eq: "Missing in destination" + mismatch: + - s_eq: "*" + - s_eq: "Mismatch" + error: + - s_eq: "!" + - s_eq: "Error" + cond_formatting_colours: + - match: "#5cb85c" + - missing_source: "#f0ad4e" + - missing_destination: "#5bc0de" + - mismatch: "#d9534f" + - error: "#8b0000" + File: + title: File + description: "File checked by rclone" + Priority: + title: Priority + hidden: true pconfig: no_violin: true + defaultsort: + - column: Priority + direction: asc rclone_check: section_name: "Source-Destination Checksum Validation" description: "Comparison of the checksums of corresponding file(s) in the source input path and the output destination to confirm data integrity following file transfer." plot_type: "table" file_format: "tsv" + headers: + Status: + title: Result + description: "= Match; - Missing in source; + Missing in destination; * Mismatch; ! Error" + cond_formatting_rules: + match: + - s_eq: "=" + - s_eq: "Match" + missing_source: + - s_eq: "-" + - s_eq: "Missing in source" + missing_destination: + - s_eq: "+" + - s_eq: "Missing in destination" + mismatch: + - s_eq: "*" + - s_eq: "Mismatch" + error: + - s_eq: "!" + - s_eq: "Error" + cond_formatting_colours: + - match: "#5cb85c" + - missing_source: "#f0ad4e" + - missing_destination: "#5bc0de" + - mismatch: "#d9534f" + - error: "#8b0000" + File: + title: File + description: "File checked by rclone" + Priority: + title: Priority + hidden: true pconfig: no_violin: true + defaultsort: + - column: Priority + direction: asc sp: samplesheet: diff --git a/assets/multiqc_custom.css b/assets/multiqc_custom.css new file mode 100644 index 0000000..eccc93b --- /dev/null +++ b/assets/multiqc_custom.css @@ -0,0 +1,33 @@ +/* Keep the internal row identifier available to MultiQC without displaying it. */ +#rclone_checksum_md5-section-plot_table .rowheader, +#rclone_checksum_sha-section-plot_table .rowheader, +#rclone_check-section-plot_table .rowheader { + display: none; +} + +/* Fit rclone result tables to the report width and wrap long file paths. */ +#rclone_checksum_md5-section-plot_table, +#rclone_checksum_sha-section-plot_table, +#rclone_check-section-plot_table { + table-layout: fixed; + width: 100%; +} + +#rclone_checksum_md5-section-plot_table .Status, +#rclone_checksum_sha-section-plot_table .Status, +#rclone_check-section-plot_table .Status { + width: 14rem; +} + +#rclone_checksum_md5-section-plot_table .File .val, +#rclone_checksum_sha-section-plot_table .File .val, +#rclone_check-section-plot_table .File .val { + overflow-wrap: anywhere; + white-space: normal; +} + +#rclone_checksum_md5-section-plot_table_container .mqc-table-responsive, +#rclone_checksum_sha-section-plot_table_container .mqc-table-responsive, +#rclone_check-section-plot_table_container .mqc-table-responsive { + overflow-x: hidden; +} diff --git a/conf/modules.config b/conf/modules.config index be5c307..7b4b0f9 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -46,7 +46,13 @@ process { } withName: 'MULTIQC' { - ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } + ext.args = { + def args = ['--custom-css-file */multiqc_custom.css'] + if (params.multiqc_title) { + args.add("--title \"$params.multiqc_title\"") + } + args.join(' ') + } publishDir = [ path: { "${params.outdir}/multiqc" }, mode: params.publish_dir_mode, diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 010ffc2..7312219 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -183,14 +183,22 @@ def parseRcloneCheck(meta, check_file) { '*': 'Mismatch', '!': 'Error' ] + def priority_map = [ + '!': 0, + '*': 1, + '-': 2, + '+': 3, + '=': 4 + ] return check_file.readLines() .findAll { it.trim() } .collect { line -> def fields = line.split(/ /, 2) def status = status_map.get(fields[0], fields[0]) + def priority = priority_map.get(fields[0], 0) - [ meta, "${fields[1]}\t${meta.id}\t${status}\n" ] + [ meta, "${fields[1]}\t${meta.id}\t${status}\t${fields[1]}\t${priority}\n" ] } } diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 3d0c593..7e3530e 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -56,15 +56,15 @@ ], [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_rclone_check.txt:md5,b6ea8bb50b08e6a31b02de80f15cba83", - "multiqc_rclone_checksum_md5.txt:md5,b6ea8bb50b08e6a31b02de80f15cba83", + "multiqc_rclone_check.txt:md5,33c4b2d611ba070825a845a089546e76", + "multiqc_rclone_checksum_md5.txt:md5,33c4b2d611ba070825a845a089546e76", "multiqc_samplesheet.txt:md5,608c07d7a768f3d66b44f8daddcec95e" ] ], - "timestamp": "2026-07-16T18:16:30.402815144", + "timestamp": "2026-07-17T16:46:31.424092166", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.6" } } } \ No newline at end of file diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index eb928ff..8c974c2 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -43,16 +43,16 @@ ], [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_rclone_check.txt:md5,034d1d633f567288c33f2c5e2b917962", - "multiqc_rclone_checksum_md5.txt:md5,dda2aa574568eb99f579fca2a1b19207", - "multiqc_rclone_checksum_sha.txt:md5,034d1d633f567288c33f2c5e2b917962", + "multiqc_rclone_check.txt:md5,6ee1b24af2769c0620cb6a3c52d7e3ce", + "multiqc_rclone_checksum_md5.txt:md5,0367be35c8af1775ccedaac24abdbfa9", + "multiqc_rclone_checksum_sha.txt:md5,6ee1b24af2769c0620cb6a3c52d7e3ce", "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" ] ], - "timestamp": "2026-07-16T18:18:10.503592311", + "timestamp": "2026-07-17T16:51:02.615492867", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.6" } } } \ No newline at end of file diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 742bbac..52dcd7b 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -74,7 +74,7 @@ workflow DATASYNC { parseRcloneCheck(meta, check_file) } .collectFile( - seed: "File\tSample\tStatus\n", + seed: "Row\tSample\tStatus\tFile\tPriority\n", sort: false ) { meta, checksum -> return [ "${meta.id}_${meta.check_format}_rclone_checksum_mqc.tsv", checksum ] @@ -106,7 +106,7 @@ workflow DATASYNC { parseRcloneCheck(meta, check_file) } .collectFile( - seed: "File\tSample\tStatus\n", + seed: "Row\tSample\tStatus\tFile\tPriority\n", sort: false ) { meta, check -> return [ "${meta.id}_rclone_check_mqc.tsv", check ] @@ -155,6 +155,7 @@ workflow DATASYNC { : file("${projectDir}/assets/methods_description_template.yml", checkIfExists: true) def ch_methods_description = channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml', sort: true)) + ch_multiqc_files = ch_multiqc_files.mix(channel.value(file("${projectDir}/assets/multiqc_custom.css", checkIfExists: true))) MULTIQC( ch_multiqc_files.flatten().collect().map { files -> [ From f678feeee7db867b84b205ada96724f3b6207031 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:32:20 +0000 Subject: [PATCH 159/334] update multiqc report --- CHANGELOG.md | 3 +- assets/multiqc_config.yml | 38 +++++++++- assets/multiqc_custom.css | 49 +++++++----- conf/modules.config | 18 +++++ .../utils_nfcore_datasync_pipeline/main.nf | 2 +- tests/.nftignore | 4 +- tests/default.nf.test.snap | 75 +++++++++++++------ tests/main_full.nf.test.snap | 33 +++++--- workflows/datasync.nf | 4 +- 9 files changed, 166 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2e3ada..6704c6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` -- [[#31](https://github.com/nf-core/datasync/pull/31)] - Add colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). +- [[#55](https://github.com/nf-core/datasync/pull/55)] - Add subdirectories with sample id to results. Improvements to MultiQC report (width of columns, sections and sub-section headers)colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). +- [[#54](https://github.com/nf-core/datasync/pull/54)] - Add colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#46](https://github.com/nf-core/datasync/pull/46)] - Import Rclone module from nf-core([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 7cc43a3..cd549e8 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -14,9 +14,19 @@ export_plots: false disable_version_detection: true +custom_content: + order: + - samplesheet + - rclone_checksum_md5 + - rclone_checksum_sha + - rclone_check + custom_data: samplesheet: section_name: "Input Samplesheet" + description: > + The input samplesheet lists each sample included in the run, the source path to copy, the destination path, + and the user-provided checksum files used to validate the source data. plot_type: "table" file_format: "csv" headers: @@ -32,7 +42,12 @@ custom_data: title: Sha256 checksum file rclone_checksum_md5: - section_name: "MD5sum Input Validation" + parent_id: source_path_checksum_validation + parent_name: "Source checks" + parent_description: > + This section compares checksums calculated from files at each source path with the expected checksums supplied by the user + in the input samplesheet. This confirms source-file integrity before transfer. + section_name: "MD5 Checksum Validation" description: "Comparison of the expected MD5 checksums provided in the samplesheet with the observed MD5 checksums of the file(s) found at the specified source path." plot_type: "table" file_format: "tsv" @@ -65,6 +80,9 @@ custom_data: File: title: File description: "File checked by rclone" + Sample: + title: Sample + description: "Sample name from the input samplesheet" Priority: title: Priority hidden: true @@ -75,7 +93,12 @@ custom_data: direction: asc rclone_checksum_sha: - section_name: "SHAsum Input Validation" + parent_id: source_path_checksum_validation + parent_name: "Source checks" + parent_description: > + This section compares checksums calculated from files at each source path with the expected checksums supplied by the user + in the input samplesheet. This confirms source-file integrity before transfer. + section_name: "SHA-256 Checksum Validation" description: "Comparison of the expected SHA-256 checksums provided in the samplesheet with the observed SHA-256 checksums of the file(s) found at the specified source path." plot_type: "table" file_format: "tsv" @@ -108,6 +131,9 @@ custom_data: File: title: File description: "File checked by rclone" + Sample: + title: Sample + description: "Sample name from the input samplesheet" Priority: title: Priority hidden: true @@ -118,6 +144,11 @@ custom_data: direction: asc rclone_check: + parent_id: file_transfer_integrity_check + parent_name: "Post-Transfer Checks" + parent_description: > + This section compares corresponding files at the source and destination paths after the transfer step to confirm that the + destination content is complete and unchanged. section_name: "Source-Destination Checksum Validation" description: "Comparison of the checksums of corresponding file(s) in the source input path and the output destination to confirm data integrity following file transfer." plot_type: "table" @@ -151,6 +182,9 @@ custom_data: File: title: File description: "File checked by rclone" + Sample: + title: Sample + description: "Sample name from the input samplesheet" Priority: title: Priority hidden: true diff --git a/assets/multiqc_custom.css b/assets/multiqc_custom.css index eccc93b..777ea04 100644 --- a/assets/multiqc_custom.css +++ b/assets/multiqc_custom.css @@ -1,33 +1,48 @@ /* Keep the internal row identifier available to MultiQC without displaying it. */ -#rclone_checksum_md5-section-plot_table .rowheader, -#rclone_checksum_sha-section-plot_table .rowheader, -#rclone_check-section-plot_table .rowheader { +#rclone_checksum_md5-plot_table .rowheader, +#rclone_checksum_sha-plot_table .rowheader, +#rclone_check-plot_table .rowheader { display: none; } +/* Distinguish major sections from their result subsections. */ +#samplesheet, +#source_path_checksum_validation, +#file_transfer_integrity_check { + font-size: 2rem; +} + +#rclone_checksum_md5, +#rclone_checksum_sha, +#rclone_check { + color: var(--bs-secondary-color, #6c757d); + font-size: 1.35rem; +} + /* Fit rclone result tables to the report width and wrap long file paths. */ -#rclone_checksum_md5-section-plot_table, -#rclone_checksum_sha-section-plot_table, -#rclone_check-section-plot_table { - table-layout: fixed; +#rclone_checksum_md5-plot_table, +#rclone_checksum_sha-plot_table, +#rclone_check-plot_table { + table-layout: auto; width: 100%; } -#rclone_checksum_md5-section-plot_table .Status, -#rclone_checksum_sha-section-plot_table .Status, -#rclone_check-section-plot_table .Status { - width: 14rem; +#rclone_checksum_md5-plot_table .Status, +#rclone_checksum_sha-plot_table .Status, +#rclone_check-plot_table .Status { + white-space: nowrap; + width: 1%; } -#rclone_checksum_md5-section-plot_table .File .val, -#rclone_checksum_sha-section-plot_table .File .val, -#rclone_check-section-plot_table .File .val { +#rclone_checksum_md5-plot_table .File .val, +#rclone_checksum_sha-plot_table .File .val, +#rclone_check-plot_table .File .val { overflow-wrap: anywhere; white-space: normal; } -#rclone_checksum_md5-section-plot_table_container .mqc-table-responsive, -#rclone_checksum_sha-section-plot_table_container .mqc-table-responsive, -#rclone_check-section-plot_table_container .mqc-table-responsive { +#rclone_checksum_md5-plot_table_container .mqc-table-responsive, +#rclone_checksum_sha-plot_table_container .mqc-table-responsive, +#rclone_check-plot_table_container .mqc-table-responsive { overflow-x: hidden; } diff --git a/conf/modules.config b/conf/modules.config index 7b4b0f9..32a6697 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -33,6 +33,11 @@ process { } base_args.join(' ') } + publishDir = [ + path: { "${params.outdir}/rclone/copy" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] } withName: 'RCLONE_CHECK' { @@ -43,6 +48,19 @@ process { ] base_args.join(' ') } + publishDir = [ + path: { "${params.outdir}/rclone/check/${meta.id}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + + withName: 'RCLONE_CHECKSUM' { + publishDir = [ + path: { "${params.outdir}/rclone/checksum/${meta.id}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] } withName: 'MULTIQC' { diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 7312219..57723c5 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -198,7 +198,7 @@ def parseRcloneCheck(meta, check_file) { def status = status_map.get(fields[0], fields[0]) def priority = priority_map.get(fields[0], 0) - [ meta, "${fields[1]}\t${meta.id}\t${status}\t${fields[1]}\t${priority}\n" ] + [ meta, "${meta.id}:${fields[1]}\t${status}\t${fields[1]}\t${meta.id}\t${priority}\n" ] } } diff --git a/tests/.nftignore b/tests/.nftignore index f6d171f..12ea18a 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -10,5 +10,5 @@ multiqc/multiqc_plots/{svg,pdf,png}/*.{svg,pdf,png} multiqc/multiqc_report.html fastqc/*_fastqc.{html,zip} pipeline_info/*.{html,json,txt,yml} -rclone/*.txt -rclone/*.log +rclone/**/*.txt +rclone/**/*.log diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 7e3530e..c71d4e5 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -32,36 +32,63 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", - "rclone/Illumina_annotation-rclone-copy.log", - "rclone/Illumina_annotation.combined.txt", - "rclone/Illumina_annotation.differ.txt", - "rclone/Illumina_annotation.error.txt", - "rclone/Illumina_annotation.match.txt", - "rclone/Illumina_annotation.missing_on_dst.txt", - "rclone/Illumina_annotation.missing_on_src.txt", - "rclone/benchmark_bed-rclone-copy.log", - "rclone/benchmark_bed.combined.txt", - "rclone/benchmark_bed.differ.txt", - "rclone/benchmark_bed.error.txt", - "rclone/benchmark_bed.match.txt", - "rclone/benchmark_bed.missing_on_dst.txt", - "rclone/benchmark_bed.missing_on_src.txt", - "rclone/test_fastq-rclone-copy.log", - "rclone/test_fastq.combined.txt", - "rclone/test_fastq.differ.txt", - "rclone/test_fastq.error.txt", - "rclone/test_fastq.match.txt", - "rclone/test_fastq.missing_on_dst.txt", - "rclone/test_fastq.missing_on_src.txt" + "rclone/check", + "rclone/check/Illumina_annotation", + "rclone/check/Illumina_annotation/Illumina_annotation.combined.txt", + "rclone/check/Illumina_annotation/Illumina_annotation.differ.txt", + "rclone/check/Illumina_annotation/Illumina_annotation.error.txt", + "rclone/check/Illumina_annotation/Illumina_annotation.match.txt", + "rclone/check/Illumina_annotation/Illumina_annotation.missing_on_dst.txt", + "rclone/check/Illumina_annotation/Illumina_annotation.missing_on_src.txt", + "rclone/check/benchmark_bed", + "rclone/check/benchmark_bed/benchmark_bed.combined.txt", + "rclone/check/benchmark_bed/benchmark_bed.differ.txt", + "rclone/check/benchmark_bed/benchmark_bed.error.txt", + "rclone/check/benchmark_bed/benchmark_bed.match.txt", + "rclone/check/benchmark_bed/benchmark_bed.missing_on_dst.txt", + "rclone/check/benchmark_bed/benchmark_bed.missing_on_src.txt", + "rclone/check/test_fastq", + "rclone/check/test_fastq/test_fastq.combined.txt", + "rclone/check/test_fastq/test_fastq.differ.txt", + "rclone/check/test_fastq/test_fastq.error.txt", + "rclone/check/test_fastq/test_fastq.match.txt", + "rclone/check/test_fastq/test_fastq.missing_on_dst.txt", + "rclone/check/test_fastq/test_fastq.missing_on_src.txt", + "rclone/checksum", + "rclone/checksum/Illumina_annotation", + "rclone/checksum/Illumina_annotation/Illumina_annotation.combined.txt", + "rclone/checksum/Illumina_annotation/Illumina_annotation.differ.txt", + "rclone/checksum/Illumina_annotation/Illumina_annotation.error.txt", + "rclone/checksum/Illumina_annotation/Illumina_annotation.match.txt", + "rclone/checksum/Illumina_annotation/Illumina_annotation.missing_on_dst.txt", + "rclone/checksum/Illumina_annotation/Illumina_annotation.missing_on_src.txt", + "rclone/checksum/benchmark_bed", + "rclone/checksum/benchmark_bed/benchmark_bed.combined.txt", + "rclone/checksum/benchmark_bed/benchmark_bed.differ.txt", + "rclone/checksum/benchmark_bed/benchmark_bed.error.txt", + "rclone/checksum/benchmark_bed/benchmark_bed.match.txt", + "rclone/checksum/benchmark_bed/benchmark_bed.missing_on_dst.txt", + "rclone/checksum/benchmark_bed/benchmark_bed.missing_on_src.txt", + "rclone/checksum/test_fastq", + "rclone/checksum/test_fastq/test_fastq.combined.txt", + "rclone/checksum/test_fastq/test_fastq.differ.txt", + "rclone/checksum/test_fastq/test_fastq.error.txt", + "rclone/checksum/test_fastq/test_fastq.match.txt", + "rclone/checksum/test_fastq/test_fastq.missing_on_dst.txt", + "rclone/checksum/test_fastq/test_fastq.missing_on_src.txt", + "rclone/copy", + "rclone/copy/Illumina_annotation-rclone-copy.log", + "rclone/copy/benchmark_bed-rclone-copy.log", + "rclone/copy/test_fastq-rclone-copy.log" ], [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_rclone_check.txt:md5,33c4b2d611ba070825a845a089546e76", - "multiqc_rclone_checksum_md5.txt:md5,33c4b2d611ba070825a845a089546e76", + "multiqc_rclone_check.txt:md5,14b1ff73415db0533e1467cdf3dfccf8", + "multiqc_rclone_checksum_md5.txt:md5,14b1ff73415db0533e1467cdf3dfccf8", "multiqc_samplesheet.txt:md5,608c07d7a768f3d66b44f8daddcec95e" ] ], - "timestamp": "2026-07-17T16:46:31.424092166", + "timestamp": "2026-07-17T19:26:17.292861031", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.6" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 8c974c2..dcf61c3 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -33,23 +33,34 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", - "rclone/demultiplex-rclone-copy.log", - "rclone/demultiplex.combined.txt", - "rclone/demultiplex.differ.txt", - "rclone/demultiplex.error.txt", - "rclone/demultiplex.match.txt", - "rclone/demultiplex.missing_on_dst.txt", - "rclone/demultiplex.missing_on_src.txt" + "rclone/check", + "rclone/check/demultiplex", + "rclone/check/demultiplex/demultiplex.combined.txt", + "rclone/check/demultiplex/demultiplex.differ.txt", + "rclone/check/demultiplex/demultiplex.error.txt", + "rclone/check/demultiplex/demultiplex.match.txt", + "rclone/check/demultiplex/demultiplex.missing_on_dst.txt", + "rclone/check/demultiplex/demultiplex.missing_on_src.txt", + "rclone/checksum", + "rclone/checksum/demultiplex", + "rclone/checksum/demultiplex/demultiplex.combined.txt", + "rclone/checksum/demultiplex/demultiplex.differ.txt", + "rclone/checksum/demultiplex/demultiplex.error.txt", + "rclone/checksum/demultiplex/demultiplex.match.txt", + "rclone/checksum/demultiplex/demultiplex.missing_on_dst.txt", + "rclone/checksum/demultiplex/demultiplex.missing_on_src.txt", + "rclone/copy", + "rclone/copy/demultiplex-rclone-copy.log" ], [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_rclone_check.txt:md5,6ee1b24af2769c0620cb6a3c52d7e3ce", - "multiqc_rclone_checksum_md5.txt:md5,0367be35c8af1775ccedaac24abdbfa9", - "multiqc_rclone_checksum_sha.txt:md5,6ee1b24af2769c0620cb6a3c52d7e3ce", + "multiqc_rclone_check.txt:md5,204410f4dab8ab5db201f4833baa2f81", + "multiqc_rclone_checksum_md5.txt:md5,f59d50960061aee8afac0d9389b90a2e", + "multiqc_rclone_checksum_sha.txt:md5,204410f4dab8ab5db201f4833baa2f81", "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" ] ], - "timestamp": "2026-07-17T16:51:02.615492867", + "timestamp": "2026-07-17T19:31:26.493917757", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.6" diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 52dcd7b..c47edd8 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -74,7 +74,7 @@ workflow DATASYNC { parseRcloneCheck(meta, check_file) } .collectFile( - seed: "Row\tSample\tStatus\tFile\tPriority\n", + seed: "Row\tStatus\tFile\tSample\tPriority\n", sort: false ) { meta, checksum -> return [ "${meta.id}_${meta.check_format}_rclone_checksum_mqc.tsv", checksum ] @@ -106,7 +106,7 @@ workflow DATASYNC { parseRcloneCheck(meta, check_file) } .collectFile( - seed: "Row\tSample\tStatus\tFile\tPriority\n", + seed: "Row\tStatus\tFile\tSample\tPriority\n", sort: false ) { meta, check -> return [ "${meta.id}_rclone_check_mqc.tsv", check ] From 1fa3a484e5b312ba9457a8278002a74c9f5543a2 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 17 Jul 2026 16:50:09 -0300 Subject: [PATCH 160/334] docs: document datasync pipeline --- README.md | 74 +++++++++------ docs/output.md | 97 ++++++++++++++------ docs/usage.md | 237 ++++++++++++++++--------------------------------- 3 files changed, 191 insertions(+), 217 deletions(-) diff --git a/README.md b/README.md index 1c76aa4..c899b6e 100644 --- a/README.md +++ b/README.md @@ -21,52 +21,68 @@ ## Introduction -[WIP] WORK IN PROGRESS AND NOT YET STABLE - DO NOT USE FOR PRODUCTIVE SETTINGS YET +> [!WARNING] +> nf-core/datasync is under active development and is not yet recommended for production data transfers. Validate its behaviour with representative data before relying on it. + +**nf-core/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline: -**nf-core/datasync** is a system operation pipeline that provides several workflows for handling system operation / automation tasks that are commonly helpful for various tasks in large data processing / analysis facilities. This includes: +1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest; +2. copies the source to the requested destination with [rclone](https://rclone.org/); +3. compares the copied data with the source using `rclone check`; and +4. produces detailed rclone status files and a consolidated MultiQC report. -- Data Synchronization & Checksum generation - - Configurable: Can provide YAML file which files to include or exclude from sync - - Checksum backend: Can configure which backend to use for checksum generation (e.g. sha256sum, md5, ...) - - Configurable whether to include (sub-) folders in the sync or not (search for checkpoint files, e.g. has to have DEMUX_DONE that signals a demultiplexing run was finished & successfully copied) -- Data Integrity validation - - Provided with a directory to check, can validate that file(s) found are matching checksums from Synchronization subworkflow -- Data Archival & Deletion - - Can check source and target location for existence of file(s) and decide based on user configurable rules whether files can be considered archived - - Timestamp older than X days - - Checksums match Integrity validation report - - Create empty files to make it obvious that archival was performed - - Optionally: Delete files or create list of files to be deleted for manual deletion process +Sources may be local paths or HTTP(S) URLs. Destinations can be local paths or rclone-supported remote storage (for example S3 or Azure Blob Storage); authenticated remotes can be defined with `--rclone_config`. -The pipeline can be configured by users to execute any of the aforementioned subworkflows and then produces a report using MultiQC custom content that also serves as a report of _what_ was done by the pipeline for documentation purposes. +```mermaid +graph LR + A[Samplesheet] --> B[Validate supplied checksums] + A --> C[Copy with rclone] + C --> D[Compare source and destination] + B --> E[MultiQC integrity report] + D --> E +``` -## Usage +## Quick start > [!NOTE] -> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data. +> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required. -Now, you can run the pipeline using: +Create a samplesheet containing one transfer per row: + +```csv +sample,input,output_path,checksum_md5,checksum_sha +run_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv, +reference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv +``` + +Then launch the pipeline with a container profile: ```bash nextflow run nf-core/datasync \ - -profile \ - --input samplesheet.csv \ - --outdir - --sync - --sync_backend 'sha256' - --sync_done true #Creates SYNC_DONE file when done in each folder + -r \ + -profile docker \ + --input samplesheet.csv \ + --outdir results \ + --rclone_config /path/to/rclone.conf ``` +`--rclone_config` is optional when all paths are accessible without an rclone remote configuration. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination. + > [!WARNING] -> 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/running/run-pipelines#using-parameter-files). +> Provide pipeline parameters on the command line or with Nextflow's `-params-file` option. Do not put pipeline parameters in a configuration supplied with `-c`; custom configuration files are intended for executor and resource settings. -For more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/parameters). +See the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters). ## Pipeline output -To see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/datasync/results) tab on the nf-core website pipeline page. -For more details about the output files and reports, please refer to the -[output documentation](https://nf-co.re/datasync/output). +Results are written below `--outdir`: + +- `rclone/` contains a copy log and integrity status files for each samplesheet row; +- `multiqc/multiqc_report.html` provides the consolidated transfer and checksum summary; +- `multiqc/multiqc_data/` contains machine-readable report data; and +- `pipeline_info/` contains software versions and Nextflow execution reports. + +The transferred data itself is written directly to each row's `output_path`, not below `--outdir` unless that is the destination you selected. See the [output documentation](docs/output.md) for file names and status-code interpretation. ## Credits diff --git a/docs/output.md b/docs/output.md index 1b7eb8b..50ea1e3 100644 --- a/docs/output.md +++ b/docs/output.md @@ -2,60 +2,99 @@ ## Introduction -This document describes the output produced by the pipeline. Most of the plots are taken from the MultiQC report, which summarises results at the end of the pipeline. +This document describes the reports produced by nf-core/datasync. Paths below are relative to the directory supplied with `--outdir`. + +> [!IMPORTANT] +> The copied payload is written to each samplesheet row's `output_path`. It is not placed in `--outdir` unless `output_path` explicitly points there. + +## Output overview + +```text +/ +├── rclone/ +│ ├── -rclone-copy.log +│ ├── .combined.txt +│ ├── .match.txt +│ ├── .differ.txt +│ ├── .missing_on_dst.txt +│ ├── .missing_on_src.txt +│ └── .error.txt +├── multiqc/ +│ ├── multiqc_report.html +│ └── multiqc_data/ +└── pipeline_info/ + ├── nf_core_datasync_software_mqc_versions.yml + └── execution_* / pipeline_dag_* +``` + +## Rclone transfer and integrity reports -The directories listed below will be created in the results directory after the pipeline has finished. All paths are relative to the top-level results directory. - - +
    +Output files -## Pipeline overview +- `rclone/` + - `-rclone-copy.log`: informational log from the copy operation. + - `.combined.txt`: combined comparison status, one path per line. + - `.match.txt`: paths whose content matched (`=`). + - `.differ.txt`: paths present on both sides but with different content (`*`). + - `.missing_on_dst.txt`: paths found in the source or manifest but absent from the checked data (`-`). + - `.missing_on_src.txt`: paths found in the checked data but absent from the source or manifest (`+`). + - `.error.txt`: paths that could not be read or hashed (`!`). -The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: +
    -- [FastQC](#fastqc) - Raw read QC -- [MultiQC](#multiqc) - Aggregate report describing results and QC from the whole pipeline -- [Pipeline information](#pipeline-information) - Report metrics generated during the workflow execution +Two integrity stages create reports: -### FastQC +1. **Pre-copy checksum validation** uses each supplied MD5 and/or SHA-256 manifest to check the source. +2. **Post-copy validation** compares the source with the destination after the copy task finishes. -
    -Output files +Both stages use the same `.*.txt` naming convention and publish to `rclone/`. When a row supplies a checksum manifest, similarly named pre-copy and post-copy files may target the same published path; use the consolidated MultiQC sections for the stage-specific summary and retain the Nextflow work directory if both raw report sets must be audited independently. -- `fastqc/` - - `*_fastqc.html`: FastQC report containing quality metrics. - - `*_fastqc.zip`: Zip archive containing the FastQC report, tab-delimited data file and plot images. +The combined files use rclone's one-character status prefixes: -
    +| Prefix | Meaning | Action | +| ------ | ------------------------ | --------------------------------------------------------------------------------------------------------------------------- | +| `=` | File matches | No action required. | +| `-` | Missing from destination | Investigate an incomplete source checksum set or transfer. | +| `+` | Missing from source | Review unexpected destination content. The post-copy check uses `--one-way`, so destination-only files are tolerated there. | +| `*` | Content differs | Re-copy or investigate source/destination mutation. | +| `!` | Read/hash error | Inspect permissions, credentials, connectivity, and the copy log. | -[FastQC](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/) gives general quality metrics about your sequenced reads. It provides information about the quality score distribution across your reads, per base sequence content (%A/T/G/C), adapter contamination and overrepresented sequences. For further reading and documentation see the [FastQC help pages](http://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/). +Empty category files mean that rclone reported no entries in that category. The commands are designed to preserve these reports rather than terminate the whole workflow on comparison differences. Always inspect the reports; workflow success alone is not an integrity guarantee. -### MultiQC +## MultiQC
    Output files - `multiqc/` - - `multiqc_report.html`: a standalone HTML file that can be viewed in your web browser. - - `multiqc_data/`: directory containing parsed statistics from the different tools used in the pipeline. - - `multiqc_plots/`: directory containing static images from the report in various formats. + - `multiqc_report.html`: standalone report viewable in a browser. + - `multiqc_data/`: machine-readable data, logs, source inventory, software versions, and parsed rclone tables.
    -[MultiQC](http://multiqc.info) is a visualization tool that generates a single HTML report summarising all samples in your project. Most of the pipeline QC results are visualised in the report and further statistics are available in the report data directory. +The MultiQC report consolidates: + +- checksum validation status for MD5 and/or SHA-256 manifests; +- post-copy source-to-destination validation status; +- the validated samplesheet and workflow parameter summary; and +- pipeline and tool versions. -Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQC. The pipeline has special steps which also allow the software versions to be reported in the MultiQC output for future traceability. For more information about how to use MultiQC reports, see . +Open `multiqc_report.html` after every run and investigate any non-matching, missing, or error entries. Data under `multiqc_data/` can be retained for automated auditing or downstream reporting; exact filenames may vary with the MultiQC version and the checksum types present in the samplesheet. -### Pipeline information +## Pipeline information
    Output files - `pipeline_info/` - - Reports generated by Nextflow: `execution_report.html`, `execution_timeline.html`, `execution_trace.txt` and `pipeline_dag.dot`/`pipeline_dag.svg`. - - Reports generated by the pipeline: `pipeline_report.html`, `pipeline_report.txt` and `software_versions.yml`. The `pipeline_report*` files will only be present if the `--email` / `--email_on_fail` parameter's are used when running the pipeline. - - Reformatted samplesheet files used as input to the pipeline: `samplesheet.valid.csv`. - - Parameters used by the pipeline run: `params.json`. + - `nf_core_datasync_software_mqc_versions.yml`: versions of the pipeline and tools collected for MultiQC. + - `execution_timeline_.html`: chronological task execution view. + - `execution_report_.html`: task runtime and resource report. + - `execution_trace_.txt`: tabular task-level execution trace. + - `pipeline_dag_.html`: workflow dependency graph. + - Completion reports generated when `--email` or `--email_on_fail` is configured may also be present.
    -[Nextflow](https://www.nextflow.io/docs/latest/tracing.html) provides excellent functionality for generating various reports relevant to the running and execution of the pipeline. This will allow you to troubleshoot errors with the running of the pipeline, and also provide you with other information such as launch commands, run times and resource usage. +These files provide operational provenance and help diagnose performance or failures. Archive them with the MultiQC and rclone reports. The Nextflow `work/` directory and `.nextflow.log` remain in the launch directory rather than `--outdir`; keep them until transfer verification is complete if detailed troubleshooting or `-resume` may be needed. diff --git a/docs/usage.md b/docs/usage.md index 1c85a3e..ca40098 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -2,213 +2,132 @@ ## :warning: Please read this documentation on the nf-core website: [https://nf-co.re/datasync/usage](https://nf-co.re/datasync/usage) -> _Documentation of pipeline parameters is generated automatically from the pipeline schema and can no longer be found in markdown files._ +> Pipeline parameter documentation is generated automatically from [`nextflow_schema.json`](../nextflow_schema.json). This page explains how to prepare a transfer and operate the pipeline. -## Introduction +## Prerequisites - +Install Nextflow 25.10.4 or later and use a supported software profile. Docker or Singularity/Apptainer is recommended for reproducibility. Ensure that the account running Nextflow can read each source and checksum manifest and can write to every destination. + +For cloud or other authenticated rclone remotes, create an [rclone configuration](https://rclone.org/docs/) and pass it with `--rclone_config`. Avoid committing configuration files because they may contain credentials. Native environment credentials and public endpoints can be used without this option when supported by the storage backend. ## Samplesheet input -You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a comma-separated file with 3 columns, and a header row as shown in the examples below. +Supply a comma-separated samplesheet with `--input`: ```bash ---input '[path to samplesheet file]' +--input /path/to/samplesheet.csv ``` -### Multiple runs of the same sample +Each row describes an independent transfer. The header names are fixed; columns may be in any order. + +| Column | Required | Description | +| -------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `sample` | Yes | Unique identifier used in task labels and output report names. It must not contain whitespace. Use a unique value for each row to prevent published report files from colliding. | +| `input` | Yes | Source file or directory. Local paths and HTTP(S) URLs are supported by the copy step; other locations must be addressable in the execution environment. Whitespace is not allowed. | +| `output_path` | Yes | Destination directory understood by rclone, such as `/archive/runs`, `s3://bucket/prefix`, or a configured `remote:path`. Whitespace is not allowed. | +| `checksum_md5` | One checksum column | MD5 sum file (`.csv` or `.tsv`) used to validate `input` before copying. Leave empty when using SHA-256 only. | +| `checksum_sha` | One checksum column | SHA-256 sum file (`.csv` or `.tsv`) used to validate `input` before copying. Leave empty when using MD5 only. | -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: +At least one checksum manifest is required on every row. If both are supplied, both validations run. Checksum files must use the format accepted by [`rclone checksum`](https://rclone.org/commands/rclone_checksum/): one hash and one path per line, with paths relative to the source root. Despite the permitted `.csv`/`.tsv` filename suffix, the contents are checksum-manifest text rather than a table with a header. + +Example: ```csv title="samplesheet.csv" -sample,fastq_1,fastq_2 -CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz -CONTROL_REP1,AEG588A1_S1_L003_R1_001.fastq.gz,AEG588A1_S1_L003_R2_001.fastq.gz -CONTROL_REP1,AEG588A1_S1_L004_R1_001.fastq.gz,AEG588A1_S1_L004_R2_001.fastq.gz +sample,input,output_path,checksum_md5,checksum_sha +run_001,/data/run_001,s3://archive/runs,/data/checksums/run_001_md5.tsv, +reference,https://example.org/reference.fa,/data/references,,/data/checksums/reference_sha256.tsv +run_002,/data/run_002,archive:runs,/data/checksums/run_002_md5.tsv,/data/checksums/run_002_sha256.tsv ``` -### Full samplesheet +An [example samplesheet](../assets/samplesheet.csv) is included in the repository. -The pipeline will auto-detect whether a sample is single- or paired-end using the information provided in the samplesheet. The samplesheet can have as many columns as you desire, however, there is a strict requirement for the first 3 columns to match those defined in the table below. +### Destination layout -A final samplesheet file consisting of both single- and paired-end data may look something like the one below. This is for 6 samples, where `TREATMENT_REP3` has been sequenced twice. +The pipeline preserves the source basename: -```csv title="samplesheet.csv" -sample,fastq_1,fastq_2 -CONTROL_REP1,AEG588A1_S1_L002_R1_001.fastq.gz,AEG588A1_S1_L002_R2_001.fastq.gz -CONTROL_REP2,AEG588A2_S2_L002_R1_001.fastq.gz,AEG588A2_S2_L002_R2_001.fastq.gz -CONTROL_REP3,AEG588A3_S3_L002_R1_001.fastq.gz,AEG588A3_S3_L002_R2_001.fastq.gz -TREATMENT_REP1,AEG588A4_S4_L003_R1_001.fastq.gz, -TREATMENT_REP2,AEG588A5_S5_L003_R1_001.fastq.gz, -TREATMENT_REP3,AEG588A6_S6_L003_R1_001.fastq.gz, -TREATMENT_REP3,AEG588A6_S6_L004_R1_001.fastq.gz, -``` - -| Column | Description | -| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `sample` | 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 (`_`). | -| `fastq_1` | Full 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` | Full path to FastQ file for Illumina short reads 2. File has to be gzipped and have the extension ".fastq.gz" or ".fq.gz". | +- for a file source, rclone copies the file into `output_path`, and validation expects `output_path/`; +- for a directory source, the pipeline appends the source directory name, so `/data/run_001` with `output_path=/archive/runs` is copied and checked at `/archive/runs/run_001`. -An [example samplesheet](../assets/samplesheet.csv) has been provided with the pipeline. +A trailing slash on `output_path` is removed before these paths are constructed. Ensure that a destination does not already contain unrelated files: post-copy validation uses `rclone check --one-way`, which checks that source content exists and matches at the destination while tolerating destination-only files. ## Running the pipeline -The typical command for running the pipeline is as follows: +A typical local-to-cloud run is: ```bash -nextflow run nf-core/datasync --input ./samplesheet.csv --outdir ./results --genome GRCh37 -profile docker +nextflow run nf-core/datasync \ + -r \ + -profile docker \ + --input /data/samplesheet.csv \ + --outdir /data/datasync-results \ + --rclone_config /secure/rclone.conf ``` -This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. +`--outdir` stores logs, integrity reports, MultiQC, and execution metadata. It does **not** override the transfer destinations in the samplesheet. -Note that the pipeline will create the following files in your working directory: +To inspect the proposed copy without writing destination data: ```bash -work # Directory containing the nextflow working files - # Finished results in specified location (defined with --outdir) -.nextflow_log # Log file from Nextflow -# Other nextflow hidden files, eg. history of pipeline runs and old logs. +nextflow run nf-core/datasync \ + -r \ + -profile docker \ + --input /data/samplesheet.csv \ + --outdir /data/datasync-dry-run \ + --rclone_config /secure/rclone.conf \ + --rclone_dry_run ``` -If you wish to repeatedly use the same parameters for multiple runs, rather than specifying each flag in the command, you can specify these in a params file. - -Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. +The checksum and post-copy check stages still run during a dry run. Consequently, post-copy results reflect whatever was already present at the destination rather than a simulated final state. -> [!WARNING] -> Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/running/run-pipelines#configuring-pipelines), other infrastructural tweaks (such as output directories), or module arguments (args). +### Parameter files -The above pipeline run specified with a params file in yaml format: - -```bash -nextflow run nf-core/datasync -profile docker -params-file params.yaml -``` - -with: +Frequently reused settings can be stored in YAML or JSON and loaded with `-params-file`: ```yaml title="params.yaml" -input: './samplesheet.csv' -outdir: './results/' -genome: 'GRCh37' -<...> +input: /data/samplesheet.csv +outdir: /data/datasync-results +rclone_config: /secure/rclone.conf +multiqc_title: July archive transfer ``` -You can also generate such `YAML`/`JSON` files via [nf-core/launch](https://nf-co.re/launch). - -### Updating the pipeline - -When you run the above command, Nextflow automatically pulls the pipeline code from GitHub and stores it as a cached version. When running the pipeline after this, it will always use the cached version if available - even if the pipeline has been updated since. To make sure that you're running the latest version of the pipeline, make sure that you regularly update the cached version of the pipeline: - ```bash -nextflow pull nf-core/datasync +nextflow run nf-core/datasync -r -profile docker -params-file params.yaml ``` -### Reproducibility - -It is a good idea to specify the pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. - -First, go to the [nf-core/datasync releases page](https://github.com/nf-core/datasync/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. - -This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. - -To further assist in reproducibility, you can use share and reuse [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. - -> [!TIP] -> If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. - -## Core Nextflow arguments - -> [!NOTE] -> These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen) - -### `-profile` - -Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. - -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. +Do not use `-c` for pipeline parameters. Use it only for Nextflow executor, resources, and other infrastructure configuration. -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). +## Understanding completion and integrity -Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! -They are loaded in sequence, so later profiles can overwrite earlier profiles. +For each row, the pipeline first validates supplied checksum manifests, performs the copy, and then compares source and destination. Rclone comparison commands write status reports even when differences are found, allowing all results to be collected in MultiQC. Therefore, a successful Nextflow run means the workflow completed; it does **not by itself** prove every object matched. Review `multiqc/multiqc_report.html` and the reports under `rclone/`, especially lines marked `-`, `+`, `*`, or `!` (see [output documentation](output.md)). -If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer environment. +## Resuming and reproducibility -- `test` - - A profile with a complete configuration for automated testing - - Includes links to test data so needs no other parameters -- `docker` - - A generic configuration profile to be used with [Docker](https://docker.com/) -- `singularity` - - A generic configuration profile to be used with [Singularity](https://sylabs.io/docs/) -- `podman` - - A generic configuration profile to be used with [Podman](https://podman.io/) -- `shifter` - - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) -- `charliecloud` - - A generic configuration profile to be used with [Charliecloud](https://charliecloud.io/) -- `apptainer` - - 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. +Pin a released pipeline version with `-r` and record the samplesheet, parameter file, rclone configuration provenance (without exposing secrets), and generated `pipeline_info/` directory. To restart an interrupted run with unchanged inputs and parameters, add `-resume`: -### `-resume` - -Specify this when restarting a pipeline. Nextflow will use cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. For input to be considered the same, not only the names must be identical but the files' contents as well. For more info about this parameter, see [this blog post](https://www.nextflow.io/blog/2019/demystifying-nextflow-resume.html). - -You can also supply a run name to resume a specific run: `-resume [run-name]`. Use the `nextflow log` command to show previous run names. - -### `-c` - -Specify the path to a specific config file (this is a core Nextflow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information. - -## Custom configuration - -### Resource requests - -Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the pipeline steps, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher resources request (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. - -To change the resource requests, please see the [max resources](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#set-max-resources) and [customise process resources](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#customize-process-resources) section of the nf-core website. - -### Custom Containers - -In some cases, you may wish to change the container or conda environment used by a pipeline steps for a particular tool. By default, nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However, in some cases the pipeline specified version maybe out of date. - -To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#update-tool-versions) section of the nf-core website. - -### Custom Tool Arguments - -A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. - -To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#modifying-tool-arguments) section of the nf-core website. - -### nf-core/configs - -In most cases, you will only need to create a custom config as a one-off but if you and others within your organisation are likely to be running nf-core pipelines regularly and need to use the same settings regularly it may be a good idea to request that your custom config file is uploaded to the `nf-core/configs` git repository. Before you do this please can you test that the config file works with your pipeline of choice using the `-c` parameter. You can then create a pull request to the `nf-core/configs` repository with the addition of your config file, associated documentation file (see examples in [`nf-core/configs/docs`](https://github.com/nf-core/configs/tree/master/docs)), and amending [`nfcore_custom.config`](https://github.com/nf-core/configs/blob/master/nfcore_custom.config) to include your custom profile. - -See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for more information about creating your own configuration files. - -If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). - -## Running in the background +```bash +nextflow run nf-core/datasync -r -profile docker -params-file params.yaml -resume +``` -Nextflow handles job submissions and supervises the running jobs. The Nextflow process must run until the pipeline is finished. +Nextflow may reuse completed tasks from its work directory. Before retrying a partial transfer, confirm the destination contents are acceptable; rclone copy skips identical files but may update changed ones. -The Nextflow `-bg` flag launches Nextflow in the background, detached from your terminal so that the workflow does not stop if you log out of your session. The logs are saved to a file. +Update the locally cached pipeline when intentionally moving to a newer release: -Alternatively, you can use `screen` / `tmux` or similar tool to create a detached session which you can log back into at a later time. -Some HPC setups also allow you to run nextflow within a cluster job submitted your job scheduler (from where it submits more jobs). +```bash +nextflow pull nf-core/datasync +``` -## Nextflow memory requirements +## Resource configuration -In some cases, the Nextflow Java virtual machines can start to request a large amount of memory. -We recommend adding the following line to your environment to limit this (typically in `~/.bashrc` or `~./bash_profile`): +The rclone processes use the `process_low` label. Configure executors and override CPU, memory, or time in a Nextflow config, for example: -```bash -NXF_OPTS='-Xms1g -Xmx4g' +```groovy title="resources.config" +process { + withLabel: process_low { + cpus = 8 + memory = '16 GB' + time = '12h' + } +} ``` + +Run with `-c resources.config`. Rclone derives its checker count from allocated CPUs, and the copy step uses roughly half that count (minimum one) for parallel transfers. From 447fa1466d9f6cda13af1f2896dbcb02bb5e0064 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 17 Jul 2026 17:58:40 -0300 Subject: [PATCH 161/334] docs: expand rclone remote configuration guidance --- README.md | 4 +-- docs/output.md | 2 ++ docs/usage.md | 90 +++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c899b6e..7a53bb8 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ 3. compares the copied data with the source using `rclone check`; and 4. produces detailed rclone status files and a consolidated MultiQC report. -Sources may be local paths or HTTP(S) URLs. Destinations can be local paths or rclone-supported remote storage (for example S3 or Azure Blob Storage); authenticated remotes can be defined with `--rclone_config`. +Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers. ```mermaid graph LR @@ -66,7 +66,7 @@ nextflow run nf-core/datasync \ --rclone_config /path/to/rclone.conf ``` -`--rclone_config` is optional when all paths are accessible without an rclone remote configuration. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination. +`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [rclone configuration section](docs/usage.md#configuring-rclone-remotes) for S3 and Azure examples. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination. > [!WARNING] > Provide pipeline parameters on the command line or with Nextflow's `-params-file` option. Do not put pipeline parameters in a configuration supplied with `-c`; custom configuration files are intended for executor and resource settings. diff --git a/docs/output.md b/docs/output.md index 50ea1e3..9a76161 100644 --- a/docs/output.md +++ b/docs/output.md @@ -98,3 +98,5 @@ Open `multiqc_report.html` after every run and investigate any non-matching, mis
    These files provide operational provenance and help diagnose performance or failures. Archive them with the MultiQC and rclone reports. The Nextflow `work/` directory and `.nextflow.log` remain in the launch directory rather than `--outdir`; keep them until transfer verification is complete if detailed troubleshooting or `-resume` may be needed. + +The supplied rclone configuration is an input credential file and is not intentionally copied to `--outdir`. Nevertheless, execution logs may contain remote names and object paths. Review logs before sharing them, and manage `rclone.conf` separately as a secret. diff --git a/docs/usage.md b/docs/usage.md index ca40098..b6d622f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -8,7 +8,7 @@ Install Nextflow 25.10.4 or later and use a supported software profile. Docker or Singularity/Apptainer is recommended for reproducibility. Ensure that the account running Nextflow can read each source and checksum manifest and can write to every destination. -For cloud or other authenticated rclone remotes, create an [rclone configuration](https://rclone.org/docs/) and pass it with `--rclone_config`. Avoid committing configuration files because they may contain credentials. Native environment credentials and public endpoints can be used without this option when supported by the storage backend. +For cloud or other authenticated rclone remotes, create an [rclone configuration](https://rclone.org/docs/) and pass it with `--rclone_config`. The configuration applies to remote **sources and destinations**. For example, the pipeline can copy from S3 to a local directory, from Azure Blob Storage to S3, or between two separately configured S3-compatible providers. ## Samplesheet input @@ -20,13 +20,13 @@ Supply a comma-separated samplesheet with `--input`: Each row describes an independent transfer. The header names are fixed; columns may be in any order. -| Column | Required | Description | -| -------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `sample` | Yes | Unique identifier used in task labels and output report names. It must not contain whitespace. Use a unique value for each row to prevent published report files from colliding. | -| `input` | Yes | Source file or directory. Local paths and HTTP(S) URLs are supported by the copy step; other locations must be addressable in the execution environment. Whitespace is not allowed. | -| `output_path` | Yes | Destination directory understood by rclone, such as `/archive/runs`, `s3://bucket/prefix`, or a configured `remote:path`. Whitespace is not allowed. | -| `checksum_md5` | One checksum column | MD5 sum file (`.csv` or `.tsv`) used to validate `input` before copying. Leave empty when using SHA-256 only. | -| `checksum_sha` | One checksum column | SHA-256 sum file (`.csv` or `.tsv`) used to validate `input` before copying. Leave empty when using MD5 only. | +| Column | Required | Description | +| -------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `sample` | Yes | Unique identifier used in task labels and output report names. It must not contain whitespace. Use a unique value for each row to prevent published report files from colliding. | +| `input` | Yes | Source file or directory. This can be a local path, HTTP(S) URL, object-storage URL such as `s3://bucket/prefix`, or configured remote such as `source_s3:bucket/prefix` or `source_azure:container/prefix`. Whitespace is not allowed. | +| `output_path` | Yes | Destination directory understood by rclone, such as `/archive/runs`, `s3://bucket/prefix`, or a configured `remote:path`. Whitespace is not allowed. | +| `checksum_md5` | One checksum column | MD5 sum file (`.csv` or `.tsv`) used to validate `input` before copying. Leave empty when using SHA-256 only. | +| `checksum_sha` | One checksum column | SHA-256 sum file (`.csv` or `.tsv`) used to validate `input` before copying. Leave empty when using MD5 only. | At least one checksum manifest is required on every row. If both are supplied, both validations run. Checksum files must use the format accepted by [`rclone checksum`](https://rclone.org/commands/rclone_checksum/): one hash and one path per line, with paths relative to the source root. Despite the permitted `.csv`/`.tsv` filename suffix, the contents are checksum-manifest text rather than a table with a header. @@ -41,7 +41,79 @@ run_002,/data/run_002,archive:runs,/data/checksums/run_002_md5.tsv,/data/checksu An [example samplesheet](../assets/samplesheet.csv) is included in the repository. -### Destination layout +## Configuring rclone remotes + +The file supplied with `--rclone_config` uses rclone's INI-style format. Each `[name]` section defines a remote, and samplesheet paths refer to it as `name:path`. The remote name is an arbitrary local label; it does not need to match the provider or bucket name. One file may contain several sections, so a cloud-to-cloud transfer can define both providers in the same file: + +```text +source_s3:incoming/run_001 +archive_azure:research-archive/run_001 +``` + +Create the file interactively where possible: + +```bash +rclone config --config /secure/rclone.conf +rclone listremotes --config /secure/rclone.conf +``` + +Then provide that exact file to the pipeline: + +```bash +nextflow run nf-core/datasync \ + -profile docker \ + --input samplesheet.csv \ + --outdir results \ + --rclone_config /secure/rclone.conf +``` + +### S3 and S3-compatible storage + +An S3 remote specifies the provider, region, and credentials. S3-compatible services commonly also require their service endpoint. For example: + +```ini title="rclone.conf" +[source_s3] +type = s3 +provider = AWS +access_key_id = YOUR_ACCESS_KEY_ID +secret_access_key = YOUR_SECRET_ACCESS_KEY +region = eu-central-1 + +[institutional_s3] +type = s3 +provider = Other +access_key_id = YOUR_ACCESS_KEY_ID +secret_access_key = YOUR_SECRET_ACCESS_KEY +endpoint = https://objects.example.org +region = us-east-1 +``` + +The corresponding input values could be `source_s3:incoming/run_001` and `institutional_s3:project/run_002`. Provider-specific settings vary: consult the [rclone S3 documentation](https://rclone.org/s3/) and your storage provider's endpoint, region, addressing-style, and credential documentation rather than copying example values unchanged. + +The pipeline also accepts an `s3://bucket/path` source or destination. In that form, ensure credentials and provider settings are available to both Nextflow and rclone in the execution environment. A named remote such as `source_s3:bucket/path` makes the selected configuration section explicit and is preferable when a config file contains multiple S3 providers. + +### Azure Blob Storage + +An Azure remote can use a storage account and key, a SAS URL, managed identity, or another authentication method supported by rclone. A storage-account-key example is: + +```ini title="rclone.conf" +[archive_azure] +type = azureblob +account = YOUR_STORAGE_ACCOUNT +key = YOUR_STORAGE_ACCOUNT_KEY +``` + +A destination can then use `archive_azure:container/path`. See the [rclone Azure Blob Storage documentation](https://rclone.org/azureblob/) to select the authentication method appropriate for the execution environment. Prefer short-lived credentials, managed identity, or narrowly scoped SAS tokens over long-lived account keys where possible. + +### Credential handling and validation + +- Do not commit `rclone.conf`, add it to container images, or include its contents in support requests. It often contains plaintext credentials or reusable tokens. +- Restrict access, for example with `chmod 600 /secure/rclone.conf`, and inject the file through your workflow platform's secret-management facility where available. +- Use distinct, least-privilege credentials for each provider. A source generally needs list/read access, while a destination needs list/read/write access for copying and post-copy validation. +- Test each configured remote before launching the pipeline, for example with `rclone lsd source_s3:bucket --config /secure/rclone.conf`. Use a harmless test prefix before operating on production data. +- Rotate any example or real credential that is accidentally exposed. The placeholder values above are not usable credentials. + +## Destination layout The pipeline preserves the source basename: From 0506dc7a45cf5616b1f33e5730942530482a7300 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:41:36 +0000 Subject: [PATCH 162/334] add edge test cases --- tests/edge.nf.test | 36 +++++++++++++++ tests/edge.nf.test.snap | 99 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 tests/edge.nf.test create mode 100644 tests/edge.nf.test.snap diff --git a/tests/edge.nf.test b/tests/edge.nf.test new file mode 100644 index 0000000..d69a8f8 --- /dev/null +++ b/tests/edge.nf.test @@ -0,0 +1,36 @@ +nextflow_pipeline { + + name "Test pipeline edge cases" + script "../main.nf" + tag "pipeline" + tag "edge" + profile "test" + + test("-profile test edge cases") { + + when { + params { + input = "https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/test-data/samplesheet_edge.csv" + outdir = "$outputDir" + } + } + + then { + // stable_path: All files + folders in ${params.outdir}/ with a stable path (including file name) + def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_content: All files in ${params.outdir}/ with stable content + def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + assert workflow.success + assertAll( + { assert snapshot( + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_path, + // All files with stable contents + stable_content + ).match() } + ) + } + } +} diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap new file mode 100644 index 0000000..e43ee05 --- /dev/null +++ b/tests/edge.nf.test.snap @@ -0,0 +1,99 @@ +{ + "-profile test edge cases": { + "content": [ + { + "RCLONE_CHECK": { + "rclone": "1.74.3-DEV" + }, + "RCLONE_CHECKSUM": { + "rclone": "1.74.3-DEV" + }, + "RCLONE_COPY": { + "rclone": "1.65.0-DEV" + }, + "Workflow": { + "nf-core/datasync": "v1.0dev" + } + }, + [ + "multiqc", + "multiqc/multiqc_data", + "multiqc/multiqc_data/llms-full.txt", + "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc.parquet", + "multiqc/multiqc_data/multiqc_citations.txt", + "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_rclone_check.txt", + "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", + "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", + "multiqc/multiqc_data/multiqc_samplesheet.txt", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_datasync_software_mqc_versions.yml", + "rclone", + "rclone/check", + "rclone/check/Illumina_annotation_incorrect", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.differ.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.error.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.missing_on_dst.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.missing_on_src.txt", + "rclone/check/Illumina_annotation_missing", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.differ.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.error.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_src.txt", + "rclone/check/Illumina_annotation_sha_only", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.error.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.match.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.missing_on_dst.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.missing_on_src.txt", + "rclone/checksum", + "rclone/checksum/Illumina_annotation_incorrect", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.differ.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.error.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.missing_on_dst.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.missing_on_src.txt", + "rclone/checksum/Illumina_annotation_missing", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.differ.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.error.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_src.txt", + "rclone/checksum/Illumina_annotation_sha_only", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.error.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.match.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.missing_on_dst.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.missing_on_src.txt", + "rclone/copy", + "rclone/copy/Illumina_annotation_incorrect-rclone-copy.log", + "rclone/copy/Illumina_annotation_missing-rclone-copy.log", + "rclone/copy/Illumina_annotation_sha_only-rclone-copy.log" + ], + [ + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "multiqc_rclone_check.txt:md5,df42d80150a8a1f2da93c5eed053dc3f", + "multiqc_rclone_checksum_md5.txt:md5,679b4cda086bfacf50fe3ec5b22dd386", + "multiqc_rclone_checksum_sha.txt:md5,9ba162249102c1b0af4464411b3a7eb5", + "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" + ] + ], + "timestamp": "2026-07-20T14:40:38.905083297", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + } +} \ No newline at end of file From 4b9c262eb7095f47b38d5e29f1045b202bc8d781 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:43:24 +0000 Subject: [PATCH 163/334] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6704c6c..01faa82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` +- [[#57](https://github.com/nf-core/datasync/pull/57)] - Add nf-tests with edge cases([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#55](https://github.com/nf-core/datasync/pull/55)] - Add subdirectories with sample id to results. Improvements to MultiQC report (width of columns, sections and sub-section headers)colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#54](https://github.com/nf-core/datasync/pull/54)] - Add colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). From 1946fbea9acf3b34c7be43cd71b5203a81d047bd Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 21 Jul 2026 13:03:37 -0300 Subject: [PATCH 164/334] docs: clarify tested rclone configuration scope --- README.md | 4 ++-- docs/usage.md | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7a53bb8..d6d97f4 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ 3. compares the copied data with the source using `rclone check`; and 4. produces detailed rclone status files and a consolidated MultiQC report. -Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers. +Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). ```mermaid graph LR @@ -66,7 +66,7 @@ nextflow run nf-core/datasync \ --rclone_config /path/to/rclone.conf ``` -`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [rclone configuration section](docs/usage.md#configuring-rclone-remotes) for S3 and Azure examples. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination. +`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [rclone configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination. > [!WARNING] > Provide pipeline parameters on the command line or with Nextflow's `-params-file` option. Do not put pipeline parameters in a configuration supplied with `-c`; custom configuration files are intended for executor and resource settings. diff --git a/docs/usage.md b/docs/usage.md index b6d622f..da77337 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -8,7 +8,7 @@ Install Nextflow 25.10.4 or later and use a supported software profile. Docker or Singularity/Apptainer is recommended for reproducibility. Ensure that the account running Nextflow can read each source and checksum manifest and can write to every destination. -For cloud or other authenticated rclone remotes, create an [rclone configuration](https://rclone.org/docs/) and pass it with `--rclone_config`. The configuration applies to remote **sources and destinations**. For example, the pipeline can copy from S3 to a local directory, from Azure Blob Storage to S3, or between two separately configured S3-compatible providers. +For cloud or other authenticated rclone remotes, create an [rclone configuration](https://rclone.org/docs/) and pass it with `--rclone_config`. The configuration applies to remote **sources and destinations**. The pipeline has currently been tested for transfers between S3 buckets. Other rclone-supported layouts, such as Azure Blob Storage to S3 or transfers between S3-compatible providers, should be configured and validated against the upstream rclone documentation for each provider before use. ## Samplesheet input @@ -43,7 +43,7 @@ An [example samplesheet](../assets/samplesheet.csv) is included in the repositor ## Configuring rclone remotes -The file supplied with `--rclone_config` uses rclone's INI-style format. Each `[name]` section defines a remote, and samplesheet paths refer to it as `name:path`. The remote name is an arbitrary local label; it does not need to match the provider or bucket name. One file may contain several sections, so a cloud-to-cloud transfer can define both providers in the same file: +The file supplied with `--rclone_config` uses rclone's INI-style format. Each `[name]` section defines a remote, and samplesheet paths refer to it as `name:path`. The remote name is an arbitrary local label; it does not need to match the provider or bucket name. The pipeline's documented and tested configuration pattern is S3-to-S3 transfer. One file may contain several sections, so other cloud-to-cloud transfers can define both providers in the same file, but provider-specific options should be taken from the relevant rclone documentation rather than inferred from the S3 example: ```text source_s3:incoming/run_001 @@ -69,7 +69,7 @@ nextflow run nf-core/datasync \ ### S3 and S3-compatible storage -An S3 remote specifies the provider, region, and credentials. S3-compatible services commonly also require their service endpoint. For example: +The main use case tested for nf-core/datasync is transferring files between S3 buckets. An S3 remote specifies the provider, region, and credentials. S3-compatible services commonly also require their service endpoint. For example: ```ini title="rclone.conf" [source_s3] @@ -103,7 +103,7 @@ account = YOUR_STORAGE_ACCOUNT key = YOUR_STORAGE_ACCOUNT_KEY ``` -A destination can then use `archive_azure:container/path`. See the [rclone Azure Blob Storage documentation](https://rclone.org/azureblob/) to select the authentication method appropriate for the execution environment. Prefer short-lived credentials, managed identity, or narrowly scoped SAS tokens over long-lived account keys where possible. +A destination can then use `archive_azure:container/path`. Azure and other non-S3 providers are examples of rclone-supported use cases, but they are not the primary tested configuration for this pipeline. See the [rclone Azure Blob Storage documentation](https://rclone.org/azureblob/) to select the authentication method appropriate for the execution environment, and validate the configuration with rclone before launching nf-core/datasync. Prefer short-lived credentials, managed identity, or narrowly scoped SAS tokens over long-lived account keys where possible. ### Credential handling and validation From be56cb87ad0b6d951e22d8e6d91f440d195fc39a Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 15:05:09 -0300 Subject: [PATCH 165/334] Update README.md --- README.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d6d97f4..c762965 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,8 @@ Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). -```mermaid -graph LR - A[Samplesheet] --> B[Validate supplied checksums] - A --> C[Copy with rclone] - C --> D[Compare source and destination] - B --> E[MultiQC integrity report] - D --> E -``` +metromap_style_pipeline_workflow_components drawio + ## Quick start @@ -51,7 +45,7 @@ Create a samplesheet containing one transfer per row: ```csv sample,input,output_path,checksum_md5,checksum_sha -run_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv, +run_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv reference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv ``` @@ -68,8 +62,6 @@ nextflow run nf-core/datasync \ `--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [rclone configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination. -> [!WARNING] -> Provide pipeline parameters on the command line or with Nextflow's `-params-file` option. Do not put pipeline parameters in a configuration supplied with `-c`; custom configuration files are intended for executor and resource settings. See the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters). From ca5f1926f6e9aa19367c3ef3e3bd9410ed7e8ed6 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 15:17:06 -0300 Subject: [PATCH 166/334] Update usage.md --- docs/usage.md | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index da77337..91dd2f0 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -34,7 +34,7 @@ Example: ```csv title="samplesheet.csv" sample,input,output_path,checksum_md5,checksum_sha -run_001,/data/run_001,s3://archive/runs,/data/checksums/run_001_md5.tsv, +run_001,/data/run_001,s3://archive/runs,/data/checksums/run_001_md5.tsv reference,https://example.org/reference.fa,/data/references,,/data/checksums/reference_sha256.tsv run_002,/data/run_002,archive:runs,/data/checksums/run_002_md5.tsv,/data/checksums/run_002_sha256.tsv ``` @@ -69,50 +69,21 @@ nextflow run nf-core/datasync \ ### S3 and S3-compatible storage -The main use case tested for nf-core/datasync is transferring files between S3 buckets. An S3 remote specifies the provider, region, and credentials. S3-compatible services commonly also require their service endpoint. For example: +The main use case tested for nf-core/datasync is transferring files between S3 buckets. An S3 remote specifies the provider, region, and credentials. For example: ```ini title="rclone.conf" -[source_s3] +[s3] type = s3 provider = AWS access_key_id = YOUR_ACCESS_KEY_ID secret_access_key = YOUR_SECRET_ACCESS_KEY region = eu-central-1 - -[institutional_s3] -type = s3 -provider = Other -access_key_id = YOUR_ACCESS_KEY_ID -secret_access_key = YOUR_SECRET_ACCESS_KEY -endpoint = https://objects.example.org -region = us-east-1 ``` The corresponding input values could be `source_s3:incoming/run_001` and `institutional_s3:project/run_002`. Provider-specific settings vary: consult the [rclone S3 documentation](https://rclone.org/s3/) and your storage provider's endpoint, region, addressing-style, and credential documentation rather than copying example values unchanged. The pipeline also accepts an `s3://bucket/path` source or destination. In that form, ensure credentials and provider settings are available to both Nextflow and rclone in the execution environment. A named remote such as `source_s3:bucket/path` makes the selected configuration section explicit and is preferable when a config file contains multiple S3 providers. -### Azure Blob Storage - -An Azure remote can use a storage account and key, a SAS URL, managed identity, or another authentication method supported by rclone. A storage-account-key example is: - -```ini title="rclone.conf" -[archive_azure] -type = azureblob -account = YOUR_STORAGE_ACCOUNT -key = YOUR_STORAGE_ACCOUNT_KEY -``` - -A destination can then use `archive_azure:container/path`. Azure and other non-S3 providers are examples of rclone-supported use cases, but they are not the primary tested configuration for this pipeline. See the [rclone Azure Blob Storage documentation](https://rclone.org/azureblob/) to select the authentication method appropriate for the execution environment, and validate the configuration with rclone before launching nf-core/datasync. Prefer short-lived credentials, managed identity, or narrowly scoped SAS tokens over long-lived account keys where possible. - -### Credential handling and validation - -- Do not commit `rclone.conf`, add it to container images, or include its contents in support requests. It often contains plaintext credentials or reusable tokens. -- Restrict access, for example with `chmod 600 /secure/rclone.conf`, and inject the file through your workflow platform's secret-management facility where available. -- Use distinct, least-privilege credentials for each provider. A source generally needs list/read access, while a destination needs list/read/write access for copying and post-copy validation. -- Test each configured remote before launching the pipeline, for example with `rclone lsd source_s3:bucket --config /secure/rclone.conf`. Use a harmless test prefix before operating on production data. -- Rotate any example or real credential that is accidentally exposed. The placeholder values above are not usable credentials. - ## Destination layout The pipeline preserves the source basename: From ceb7d63f97e1dc05f6131d762cbe5b96a617f228 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 15:20:46 -0300 Subject: [PATCH 167/334] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b9f2c2..b9d5e86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#46](https://github.com/nf-core/datasync/pull/46)] - Import Rclone module from nf-core([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#41](https://github.com/nf-core/datasync/pull/41)] - Generate MultiQC Report with comparechecksum tables and input samplesheet ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#49](https://github.com/nf-core/datasync/pull/49)] - Install `RCLONE_CHECK` and `RCLONE_CHECKSUM` modules from nf-core ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). +- [[#59](https://github.com/nf-core/datasync/pull/59)] - Create pipeline documentation ([@antoniasaracco](https://github.com/antoniasaracco), review by [@atrigila](https://github.com/atrigila) and [@delfiterradas](https://github.com/delfiterradas)). + ### `Fixed` From f10bc2cadc88b814c896f6ef32c67eed9b2d4d3c Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 15:26:19 -0300 Subject: [PATCH 168/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c762965..e60ff31 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). -metromap_style_pipeline_workflow_components drawio +metromap_style_pipeline_workflow_components drawio (1) ## Quick start From c0cb403a90e47ffd9c243b94b944cd6ffc49167a Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 15:26:55 -0300 Subject: [PATCH 169/334] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9d5e86..e83434b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,6 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#49](https://github.com/nf-core/datasync/pull/49)] - Install `RCLONE_CHECK` and `RCLONE_CHECKSUM` modules from nf-core ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#59](https://github.com/nf-core/datasync/pull/59)] - Create pipeline documentation ([@antoniasaracco](https://github.com/antoniasaracco), review by [@atrigila](https://github.com/atrigila) and [@delfiterradas](https://github.com/delfiterradas)). - ### `Fixed` ### `Dependencies` From 7dea7d83fd21eaf2e4b026f495e9454eb57d9f63 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 15:27:32 -0300 Subject: [PATCH 170/334] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index e60ff31..c2cc376 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,6 @@ Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported r metromap_style_pipeline_workflow_components drawio (1) - ## Quick start > [!NOTE] @@ -62,7 +61,6 @@ nextflow run nf-core/datasync \ `--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [rclone configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination. - See the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters). ## Pipeline output From 6ff877415b59d41a70a8c9c47780807bf186f4cc Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 15:47:01 -0300 Subject: [PATCH 171/334] Update output.md --- docs/output.md | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/docs/output.md b/docs/output.md index 9a76161..e6de4ae 100644 --- a/docs/output.md +++ b/docs/output.md @@ -12,13 +12,24 @@ This document describes the reports produced by nf-core/datasync. Paths below ar ```text / ├── rclone/ -│ ├── -rclone-copy.log -│ ├── .combined.txt -│ ├── .match.txt -│ ├── .differ.txt -│ ├── .missing_on_dst.txt -│ ├── .missing_on_src.txt -│ └── .error.txt +│ ├── copy/ +│ │ └── -rclone-copy.log +│ ├── checksum/ +│ │ └── / +│ │ ├── .combined.txt +│ │ ├── .match.txt +│ │ ├── .differ.txt +│ │ ├── .missing_on_dst.txt +│ │ ├── .missing_on_src.txt +│ │ └── .error.txt +│ └── check/ +│ └── / +│ ├── .combined.txt +│ ├── .match.txt +│ ├── .differ.txt +│ ├── .missing_on_dst.txt +│ ├── .missing_on_src.txt +│ └── .error.txt ├── multiqc/ │ ├── multiqc_report.html │ └── multiqc_data/ @@ -27,26 +38,36 @@ This document describes the reports produced by nf-core/datasync. Paths below ar └── execution_* / pipeline_dag_* ``` +The `rclone/` directory is split by module stage. Copy logs are published to `rclone/copy/`, pre-copy checksum validation reports are published to `rclone/checksum//`, and post-copy source-to-destination comparison reports are published to `rclone/check//`. The `` directory name is taken from the `sample` value in the samplesheet row. + ## Rclone transfer and integrity reports
    Output files -- `rclone/` +- `rclone/copy/` - `-rclone-copy.log`: informational log from the copy operation. - - `.combined.txt`: combined comparison status, one path per line. - - `.match.txt`: paths whose content matched (`=`). +- `rclone/checksum//` + - `.combined.txt`: combined pre-copy checksum-validation status, one path per line. + - `.match.txt`: paths whose content matched the supplied checksum manifest (`=`). + - `.differ.txt`: paths present in the source and manifest but with different content (`*`). + - `.missing_on_dst.txt`: paths present in the checksum manifest but absent from the checked source (`-`). + - `.missing_on_src.txt`: paths present in the checked source but absent from the checksum manifest (`+`). + - `.error.txt`: paths that could not be read or hashed (`!`). +- `rclone/check//` + - `.combined.txt`: combined post-copy source-to-destination comparison status, one path per line. + - `.match.txt`: paths whose content matched between source and destination (`=`). - `.differ.txt`: paths present on both sides but with different content (`*`). - - `.missing_on_dst.txt`: paths found in the source or manifest but absent from the checked data (`-`). - - `.missing_on_src.txt`: paths found in the checked data but absent from the source or manifest (`+`). + - `.missing_on_dst.txt`: paths found in the source but absent from the destination (`-`). + - `.missing_on_src.txt`: paths found at the destination but absent from the source (`+`). - `.error.txt`: paths that could not be read or hashed (`!`).
    Two integrity stages create reports: -1. **Pre-copy checksum validation** uses each supplied MD5 and/or SHA-256 manifest to check the source. -2. **Post-copy validation** compares the source with the destination after the copy task finishes. +1. **Pre-copy checksum validation** uses each supplied MD5 and/or SHA-256 manifest to check the source and publishes reports under `rclone/checksum//`. +2. **Post-copy validation** compares the source with the destination after the copy task finishes and publishes reports under `rclone/check//`. Both stages use the same `.*.txt` naming convention and publish to `rclone/`. When a row supplies a checksum manifest, similarly named pre-copy and post-copy files may target the same published path; use the consolidated MultiQC sections for the stage-specific summary and retain the Nextflow work directory if both raw report sets must be audited independently. From 790a648ff040eaeb93919d417ef2205b2ca09304 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Wed, 22 Jul 2026 19:45:55 +0000 Subject: [PATCH 172/334] Update rclone modules and inputs in workflow --- conf/modules.config | 7 + modules.json | 6 +- modules/nf-core/rclone/check/main.nf | 17 ++- modules/nf-core/rclone/check/meta.yml | 44 ++++-- .../nf-core/rclone/check/tests/main.nf.test | 29 ++-- .../rclone/check/tests/main.nf.test.snap | 93 +++++------- .../rclone/check/tests/nextflow.config | 7 + modules/nf-core/rclone/checksum/main.nf | 14 +- modules/nf-core/rclone/checksum/meta.yml | 49 ++++-- .../rclone/checksum/tests/main.nf.test | 45 ++---- .../rclone/checksum/tests/main.nf.test.snap | 142 +++--------------- .../rclone/checksum/tests/nextflow.config | 7 + .../nf-core/rclone/copy/tests/main.nf.test | 4 +- workflows/datasync.nf | 16 +- 14 files changed, 227 insertions(+), 253 deletions(-) create mode 100644 modules/nf-core/rclone/check/tests/nextflow.config create mode 100644 modules/nf-core/rclone/checksum/tests/nextflow.config diff --git a/conf/modules.config b/conf/modules.config index 32a6697..3a376b6 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -56,6 +56,13 @@ process { } withName: 'RCLONE_CHECKSUM' { + ext.args = { + def base_args = [ + '--no-check-certificate', + "--one-way" + ] + base_args.join(' ') + } publishDir = [ path: { "${params.outdir}/rclone/checksum/${meta.id}" }, mode: params.publish_dir_mode, diff --git a/modules.json b/modules.json index 36c8de3..66e3022 100644 --- a/modules.json +++ b/modules.json @@ -12,17 +12,17 @@ }, "rclone/check": { "branch": "master", - "git_sha": "0983b1ef5f0729946953d921100af925f86fafb0", + "git_sha": "a554e54c63c3f03f91c88a18ece7b89eca5a5212", "installed_by": ["modules"] }, "rclone/checksum": { "branch": "master", - "git_sha": "0983b1ef5f0729946953d921100af925f86fafb0", + "git_sha": "a554e54c63c3f03f91c88a18ece7b89eca5a5212", "installed_by": ["modules"] }, "rclone/copy": { "branch": "master", - "git_sha": "969013a2a91dc8152ca537bbd4dd4feaa15c13a7", + "git_sha": "a554e54c63c3f03f91c88a18ece7b89eca5a5212", "installed_by": ["modules"] } } diff --git a/modules/nf-core/rclone/check/main.nf b/modules/nf-core/rclone/check/main.nf index 56b2a67..ee1d36b 100644 --- a/modules/nf-core/rclone/check/main.nf +++ b/modules/nf-core/rclone/check/main.nf @@ -8,7 +8,8 @@ process RCLONE_CHECK { : 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' }" input: - tuple val(meta), path(source, stageAs: 'source/*'), path(destination, stageAs: 'destination/*') + tuple val(meta), val(source), val(destination) + path rclone_config output: tuple val(meta), path("${prefix}.combined.txt") , emit: combined , optional: true @@ -17,6 +18,7 @@ process RCLONE_CHECK { tuple val(meta), path("${prefix}.missing_on_src.txt") , emit: missing_on_src, optional: true tuple val(meta), path("${prefix}.match.txt") , emit: match , optional: true tuple val(meta), path("${prefix}.error.txt") , emit: error , optional: true + tuple val(meta), path("${prefix}.exit_code.txt") , emit: exit_code , optional: true tuple val("${task.process}"), val('rclone'), eval("rclone --version | sed -n '1s/^rclone v//p'"), topic: versions, emit: versions_rclone when: @@ -25,10 +27,10 @@ process RCLONE_CHECK { script: def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" + def configArg = rclone_config ? "--config ${rclone_config}" : '' """ - rclone check \\ - --copy-links \\ + rclone check ${configArg} \\ $args \\ --combined ${prefix}.combined.txt \\ --differ ${prefix}.differ.txt \\ @@ -37,8 +39,13 @@ process RCLONE_CHECK { --match ${prefix}.match.txt \\ --error ${prefix}.error.txt \\ --checkers $task.cpus \\ - source \\ - destination || true + ${source} \\ + ${destination} || echo \$? > ${prefix}.exit_code.txt + + # Do not emit empty output files + for f in *.txt; do + [ -s "\$f" ] || rm -f "\$f" + done """ stub: diff --git a/modules/nf-core/rclone/check/meta.yml b/modules/nf-core/rclone/check/meta.yml index 05766b3..2ae5d92 100644 --- a/modules/nf-core/rclone/check/meta.yml +++ b/modules/nf-core/rclone/check/meta.yml @@ -21,17 +21,29 @@ input: Groovy Map containing source information e.g. [ id:'test' ] - source: - type: file - description: File or directory containing source files to compare. - pattern: "" - ontologies: - - edam: "http://edamontology.org/data_0006" + type: string + description: | + File or directory containing source files to compare. This should be a path understood by Rclone, + such as a local path or a configured remote path. + Examples: `data/input`, `s3:bucket/path`, `gs:bucket/path`, + `remote:path/to/data`. - destination: - type: file - description: File or directory containing destination files to compare. - pattern: "" - ontologies: - - edam: "http://edamontology.org/data_0006" + type: string + description: | + Directory containing destination files to compare. This should be the fully resolved target + path understood by Rclone, such as a local path or a configured remote + path. The module does not append sample IDs, basenames, or modify this + path internally. + Examples: `results/output`, `s3:bucket/output`, `gs:bucket/output`, + `remote:path/to/output`. + - rclone_config: + type: file + description: | + Rclone configuration file defining the remotes used by source_path and/or + destination_path. Authentication and remote-specific options should be + configured in this file where possible. + pattern: "*.conf" + ontologies: [] output: combined: - - meta: @@ -105,6 +117,18 @@ output: pattern: "*.error.txt" ontologies: - edam: "http://edamontology.org/data_3671" + exit_code: + - - meta: + type: map + description: | + Groovy Map containing checksum source information + e.g. [ id:'test' ] + - ${prefix}.exit_code.txt: + type: file + description: File with exit status. + pattern: "*.exit_code.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" versions_rclone: - - ${task.process}: type: string diff --git a/modules/nf-core/rclone/check/tests/main.nf.test b/modules/nf-core/rclone/check/tests/main.nf.test index 093265e..312d631 100644 --- a/modules/nf-core/rclone/check/tests/main.nf.test +++ b/modules/nf-core/rclone/check/tests/main.nf.test @@ -3,17 +3,21 @@ nextflow_process { name "Test Process RCLONE_CHECK" script "../main.nf" process "RCLONE_CHECK" + config "./nextflow.config" tag "modules" tag "modules_nfcore" tag "rclone" tag "rclone/check" - test("sarscov2 - fastq") { + test("match - malt") { when { process { """ - input[0] = [[id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + file('rclone.config').text = '[s3]\\ntype = s3\\nprovider = AWS\\nregion = eu-west-1\\nenv_auth = false\\nno_check_bucket = true' + + input[0] = [[id:'test'], "s3://nf-core-test-datasets/modules/data/delete_me/malt/", "s3://nf-core-test-datasets/modules/data/delete_me/malt/"] + input[1] = file('rclone.config') """ } } @@ -21,7 +25,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "missing_on_dst", "missing_on_src", "error"])).match() } + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "match", "missing_on_dst", "missing_on_src", "error"])).match() } ) } } @@ -32,7 +36,8 @@ nextflow_process { when { process { """ - input[0] = [[id:'test'], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + input[0] = [[id:'test'], params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/', params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/'] + input[1] = [] """ } } @@ -45,11 +50,14 @@ nextflow_process { } } - test("different files - fails") { + test("different files") { when { process { """ - input[0] = [[id:'test'], file(params.modules_testdata_base_path + 'delete_me/aracne3/README.md', checkIfExists: true), file(params.modules_testdata_base_path + 'delete_me/binette_checkm2/README.md', checkIfExists: true)] + file('rclone.config').text = '[https]\\ntype = http\\n[s3]\\ntype = s3\\nprovider = AWS\\nregion = eu-west-1\\nenv_auth = false\\nno_check_bucket = true' + + input[0] = [[id:'test'], "s3://nf-core-test-datasets/modules/data/delete_me/malt/", "s3://annotation-cache/snpeff_cache/WBcel235.105/"] + input[1] = file('rclone.config') """ } } @@ -62,11 +70,14 @@ nextflow_process { } } - test("destination subset - partial match and missing") { + test("differ and missing") { when { process { """ - input[0] = [[id:'test'], [file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true)], file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true)] + file('rclone.config').text = '[https]\\ntype = http\\n[s3]\\ntype = s3\\nprovider = AWS\\nregion = eu-west-1\\nenv_auth = false\\nno_check_bucket = true' + + input[0] = [[id:'test'], "s3://nf-core-test-datasets/modules/data/delete_me/mirtop/", "s3://nf-core-test-datasets/modules/data/delete_me/metabuli"] + input[1] = file('rclone.config') """ } } @@ -74,7 +85,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "missing_on_src", "error"])).match() } + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "missing_on_dst", "missing_on_src", "error"])).match() } ) } } diff --git a/modules/nf-core/rclone/check/tests/main.nf.test.snap b/modules/nf-core/rclone/check/tests/main.nf.test.snap index 5d14e75..031a7c7 100644 --- a/modules/nf-core/rclone/check/tests/main.nf.test.snap +++ b/modules/nf-core/rclone/check/tests/main.nf.test.snap @@ -1,5 +1,5 @@ { - "sarscov2 - fastq - stub": { + "match - malt": { "content": [ { "combined": [ @@ -11,20 +11,13 @@ ] ], "differ": [ - [ - { - "id": "test" - }, - "test.differ.txt" - ] + ], "error": [ - [ - { - "id": "test" - }, - "test.error.txt" - ] + + ], + "exit_code": [ + ], "match": [ [ @@ -35,20 +28,10 @@ ] ], "missing_on_dst": [ - [ - { - "id": "test" - }, - "test.missing_on_dst.txt" - ] + ], "missing_on_src": [ - [ - { - "id": "test" - }, - "test.missing_on_src.txt" - ] + ], "versions_rclone": [ [ @@ -59,13 +42,13 @@ ] } ], - "timestamp": "2026-07-10T21:39:36.202209966", + "timestamp": "2026-07-22T14:46:30.042575576", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } }, - "different files - fails": { + "sarscov2 - fastq - stub": { "content": [ { "combined": [ @@ -81,7 +64,7 @@ { "id": "test" }, - "test.differ.txt:md5,ac036608c5c402f92926505d0f0ab0e4" + "test.differ.txt" ] ], "error": [ @@ -91,6 +74,9 @@ }, "test.error.txt" ] + ], + "exit_code": [ + ], "match": [ [ @@ -125,13 +111,13 @@ ] } ], - "timestamp": "2026-07-10T21:39:43.336064968", + "timestamp": "2026-07-21T21:03:37.410543015", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } }, - "sarscov2 - fastq": { + "different files": { "content": [ { "combined": [ @@ -143,28 +129,21 @@ ] ], "differ": [ - [ - { - "id": "test" - }, - "test.differ.txt" - ] + ], "error": [ + + ], + "exit_code": [ [ { "id": "test" }, - "test.error.txt" + "test.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], "match": [ - [ - { - "id": "test" - }, - "test.match.txt:md5,6f2d815bc8fe93026183cc59946ffc46" - ] + ], "missing_on_dst": [ [ @@ -191,13 +170,13 @@ ] } ], - "timestamp": "2026-07-10T21:39:29.273416483", + "timestamp": "2026-07-21T21:03:45.979925514", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } }, - "destination subset - partial match and missing": { + "differ and missing": { "content": [ { "combined": [ @@ -217,27 +196,25 @@ ] ], "error": [ + + ], + "exit_code": [ [ { "id": "test" }, - "test.error.txt" + "test.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], "match": [ - [ - { - "id": "test" - }, - "test.match.txt:md5,6f2d815bc8fe93026183cc59946ffc46" - ] + ], "missing_on_dst": [ [ { "id": "test" }, - "test.missing_on_dst.txt:md5,827cbdd053152d88295a331ab8bae87c" + "test.missing_on_dst.txt" ] ], "missing_on_src": [ @@ -257,10 +234,10 @@ ] } ], - "timestamp": "2026-07-13T17:42:54.497150157", + "timestamp": "2026-07-22T14:46:52.993591106", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/modules/nf-core/rclone/check/tests/nextflow.config b/modules/nf-core/rclone/check/tests/nextflow.config new file mode 100644 index 0000000..b208cef --- /dev/null +++ b/modules/nf-core/rclone/check/tests/nextflow.config @@ -0,0 +1,7 @@ +process { + withName: 'RCLONE_CHECK' { + ext.args = { + "--no-check-certificate" + } + } +} diff --git a/modules/nf-core/rclone/checksum/main.nf b/modules/nf-core/rclone/checksum/main.nf index 71a21f1..bef4c5e 100644 --- a/modules/nf-core/rclone/checksum/main.nf +++ b/modules/nf-core/rclone/checksum/main.nf @@ -8,7 +8,8 @@ process RCLONE_CHECKSUM { : 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' }" input: - tuple val(meta), path(sumfile), val(hash), path(destination, stageAs: 'destination/*') + tuple val(meta), path(sumfile), val(hash), val(destination) + path rclone_config output: tuple val(meta), path("${prefix}.combined.txt") , emit: combined , optional: true @@ -17,6 +18,7 @@ process RCLONE_CHECKSUM { tuple val(meta), path("${prefix}.missing_on_src.txt") , emit: missing_on_src, optional: true tuple val(meta), path("${prefix}.match.txt") , emit: match , optional: true tuple val(meta), path("${prefix}.error.txt") , emit: error , optional: true + tuple val(meta), path("${prefix}.exit_code.txt") , emit: exit_code , optional: true tuple val("${task.process}"), val('rclone'), eval("rclone --version | sed -n '1s/^rclone v//p'"), topic: versions, emit: versions_rclone when: @@ -25,9 +27,10 @@ process RCLONE_CHECKSUM { script: def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" + def configArg = rclone_config ? "--config ${rclone_config}" : '' """ - rclone checksum \\ + rclone checksum ${configArg} \\ --copy-links \\ $args \\ --combined ${prefix}.combined.txt \\ @@ -39,7 +42,12 @@ process RCLONE_CHECKSUM { --checkers $task.cpus \\ $hash \\ $sumfile \\ - destination || true + ${destination} || echo \$? > ${prefix}.exit_code.txt + + # Do not emit empty output files + for f in *.txt; do + [ -s "\$f" ] || rm -f "\$f" + done """ stub: diff --git a/modules/nf-core/rclone/checksum/meta.yml b/modules/nf-core/rclone/checksum/meta.yml index 8239375..40a8f87 100644 --- a/modules/nf-core/rclone/checksum/meta.yml +++ b/modules/nf-core/rclone/checksum/meta.yml @@ -15,7 +15,6 @@ tools: licence: - "MIT" identifier: "" - input: - - meta: type: map @@ -24,7 +23,8 @@ input: e.g. [ id:'test' ] - sumfile: type: file - description: Checksum SUM file containing hashes and destination paths to verify. + description: Checksum SUM file containing hashes and destination paths to + verify. pattern: "*.{md5,sha1,sha256,sum,txt}" ontologies: - edam: "http://edamontology.org/data_3671" @@ -32,11 +32,22 @@ input: type: string description: Hash type to check, for example MD5, SHA1, or SHA256. - destination: - type: file - description: File or directory containing destination files to check against the SUM file. - pattern: "" - ontologies: - - edam: "http://edamontology.org/data_0006" + type: string + description: | + Directory containing destination files to check against the SUM file. This should be the fully resolved target + path understood by Rclone, such as a local path or a configured remote + path. The module does not append sample IDs, basenames, or modify this + path internally. + Examples: `results/output`, `s3:bucket/output`, `gs:bucket/output`, + `remote:path/to/output`. + - rclone_config: + type: file + description: | + Rclone configuration file defining the remotes used by source_path and/or + destination_path. Authentication and remote-specific options should be + configured in this file where possible. + pattern: "*.conf" + ontologies: [] output: combined: - - meta: @@ -46,7 +57,8 @@ output: e.g. [ id:'test' ] - ${prefix}.combined.txt: type: file - description: Combined report of matching, missing, differing, and error paths. + description: Combined report of matching, missing, differing, and error + paths. pattern: "*.combined.txt" ontologies: - edam: "http://edamontology.org/data_3671" @@ -58,7 +70,8 @@ output: e.g. [ id:'test' ] - ${prefix}.differ.txt: type: file - description: Report of paths present in both source SUM file and destination but different. + description: Report of paths present in both source SUM file and + destination but different. pattern: "*.differ.txt" ontologies: - edam: "http://edamontology.org/data_3671" @@ -70,7 +83,8 @@ output: e.g. [ id:'test' ] - ${prefix}.missing_on_dst.txt: type: file - description: Report of paths present in the SUM file but missing from the destination. + description: Report of paths present in the SUM file but missing from + the destination. pattern: "*.missing_on_dst.txt" ontologies: - edam: "http://edamontology.org/data_3671" @@ -82,7 +96,8 @@ output: e.g. [ id:'test' ] - ${prefix}.missing_on_src.txt: type: file - description: Report of paths present in the destination but missing from the SUM file. + description: Report of paths present in the destination but missing from + the SUM file. pattern: "*.missing_on_src.txt" ontologies: - edam: "http://edamontology.org/data_3671" @@ -120,6 +135,18 @@ output: - rclone --version | sed -n '1s/^rclone v//p': type: eval description: The expression to obtain the version of the tool + exit_code: + - - meta: + type: map + description: | + Groovy Map containing checksum source information + e.g. [ id:'test' ] + - ${prefix}.exit_code.txt: + type: file + description: File with exit status. + pattern: "*.exit_code.txt" + ontologies: + - edam: "http://edamontology.org/data_3671" topics: versions: - - ${task.process}: diff --git a/modules/nf-core/rclone/checksum/tests/main.nf.test b/modules/nf-core/rclone/checksum/tests/main.nf.test index 2d833de..bbfab84 100644 --- a/modules/nf-core/rclone/checksum/tests/main.nf.test +++ b/modules/nf-core/rclone/checksum/tests/main.nf.test @@ -3,19 +3,22 @@ nextflow_process { name "Test Process RCLONE_CHECKSUM" script "../main.nf" process "RCLONE_CHECKSUM" + config "./nextflow.config" tag "modules" tag "modules_nfcore" tag "rclone" tag "rclone/checksum" - test("hello - md5") { + test("test - md5 - match") { + when { process { """ - file('hello.md5').text = 'e59ff97941044f85df5297e1c302d260 hello.txt\\n' + file('rclone.config').text = '[s3]\\ntype = s3\\nprovider = AWS\\nregion = eu-west-1\\nenv_auth = false\\nno_check_bucket = true' - input[0] = [[id:'test'], file('hello.md5'), 'MD5', file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)] + input[0] = [[id:'test'], file(params.modules_testdata_base_path + 'generic/txt/snpeff_cache_md5.txt', checkIfExists: true), 'MD5', "s3://annotation-cache/snpeff_cache/WBcel235.105/"] + input[1] = file('rclone.config') """ } } @@ -23,20 +26,21 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "missing_on_dst", "missing_on_src", "error"]) ).match() } + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "match", "differ", "missing_on_dst", "missing_on_src", "error"]) ).match() } ) } } - test("hello - md5 - stub") { + test("test - md5 - stub") { options "-stub" when { process { """ - file('hello.md5').text = 'e59ff97941044f85df5297e1c302d260 hello.txt\\n' + file('test.md5').text = 'e59ff97941044f85df5297e1c302d260 hello.txt\\n' - input[0] = [[id:'test'], file('hello.md5'), 'MD5', file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)] + input[0] = [[id:'test'], file('test.md5'), 'MD5', "s3://nf-core-test-datasets/modules/data/delete_me/malt/"] + input[1] = [] """ } } @@ -49,13 +53,15 @@ nextflow_process { } } - test("hello - differs") { + test("test - md5 - differs") { when { process { """ - file('hello_bad.md5').text = '00000000000000000000000000000000 hello.txt\\n' + file('test_bad.md5').text = '00000000000000000000000000000000 hello.txt' + file('rclone.config').text = '[s3]\\ntype = s3\\nprovider = AWS\\nregion = eu-west-1\\nenv_auth = false\\nno_check_bucket = true' - input[0] = [[id:'test'], file('hello_bad.md5'), 'MD5', file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)] + input[0] = [[id:'test'], file('test_bad.md5'), 'MD5', "s3://annotation-cache/snpeff_cache/WBcel235.105/"] + input[1] = file('rclone.config') """ } } @@ -67,23 +73,4 @@ nextflow_process { ) } } - - test("missing destination") { - when { - process { - """ - file('missing.md5').text = 'e59ff97941044f85df5297e1c302d260 missing.txt\\n' - - input[0] = [[id:'test'], file('missing.md5'), 'MD5', file(params.modules_testdata_base_path + 'generic/txt/hello.txt', checkIfExists: true)] - """ - } - } - - then { - assertAll( - { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "match", "missing_on_src", "error"])).match() } - ) - } - } } diff --git a/modules/nf-core/rclone/checksum/tests/main.nf.test.snap b/modules/nf-core/rclone/checksum/tests/main.nf.test.snap index 57ba70b..a100d10 100644 --- a/modules/nf-core/rclone/checksum/tests/main.nf.test.snap +++ b/modules/nf-core/rclone/checksum/tests/main.nf.test.snap @@ -1,5 +1,5 @@ { - "missing destination": { + "test - md5 - match": { "content": [ { "combined": [ @@ -11,20 +11,13 @@ ] ], "differ": [ - [ - { - "id": "test" - }, - "test.differ.txt" - ] + ], "error": [ - [ - { - "id": "test" - }, - "test.error.txt" - ] + + ], + "exit_code": [ + ], "match": [ [ @@ -35,20 +28,10 @@ ] ], "missing_on_dst": [ - [ - { - "id": "test" - }, - "test.missing_on_dst.txt:md5,9ddf8bbca47985a064c1d7163d0235da" - ] + ], "missing_on_src": [ - [ - { - "id": "test" - }, - "test.missing_on_src.txt" - ] + ], "versions_rclone": [ [ @@ -59,13 +42,13 @@ ] } ], - "timestamp": "2026-07-10T21:34:34.881758203", + "timestamp": "2026-07-21T23:18:32.247989694", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } }, - "hello - md5 - stub": { + "test - md5 - differs": { "content": [ { "combined": [ @@ -77,28 +60,21 @@ ] ], "differ": [ - [ - { - "id": "test" - }, - "test.differ.txt" - ] + ], "error": [ + + ], + "exit_code": [ [ { "id": "test" }, - "test.error.txt" + "test.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], "match": [ - [ - { - "id": "test" - }, - "test.match.txt" - ] + ], "missing_on_dst": [ [ @@ -109,12 +85,7 @@ ] ], "missing_on_src": [ - [ - { - "id": "test" - }, - "test.missing_on_src.txt" - ] + ], "versions_rclone": [ [ @@ -125,13 +96,13 @@ ] } ], - "timestamp": "2026-07-10T21:34:20.471038214", + "timestamp": "2026-07-21T23:20:27.477738495", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } }, - "hello - md5": { + "test - md5 - stub": { "content": [ { "combined": [ @@ -158,71 +129,8 @@ "test.error.txt" ] ], - "match": [ - [ - { - "id": "test" - }, - "test.match.txt:md5,a438474115db37daf9d8e1307c06eb4a" - ] - ], - "missing_on_dst": [ - [ - { - "id": "test" - }, - "test.missing_on_dst.txt" - ] - ], - "missing_on_src": [ - [ - { - "id": "test" - }, - "test.missing_on_src.txt" - ] - ], - "versions_rclone": [ - [ - "RCLONE_CHECKSUM", - "rclone", - "1.74.3-DEV" - ] - ] - } - ], - "timestamp": "2026-07-10T21:34:13.264088794", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.6" - } - }, - "hello - differs": { - "content": [ - { - "combined": [ - [ - { - "id": "test" - }, - "test.combined.txt" - ] - ], - "differ": [ - [ - { - "id": "test" - }, - "test.differ.txt:md5,a438474115db37daf9d8e1307c06eb4a" - ] - ], - "error": [ - [ - { - "id": "test" - }, - "test.error.txt" - ] + "exit_code": [ + ], "match": [ [ @@ -257,10 +165,10 @@ ] } ], - "timestamp": "2026-07-10T21:34:27.556428476", + "timestamp": "2026-07-21T23:19:49.064384002", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/modules/nf-core/rclone/checksum/tests/nextflow.config b/modules/nf-core/rclone/checksum/tests/nextflow.config new file mode 100644 index 0000000..a78067e --- /dev/null +++ b/modules/nf-core/rclone/checksum/tests/nextflow.config @@ -0,0 +1,7 @@ +process { + withName: 'RCLONE_CHECKSUM' { + ext.args = { + "--no-check-certificate --one-way" + } + } +} diff --git a/modules/nf-core/rclone/copy/tests/main.nf.test b/modules/nf-core/rclone/copy/tests/main.nf.test index 14d79cb..b9f0a77 100644 --- a/modules/nf-core/rclone/copy/tests/main.nf.test +++ b/modules/nf-core/rclone/copy/tests/main.nf.test @@ -19,7 +19,7 @@ nextflow_process { input[0] = [ [ id:'test' ], params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf.gz', - '/tmp/test.genome.vcf.gz' + '/tmp/' ] input[1] = [] """ @@ -44,7 +44,7 @@ nextflow_process { input[0] = [ [ id:'test' ], params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf.gz', - '/tmp/test.genome.vcf.gz' + '/tmp/' ] input[1] = [] """ diff --git a/workflows/datasync.nf b/workflows/datasync.nf index c47edd8..7085cc1 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -44,11 +44,13 @@ workflow DATASYNC { def rclone_destination = source.isFile() ? output_path.toString().replaceAll('/+$', '') : "${output_path.toString().replaceAll('/+$', '')}/${source.name}" - def rclone_check = "${output_path.toString().replaceAll('/+$', '')}/${source.name}" + + def rclone_check = source.isFile() + ? input_path.replaceFirst('/[^/]+$', '') + : input_path.toString().replaceAll('/+$', '') rclone: [ meta, source_uri, rclone_destination ] - checksum: [ meta, md5, sha, source ] - check : [ meta, source, file(rclone_check) ] + checksum: [ meta, md5, sha, rclone_check ] } // Group input md5sum/shasum with their respective generated checksum @@ -66,7 +68,8 @@ workflow DATASYNC { } RCLONE_CHECKSUM( - ch_checksum + ch_checksum, + rclone_config ? file(rclone_config, checkIfExists: true) : [] ) ch_multiqc_files = ch_multiqc_files.mix(RCLONE_CHECKSUM.out.combined @@ -93,12 +96,13 @@ workflow DATASYNC { // File transfer validation // // Wait for file copy to finish before running RCLONE_CHECK - ch_rclone_check = ch_samplesheet.check + ch_rclone_check = ch_samplesheet.rclone .join(RCLONE_COPY.out.log) .map { meta, input, output, log -> [ meta, input, output ]} RCLONE_CHECK( - ch_rclone_check + ch_rclone_check, + rclone_config ? file(rclone_config, checkIfExists: true) : [] ) ch_multiqc_files = ch_multiqc_files.mix(RCLONE_CHECK.out.combined From eb934c8b17d691b5b402df0cc35b6356b773fb31 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 16:46:21 -0300 Subject: [PATCH 173/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2cc376..6019685 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). -metromap_style_pipeline_workflow_components drawio (1) +metromap_style_pipeline_workflow_components drawio (1) ## Quick start From 4f16da8cab0f8b0554fa6417cabdb6c72f0a7ab1 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 16:47:22 -0300 Subject: [PATCH 174/334] Add files via upload --- ...tyle_pipeline_workflow_components.drawio.png | Bin 0 -> 81474 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/metromap_style_pipeline_workflow_components.drawio.png diff --git a/docs/images/metromap_style_pipeline_workflow_components.drawio.png b/docs/images/metromap_style_pipeline_workflow_components.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..2f082d2523712740d8cd49bf4a69d72c062898c5 GIT binary patch literal 81474 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 zK{js7695G Date: Wed, 22 Jul 2026 16:49:01 -0300 Subject: [PATCH 175/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6019685..da4fbf8 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). -metromap_style_pipeline_workflow_components drawio (1) +![nf-core/datasync metro map](docs/images/metromap_style_pipeline_workflow_components.drawio.png) ## Quick start From fdb0a8d392a6dc88a5f7f32493e2a0f73c456fdb Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 16:50:13 -0300 Subject: [PATCH 176/334] Update README.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da4fbf8..6b0da93 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ run_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv reference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv ``` -Then launch the pipeline with a container profile: +Then launch the pipeline using: ```bash nextflow run nf-core/datasync \ From 51b9fdf1753371c9e9a32a5b06909f6ce1553694 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 16:52:06 -0300 Subject: [PATCH 177/334] Update README.md --- README.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.md b/README.md index 6b0da93..87c9b9b 100644 --- a/README.md +++ b/README.md @@ -65,14 +65,7 @@ See the [usage documentation](docs/usage.md) for samplesheet rules, destination ## Pipeline output -Results are written below `--outdir`: - -- `rclone/` contains a copy log and integrity status files for each samplesheet row; -- `multiqc/multiqc_report.html` provides the consolidated transfer and checksum summary; -- `multiqc/multiqc_data/` contains machine-readable report data; and -- `pipeline_info/` contains software versions and Nextflow execution reports. - -The transferred data itself is written directly to each row's `output_path`, not below `--outdir` unless that is the destination you selected. See the [output documentation](docs/output.md) for file names and status-code interpretation. +Results are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation. ## Credits From b558b3ce1008a4adc440c1fe6283a8d27ed0eb88 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 17:09:09 -0300 Subject: [PATCH 178/334] Update README.md --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 87c9b9b..7889f05 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,18 @@ Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported r > [!NOTE] > If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required. -Create a samplesheet containing one transfer per row: +To explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile: + +```bash +nextflow run nf-core/datasync \ + -r \ + -profile test,docker \ + --outdir results +``` + +The `test` profile supplies a small samplesheet and rclone configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data. + +To run the pipeline on your own data, create a samplesheet containing one transfer per row: ```csv sample,input,output_path,checksum_md5,checksum_sha From c3c93c9ace89524920c9ec95d8daef8cda214d23 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 17:09:42 -0300 Subject: [PATCH 179/334] Update README.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7889f05..076a36e 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ **nf-core/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline: 1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest; -2. copies the source to the requested destination with [rclone](https://rclone.org/); +2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/); 3. compares the copied data with the source using `rclone check`; and 4. produces detailed rclone status files and a consolidated MultiQC report. From c6d12e368795c5515692446636053cf7cd29950e Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 22 Jul 2026 22:11:13 +0200 Subject: [PATCH 180/334] Update snapshots --- tests/default.nf.test.snap | 43 +++++------------------------------- tests/edge.nf.test.snap | 37 ++++++------------------------- tests/main_full.nf.test.snap | 19 +++++----------- 3 files changed, 18 insertions(+), 81 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index c71d4e5..2b27518 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -35,63 +35,32 @@ "rclone/check", "rclone/check/Illumina_annotation", "rclone/check/Illumina_annotation/Illumina_annotation.combined.txt", - "rclone/check/Illumina_annotation/Illumina_annotation.differ.txt", - "rclone/check/Illumina_annotation/Illumina_annotation.error.txt", "rclone/check/Illumina_annotation/Illumina_annotation.match.txt", - "rclone/check/Illumina_annotation/Illumina_annotation.missing_on_dst.txt", - "rclone/check/Illumina_annotation/Illumina_annotation.missing_on_src.txt", "rclone/check/benchmark_bed", "rclone/check/benchmark_bed/benchmark_bed.combined.txt", - "rclone/check/benchmark_bed/benchmark_bed.differ.txt", - "rclone/check/benchmark_bed/benchmark_bed.error.txt", "rclone/check/benchmark_bed/benchmark_bed.match.txt", - "rclone/check/benchmark_bed/benchmark_bed.missing_on_dst.txt", - "rclone/check/benchmark_bed/benchmark_bed.missing_on_src.txt", - "rclone/check/test_fastq", - "rclone/check/test_fastq/test_fastq.combined.txt", - "rclone/check/test_fastq/test_fastq.differ.txt", - "rclone/check/test_fastq/test_fastq.error.txt", - "rclone/check/test_fastq/test_fastq.match.txt", - "rclone/check/test_fastq/test_fastq.missing_on_dst.txt", - "rclone/check/test_fastq/test_fastq.missing_on_src.txt", "rclone/checksum", "rclone/checksum/Illumina_annotation", "rclone/checksum/Illumina_annotation/Illumina_annotation.combined.txt", - "rclone/checksum/Illumina_annotation/Illumina_annotation.differ.txt", - "rclone/checksum/Illumina_annotation/Illumina_annotation.error.txt", "rclone/checksum/Illumina_annotation/Illumina_annotation.match.txt", - "rclone/checksum/Illumina_annotation/Illumina_annotation.missing_on_dst.txt", - "rclone/checksum/Illumina_annotation/Illumina_annotation.missing_on_src.txt", "rclone/checksum/benchmark_bed", "rclone/checksum/benchmark_bed/benchmark_bed.combined.txt", - "rclone/checksum/benchmark_bed/benchmark_bed.differ.txt", - "rclone/checksum/benchmark_bed/benchmark_bed.error.txt", "rclone/checksum/benchmark_bed/benchmark_bed.match.txt", - "rclone/checksum/benchmark_bed/benchmark_bed.missing_on_dst.txt", - "rclone/checksum/benchmark_bed/benchmark_bed.missing_on_src.txt", - "rclone/checksum/test_fastq", - "rclone/checksum/test_fastq/test_fastq.combined.txt", - "rclone/checksum/test_fastq/test_fastq.differ.txt", - "rclone/checksum/test_fastq/test_fastq.error.txt", - "rclone/checksum/test_fastq/test_fastq.match.txt", - "rclone/checksum/test_fastq/test_fastq.missing_on_dst.txt", - "rclone/checksum/test_fastq/test_fastq.missing_on_src.txt", "rclone/copy", "rclone/copy/Illumina_annotation-rclone-copy.log", - "rclone/copy/benchmark_bed-rclone-copy.log", - "rclone/copy/test_fastq-rclone-copy.log" + "rclone/copy/benchmark_bed-rclone-copy.log" ], [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_rclone_check.txt:md5,14b1ff73415db0533e1467cdf3dfccf8", - "multiqc_rclone_checksum_md5.txt:md5,14b1ff73415db0533e1467cdf3dfccf8", - "multiqc_samplesheet.txt:md5,608c07d7a768f3d66b44f8daddcec95e" + "multiqc_rclone_check.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", + "multiqc_rclone_checksum_md5.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", + "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4" ] ], - "timestamp": "2026-07-17T19:26:17.292861031", + "timestamp": "2026-07-22T22:00:27.445840436", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index e43ee05..517b27b 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -25,7 +25,6 @@ "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_rclone_check.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", - "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -36,47 +35,26 @@ "rclone/check", "rclone/check/Illumina_annotation_incorrect", "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.differ.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.error.txt", "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.missing_on_dst.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.missing_on_src.txt", "rclone/check/Illumina_annotation_missing", "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.differ.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.error.txt", "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_src.txt", "rclone/check/Illumina_annotation_sha_only", "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.error.txt", "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.match.txt", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.missing_on_dst.txt", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.missing_on_src.txt", "rclone/checksum", "rclone/checksum/Illumina_annotation_incorrect", "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.differ.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.error.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.exit_code.txt", "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.missing_on_dst.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.missing_on_src.txt", "rclone/checksum/Illumina_annotation_missing", "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.differ.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.error.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.exit_code.txt", "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_src.txt", "rclone/checksum/Illumina_annotation_sha_only", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.error.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.match.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.missing_on_dst.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.missing_on_src.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.exit_code.txt", "rclone/copy", "rclone/copy/Illumina_annotation_incorrect-rclone-copy.log", "rclone/copy/Illumina_annotation_missing-rclone-copy.log", @@ -84,16 +62,15 @@ ], [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_rclone_check.txt:md5,df42d80150a8a1f2da93c5eed053dc3f", - "multiqc_rclone_checksum_md5.txt:md5,679b4cda086bfacf50fe3ec5b22dd386", - "multiqc_rclone_checksum_sha.txt:md5,9ba162249102c1b0af4464411b3a7eb5", + "multiqc_rclone_check.txt:md5,c8f13c10aa4f0e4b356c5c08a9ae7ee9", + "multiqc_rclone_checksum_md5.txt:md5,cf92203df21f04ddf8315fc606812e0b", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" ] ], - "timestamp": "2026-07-20T14:40:38.905083297", + "timestamp": "2026-07-22T22:01:06.286788462", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index dcf61c3..7bc1eeb 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -25,7 +25,6 @@ "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_rclone_check.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", - "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -36,34 +35,26 @@ "rclone/check", "rclone/check/demultiplex", "rclone/check/demultiplex/demultiplex.combined.txt", - "rclone/check/demultiplex/demultiplex.differ.txt", - "rclone/check/demultiplex/demultiplex.error.txt", "rclone/check/demultiplex/demultiplex.match.txt", - "rclone/check/demultiplex/demultiplex.missing_on_dst.txt", - "rclone/check/demultiplex/demultiplex.missing_on_src.txt", "rclone/checksum", "rclone/checksum/demultiplex", "rclone/checksum/demultiplex/demultiplex.combined.txt", - "rclone/checksum/demultiplex/demultiplex.differ.txt", - "rclone/checksum/demultiplex/demultiplex.error.txt", + "rclone/checksum/demultiplex/demultiplex.exit_code.txt", "rclone/checksum/demultiplex/demultiplex.match.txt", - "rclone/checksum/demultiplex/demultiplex.missing_on_dst.txt", - "rclone/checksum/demultiplex/demultiplex.missing_on_src.txt", "rclone/copy", "rclone/copy/demultiplex-rclone-copy.log" ], [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_rclone_check.txt:md5,204410f4dab8ab5db201f4833baa2f81", - "multiqc_rclone_checksum_md5.txt:md5,f59d50960061aee8afac0d9389b90a2e", - "multiqc_rclone_checksum_sha.txt:md5,204410f4dab8ab5db201f4833baa2f81", + "multiqc_rclone_check.txt:md5,03a73f087a286ec6580aada2a5db2e7c", + "multiqc_rclone_checksum_md5.txt:md5,d7c7dd71a9ff75955dd0e508d1ad9968", "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" ] ], - "timestamp": "2026-07-17T19:31:26.493917757", + "timestamp": "2026-07-22T22:01:43.699965019", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file From fd9b00ce37e7fc2a7243a2a5c7643c7d70ceb34f Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 17:13:16 -0300 Subject: [PATCH 181/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 076a36e..c2b08fe 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ **nf-core/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline: -1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest; +1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/); 2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/); -3. compares the copied data with the source using `rclone check`; and +3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and 4. produces detailed rclone status files and a consolidated MultiQC report. Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). From 110eaf89ad17d909de00dda9ac2488da4e4d5a94 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 17:13:38 -0300 Subject: [PATCH 182/334] Update docs/usage.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 91dd2f0..f08519f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -173,4 +173,4 @@ process { } ``` -Run with `-c resources.config`. Rclone derives its checker count from allocated CPUs, and the copy step uses roughly half that count (minimum one) for parallel transfers. +Run with `-c resources.config`. `rclone` derives its checker count from allocated CPUs, and the copy step uses roughly half that count (minimum one) for parallel transfers. From cfd37ed8c0ee5bd7856751faa3d5a906637eea43 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Wed, 22 Jul 2026 17:13:53 -0300 Subject: [PATCH 183/334] Update docs/usage.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index f08519f..1543172 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -161,7 +161,7 @@ nextflow pull nf-core/datasync ## Resource configuration -The rclone processes use the `process_low` label. Configure executors and override CPU, memory, or time in a Nextflow config, for example: +The `rclone` processes use the `process_low` label. Configure executors and override CPU, memory, or time in a Nextflow config, for example: ```groovy title="resources.config" process { From fa3c7e848bc3816e5d54990e56a8d34e811a66c2 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 23 Jul 2026 15:03:36 +0200 Subject: [PATCH 184/334] Apply suggestion --- workflows/datasync.nf | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 7085cc1..23eb696 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -33,6 +33,7 @@ workflow DATASYNC { ch_versions = channel.empty() ch_multiqc_files = channel.empty() + ch_rclone_config = rclone_config ? file(rclone_config, checkIfExists: true) : [] ch_samplesheet = ch_samplesheet.multiMap { meta, input_path, output_path, md5, sha -> @@ -69,7 +70,7 @@ workflow DATASYNC { RCLONE_CHECKSUM( ch_checksum, - rclone_config ? file(rclone_config, checkIfExists: true) : [] + ch_rclone_config ) ch_multiqc_files = ch_multiqc_files.mix(RCLONE_CHECKSUM.out.combined @@ -89,7 +90,7 @@ workflow DATASYNC { // RCLONE_COPY( ch_samplesheet.rclone, - rclone_config ? file(rclone_config, checkIfExists: true) : [] + ch_rclone_config ) // @@ -102,7 +103,7 @@ workflow DATASYNC { RCLONE_CHECK( ch_rclone_check, - rclone_config ? file(rclone_config, checkIfExists: true) : [] + ch_rclone_config ) ch_multiqc_files = ch_multiqc_files.mix(RCLONE_CHECK.out.combined From 65d43d6c09a5dd39589617a82b1e04fd76537e0e Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 23 Jul 2026 19:39:52 -0300 Subject: [PATCH 185/334] Update usage.md --- docs/usage.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/usage.md b/docs/usage.md index 1543172..f2a4800 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -122,6 +122,39 @@ nextflow run nf-core/datasync \ The checksum and post-copy check stages still run during a dry run. Consequently, post-copy results reflect whatever was already present at the destination rather than a simulated final state. +Note that the pipeline will create the following files in your working directory: + +```bash +work # Directory containing the nextflow working files + # Finished results in specified location (defined with --outdir) +.nextflow_log # Log file from Nextflow +# Other nextflow hidden files, eg. history of pipeline runs and old logs. +``` + +If you wish to repeatedly use the same parameters for multiple runs, rather than specifying each flag in the command, you can specify these in a params file. + +Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. + +> [!WARNING] +> Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/running/run-pipelines#configuring-pipelines), other infrastructural tweaks (such as output directories), or module arguments (args). + +The above pipeline run specified with a params file in yaml format: + +```bash +nextflow run nf-core/datasync -profile docker -params-file params.yaml +``` + +with: + +```yaml title="params.yaml" +input: './samplesheet.csv' +outdir: './results/' +genome: 'GRCh37' +<...> +``` + +You can also generate such `YAML`/`JSON` files via [nf-core/launch](https://nf-co.re/launch). + ### Parameter files Frequently reused settings can be stored in YAML or JSON and loaded with `-params-file`: From 673cd47cd5a0e0712adb92733e89aa58ea829ebe Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 23 Jul 2026 19:41:53 -0300 Subject: [PATCH 186/334] Update usage.md --- docs/usage.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index f2a4800..a903ce4 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -176,21 +176,24 @@ Do not use `-c` for pipeline parameters. Use it only for Nextflow executor, reso For each row, the pipeline first validates supplied checksum manifests, performs the copy, and then compares source and destination. Rclone comparison commands write status reports even when differences are found, allowing all results to be collected in MultiQC. Therefore, a successful Nextflow run means the workflow completed; it does **not by itself** prove every object matched. Review `multiqc/multiqc_report.html` and the reports under `rclone/`, especially lines marked `-`, `+`, `*`, or `!` (see [output documentation](output.md)). -## Resuming and reproducibility +### Reproducibility -Pin a released pipeline version with `-r` and record the samplesheet, parameter file, rclone configuration provenance (without exposing secrets), and generated `pipeline_info/` directory. To restart an interrupted run with unchanged inputs and parameters, add `-resume`: +It is a good idea to specify the pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. -```bash -nextflow run nf-core/datasync -r -profile docker -params-file params.yaml -resume -``` +First, go to the [nf-core/datasync releases page](https://github.com/nf-core/datasync/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. -Nextflow may reuse completed tasks from its work directory. Before retrying a partial transfer, confirm the destination contents are acceptable; rclone copy skips identical files but may update changed ones. +This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. -Update the locally cached pipeline when intentionally moving to a newer release: +To further assist in reproducibility, you can use share and reuse [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. -```bash -nextflow pull nf-core/datasync -``` +> [!TIP] +> If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. + +### `-resume` + +Specify this when restarting a pipeline. Nextflow will use cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. For input to be considered the same, not only the names must be identical but the files' contents as well. For more info about this parameter, see [this blog post](https://www.nextflow.io/blog/2019/demystifying-nextflow-resume.html). + +You can also supply a run name to resume a specific run: `-resume [run-name]`. Use the `nextflow log` command to show previous run names. ## Resource configuration From f59d2977acc43d465d5fecf860fc5ceacd5a58c2 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 23 Jul 2026 19:44:06 -0300 Subject: [PATCH 187/334] Update usage.md --- docs/usage.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docs/usage.md b/docs/usage.md index a903ce4..3d169b3 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -189,12 +189,57 @@ To further assist in reproducibility, you can use share and reuse [parameter fil > [!TIP] > If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. +## Core Nextflow arguments + +> [!NOTE] +> These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen) + +### `-profile` + +Use this parameter to choose a configuration profile. Profiles can give configuration presets for different compute environments. + +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. + +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). + +Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! +They are loaded in sequence, so later profiles can overwrite earlier profiles. + +If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer environment. + +- `test` + - A profile with a complete configuration for automated testing + - Includes links to test data so needs no other parameters +- `docker` + - A generic configuration profile to be used with [Docker](https://docker.com/) +- `singularity` + - A generic configuration profile to be used with [Singularity](https://sylabs.io/docs/) +- `podman` + - A generic configuration profile to be used with [Podman](https://podman.io/) +- `shifter` + - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) +- `charliecloud` + - A generic configuration profile to be used with [Charliecloud](https://charliecloud.io/) +- `apptainer` + - 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. + ### `-resume` Specify this when restarting a pipeline. Nextflow will use cached results from any pipeline steps where the inputs are the same, continuing from where it got to previously. For input to be considered the same, not only the names must be identical but the files' contents as well. For more info about this parameter, see [this blog post](https://www.nextflow.io/blog/2019/demystifying-nextflow-resume.html). You can also supply a run name to resume a specific run: `-resume [run-name]`. Use the `nextflow log` command to show previous run names. +### `-c` + +Specify the path to a specific config file (this is a core Nextflow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information. + ## Resource configuration The `rclone` processes use the `process_low` label. Configure executors and override CPU, memory, or time in a Nextflow config, for example: From 13c631482715313c8c055aebe8f85f7989892e72 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 23 Jul 2026 19:46:29 -0300 Subject: [PATCH 188/334] Update usage.md --- docs/usage.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 3d169b3..cb2553c 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -240,7 +240,9 @@ You can also supply a run name to resume a specific run: `-resume [run-name]`. U Specify the path to a specific config file (this is a core Nextflow command). See the [nf-core website documentation](https://nf-co.re/usage/configuration) for more information. -## Resource configuration +## Custom configuration + +### Resource requests The `rclone` processes use the `process_low` label. Configure executors and override CPU, memory, or time in a Nextflow config, for example: @@ -255,3 +257,25 @@ process { ``` Run with `-c resources.config`. `rclone` derives its checker count from allocated CPUs, and the copy step uses roughly half that count (minimum one) for parallel transfers. +To change the resource requests, please see the [max resources](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#set-max-resources) and [customise process resources](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#customize-process-resources) section of the nf-core website. + +### Custom Containers + +In some cases, you may wish to change the container or conda environment used by a pipeline steps for a particular tool. By default, nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However, in some cases the pipeline specified version maybe out of date. + +To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#update-tool-versions) section of the nf-core website. + +### Custom Tool Arguments + +A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. + +To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#modifying-tool-arguments) section of the nf-core website. + +### nf-core/configs + +In most cases, you will only need to create a custom config as a one-off but if you and others within your organisation are likely to be running nf-core pipelines regularly and need to use the same settings regularly it may be a good idea to request that your custom config file is uploaded to the `nf-core/configs` git repository. Before you do this please can you test that the config file works with your pipeline of choice using the `-c` parameter. You can then create a pull request to the `nf-core/configs` repository with the addition of your config file, associated documentation file (see examples in [`nf-core/configs/docs`](https://github.com/nf-core/configs/tree/master/docs)), and amending [`nfcore_custom.config`](https://github.com/nf-core/configs/blob/master/nfcore_custom.config) to include your custom profile. + +See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for more information about creating your own configuration files. + +If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). + From e4b7dddefd12cd9494c38acc319235ee9df39528 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 23 Jul 2026 20:35:59 -0300 Subject: [PATCH 189/334] Update usage.md --- docs/usage.md | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index cb2553c..5b28f65 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -25,20 +25,45 @@ Each row describes an independent transfer. The header names are fixed; columns | `sample` | Yes | Unique identifier used in task labels and output report names. It must not contain whitespace. Use a unique value for each row to prevent published report files from colliding. | | `input` | Yes | Source file or directory. This can be a local path, HTTP(S) URL, object-storage URL such as `s3://bucket/prefix`, or configured remote such as `source_s3:bucket/prefix` or `source_azure:container/prefix`. Whitespace is not allowed. | | `output_path` | Yes | Destination directory understood by rclone, such as `/archive/runs`, `s3://bucket/prefix`, or a configured `remote:path`. Whitespace is not allowed. | -| `checksum_md5` | One checksum column | MD5 sum file (`.csv` or `.tsv`) used to validate `input` before copying. Leave empty when using SHA-256 only. | -| `checksum_sha` | One checksum column | SHA-256 sum file (`.csv` or `.tsv`) used to validate `input` before copying. Leave empty when using MD5 only. | +| `checksum_md5` | One checksum column | Path or URL to an MD5 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using SHA-256 only. | +| `checksum_sha` | One checksum column | Path or URL to a SHA-256 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using MD5 only. | -At least one checksum manifest is required on every row. If both are supplied, both validations run. Checksum files must use the format accepted by [`rclone checksum`](https://rclone.org/commands/rclone_checksum/): one hash and one path per line, with paths relative to the source root. Despite the permitted `.csv`/`.tsv` filename suffix, the contents are checksum-manifest text rather than a table with a header. +At least one checksum manifest is required on every row. If both are supplied, both validations run. Checksum files must use the format accepted by [`rclone checksum`](https://rclone.org/commands/rclone_checksum/): one checksum record per line with the hash value followed by two spaces and then the file path. Paths must be relative to the source root from the `input` column, not absolute paths. -Example: +For a directory input, the source root is the directory named in the samplesheet. For example, if the samplesheet `input` is `/data/run_001` and one file in that directory is `/data/run_001/reads/sample_R1.fastq.gz`, the checksum manifest path must be `reads/sample_R1.fastq.gz`. Do not write `/data/run_001/reads/sample_R1.fastq.gz` in the manifest. For a single-file input, use the input file name as the manifest path. + +Checksum manifests may use a `.tsv` or `.csv` filename extension, but their contents are not tab-separated or comma-separated tables and must not include a header. Each record is plain text with the hash and path separated by exactly two spaces. The required fields are: + +| Field | Required | Description | +| ----- | -------- | ----------------------------------------------------------------------------------------------- | +| Hash | Yes | MD5 hash for `checksum_md5` files or SHA-256 hash for `checksum_sha` files. | +| Path | Yes | Relative path to the file being validated, resolved from the corresponding `input` source root. | + +Example samplesheet: ```csv title="samplesheet.csv" sample,input,output_path,checksum_md5,checksum_sha -run_001,/data/run_001,s3://archive/runs,/data/checksums/run_001_md5.tsv +run_001,/data/run_001,s3://archive/runs,/data/checksums/run_001_md5.tsv, reference,https://example.org/reference.fa,/data/references,,/data/checksums/reference_sha256.tsv run_002,/data/run_002,archive:runs,/data/checksums/run_002_md5.tsv,/data/checksums/run_002_sha256.tsv ``` +For the `run_001` directory example, `/data/checksums/run_001_md5.tsv` could contain: + +```text title="run_001_md5.tsv" +d41d8cd98f00b204e9800998ecf8427e reads/sample_R1.fastq.gz +0cc175b9c0f1b6a831c399e269772661 reads/sample_R2.fastq.gz +900150983cd24fb0d6963f7d28e17f72 reports/qc_summary.txt +``` + +For a SHA-256 manifest, the same relative paths are used with SHA-256 hashes: + +```text title="run_001_sha256.tsv" +e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 reads/sample_R1.fastq.gz +ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb reads/sample_R2.fastq.gz +ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad reports/qc_summary.txt +``` + An [example samplesheet](../assets/samplesheet.csv) is included in the repository. ## Configuring rclone remotes From 90155e6a583df836497b46d5bd69942bd272f9be Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 23 Jul 2026 20:40:40 -0300 Subject: [PATCH 190/334] Add files via upload --- docs/images/datasync-metromap.drawio.png | Bin 0 -> 59786 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..2f17a1e3af56ca896c5835c690f6387dba354e61 GIT binary patch literal 59786 zcmeEv2S8Iv`ZypWtX)y8fFgrL-u?FO_U`Yl?!GrOZ|0k?&3t7h#|-tgmj1NiCk_sd zr6_H6V-61PCE$6Cmk0b;6j$lQ!4arR(XgZt16=V07YYZ>dp3DYl5)DrvIElhFr6pjXO3VW9i6!}y!K1z@_>UwE z6eCo@6R41pVmt=ONbLkADqda$7Yi3>T|DSlQyL*Ffsg^kV!GOBPwT5wT>hA2!0G==^k)R-s% zFP=_dY&xn80anDBpX0HNGG7l%H?l7Uujg)|udN?oX63FUKEF3spTqzyA15z2GzsfM z03Blkm;lMkGdsmnnI&@aQVb|@KCFS5O`rl3JdFvFG_#d29_vD8e#HdQB#2hNA& z>xpH|`=1(~Z06;uui+bjLThSUtGc?wNh+%1l0ZNpOuArMB$}bwEI_{pIGI9aNrsCj zRt4e)fPPPsCjed5jY1@VH%ahFhu#I^3+Rmuq|Rf8*piR}U=*p52qcD7A>dNZFs43$ zAY?-a1oH1wZkB#pEF$q# zFbjww2@g~v9LAJdad{>LOqmszgu$34tg*->UmuJM^E(Iyf1m7(;r`~JaHhbs#*~+r zmyl&nnl&oL$p_~``6ot20ClVhbQB9izfU1%Yr1&-y_Vld;dfb?i9M#0a&l&|C9|Ae z!u}vbLn7zJkdJxX2iVcYhvLH0z<&ZmveXhevdu>2*3RK zRQQhi_&sW|sSlvLy&yTn6Y0x^suS6ZvDmoc10cnr%B)bwI#HZN5h{#VxF*>TCkj^$ z0GbA_W~eSNc?0bO=_K#sq6MRfLnJF$twX@O47y zyIWbR5>RSxB&@cvzX4v(4~xJe^oX-{dPI4uHC4_Fr3RxI;z+uN+WK&7e-aJ_^WP%+zCv1OgVO zucqRUQbz^oxodzvtPtRtrss|eK)ajyqw$RX=3ycLg`>mZWevW^Agn$0X=pgB zt&5f<+1V2fu;2#6YOBcTQRTs`FuqtC+SeJOfU{Gjic{QztS_+n^YG%OMG z$G&ryg61h_tz}Nc(D9*yLunB_3{7-AtSzi*03JyL6BJI5#%wpY4cW?)K)|?b;MMTp zJAf|?!dTi_3!fnGsSny3 z6Li(l2t9Wd7@z|JP4%asO^y8Z+)-2mQw@Z!2@2u_#z=Au>M=%jvM>T8Vgd}*jie0J zU^G2b)C@#`!Y~X`(-#A`_QMci@+eQn=+0W2Fl!SW7{Lmz=WZpXPcxF%Q#S&mTT%7Z zJ*4%i9_)S4u-XK&HGmfIEDfU-;O1iL<>gEa0DsN!fTQTMhcJl&{W_`4yh9wupe|Id z4*I59QS{Yd{(7cXZ2d!6(TBNM1P}n`iB1*)WCOfD(VG6Rl`Oz2)frA9=viXDthJ3v z2JR}pXm_-~K23!>gH?ciFcw5P3QAprhQ>=lScB{1{iOltN~7H|pgjtQ#j8+(3K>8?YW@KKQc?z{W>RPXvlUgvAB+ug0$g9+42-Qp zL90no_1%r2w$QUA+T8=p$q1)ss^Y6}3c-sZ)1PS`fQ!wjC@p_bXXFcLivV~5b!cA$ zFegBFDU=qP{vF!g3Rpon`ghD{DKLL9t{I&J88FbF;reQH7^DDR0ng2a0pJwOQwoMw zH-qV$s8GOMq|r2tB*3pbqdyG&T~A#Fj0?054dQSVdG0*e%1xwbXa)^%Xf=OGLL~J~ z%_IRH{Pol|U_j#ppiMRW8SgV12+$s?2l!y%0DQ~D6V)GRDKr(}j0$*Vc6`=2cvTWg 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 h zcL8_wNKclmKNK~&m5n=P_OEWo$<O1o{lqH{)Pfr!p?+6V3-923C z=+9^J2540Cy5)RIde|<&B~&MzGM;sl&(AKtghrR)Y%7dwxjqL10XPqFgTPiC*fLuas<=Kssm50*(_he>=kL`rA zUUsbv2=0Bm()8=2>_&T*G5W`_h2!awct8weJKWC?`K=SV?P2ihBP#l@=$1=UH$H9b zuG7AlKvrS{3RM=YyeX%N%}jp@zB<#9E=Lmh zJboM5?3=3N_jmY)vQEQUG~QHa_bdD)!}^BY3NA~s(ylQkGQQR>-c+{hVVdHRfh$1?Y<#bV*t}L&bpW&o!+$8axz8Vg{Wa>M-FcLxiV?ie>dnQ?f>tkN@pO^5|qjEJSn_KtO*;NF= z+T}ex_54u}Kd<2AZI?TG#b?z&f>%je?$SE$JA^qvuHVlAKvh*0)uOYG8ej(HK>=23a3ZuF^vD)rMn+0)#W7B=?^a7dpZdF3ka9bYMw4*dZd{r{j&DuP`f0Ks6S^?31>b&_jC@l#m@Xs zA8*GSOrZjapp)sXK=^f$s$KwDg71H)px^7XsNVKpd7S+>n(yUJk9ym|7Te`lxt2`I z2hS0ID`B-b>7pIe^BT<#$vxFy#fF%-DkjvwgoQNkAD2HC(2`%??f34ee(Whz6H}f8 zZ7z#=d6wmYV;91~vWq);%q7}61aUI=^<=x^x8h!d30t9;26he6TmHGbvCz70)iV zxB)~p!!to(l1X97jnu8#-G{Zm2i=?_8--Me15>NK2@mCm>JO0oGOY{iZ}%e*AbHs+ z85^&Z>v`FOjYBn!lrjkb;659H&Rx18w&TLTt=lU!}K1j>D)&Q^=F2I(UIy#T#F2D>m z6+*S*S_!OW{J*^>T>#c;{Hpxni<52>>CI>M1E=ujzwK3;hvz&F){ntj`1kpK4omZ4 zSeJc{@}~#YE4!&A$>vEv5jhhNuQ~j zN+*O1)^f73sl#<^UZx6LJ#y@oi6}cbd{l`~_ukvcoWQ4f?|U@Vc@a0J^G!Vk8vOop zU`PhotSna{orYT1*i56z#{PA5azKDz^ZtYb-3Czrx%_O_)e+@1KKqA01tRG(wT@n< zX!;c@JKM71*&E?Ap=38I9-D16D?9V&YC2^0ZC%Hm`5hG)o66DtVC7oj?LQ8I%P!!W zCgf7x{_V6_SCso`ZN}VbB!^_nZl+j6jqjJ0^byNh+40@X^+|+J69P7lfcxhM=Ll9aGTK$akWUW}-n_DU!1#0IT@CW1w?*;ZVnJdIs;ivumQhAe0O z-@Zj+PaZ?DB3=DBwc}gAkgks%jLS-qzO4^U{2;rL8^?_!+QW7~!Qj)!B~FiDdy%SM z*9ej3Ea$ckC*)54X^HwT8sS$n?ZL(!zGsCymEUpqO=yAF| zEkJu;@|_5koertQoBix1^#A=ju}m?6H{0LRbx%Mz?1_EaKtEeG)5A7qBc`##oA`i9 z1kg8}BMLXBEoU3yi0Ph#0}mW}cX*uG>*oXPZ|pTRcoFvfhlk5ncJRJ_i$QI*SfUsn zR*zSmiS?A7p5Qp8L;W!<2HGw0s+LSUes!5Qxq9JoS*TsW?o**sB{qwuUo;ypZyIj- zJ3-L$p2a}>en*e}JI7-s?*Mh47tpPBCy3{8%wCOmk;IbJq2~}PqH8Awg7r^1uxqU4 z*7GA(MgLjAj!T0jA`5S?f4xe8NyqB#hRjHUjnNW1H&>Q!<^19HO>c-b&AcOtZNUC@ zy8`Ar`?L1;d>5~}s>)-7-bQJ5nE!sy2}4%UZU*%1H>$h=*cjhRF2eYlxCTY6rFriN zJJ=n_j8+))H3Eucu^pully*Ol}j>fY>|PKM^?L zW%(0!`dDod*F0E&UUu~{bATKS8_ib4UHu zz;2qQYs8wrc}aFnc{g!dr7FHa!xl`JYbUiXlTZ<=+ z+F~WWi~2~f%hp`XNBqjIi z*J*2Ab5ufSuisneNPKcK!=l;m`1rp|!o+gSR;Xt4Oj`lk;dJ_L7_cbJqB6S7+^m!-dC)# zQ?zQgi>&jBCF|6ZoVMP=fYL2~vdMgyHh~6=Zq~JJ)U)|62Ob_(19L?`JprSM%Y8Il zSf$}9z*2Qka63)N8PzXn7o>+a6HGIjEk-YYB+0Jd1@o{xn6R4Q4*XhCx?iGUhpq7_ zovD=>wZ!_H&ZaE`%S5$LN@>l}<+GSIO6uE9)BX5&n{gov*3E=Qqnth&FOYe3|pZSZ!7oI!__vn{9@bJ_YQbhwM1X}ZO zh?i-_%N)><^7H|PaeZ}5PtSJkc~8m_@;=SxbF>QpNm8yj7s zkNDkzw7&L!jMTj&J{9h<>5u2&wbz8hg9d7MP5 zVWhOwV@OFHzg#wwCFS-d^Gz#FVaFAbKb0F!SyF+2eemtVUzuee*!8G9ce}<~(~?t% zHn>)HRC_?UBxt%g)duKu?`zJzL7mx{qzx0A00HXcRq557#dhQI%|^%XzJRJQl`2D| zZvW-OxZJtUs@Cz4@155N2!mHD#OGJQXZ0K3+OF0BHR9jQCKjJrw`T#yeeu~lS{ig) z{%9cJZqg*sWn2!c$I4A8v^`Lud3+bpt6=X}VgWS^;oT;nSsbnEHUhaoeV3U103A-k z5*7_IH!*>;UV-`UJ)>L9V7X|hNx5gMlL>cl8Tte%;~oC=a{5-^K4WBe&gj%ihI@=S zVC5_sNK}2-D(Vrp)&F)rDkGSd%Kc;Gr}nAFGv+$Cpo3$~60G&y6(=e*IN8prz27di zcaWu&M+fDyq|)jd6-rXlyKaRMwQIVgKxUQmYY ziAszDYNavyr3jUM68_mu7i&PV=|})spnu}8jn~xFEZ(+g63cYQun1GeN|8Z6`u)}a zU{(OV{CNFan{z0g#J94V34T)>q|qy2aK*ZyafLNY$>tM)^;tUcVqf>xP^G;|eJqF! z5C<+Udy9k*nwq`@d>^cacN+-R;OK?Rsh%)0(4VF7i|@6J7+ASNROCow$O8-0X+|B{ z&yBYa0aqNcCcgqecXj%A1#G7^$ySuDIXPCF?LE(_8%@dHsJBx0c1e5t-Cj|qU(&*= zUF0=DAy`iF%soQuMUaqH38>U>w^ve2$Z71O0zx~}5w=sg><&0XG*=XE(aH`7kf!qd z>hw7|Lt7kX281B@m-p7;$-Le7#BG12RC#kmKhHZxJr@E?HJ@2OR=bPe^|HJ!B}G8xJ{y@Uow;HTv!%N?4YE=h2895c zS?*gl$0_OxU?G^HBd{4%eZ6vUw_9qR18GRz2}~L$>AsfU_?fF>AeeZ753lYyO{y<#osPKCaX9KewqVWQNystoE&dYVt9!`~bOnbN-oI!i> zk8A-)bwfYti#x!oH8IR(Y+a;nvC()Db+Dc;n0c~EHv#$cc+A$ETB)zwjPw_Sl1z0rLFw#fP6lwsme6JrAo?-jn*Ta`FBRbqhQS9vO7*%`# zK+gYICdEuElHlcv;F}_>4xH^hbeFa=R`}R2nZGV@f@PAXs$(Kl1QaUuoiy>ufnlhkpoFa04DLfK4laE-TIH zSbnl3H~Vv1A}FUXF-D@W@T(78AJSrkoDnsynDuTd*4?|8<6CANu!mUu=~>v4^Wj*} zSZgrvB6?DUwaLtwa+Q{nKRtMcF)v$XL?2_TlFRLj9xmY?$9x3l2ikub4_!w}%N;8G z=L-B37R50&cS?cGl}*NtziC$mxR*y9%oG2?NO|4J#qRt^aUL=R5Q8~;v3KSEBS2qF z|DP3`ZU`VkHJnpK^!y`F*Tqq;{*T>W%?5z8Q?}3K|9+G16s7&`|4Pg|DFDT$Z?O93 ze|7C4^9-Cq|2@e|1weRF^SlF8|3EOjcI10>{}sR|asi*@_Wf-y_RsszEe8MRHj<s+lO{TT?K?ns2yzZHQ`MFgYvVJd&u>TmFF|-N%#CL7 zDFNV1!jl)wLPT5aJ*2*e$OTy(9kerPt&flyVNoz4_j1ar(ci z{bb-KD&(p>XvvvX<|wvyJ_=4}!gsz)G9s4t%#82k%YfCM-Z@L;$%mt4&hFN8_zvXJ z$9HQ7_$!>;%`~R4Hwq?bsG}P1$`7BFUn<%VVVJ^Awq$PH#MX{5rgy_fHo3m- zW>4g8a~5nwuMrX-{OI5)k=?ZM>_$};2Xy^H$(L^NE0B!L)Fv+*WDI>skLHT6Nm{dR(eXEV#&7i=Z^25un8QD#;!0>SPq`7in~ zj=tdIl|2b+s9oZNQ$1Iy7eX}bnk}G`E~Rb1UJGIO0Oq8sMJS^s+ilFBN8R_KCo)GE zD*sK-dfnHmmC+qVF}i)O0YQ53Zap)tD1!&zIg+HRJx8re`-9}}!M7PkS-KA(3G<3e zVVH=Hn~B;1;7-Qkt+kKG`Iur7zmkL81d||G^+be=cY~EavHW|JAi}@<4i|-r$s(u3 zlgDOyxz3KL2>}P0ZKGTN_$N}6qhDWoRcKt^OH>!7YZbW#UY|!J(b%@GId)9mll*R% zgUnyD$FDU=Sp(ifEm_*y*w<`XNhT-p3!@y6gX-Ax-ny6wbkmH5d|`lrdrxEE%EnWg zRut4bnHOoB672Y;G_pS5C05%#%^5VuboL-G)Q<=HjGB&`_&d0jODij=j1GGR`M{zj z?5$YbaNczhM|*~%Lk7FTrg=5*?qh@1>eHowEjTpQPe@D{~K9t0h+a)R#ufphzrM200LC{r=)ofPB9Hi8F4+Yp}>+R8M zy`Rf;O>ZHSp1nh!hVxNCZGV&bMb&>Huot+Z_%nOT555j=x^deUdSsIlFS_awGP%@VJ<|s^ed2u{k4;PVj zzyY_Yk+=6PNiOD>H?n$}$)4QrLT4!cg3gnYB9vDAuI5h)tvzwot5z+lxg^6^;rl20 zxhGf?^AEs8&z}&CfxdHlPT9IhdOJ%)WiBUDxOM-CBV)N$TqpcOfNNOi#{eap9_rjA z3QW2b1guow!khl|uvxbj*(NfeKCxe9?V0L-e&@jDRy3E~$v?yi_CA#llY*SRt^Hy8UydIU{!J_3hksPAZ z@pSSWL{une>@0Be;S8Xgy#w&B|3IF;4*=9Ihb*6J*db{apcf{MqBsC^x3XdB+45b~ z)mVU>RJeA1fbx0lwITV5$*B(azN%I5lmcdKvDbVI(@s8ZImDxAkjWjO zSpN;YcI?^?7YVH!lN{+tK)!t^#@BBg+IjN5FDz~SIYQjiM`P1FBO~gSnU}1!Kge}56)xqn zM>~L3dsO|**%*fMkNH(Ri;yF4s+C>T=`^Otf_1#-Z0fY=Oh}IKZY{bkCv##EW<<;} zc7nNEFS~+hw4vI|Qe*Q?m(6S^XT@f;@Yi3nux|}^y0_zNn3okJWv0(cX%F6TKh3Fa zfzo(}6g~mGf?GXxsV=aoiHFdHUtqHm1r2)Y&Z=F;RvX~BUGQco6-FjW1{|yuUrZ>8 z=G3|@Ue2z{mS1c^Zl=cyLm36ZEQHtTvDhQ*TA2O%lBF?1%+)vgbzvQLsnt$xRumF~ z$qkqu7^v&>Zpe^#6{#W`nV7tk2-nGx3~foAXMq@V`!6&N_WRaH00WMo_=3U4QKVFc zpI}hwpj$}ubz#v7x|1daddMrTZNqDU8KQEySGJuq;xkP%q`}DT0*YPJueYiXa(vFK zgqiqKhsl>Y<5$6j>f=o;H$d8$eeR?(;cCc6hB z@W4668hL8*O%tYPa0H|6l97eXaY|yB#_-!2zBybhaHCG(PJLKUwbv;!r*_RKYgB@u6my5 z@ihh~_wqt$v(vs)cJVR{Q7Sn)rts{Ez{2-Zmu$7a8731zP2Izo{2E?VD|b?H1#<*v z+^6q;98x{ZGeY@Y4IItM*K&K?3^F-N2fLZs$ez?~?twG|sjpy$!c^$QBeD0TE*ngY z$ih&c*Wl$EAbKL(Wt-J0>>3*zqjjflo&QFULQa23Ykr)BsD&G^&bf;~5&Gs|=qHW- zuUYGX-0IH~#2dHF_7?zfCrLdx@E>mmPTB>*ozvC&!4a}dD&GnEq3?qUMBG0?7D0(h zE}=x4E2+$8SpB{OIDdG~Xtwe)Jkiou$zKBMovq(v5SWyZX6&NptLW(T!Q`k!g?%OD z?x%g`6-9^;*@ggA6;bu?takk{R&res&NByNQuID(UOs_k4~uTHv|gkLMvjWWY{u9) zR%n_jum9bii5b}w$?19%$NtlcgJ#c0Shw2s1T4oQJ5EwhjOMAp_yQKvy!Xk^4TXw4 z$kA*$E6>^$DMYm9+93DB)L`1uo)ureaccF6ZyTgB@Id>MZI|`r_{~F&3O?_pWb;h% zt5BFur|Q?`@5P>kFHGa-tsf4kca9Jep-V-wHo7-QZn#_m_Q%{+^WKblhDk^lkaTO4 zf3Lkx+2o3-u{W(BD#~yUo#}hIeI5+}hM|y^QO>3gPKyp}&e5m~Vf04m6O;;7B3RZj zM|gw&8SKu7WeYR8$_%^2Ee<3r^`4zDZ@9z|kR9aQA%A)v#ItgdX}$ME0PY6F>$Q2( zyH2TyRwjg4al%p`S0uttMO+PgK_^sa=`$*TPF1{E=epPFm8Ebo*m&|9_0s#0!t?N{ zTfAlKSJrY^ZI2U8=@9;PD#59~G`Xqdb+uxuSez02Xu)YwZ;64MVu_HrR*^Xs85>m< z$_o_0D>+4H!1_;gv`$%-rhrw@`XRaI?EDDQ;qggZoZMUD8jAJYA|yOd;U;ICcCg%e zR&&IY6ZwtjM~MpKYXP0n7y1cr!uYf)G=QL4!|1tSNj5oMzfKSKf?=q<0GJME^OU+7 zlbjw-oa}l;)YoLq}-05dysrQ8d-jMxa1Nk{$1dV>B(J-Nkuco!bYn*;QsT_ zhE2F#={qge`H+r^QFxwZ_946ppR^|~OkDlqDMH(+kfZpztX992PV9RUS*y3(`5V>W z1=ChoT}M*&ya7=lYbyCzX~gQWL?QDuhC+NpG?^7R9fdYTAaf=C$k}MDN0Q1DM`+wH zT%apH{~rM}mn)#|R&N7gVP1>aU%tsd9L%jm9y-a;EJDv6xjTiR>Ov~ydwf_*Ywoe0 zo~mdmxDEc}Q*V$>Dm(f1+sH{U}eD_ul()8!q4r=%){ z3f;c`@IlS(?!o&P&2Tv?6z}$4mj3cbYZQ7pFo$wz={CwYOCJ!~23ELeEk{{4K%b7? z<0LGsMuT0=9J7sLW^N(32L#!u3~PqMyl>|(oBR_#0>+;2@o5w1>pfyZ+ekGJk3bfq zv(}E`X@#{eWtIa6YIU21g$5AVp4Ke=U5M?tNMHAd9DlR<2ZQF_||bH-Nr1>>bX5 z7?$W3JYSCViiCmt7Z9-q%)z?{bCLyzF61r%j!8HQ%9Mk(Z_j;rmUT~n7B<^ z&u8Ag>_raW3nLpgThBwLkCi^&+?%iNCo)pS@ju`t`s)ZhiM?k(01PGe9R6mibjQ#& zp**B9|j`Ji+wc9U-$s>{(smjzDyNA4rlz<5DUJkyx@6pjjKin|z?pl}037_{O z&FXQHQ;JzU3^E)T7Z|`vJVrPz z6+1|jf8T}mv#VNDoP|uN_yXopoc+Okm^sR#Z&lRx-%*jyu275m^-ny>^W$~_WMK^{ z?fV6JUI20fU<30#=H9ODPaTfeKJpB!mxhF7tt407w!DlGQ8!Ifb)2jG!6}owtGSZi z*Pv)CaIy#+gRYo6s)!d&_EA*Obu$(AYfDMWnJ$RM_0))PM*bq`EEQcHO=2&rDbgyo zvN8|t)AE1d$xys|(!f#3OtzUikyB$Yqv~RmZe&MoAV137JrwBpSp5Nol6|)E&G*tw z5&z7lATkJu_!|CZdbnES)um5Ctwf`Qw;Mh5qyeIVRXjm^o7yEpj9_r!sbwS`rWOTn zt+CsBo9d9nqYAog-8jbjz?wRM+F`MDogo%_0Z7a*Ur6N-R|;;l(Nus^r?EQaARB_# zN_fy_kSH z!y1?^>CJFf^O^sABdLlL8P2aU+KF#9)V4?P2s$EK#Rik^Fb(aEv9M7yAz11hf;k=H zaza8e{zlp_%Fv-tZZh4O5CVQ@AxUCS1+(w@^@qizbRfU^P)+L(&2__{3I(tvNmWk} z%70pXtY(uRkNnnJm2HL~*o>9_+Yl`^DogNCv4J(0?*(M}3-81(jLd11HU*$--}R3Y zwQ&V+W^hx(HLZqO-CA-iN-2a(#RBTH=^h-V(Q)$CF>xv`G&_XRF$VY=-u*^*x3RY4 z#IOFBj<+WN31ozUwbT}WqBu*VBovnM_}pr1MV0TH4*An3IqAV!CSyIXE1DRzyhG@5 z+K%Y^Uukjx$hO$^eZf+iaJX9jrF25X%BO0fFtw_hP_g;OhwFQPoZk7u5qca4=!}W{ zE*Fzv*Y)`!5xaxy@U&+M6Xx*)dqKHit9yykZi9|w1y>W2PLHoAQ$)F?R5?Al<5NsW z?-wG%4}`WOg6*CcY2PSysQ*f`uyG{k0cOgVUf(3Bcy~0H5YEyV>As0Ro@$v&of4A{ z%?@o}YvF;T!d-1=rf|-IJ7mDFTwj6Veaj%<4?;i%WPeqLSM}$Rv)o8^X{{LgbWQr! zf+$@Yzs^#)&rylV{CK`p!JxP$w%OT%8VHg(g`I(Z6#nU3#g&``239IEEf}#e&9bJj z;YX^nL+ZE9%Z_a23u4brIMgP)OI_N-XsU^*$9V;Vm#^3mu`DDH{qrYr zR%bVsGurf{ShHMThHKi!=p?>V@$Z$T4<8SCOOMM$fQY%ubTU9~W7v<%Fs9ppjZlqZ z;fW0Cqf5HBHaczJbU`P8PIE-4-N`7@*qXPgPc+lDcqOLw8fC?`xLmaaX|__2(@#53 ztqR_|F7Uq(=2@1$q~B2LRKaslY!$#3+)?Ci`(%W)ru}OIM}XHVPL!}ZnOrox&FSU z~jskt_Z%+b5XT|wh!C7YsQ@*1v; z?mZk#2GQ{7Q=RA=dzCpX9pN$E>BV8wqx9VO+Ca5(xH?h&r%vV-wAX6dS9c|>Tf5r% zLz*5XO0tR>#ngDxja|OMb^(}-stu_0+b^{hwHgHu{KQ-{HrQC6WW92W9LOFz?*L2K z(JOOG?qN#mMCOndZCL{ulwvl|k2F@h2J?ip8q|ic9`?H)PHbny+Soh1>duIXxw!Di zb$!yy7U`_JwDJL>y#?%7^r5X1ahUhVZBH#3@3=% zqZN>p2jq%CUR@CKWwQveJeUswT`}}p7O`K_vn<#u6AE$hsn0$xby-ro-C6Rm8WKA6 zg0ibIy+E;?ppi?Plps{RAtF_@wNP4fu~>jT4)ke3>E=kR^GYz)HhaoPJ5>ecBay};@6K}tREZqE)2D@C*n*Pq~4W}*8bR2K7aO0jutzJd2y^<~b*D}g`?q?k*q zr78ZI&f$d6mZMKamc-ai?Q0lo8C(=lt+S*4AS{WNL{#=J`oXnlL>jF*MiIn9jD3ss z{R|O=F8U2a`6YN&S>3!U3IDNDYAwZjAL2qsq9>NhIl_-#2-p{FET=<#<+OL zFK4sF>CIYtlXP`KGsd2+lnRl{@Q5Z>;sbn5%_i5wF=C-g0D3Z!oCr=RZr#0mJ7ENE z6mk4T-a)1@RBAl@hb!SsxCK8I~aCnCjdG{{F3@gOuM3m#qLoN_om6*RW+c-wlgjS)LZP7Db zI^w+V#r{{=MzKZ$K|MiJfr5kXy_mw#Q|(cQfqeMKu!5D#!;5;}FM;C7QB|}hF458| zo~KUz0pFP+{fJkJ^)ZsKiNI%Z*@jhUz^~#m{}cM5k}gg#5v;Gfx1PMXxX~ z-ZBDjW`33a@2j}#>|&sVxKSz;1y7Vuyvwte*IMxFuR6kuS5Wl?$gsf)4!lrYqRJ8| zGv6gF?3A}`pIPvg3N#~0+oohDCl2a1&dM)asZ+e6+ju^qOK%y5w=$gfWDGF8lO5xX z&Da8JcRz(#s(4H%?C3wE=uei?+P7I8@zfwg|Lppfv%$%x?I}QeQj8&Vb><`)hdwex zB)6P9JOY0RWEj(u17+d@9>=rbU@8@M1qZfeYQt>fg5*@~gSZ3>_Nn@a9*U69i(mhZ zOk_Pi-2?0uMYuWh6ooCj;e(Q_SHyBnQvME*;w+y9GZbzyvpq^Oj^8m$IAsum;+RW^{695?o@!coRIb zaQ-0l&q2V{6X@)~t)1_q6Rd@Ke literal 0 HcmV?d00001 From dd4a55215730c57cf024cee99e11cb7cf83eaddb Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 23 Jul 2026 20:41:12 -0300 Subject: [PATCH 191/334] Delete docs/images/metromap_style_pipeline_workflow_components.drawio.png --- ...tyle_pipeline_workflow_components.drawio.png | Bin 81474 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/images/metromap_style_pipeline_workflow_components.drawio.png diff --git a/docs/images/metromap_style_pipeline_workflow_components.drawio.png b/docs/images/metromap_style_pipeline_workflow_components.drawio.png deleted file mode 100644 index 2f082d2523712740d8cd49bf4a69d72c062898c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81474 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 zK{js7695G Date: Thu, 23 Jul 2026 20:42:26 -0300 Subject: [PATCH 192/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2b08fe..b681bad 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). -![nf-core/datasync metro map](docs/images/metromap_style_pipeline_workflow_components.drawio.png) +![nf-core/datasync metro map](docs/images/datasync-metromap.drawio.png) ## Quick start From 3baecb63a50f0893ff04cca2c41dcb7e8ef4f5c6 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Thu, 23 Jul 2026 20:47:27 -0300 Subject: [PATCH 193/334] Update output.md --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index e6de4ae..1286736 100644 --- a/docs/output.md +++ b/docs/output.md @@ -101,7 +101,7 @@ The MultiQC report consolidates: - the validated samplesheet and workflow parameter summary; and - pipeline and tool versions. -Open `multiqc_report.html` after every run and investigate any non-matching, missing, or error entries. Data under `multiqc_data/` can be retained for automated auditing or downstream reporting; exact filenames may vary with the MultiQC version and the checksum types present in the samplesheet. +Open `multiqc_report.html` after every run and investigate any non-matching, missing, or error entries. In the rclone result sections, entries are prioritised so rows needing attention are shown before successful matches: errors, mismatches, and missing-file statuses appear ahead of matching files. Data under `multiqc_data/` can be retained for automated auditing or downstream reporting; exact filenames may vary with the MultiQC version and the checksum types present in the samplesheet. ## Pipeline information From 18e1b6b4a488308ca7832f83c8e5bffa91813746 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 08:31:55 -0300 Subject: [PATCH 194/334] Update usage.md --- docs/usage.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 5b28f65..baefddf 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -303,4 +303,3 @@ In most cases, you will only need to create a custom config as a one-off but if See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config.html) for more information about creating your own configuration files. If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). - From 98c775ee85e267ec0a94665daac763c6d8d7c936 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 08:39:48 -0300 Subject: [PATCH 195/334] Add files via upload --- docs/images/datasync-multiqc-checksum-md5.png | Bin 0 -> 119323 bytes .../datasync-multiqc-post-transfer-check.png | Bin 0 -> 123499 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/datasync-multiqc-checksum-md5.png create mode 100644 docs/images/datasync-multiqc-post-transfer-check.png diff --git a/docs/images/datasync-multiqc-checksum-md5.png b/docs/images/datasync-multiqc-checksum-md5.png new file mode 100644 index 0000000000000000000000000000000000000000..42968b7b0e0e681fe79e8c104b76bec0f1701ed6 GIT binary patch literal 119323 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

    f{pX2yO1af$ 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 z�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%0A_JusSVF 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

    Z=dhQ|E*Y}6 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

    KHoy%@^4sncuZn?&gN8$LZp- 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 aXJ=-=73Ev=unw@-{kWy=u`+YltN#XIC(y9~ literal 0 HcmV?d00001 From 331046befab8b9def62abea0e27772763709e2e7 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 08:49:17 -0300 Subject: [PATCH 196/334] Update output.md --- docs/output.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/output.md b/docs/output.md index 1286736..4371f7f 100644 --- a/docs/output.md +++ b/docs/output.md @@ -96,11 +96,23 @@ Empty category files mean that rclone reported no entries in that category. The The MultiQC report consolidates: -- checksum validation status for MD5 and/or SHA-256 manifests; -- post-copy source-to-destination validation status; +- checksum validation status for MD5 and/or SHA-256 manifests generated from `rclone checksum`; +- post-copy source-to-destination validation status generated from `rclone check`; - the validated samplesheet and workflow parameter summary; and - pipeline and tool versions. +### Rclone checksum sections + +The MD5 and SHA-256 input-validation sections show the results from `rclone checksum`. Use these sections to confirm that each source file matched the checksum manifest supplied in `checksum_md5` and/or `checksum_sha` before copying. + +![nf-core/multiqc checksum md5](docs/images/datasync-multiqc-checksum-md5.png) + +### Rclone check section + +The source-destination validation section shows the results from `rclone check` after the copy step. Use this section to confirm that copied files at `output_path` match the corresponding source files. + +![nf-core/multiqc checksum md5](docs/images/datasync-multiqc-post-transfer-check.png) + Open `multiqc_report.html` after every run and investigate any non-matching, missing, or error entries. In the rclone result sections, entries are prioritised so rows needing attention are shown before successful matches: errors, mismatches, and missing-file statuses appear ahead of matching files. Data under `multiqc_data/` can be retained for automated auditing or downstream reporting; exact filenames may vary with the MultiQC version and the checksum types present in the samplesheet. ## Pipeline information From c184be491eb46923163c339ab3c238b077ef7134 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 08:57:32 -0300 Subject: [PATCH 197/334] Update output.md --- docs/output.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/output.md b/docs/output.md index 4371f7f..27a0c6b 100644 --- a/docs/output.md +++ b/docs/output.md @@ -105,13 +105,13 @@ The MultiQC report consolidates: The MD5 and SHA-256 input-validation sections show the results from `rclone checksum`. Use these sections to confirm that each source file matched the checksum manifest supplied in `checksum_md5` and/or `checksum_sha` before copying. -![nf-core/multiqc checksum md5](docs/images/datasync-multiqc-checksum-md5.png) +![nf-core/multiqc checksum md5](images/datasync-multiqc-checksum-md5.png) ### Rclone check section The source-destination validation section shows the results from `rclone check` after the copy step. Use this section to confirm that copied files at `output_path` match the corresponding source files. -![nf-core/multiqc checksum md5](docs/images/datasync-multiqc-post-transfer-check.png) +![nf-core/multiqc checksum md5](images/datasync-multiqc-post-transfer-check.png) Open `multiqc_report.html` after every run and investigate any non-matching, missing, or error entries. In the rclone result sections, entries are prioritised so rows needing attention are shown before successful matches: errors, mismatches, and missing-file statuses appear ahead of matching files. Data under `multiqc_data/` can be retained for automated auditing or downstream reporting; exact filenames may vary with the MultiQC version and the checksum types present in the samplesheet. From 10631f6e6c46b15b26dda69db4bc378f53f4ee42 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 09:23:05 -0300 Subject: [PATCH 198/334] Update usage.md --- docs/usage.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/docs/usage.md b/docs/usage.md index baefddf..c8e95fd 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -197,6 +197,65 @@ nextflow run nf-core/datasync -r -profile docker -params-file params.y Do not use `-c` for pipeline parameters. Use it only for Nextflow executor, resources, and other infrastructure configuration. +### Common integrity outcomes + +The workflow is designed to collect rclone reports even when rclone detects differences. The table below summarises common edge cases and how to interpret them in the published reports and MultiQC. + +| Situation | Where it is detected | Report status | Pipeline behaviour and action | +| ------------------------------------------------------------------ | ---------------------------------------------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| File exists and checksum/content matches | `rclone checksum` before copy and `rclone check` after copy | `=` / `Match` | Expected result; no action needed. | +| File is listed in the checksum manifest but absent from the source | Pre-copy `rclone checksum` | `-` / missing from checked source | The report is retained for review. Fix the manifest or restore the missing source file before relying on the transfer. | +| Source file exists but is absent from the checksum manifest | Pre-copy `rclone checksum` | `+` / missing from manifest | Review whether the manifest is incomplete or whether the extra source file should be excluded from the transfer. | +| Source file hash differs from the supplied manifest | Pre-copy `rclone checksum` | `*` / mismatch | Investigate source mutation, stale manifests, or incorrect checksum files before accepting the copy. | +| Source file cannot be read or hashed | Pre-copy `rclone checksum` | `!` / error | Inspect credentials, permissions, connectivity, and source path spelling. | +| Destination is missing a copied file | Post-copy `rclone check` | `-` / missing from destination | Treat as an incomplete transfer unless the file was intentionally excluded; re-run or inspect the rclone copy log. | +| Destination file exists but content differs from source | Post-copy `rclone check` | `*` / mismatch | Re-copy or investigate concurrent source/destination changes. | +| Destination contains files absent from the source | Post-copy `rclone check` | `+` / missing from source | The post-copy check uses `--one-way`, so destination-only files are tolerated, but should still be reviewed for unexpected stale or unrelated data. | +| Dry-run execution | Copy step uses `--dry-run`; checksum and check reports still run | Depends on existing destination | No transfer data is written. Post-copy reports describe whatever was already present at the destination. | + +### Including or excluding files + +Filter files by passing additional rclone filter flags to the relevant rclone module through a Nextflow configuration file. Rclone supports flags such as `--include`, `--exclude`, `--filter`, `--files-from`, and related rule files; see the [rclone filtering documentation](https://rclone.org/filtering/) for rule syntax and ordering. + +For example, to copy and check only FASTQ files while excluding temporary files, create a small infrastructure config: + +```groovy title="rclone_filters.config" +process { + withName: 'RCLONE_COPY' { + ext.args = { + [ + '--log-level INFO', + '--stats 30s', + '--stats-one-line', + '--stats-log-level INFO', + '--s3-chunk-size 64M', + '--no-check-certificate', + params.rclone_dry_run ? '--dry-run' : '', + '--include "*.fastq.gz"', + '--include "*.fq.gz"', + '--exclude "*.tmp"', + '--exclude "*"' + ].findAll { it }.join(' ') + } + } + + withName: 'RCLONE_CHECK' { + ext.args = { + [ + '--no-check-certificate', + '--one-way', + '--include "*.fastq.gz"', + '--include "*.fq.gz"', + '--exclude "*.tmp"', + '--exclude "*"' + ].join(' ') + } + } +} +``` + +Run it with `-c rclone_filters.config` in addition to your normal profile and parameters. Because `ext.args` overrides module defaults, include the default rclone flags you still need when adding filters. Keep checksum manifests consistent with the same filtering rules: if a file is intentionally excluded from copy/check, remove it from the checksum manifest or generate a manifest for only the included files. + ## Understanding completion and integrity For each row, the pipeline first validates supplied checksum manifests, performs the copy, and then compares source and destination. Rclone comparison commands write status reports even when differences are found, allowing all results to be collected in MultiQC. Therefore, a successful Nextflow run means the workflow completed; it does **not by itself** prove every object matched. Review `multiqc/multiqc_report.html` and the reports under `rclone/`, especially lines marked `-`, `+`, `*`, or `!` (see [output documentation](output.md)). From 77738d523e3cced9b6bb9121575ee5741e870826 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Fri, 24 Jul 2026 12:35:44 +0000 Subject: [PATCH 199/334] Template update for nf-core/tools version 4.0.3 --- .devcontainer/devcontainer.json | 29 +- .devcontainer/setup.sh | 13 + .github/CONTRIBUTING.md | 125 -- .github/PULL_REQUEST_TEMPLATE.md | 4 +- .github/actions/get-shards/action.yml | 2 +- .github/actions/nf-test/action.yml | 18 +- .github/workflows/awsfulltest.yml | 37 +- .github/workflows/awstest.yml | 16 +- .github/workflows/branch.yml | 60 +- .github/workflows/clean-up.yml | 2 +- .github/workflows/download_pipeline.yml | 18 +- .github/workflows/fix_linting.yml | 32 +- .github/workflows/linting.yml | 54 +- .github/workflows/linting_comment.yml | 28 - .github/workflows/nf-test.yml | 105 +- .github/workflows/pr-comment.yml | 82 + .github/workflows/release-announcements.yml | 10 +- .../workflows/template-version-comment.yml | 58 +- .gitignore | 1 + .gitpod.yml | 10 - .nf-core.yml | 4 +- .pre-commit-config.yaml | 18 +- .prettierignore | 5 +- README.md | 15 +- assets/adaptivecard.json | 67 - assets/schema_input.json | 6 +- assets/slackreport.json | 34 - conf/base.config | 3 +- conf/containers_conda_lock_files_amd64.config | 2 + conf/containers_conda_lock_files_arm64.config | 2 + conf/containers_docker_amd64.config | 2 + conf/containers_docker_arm64.config | 2 + .../containers_singularity_https_amd64.config | 2 + .../containers_singularity_https_arm64.config | 2 + conf/containers_singularity_oras_amd64.config | 2 + conf/containers_singularity_oras_arm64.config | 2 + docs/CONTRIBUTING.md | 185 ++ docs/usage.md | 10 +- main.nf | 12 +- modules.json | 10 +- .../linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt | 822 +++++++++ .../linux_arm64-bd-e455e32f745abe68_1.txt | 769 ++++++++ modules/nf-core/fastqc/environment.yml | 2 + modules/nf-core/fastqc/main.nf | 43 +- modules/nf-core/fastqc/meta.yml | 62 +- modules/nf-core/fastqc/tests/main.nf.test | 12 +- .../nf-core/fastqc/tests/main.nf.test.snap | 228 ++- .../linux_amd64-bd-c1f4a7982b743963_1.txt | 1552 +++++++++++++++++ .../linux_amd64-bd-db7c73dae76bc9e6_1.txt | 126 ++ .../linux_arm64-bd-40bf3b435e89dc22_1.txt | 1502 ++++++++++++++++ .../linux_arm64-bd-d167b8012595a136_1.txt | 125 ++ modules/nf-core/multiqc/environment.yml | 4 +- modules/nf-core/multiqc/main.nf | 51 +- modules/nf-core/multiqc/meta.yml | 103 +- .../multiqc/tests/custom_prefix.config | 5 + modules/nf-core/multiqc/tests/main.nf.test | 191 +- .../nf-core/multiqc/tests/main.nf.test.snap | 435 ++++- modules/nf-core/multiqc/tests/nextflow.config | 1 + modules/nf-core/multiqc/tests/tags.yml | 2 - nextflow.config | 69 +- nextflow_schema.json | 22 +- nf-test.config | 26 +- ro-crate-metadata.json | 27 +- .../utils_nfcore_datasync_pipeline/main.nf | 52 +- .../utils_nextflow_pipeline/tests/tags.yml | 2 - .../nf-core/utils_nfcore_pipeline/main.nf | 68 +- .../utils_nfcore_pipeline/tests/main.nf.test | 29 + .../tests/main.nf.test.snap | 19 + .../utils_nfcore_pipeline/tests/tags.yml | 2 - .../nf-core/utils_nfschema_plugin/main.nf | 41 +- .../utils_nfschema_plugin/tests/main.nf.test | 56 + .../tests/nextflow.config | 4 +- tests/.nftignore | 2 + tests/default.nf.test | 16 +- tests/nextflow.config | 6 +- workflows/datasync.nf | 100 +- 76 files changed, 6750 insertions(+), 915 deletions(-) create mode 100755 .devcontainer/setup.sh delete mode 100644 .github/CONTRIBUTING.md delete mode 100644 .github/workflows/linting_comment.yml create mode 100644 .github/workflows/pr-comment.yml delete mode 100644 .gitpod.yml delete mode 100644 assets/adaptivecard.json delete mode 100644 assets/slackreport.json create mode 100644 conf/containers_conda_lock_files_amd64.config create mode 100644 conf/containers_conda_lock_files_arm64.config create mode 100644 conf/containers_docker_amd64.config create mode 100644 conf/containers_docker_arm64.config create mode 100644 conf/containers_singularity_https_amd64.config create mode 100644 conf/containers_singularity_https_arm64.config create mode 100644 conf/containers_singularity_oras_amd64.config create mode 100644 conf/containers_singularity_oras_arm64.config create mode 100644 docs/CONTRIBUTING.md create mode 100644 modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt create mode 100644 modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt create mode 100644 modules/nf-core/multiqc/tests/custom_prefix.config delete mode 100644 modules/nf-core/multiqc/tests/tags.yml delete mode 100644 subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test create mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap delete mode 100644 subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b290e09..237c9ed 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,20 +1,21 @@ { + "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json", "name": "nfcore", - "image": "nfcore/gitpod:latest", - "remoteUser": "gitpod", - "runArgs": ["--privileged"], + "image": "nfcore/devcontainer:latest", - // Configure tool-specific properties. - "customizations": { - // Configure properties specific to VS Code. - "vscode": { - // Set *default* container specific settings.json values on container create. - "settings": { - "python.defaultInterpreterPath": "/opt/conda/bin/python" - }, + "remoteUser": "root", + "privileged": true, - // Add the IDs of extensions you want installed when the container is created. - "extensions": ["ms-python.python", "ms-python.vscode-pylance", "nf-core.nf-core-extensionpack"] - } + "remoteEnv": { + // Workspace path on the host for mounting with docker-outside-of-docker + "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" + }, + + "onCreateCommand": "./.devcontainer/setup.sh", + + "hostRequirements": { + "cpus": 4, + "memory": "16gb", + "storage": "32gb" } } diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh new file mode 100755 index 0000000..c0ca3c6 --- /dev/null +++ b/.devcontainer/setup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Customise the terminal command prompt +echo "export PROMPT_DIRTRIM=2" >> $HOME/.bashrc +echo "export PS1='\[\e[3;36m\]\w ->\[\e[0m\\] '" >> $HOME/.bashrc +export PROMPT_DIRTRIM=2 +export PS1='\[\e[3;36m\]\w ->\[\e[0m\\] ' + +# Update Nextflow +nextflow self-update + +# Update welcome message +echo "Welcome to the nf-core/datasync devcontainer!" > /usr/local/etc/vscode-dev-containers/first-run-notice.txt diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index 8aed170..0000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,125 +0,0 @@ -# `nf-core/datasync`: Contributing Guidelines - -Hi there! -Many thanks for taking an interest in improving nf-core/datasync. - -We try to manage the required tasks for nf-core/datasync using GitHub issues, you probably came to this page when creating one. -Please use the pre-filled template to save time. - -However, don't be put off by this template - other more general issues and suggestions are welcome! -Contributions to the code are even more welcome ;) - -> [!NOTE] -> If you need help using or modifying nf-core/datasync then the best place to ask is on the nf-core Slack [#datasync](https://nfcore.slack.com/channels/datasync) channel ([join our Slack here](https://nf-co.re/join/slack)). - -## Contribution workflow - -If you'd like to write some code for nf-core/datasync, the standard workflow is as follows: - -1. Check that there isn't already an issue about your idea in the [nf-core/datasync issues](https://github.com/nf-core/datasync/issues) to avoid duplicating work. If there isn't one already, please create one so that others know you're working on this -2. [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the [nf-core/datasync repository](https://github.com/nf-core/datasync) to your GitHub account -3. Make the necessary changes / additions within your forked repository following [Pipeline conventions](#pipeline-contribution-conventions) -4. Use `nf-core pipelines schema build` and add any new parameters to the pipeline JSON schema (requires [nf-core tools](https://github.com/nf-core/tools) >= 1.10). -5. Submit a Pull Request against the `dev` branch and wait for the code to be reviewed and merged - -If you're not used to this workflow with git, you can start with some [docs from GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests) or even their [excellent `git` resources](https://try.github.io/). - -## Tests - -You have the option to test your changes locally by running the pipeline. For receiving warnings about process selectors and other `debug` information, it is recommended to use the debug profile. Execute all the tests with the following command: - -```bash -nf-test test --profile debug,test,docker --verbose -``` - -When you create a pull request with changes, [GitHub Actions](https://github.com/features/actions) will run automatic tests. -Typically, pull-requests are only fully reviewed when these tests are passing, though of course we can help out before then. - -There are typically two types of tests that run: - -### Lint tests - -`nf-core` has a [set of guidelines](https://nf-co.re/developers/guidelines) which all pipelines must adhere to. -To enforce these and ensure that all pipelines stay in sync, we have developed a helper tool which runs checks on the pipeline code. This is in the [nf-core/tools repository](https://github.com/nf-core/tools) and once installed can be run locally with the `nf-core pipelines lint ` command. - -If any failures or warnings are encountered, please follow the listed URL for more documentation. - -### Pipeline tests - -Each `nf-core` pipeline should be set up with a minimal set of test-data. -`GitHub Actions` then runs the pipeline on this data to ensure that it exits successfully. -If there are any failures then the automated tests fail. -These tests are run both with the latest available version of `Nextflow` and also the minimum required version that is stated in the pipeline code. - -## Patch - -:warning: Only in the unlikely and regretful event of a release happening with a bug. - -- On your own fork, make a new branch `patch` based on `upstream/main` or `upstream/master`. -- Fix the bug, and bump version (X.Y.Z+1). -- Open a pull-request from `patch` to `main`/`master` with the changes. - -## Getting help - -For further information/help, please consult the [nf-core/datasync documentation](https://nf-co.re/datasync/usage) and don't hesitate to get in touch on the nf-core Slack [#datasync](https://nfcore.slack.com/channels/datasync) channel ([join our Slack here](https://nf-co.re/join/slack)). - -## Pipeline contribution conventions - -To make the `nf-core/datasync` code and processing logic more understandable for new contributors and to ensure quality, we semi-standardise the way the code and other contributions are written. - -### Adding a new step - -If you wish to contribute a new step, please use the following coding standards: - -1. Define the corresponding input channel into your new process from the expected previous process channel. -2. Write the process block (see below). -3. Define the output channel if needed (see below). -4. Add any new parameters to `nextflow.config` with a default (see below). -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 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`. - -### Default values - -Parameters should be initialised / defined with default values within the `params` scope in `nextflow.config`. - -Once there, use `nf-core pipelines schema build` to add to `nextflow_schema.json`. - -### Default processes resource requirements - -Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/main/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. - -The process resources can be passed on to the tool dynamically within the process with the `${task.cpus}` and `${task.memory}` variables in the `script:` block. - -### Naming schemes - -Please use the following naming schemes, to make it easy to understand what is going where. - -- initial process channel: `ch_output_from_` -- intermediate and terminal channels: `ch__for_` - -### Nextflow version bumping - -If you are using a new feature from core Nextflow, you may bump the minimum required version of nextflow in the pipeline with: `nf-core pipelines bump-version --nextflow . [min-nf-version]` - -### Images and figures - -For overview images and other documents we follow the nf-core [style guidelines and examples](https://nf-co.re/developers/design_guidelines). - -## GitHub Codespaces - -This repo includes a devcontainer configuration which will create a GitHub Codespaces for Nextflow development! This is an online developer environment that runs in your browser, complete with VSCode and a terminal. - -To get started: - -- Open the repo in [Codespaces](https://github.com/nf-core/datasync/codespaces) -- Tools installed - - nf-core - - Nextflow - -Devcontainer specs: - -- [DevContainer config](.devcontainer/devcontainer.json) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 68ec5da..87aab4d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/.github/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/.github/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). diff --git a/.github/actions/get-shards/action.yml b/.github/actions/get-shards/action.yml index 3408527..e2833ee 100644 --- a/.github/actions/get-shards/action.yml +++ b/.github/actions/get-shards/action.yml @@ -21,7 +21,7 @@ runs: using: "composite" steps: - name: Install nf-test - uses: nf-core/setup-nf-test@v1 + uses: nf-core/setup-nf-test@4069fbbaabe94c08faba4ad261bfa88225ba133f # v2 with: version: ${{ env.NFT_VER }} - name: Get number of shards diff --git a/.github/actions/nf-test/action.yml b/.github/actions/nf-test/action.yml index 243e782..945c56f 100644 --- a/.github/actions/nf-test/action.yml +++ b/.github/actions/nf-test/action.yml @@ -20,24 +20,24 @@ runs: using: "composite" steps: - name: Setup Nextflow - uses: nf-core/setup-nextflow@v2 + uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 with: version: "${{ env.NXF_VERSION }}" - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: - python-version: "3.13" + python-version: "3.14" - name: Install nf-test - uses: nf-core/setup-nf-test@v1 + uses: nf-core/setup-nf-test@4069fbbaabe94c08faba4ad261bfa88225ba133f # v2 with: version: "${{ env.NFT_VER }}" install-pdiff: true - name: Setup apptainer if: contains(inputs.profile, 'singularity') - uses: eWaterCycle/setup-apptainer@main + uses: eWaterCycle/setup-apptainer@4bb22c52d4f63406c49e94c804632975787312b3 # v2.0.0 - name: Set up Singularity if: contains(inputs.profile, 'singularity') @@ -48,19 +48,17 @@ runs: - name: Conda setup if: contains(inputs.profile, 'conda') - uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3 + uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4 with: auto-update-conda: true conda-solver: libmamba + channels: conda-forge + channel-priority: strict conda-remove-defaults: true - # TODO Skip failing conda tests and document their failures - # https://github.com/nf-core/modules/issues/7017 - name: Run nf-test shell: bash env: - NFT_DIFF: ${{ env.NFT_DIFF }} - NFT_DIFF_ARGS: ${{ env.NFT_DIFF_ARGS }} NFT_WORKDIR: ${{ env.NFT_WORKDIR }} run: | nf-test test \ diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 5f5aa19..b498008 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -23,26 +23,45 @@ jobs: echo "revision=${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'release') && github.sha || 'dev' }}" >> "$GITHUB_OUTPUT" - name: Launch workflow via Seqera Platform - uses: seqeralabs/action-tower-launch@v2 + uses: seqeralabs/action-tower-launch@51565b514bff1827cf34620de25d0055759f1fc9 # v2 # TODO nf-core: You can customise AWS full pipeline tests as required # Add full size test data (but still relatively small datasets for few samples) # on the `test_full.config` test runs with only one set of parameters with: - workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} + workspace_id: ${{ vars.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} - compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + compute_env: ${{ vars.TOWER_COMPUTE_ENV }} revision: ${{ steps.revision.outputs.revision }} - workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/datasync/work-${{ steps.revision.outputs.revision }} + workdir: s3://${{ vars.AWS_S3_BUCKET }}/work/datasync/work-${{ steps.revision.outputs.revision }} + nextflow_config: | + plugins { + id 'nf-slack@0.5.0' + } + slack { + enabled = true + bot { + token = '${{ secrets.NFSLACK_BOT_TOKEN }}' + channel = 'datasync' + } + onStart { + enabled = false + } + onComplete { + message = ':white_check_mark: *datasync/test_full* completed successfully! :tada:' + } + onError { + message = ':x: *datasync/test_full* failed :crying_cat_face:' + } + } parameters: | { - "hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}", - "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/datasync/results-${{ steps.revision.outputs.revision }}" + "outdir": "s3://${{ vars.AWS_S3_BUCKET }}/datasync/results-${{ steps.revision.outputs.revision }}" } profiles: test_full - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: Seqera Platform debug log file path: | - seqera_platform_action_*.log - seqera_platform_action_*.json + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index d937e2f..b9e6efa 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -12,22 +12,22 @@ jobs: steps: # Launch workflow using Seqera Platform CLI tool action - name: Launch workflow via Seqera Platform - uses: seqeralabs/action-tower-launch@v2 + uses: seqeralabs/action-tower-launch@51565b514bff1827cf34620de25d0055759f1fc9 # v2 with: - workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} + workspace_id: ${{ vars.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} - compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + compute_env: ${{ vars.TOWER_COMPUTE_ENV }} revision: ${{ github.sha }} - workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/datasync/work-${{ github.sha }} + workdir: s3://${{ vars.AWS_S3_BUCKET }}/work/datasync/work-${{ github.sha }} parameters: | { - "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/datasync/results-test-${{ github.sha }}" + "outdir": "s3://${{ vars.AWS_S3_BUCKET }}/datasync/results-test-${{ github.sha }}" } profiles: test - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: Seqera Platform debug log file path: | - seqera_platform_action_*.log - seqera_platform_action_*.json + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 72e58e1..720e16c 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -2,11 +2,13 @@ name: nf-core branch protection # This workflow is triggered on PRs to `main`/`master` branch on the repository # It fails when someone tries to make a PR against the nf-core `main`/`master` branch instead of `dev` on: - pull_request_target: + pull_request: branches: - main - master +permissions: {} + jobs: test: runs-on: ubuntu-latest @@ -14,33 +16,47 @@ jobs: # PRs to the nf-core repo main/master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches - name: Check PRs if: github.repository == 'nf-core/datasync' + env: + HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} run: | - { [[ ${{github.event.pull_request.head.repo.full_name }} == nf-core/datasync ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] + { [[ "$HEAD_REPO" == nf-core/datasync ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] - # If the above check failed, post a comment on the PR explaining the failure - # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets - - name: Post PR comment + # If the above check failed, build a comment to be posted by the shared poster workflow + - name: Build PR comment if: failure() - uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 - with: - message: | - ## This PR is against the `${{github.event.pull_request.base.ref}}` branch :x: + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + BASE_REF: ${{ github.event.pull_request.base.ref }} + HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} + PR_USER: ${{ github.event.pull_request.user.login }} + run: | + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "branch" > pr-comment/header.txt + cat > pr-comment/comment.md <> "$GITHUB_OUTPUT" + - name: Install dependencies run: | python -m pip install --upgrade pip - pip install git+https://github.com/nf-core/tools.git@dev + pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} - name: Make a cache directory for the container images run: | @@ -127,7 +135,7 @@ jobs: fi - name: Upload Nextflow logfile for debugging purposes - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: nextflow_logfile.txt path: .nextflow.log* diff --git a/.github/workflows/fix_linting.yml b/.github/workflows/fix_linting.yml index 42f855d..8837738 100644 --- a/.github/workflows/fix_linting.yml +++ b/.github/workflows/fix_linting.yml @@ -13,13 +13,13 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: token: ${{ secrets.nf_core_bot_auth_token }} # indication that the linting is being fixed - name: React on comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: eyes @@ -31,30 +31,26 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} - # Install and run pre-commit - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: "3.13" - - - name: Install pre-commit - run: pip install pre-commit + - name: Install Nextflow + uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 - - name: Run pre-commit - id: pre-commit - run: pre-commit run --all-files + # Install and run prek + - name: Run prek + id: prek + uses: j178/prek-action@6ad80277337ad479fe43bd70701c3f7f8aa74db3 # v2 continue-on-error: true # indication that the linting has finished - name: react if linting finished succesfully - if: steps.pre-commit.outcome == 'success' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + if: steps.prek.outcome == 'success' + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: "+1" - name: Commit & push changes id: commit-and-push - if: steps.pre-commit.outcome == 'failure' + if: steps.prek.outcome == 'failure' run: | git config user.email "core@nf-co.re" git config user.name "nf-core-bot" @@ -67,21 +63,21 @@ jobs: - name: react if linting errors were fixed id: react-if-fixed if: steps.commit-and-push.outcome == 'success' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: hooray - name: react if linting errors were not fixed if: steps.commit-and-push.outcome == 'failure' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: confused - name: react if linting errors were not fixed if: steps.commit-and-push.outcome == 'failure' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: issue-number: ${{ github.event.issue.number }} body: | diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index f2d7d1d..bc32219 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -11,33 +11,31 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - name: Set up Python 3.12 - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 - with: - python-version: "3.13" - - - name: Install pre-commit - run: pip install pre-commit + - name: Install Nextflow + uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 - - name: Run pre-commit - run: pre-commit run --all-files + - name: Run prek + uses: j178/prek-action@6ad80277337ad479fe43bd70701c3f7f8aa74db3 # v2 nf-core: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Install Nextflow - uses: nf-core/setup-nextflow@v2 + uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: - python-version: "3.13" + python-version: "3.14" architecture: "x64" + - name: Setup uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + - name: read .nf-core.yml uses: pietrobolcato/action-read-yaml@9f13718d61111b69f30ab4ac683e67a56d254e1d # 1.1.0 id: read_yml @@ -45,12 +43,10 @@ jobs: config: ${{ github.workspace }}/.nf-core.yml - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} + run: uv tool install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} - name: Run nf-core pipelines lint - if: ${{ github.base_ref != 'master' }} + if: ${{ github.base_ref != 'master' || github.base_ref != 'main' }} env: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -58,7 +54,7 @@ jobs: run: nf-core -l lint_log.txt pipelines lint --dir ${GITHUB_WORKSPACE} --markdown lint_results.md - name: Run nf-core pipelines lint --release - if: ${{ github.base_ref == 'master' }} + if: ${{ github.base_ref == 'master' || github.base_ref == 'main' }} env: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -71,10 +67,28 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: linting-logs path: | lint_log.txt lint_results.md PR_number.txt + + # Build a comment for the shared pr-comment.yml poster to publish on the PR + - name: Prepare PR comment + if: ${{ always() }} + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "lint" > pr-comment/header.txt + [ -f lint_results.md ] && cp lint_results.md pr-comment/comment.md || true + + - name: Upload PR comment artifact + if: ${{ always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pr-comment + path: pr-comment/ diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml deleted file mode 100644 index 7e8050f..0000000 --- a/.github/workflows/linting_comment.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: nf-core linting comment -# This workflow is triggered after the linting action is complete -# It posts an automated comment to the PR, even if the PR is coming from a fork - -on: - workflow_run: - workflows: ["nf-core linting"] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Download lint results - uses: dawidd6/action-download-artifact@4c1e823582f43b179e2cbb49c3eade4e41f992e2 # v10 - with: - workflow: linting.yml - workflow_conclusion: completed - - - name: Get PR number - id: pr_number - run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - - - name: Post PR comment - uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - number: ${{ steps.pr_number.outputs.pr_number }} - path: linting-logs/lint_results.md diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml index f03aea0..4de681a 100644 --- a/.github/workflows/nf-test.yml +++ b/.github/workflows/nf-test.yml @@ -1,12 +1,5 @@ name: Run nf-test on: - push: - paths-ignore: - - "docs/**" - - "**/meta.yml" - - "**/*.md" - - "**/*.png" - - "**/*.svg" pull_request: paths-ignore: - "docs/**" @@ -25,7 +18,7 @@ concurrency: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NFT_VER: "0.9.2" + NFT_VER: "0.9.4" NFT_WORKDIR: "~" NXF_ANSI_LOG: false NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity @@ -35,7 +28,7 @@ jobs: nf-test-changes: name: nf-test-changes runs-on: # use self-hosted runners - - runs-on=$-nf-test-changes + - runs-on=${{ github.run_id }}-nf-test-changes - runner=4cpu-linux-x64 outputs: shard: ${{ steps.set-shards.outputs.shard }} @@ -47,7 +40,7 @@ jobs: rm -rf ./* || true rm -rf ./.??* || true ls -la ./ - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 @@ -69,7 +62,7 @@ jobs: needs: [nf-test-changes] if: ${{ needs.nf-test-changes.outputs.total_shards != '0' }} runs-on: # use self-hosted runners - - runs-on=$-nf-test + - runs-on=${{ github.run_id }}-nf-test - runner=4cpu-linux-x64 strategy: fail-fast: false @@ -85,35 +78,68 @@ jobs: - isMain: false profile: "singularity" NXF_VER: - - "24.04.2" + - "25.10.4" - "latest-everything" env: NXF_ANSI_LOG: false TOTAL_SHARDS: ${{ needs.nf-test-changes.outputs.total_shards }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 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_DIFF: ${{ env.NFT_DIFF }} - NFT_DIFF_ARGS: ${{ env.NFT_DIFF_ARGS }} NFT_WORKDIR: ${{ env.NFT_WORKDIR }} + NXF_VERSION: ${{ matrix.NXF_VER }} 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 + + # continue-on-error keeps latest-everything from failing the job, so it never shows up in + # `needs.nf-test.result` downstream and CI stays green. Surface it via a PR comment instead; + # other NXF_VER failures already fail the job/CI directly, so no comment is needed for those. + - name: Prepare PR comment fragment + if: ${{ always() && steps.run_nf_test.outcome == 'failure' && matrix.NXF_VER == 'latest-everything' }} + run: | + mkdir -p pr-comment-fragment + echo "* ❌ \`${{ matrix.profile }}\` | \`${{ matrix.NXF_VER }}\` | Shard ${{ matrix.shard }}/${{ env.TOTAL_SHARDS }}" > pr-comment-fragment/fragment.md + + - name: Upload PR comment fragment + if: ${{ always() && steps.run_nf_test.outcome == 'failure' && matrix.NXF_VER == 'latest-everything' }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pr-comment-fragment-${{ strategy.job-index }} + path: pr-comment-fragment/ + confirm-pass: needs: [nf-test] if: always() runs-on: # use self-hosted runners - - runs-on=$-confirm-pass + - runs-on=${{ github.run_id }}-confirm-pass - runner=2cpu-linux-x64 steps: - - name: One or more tests failed + - name: One or more tests failed (excluding latest-everything) if: ${{ contains(needs.*.result, 'failure') }} run: exit 1 @@ -133,10 +159,43 @@ jobs: echo "DEBUG: toJSON(needs.*.result) = ${{ toJSON(needs.*.result) }}" echo "::endgroup::" - - name: Clean Workspace # Purge the workspace in case it's running on a self-hosted runner - if: always() + - name: Download PR comment fragments + if: ${{ always() }} + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + continue-on-error: true + with: + pattern: pr-comment-fragment-* + path: pr-comment-fragments + merge-multiple: true + + # Build a comment for the shared pr-comment.yml poster to publish on the PR. + # Based on the fragments above (not needs.*.result) so non-blocking failures are still reported. + - name: Prepare PR comment + if: ${{ always() }} + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | - ls -la ./ - rm -rf ./* || true - rm -rf ./.??* || true - ls -la ./ + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "nf-test" > pr-comment/header.txt + if [ -d pr-comment-fragments ] && [ -n "$(ls -A pr-comment-fragments)" ]; then + { + echo "## ❌ nf-test failed with latest Nextflow version" + echo "" + echo "> [!NOTE]" + echo "> Tests with Nextflow's latest version failed but it will not cause a CI workflow failure." + echo "> Please check if the failure is expected with newer (edge-)releases of Nextflow or if it needs fixing." + echo "" + cat pr-comment-fragments/*.md + echo "" + echo "See the [full run](${RUN_URL}) for details." + } > pr-comment/comment.md + fi + + - name: Upload PR comment artifact + if: ${{ always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pr-comment + path: pr-comment/ diff --git a/.github/workflows/pr-comment.yml b/.github/workflows/pr-comment.yml new file mode 100644 index 0000000..ab7b59d --- /dev/null +++ b/.github/workflows/pr-comment.yml @@ -0,0 +1,82 @@ +name: Post PR comment +# Shared, privileged comment poster. +# +# This is the single workflow that runs with a write token. It is triggered +# after any of the listed "producer" workflows complete on a pull request. +# Each producer runs untrusted PR code (if any) with a read-only token and +# uploads a `pr-comment` artifact describing the comment to post; this workflow +# only ever reads that plain-text artifact, so no PR code is executed here. +# +# Artifact contract (uploaded by producers under the name `pr-comment`): +# pr_number.txt - the pull request number +# header.txt - sticky-comment identifier (keeps comment types separate) +# comment.md - the Markdown body (omit the file to post nothing) + +on: + workflow_run: + workflows: + - "nf-core linting" + - "nf-core template version comment" + - "nf-core branch protection" + - "Run nf-test" + +permissions: + actions: read + contents: read + pull-requests: write + +jobs: + post-comment: + runs-on: ubuntu-latest + if: github.event.workflow_run.event == 'pull_request' + steps: + - name: Download PR comment artifact + uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 + with: + run_id: ${{ github.event.workflow_run.id }} + name: pr-comment + path: pr-comment + if_no_artifact_found: ignore + + - name: Read comment metadata + id: meta + run: | + echo "::group::Downloaded pr-comment contents" + ls -la pr-comment 2>/dev/null || echo "No pr-comment/ directory was downloaded." + echo "::endgroup::" + + if [ ! -d pr-comment ]; then + echo "No pr-comment artifact found; nothing to post." + exit 0 + fi + + if [ ! -f pr-comment/comment.md ]; then + echo "Artifact present but no comment.md; nothing to post." + exit 0 + fi + + pr_number=$(cat pr-comment/pr_number.txt) + header=$(cat pr-comment/header.txt) + echo "Found comment.md (header='$header', pr_number='$pr_number')." + + # Guard against anything unexpected ending up in the PR number. + case "$pr_number" in + ''|*[!0-9]*) + echo "Invalid PR number: '$pr_number'" + exit 1 + ;; + esac + + echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" + echo "header=$header" >> "$GITHUB_OUTPUT" + echo "post=true" >> "$GITHUB_OUTPUT" + echo "Will post comment to PR #${pr_number}." + + - name: Post PR comment + if: steps.meta.outputs.post == 'true' + uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + number: ${{ steps.meta.outputs.pr_number }} + header: ${{ steps.meta.outputs.header }} + path: pr-comment/comment.md diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 4abaf48..4974f44 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -14,7 +14,11 @@ jobs: run: | echo "topics=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ')" | sed 's/-//g' >> $GITHUB_OUTPUT - - uses: rzr/fediverse-action@master + - name: get description + id: get_description + run: | + echo "description=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .description')" >> $GITHUB_OUTPUT + - uses: rzr/fediverse-action@66c2cbb5b1997666b0e28d597631b6a4f09a2719 # v0.0.6 with: access-token: ${{ secrets.MASTODON_ACCESS_TOKEN }} host: "mstdn.science" # custom host if not "mastodon.social" (default) @@ -22,7 +26,7 @@ jobs: # https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#release message: | Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! - + ${{ steps.get_description.outputs.description }} Please see the changelog: ${{ github.event.release.html_url }} ${{ steps.get_topics.outputs.topics }} #nfcore #openscience #nextflow #bioinformatics @@ -30,7 +34,7 @@ jobs: bsky-post: runs-on: ubuntu-latest steps: - - uses: zentered/bluesky-post-action@4aa83560bb3eac05dbad1e5f221ee339118abdd2 # v0.2.0 + - uses: zentered/bluesky-post-action@5a91cc2ad10a304a4e96c16182dbe4918710bcf6 # v0.4.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 index beb5c77..ee102f7 100644 --- a/.github/workflows/template-version-comment.yml +++ b/.github/workflows/template-version-comment.yml @@ -2,14 +2,17 @@ name: nf-core template version comment # This workflow is triggered on PRs to check if the pipeline template version matches the latest nf-core version. # It posts a comment to the PR, even if it comes from a fork. -on: pull_request_target +on: + pull_request: + +permissions: {} jobs: - template_version: + check_template_version: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.sha }} @@ -22,25 +25,36 @@ jobs: - name: Install nf-core run: | python -m pip install --upgrade pip - pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} + pip install nf-core + + - name: Build PR comment if template is outdated + # The fork-controlled version is passed via the environment and only ever + # used as quoted shell data (never interpolated into a command), so it + # cannot be used for script injection. + env: + PR_VERSION: ${{ steps.read_yml.outputs['nf_core_version'] }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "template-version" > pr-comment/header.txt + + latest_version=$(nf-core --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1) - - name: Check nf-core outdated - id: nf_core_outdated - run: echo "OUTPUT=$(pip list --outdated | grep nf-core)" >> ${GITHUB_ENV} + if [ -n "$PR_VERSION" ] && [ -n "$latest_version" ] && [ "$PR_VERSION" != "$latest_version" ]; then + cat > pr-comment/comment.md < [!WARNING] + > Newer version of the nf-core template is available. + > + > Your pipeline is using an old version of the nf-core template: ${PR_VERSION}. + > Please update your pipeline to the latest version. + > + > For more documentation on how to update your pipeline, please see the [Synchronisation documentation](https://nf-co.re/docs/developing/template-syncs/overview). + EOF + fi - - name: Post nf-core template version comment - uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 - if: | - contains(env.OUTPUT, 'nf-core') + - name: Upload PR comment artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - repo-token: ${{ secrets.NF_CORE_BOT_AUTH_TOKEN }} - allow-repeats: false - message: | - > [!WARNING] - > Newer version of the nf-core template is available. - > - > Your pipeline is using an old version of the nf-core template: ${{ steps.read_yml.outputs['nf_core_version'] }}. - > Please update your pipeline to the latest version. - > - > For more documentation on how to update your pipeline, please see the [nf-core documentation](https://github.com/nf-core/tools?tab=readme-ov-file#sync-a-pipeline-with-the-template) and [Synchronisation documentation](https://nf-co.re/docs/contributing/sync). - # + name: pr-comment + path: pr-comment/ diff --git a/.gitignore b/.gitignore index a42ce01..cc2b1a7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ testing/ testing* *.pyc null/ +.lineage/ diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index 83599f6..0000000 --- a/.gitpod.yml +++ /dev/null @@ -1,10 +0,0 @@ -image: nfcore/gitpod:latest -tasks: - - name: Update Nextflow and setup pre-commit - command: | - pre-commit install --install-hooks - nextflow self-update - -vscode: - extensions: - - nf-core.nf-core-extensionpack # https://github.com/nf-core/vscode-extensionpack diff --git a/.nf-core.yml b/.nf-core.yml index 82ea73d..d72e474 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,6 @@ -nf_core_version: 3.3.1 +lint: + multiqc_config: false +nf_core_version: 4.0.3 repository_type: pipeline template: author: Alexander Peltzer diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9d0b248..f51e1a2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,24 +4,30 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.5.0 + - prettier@3.8.3 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: trailing-whitespace args: [--markdown-linebreak-ext=md] exclude: | (?x)^( .*ro-crate-metadata.json$| - modules/nf-core/.*| - subworkflows/nf-core/.*| + modules/(?!local/).*| + subworkflows/(?!local/).*| .*\.snap$ )$ - id: end-of-file-fixer exclude: | (?x)^( .*ro-crate-metadata.json$| - modules/nf-core/.*| - subworkflows/nf-core/.*| + modules/(?!local/).*| + subworkflows/(?!local/).*| .*\.snap$ )$ + - repo: https://github.com/seqeralabs/nf-lint-pre-commit + rev: v0.3.0 + hooks: + - id: nextflow-lint + files: '\.nf$|nextflow\.config$' + args: ["-output", "json"] diff --git a/.prettierignore b/.prettierignore index edd29f0..63cde50 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,4 @@ email_template.html -adaptivecard.json -slackreport.json .nextflow* work/ data/ @@ -10,4 +8,7 @@ testing/ testing* *.pyc bin/ +.nf-test/ ro-crate-metadata.json +modules/nf-core/ +subworkflows/nf-core/ diff --git a/README.md b/README.md index 4a3cc67..3d20e4c 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,13 @@ -[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml) +[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync) +[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml) [![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) -[![Nextflow](https://img.shields.io/badge/version-%E2%89%A524.04.2-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.1-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.1) +[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.10.4-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-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3) [![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/) @@ -29,13 +30,13 @@ --> + workflows use the "tube map" design for that. See https://nf-co.re/docs/community/brand/workflow-schematics#examples for examples. --> 1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) ## Usage > [!NOTE] -> 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. +> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data. diff --git a/docs/usage.md b/docs/usage.md index 210645c..1c85a3e 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -76,7 +76,7 @@ If you wish to repeatedly use the same parameters for multiple runs, rather than Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. > [!WARNING] -> Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). +> Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/running/run-pipelines#configuring-pipelines), other infrastructural tweaks (such as output directories), or module arguments (args). The above pipeline run specified with a params file in yaml format: @@ -149,7 +149,7 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - `shifter` - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) - `charliecloud` - - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) + - A generic configuration profile to be used with [Charliecloud](https://charliecloud.io/) - `apptainer` - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) - `wave` @@ -173,19 +173,19 @@ Specify the path to a specific config file (this is a core Nextflow command). Se Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the pipeline steps, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher resources request (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. -To change the resource requests, please see the [max resources](https://nf-co.re/docs/usage/configuration#max-resources) and [tuning workflow resources](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources) section of the nf-core website. +To change the resource requests, please see the [max resources](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#set-max-resources) and [customise process resources](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#customize-process-resources) section of the nf-core website. ### Custom Containers In some cases, you may wish to change the container or conda environment used by a pipeline steps for a particular tool. By default, nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However, in some cases the pipeline specified version maybe out of date. -To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/usage/configuration#updating-tool-versions) section of the nf-core website. +To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#update-tool-versions) section of the nf-core website. ### Custom Tool Arguments A pipeline might not always support every possible argument or option of a particular tool used in pipeline. Fortunately, nf-core pipelines provide some freedom to users to insert additional parameters that the pipeline does not include by default. -To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/usage/configuration#customising-tool-arguments) section of the nf-core website. +To learn how to provide additional arguments to a particular tool of the pipeline, please see the [customising tool arguments](https://nf-co.re/docs/running/configuration/nextflow-for-your-system#modifying-tool-arguments) section of the nf-core website. ### nf-core/configs diff --git a/main.nf b/main.nf index e23a4c6..637723e 100644 --- a/main.nf +++ b/main.nf @@ -51,7 +51,11 @@ workflow NFCORE_DATASYNC { // WORKFLOW: Run pipeline // DATASYNC ( - samplesheet + samplesheet, + params.multiqc_config, + params.multiqc_logo, + params.multiqc_methods_description, + params.outdir, ) emit: multiqc_report = DATASYNC.out.multiqc_report // channel: /path/to/multiqc_report.html @@ -74,7 +78,10 @@ workflow { params.monochrome_logs, args, params.outdir, - params.input + params.input, + params.help, + params.help_full, + params.show_hidden ) // @@ -92,7 +99,6 @@ workflow { params.plaintext_email, params.outdir, params.monochrome_logs, - params.hook_url, NFCORE_DATASYNC.out.multiqc_report ) } diff --git a/modules.json b/modules.json index ac0474c..578acbb 100644 --- a/modules.json +++ b/modules.json @@ -7,12 +7,12 @@ "nf-core": { "fastqc": { "branch": "master", - "git_sha": "08108058ea36a63f141c25c4e75f9f872a5b2296", + "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "f0719ae309075ae4a291533883847c3f7c441dad", + "git_sha": "008f9d3e61209bf995edac3ba531f54e269e1215", "installed_by": ["modules"] } } @@ -21,17 +21,17 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "c2b22d85f30a706a3073387f30380704fcae013b", + "git_sha": "05954dab2ff481bcb999f24455da29a5828af08d", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "51ae5406a030d4da1e49e4dab49756844fdd6c7a", + "git_sha": "a3fb7351b1fdb2b1de282b765816bbea190e86a8", "installed_by": ["subworkflows"] }, "utils_nfschema_plugin": { "branch": "master", - "git_sha": "2fd2cd6d0e7b273747f32e465fdc6bcc3ae0814e", + "git_sha": "fdc08b8b1ae74f56686ce21f7ea11ad11990ce57", "installed_by": ["subworkflows"] } } diff --git a/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt new file mode 100644 index 0000000..7770ccd --- /dev/null +++ b/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt @@ -0,0 +1,822 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-64: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 +md5: a9f577daf3de00bca7c3c76c0ecbd1de +depends: +- __glibc >=2.17,<3.0.a0 +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28948 +timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda +sha256: d88aa7ae766cf584e180996e92fef2aa7d8e0a0a5ab1d4d49c32390c1b5fff31 +md5: dcdc58c15961dbf17a0621312b01f5cb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: LGPL-2.1-or-later +license_family: GPL +size: 584660 +timestamp: 1768327524772 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 +md5: d2ffd7602c02f2b316fd921d39876885 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 260182 +timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda +sha256: 06525fa0c4e4f56e771a3b986d0fdf0f0fc5a3270830ee47e127a5105bde1b9a +md5: bb6c4808bfa69d6f7f6b07e5846ced37 +depends: +- __glibc >=2.17,<3.0.a0 +- fontconfig >=2.15.0,<3.0a0 +- fonts-conda-ecosystem +- icu >=78.1,<79.0a0 +- libexpat >=2.7.3,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libglib >=2.86.3,<3.0a0 +- libpng >=1.6.53,<1.7.0a0 +- libstdcxx >=14 +- libxcb >=1.17.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pixman >=0.46.4,<1.0a0 +- xorg-libice >=1.1.2,<2.0a0 +- xorg-libsm >=1.2.6,<2.0a0 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: LGPL-2.1-only or MPL-1.1 +size: 989514 +timestamp: 1766415934926 +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c +md5: c9f6a4b12229f7331f79c9a00dd6e240 +depends: +- font-ttf-dejavu-sans-mono +- fontconfig +- openjdk >=8.0.144 +- perl +license: GPL >=3 +size: 11664291 +timestamp: 1677946722445 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +sha256: aa4a44dba97151221100a637c7f4bde619567afade9c0265f8e1c8eed8d7bd8c +md5: 867127763fbe935bab59815b6e0b7b5c +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 270705 +timestamp: 1771382710863 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 +md5: fee5683a3f04bd15cbd8318b096a27ab +depends: +- fonts-conda-forge +license: BSD-3-Clause +license_family: BSD +size: 3667 +timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda +sha256: aac402a8298f0c0cc528664249170372ef6b37ac39fdc92b40601a6aed1e32ff +md5: 3bf7b9fd5a7136126e0234db4b87c8b6 +depends: +- libgcc-ng >=12 +license: MIT +license_family: MIT +size: 77248 +timestamp: 1712692454246 +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda +sha256: 25ba37da5c39697a77fce2c9a15e48cf0a84f1464ad2aafbe53d8357a9f6cc8c +md5: 2cd94587f3a401ae05e03a6caf09539d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: LGPL-2.0-or-later +license_family: LGPL +size: 99596 +timestamp: 1755102025473 +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda +sha256: 477f2c553f72165020d3c56740ba354be916c2f0b76fd9f535e83d698277d5ec +md5: 14470902326beee192e33719a2e8bb7f +depends: +- __glibc >=2.17,<3.0.a0 +- cairo >=1.18.4,<2.0a0 +- graphite2 >=1.3.14,<2.0a0 +- icu >=78.3,<79.0a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.2 +- libfreetype6 >=2.14.2 +- libgcc >=14 +- libglib >=2.86.4,<3.0a0 +- libstdcxx >=14 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 2384060 +timestamp: 1774276284520 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a +md5: c80d8a3b84358cb967fa81e7075fbc8a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12723451 +timestamp: 1773822285671 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda +sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 +md5: b38117a3c920364aff79f870c984b4a3 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: LGPL-2.1-or-later +size: 134088 +timestamp: 1754905959823 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda +sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 +md5: fb53fb07ce46a575c5d004bbc96032c2 +depends: +- __glibc >=2.17,<3.0.a0 +- keyutils >=1.6.3,<2.0a0 +- libedit >=3.1.20250104,<3.2.0a0 +- libedit >=3.1.20250104,<4.0a0 +- libgcc >=14 +- libstdcxx >=14 +- openssl >=3.5.5,<4.0a0 +license: MIT +license_family: MIT +size: 1386730 +timestamp: 1769769569681 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +sha256: 836ec4b895352110335b9fdcfa83a8dcdbe6c5fb7c06c4929130600caea91c0a +md5: 6f2e2c8f58160147c4d1c6f4c14cbac4 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 249959 +timestamp: 1768184673131 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +sha256: f84cb54782f7e9cea95e810ea8fef186e0652d0fa73d3009914fa2c1262594e1 +md5: a752488c68f2e7c456bcbd8f16eec275 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 261513 +timestamp: 1773113328888 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda +sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c +md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 +depends: +- __glibc >=2.17,<3.0.a0 +- krb5 >=1.22.2,<1.23.0a0 +- libgcc >=14 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +license: Apache-2.0 +license_family: Apache +size: 4518030 +timestamp: 1770902209173 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 +md5: 6c77a605a7a689d17d4819c0f8ac9a00 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 73490 +timestamp: 1761979956660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda +sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 +md5: c277e0a4d549b03ac1e9d6cbbe3d017b +depends: +- ncurses +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- ncurses >=6.5,<7.0a0 +license: BSD-2-Clause +license_family: BSD +size: 134676 +timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 +md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76798 +timestamp: 1771259418166 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 +md5: a360c33a5abe61c07959e449fa1453eb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 58592 +timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 +md5: e289f3d17880e44b633ba911d57a321b +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8049 +timestamp: 1774298163029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d +md5: fb16b4b69e3f1dcfe79d80db8fd0c55d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 384575 +timestamp: 1774298162622 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 +md5: 0aa00f03f9e39fb9876085dee11a85d4 +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1041788 +timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 +md5: d5e96b1ed75ca01906b3d2469b4ce493 +depends: +- libgcc 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27526 +timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda +sha256: a27e44168a1240b15659888ce0d9b938ed4bdb49e9ea68a7c1ff27bcea8b55ce +md5: bb26456332b07f68bf3b7622ed71c0da +depends: +- __glibc >=2.17,<3.0.a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- libiconv >=1.18,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pcre2 >=10.47,<10.48.0a0 +constrains: +- glib 2.86.4 *_1 +license: LGPL-2.1-or-later +size: 4398701 +timestamp: 1771863239578 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 +md5: 239c5e9546c38a1e884d69effcf4c882 +depends: +- __glibc >=2.17,<3.0.a0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 603262 +timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda +sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f +md5: 915f5995e94f60e9a4826e0b0920ee88 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: LGPL-2.1-only +size: 790176 +timestamp: 1754908768807 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32 +md5: 8397539e3a0bbd1695584fb4f927485a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 633710 +timestamp: 1762094827865 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb +md5: c7c83eecbb72d88b940c249af56c8b17 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 113207 +timestamp: 1768752626120 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +sha256: 36ade759122cdf0f16e2a2562a19746d96cf9c863ffaa812f2f5071ebbe9c03c +md5: 5f13ffc7d30ffec87864e678df9957b4 +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 317669 +timestamp: 1770691470744 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e +md5: 1b08cd684f34175e4514474793d44bcb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc 15.2.0 he0feb66_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5852330 +timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 +md5: cd5a90476766d53e901500df9215e927 +depends: +- __glibc >=2.17,<3.0.a0 +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 435273 +timestamp: 1762022005702 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee +md5: db409b7c1720428638e7c0d509d3e1b5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 40311 +timestamp: 1766271528534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b +md5: aea31d2e5b1091feca96fcfe945c3cf9 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 429011 +timestamp: 1752159441324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa +md5: 92ed62436b625154323d40d5f2f11dd7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 395888 +timestamp: 1727278577118 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda +sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c +md5: 5aa797f8787fe7a17d1b0821485b5adc +depends: +- libgcc-ng >=12 +license: LGPL-2.1-or-later +size: 100393 +timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 +md5: d87ff7921124eccd67248aa483c23fec +depends: +- __glibc >=2.17,<3.0.a0 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 63629 +timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 +md5: 47e340acb35de30501a76c7c799c41d7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 891641 +timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda +sha256: 3825a4c84676a8a5cc23b397a2911e4efa4a805daf2af764153bd904e142ec41 +md5: a41092b0177362dbe5eb2a18501e86c0 +depends: +- xorg-libx11 +- xorg-libxext +- xorg-libxi +- xorg-libxrender +- xorg-libxtst +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- xorg-libxrender >=0.9.12,<0.10.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- giflib >=5.2.2,<5.3.0a0 +- xorg-libxrandr >=1.5.5,<2.0a0 +- harfbuzz >=12.3.2 +- fontconfig >=2.17.1,<3.0a0 +- fonts-conda-ecosystem +- xorg-libxtst >=1.2.5,<2.0a0 +- xorg-libxi >=1.8.2,<2.0a0 +- lcms2 >=2.18,<3.0a0 +- alsa-lib >=1.2.15.3,<1.3.0a0 +- libpng >=1.6.55,<1.7.0a0 +- xorg-libxt >=1.3.1,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- xorg-libxext >=1.3.7,<2.0a0 +- xorg-libx11 >=1.8.13,<2.0a0 +- libcups >=2.3.3,<2.4.0a0 +license: GPL-2.0-or-later WITH Classpath-exception-2.0 +license_family: GPL +size: 122465031 +timestamp: 1771443671180 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c +md5: f61eb8cd60ff9057122a3d338b99c00f +depends: +- __glibc >=2.17,<3.0.a0 +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3164551 +timestamp: 1769555830639 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda +sha256: 5e6f7d161356fefd981948bea5139c5aa0436767751a6930cb1ca801ebb113ff +md5: 7a3bff861a6583f1889021facefc08b1 +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 1222481 +timestamp: 1763655398280 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda +build_number: 7 +sha256: 9ec32b6936b0e37bcb0ed34f22ec3116e75b3c0964f9f50ecea5f58734ed6ce9 +md5: f2cfec9406850991f4e3d960cc9e3321 +depends: +- libgcc-ng >=12 +- libxcrypt >=4.4.36 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 13344463 +timestamp: 1703310653947 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda +sha256: 43d37bc9ca3b257c5dd7bf76a8426addbdec381f6786ff441dc90b1a49143b6a +md5: c01af13bdc553d1a8fbfff6e8db075f0 +depends: +- libgcc >=14 +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +license: MIT +license_family: MIT +size: 450960 +timestamp: 1754665235234 +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d +md5: f2c23a77b25efcad57d377b34bd84941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 593603 +timestamp: 1769710381284 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 +md5: b3c17d95b5a10c6e64a21fa17573e70e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 8252 +timestamp: 1726802366959 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda +sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b +md5: fb901ff28063514abb6046c9ec2c4a45 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 58628 +timestamp: 1734227592886 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda +sha256: 277841c43a39f738927145930ff963c5ce4c4dacf66637a3d95d802a64173250 +md5: 1c74ff8c35dcadf952a16f752ca5aa49 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libuuid >=2.38.1,<3.0a0 +- xorg-libice >=1.1.2,<2.0a0 +license: MIT +license_family: MIT +size: 27590 +timestamp: 1741896361728 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda +sha256: 516d4060139dbb4de49a4dcdc6317a9353fb39ebd47789c14e6fe52de0deee42 +md5: 861fb6ccbc677bb9a9fb2468430b9c6a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libxcb >=1.17.0,<2.0a0 +license: MIT +license_family: MIT +size: 839652 +timestamp: 1770819209719 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b +md5: b2895afaf55bf96a8c8282a2e47a5de0 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 15321 +timestamp: 1762976464266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 +md5: 1dafce8548e38671bea82e3f5c6ce22f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 20591 +timestamp: 1762976546182 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda +sha256: 79c60fc6acfd3d713d6340d3b4e296836a0f8c51602327b32794625826bd052f +md5: 34e54f03dfea3e7a2dcf1453a85f1085 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 50326 +timestamp: 1769445253162 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda +sha256: 83c4c99d60b8784a611351220452a0a85b080668188dce5dfa394b723d7b64f4 +md5: ba231da7fccf9ea1e768caf5c7099b84 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 20071 +timestamp: 1759282564045 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda +sha256: 1a724b47d98d7880f26da40e45f01728e7638e6ec69f35a3e11f92acd05f9e7a +md5: 17dcc85db3c7886650b8908b183d6876 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxfixes >=6.0.1,<7.0a0 +license: MIT +license_family: MIT +size: 47179 +timestamp: 1727799254088 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda +sha256: 80ed047a5cb30632c3dc5804c7716131d767089f65877813d4ae855ee5c9d343 +md5: e192019153591938acf7322b6459d36e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: MIT +license_family: MIT +size: 30456 +timestamp: 1769445263457 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda +sha256: 044c7b3153c224c6cedd4484dd91b389d2d7fd9c776ad0f4a34f099b3389f4a1 +md5: 96d57aba173e878a2089d5638016dc5e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 33005 +timestamp: 1734229037766 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda +sha256: a8afba4a55b7b530eb5c8ad89737d60d60bc151a03fbef7a2182461256953f0e +md5: 279b0de5f6ba95457190a1c459a64e31 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libice >=1.1.1,<2.0a0 +- xorg-libsm >=1.2.4,<2.0a0 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 379686 +timestamp: 1731860547604 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda +sha256: 752fdaac5d58ed863bbf685bb6f98092fe1a488ea8ebb7ed7b606ccfce08637a +md5: 7bbe9a0cc0df0ac5f5a8ad6d6a11af2f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxi >=1.7.10,<2.0a0 +license: MIT +license_family: MIT +size: 32808 +timestamp: 1727964811275 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 +md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 +depends: +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 601375 +timestamp: 1764777111296 diff --git a/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt new file mode 100644 index 0000000..cdc434c --- /dev/null +++ b/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt @@ -0,0 +1,769 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-aarch64: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 +md5: 468fd3bb9e1f671d36c2cbc677e56f1d +depends: +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28926 +timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda +sha256: ea2233e2db9908c2e5f29d3ca420a546b4583253f4f70abb5494cdd676866d42 +md5: 4a98cbc4ade694520227402ff8880630 +depends: +- libgcc >=14 +license: LGPL-2.1-or-later +license_family: GPL +size: 615729 +timestamp: 1768327548407 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c +md5: 840d8fc0d7b3209be93080bc20e07f2d +depends: +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 192412 +timestamp: 1771350241232 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda +sha256: 675db823f3d6fb6bf747fab3b0170ba99b269a07cf6df1e49fff2f9972be9cd1 +md5: 043c13ed3a18396994be9b4fab6572ad +depends: +- fontconfig >=2.15.0,<3.0a0 +- fonts-conda-ecosystem +- icu >=78.1,<79.0a0 +- libexpat >=2.7.3,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libglib >=2.86.3,<3.0a0 +- libpng >=1.6.53,<1.7.0a0 +- libstdcxx >=14 +- libxcb >=1.17.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pixman >=0.46.4,<1.0a0 +- xorg-libice >=1.1.2,<2.0a0 +- xorg-libsm >=1.2.6,<2.0a0 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: LGPL-2.1-only or MPL-1.1 +size: 927045 +timestamp: 1766416003626 +- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 +sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c +md5: c9f6a4b12229f7331f79c9a00dd6e240 +depends: +- font-ttf-dejavu-sans-mono +- fontconfig +- openjdk >=8.0.144 +- perl +license: GPL >=3 +size: 11664291 +timestamp: 1677946722445 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +sha256: 835aff8615dd8d8fff377679710ce81b8a2c47b6404e21a92fb349fda193a15c +md5: 0fed1ff55f4938a65907f3ecf62609db +depends: +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 279044 +timestamp: 1771382728182 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 +md5: fee5683a3f04bd15cbd8318b096a27ab +depends: +- fonts-conda-forge +license: BSD-3-Clause +license_family: BSD +size: 3667 +timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda +sha256: a79dc3bd54c4fb1f249942ee2d5b601a76ecf9614774a4cff9af49adfa458db2 +md5: 2f809afaf0ba1ea4135dce158169efac +depends: +- libgcc-ng >=12 +license: MIT +license_family: MIT +size: 82124 +timestamp: 1712692444545 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda +sha256: c9b1781fe329e0b77c5addd741e58600f50bef39321cae75eba72f2f381374b7 +md5: 4aa540e9541cc9d6581ab23ff2043f13 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: LGPL-2.0-or-later +license_family: LGPL +size: 102400 +timestamp: 1755102000043 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda +sha256: e22f485fddaaea3ff4b6cae98e0197b9dccd2ed2770337ad6ff38a92afe04e59 +md5: 05d65a2cf410adc331c9ea61f59f1013 +depends: +- cairo >=1.18.4,<2.0a0 +- graphite2 >=1.3.14,<2.0a0 +- icu >=78.3,<79.0a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.2 +- libfreetype6 >=2.14.2 +- libgcc >=14 +- libglib >=2.86.4,<3.0a0 +- libstdcxx >=14 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 2345732 +timestamp: 1774281448329 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +sha256: 49ba6aed2c6b482bb0ba41078057555d29764299bc947b990708617712ef6406 +md5: 546da38c2fa9efacf203e2ad3f987c59 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12837286 +timestamp: 1773822650615 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda +sha256: 5ce830ca274b67de11a7075430a72020c1fb7d486161a82839be15c2b84e9988 +md5: e7df0aab10b9cbb73ab2a467ebfaf8c7 +depends: +- libgcc >=13 +license: LGPL-2.1-or-later +size: 129048 +timestamp: 1754906002667 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda +sha256: b53999d888dda53c506b264e8c02b5f5c8e022c781eda0718f007339e6bc90ba +md5: d9ca108bd680ea86a963104b6b3e95ca +depends: +- keyutils >=1.6.3,<2.0a0 +- libedit >=3.1.20250104,<3.2.0a0 +- libedit >=3.1.20250104,<4.0a0 +- libgcc >=14 +- libstdcxx >=14 +- openssl >=3.5.5,<4.0a0 +license: MIT +license_family: MIT +size: 1517436 +timestamp: 1769773395215 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +sha256: 379ef5e91a587137391a6149755d0e929f1a007d2dcb211318ac670a46c8596f +md5: bb960f01525b5e001608afef9d47b79c +depends: +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 293039 +timestamp: 1768184778398 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +sha256: 8957fd460c1c132c8031f65fd5f56ec3807fd71b7cab2c5e2b0937b13404ab36 +md5: d13423b06447113a90b5b1366d4da171 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 240444 +timestamp: 1773114901155 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda +sha256: 41b04f995c9f63af8c4065a35931e46cbc2fdd6b9bf7e4c19f90d53cbb2bc8e5 +md5: 67828c963b17db7dc989fe5d509ef04a +depends: +- krb5 >=1.22.2,<1.23.0a0 +- libgcc >=14 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +license: Apache-2.0 +license_family: Apache +size: 4553739 +timestamp: 1770903929794 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 +md5: a9138815598fe6b91a1d6782ca657b0c +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 71117 +timestamp: 1761979776756 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda +sha256: c0b27546aa3a23d47919226b3a1635fccdb4f24b94e72e206a751b33f46fd8d6 +md5: fb640d776fc92b682a14e001980825b1 +depends: +- ncurses +- libgcc >=13 +- ncurses >=6.5,<7.0a0 +license: BSD-2-Clause +license_family: BSD +size: 148125 +timestamp: 1738479808948 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 +md5: 57f3b3da02a50a1be2a6fe847515417d +depends: +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76564 +timestamp: 1771259530958 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 +md5: 2f364feefb6a7c00423e80dcb12db62a +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 55952 +timestamp: 1769456078358 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a +md5: a229e22d4d8814a07702b0919d8e6701 +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8125 +timestamp: 1774301094057 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c +md5: b99ed99e42dafb27889483b3098cace7 +depends: +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 422941 +timestamp: 1774301093473 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +sha256: 43df385bedc1cab11993c4369e1f3b04b4ca5d0ea16cba6a0e7f18dbc129fcc9 +md5: 552567ea2b61e3a3035759b2fdb3f9a6 +depends: +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 622900 +timestamp: 1771378128706 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +sha256: 83bb0415f59634dccfa8335d4163d1f6db00a27b36666736f9842b650b92cf2f +md5: 4feebd0fbf61075a1a9c2e9b3936c257 +depends: +- libgcc 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27568 +timestamp: 1771378136019 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda +sha256: afc503dbd04a5bf2709aa9d8318a03a8c4edb389f661ff280c3494bfef4341ec +md5: 4ac4372fc4d7f20630a91314cdac8afd +depends: +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- libiconv >=1.18,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pcre2 >=10.47,<10.48.0a0 +constrains: +- glib 2.86.4 *_1 +license: LGPL-2.1-or-later +size: 4512186 +timestamp: 1771863220969 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +sha256: fc716f11a6a8525e27a5d332ef6a689210b0d2a4dd1133edc0f530659aa9faa6 +md5: 4faa39bf919939602e594253bd673958 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 588060 +timestamp: 1771378040807 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda +sha256: 1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9 +md5: 5a86bf847b9b926f3a4f203339748d78 +depends: +- libgcc >=14 +license: LGPL-2.1-only +size: 791226 +timestamp: 1754910975665 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +sha256: 84064c7c53a64291a585d7215fe95ec42df74203a5bf7615d33d49a3b0f08bb6 +md5: 5109d7f837a3dfdf5c60f60e311b041f +depends: +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 691818 +timestamp: 1762094728337 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +sha256: 843c46e20519651a3e357a8928352b16c5b94f4cd3d5481acc48be2e93e8f6a3 +md5: 96944e3c92386a12755b94619bae0b35 +depends: +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 125916 +timestamp: 1768754941722 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +sha256: c7378c6b79de4d571d00ad1caf0a4c19d43c9c94077a761abb6ead44d891f907 +md5: be4088903b94ea297975689b3c3aeb27 +depends: +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 340156 +timestamp: 1770691477245 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +sha256: 31fdb9ffafad106a213192d8319b9f810e05abca9c5436b60e507afb35a6bc40 +md5: f56573d05e3b735cb03efeb64a15f388 +depends: +- libgcc 15.2.0 h8acb6b2_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5541411 +timestamp: 1771378162499 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 +md5: 8c6fd84f9c87ac00636007c6131e457d +depends: +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 488407 +timestamp: 1762022048105 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 +md5: cf2861212053d05f27ec49c3784ff8bb +depends: +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 43453 +timestamp: 1766271546875 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 +md5: 24e92d0942c799db387f5c9d7b81f1af +depends: +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 359496 +timestamp: 1752160685488 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b +md5: cd14ee5cca2464a425b1dbfc24d90db2 +depends: +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 397493 +timestamp: 1727280745441 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda +sha256: 6b46c397644091b8a26a3048636d10b989b1bf266d4be5e9474bf763f828f41f +md5: b4df5d7d4b63579d081fd3a4cf99740e +depends: +- libgcc-ng >=12 +license: LGPL-2.1-or-later +size: 114269 +timestamp: 1702724369203 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f +md5: 502006882cf5461adced436e410046d1 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 69833 +timestamp: 1774072605429 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468 +md5: 182afabe009dc78d8b73100255ee6868 +depends: +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 926034 +timestamp: 1738196018799 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda +sha256: 6fd2c872b275fa5d42a61a4b6dc28a819cde29f9048adb547363597432e0720e +md5: 27fdd5d67e235c20d23b2d66406497d3 +depends: +- xorg-libx11 +- xorg-libxext +- xorg-libxi +- xorg-libxrender +- xorg-libxtst +- libstdcxx >=14 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +- xorg-libxtst >=1.2.5,<2.0a0 +- libpng >=1.6.55,<1.7.0a0 +- alsa-lib >=1.2.15.3,<1.3.0a0 +- xorg-libx11 >=1.8.13,<2.0a0 +- xorg-libxi >=1.8.2,<2.0a0 +- xorg-libxrandr >=1.5.5,<2.0a0 +- lcms2 >=2.18,<3.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +- libcups >=2.3.3,<2.4.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- harfbuzz >=12.3.2 +- xorg-libxext >=1.3.7,<2.0a0 +- giflib >=5.2.2,<5.3.0a0 +- xorg-libxt >=1.3.1,<2.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- fontconfig >=2.17.1,<3.0a0 +- fonts-conda-ecosystem +license: GPL-2.0-or-later WITH Classpath-exception-2.0 +license_family: GPL +size: 106988620 +timestamp: 1771443741031 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +sha256: 7f8048c0e75b2620254218d72b4ae7f14136f1981c5eb555ef61645a9344505f +md5: 25f5885f11e8b1f075bccf4a2da91c60 +depends: +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3692030 +timestamp: 1769557678657 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda +sha256: 04df2cee95feba440387f33f878e9f655521e69f4be33a0cd637f07d3d81f0f9 +md5: 1a30c42e32ca0ea216bd0bfe6f842f0b +depends: +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 1166552 +timestamp: 1763655534263 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda +build_number: 7 +sha256: d78296134263b5bf476cad838ded65451e7162db756f9997c5d06b08122572ed +md5: 17d019cb2a6c72073c344e98e40dfd61 +depends: +- libgcc-ng >=12 +- libxcrypt >=4.4.36 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 13338804 +timestamp: 1703310557094 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda +sha256: e6b0846a998f2263629cfeac7bca73565c35af13251969f45d385db537a514e4 +md5: 1587081d537bd4ae77d1c0635d465ba5 +depends: +- libgcc >=14 +- libstdcxx >=14 +- libgcc >=14 +license: MIT +license_family: MIT +size: 357913 +timestamp: 1754665583353 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 +md5: ab7288cc39545556d1bc5e71ab2df9a9 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 636733 +timestamp: 1769712412683 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba +md5: bb5a90c93e3bac3d5690acf76b4a6386 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 8342 +timestamp: 1726803319942 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda +sha256: a2ba1864403c7eb4194dacbfe2777acf3d596feae43aada8d1b478617ce45031 +md5: c8d8ec3e00cd0fd8a231789b91a7c5b7 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 60433 +timestamp: 1734229908988 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda +sha256: b86a819cd16f90c01d9d81892155126d01555a20dabd5f3091da59d6309afd0a +md5: 2d1409c50882819cb1af2de82e2b7208 +depends: +- libgcc >=13 +- libuuid >=2.38.1,<3.0a0 +- xorg-libice >=1.1.2,<2.0a0 +license: MIT +license_family: MIT +size: 28701 +timestamp: 1741897678254 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda +sha256: cf886160e2ff580d77f7eb8ec1a77c41c2c5b05343e329bc35f0ddf40b8d92ab +md5: 22dd10425ef181e80e130db50675d615 +depends: +- libgcc >=14 +- libxcb >=1.17.0,<2.0a0 +license: MIT +license_family: MIT +size: 869058 +timestamp: 1770819244991 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 +md5: 1c246e1105000c3660558459e2fd6d43 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 16317 +timestamp: 1762977521691 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1 +md5: bff06dcde4a707339d66d45d96ceb2e2 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 21039 +timestamp: 1762979038025 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda +sha256: db2188bc0d844d4e9747bac7f6c1d067e390bd769c5ad897c93f1df759dc5dba +md5: fb42b683034619915863d68dd9df03a3 +depends: +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 52409 +timestamp: 1769446753771 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda +sha256: 8cb9c88e25c57e47419e98f04f9ef3154ad96b9f858c88c570c7b91216a64d0e +md5: e8b4056544341daf1d415eaeae7a040c +depends: +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 20704 +timestamp: 1759284028146 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda +sha256: 7b587407ecb9ccd2bbaf0fb94c5dbdde4d015346df063e9502dc0ce2b682fb5e +md5: eeee3bdb31c6acde2b81ad1b8c287087 +depends: +- libgcc >=13 +- xorg-libx11 >=1.8.9,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxfixes >=6.0.1,<7.0a0 +license: MIT +license_family: MIT +size: 48197 +timestamp: 1727801059062 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda +sha256: 9f5196665a8d72f4f119c40dcc4bafeb0b540b102cc7b8b299c2abf599e7919f +md5: 1f64c613f0b8d67e9fb0e165d898fb6b +depends: +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: MIT +license_family: MIT +size: 31122 +timestamp: 1769445286951 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda +sha256: ffd77ee860c9635a28cfda46163dcfe9224dc6248c62404c544ae6b564a0be1f +md5: ae2c2dd0e2d38d249887727db2af960e +depends: +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 33649 +timestamp: 1734229123157 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda +sha256: 7c109792b60720809a580612aba7f8eb2a0bd425b9fc078748a9d6ffc97cbfa8 +md5: a9e4852c8e0b68ee783e7240030b696f +depends: +- libgcc >=13 +- xorg-libice >=1.1.1,<2.0a0 +- xorg-libsm >=1.2.4,<2.0a0 +- xorg-libx11 >=1.8.9,<2.0a0 +license: MIT +license_family: MIT +size: 384752 +timestamp: 1731860572314 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda +sha256: 6eaffce5a34fc0a16a21ddeaefb597e792a263b1b0c387c1ce46b0a967d558e1 +md5: c05698071b5c8e0da82a282085845860 +depends: +- libgcc >=13 +- xorg-libx11 >=1.8.9,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxi >=1.7.10,<2.0a0 +license: MIT +license_family: MIT +size: 33786 +timestamp: 1727964907993 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 +md5: c3655f82dcea2aa179b291e7099c1fcc +depends: +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 614429 +timestamp: 1764777145593 diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml index 691d4c7..f9f54ee 100644 --- a/modules/nf-core/fastqc/environment.yml +++ b/modules/nf-core/fastqc/environment.yml @@ -1,3 +1,5 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json channels: - conda-forge - bioconda diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index 033f415..1085126 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -1,37 +1,40 @@ process FASTQC { tag "${meta.id}" - label 'process_medium' + label 'process_low' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' : - 'biocontainers/fastqc:0.12.1--hdfd78af_0' }" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://depot.galaxyproject.org/singularity/fastqc:0.12.1--hdfd78af_0' + : 'quay.io/biocontainers/fastqc:0.12.1--hdfd78af_0'}" input: - tuple val(meta), path(reads) + tuple val(meta), path(reads, stageAs: '?/*') output: tuple val(meta), path("*.html"), emit: html - tuple val(meta), path("*.zip") , emit: zip - path "versions.yml" , emit: versions + tuple val(meta), path("*.zip"), emit: zip + tuple val("${task.process}"), val('fastqc'), eval('fastqc --version | sed "/FastQC v/!d; s/.*v//"'), emit: versions_fastqc, topic: versions when: task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" // Make list of old name and new name pairs to use for renaming in the bash while loop - def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } - def rename_to = old_new_pairs*.join(' ').join(' ') - def renamed_files = old_new_pairs.collect{ _old_name, new_name -> new_name }.join(' ') + def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[reads, "${prefix}.${reads.extension}"]] : reads.withIndex().collect { entry, index -> [entry, "${prefix}_${index + 1}.${entry.extension}"] } + def rename_to = old_new_pairs*.join(' ').join(' ') + def renamed_files = old_new_pairs.collect { _old_name, new_name -> new_name }.join(' ') // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 - // Dividing the task.memory by task.cpu allows to stick to requested amount of RAM in the label - def memory_in_mb = task.memory ? task.memory.toUnit('MB').toFloat() / task.cpus : null + // Dividing the task.memory by task.cpus allows to stick to requested amount of RAM in the label + def memory_in_mb = task.memory + ? (task.memory.toUnit('MB') / task.cpus).intValue() + : null // FastQC memory value allowed range (100 - 10000) def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) + def fastqc_memory_arg = fastqc_memory ? "--memory ${fastqc_memory}" : '' """ printf "%s %s\\n" ${rename_to} | while read old_name new_name; do @@ -41,13 +44,8 @@ process FASTQC { fastqc \\ ${args} \\ --threads ${task.cpus} \\ - --memory ${fastqc_memory} \\ + ${fastqc_memory_arg} \\ ${renamed_files} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) - END_VERSIONS """ stub: @@ -55,10 +53,5 @@ process FASTQC { """ touch ${prefix}.html touch ${prefix}.zip - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - fastqc: \$( fastqc --version | sed '/FastQC v/!d; s/.*v//' ) - END_VERSIONS """ } diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml index 2b2e62b..2f6cfef 100644 --- a/modules/nf-core/fastqc/meta.yml +++ b/modules/nf-core/fastqc/meta.yml @@ -29,9 +29,10 @@ input: description: | List of input FastQ files of size 1 and 2 for single-end and paired-end data, respectively. + ontologies: [] output: - - html: - - meta: + html: + - - meta: type: map description: | Groovy Map containing sample information @@ -40,8 +41,9 @@ output: type: file description: FastQC report pattern: "*_{fastqc.html}" - - zip: - - meta: + ontologies: [] + zip: + - - meta: type: map description: | Groovy Map containing sample information @@ -50,11 +52,29 @@ output: type: file description: FastQC report archive pattern: "*_{fastqc.zip}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions_fastqc: + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool + +topics: + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - fastqc: + type: string + description: The tool name + - fastqc --version | sed "/FastQC v/!d; s/.*v//": + type: eval + description: The expression to obtain the version of the tool authors: - "@drpatelh" - "@grst" @@ -65,3 +85,27 @@ maintainers: - "@grst" - "@ewels" - "@FelixKrueger" +containers: + docker: + linux/arm64: + name: community.wave.seqera.io/library/fastqc:0.12.1--e455e32f745abe68 + build_id: bd-e455e32f745abe68_1 + scan_id: sc-f102f736465af88c_1 + linux/amd64: + name: community.wave.seqera.io/library/fastqc:0.12.1--5cb1a2fa2f18c7c2 + build_id: bd-5cb1a2fa2f18c7c2_1 + scan_id: sc-0c0466326b6b77d2_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--5c4bd442468d75dd + build_id: bd-5c4bd442468d75dd_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/f2/f20b021476d1d87658820f971ebecc1e8cdbde0f338eb0d9cea2b0a8fc54a54b/data + linux/arm64: + name: oras://community.wave.seqera.io/library/fastqc:0.12.1--127a87fc06499035 + build_id: bd-127a87fc06499035_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/46/46daf2dad0169afd2ae047c3e50ed3776259f664bf07e5e06b045dc23449e994/data + conda: + linux/amd64: + lock_file: modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt + linux/arm64: + lock_file: modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test index e9d79a0..66c44da 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test +++ b/modules/nf-core/fastqc/tests/main.nf.test @@ -30,7 +30,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -58,7 +58,7 @@ nextflow_process { { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -82,7 +82,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -106,7 +106,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -142,7 +142,7 @@ nextflow_process { { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } @@ -166,7 +166,7 @@ nextflow_process { { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(sanitizeOutput(process.out).findAll { key, val -> key != 'html' && key != 'zip' }).match() } ) } } diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap index d5db309..c8ee120 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test.snap +++ b/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -1,15 +1,21 @@ { "sarscov2 custom_prefix": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:16.374038" + "timestamp": "2025-10-28T16:39:14.518503" }, "sarscov2 single-end [fastq] - stub": { "content": [ @@ -33,7 +39,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -44,8 +54,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -59,10 +73,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:24.993809" + "timestamp": "2025-10-28T16:39:19.309008" }, "sarscov2 custom_prefix - stub": { "content": [ @@ -86,7 +100,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -97,8 +115,12 @@ "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -112,58 +134,82 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:03:10.93942" + "timestamp": "2025-10-28T16:39:44.94888" }, "sarscov2 interleaved [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:42.355718" + "timestamp": "2025-10-28T16:38:45.168496" }, "sarscov2 paired-end [bam]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:53.276274" + "timestamp": "2025-10-28T16:38:53.268919" }, "sarscov2 multiple [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:05.527626" + "timestamp": "2025-10-28T16:39:05.050305" }, "sarscov2 paired-end [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:31.188871" + "timestamp": "2025-10-28T16:38:37.2373" }, "sarscov2 paired-end [fastq] - stub": { "content": [ @@ -187,7 +233,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -198,8 +248,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -213,10 +267,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:34.273566" + "timestamp": "2025-10-28T16:39:24.450398" }, "sarscov2 multiple [fastq] - stub": { "content": [ @@ -240,7 +294,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -251,8 +309,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -266,22 +328,28 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:03:02.304411" + "timestamp": "2025-10-28T16:39:39.758762" }, "sarscov2 single-end [fastq]": { "content": [ - [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] + ] + } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:01:19.095607" + "timestamp": "2025-10-28T16:38:29.555068" }, "sarscov2 interleaved [fastq] - stub": { "content": [ @@ -305,7 +373,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -316,8 +388,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -331,10 +407,10 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:44.640184" + "timestamp": "2025-10-28T16:39:29.193136" }, "sarscov2 paired-end [bam] - stub": { "content": [ @@ -358,7 +434,11 @@ ] ], "2": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "html": [ [ @@ -369,8 +449,12 @@ "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + "versions_fastqc": [ + [ + "FASTQC", + "fastqc", + "0.12.1" + ] ], "zip": [ [ @@ -384,9 +468,9 @@ } ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.04.3" + "nf-test": "0.9.2", + "nextflow": "25.10.0" }, - "timestamp": "2024-07-22T11:02:53.550742" + "timestamp": "2025-10-28T16:39:34.144919" } } \ No newline at end of file diff --git a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt new file mode 100644 index 0000000..7619030 --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt @@ -0,0 +1,1552 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-64: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py314h2b28147_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.1.1-py314h8ec4b1a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.39.3-py310hffdcd12_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.39.3-py310hbcd5346_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py314h2e6c369_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.2.28-py314h5bd0f2a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.52.0-h04a0ce9_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 +md5: a9f577daf3de00bca7c3c76c0ecbd1de +depends: +- __glibc >=2.17,<3.0.a0 +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28948 +timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 +md5: aaa2a381ccc56eac91d63b6c1240312f +depends: +- cpython +- python-gil +license: MIT +license_family: MIT +size: 8191 +timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 +md5: 2934f256a8acfe48f6ebb4fce6cde29c +depends: +- python >=3.9 +- typing-extensions >=4.0.0 +license: MIT +license_family: MIT +size: 18074 +timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab +md5: c6b0543676ecb1fb2d7643941fe375f2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 64927 +timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +noarch: generic +sha256: c31ab719d256bc6f89926131e88ecd0f0c5d003fe8481852c6424f4ec6c7eb29 +md5: a2ac7763a9ac75055b68f325d3255265 +depends: +- python >=3.14 +license: BSD-3-Clause AND MIT AND EPL-2.0 +size: 7514 +timestamp: 1767044983590 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda +sha256: 3ad3500bff54a781c29f16ce1b288b36606e2189d0b0ef2f67036554f47f12b0 +md5: 8910d2c46f7e7b519129f486e0fe927a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- libbrotlicommon 1.2.0 hb03c661_1 +license: MIT +license_family: MIT +size: 367376 +timestamp: 1764017265553 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 +md5: d2ffd7602c02f2b316fd921d39876885 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 260182 +timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda +sha256: a6b118fd1ed6099dc4fc03f9c492b88882a780fadaef4ed4f93dc70757713656 +md5: 765c4d97e877cdbbb88ff33152b86125 +depends: +- python >=3.10 +license: ISC +size: 151445 +timestamp: 1772001170301 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda +sha256: d86dfd428b2e3c364fa90e07437c8405d635aa4ef54b25ab51d9c712be4112a5 +md5: 49ee13eb9b8f44d63879c69b8a40a74b +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 58510 +timestamp: 1773660086450 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715 +md5: ea8a6c3256897cc31263de9f455e25d9 +depends: +- python >=3.10 +- __unix +- python +license: BSD-3-Clause +license_family: BSD +size: 97676 +timestamp: 1764518652276 +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 +md5: b866ff7007b934d564961066c8195983 +depends: +- humanfriendly >=9.1 +- python >=3.9 +license: MIT +license_family: MIT +size: 43758 +timestamp: 1733928076798 +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +sha256: 59c9e29800b483b390467f90e82b0da3a4fbf0612efe1c90813fca232780e160 +md5: 071cf7b0ce333c81718b054066c15102 +depends: +- networkx >=2.0 +- numpy +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 39326 +timestamp: 1735759976140 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +noarch: generic +sha256: 91b06300879df746214f7363d6c27c2489c80732e46a369eb2afc234bcafb44c +md5: 3bb89e4f795e5414addaa531d6b1500a +depends: +- python >=3.14,<3.15.0a0 +- python_abi * *_cp314 +license: Python-2.0 +size: 50078 +timestamp: 1770674447292 +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda +sha256: 0cc345e4dead417996ce9a1f088b28d858f03d113d43c1963d29194366dcce27 +md5: a0535741a4934b3e386051065c58761a +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat 2.7.4 hecca717_0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 145274 +timestamp: 1771259434699 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda +sha256: aa4a44dba97151221100a637c7f4bde619567afade9c0265f8e1c8eed8d7bd8c +md5: 867127763fbe935bab59815b6e0b7b5c +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 270705 +timestamp: 1771382710863 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 +md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 +depends: +- python >=3.10 +- hyperframe >=6.1,<7 +- hpack >=4.1,<5 +- python +license: MIT +license_family: MIT +size: 95967 +timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba +md5: 0a802cb9888dd14eeefc611f05c40b6e +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 30731 +timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d +md5: 7fe569c10905402ed47024fc481bb371 +depends: +- __unix +- python >=3.9 +license: MIT +license_family: MIT +size: 73563 +timestamp: 1733928021866 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +sha256: 6c4343b376d0b12a4c75ab992640970d36c933cad1fd924f6a1181fa91710e80 +md5: daddf757c3ecd6067b9af1df1f25d89e +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 67994 +timestamp: 1766267728652 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 +md5: 8e6923fc12f1fe8f8c4e5c9f343256ac +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 17397 +timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda +sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a +md5: c80d8a3b84358cb967fa81e7075fbc8a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12723451 +timestamp: 1773822285671 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda +sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 +md5: 53abe63df7e10a6ba605dc5f9f961d36 +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 50721 +timestamp: 1760286526795 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 +md5: 080594bf4493e6bae2607e65390c520a +depends: +- python >=3.10 +- zipp >=3.20 +- python +license: Apache-2.0 +license_family: APACHE +size: 34387 +timestamp: 1773931568510 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b +md5: 04558c96691bed63104678757beb4f8d +depends: +- markupsafe >=2.0 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 120685 +timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 +md5: ada41c863af263cc4c5fcbaff7c3e4dc +depends: +- attrs >=22.2.0 +- jsonschema-specifications >=2023.3.6 +- python >=3.10 +- referencing >=0.28.4 +- rpds-py >=0.25.0 +- python +license: MIT +license_family: MIT +size: 82356 +timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 +md5: 439cd0f567d697b20a8f45cb70a1005a +depends: +- python >=3.10 +- referencing >=0.31.0 +- python +license: MIT +license_family: MIT +size: 19236 +timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2 +sha256: 7f243680ca03eba7457b7a48f93a9440ba8181a8eac20a3eb5ef165ab6c96664 +md5: b3723b235b0758abaae8c82ce4d80146 +depends: +- __glibc >=2.17,<3.0.a0 +- expat >=2.2.10,<3.0.0a0 +- fontconfig +- fonts-conda-forge +- libgcc-ng >=9.3.0 +- mathjax 2.7.* +- nspr >=4.29,<5.0a0 +- nss >=3.62,<4.0a0 +- sqlite >=3.34.0,<4.0a0 +license: MIT +license_family: MIT +size: 62099926 +timestamp: 1615199463039 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda +sha256: 836ec4b895352110335b9fdcfa83a8dcdbe6c5fb7c06c4929130600caea91c0a +md5: 6f2e2c8f58160147c4d1c6f4c14cbac4 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 249959 +timestamp: 1768184673131 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda +sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c +md5: 18335a698559cdbcd86150a48bf54ba6 +depends: +- __glibc >=2.17,<3.0.a0 +- zstd >=1.5.7,<1.6.0a0 +constrains: +- binutils_impl_linux-64 2.45.1 +license: GPL-3.0-only +license_family: GPL +size: 728002 +timestamp: 1774197446916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +sha256: f84cb54782f7e9cea95e810ea8fef186e0652d0fa73d3009914fa2c1262594e1 +md5: a752488c68f2e7c456bcbd8f16eec275 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 261513 +timestamp: 1773113328888 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-5_h4a7cf45_openblas.conda +build_number: 5 +sha256: 18c72545080b86739352482ba14ba2c4815e19e26a7417ca21a95b76ec8da24c +md5: c160954f7418d7b6e87eaf05a8913fa9 +depends: +- libopenblas >=0.3.30,<0.3.31.0a0 +- libopenblas >=0.3.30,<1.0a0 +constrains: +- mkl <2026 +- liblapack 3.11.0 5*_openblas +- libcblas 3.11.0 5*_openblas +- blas 2.305 openblas +- liblapacke 3.11.0 5*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18213 +timestamp: 1765818813880 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-5_h0358290_openblas.conda +build_number: 5 +sha256: 0cbdcc67901e02dc17f1d19e1f9170610bd828100dc207de4d5b6b8ad1ae7ad8 +md5: 6636a2b6f1a87572df2970d3ebc87cc0 +depends: +- libblas 3.11.0 5_h4a7cf45_openblas +constrains: +- liblapacke 3.11.0 5*_openblas +- blas 2.305 openblas +- liblapack 3.11.0 5*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18194 +timestamp: 1765818837135 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 +md5: 6c77a605a7a689d17d4819c0f8ac9a00 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 73490 +timestamp: 1761979956660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda +sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 +md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76798 +timestamp: 1771259418166 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 +md5: a360c33a5abe61c07959e449fa1453eb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 58592 +timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 +md5: e289f3d17880e44b633ba911d57a321b +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8049 +timestamp: 1774298163029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d +md5: fb16b4b69e3f1dcfe79d80db8fd0c55d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 384575 +timestamp: 1774298162622 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda +sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 +md5: 0aa00f03f9e39fb9876085dee11a85d4 +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1041788 +timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda +sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 +md5: d5e96b1ed75ca01906b3d2469b4ce493 +depends: +- libgcc 15.2.0 he0feb66_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27526 +timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda +sha256: d2c9fad338fd85e4487424865da8e74006ab2e2475bd788f624d7a39b2a72aee +md5: 9063115da5bc35fdc3e1002e69b9ef6e +depends: +- libgfortran5 15.2.0 h68bc16d_18 +constrains: +- libgfortran-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27523 +timestamp: 1771378269450 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda +sha256: 539b57cf50ec85509a94ba9949b7e30717839e4d694bc94f30d41c9d34de2d12 +md5: 646855f357199a12f02a87382d429b75 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=15.2.0 +constrains: +- libgfortran 15.2.0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 2482475 +timestamp: 1771378241063 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda +sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 +md5: 239c5e9546c38a1e884d69effcf4c882 +depends: +- __glibc >=2.17,<3.0.a0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 603262 +timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda +sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32 +md5: 8397539e3a0bbd1695584fb4f927485a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 633710 +timestamp: 1762094827865 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-5_h47877c9_openblas.conda +build_number: 5 +sha256: c723b6599fcd4c6c75dee728359ef418307280fa3e2ee376e14e85e5bbdda053 +md5: b38076eb5c8e40d0106beda6f95d7609 +depends: +- libblas 3.11.0 5_h4a7cf45_openblas +constrains: +- blas 2.305 openblas +- liblapacke 3.11.0 5*_openblas +- libcblas 3.11.0 5*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18200 +timestamp: 1765818857876 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda +sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb +md5: c7c83eecbb72d88b940c249af56c8b17 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 113207 +timestamp: 1768752626120 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda +sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 +md5: 2c21e66f50753a083cbe6b80f38268fa +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-2-Clause +license_family: BSD +size: 92400 +timestamp: 1769482286018 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.30-pthreads_h94d23a6_4.conda +sha256: 199d79c237afb0d4780ccd2fbf829cea80743df60df4705202558675e07dd2c5 +md5: be43915efc66345cccb3c310b6ed0374 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libgfortran +- libgfortran5 >=14.3.0 +constrains: +- openblas >=0.3.30,<0.3.31.0a0 +license: BSD-3-Clause +license_family: BSD +size: 5927939 +timestamp: 1763114673331 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda +sha256: 36ade759122cdf0f16e2a2562a19746d96cf9c863ffaa812f2f5071ebbe9c03c +md5: 5f13ffc7d30ffec87864e678df9957b4 +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 317669 +timestamp: 1770691470744 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda +sha256: d716847b7deca293d2e49ed1c8ab9e4b9e04b9d780aea49a97c26925b28a7993 +md5: fd893f6a3002a635b5e50ceb9dd2c0f4 +depends: +- __glibc >=2.17,<3.0.a0 +- icu >=78.2,<79.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: blessing +size: 951405 +timestamp: 1772818874251 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda +sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e +md5: 1b08cd684f34175e4514474793d44bcb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc 15.2.0 he0feb66_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5852330 +timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 +md5: cd5a90476766d53e901500df9215e927 +depends: +- __glibc >=2.17,<3.0.a0 +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 435273 +timestamp: 1762022005702 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda +sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee +md5: db409b7c1720428638e7c0d509d3e1b5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 40311 +timestamp: 1766271528534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b +md5: aea31d2e5b1091feca96fcfe945c3cf9 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 429011 +timestamp: 1752159441324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa +md5: 92ed62436b625154323d40d5f2f11dd7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 395888 +timestamp: 1727278577118 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 +md5: d87ff7921124eccd67248aa483c23fec +depends: +- __glibc >=2.17,<3.0.a0 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 63629 +timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +sha256: 20e0892592a3e7c683e3d66df704a9425d731486a97c34fc56af4da1106b2b6b +md5: ba0a9221ce1063f31692c07370d062f3 +depends: +- importlib-metadata >=4.4 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 85893 +timestamp: 1770694658918 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e +md5: 5b5203189eb668f042ac2b0826244964 +depends: +- mdurl >=0.1,<1 +- python >=3.10 +license: MIT +license_family: MIT +size: 64736 +timestamp: 1754951288511 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda +sha256: c279be85b59a62d5c52f5dd9a4cd43ebd08933809a8416c22c3131595607d4cf +md5: 9a17c4307d23318476d7fbf0fedc0cde +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- jinja2 >=3.0.0 +license: BSD-3-Clause +license_family: BSD +size: 27424 +timestamp: 1772445227915 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2 +sha256: 02fef69bde69db264a12f21386612262f545b6e3e68d8f1ccec19f3eaae58edf +md5: 86e69bd82c2a2c6fd29f5ab7e02b3691 +license: Apache-2.0 +license_family: Apache +size: 22281629 +timestamp: 1662784498331 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 +md5: 592132998493b3ff25fd7479396e8351 +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 14465 +timestamp: 1733255681319 +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda +sha256: f005760b13093362fc9c997d603dd487de32ab2e821a3cbce52a42bcb8136517 +md5: 698a8a27c2b9d8a542c70cb47099a75e +depends: +- click +- coloredlogs +- humanize +- importlib-metadata +- jinja2 >=3.0.0 +- jsonschema +- markdown +- natsort +- numpy +- packaging +- pillow >=10.2.0 +- plotly >=5.18 +- polars-lts-cpu +- pyaml-env +- pydantic >=2.7.1 +- python >=3.8,!=3.14.1 +- python-dotenv +- python-kaleido 0.2.1 +- pyyaml >=4 +- requests +- rich >=10 +- rich-click +- spectra >=0.0.10 +- tiktoken +- tqdm +- typeguard +license: GPL-3.0-or-later +license_family: GPL3 +size: 4198799 +timestamp: 1765300743879 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +sha256: 541fd4390a0687228b8578247f1536a821d9261389a65585af9d1a6f2a14e1e0 +md5: 30bec5e8f4c3969e2b1bd407c5e52afb +depends: +- python >=3.10 +- python +license: MIT +size: 280459 +timestamp: 1774380620329 +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 +md5: e941e85e273121222580723010bd4fa2 +depends: +- python >=3.9 +- python +license: MIT +license_family: MIT +size: 39262 +timestamp: 1770905275632 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda +sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 +md5: 47e340acb35de30501a76c7c799c41d7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 891641 +timestamp: 1738195959188 +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 +md5: a2c1eeadae7a309daed9d62c96012a2b +depends: +- python >=3.11 +- python +constrains: +- numpy >=1.25 +- scipy >=1.11.2 +- matplotlib-base >=3.8 +- pandas >=2.0 +license: BSD-3-Clause +license_family: BSD +size: 1587439 +timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda +sha256: e3664264bd936c357523b55c71ed5a30263c6ba278d726a75b1eb112e6fb0b64 +md5: e235d5566c9cc8970eb2798dd4ecf62f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: MPL-2.0 +license_family: MOZILLA +size: 228588 +timestamp: 1762348634537 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda +sha256: 44dd98ffeac859d84a6dcba79a2096193a42fc10b29b28a5115687a680dd6aea +md5: 567fbeed956c200c1db5782a424e58ee +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libsqlite >=3.51.0,<4.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- nspr >=4.38,<5.0a0 +license: MPL-2.0 +license_family: MOZILLA +size: 2057773 +timestamp: 1763485556350 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py314h2b28147_0.conda +sha256: f2ba8cb0d86a6461a6bcf0d315c80c7076083f72c6733c9290086640723f79ec +md5: 36f5b7eb328bdc204954a2225cf908e2 +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +- libcblas >=3.9.0,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- libblas >=3.9.0,<4.0a0 +constrains: +- numpy-base <0a0 +license: BSD-3-Clause +license_family: BSD +size: 8927860 +timestamp: 1773839233468 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda +sha256: 3900f9f2dbbf4129cf3ad6acf4e4b6f7101390b53843591c53b00f034343bc4d +md5: 11b3379b191f63139e29c0d19dee24cd +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.50,<1.7.0a0 +- libstdcxx >=14 +- libtiff >=4.7.1,<4.8.0a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-2-Clause +license_family: BSD +size: 355400 +timestamp: 1758489294972 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda +sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c +md5: f61eb8cd60ff9057122a3d338b99c00f +depends: +- __glibc >=2.17,<3.0.a0 +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3164551 +timestamp: 1769555830639 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda +sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 +md5: b76541e68fea4d511b1ac46a28dcd2c6 +depends: +- python >=3.8 +- python +license: Apache-2.0 +license_family: APACHE +size: 72010 +timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.1.1-py314h8ec4b1a_0.conda +sha256: 9e6ec8f3213e8b7d64b0ad45f84c51a2c9eba4398efda31e196c9a56186133ee +md5: 79678378ae235e24b3aa83cee1b38207 +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libwebp-base >=1.6.0,<2.0a0 +- zlib-ng >=2.3.3,<2.4.0a0 +- python_abi 3.14.* *_cp314 +- tk >=8.6.13,<8.7.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libxcb >=1.17.0,<2.0a0 +- openjpeg >=2.5.4,<3.0a0 +- lcms2 >=2.18,<3.0a0 +- libtiff >=4.7.1,<4.8.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +license: HPND +size: 1073026 +timestamp: 1770794002408 +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 +md5: 3e9427ee186846052e81fadde8ebe96a +depends: +- narwhals >=1.15.1 +- packaging +- python >=3.10 +constrains: +- ipywidgets >=7.6 +license: MIT +license_family: MIT +size: 5251872 +timestamp: 1772628857717 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda +sha256: d332c2d5002fc440ae37ed9679ffc21b552f18d20232390005d1dd3bce0888d3 +md5: d5a4e013a30dd8dfde9ab39f45aaf9c1 +depends: +- polars-runtime-32 ==1.39.3 +- python >=3.10 +- python +constrains: +- numpy >=1.16.0 +- pyarrow >=7.0.0 +- fastexcel >=0.9 +- openpyxl >=3.0.0 +- xlsx2csv >=0.8.0 +- connectorx >=0.3.2 +- deltalake >=1.0.0 +- pyiceberg >=0.7.1 +- altair >=5.4.0 +- great_tables >=0.8.0 +- polars-runtime-32 ==1.39.3 +- polars-runtime-64 ==1.39.3 +- polars-runtime-compat ==1.39.3 +license: MIT +license_family: MIT +size: 533495 +timestamp: 1774207987966 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda +sha256: e466fb31f67ba9bde18deafeb34263ca5eb25807f39ead0e9d753a8e82c4c4f4 +md5: ef0340e75068ac8ff96462749b5c98e7 +depends: +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 +license: MIT +license_family: MIT +size: 3902 +timestamp: 1760206808444 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.39.3-py310hffdcd12_1.conda +noarch: python +sha256: 9744f8086bb0832998f5b01076f57ddc9efbe460e493b14303c3567dc4f401e7 +md5: f9327f9f2cfc4215f55b613e64afd3ba +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 37570276 +timestamp: 1774207987966 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.39.3-py310hbcd5346_1.conda +noarch: python +sha256: bf0b932713f0f27924f42159c98426e0073bb6145ed796eaa4cec79ca05363c7 +md5: 4b9b312453eebd6fbdbbe2a88fa1b5c4 +depends: +- python +- libgcc >=14 +- libstdcxx >=14 +- __glibc >=2.17,<3.0.a0 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 37224264 +timestamp: 1774207985377 +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d +md5: f2c23a77b25efcad57d377b34bd84941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 593603 +timestamp: 1769710381284 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 +md5: b3c17d95b5a10c6e64a21fa17573e70e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 8252 +timestamp: 1726802366959 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +sha256: 58994e0d2ea8584cb399546e6f6896d771995e6121d1a7b6a2c9948388358932 +md5: e17be1016bcc3516827b836cd3e4d9dc +depends: +- python >=3.9 +- pyyaml >=5.0,<=7.0 +license: MIT +license_family: MIT +size: 14645 +timestamp: 1736766960536 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda +sha256: 868569d9505b7fe246c880c11e2c44924d7613a8cdcc1f6ef85d5375e892f13d +md5: c3946ed24acdb28db1b5d63321dbca7d +depends: +- typing-inspection >=0.4.2 +- typing_extensions >=4.14.1 +- python >=3.10 +- typing-extensions >=4.6.1 +- annotated-types >=0.6.0 +- pydantic-core ==2.41.5 +- python +license: MIT +license_family: MIT +size: 340482 +timestamp: 1764434463101 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.41.5-py314h2e6c369_1.conda +sha256: 7e0ae379796e28a429f8e48f2fe22a0f232979d65ec455e91f8dac689247d39f +md5: 432b0716a1dfac69b86aa38fdd59b7e6 +depends: +- python +- typing-extensions >=4.6.0,!=4.7.0 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 1943088 +timestamp: 1762988995556 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a +md5: 6b6ece66ebcae2d5f326c77ef2c5a066 +depends: +- python >=3.9 +license: BSD-2-Clause +license_family: BSD +size: 889287 +timestamp: 1750615908735 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 +md5: 461219d1a5bd61342293efa2c0c90eac +depends: +- __unix +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 21085 +timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.3-h32b2ec7_101_cp314.conda +build_number: 101 +sha256: cb0628c5f1732f889f53a877484da98f5a0e0f47326622671396fb4f2b0cd6bd +md5: c014ad06e60441661737121d3eae8a60 +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- ld_impl_linux-64 >=2.36.1 +- libexpat >=2.7.3,<3.0a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- liblzma >=5.8.2,<6.0a0 +- libmpdec >=4.0.0,<5.0a0 +- libsqlite >=3.51.2,<4.0a0 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +- openssl >=3.5.5,<4.0a0 +- python_abi 3.14.* *_cp314 +- readline >=8.3,<9.0a0 +- tk >=8.6.13,<8.7.0a0 +- tzdata +- zstd >=1.5.7,<1.6.0a0 +license: Python-2.0 +size: 36702440 +timestamp: 1770675584356 +python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 +md5: 130584ad9f3a513cdd71b1fdc1244e9c +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 27848 +timestamp: 1772388605021 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +sha256: 233aebd94c704ac112afefbb29cf4170b7bc606e22958906f2672081bc50638a +md5: 235765e4ea0d0301c75965985163b5a1 +depends: +- cpython 3.14.3.* +- python_abi * *_cp314 +license: Python-2.0 +size: 50062 +timestamp: 1770674497152 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 +md5: 310259a5b03ff02289d7705f39e2b1d2 +depends: +- kaleido-core 0.2.1.* +- python >=3.5 +license: MIT +license_family: MIT +size: 18320 +timestamp: 1615204747600 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +build_number: 8 +sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 +md5: 0539938c55b6b1a59b560e843ad864a4 +constrains: +- python 3.14.* *_cp314 +license: BSD-3-Clause +license_family: BSD +size: 6989 +timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda +sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d +md5: 2035f68f96be30dc60a5dfd7452c7941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- yaml >=0.2.5,<0.3.0a0 +license: MIT +license_family: MIT +size: 202391 +timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda +sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 +md5: d7d95fc8287ea7bf33e0e7116d2b95ec +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-3.0-only +license_family: GPL +size: 345073 +timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 +md5: 870293df500ca7e18bedefa5838a22ab +depends: +- attrs >=22.2.0 +- python >=3.10 +- rpds-py >=0.7.0 +- typing_extensions >=4.4.0 +- python +license: MIT +license_family: MIT +size: 51788 +timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.2.28-py314h5bd0f2a_0.conda +sha256: e085e336f1446f5263a3ec9747df8c719b6996753901181add50dc4fdd8bb2e8 +md5: 3c8b6a8c4d0ff5a264e9831eac4941f4 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +license: Apache-2.0 AND CNRI-Python +license_family: PSF +size: 411924 +timestamp: 1772255161535 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda +sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5 +md5: c65df89a0b2e321045a9e01d1337b182 +depends: +- python >=3.10 +- certifi >=2017.4.17 +- charset-normalizer >=2,<4 +- idna >=2.5,<4 +- urllib3 >=1.21.1,<3 +- python +constrains: +- chardet >=3.0.2,<6 +license: Apache-2.0 +license_family: APACHE +size: 63602 +timestamp: 1766926974520 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +sha256: b06ce84d6a10c266811a7d3adbfa1c11f13393b91cc6f8a5b468277d90be9590 +md5: 7a6289c50631d620652f5045a63eb573 +depends: +- markdown-it-py >=2.2.0 +- pygments >=2.13.0,<3.0.0 +- python >=3.10 +- typing_extensions >=4.0.0,<5.0.0 +- python +license: MIT +license_family: MIT +size: 208472 +timestamp: 1771572730357 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 +md5: 0c20a8ebcddb24a45da89d5e917e6cb9 +depends: +- python >=3.10 +- rich >=12 +- click >=8 +- typing-extensions >=4 +- __unix +- python +license: MIT +license_family: MIT +size: 64356 +timestamp: 1769850479089 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda +sha256: e53b0cbf3b324eaa03ca1fe1a688fdf4ab42cea9c25270b0a7307d8aaaa4f446 +md5: c1c368b5437b0d1a68f372ccf01cb133 +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 376121 +timestamp: 1764543122774 +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +sha256: 7c65782d2511738e62c70462e89d65da4fa54d5a7e47c46667bcd27a59f81876 +md5: 472239e4eb7b5a84bb96b3ed7e3a596a +depends: +- colormath >=3.0.0 +- python >=3.9 +license: MIT +license_family: MIT +size: 22284 +timestamp: 1735770589188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.52.0-h04a0ce9_0.conda +sha256: c9af81e7830d9c4b67a7f48e512d060df2676b29cac59e3b31f09dbfcee29c58 +md5: 7d9d7efe9541d4bb71b5934e8ee348ea +depends: +- __glibc >=2.17,<3.0.a0 +- icu >=78.2,<79.0a0 +- libgcc >=14 +- libsqlite 3.52.0 hf4e2dac_0 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +- readline >=8.3,<9.0a0 +license: blessing +size: 203641 +timestamp: 1772818888368 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda +sha256: 7e395d67fd249d901beb1ae269057763c0d8c3ee5f7a348694bdb16d158a37d9 +md5: d705f9d8a1185a2b01cced191177a028 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- regex >=2022.1.18 +- requests >=2.26.0 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 939648 +timestamp: 1764028306357 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda +sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac +md5: cffd3bdd58090148f4cfcd831f4b26ab +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +constrains: +- xorg-libx11 >=1.8.12,<2.0a0 +license: TCL +license_family: BSD +size: 3301196 +timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 +md5: e5ce43272193b38c2e9037446c1d9206 +depends: +- python >=3.10 +- __unix +- python +license: MPL-2.0 and MIT +size: 94132 +timestamp: 1770153424136 +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +sha256: 39d8ae33c43cdb8f771373e149b0b4fae5a08960ac58dcca95b2f1642bb17448 +md5: 260af1b0a94f719de76b4e14094e9a3b +depends: +- importlib-metadata >=3.6 +- python >=3.10 +- typing-extensions >=4.10.0 +- typing_extensions >=4.14.0 +constrains: +- pytest >=7 +license: MIT +license_family: MIT +size: 36838 +timestamp: 1771532971545 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c +md5: edd329d7d3a4ab45dcf905899a7a6115 +depends: +- typing_extensions ==4.15.0 pyhcf101f3_0 +license: PSF-2.0 +license_family: PSF +size: 91383 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +sha256: 70db27de58a97aeb7ba7448366c9853f91b21137492e0b4430251a1870aa8ff4 +md5: a0a4a3035667fc34f29bfbd5c190baa6 +depends: +- python >=3.10 +- typing_extensions >=4.12.0 +license: MIT +license_family: MIT +size: 18923 +timestamp: 1764158430324 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 +md5: 0caa1af407ecff61170c9437a808404d +depends: +- python >=3.10 +- python +license: PSF-2.0 +license_family: PSF +size: 51692 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c +md5: ad659d0a2b3e47e38d829aa8cad2d610 +license: LicenseRef-Public-Domain +size: 119135 +timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a +md5: 9272daa869e03efe68833e3dc7a02130 +depends: +- backports.zstd >=1.0.0 +- brotli-python >=1.2.0 +- h2 >=4,<5 +- pysocks >=1.5.6,<2.0,!=1.5.7 +- python >=3.10 +license: MIT +license_family: MIT +size: 103172 +timestamp: 1767817860341 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b +md5: b2895afaf55bf96a8c8282a2e47a5de0 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 15321 +timestamp: 1762976464266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 +md5: 1dafce8548e38671bea82e3f5c6ce22f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 20591 +timestamp: 1762976546182 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda +sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad +md5: a77f85f77be52ff59391544bfe73390a +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +license: MIT +license_family: MIT +size: 85189 +timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae +md5: 30cd29cb87d819caead4d55184c1d115 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 24194 +timestamp: 1764460141901 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda +sha256: ea4e50c465d70236408cb0bfe0115609fd14db1adcd8bd30d8918e0291f8a75f +md5: 2aadb0d17215603a82a2a6b0afd9a4cb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Zlib +license_family: Other +size: 122618 +timestamp: 1770167931827 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 +md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 +depends: +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 601375 +timestamp: 1764777111296 diff --git a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt new file mode 100644 index 0000000..a55a4d4 --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt @@ -0,0 +1,126 @@ + +# This file may be used to create an environment using: +# $ conda create --name --file +# platform: linux-64 +@EXPLICIT +https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda#239c5e9546c38a1e884d69effcf4c882 +https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda#a9f577daf3de00bca7c3c76c0ecbd1de +https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda#0aa00f03f9e39fb9876085dee11a85d4 +https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda#d2ffd7602c02f2b316fd921d39876885 +https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda#d87ff7921124eccd67248aa483c23fec +https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda#4a13eeac0b5c8e5b8ab496e6c4ddd829 +https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda#18335a698559cdbcd86150a48bf54ba6 +https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.5-hecca717_0.conda#49f570f3bc4c874a06ea69b7225753af +https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda#a360c33a5abe61c07959e449fa1453eb +https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda#b88d90cad08e6bc8ad540cb310a761fb +https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda#2c21e66f50753a083cbe6b80f38268fa +https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda#1b08cd684f34175e4514474793d44bcb +https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda#c80d8a3b84358cb967fa81e7075fbc8a +https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.0-hf4e2dac_0.conda#810d83373448da85c3f673fbcb7ad3a3 +https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42-h5347b49_0.conda#38ffe67b78c9d4de527be8315e5ada2c +https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda#47e340acb35de30501a76c7c799c41d7 +https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda#e18ad67cf881dcadee8b8d9e2f8e5f73 +https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda#da1b85b6a87e141f5140bb9924cecab0 +https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda#0539938c55b6b1a59b560e843ad864a4 +https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda#d7d95fc8287ea7bf33e0e7116d2b95ec +https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda#cffd3bdd58090148f4cfcd831f4b26ab +https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda#ad659d0a2b3e47e38d829aa8cad2d610 +https://conda.anaconda.org/conda-forge/linux-64/python-3.14.4-habeac84_100_cp314.conda#a443f87920815d41bfe611296e507995 +https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda#f111d4cfaf1fe9496f386bc98ae94452 +https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda#e4e60721757979d01d3964122f674959 +https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda#aaa2a381ccc56eac91d63b6c1240312f +https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda#0caa1af407ecff61170c9437a808404d +https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda#edd329d7d3a4ab45dcf905899a7a6115 +https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda#2934f256a8acfe48f6ebb4fce6cde29c +https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda#c6b0543676ecb1fb2d7643941fe375f2 +https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda#a2ac7763a9ac75055b68f325d3255265 +https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda#8910d2c46f7e7b519129f486e0fe927a +https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda#929471569c93acefb30282a22060dcd5 +https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda#a9167b9571f3baa9d448faa2139d1089 +https://conda.anaconda.org/conda-forge/noarch/click-8.3.2-pyhc90fa1f_0.conda#4d18bc3af7cfcea97bd817164672a08c +https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda#7fe569c10905402ed47024fc481bb371 +https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda#b866ff7007b934d564961066c8195983 +https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda#a2c1eeadae7a309daed9d62c96012a2b +https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_18.conda#646855f357199a12f02a87382d429b75 +https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_18.conda#9063115da5bc35fdc3e1002e69b9ef6e +https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.32-pthreads_h94d23a6_0.conda#89d61bc91d3f39fda0ca10fcd3c68594 +https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-6_h4a7cf45_openblas.conda#6d6d225559bfa6e2f3c90ee9c03d4e2e +https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-6_h0358290_openblas.conda#36ae340a916635b97ac8a0655ace2a35 +https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-6_h47877c9_openblas.conda#881d801569b201c2e753f03c84b85e15 +https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.3-py314h2b28147_0.conda#36f5b7eb328bdc204954a2225cf908e2 +https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda#071cf7b0ce333c81718b054066c15102 +https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.5-hecca717_0.conda#7de50d165039df32d38be74c1b34a910 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2#0c96522c6bdaed4b1566d11387caaf45 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2#34893075a5c9e55cdafac56607368fc6 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2#4d59c254e01d9cde7957100457e2d5fb +https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda#49023d73832ef61042f6a237cb2687e7 +https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda#eba48a68a1a2b9d3c0d9511548db85db +https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda#fb16b4b69e3f1dcfe79d80db8fd0c55d +https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda#e289f3d17880e44b633ba911d57a321b +https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda#867127763fbe935bab59815b6e0b7b5c +https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda#a7970cd949a077b7cb9696379d338681 +https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda#0a802cb9888dd14eeefc611f05c40b6e +https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda#8e6923fc12f1fe8f8c4e5c9f343256ac +https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda#164fc43f0b53b6e3a7bc7dce5e4f1dc9 +https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda#daddf757c3ecd6067b9af1df1f25d89e +https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda#fb7130c190f9b4ec91219840a05ba3ac +https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda#e1c36c6121a7c9c76f2f148f1e83b983 +https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda#080594bf4493e6bae2607e65390c520a +https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda#9a17c4307d23318476d7fbf0fedc0cde +https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda#04558c96691bed63104678757beb4f8d +https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda#c1c368b5437b0d1a68f372ccf01cb133 +https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda#870293df500ca7e18bedefa5838a22ab +https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda#439cd0f567d697b20a8f45cb70a1005a +https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda#ada41c863af263cc4c5fcbaff7c3e4dc +https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda#d5e96b1ed75ca01906b3d2469b4ce493 +https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2#86e69bd82c2a2c6fd29f5ab7e02b3691 +https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda#e235d5566c9cc8970eb2798dd4ecf62f +https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda#567fbeed956c200c1db5782a424e58ee +https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.0-h04a0ce9_0.conda#dc540e5bd5616d83a1ec46af8315ff98 +https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2#b3723b235b0758abaae8c82ce4d80146 +https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda#6178c6f2fb254558238ef4e6c56fb782 +https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda#a752488c68f2e7c456bcbd8f16eec275 +https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda#6c77a605a7a689d17d4819c0f8ac9a00 +https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda#aea31d2e5b1091feca96fcfe945c3cf9 +https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda#cd5a90476766d53e901500df9215e927 +https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda#6f2e2c8f58160147c4d1c6f4c14cbac4 +https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda#b3c17d95b5a10c6e64a21fa17573e70e +https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda#b2895afaf55bf96a8c8282a2e47a5de0 +https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda#1dafce8548e38671bea82e3f5c6ce22f +https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda#92ed62436b625154323d40d5f2f11dd7 +https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda#ba0a9221ce1063f31692c07370d062f3 +https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda#592132998493b3ff25fd7479396e8351 +https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda#5b5203189eb668f042ac2b0826244964 +https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda#e941e85e273121222580723010bd4fa2 +https://conda.anaconda.org/conda-forge/noarch/packaging-26.1-pyhc364b38_0.conda#b8ae38639d323d808da535fb71e31be8 +https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda#11b3379b191f63139e29c0d19dee24cd +https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda#2aadb0d17215603a82a2a6b0afd9a4cb +https://conda.anaconda.org/conda-forge/linux-64/pillow-12.2.0-py314h8ec4b1a_0.conda#76c4757c0ec9d11f969e8eb44899307b +https://conda.anaconda.org/conda-forge/noarch/narwhals-2.20.0-pyhcf101f3_0.conda#6cac1a50359219d786453c6fef819f98 +https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda#3e9427ee186846052e81fadde8ebe96a +https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.40.0-py310hffdcd12_0.conda#8eacf9ff4d4e1ca1b52f8f3ba3e0c993 +https://conda.anaconda.org/conda-forge/noarch/polars-1.40.0-pyh58ad624_0.conda#fd16be490f5403adfbf27dd4901bbe34 +https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.40.0-py310hbcd5346_0.conda#03a6899e17bb731c8e21b08212f1a64c +https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda#ef0340e75068ac8ff96462749b5c98e7 +https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda#a77f85f77be52ff59391544bfe73390a +https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda#2035f68f96be30dc60a5dfd7452c7941 +https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda#e17be1016bcc3516827b836cd3e4d9dc +https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.3-py314h2e6c369_0.conda#1f3fd537f929b8d3236f9f0f0e7f7a32 +https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda#a0a4a3035667fc34f29bfbd5c190baa6 +https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.3-pyhcf101f3_0.conda#f690e6f204efd2e5c06b57518a383d98 +https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda#130584ad9f3a513cdd71b1fdc1244e9c +https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2#310259a5b03ff02289d7705f39e2b1d2 +https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda#461219d1a5bd61342293efa2c0c90eac +https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda#9272daa869e03efe68833e3dc7a02130 +https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda#10afbb4dbf06ff959ad25a92ccee6e59 +https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda#16c18772b340887160c79a6acc022db0 +https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda#0242025a3c804966bf71aa04eee82f66 +https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda#0c20a8ebcddb24a45da89d5e917e6cb9 +https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda#472239e4eb7b5a84bb96b3ed7e3a596a +https://conda.anaconda.org/conda-forge/linux-64/regex-2026.4.4-py314h5bd0f2a_0.conda#4ffb42385183c854564f1f9adcf80a63 +https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda#d705f9d8a1185a2b01cced191177a028 +https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda#e5ce43272193b38c2e9037446c1d9206 +https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda#260af1b0a94f719de76b4e14094e9a3b +https://conda.anaconda.org/bioconda/noarch/multiqc-1.34-pyhdfd78af_0.conda#a7111ab9a6a6146b40cbce16655ac873 +https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh145f28c_0.conda#09a970fbf75e8ed1aa633827ded6aa4f +https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda#f2c23a77b25efcad57d377b34bd84941 diff --git a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt new file mode 100644 index 0000000..a58231a --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt @@ -0,0 +1,1502 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-aarch64: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.7.4-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py314haac167e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.1.1-py314hac3e5ec_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.39.3-py310hff09b76_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.39.3-py310hf00a4a2_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.41.5-py314h451b6cc_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.2.28-py314h51f160d_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.52.0-hf1c7be2_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 +md5: 468fd3bb9e1f671d36c2cbc677e56f1d +depends: +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28926 +timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 +md5: aaa2a381ccc56eac91d63b6c1240312f +depends: +- cpython +- python-gil +license: MIT +license_family: MIT +size: 8191 +timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 +md5: 2934f256a8acfe48f6ebb4fce6cde29c +depends: +- python >=3.9 +- typing-extensions >=4.0.0 +license: MIT +license_family: MIT +size: 18074 +timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab +md5: c6b0543676ecb1fb2d7643941fe375f2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 64927 +timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda +noarch: generic +sha256: c31ab719d256bc6f89926131e88ecd0f0c5d003fe8481852c6424f4ec6c7eb29 +md5: a2ac7763a9ac75055b68f325d3255265 +depends: +- python >=3.14 +license: BSD-3-Clause AND MIT AND EPL-2.0 +size: 7514 +timestamp: 1767044983590 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda +sha256: 5a5b0cdcd7ed89c6a8fb830924967f6314a2b71944bc1ebc2c105781ba97aa75 +md5: a1b5c571a0923a205d663d8678df4792 +depends: +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +constrains: +- libbrotlicommon 1.2.0 he30d5cf_1 +license: MIT +license_family: MIT +size: 373193 +timestamp: 1764017486851 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c +md5: 840d8fc0d7b3209be93080bc20e07f2d +depends: +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 192412 +timestamp: 1771350241232 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda +sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc +md5: 4492fd26db29495f0ba23f146cd5638d +depends: +- __unix +license: ISC +size: 147413 +timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda +sha256: a6b118fd1ed6099dc4fc03f9c492b88882a780fadaef4ed4f93dc70757713656 +md5: 765c4d97e877cdbbb88ff33152b86125 +depends: +- python >=3.10 +license: ISC +size: 151445 +timestamp: 1772001170301 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.6-pyhd8ed1ab_0.conda +sha256: d86dfd428b2e3c364fa90e07437c8405d635aa4ef54b25ab51d9c712be4112a5 +md5: 49ee13eb9b8f44d63879c69b8a40a74b +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 58510 +timestamp: 1773660086450 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda +sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715 +md5: ea8a6c3256897cc31263de9f455e25d9 +depends: +- python >=3.10 +- __unix +- python +license: BSD-3-Clause +license_family: BSD +size: 97676 +timestamp: 1764518652276 +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 +md5: b866ff7007b934d564961066c8195983 +depends: +- humanfriendly >=9.1 +- python >=3.9 +license: MIT +license_family: MIT +size: 43758 +timestamp: 1733928076798 +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +sha256: 59c9e29800b483b390467f90e82b0da3a4fbf0612efe1c90813fca232780e160 +md5: 071cf7b0ce333c81718b054066c15102 +depends: +- networkx >=2.0 +- numpy +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 39326 +timestamp: 1735759976140 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.3-py314hd8ed1ab_101.conda +noarch: generic +sha256: 91b06300879df746214f7363d6c27c2489c80732e46a369eb2afc234bcafb44c +md5: 3bb89e4f795e5414addaa531d6b1500a +depends: +- python >=3.14,<3.15.0a0 +- python_abi * *_cp314 +license: Python-2.0 +size: 50078 +timestamp: 1770674447292 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.7.4-hfae3067_0.conda +sha256: 5f087bef054c681edcaae84a8c2230585b938691e371ff92957a30707b7fcdf7 +md5: b304307db639831ad7caabd2eac6fca6 +depends: +- libexpat 2.7.4 hfae3067_0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 137701 +timestamp: 1771259543650 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda +sha256: 835aff8615dd8d8fff377679710ce81b8a2c47b6404e21a92fb349fda193a15c +md5: 0fed1ff55f4938a65907f3ecf62609db +depends: +- libexpat >=2.7.4,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 279044 +timestamp: 1771382728182 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 +md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 +depends: +- python >=3.10 +- hyperframe >=6.1,<7 +- hpack >=4.1,<5 +- python +license: MIT +license_family: MIT +size: 95967 +timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba +md5: 0a802cb9888dd14eeefc611f05c40b6e +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 30731 +timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d +md5: 7fe569c10905402ed47024fc481bb371 +depends: +- __unix +- python >=3.9 +license: MIT +license_family: MIT +size: 73563 +timestamp: 1733928021866 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +sha256: 6c4343b376d0b12a4c75ab992640970d36c933cad1fd924f6a1181fa91710e80 +md5: daddf757c3ecd6067b9af1df1f25d89e +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 67994 +timestamp: 1766267728652 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 +md5: 8e6923fc12f1fe8f8c4e5c9f343256ac +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 17397 +timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda +sha256: 49ba6aed2c6b482bb0ba41078057555d29764299bc947b990708617712ef6406 +md5: 546da38c2fa9efacf203e2ad3f987c59 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: MIT +license_family: MIT +size: 12837286 +timestamp: 1773822650615 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda +sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 +md5: 53abe63df7e10a6ba605dc5f9f961d36 +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 50721 +timestamp: 1760286526795 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda +sha256: 82ab2a0d91ca1e7e63ab6a4939356667ef683905dea631bc2121aa534d347b16 +md5: 080594bf4493e6bae2607e65390c520a +depends: +- python >=3.10 +- zipp >=3.20 +- python +license: Apache-2.0 +license_family: APACHE +size: 34387 +timestamp: 1773931568510 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b +md5: 04558c96691bed63104678757beb4f8d +depends: +- markupsafe >=2.0 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 120685 +timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 +md5: ada41c863af263cc4c5fcbaff7c3e4dc +depends: +- attrs >=22.2.0 +- jsonschema-specifications >=2023.3.6 +- python >=3.10 +- referencing >=0.28.4 +- rpds-py >=0.25.0 +- python +license: MIT +license_family: MIT +size: 82356 +timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 +md5: 439cd0f567d697b20a8f45cb70a1005a +depends: +- python >=3.10 +- referencing >=0.31.0 +- python +license: MIT +license_family: MIT +size: 19236 +timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2 +sha256: d3c7f4797566e6f983d16c2a87063a18e4b2d819a66230190a21584d70042755 +md5: 4f0d284f5d11e04277b552eb1c172c7f +depends: +- __glibc >=2.17,<3.0.a0 +- expat >=2.2.10,<3.0.0a0 +- fontconfig +- fonts-conda-forge +- libgcc-ng >=9.3.0 +- mathjax 2.7.* +- nspr >=4.29,<5.0a0 +- nss >=3.62,<4.0a0 +- sqlite >=3.34.0,<4.0a0 +license: MIT +license_family: MIT +size: 65750397 +timestamp: 1615199465742 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda +sha256: 379ef5e91a587137391a6149755d0e929f1a007d2dcb211318ac670a46c8596f +md5: bb960f01525b5e001608afef9d47b79c +depends: +- libgcc >=14 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 293039 +timestamp: 1768184778398 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda +sha256: 7abd913d81a9bf00abb699e8987966baa2065f5132e37e815f92d90fc6bba530 +md5: a21644fc4a83da26452a718dc9468d5f +depends: +- zstd >=1.5.7,<1.6.0a0 +constrains: +- binutils_impl_linux-aarch64 2.45.1 +license: GPL-3.0-only +license_family: GPL +size: 875596 +timestamp: 1774197520746 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +sha256: 8957fd460c1c132c8031f65fd5f56ec3807fd71b7cab2c5e2b0937b13404ab36 +md5: d13423b06447113a90b5b1366d4da171 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 240444 +timestamp: 1773114901155 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-5_haddc8a3_openblas.conda +build_number: 5 +sha256: 700f3c03d0fba8e687a345404a45fbabe781c1cf92242382f62cef2948745ec4 +md5: 5afcea37a46f76ec1322943b3c4dfdc0 +depends: +- libopenblas >=0.3.30,<0.3.31.0a0 +- libopenblas >=0.3.30,<1.0a0 +constrains: +- mkl <2026 +- libcblas 3.11.0 5*_openblas +- liblapack 3.11.0 5*_openblas +- liblapacke 3.11.0 5*_openblas +- blas 2.305 openblas +license: BSD-3-Clause +license_family: BSD +size: 18369 +timestamp: 1765818610617 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-5_hd72aa62_openblas.conda +build_number: 5 +sha256: 3fad5c9de161dccb4e42c8b1ae8eccb33f4ed56bccbcced9cbb0956ae7869e61 +md5: 0b2f1143ae2d0aa4c991959d0daaf256 +depends: +- libblas 3.11.0 5_haddc8a3_openblas +constrains: +- liblapack 3.11.0 5*_openblas +- liblapacke 3.11.0 5*_openblas +- blas 2.305 openblas +license: BSD-3-Clause +license_family: BSD +size: 18371 +timestamp: 1765818618899 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 +md5: a9138815598fe6b91a1d6782ca657b0c +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 71117 +timestamp: 1761979776756 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda +sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 +md5: 57f3b3da02a50a1be2a6fe847515417d +depends: +- libgcc >=14 +constrains: +- expat 2.7.4.* +license: MIT +license_family: MIT +size: 76564 +timestamp: 1771259530958 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 +md5: 2f364feefb6a7c00423e80dcb12db62a +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 55952 +timestamp: 1769456078358 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a +md5: a229e22d4d8814a07702b0919d8e6701 +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8125 +timestamp: 1774301094057 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c +md5: b99ed99e42dafb27889483b3098cace7 +depends: +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 422941 +timestamp: 1774301093473 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda +sha256: 43df385bedc1cab11993c4369e1f3b04b4ca5d0ea16cba6a0e7f18dbc129fcc9 +md5: 552567ea2b61e3a3035759b2fdb3f9a6 +depends: +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_18 +- libgomp 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 622900 +timestamp: 1771378128706 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda +sha256: 83bb0415f59634dccfa8335d4163d1f6db00a27b36666736f9842b650b92cf2f +md5: 4feebd0fbf61075a1a9c2e9b3936c257 +depends: +- libgcc 15.2.0 h8acb6b2_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27568 +timestamp: 1771378136019 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda +sha256: 7dcd7dff2505d56fd5272a6e712ec912f50a46bf07dc6873a7e853694304e6e4 +md5: 41f261f5e4e2e8cbd236c2f1f15dae1b +depends: +- libgfortran5 15.2.0 h1b7bec0_18 +constrains: +- libgfortran-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27587 +timestamp: 1771378169244 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda +sha256: 85347670dfb4a8d4c13cd7cae54138dcf2b1606b6bede42eef5507bf5f9660c6 +md5: 574d88ce3348331e962cfa5ed451b247 +depends: +- libgcc >=15.2.0 +constrains: +- libgfortran 15.2.0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1486341 +timestamp: 1771378148102 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda +sha256: fc716f11a6a8525e27a5d332ef6a689210b0d2a4dd1133edc0f530659aa9faa6 +md5: 4faa39bf919939602e594253bd673958 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 588060 +timestamp: 1771378040807 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda +sha256: 84064c7c53a64291a585d7215fe95ec42df74203a5bf7615d33d49a3b0f08bb6 +md5: 5109d7f837a3dfdf5c60f60e311b041f +depends: +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 691818 +timestamp: 1762094728337 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-5_h88aeb00_openblas.conda +build_number: 5 +sha256: 692222d186d3ffbc99eaf04b5b20181fd26aee1edec1106435a0a755c57cce86 +md5: 88d1e4133d1182522b403e9ba7435f04 +depends: +- libblas 3.11.0 5_haddc8a3_openblas +constrains: +- liblapacke 3.11.0 5*_openblas +- blas 2.305 openblas +- libcblas 3.11.0 5*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18392 +timestamp: 1765818627104 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda +sha256: 843c46e20519651a3e357a8928352b16c5b94f4cd3d5481acc48be2e93e8f6a3 +md5: 96944e3c92386a12755b94619bae0b35 +depends: +- libgcc >=14 +constrains: +- xz 5.8.2.* +license: 0BSD +size: 125916 +timestamp: 1768754941722 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda +sha256: 57c0dd12d506e84541c4e877898bd2a59cca141df493d34036f18b2751e0a453 +md5: 7b9813e885482e3ccb1fa212b86d7fd0 +depends: +- libgcc >=14 +license: BSD-2-Clause +license_family: BSD +size: 114056 +timestamp: 1769482343003 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.30-pthreads_h9d3fd7e_4.conda +sha256: 794a7270ea049ec931537874cd8d2de0ef4b3cef71c055cfd8b4be6d2f4228b0 +md5: 11d7d57b7bdd01da745bbf2b67020b2e +depends: +- libgcc >=14 +- libgfortran +- libgfortran5 >=14.3.0 +constrains: +- openblas >=0.3.30,<0.3.31.0a0 +license: BSD-3-Clause +license_family: BSD +size: 4959359 +timestamp: 1763114173544 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda +sha256: c7378c6b79de4d571d00ad1caf0a4c19d43c9c94077a761abb6ead44d891f907 +md5: be4088903b94ea297975689b3c3aeb27 +depends: +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: zlib-acknowledgement +size: 340156 +timestamp: 1770691477245 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.52.0-h10b116e_0.conda +sha256: 1ddaf91b44fae83856276f4cb7ce544ffe41d4b55c1e346b504c6b45f19098d6 +md5: 77891484f18eca74b8ad83694da9815e +depends: +- icu >=78.2,<79.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: blessing +size: 952296 +timestamp: 1772818881550 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda +sha256: 31fdb9ffafad106a213192d8319b9f810e05abca9c5436b60e507afb35a6bc40 +md5: f56573d05e3b735cb03efeb64a15f388 +depends: +- libgcc 15.2.0 h8acb6b2_18 +constrains: +- libstdcxx-ng ==15.2.0=*_18 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5541411 +timestamp: 1771378162499 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 +md5: 8c6fd84f9c87ac00636007c6131e457d +depends: +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 488407 +timestamp: 1762022048105 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda +sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 +md5: cf2861212053d05f27ec49c3784ff8bb +depends: +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 43453 +timestamp: 1766271546875 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 +md5: 24e92d0942c799db387f5c9d7b81f1af +depends: +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 359496 +timestamp: 1752160685488 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b +md5: cd14ee5cca2464a425b1dbfc24d90db2 +depends: +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 397493 +timestamp: 1727280745441 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f +md5: 502006882cf5461adced436e410046d1 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 69833 +timestamp: 1774072605429 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +sha256: 20e0892592a3e7c683e3d66df704a9425d731486a97c34fc56af4da1106b2b6b +md5: ba0a9221ce1063f31692c07370d062f3 +depends: +- importlib-metadata >=4.4 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 85893 +timestamp: 1770694658918 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda +sha256: 7b1da4b5c40385791dbc3cc85ceea9fad5da680a27d5d3cb8bfaa185e304a89e +md5: 5b5203189eb668f042ac2b0826244964 +depends: +- mdurl >=0.1,<1 +- python >=3.10 +license: MIT +license_family: MIT +size: 64736 +timestamp: 1754951288511 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda +sha256: 383c188496d13a55658c06e61e7d4cdff2c9f9d5a0648769fca8250bece7e0ef +md5: e5de3c36dd548b35ff2a8aa49208dcb3 +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- jinja2 >=3.0.0 +license: BSD-3-Clause +license_family: BSD +size: 27913 +timestamp: 1772446407659 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2 +sha256: 8fd4c79d6eda3d4cba73783114305a53a154ada4d1e334d4e02cb3521429599b +md5: 7b08314a6867a9d5648a1c3265e9eb8e +license: Apache-2.0 +license_family: Apache +size: 22257008 +timestamp: 1662784555011 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 +md5: 592132998493b3ff25fd7479396e8351 +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 14465 +timestamp: 1733255681319 +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.33-pyhdfd78af_0.conda +sha256: f005760b13093362fc9c997d603dd487de32ab2e821a3cbce52a42bcb8136517 +md5: 698a8a27c2b9d8a542c70cb47099a75e +depends: +- click +- coloredlogs +- humanize +- importlib-metadata +- jinja2 >=3.0.0 +- jsonschema +- markdown +- natsort +- numpy +- packaging +- pillow >=10.2.0 +- plotly >=5.18 +- polars-lts-cpu +- pyaml-env +- pydantic >=2.7.1 +- python >=3.8,!=3.14.1 +- python-dotenv +- python-kaleido 0.2.1 +- pyyaml >=4 +- requests +- rich >=10 +- rich-click +- spectra >=0.0.10 +- tiktoken +- tqdm +- typeguard +license: GPL-3.0-or-later +license_family: GPL3 +size: 4198799 +timestamp: 1765300743879 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.18.1-pyhcf101f3_1.conda +sha256: 541fd4390a0687228b8578247f1536a821d9261389a65585af9d1a6f2a14e1e0 +md5: 30bec5e8f4c3969e2b1bd407c5e52afb +depends: +- python >=3.10 +- python +license: MIT +size: 280459 +timestamp: 1774380620329 +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 +md5: e941e85e273121222580723010bd4fa2 +depends: +- python >=3.9 +- python +license: MIT +license_family: MIT +size: 39262 +timestamp: 1770905275632 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda +sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468 +md5: 182afabe009dc78d8b73100255ee6868 +depends: +- libgcc >=13 +license: X11 AND BSD-3-Clause +size: 926034 +timestamp: 1738196018799 +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 +md5: a2c1eeadae7a309daed9d62c96012a2b +depends: +- python >=3.11 +- python +constrains: +- numpy >=1.25 +- scipy >=1.11.2 +- matplotlib-base >=3.8 +- pandas >=2.0 +license: BSD-3-Clause +license_family: BSD +size: 1587439 +timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda +sha256: 78a06e89285fef242e272998b292c1e621e3ee3dd4fba62ec014e503c7ec118f +md5: 6dd4f07147774bf720075a210f8026b9 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: MPL-2.0 +license_family: MOZILLA +size: 235140 +timestamp: 1762350120355 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda +sha256: 48942696889367ffd448f8dccfc080fb7e130b9938a4a3b6b20ef8e6af856463 +md5: 4540f9570d12db2150f42ba036154552 +depends: +- libgcc >=14 +- libsqlite >=3.51.0,<4.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- nspr >=4.38,<5.0a0 +license: MPL-2.0 +license_family: MOZILLA +size: 2061869 +timestamp: 1763490303490 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py314haac167e_0.conda +sha256: a6d42fd88afc57c3b0a57b21a12eff7492dfc419bb61ee3f74e9ba6261dabc88 +md5: 25d896c331481145720a21e5145fad65 +depends: +- python +- libgcc >=14 +- python 3.14.* *_cp314 +- libstdcxx >=14 +- libcblas >=3.9.0,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- python_abi 3.14.* *_cp314 +- libblas >=3.9.0,<4.0a0 +constrains: +- numpy-base <0a0 +license: BSD-3-Clause +license_family: BSD +size: 8008045 +timestamp: 1773839355275 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda +sha256: bd1bc8bdde5e6c5cbac42d462b939694e40b59be6d0698f668515908640c77b8 +md5: cea962410e327262346d48d01f05936c +depends: +- libgcc >=14 +- libpng >=1.6.50,<1.7.0a0 +- libstdcxx >=14 +- libtiff >=4.7.1,<4.8.0a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-2-Clause +license_family: BSD +size: 392636 +timestamp: 1758489353577 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda +sha256: 7f8048c0e75b2620254218d72b4ae7f14136f1981c5eb555ef61645a9344505f +md5: 25f5885f11e8b1f075bccf4a2da91c60 +depends: +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3692030 +timestamp: 1769557678657 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda +sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 +md5: b76541e68fea4d511b1ac46a28dcd2c6 +depends: +- python >=3.8 +- python +license: Apache-2.0 +license_family: APACHE +size: 72010 +timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.1.1-py314hac3e5ec_0.conda +sha256: 1ca2d1616baad9bccb7ebc425ef2dcd6cebe742fbe91edf226fb606ad371ca0f +md5: d3c959c7efe560b2d7da459d69121fe9 +depends: +- python +- python 3.14.* *_cp314 +- libgcc >=14 +- zlib-ng >=2.3.3,<2.4.0a0 +- libwebp-base >=1.6.0,<2.0a0 +- tk >=8.6.13,<8.7.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libtiff >=4.7.1,<4.8.0a0 +- lcms2 >=2.18,<3.0a0 +- python_abi 3.14.* *_cp314 +- openjpeg >=2.5.4,<3.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libxcb >=1.17.0,<2.0a0 +license: HPND +size: 1051828 +timestamp: 1770794010335 +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 +md5: 3e9427ee186846052e81fadde8ebe96a +depends: +- narwhals >=1.15.1 +- packaging +- python >=3.10 +constrains: +- ipywidgets >=7.6 +license: MIT +license_family: MIT +size: 5251872 +timestamp: 1772628857717 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.39.3-pyh58ad624_1.conda +sha256: d332c2d5002fc440ae37ed9679ffc21b552f18d20232390005d1dd3bce0888d3 +md5: d5a4e013a30dd8dfde9ab39f45aaf9c1 +depends: +- polars-runtime-32 ==1.39.3 +- python >=3.10 +- python +constrains: +- numpy >=1.16.0 +- pyarrow >=7.0.0 +- fastexcel >=0.9 +- openpyxl >=3.0.0 +- xlsx2csv >=0.8.0 +- connectorx >=0.3.2 +- deltalake >=1.0.0 +- pyiceberg >=0.7.1 +- altair >=5.4.0 +- great_tables >=0.8.0 +- polars-runtime-32 ==1.39.3 +- polars-runtime-64 ==1.39.3 +- polars-runtime-compat ==1.39.3 +license: MIT +license_family: MIT +size: 533495 +timestamp: 1774207987966 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda +sha256: e466fb31f67ba9bde18deafeb34263ca5eb25807f39ead0e9d753a8e82c4c4f4 +md5: ef0340e75068ac8ff96462749b5c98e7 +depends: +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 +license: MIT +license_family: MIT +size: 3902 +timestamp: 1760206808444 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.39.3-py310hff09b76_1.conda +noarch: python +sha256: c070be507c5a90df397a47ae0299660be437d5546d68f1bc0fa4402c9f07d59e +md5: 3c1a7c6b4ba8b9fb773ace9723f8a5db +depends: +- python +- libgcc >=14 +- libstdcxx >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 34785466 +timestamp: 1774207998285 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.39.3-py310hf00a4a2_1.conda +noarch: python +sha256: 683315f1a49e47ce72bf9462419733b40b588b2b3106552d95fd4cd994e174de +md5: dd3464e2132dc3a783e76e5078870c76 +depends: +- python +- libgcc >=14 +- libstdcxx >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 34652491 +timestamp: 1774207996879 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 +md5: ab7288cc39545556d1bc5e71ab2df9a9 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 636733 +timestamp: 1769712412683 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba +md5: bb5a90c93e3bac3d5690acf76b4a6386 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 8342 +timestamp: 1726803319942 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +sha256: 58994e0d2ea8584cb399546e6f6896d771995e6121d1a7b6a2c9948388358932 +md5: e17be1016bcc3516827b836cd3e4d9dc +depends: +- python >=3.9 +- pyyaml >=5.0,<=7.0 +license: MIT +license_family: MIT +size: 14645 +timestamp: 1736766960536 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.12.5-pyhcf101f3_1.conda +sha256: 868569d9505b7fe246c880c11e2c44924d7613a8cdcc1f6ef85d5375e892f13d +md5: c3946ed24acdb28db1b5d63321dbca7d +depends: +- typing-inspection >=0.4.2 +- typing_extensions >=4.14.1 +- python >=3.10 +- typing-extensions >=4.6.1 +- annotated-types >=0.6.0 +- pydantic-core ==2.41.5 +- python +license: MIT +license_family: MIT +size: 340482 +timestamp: 1764434463101 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.41.5-py314h451b6cc_1.conda +sha256: f8acb2d03ebe80fed0032b9a989fc9acfb6735e3cd3f8c704b72728cb31868f6 +md5: 28f5027a1e04d67aa13fac1c5ba79693 +depends: +- python +- typing-extensions >=4.6.0,!=4.7.0 +- libgcc >=14 +- python 3.14.* *_cp314 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 1828339 +timestamp: 1762989038561 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.19.2-pyhd8ed1ab_0.conda +sha256: 5577623b9f6685ece2697c6eb7511b4c9ac5fb607c9babc2646c811b428fd46a +md5: 6b6ece66ebcae2d5f326c77ef2c5a066 +depends: +- python >=3.9 +license: BSD-2-Clause +license_family: BSD +size: 889287 +timestamp: 1750615908735 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 +md5: 461219d1a5bd61342293efa2c0c90eac +depends: +- __unix +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 21085 +timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.3-hb06a95a_101_cp314.conda +build_number: 101 +sha256: 87e9dff5646aba87cecfbc08789634c855871a7325169299d749040b0923a356 +md5: 205011b36899ff0edf41b3db0eda5a44 +depends: +- bzip2 >=1.0.8,<2.0a0 +- ld_impl_linux-aarch64 >=2.36.1 +- libexpat >=2.7.3,<3.0a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- liblzma >=5.8.2,<6.0a0 +- libmpdec >=4.0.0,<5.0a0 +- libsqlite >=3.51.2,<4.0a0 +- libuuid >=2.41.3,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +- openssl >=3.5.5,<4.0a0 +- python_abi 3.14.* *_cp314 +- readline >=8.3,<9.0a0 +- tk >=8.6.13,<8.7.0a0 +- tzdata +- zstd >=1.5.7,<1.6.0a0 +license: Python-2.0 +size: 37305578 +timestamp: 1770674395875 +python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 +md5: 130584ad9f3a513cdd71b1fdc1244e9c +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 27848 +timestamp: 1772388605021 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda +sha256: 233aebd94c704ac112afefbb29cf4170b7bc606e22958906f2672081bc50638a +md5: 235765e4ea0d0301c75965985163b5a1 +depends: +- cpython 3.14.3.* +- python_abi * *_cp314 +license: Python-2.0 +size: 50062 +timestamp: 1770674497152 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 +md5: 310259a5b03ff02289d7705f39e2b1d2 +depends: +- kaleido-core 0.2.1.* +- python >=3.5 +license: MIT +license_family: MIT +size: 18320 +timestamp: 1615204747600 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +build_number: 8 +sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 +md5: 0539938c55b6b1a59b560e843ad864a4 +constrains: +- python 3.14.* *_cp314 +license: BSD-3-Clause +license_family: BSD +size: 6989 +timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda +sha256: 496b5e65dfdd0aaaaa5de0dcaaf3bceea00fcb4398acf152f89e567c82ec1046 +md5: 9ae2c92975118058bd720e9ba2bb7c58 +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +- yaml >=0.2.5,<0.3.0a0 +license: MIT +license_family: MIT +size: 195678 +timestamp: 1770223441816 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda +sha256: fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216 +md5: 3d49cad61f829f4f0e0611547a9cda12 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-3.0-only +license_family: GPL +size: 357597 +timestamp: 1765815673644 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 +md5: 870293df500ca7e18bedefa5838a22ab +depends: +- attrs >=22.2.0 +- python >=3.10 +- rpds-py >=0.7.0 +- typing_extensions >=4.4.0 +- python +license: MIT +license_family: MIT +size: 51788 +timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.2.28-py314h51f160d_0.conda +sha256: 2080ecea825e1ef91a2422cc0bc63e85db9e38908ed17657fb8f41de7a6eee71 +md5: 818aa2c9f6b3c808da5e7be22a9a424c +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +license: Apache-2.0 AND CNRI-Python +license_family: PSF +size: 408097 +timestamp: 1772255205521 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda +sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5 +md5: c65df89a0b2e321045a9e01d1337b182 +depends: +- python >=3.10 +- certifi >=2017.4.17 +- charset-normalizer >=2,<4 +- idna >=2.5,<4 +- urllib3 >=1.21.1,<3 +- python +constrains: +- chardet >=3.0.2,<6 +license: Apache-2.0 +license_family: APACHE +size: 63602 +timestamp: 1766926974520 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-14.3.3-pyhcf101f3_0.conda +sha256: b06ce84d6a10c266811a7d3adbfa1c11f13393b91cc6f8a5b468277d90be9590 +md5: 7a6289c50631d620652f5045a63eb573 +depends: +- markdown-it-py >=2.2.0 +- pygments >=2.13.0,<3.0.0 +- python >=3.10 +- typing_extensions >=4.0.0,<5.0.0 +- python +license: MIT +license_family: MIT +size: 208472 +timestamp: 1771572730357 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 +md5: 0c20a8ebcddb24a45da89d5e917e6cb9 +depends: +- python >=3.10 +- rich >=12 +- click >=8 +- typing-extensions >=4 +- __unix +- python +license: MIT +license_family: MIT +size: 64356 +timestamp: 1769850479089 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda +sha256: a587240f16eac7c6a80f9585cef679cd1cb9a287b8dfcdd36dcef1f7e7db15dc +md5: e7f6ed9e60043bb5cbcc527764897f0d +depends: +- python +- libgcc >=14 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 376332 +timestamp: 1764543345455 +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +sha256: 7c65782d2511738e62c70462e89d65da4fa54d5a7e47c46667bcd27a59f81876 +md5: 472239e4eb7b5a84bb96b3ed7e3a596a +depends: +- colormath >=3.0.0 +- python >=3.9 +license: MIT +license_family: MIT +size: 22284 +timestamp: 1735770589188 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.52.0-hf1c7be2_0.conda +sha256: 4f8523f5341f0d9e1547085206c6c1f71f9fc7c277443ca363a8cf98add8fc01 +md5: d9634079df93a65ee045b3c75f35cae1 +depends: +- icu >=78.2,<79.0a0 +- libgcc >=14 +- libsqlite 3.52.0 h10b116e_0 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +- readline >=8.3,<9.0a0 +license: blessing +size: 209416 +timestamp: 1772818891689 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda +sha256: c1da41c79262b27efa168407cfecc47b20270e5fc071a8307f95a2c85fb94170 +md5: 55bf7b559202236157b14323b40f19e6 +depends: +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- regex >=2022.1.18 +- requests >=2.26.0 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 914402 +timestamp: 1764030357702 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda +sha256: e25c314b52764219f842b41aea2c98a059f06437392268f09b03561e4f6e5309 +md5: 7fc6affb9b01e567d2ef1d05b84aa6ed +depends: +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +constrains: +- xorg-libx11 >=1.8.12,<2.0a0 +license: TCL +license_family: BSD +size: 3368666 +timestamp: 1769464148928 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 +md5: e5ce43272193b38c2e9037446c1d9206 +depends: +- python >=3.10 +- __unix +- python +license: MPL-2.0 and MIT +size: 94132 +timestamp: 1770153424136 +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda +sha256: 39d8ae33c43cdb8f771373e149b0b4fae5a08960ac58dcca95b2f1642bb17448 +md5: 260af1b0a94f719de76b4e14094e9a3b +depends: +- importlib-metadata >=3.6 +- python >=3.10 +- typing-extensions >=4.10.0 +- typing_extensions >=4.14.0 +constrains: +- pytest >=7 +license: MIT +license_family: MIT +size: 36838 +timestamp: 1771532971545 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c +md5: edd329d7d3a4ab45dcf905899a7a6115 +depends: +- typing_extensions ==4.15.0 pyhcf101f3_0 +license: PSF-2.0 +license_family: PSF +size: 91383 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda +sha256: 70db27de58a97aeb7ba7448366c9853f91b21137492e0b4430251a1870aa8ff4 +md5: a0a4a3035667fc34f29bfbd5c190baa6 +depends: +- python >=3.10 +- typing_extensions >=4.12.0 +license: MIT +license_family: MIT +size: 18923 +timestamp: 1764158430324 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 +md5: 0caa1af407ecff61170c9437a808404d +depends: +- python >=3.10 +- python +license: PSF-2.0 +license_family: PSF +size: 51692 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c +md5: ad659d0a2b3e47e38d829aa8cad2d610 +license: LicenseRef-Public-Domain +size: 119135 +timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda +sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a +md5: 9272daa869e03efe68833e3dc7a02130 +depends: +- backports.zstd >=1.0.0 +- brotli-python >=1.2.0 +- h2 >=4,<5 +- pysocks >=1.5.6,<2.0,!=1.5.7 +- python >=3.10 +license: MIT +license_family: MIT +size: 103172 +timestamp: 1767817860341 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 +md5: 1c246e1105000c3660558459e2fd6d43 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 16317 +timestamp: 1762977521691 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1 +md5: bff06dcde4a707339d66d45d96ceb2e2 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 21039 +timestamp: 1762979038025 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda +sha256: 66265e943f32ce02396ad214e27cb35f5b0490b3bd4f064446390f9d67fa5d88 +md5: 032d8030e4a24fe1f72c74423a46fb88 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 88088 +timestamp: 1753484092643 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda +sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae +md5: 30cd29cb87d819caead4d55184c1d115 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 24194 +timestamp: 1764460141901 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda +sha256: 638a3a41a4fbfed52d3c60c8ef5a3693b3f12a5b1a3f58fa29f5698d0a0702e2 +md5: f731af71c723065d91b4c01bb822641b +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Zlib +license_family: Other +size: 121046 +timestamp: 1770167944449 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 +md5: c3655f82dcea2aa179b291e7099c1fcc +depends: +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 614429 +timestamp: 1764777145593 diff --git a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt new file mode 100644 index 0000000..f787dbe --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt @@ -0,0 +1,125 @@ + +# This file may be used to create an environment using: +# $ conda create --name --file +# platform: linux-aarch64 +@EXPLICIT +https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda#4faa39bf919939602e594253bd673958 +https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda#468fd3bb9e1f671d36c2cbc677e56f1d +https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda#552567ea2b61e3a3035759b2fdb3f9a6 +https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda#840d8fc0d7b3209be93080bc20e07f2d +https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda#502006882cf5461adced436e410046d1 +https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda#c3655f82dcea2aa179b291e7099c1fcc +https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda#a21644fc4a83da26452a718dc9468d5f +https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.5-hfae3067_0.conda#05d1e0b30acd816a192c03dc6e164f4d +https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda#2f364feefb6a7c00423e80dcb12db62a +https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda#76298a9e6d71ee6e832a8d0d7373b261 +https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda#7b9813e885482e3ccb1fa212b86d7fd0 +https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.0-h022381a_0.conda#86db4036fd08bf34e991bf48a8af405d +https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42-h1022ec0_0.conda#a0b5de740d01c390bdbb46d7503c9fab +https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda#182afabe009dc78d8b73100255ee6868 +https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.4.22-hbd8a1cb_0.conda#e18ad67cf881dcadee8b8d9e2f8e5f73 +https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda#3b129669089e4d6a5c6871dbb4669b99 +https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda#0539938c55b6b1a59b560e843ad864a4 +https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda#3d49cad61f829f4f0e0611547a9cda12 +https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda#7fc6affb9b01e567d2ef1d05b84aa6ed +https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda#ad659d0a2b3e47e38d829aa8cad2d610 +https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.4-hfd9ac0a_100_cp314.conda#3cfbe780f0f51cc8cba41db9f8a28bfe +https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.4-py314hd8ed1ab_100.conda#f111d4cfaf1fe9496f386bc98ae94452 +https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.4-h4df99d1_100.conda#e4e60721757979d01d3964122f674959 +https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda#aaa2a381ccc56eac91d63b6c1240312f +https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda#0caa1af407ecff61170c9437a808404d +https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda#edd329d7d3a4ab45dcf905899a7a6115 +https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda#2934f256a8acfe48f6ebb4fce6cde29c +https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda#c6b0543676ecb1fb2d7643941fe375f2 +https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.3.0-py314h680f03e_0.conda#a2ac7763a9ac75055b68f325d3255265 +https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda#f56573d05e3b735cb03efeb64a15f388 +https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda#a1b5c571a0923a205d663d8678df4792 +https://conda.anaconda.org/conda-forge/noarch/certifi-2026.4.22-pyhd8ed1ab_0.conda#929471569c93acefb30282a22060dcd5 +https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda#a9167b9571f3baa9d448faa2139d1089 +https://conda.anaconda.org/conda-forge/noarch/click-8.3.2-pyhc90fa1f_0.conda#4d18bc3af7cfcea97bd817164672a08c +https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda#7fe569c10905402ed47024fc481bb371 +https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda#b866ff7007b934d564961066c8195983 +https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda#a2c1eeadae7a309daed9d62c96012a2b +https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_18.conda#574d88ce3348331e962cfa5ed451b247 +https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_18.conda#41f261f5e4e2e8cbd236c2f1f15dae1b +https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.32-pthreads_h9d3fd7e_0.conda#5d2ce5cf40443d055ec6d33840192265 +https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-6_haddc8a3_openblas.conda#652bb20bb4618cacd11e17ae070f47ce +https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-6_hd72aa62_openblas.conda#939e300b110db241a96a1bed438c315b +https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-6_h88aeb00_openblas.conda#e23a27b52fb320687239e2c5ae4d7540 +https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.3-py314haac167e_0.conda#25d896c331481145720a21e5145fad65 +https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda#071cf7b0ce333c81718b054066c15102 +https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.7.5-hfae3067_0.conda#d2bb0c889d94f2fdc5856392c3002976 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2#0c96522c6bdaed4b1566d11387caaf45 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2#34893075a5c9e55cdafac56607368fc6 +https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2#4d59c254e01d9cde7957100457e2d5fb +https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda#49023d73832ef61042f6a237cb2687e7 +https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda#f51503ac45a4888bce71af9027a2ecc9 +https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda#b99ed99e42dafb27889483b3098cace7 +https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda#a229e22d4d8814a07702b0919d8e6701 +https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda#0fed1ff55f4938a65907f3ecf62609db +https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda#a7970cd949a077b7cb9696379d338681 +https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda#0a802cb9888dd14eeefc611f05c40b6e +https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda#8e6923fc12f1fe8f8c4e5c9f343256ac +https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda#164fc43f0b53b6e3a7bc7dce5e4f1dc9 +https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda#daddf757c3ecd6067b9af1df1f25d89e +https://conda.anaconda.org/conda-forge/noarch/idna-3.13-pyhcf101f3_0.conda#fb7130c190f9b4ec91219840a05ba3ac +https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.1-pyhcf101f3_0.conda#e1c36c6121a7c9c76f2f148f1e83b983 +https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.8.0-pyhcf101f3_0.conda#080594bf4493e6bae2607e65390c520a +https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda#e5de3c36dd548b35ff2a8aa49208dcb3 +https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda#04558c96691bed63104678757beb4f8d +https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda#e7f6ed9e60043bb5cbcc527764897f0d +https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda#870293df500ca7e18bedefa5838a22ab +https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda#439cd0f567d697b20a8f45cb70a1005a +https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda#ada41c863af263cc4c5fcbaff7c3e4dc +https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda#4feebd0fbf61075a1a9c2e9b3936c257 +https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2#7b08314a6867a9d5648a1c3265e9eb8e +https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda#6dd4f07147774bf720075a210f8026b9 +https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda#4540f9570d12db2150f42ba036154552 +https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.0-he8854b5_0.conda#ad8164bdeece883b825c50639c0c4725 +https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2#4f0d284f5d11e04277b552eb1c172c7f +https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda#a85ba48648f6868016f2741fd9170250 +https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda#d13423b06447113a90b5b1366d4da171 +https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda#a9138815598fe6b91a1d6782ca657b0c +https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda#24e92d0942c799db387f5c9d7b81f1af +https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda#8c6fd84f9c87ac00636007c6131e457d +https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda#bb960f01525b5e001608afef9d47b79c +https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda#bb5a90c93e3bac3d5690acf76b4a6386 +https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda#1c246e1105000c3660558459e2fd6d43 +https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda#bff06dcde4a707339d66d45d96ceb2e2 +https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda#cd14ee5cca2464a425b1dbfc24d90db2 +https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda#ba0a9221ce1063f31692c07370d062f3 +https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda#592132998493b3ff25fd7479396e8351 +https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda#5b5203189eb668f042ac2b0826244964 +https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda#e941e85e273121222580723010bd4fa2 +https://conda.anaconda.org/conda-forge/noarch/packaging-26.1-pyhc364b38_0.conda#b8ae38639d323d808da535fb71e31be8 +https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda#cea962410e327262346d48d01f05936c +https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda#f731af71c723065d91b4c01bb822641b +https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.2.0-py314hac3e5ec_0.conda#87d58d103b47c4a8567b3d7666647684 +https://conda.anaconda.org/conda-forge/noarch/narwhals-2.20.0-pyhcf101f3_0.conda#6cac1a50359219d786453c6fef819f98 +https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda#3e9427ee186846052e81fadde8ebe96a +https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.40.0-py310hff09b76_0.conda#d5628a33ce7652511e38fc98643dc910 +https://conda.anaconda.org/conda-forge/noarch/polars-1.40.0-pyh58ad624_0.conda#fd16be490f5403adfbf27dd4901bbe34 +https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.40.0-py310hf00a4a2_0.conda#a82af0fcbb72db253dc89a7a45279372 +https://conda.anaconda.org/conda-forge/noarch/polars-lts-cpu-1.34.0.deprecated-hc364b38_0.conda#ef0340e75068ac8ff96462749b5c98e7 +https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda#032d8030e4a24fe1f72c74423a46fb88 +https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda#9ae2c92975118058bd720e9ba2bb7c58 +https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda#e17be1016bcc3516827b836cd3e4d9dc +https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.46.3-py314h451b6cc_0.conda#1a2cb55be9a153ad6203bff6b787c240 +https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhd8ed1ab_1.conda#a0a4a3035667fc34f29bfbd5c190baa6 +https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.3-pyhcf101f3_0.conda#f690e6f204efd2e5c06b57518a383d98 +https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda#130584ad9f3a513cdd71b1fdc1244e9c +https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2#310259a5b03ff02289d7705f39e2b1d2 +https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda#461219d1a5bd61342293efa2c0c90eac +https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda#9272daa869e03efe68833e3dc7a02130 +https://conda.anaconda.org/conda-forge/noarch/requests-2.33.1-pyhcf101f3_0.conda#10afbb4dbf06ff959ad25a92ccee6e59 +https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda#16c18772b340887160c79a6acc022db0 +https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda#0242025a3c804966bf71aa04eee82f66 +https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda#0c20a8ebcddb24a45da89d5e917e6cb9 +https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda#472239e4eb7b5a84bb96b3ed7e3a596a +https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.4.4-py314h51f160d_0.conda#88a3dbd279e6b1faf0cddb8397866864 +https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda#55bf7b559202236157b14323b40f19e6 +https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda#e5ce43272193b38c2e9037446c1d9206 +https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.1-pyhd8ed1ab_0.conda#260af1b0a94f719de76b4e14094e9a3b +https://conda.anaconda.org/bioconda/noarch/multiqc-1.34-pyhdfd78af_0.conda#a7111ab9a6a6146b40cbce16655ac873 +https://conda.anaconda.org/conda-forge/noarch/pip-26.0.1-pyh145f28c_0.conda#09a970fbf75e8ed1aa633827ded6aa4f +https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda#ab7288cc39545556d1bc5e71ab2df9a9 diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index a27122c..37e7612 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -1,5 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.27 + - bioconda::multiqc=1.34 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 58d9313..e80e8cd 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,24 +1,21 @@ process MULTIQC { + tag "${meta.id}" label 'process_single' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.27--pyhdfd78af_0' : - 'biocontainers/multiqc:1.27--pyhdfd78af_0' }" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data' + : 'community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6'}" input: - path multiqc_files, stageAs: "?/*" - path(multiqc_config) - path(extra_multiqc_config) - path(multiqc_logo) - path(replace_names) - path(sample_names) + tuple val(meta), path(multiqc_files, stageAs: "?/*"), path(multiqc_config, stageAs: "?/*"), path(multiqc_logo), path(replace_names), path(sample_names) output: - path "*multiqc_report.html", emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - path "versions.yml" , emit: versions + tuple val(meta), path("*.html"), emit: report + tuple val(meta), path("*_data"), emit: data + tuple val(meta), path("*_plots"), emit: plots, optional: true + // MultiQC should not push its versions to the `versions` topic. Its input depends on the versions topic to be resolved thus outputting to the topic will let the pipeline hang forever + tuple val("${task.process}"), val('multiqc'), eval('multiqc --version | sed "s/.* //g"'), emit: versions when: task.ext.when == null || task.ext.when @@ -26,38 +23,28 @@ process MULTIQC { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' - def config = multiqc_config ? "--config $multiqc_config" : '' - def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + def config = multiqc_config ? multiqc_config instanceof List ? "--config ${multiqc_config.join(' --config ')}" : "--config ${multiqc_config}" : "" def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' def replace = replace_names ? "--replace-names ${replace_names}" : '' def samples = sample_names ? "--sample-names ${sample_names}" : '' """ multiqc \\ --force \\ - $args \\ - $config \\ - $prefix \\ - $extra_config \\ - $logo \\ - $replace \\ - $samples \\ + ${args} \\ + ${config} \\ + ${prefix} \\ + ${logo} \\ + ${replace} \\ + ${samples} \\ . - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ stub: """ mkdir multiqc_data + touch multiqc_data/.stub mkdir multiqc_plots + touch multiqc_plots/.stub touch multiqc_report.html - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ } diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index b16c187..2facc62 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -1,6 +1,6 @@ name: multiqc -description: Aggregate results from bioinformatics analyses across many samples into - a single report +description: Aggregate results from bioinformatics analyses across many samples + into a single report keywords: - QC - bioinformatics tools @@ -12,60 +12,91 @@ tools: It's a general use tool, perfect for summarising the output from numerous bioinformatics tools. homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ - licence: ["GPL-3.0-or-later"] + licence: + - "GPL-3.0-or-later" identifier: biotools:multiqc input: - - - multiqc_files: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - multiqc_files: type: file description: | List of reports / files recognised by MultiQC, for example the html and zip output of FastQC - - - multiqc_config: + ontologies: [] + - multiqc_config: type: file description: Optional config yml for MultiQC pattern: "*.{yml,yaml}" - - - extra_multiqc_config: - type: file - description: Second optional config yml for MultiQC. Will override common sections - in multiqc_config. - pattern: "*.{yml,yaml}" - - - multiqc_logo: + ontologies: + - edam: http://edamontology.org/format_3750 + - multiqc_logo: type: file description: Optional logo file for MultiQC pattern: "*.{png}" - - - replace_names: + ontologies: [] + - replace_names: type: file description: | Optional two-column sample renaming file. First column a set of patterns, second column a set of corresponding replacements. Passed via MultiQC's `--replace-names` option. pattern: "*.{tsv}" - - - sample_names: + ontologies: + - edam: http://edamontology.org/format_3475 + - sample_names: type: file description: | Optional TSV file with headers, passed to the MultiQC --sample_names argument. pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 output: - - report: - - "*multiqc_report.html": + report: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] + - "*.html": type: file description: MultiQC report file - pattern: "multiqc_report.html" - - data: + pattern: ".html" + ontologies: [] + data: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] - "*_data": type: directory description: MultiQC data dir pattern: "multiqc_data" - - plots: + plots: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'sample1', single_end:false ] - "*_plots": type: file description: Plots created by MultiQC - pattern: "*_data" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + pattern: "*_plots" + ontologies: [] + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - multiqc: + type: string + description: The tool name + - multiqc --version | sed "s/.* //g": + type: eval + description: The expression to obtain the version of the tool authors: - "@abhi18av" - "@bunop" @@ -76,3 +107,27 @@ maintainers: - "@bunop" - "@drpatelh" - "@jfy133" +containers: + conda: + linux/amd64: + lock_file: modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt + linux/arm64: + lock_file: modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt + docker: + linux/amd64: + name: community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6 + build_id: bd-db7c73dae76bc9e6_1 + scan_id: sc-66fc7138dbf1cf48_1 + linux/arm64: + name: community.wave.seqera.io/library/multiqc:1.34--d167b8012595a136 + build_id: bd-d167b8012595a136_1 + scan_id: sc-ac701dfa631a2af9_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/multiqc:1.34--4fc8657c816047c0 + build_id: bd-4fc8657c816047c0_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data + linux/arm64: + name: oras://community.wave.seqera.io/library/multiqc:1.34--7fbd82d945c06726 + build_id: bd-7fbd82d945c06726_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/9a/9a1fec9662a152683e6fcae440d0ce20920b3b89dc62d1e3a52e73f92eba0969/data diff --git a/modules/nf-core/multiqc/tests/custom_prefix.config b/modules/nf-core/multiqc/tests/custom_prefix.config new file mode 100644 index 0000000..b30b135 --- /dev/null +++ b/modules/nf-core/multiqc/tests/custom_prefix.config @@ -0,0 +1,5 @@ +process { + withName: 'MULTIQC' { + ext.prefix = "custom_prefix" + } +} diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test index 33316a7..4cbdb95 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -15,25 +15,84 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = [] - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) """ } } then { - assertAll( - { assert process.success }, - { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, - { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_single") } - ) + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } + } + + test("sarscov2 single-end [fastqc] - custom prefix") { + config "./custom_prefix.config" + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) + """ + } } + then { + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } } test("sarscov2 single-end [fastqc] [config]") { @@ -41,23 +100,85 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true), + [], + [], + [] + ]) """ } } then { - assertAll( - { assert process.success }, - { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, - { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_config") } - ) + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() + } + } + + test("sarscov2 single-end [fastqc] [multiple configs]") { + + when { + process { + """ + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [ + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true), + file("https://raw.githubusercontent.com/nf-core/seqinspector/1.0.0/assets/multiqc_config.yml", checkIfExists: true) + ], + [], + [], + [] + ]) + """ + } + } + + then { + assert process.success + assert snapshot( + sanitizeOutput(process.out).collectEntries { key, val -> + if (key == "data") { + return [key, val.collect { [path(it[1]).list().collect { file(it.toString()).name }] }] + } + else if (key == "plots") { + return [key, val.collect { [ + "pdf", + path("${it[1]}/pdf").list().collect { file(it.toString()).name }, + "png", + path("${it[1]}/png").list().collect { file(it.toString()).name }, + "svg", + path("${it[1]}/svg").list().collect { file(it.toString()).name }] }] + } + else if (key == "report") { + return [key, file(val[0][1].toString()).name] + } + return [key, val] + } + ).match() } } @@ -68,25 +189,23 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = [] - input[2] = [] - input[3] = [] - input[4] = [] - input[5] = [] + input[0] = channel.of([ + [ id: 'FASTQC' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true), + [], + [], + [], + [] + ]) """ } } then { + assert process.success assertAll( - { assert process.success }, - { assert snapshot(process.out.report.collect { file(it).getName() } + - process.out.data.collect { file(it).getName() } + - process.out.plots.collect { file(it).getName() } + - process.out.versions ).match("multiqc_stub") } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } - } } diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index 7b7c132..7c2f370 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -1,41 +1,422 @@ { - "multiqc_versions_single": { + "sarscov2 single-end [fastqc] [multiple configs]": { "content": [ - [ - "versions.yml:md5,8f3b8c1cec5388cf2708be948c9fa42f" - ] + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } ], + "timestamp": "2026-03-17T16:15:42.577775492", "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.4" - }, - "timestamp": "2025-01-27T09:29:57.631982377" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, - "multiqc_stub": { + "sarscov2 single-end [fastqc]": { "content": [ - [ - "multiqc_report.html", - "multiqc_data", - "multiqc_plots", - "versions.yml:md5,8f3b8c1cec5388cf2708be948c9fa42f" - ] + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_software_versions.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } ], + "timestamp": "2026-03-17T16:21:17.072841555", "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.4" - }, - "timestamp": "2025-01-27T09:30:34.743726958" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, - "multiqc_versions_config": { + "sarscov2 single-end [fastqc] - stub": { "content": [ - [ - "versions.yml:md5,8f3b8c1cec5388cf2708be948c9fa42f" - ] + { + "data": [ + [ + { + "id": "FASTQC" + }, + [ + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "plots": [ + [ + { + "id": "FASTQC" + }, + [ + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "report": [ + [ + { + "id": "FASTQC" + }, + "multiqc_report.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } ], + "timestamp": "2026-02-26T15:14:39.789193051", "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.4" - }, - "timestamp": "2025-01-27T09:30:21.44383553" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "sarscov2 single-end [fastqc] [config]": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "multiqc_report.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:30.372239611", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, + "sarscov2 single-end [fastqc] - custom prefix": { + "content": [ + { + "data": [ + [ + [ + "fastqc-status-check-heatmap.txt", + "fastqc_overrepresented_sequences_plot.txt", + "fastqc_per_base_n_content_plot.txt", + "fastqc_per_base_sequence_quality_plot.txt", + "fastqc_per_sequence_gc_content_plot_Counts.txt", + "fastqc_per_sequence_gc_content_plot_Percentages.txt", + "fastqc_per_sequence_quality_scores_plot.txt", + "fastqc_sequence_counts_plot.txt", + "fastqc_sequence_duplication_levels_plot.txt", + "fastqc_sequence_length_distribution_plot.txt", + "fastqc_top_overrepresented_sequences_table.txt", + "llms-full.txt", + "multiqc.log", + "multiqc.parquet", + "multiqc_citations.txt", + "multiqc_data.json", + "multiqc_fastqc.txt", + "multiqc_general_stats.txt", + "multiqc_software_versions.txt", + "multiqc_sources.txt" + ] + ] + ], + "plots": [ + [ + "pdf", + [ + "fastqc-status-check-heatmap.pdf", + "fastqc_overrepresented_sequences_plot.pdf", + "fastqc_per_base_n_content_plot.pdf", + "fastqc_per_base_sequence_quality_plot.pdf", + "fastqc_per_sequence_gc_content_plot_Counts.pdf", + "fastqc_per_sequence_gc_content_plot_Percentages.pdf", + "fastqc_per_sequence_quality_scores_plot.pdf", + "fastqc_sequence_counts_plot-cnt.pdf", + "fastqc_sequence_counts_plot-pct.pdf", + "fastqc_sequence_duplication_levels_plot.pdf", + "fastqc_sequence_length_distribution_plot.pdf", + "fastqc_top_overrepresented_sequences_table.pdf" + ], + "png", + [ + "fastqc-status-check-heatmap.png", + "fastqc_overrepresented_sequences_plot.png", + "fastqc_per_base_n_content_plot.png", + "fastqc_per_base_sequence_quality_plot.png", + "fastqc_per_sequence_gc_content_plot_Counts.png", + "fastqc_per_sequence_gc_content_plot_Percentages.png", + "fastqc_per_sequence_quality_scores_plot.png", + "fastqc_sequence_counts_plot-cnt.png", + "fastqc_sequence_counts_plot-pct.png", + "fastqc_sequence_duplication_levels_plot.png", + "fastqc_sequence_length_distribution_plot.png", + "fastqc_top_overrepresented_sequences_table.png" + ], + "svg", + [ + "fastqc-status-check-heatmap.svg", + "fastqc_overrepresented_sequences_plot.svg", + "fastqc_per_base_n_content_plot.svg", + "fastqc_per_base_sequence_quality_plot.svg", + "fastqc_per_sequence_gc_content_plot_Counts.svg", + "fastqc_per_sequence_gc_content_plot_Percentages.svg", + "fastqc_per_sequence_quality_scores_plot.svg", + "fastqc_sequence_counts_plot-cnt.svg", + "fastqc_sequence_counts_plot-pct.svg", + "fastqc_sequence_duplication_levels_plot.svg", + "fastqc_sequence_length_distribution_plot.svg", + "fastqc_top_overrepresented_sequences_table.svg" + ] + ] + ], + "report": "custom_prefix.html", + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.34" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:18.189023981", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } } } \ No newline at end of file diff --git a/modules/nf-core/multiqc/tests/nextflow.config b/modules/nf-core/multiqc/tests/nextflow.config index c537a6a..374dfef 100644 --- a/modules/nf-core/multiqc/tests/nextflow.config +++ b/modules/nf-core/multiqc/tests/nextflow.config @@ -1,5 +1,6 @@ process { withName: 'MULTIQC' { ext.prefix = null + ext.args = '-p' } } diff --git a/modules/nf-core/multiqc/tests/tags.yml b/modules/nf-core/multiqc/tests/tags.yml deleted file mode 100644 index bea6c0d..0000000 --- a/modules/nf-core/multiqc/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -multiqc: - - modules/nf-core/multiqc/** diff --git a/nextflow.config b/nextflow.config index 68a61a0..1b1ea2e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -32,13 +32,14 @@ params { email_on_fail = null plaintext_email = false monochrome_logs = false - hook_url = null help = false help_full = false show_hidden = false version = false pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' - trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss')// Config options + trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') + + // Config options config_profile_name = null config_profile_description = null @@ -51,6 +52,10 @@ params { validate_params = true } +// Backwards compatibility for publishDir syntax +outputDir = params.outdir +workflow.output.mode = params.publish_dir_mode + // Load base.config by default for all pipelines includeConfig 'conf/base.config' @@ -91,7 +96,18 @@ profiles { apptainer.enabled = false docker.runOptions = '-u $(id -u):$(id -g)' } - arm { + arm64 { + process.arch = 'arm64' + // TODO https://github.com/nf-core/modules/issues/6694 + // For now if you're using arm64 you have to use wave for the sake of the maintainers + // wave profile + apptainer.ociAutoPull = true + singularity.ociAutoPull = true + wave.enabled = true + wave.freeze = true + wave.strategy = 'conda,container' + } + emulate_amd64 { docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' } singularity { @@ -148,18 +164,6 @@ profiles { wave.freeze = true wave.strategy = 'conda,container' } - gitpod { - executor.name = 'local' - executor.cpus = 4 - executor.memory = 8.GB - process { - resourceLimits = [ - memory: 8.GB, - cpus : 4, - time : 1.h - ] - } - } gpu { docker.runOptions = '-u $(id -u):$(id -g) --gpus all' apptainer.runOptions = '--nv' @@ -235,7 +239,6 @@ dag { manifest { name = 'nf-core/datasync' - author = """Alexander Peltzer""" // The author field is deprecated from Nextflow version 24.10.0, use contributors instead contributors = [ // TODO nf-core: Update the field with the details of the contributors to your pipeline. New with Nextflow version 24.10.0 [ @@ -250,48 +253,20 @@ manifest { homePage = 'https://github.com/nf-core/datasync' description = """A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.""" mainScript = 'main.nf' - defaultBranch = 'master' - nextflowVersion = '!>=24.04.2' + defaultBranch = 'main' + nextflowVersion = '!>=25.10.4' version = '1.0dev' doi = '' } // Nextflow plugins plugins { - id 'nf-schema@2.3.0' // Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-schema@2.5.1' // Validation of pipeline parameters and creation of an input channel from a sample sheet } validation { defaultIgnoreParams = ["genomes"] monochromeLogs = params.monochrome_logs - help { - enabled = true - command = "nextflow run nf-core/datasync -profile --input samplesheet.csv --outdir " - fullParameter = "help_full" - showHiddenParameter = "show_hidden" - beforeText = """ --\033[2m----------------------------------------------------\033[0m- - \033[0;32m,--.\033[0;30m/\033[0;32m,-.\033[0m -\033[0;34m ___ __ __ __ ___ \033[0;32m/,-._.--~\'\033[0m -\033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m -\033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m - \033[0;32m`._,._,\'\033[0m -\033[0;35m nf-core/datasync ${manifest.version}\033[0m --\033[2m----------------------------------------------------\033[0m- -""" - afterText = """${manifest.doi ? "\n* The pipeline\n" : ""}${manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${manifest.doi ? "\n" : ""} -* The nf-core framework - https://doi.org/10.1038/s41587-020-0439-x - -* Software dependencies - https://github.com/nf-core/datasync/blob/master/CITATIONS.md -""" - } - summary { - beforeText = validation.help.beforeText - afterText = validation.help.afterText - } } - // Load modules.config for DSL2 module specific options includeConfig 'conf/modules.config' diff --git a/nextflow_schema.json b/nextflow_schema.json index d9e3dd8..10b92c1 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://raw.githubusercontent.com/nf-core/datasync/master/nextflow_schema.json", + "$id": "https://raw.githubusercontent.com/nf-core/datasync/main/nextflow_schema.json", "title": "nf-core/datasync pipeline parameters", "description": "A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.", "type": "object", @@ -74,7 +74,6 @@ }, "igenomes_base": { "type": "string", - "format": "directory-path", "description": "The base path to the igenomes reference files", "fa_icon": "fas fa-ban", "hidden": true, @@ -180,13 +179,6 @@ "fa_icon": "fas fa-palette", "hidden": true }, - "hook_url": { - "type": "string", - "description": "Incoming hook URL for messaging service", - "fa_icon": "fas fa-people-group", - "help_text": "Incoming hook URL for messaging service. Currently, MS Teams and Slack are supported.", - "hidden": true - }, "multiqc_config": { "type": "string", "format": "file-path", @@ -224,6 +216,18 @@ "fa_icon": "far calendar", "description": "Suffix to add to the trace report filename. Default is the date and time in the format yyyy-MM-dd_HH-mm-ss.", "hidden": true + }, + "help": { + "type": ["boolean", "string"], + "description": "Display the help message." + }, + "help_full": { + "type": "boolean", + "description": "Display the full detailed help message." + }, + "show_hidden": { + "type": "boolean", + "description": "Display hidden parameters in the help message (only works when --help or --help_full are provided)." } } } diff --git a/nf-test.config b/nf-test.config index 889df76..f7aaeb4 100644 --- a/nf-test.config +++ b/nf-test.config @@ -1,21 +1,35 @@ config { // location for all nf-test tests - testsDir "." + testsDir = "." // nf-test directory including temporary files for each test - workDir System.getenv("NFT_WORKDIR") ?: ".nf-test" + workDir = System.getenv("NFT_WORKDIR") ?: ".nf-test" // location of an optional nextflow.config file specific for executing tests - configFile "tests/nextflow.config" + configFile = "tests/nextflow.config" // ignore tests coming from the nf-core/modules repo - ignore 'modules/nf-core/**/*', 'subworkflows/nf-core/**/*' + ignore = [ + 'modules/nf-core/**/tests/*', + 'subworkflows/nf-core/**/tests/*', + ] // run all test with defined profile(s) from the main nextflow.config - profile "test" + 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' + triggers = [ + '.github/actions/nf-test/action.yml', + '.github/workflows/nf-test.yml', + 'assets/schema_input.json', + 'bin/*', + 'conf/test.config', + 'nextflow.config', + 'nextflow_schema.json', + 'nf-test.config', + 'tests/.nftignore', + 'tests/nextflow.config', + ] // load the necessary plugins plugins { diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index a99dec5..29e366a 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -1,6 +1,6 @@ { "@context": [ - "https://w3id.org/ro/crate/1.1/context", + "https://w3id.org/ro/crate/1.2/context", { "GithubService": "https://w3id.org/ro/terms/test#GithubService", "JenkinsService": "https://w3id.org/ro/terms/test#JenkinsService", @@ -22,8 +22,8 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "InProgress", - "datePublished": "2025-06-03T11:01:27+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A524.04.2-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.1-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.1)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "datePublished": "2026-07-24T12:35:36+00:00", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#6e1856e4-68ad-483f-95f4-97b1f4ec6a75" + "@id": "#48344b18-cfae-44a4-ad69-b23734224749" } ], "name": "nf-core/datasync" @@ -112,7 +112,7 @@ }, "conformsTo": [ { - "@id": "https://w3id.org/ro/crate/1.1" + "@id": "https://w3id.org/ro/crate/1.2" }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.0" @@ -122,21 +122,16 @@ { "@id": "main.nf", "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], - "creator": [ + "contributor": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], "dateCreated": "", - "dateModified": "2025-06-03T11:01:27Z", + "dateModified": "2026-07-24T12:35:36Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": ["nf-core", "nextflow"], "license": ["MIT"], - "maintainer": [ - { - "@id": "https://orcid.org/0000-0002-6503-2180" - } - ], "name": ["nf-core/datasync"], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" @@ -157,14 +152,14 @@ "url": { "@id": "https://www.nextflow.io/" }, - "version": "!>=24.04.2" + "version": "!>=25.10.4" }, { - "@id": "#6e1856e4-68ad-483f-95f4-97b1f4ec6a75", + "@id": "#48344b18-cfae-44a4-ad69-b23734224749", "@type": "TestSuite", "instance": [ { - "@id": "#8316b07c-aa2f-4100-b61a-d1aa1321ccfd" + "@id": "#867a3285-b1be-4cd0-8b71-8341c5d037f8" } ], "mainEntity": { @@ -173,7 +168,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#8316b07c-aa2f-4100-b61a-d1aa1321ccfd", + "@id": "#867a3285-b1be-4cd0-8b71-8341c5d037f8", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/nf-test.yml", diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index e65bbf3..e9e92f3 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -11,9 +11,9 @@ include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' include { paramsSummaryMap } from 'plugin/nf-schema' include { samplesheetToList } from 'plugin/nf-schema' +include { paramsHelp } from 'plugin/nf-schema' include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' -include { imNotification } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' @@ -32,10 +32,13 @@ workflow PIPELINE_INITIALISATION { nextflow_cli_args // array: List of positional nextflow CLI args outdir // string: The output directory where the results will be saved input // string: Path to input samplesheet + help // boolean: Display help message and exit + help_full // boolean: Show the full help message + show_hidden // boolean: Show hidden parameters in the help message main: - ch_versions = Channel.empty() + ch_versions = channel.empty() // // Print version and exit if required and dump pipeline parameters to JSON file @@ -50,10 +53,42 @@ workflow PIPELINE_INITIALISATION { // // Validate parameters and generate parameter summary to stdout // + + def before_text = "" + def after_text = "" + before_text = """ +-\033[2m----------------------------------------------------\033[0m- + \033[0;32m,--.\033[0;30m/\033[0;32m,-.\033[0m +\033[0;34m ___ __ __ __ ___ \033[0;32m/,-._.--~\'\033[0m +\033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m +\033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m + \033[0;32m`._,._,\'\033[0m +\033[0;35m nf-core/datasync ${workflow.manifest.version}\033[0m +-\033[2m----------------------------------------------------\033[0m- +""" + after_text = """${workflow.manifest.doi ? "\n* The pipeline\n" : ""}${workflow.manifest.doi.tokenize(",").collect { doi -> " https://doi.org/${doi.trim().replace('https://doi.org/','')}"}.join("\n")}${workflow.manifest.doi ? "\n" : ""} +* The nf-core framework + https://doi.org/10.1038/s41587-020-0439-x + +* Software dependencies + https://github.com/nf-core/datasync/blob/main/CITATIONS.md +""" + if (monochrome_logs) { + before_text = before_text.replaceAll(/\033\[[0-9;]*m/, '') + } + + command = "nextflow run ${workflow.manifest.name} -profile --input samplesheet.csv --outdir " + UTILS_NFSCHEMA_PLUGIN ( workflow, validate_params, - null + null, + help, + help_full, + show_hidden, + before_text, + after_text, + command ) // @@ -72,8 +107,8 @@ workflow PIPELINE_INITIALISATION { // Create channel from input file provided through params.input // - Channel - .fromList(samplesheetToList(params.input, "${projectDir}/assets/schema_input.json")) + channel + .fromList(samplesheetToList(input, "${projectDir}/assets/schema_input.json")) .map { meta, fastq_1, fastq_2 -> if (!fastq_2) { @@ -111,7 +146,6 @@ workflow PIPELINE_COMPLETION { plaintext_email // boolean: Send plain-text email instead of HTML outdir // path: Path to output directory where results will be published monochrome_logs // boolean: Disable ANSI colour codes in log output - hook_url // string: hook URL for notifications multiqc_report // string: Path to MultiQC report main: @@ -135,13 +169,11 @@ workflow PIPELINE_COMPLETION { } completionSummary(monochrome_logs) - if (hook_url) { - imNotification(summary_params, hook_url) - } + } workflow.onError { - log.error "Pipeline failed. Please refer to troubleshooting docs: https://nf-co.re/docs/usage/troubleshooting" + log.error "Pipeline failed. Please refer to troubleshooting docs for common issues: https://nf-co.re/docs/running/troubleshooting" } } diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml b/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml deleted file mode 100644 index f847611..0000000 --- a/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -subworkflows/utils_nextflow_pipeline: - - subworkflows/nf-core/utils_nextflow_pipeline/** diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index bfd2587..afca543 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -17,7 +17,7 @@ workflow UTILS_NFCORE_PIPELINE { checkProfileProvided(nextflow_cli_args) emit: - valid_config + valid_config = valid_config } /* @@ -98,7 +98,7 @@ def workflowVersionToYAML() { // Get channel of software versions used in pipeline in YAML format // def softwareVersionsToYAML(ch_versions) { - return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(Channel.of(workflowVersionToYAML())) + return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(channel.of(workflowVersionToYAML())) } // @@ -353,67 +353,3 @@ def completionSummary(monochrome_logs=true) { log.info("-${colors.purple}[${workflow.manifest.name}]${colors.red} Pipeline completed with errors${colors.reset}-") } } - -// -// Construct and send a notification to a web server as JSON e.g. Microsoft Teams and Slack -// -def imNotification(summary_params, hook_url) { - def summary = [:] - summary_params - .keySet() - .sort() - .each { group -> - summary << summary_params[group] - } - - def misc_fields = [:] - misc_fields['start'] = workflow.start - misc_fields['complete'] = workflow.complete - misc_fields['scriptfile'] = workflow.scriptFile - misc_fields['scriptid'] = workflow.scriptId - if (workflow.repository) { - misc_fields['repository'] = workflow.repository - } - if (workflow.commitId) { - misc_fields['commitid'] = workflow.commitId - } - if (workflow.revision) { - misc_fields['revision'] = workflow.revision - } - misc_fields['nxf_version'] = workflow.nextflow.version - misc_fields['nxf_build'] = workflow.nextflow.build - misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp - - def msg_fields = [:] - msg_fields['version'] = getWorkflowVersion() - msg_fields['runName'] = workflow.runName - msg_fields['success'] = workflow.success - msg_fields['dateComplete'] = workflow.complete - msg_fields['duration'] = workflow.duration - msg_fields['exitStatus'] = workflow.exitStatus - msg_fields['errorMessage'] = (workflow.errorMessage ?: 'None') - msg_fields['errorReport'] = (workflow.errorReport ?: 'None') - msg_fields['commandLine'] = workflow.commandLine.replaceFirst(/ +--hook_url +[^ ]+/, "") - msg_fields['projectDir'] = workflow.projectDir - msg_fields['summary'] = summary << misc_fields - - // Render the JSON template - def engine = new groovy.text.GStringTemplateEngine() - // Different JSON depending on the service provider - // Defaults to "Adaptive Cards" (https://adaptivecards.io), except Slack which has its own format - def json_path = hook_url.contains("hooks.slack.com") ? "slackreport.json" : "adaptivecard.json" - def hf = new File("${workflow.projectDir}/assets/${json_path}") - def json_template = engine.createTemplate(hf).make(msg_fields) - def json_message = json_template.toString() - - // POST - def post = new URL(hook_url).openConnection() - post.setRequestMethod("POST") - post.setDoOutput(true) - post.setRequestProperty("Content-Type", "application/json") - post.getOutputStream().write(json_message.getBytes("UTF-8")) - def postRC = post.getResponseCode() - if (!postRC.equals(200)) { - log.warn(post.getErrorStream().getText()) - } -} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test new file mode 100644 index 0000000..8940d32 --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test @@ -0,0 +1,29 @@ +nextflow_workflow { + + name "Test Workflow UTILS_NFCORE_PIPELINE" + script "../main.nf" + config "subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config" + workflow "UTILS_NFCORE_PIPELINE" + tag "subworkflows" + tag "subworkflows_nfcore" + tag "utils_nfcore_pipeline" + tag "subworkflows/utils_nfcore_pipeline" + + test("Should run without failures") { + + when { + workflow { + """ + input[0] = [] + """ + } + } + + then { + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out).match() } + ) + } + } +} diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap new file mode 100644 index 0000000..859d103 --- /dev/null +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.nf.test.snap @@ -0,0 +1,19 @@ +{ + "Should run without failures": { + "content": [ + { + "0": [ + true + ], + "valid_config": [ + true + ] + } + ], + "meta": { + "nf-test": "0.8.4", + "nextflow": "23.10.1" + }, + "timestamp": "2024-02-28T12:03:25.726491" + } +} \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml b/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml deleted file mode 100644 index ac8523c..0000000 --- a/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -subworkflows/utils_nfcore_pipeline: - - subworkflows/nf-core/utils_nfcore_pipeline/** diff --git a/subworkflows/nf-core/utils_nfschema_plugin/main.nf b/subworkflows/nf-core/utils_nfschema_plugin/main.nf index 4994303..1df8b76 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/main.nf +++ b/subworkflows/nf-core/utils_nfschema_plugin/main.nf @@ -4,6 +4,7 @@ include { paramsSummaryLog } from 'plugin/nf-schema' include { validateParameters } from 'plugin/nf-schema' +include { paramsHelp } from 'plugin/nf-schema' workflow UTILS_NFSCHEMA_PLUGIN { @@ -15,32 +16,58 @@ workflow UTILS_NFSCHEMA_PLUGIN { // when this input is empty it will automatically use the configured schema or // "${projectDir}/nextflow_schema.json" as default. This input should not be empty // for meta pipelines + help // boolean: show help message + help_full // boolean: show full help message + show_hidden // boolean: show hidden parameters in help message + before_text // string: text to show before the help message and parameters summary + after_text // string: text to show after the help message and parameters summary + command // string: an example command of the pipeline main: + if(help || help_full) { + help_options = [ + beforeText: before_text, + afterText: after_text, + command: command, + showHidden: show_hidden, + fullHelp: help_full, + ] + if(parameters_schema) { + help_options << [parametersSchema: parameters_schema] + } + log.info paramsHelp( + help_options, + (params.help instanceof String && params.help != "true") ? params.help : "", + ) + exit 0 + } + // // Print parameter summary to stdout. This will display the parameters // that differ from the default given in the JSON schema // + + summary_options = [:] if(parameters_schema) { - log.info paramsSummaryLog(input_workflow, parameters_schema:parameters_schema) - } else { - log.info paramsSummaryLog(input_workflow) + summary_options << [parametersSchema: parameters_schema] } + log.info before_text + log.info paramsSummaryLog(summary_options, input_workflow) + log.info after_text // // Validate the parameters using nextflow_schema.json or the schema // given via the validation.parametersSchema configuration option // if(validate_params) { + validateOptions = [:] if(parameters_schema) { - validateParameters(parameters_schema:parameters_schema) - } else { - validateParameters() + validateOptions << [parametersSchema: parameters_schema] } + validateParameters(validateOptions) } emit: dummy_emit = true } - diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test index 8fb3016..c977917 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test @@ -25,6 +25,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -51,6 +57,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -77,6 +89,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -103,6 +121,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -114,4 +138,36 @@ nextflow_workflow { ) } } + + test("Should create a help message") { + + when { + + params { + test_data = '' + outdir = null + } + + workflow { + """ + validate_params = true + input[0] = workflow + input[1] = validate_params + input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + input[3] = true + input[4] = false + input[5] = false + input[6] = "Before" + input[7] = "After" + input[8] = "nextflow run test/test" + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config index 0907ac5..f6537cc 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config @@ -1,8 +1,8 @@ plugins { - id "nf-schema@2.1.0" + id "nf-schema@2.6.1" } validation { parametersSchema = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" monochromeLogs = true -} \ No newline at end of file +} diff --git a/tests/.nftignore b/tests/.nftignore index c10bc1f..e128a12 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -1,9 +1,11 @@ .DS_Store multiqc/multiqc_data/fastqc_top_overrepresented_sequences_table.txt +multiqc/multiqc_data/multiqc.parquet multiqc/multiqc_data/multiqc.log multiqc/multiqc_data/multiqc_data.json multiqc/multiqc_data/multiqc_sources.txt multiqc/multiqc_data/multiqc_software_versions.txt +multiqc/multiqc_data/llms-full.txt multiqc/multiqc_plots/{svg,pdf,png}/*.{svg,pdf,png} multiqc/multiqc_report.html fastqc/*_fastqc.{html,zip} diff --git a/tests/default.nf.test b/tests/default.nf.test index 43cf2c9..7576e53 100644 --- a/tests/default.nf.test +++ b/tests/default.nf.test @@ -13,21 +13,19 @@ nextflow_pipeline { } 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 = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + // stable_path: All files + folders in ${params.outdir}/ with a stable path (including file name) + def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_content: All files in ${params.outdir}/ with stable content + def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + assert workflow.success 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 test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), // All stable path name, with a relative path - stable_name, + stable_path, // All files with stable contents - stable_path + stable_content ).match() } ) } diff --git a/tests/nextflow.config b/tests/nextflow.config index 12b4c0a..da48321 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -6,7 +6,9 @@ // TODO nf-core: Specify any additional parameters here // Or any resources requirements -params.modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' -params.pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync' +params { + modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' + pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/' +} aws.client.anonymous = true // fixes S3 access issues on self-hosted runners diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 6905242..7d12501 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -20,74 +20,78 @@ workflow DATASYNC { take: ch_samplesheet // channel: samplesheet read in from --input + multiqc_config + multiqc_logo + multiqc_methods_description + outdir + main: - ch_versions = Channel.empty() - ch_multiqc_files = Channel.empty() + def ch_versions = channel.empty() + def ch_multiqc_files = channel.empty() // // MODULE: Run FastQC // - FASTQC ( - ch_samplesheet - ) - ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.collect{it[1]}) - ch_versions = ch_versions.mix(FASTQC.out.versions.first()) + FASTQC(ch_samplesheet) + ch_multiqc_files = ch_multiqc_files.mix(FASTQC.out.zip.map{ _meta, file -> file }) // // Collate and save software versions // - softwareVersionsToYAML(ch_versions) + def topic_versions = channel.topic("versions") + .distinct() + .branch { entry -> + versions_file: entry instanceof Path + versions_tuple: true + } + + def topic_versions_string = topic_versions.versions_tuple + .map { process, tool, version -> + [ process[process.lastIndexOf(':')+1..-1], " ${tool}: ${version}" ] + } + .groupTuple(by:0) + .map { process, tool_versions -> + tool_versions.unique().sort() + "${process}:\n${tool_versions.join('\n')}" + } + + def ch_collated_versions = softwareVersionsToYAML(ch_versions.mix(topic_versions.versions_file)) + .mix(topic_versions_string) .collectFile( - storeDir: "${params.outdir}/pipeline_info", + storeDir: "${outdir}/pipeline_info", name: 'nf_core_' + 'datasync_software_' + 'mqc_' + 'versions.yml', sort: true, newLine: true - ).set { ch_collated_versions } - + ) // // MODULE: MultiQC // - ch_multiqc_config = Channel.fromPath( - "$projectDir/assets/multiqc_config.yml", checkIfExists: true) - ch_multiqc_custom_config = params.multiqc_config ? - Channel.fromPath(params.multiqc_config, checkIfExists: true) : - Channel.empty() - ch_multiqc_logo = params.multiqc_logo ? - Channel.fromPath(params.multiqc_logo, checkIfExists: true) : - Channel.empty() - - summary_params = paramsSummaryMap( - workflow, parameters_schema: "nextflow_schema.json") - ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) - ch_multiqc_files = ch_multiqc_files.mix( - ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) - ch_multiqc_custom_methods_description = params.multiqc_methods_description ? - file(params.multiqc_methods_description, checkIfExists: true) : - file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) - ch_methods_description = Channel.value( - methodsDescriptionText(ch_multiqc_custom_methods_description)) - ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) - ch_multiqc_files = ch_multiqc_files.mix( - ch_methods_description.collectFile( - name: 'methods_description_mqc.yaml', - sort: true - ) - ) - - MULTIQC ( - ch_multiqc_files.collect(), - ch_multiqc_config.toList(), - ch_multiqc_custom_config.toList(), - ch_multiqc_logo.toList(), - [], - [] + def ch_summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") + def ch_workflow_summary = channel.value(paramsSummaryMultiqc(ch_summary_params)) + ch_multiqc_files = ch_multiqc_files.mix(ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) + def ch_multiqc_custom_methods_description = multiqc_methods_description + ? file(multiqc_methods_description, checkIfExists: true) + : file("${projectDir}/assets/methods_description_template.yml", checkIfExists: true) + def ch_methods_description = channel.value(methodsDescriptionText(ch_multiqc_custom_methods_description)) + ch_multiqc_files = ch_multiqc_files.mix(ch_methods_description.collectFile(name: 'methods_description_mqc.yaml', sort: true)) + MULTIQC( + ch_multiqc_files.flatten().collect().map { files -> + [ + [id: 'datasync'], + files, + multiqc_config + ? file(multiqc_config, checkIfExists: true) + : file("${projectDir}/assets/multiqc_config.yml", checkIfExists: true), + multiqc_logo ? file(multiqc_logo, checkIfExists: true) : [], + [], + [], + ] + } ) - - emit:multiqc_report = MULTIQC.out.report.toList() // channel: /path/to/multiqc_report.html + emit:multiqc_report = MULTIQC.out.report.map { _meta, report -> [report] }.toList() // channel: /path/to/multiqc_report.html versions = ch_versions // channel: [ path(versions.yml) ] - } /* From d5daf90e3415af26b4c1c7ec7deb4da8c88eb449 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 12:02:24 -0300 Subject: [PATCH 200/334] Update docs/output.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index 27a0c6b..986bdd3 100644 --- a/docs/output.md +++ b/docs/output.md @@ -101,7 +101,7 @@ The MultiQC report consolidates: - the validated samplesheet and workflow parameter summary; and - pipeline and tool versions. -### Rclone checksum sections +### `rclone checksum` section (source integrity checks) The MD5 and SHA-256 input-validation sections show the results from `rclone checksum`. Use these sections to confirm that each source file matched the checksum manifest supplied in `checksum_md5` and/or `checksum_sha` before copying. From db629124b86218c9a23e14c1d1b1fc885dacfece Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 12:02:33 -0300 Subject: [PATCH 201/334] Update docs/output.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index 986bdd3..43f95ae 100644 --- a/docs/output.md +++ b/docs/output.md @@ -107,7 +107,7 @@ The MD5 and SHA-256 input-validation sections show the results from `rclone chec ![nf-core/multiqc checksum md5](images/datasync-multiqc-checksum-md5.png) -### Rclone check section +### `rclone check` section (post-transfer checks) The source-destination validation section shows the results from `rclone check` after the copy step. Use this section to confirm that copied files at `output_path` match the corresponding source files. From 01f6cdafae386375e76d2402a1cc338540976d2c Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 12:02:43 -0300 Subject: [PATCH 202/334] Update docs/output.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index 43f95ae..4822585 100644 --- a/docs/output.md +++ b/docs/output.md @@ -113,7 +113,7 @@ The source-destination validation section shows the results from `rclone check` ![nf-core/multiqc checksum md5](images/datasync-multiqc-post-transfer-check.png) -Open `multiqc_report.html` after every run and investigate any non-matching, missing, or error entries. In the rclone result sections, entries are prioritised so rows needing attention are shown before successful matches: errors, mismatches, and missing-file statuses appear ahead of matching files. Data under `multiqc_data/` can be retained for automated auditing or downstream reporting; exact filenames may vary with the MultiQC version and the checksum types present in the samplesheet. +Open `multiqc_report.html` after every run and investigate any non-matching, missing, or error entries. In the `rclone` result sections, entries are prioritised so rows needing attention are shown before successful matches: errors, mismatches, and missing-file statuses appear ahead of matching files. Data under `multiqc_data/` can be retained for automated auditing or downstream reporting; exact filenames may vary with the MultiQC version and the checksum types present in the samplesheet. ## Pipeline information From 679d21000b970c274921185acd09fd2c44502d99 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 12:02:53 -0300 Subject: [PATCH 203/334] Update docs/usage.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index c8e95fd..f3a1288 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -8,7 +8,7 @@ Install Nextflow 25.10.4 or later and use a supported software profile. Docker or Singularity/Apptainer is recommended for reproducibility. Ensure that the account running Nextflow can read each source and checksum manifest and can write to every destination. -For cloud or other authenticated rclone remotes, create an [rclone configuration](https://rclone.org/docs/) and pass it with `--rclone_config`. The configuration applies to remote **sources and destinations**. The pipeline has currently been tested for transfers between S3 buckets. Other rclone-supported layouts, such as Azure Blob Storage to S3 or transfers between S3-compatible providers, should be configured and validated against the upstream rclone documentation for each provider before use. +For cloud or other authenticated rclone remotes, create an [rclone configuration](https://rclone.org/docs/) and pass it with `--rclone_config`. The configuration applies to remote **sources and destinations**. The pipeline has currently been tested for transfers between S3 buckets. Other rclone-supported layouts, such as Azure Blob Storage to S3 or transfers between S3-compatible providers, should be configured and validated against the upstream `rclone` documentation for each provider before use. ## Samplesheet input From 083f023700ed7bf75071ec85559e099146e452fc Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 12:03:43 -0300 Subject: [PATCH 204/334] Update docs/output.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index 4822585..bdbfdcd 100644 --- a/docs/output.md +++ b/docs/output.md @@ -40,7 +40,7 @@ This document describes the reports produced by nf-core/datasync. Paths below ar The `rclone/` directory is split by module stage. Copy logs are published to `rclone/copy/`, pre-copy checksum validation reports are published to `rclone/checksum//`, and post-copy source-to-destination comparison reports are published to `rclone/check//`. The `` directory name is taken from the `sample` value in the samplesheet row. -## Rclone transfer and integrity reports +## `rclone` directory
    -[Nextflow](https://www.nextflow.io/docs/latest/tracing.html) provides excellent functionality for generating various reports relevant to the running and execution of the pipeline. This will allow you to troubleshoot errors with the running of the pipeline, and also provide you with other information such as launch commands, run times and resource usage. +[Nextflow](https://docs.seqera.io/platform-cloud/reports/overview) provides excellent functionality for generating various reports relevant to the running and execution of the pipeline. This will allow you to troubleshoot errors with the running of the pipeline, and also provide you with other information such as launch commands, run times and resource usage. diff --git a/docs/usage.md b/docs/usage.md index 1c85a3e..7822aa9 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -153,7 +153,7 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - `apptainer` - 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). + - 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. diff --git a/modules.json b/modules.json index 578acbb..0579f07 100644 --- a/modules.json +++ b/modules.json @@ -12,7 +12,7 @@ }, "multiqc": { "branch": "master", - "git_sha": "008f9d3e61209bf995edac3ba531f54e269e1215", + "git_sha": "98403d15b0e50edae1f3fec5eae5e24982f1fade", "installed_by": ["modules"] } } @@ -21,7 +21,7 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "05954dab2ff481bcb999f24455da29a5828af08d", + "git_sha": "c2b22d85f30a706a3073387f30380704fcae013b", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { @@ -31,7 +31,7 @@ }, "utils_nfschema_plugin": { "branch": "master", - "git_sha": "fdc08b8b1ae74f56686ce21f7ea11ad11990ce57", + "git_sha": "a7b27fd25bfa8dcc07d299e88bd790585901a436", "installed_by": ["subworkflows"] } } diff --git a/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt new file mode 100644 index 0000000..2a91c22 --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt @@ -0,0 +1,1526 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-64: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.0-h27c8c51_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.6-py314h2b28147_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.2.0-py314h8ec4b1a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.41.0-py310h49dadd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.41.0-py310hcbd6021_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.4-py314h2e6c369_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.5-habeac84_100_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.5.9-py314h5bd0f2a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.1-hbc0de68_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 +md5: a9f577daf3de00bca7c3c76c0ecbd1de +depends: +- __glibc >=2.17,<3.0.a0 +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28948 +timestamp: 1770939786096 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 +md5: aaa2a381ccc56eac91d63b6c1240312f +depends: +- cpython +- python-gil +license: MIT +license_family: MIT +size: 8191 +timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 +md5: 2934f256a8acfe48f6ebb4fce6cde29c +depends: +- python >=3.9 +- typing-extensions >=4.0.0 +license: MIT +license_family: MIT +size: 18074 +timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab +md5: c6b0543676ecb1fb2d7643941fe375f2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 64927 +timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda +noarch: generic +sha256: a1c97297e867776760489537bc5ae36fa83a154be30e3b79385a39ca4cb058fe +md5: 1133126d840e75287d83947be3fc3e71 +depends: +- python >=3.14 +license: BSD-3-Clause AND MIT AND EPL-2.0 +size: 7533 +timestamp: 1778594057496 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py314h3de4e8d_1.conda +sha256: 3ad3500bff54a781c29f16ce1b288b36606e2189d0b0ef2f67036554f47f12b0 +md5: 8910d2c46f7e7b519129f486e0fe927a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- libbrotlicommon 1.2.0 hb03c661_1 +license: MIT +license_family: MIT +size: 367376 +timestamp: 1764017265553 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda +sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 +md5: d2ffd7602c02f2b316fd921d39876885 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 260182 +timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +sha256: 9812a303a1395e1dafbd92e5bc8a1ff6013bcbba0a09c7f03a8d23e43560aa9b +md5: 489b8e97e666c93f68fdb35c3c9b957f +depends: +- __unix +license: ISC +size: 129868 +timestamp: 1779289852439 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +sha256: 645655a3510e38e625da136595f3f16f2130c3263630cc3bc8f60f619ddbe490 +md5: 9fefff2f745ea1cc2ef15211a20c054a +depends: +- python >=3.10 +license: ISC +size: 134201 +timestamp: 1779285131141 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +sha256: 3f9483d62ce24ecd063f8a5a714448445dc8d9e201147c46699fc0033e824457 +md5: a9167b9571f3baa9d448faa2139d1089 +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 58872 +timestamp: 1775127203018 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +sha256: 99ab8ef815c4520cce3a7482c2513f377c14348206857661d84c76a55e030f97 +md5: 003767c47f1f0a474c4de268b57839c3 +depends: +- __unix +- python +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 104631 +timestamp: 1779108494556 +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 +md5: b866ff7007b934d564961066c8195983 +depends: +- humanfriendly >=9.1 +- python >=3.9 +license: MIT +license_family: MIT +size: 43758 +timestamp: 1733928076798 +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +sha256: 59c9e29800b483b390467f90e82b0da3a4fbf0612efe1c90813fca232780e160 +md5: 071cf7b0ce333c81718b054066c15102 +depends: +- networkx >=2.0 +- numpy +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 39326 +timestamp: 1735759976140 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +noarch: generic +sha256: 777882d2685f368417f31bbe1b28f73687fc6c8f6a5768bda20ffeefa6b07f5b +md5: a749029ce5d0632a913db19d17f944ab +depends: +- python >=3.14,<3.15.0a0 +- python_abi * *_cp314 +license: Python-2.0 +size: 50212 +timestamp: 1779236682725 +- conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.8.1-hecca717_0.conda +sha256: 29a10599d56d93bd750914888ebe6822d47722070762b4647b34d12df9f4476e +md5: d0757fd84af06f065eba49d39af6c546 +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat 2.8.1 hecca717_0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 148238 +timestamp: 1779278694477 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.0-h27c8c51_0.conda +sha256: e798086d8a65d55dc4c51f5746705639c9a5f2eeb0b8fc50e6152cfc0d69a4e8 +md5: 06965b2f9854d0b15e0443ee81fe83dc +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat >=2.8.1,<3.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +- libgcc >=14 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 280882 +timestamp: 1779421631622 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 +md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 +depends: +- python >=3.10 +- hyperframe >=6.1,<7 +- hpack >=4.1,<5 +- python +license: MIT +license_family: MIT +size: 95967 +timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba +md5: 0a802cb9888dd14eeefc611f05c40b6e +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 30731 +timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d +md5: 7fe569c10905402ed47024fc481bb371 +depends: +- __unix +- python >=3.9 +license: MIT +license_family: MIT +size: 73563 +timestamp: 1733928021866 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +sha256: 6c4343b376d0b12a4c75ab992640970d36c933cad1fd924f6a1181fa91710e80 +md5: daddf757c3ecd6067b9af1df1f25d89e +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 67994 +timestamp: 1766267728652 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 +md5: 8e6923fc12f1fe8f8c4e5c9f343256ac +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 17397 +timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +sha256: 3d25f9f6f7ab3e1ce6429fc8c8aae0335cf446692e715068488536d220cc43de +md5: 1b9083b7f00609605d1483dbc6071a81 +depends: +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 62642 +timestamp: 1779294335905 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +sha256: 43e2a5497cad1598ff88a3e69f69bc88b7b8f141fa63c60eab5db296317318b8 +md5: ffc17e785d64e12fc311af9184221839 +depends: +- python >=3.10 +- zipp >=3.20 +- python +license: Apache-2.0 +size: 34766 +timestamp: 1779714582554 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b +md5: 04558c96691bed63104678757beb4f8d +depends: +- markupsafe >=2.0 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 120685 +timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 +md5: ada41c863af263cc4c5fcbaff7c3e4dc +depends: +- attrs >=22.2.0 +- jsonschema-specifications >=2023.3.6 +- python >=3.10 +- referencing >=0.28.4 +- rpds-py >=0.25.0 +- python +license: MIT +license_family: MIT +size: 82356 +timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 +md5: 439cd0f567d697b20a8f45cb70a1005a +depends: +- python >=3.10 +- referencing >=0.31.0 +- python +license: MIT +license_family: MIT +size: 19236 +timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/linux-64/kaleido-core-0.2.1-h3644ca4_0.tar.bz2 +sha256: 7f243680ca03eba7457b7a48f93a9440ba8181a8eac20a3eb5ef165ab6c96664 +md5: b3723b235b0758abaae8c82ce4d80146 +depends: +- __glibc >=2.17,<3.0.a0 +- expat >=2.2.10,<3.0.0a0 +- fontconfig +- fonts-conda-forge +- libgcc-ng >=9.3.0 +- mathjax 2.7.* +- nspr >=4.29,<5.0a0 +- nss >=3.62,<4.0a0 +- sqlite >=3.34.0,<4.0a0 +license: MIT +license_family: MIT +size: 62099926 +timestamp: 1615199463039 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_0.conda +sha256: eb89c6c39f2f6a93db55723dbb2f6bba8c8e63e6312bf1abf13e6e9ff45849c8 +md5: f92f984b558e6e6204014b16d212b271 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.4.1,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 251086 +timestamp: 1778079286384 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_102.conda +sha256: 3d584956604909ff5df353767f3a2a2f60e07d070b328d109f30ac40cd62df6c +md5: 18335a698559cdbcd86150a48bf54ba6 +depends: +- __glibc >=2.17,<3.0.a0 +- zstd >=1.5.7,<1.6.0a0 +constrains: +- binutils_impl_linux-64 2.45.1 +license: GPL-3.0-only +license_family: GPL +size: 728002 +timestamp: 1774197446916 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda +sha256: f84cb54782f7e9cea95e810ea8fef186e0652d0fa73d3009914fa2c1262594e1 +md5: a752488c68f2e7c456bcbd8f16eec275 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 261513 +timestamp: 1773113328888 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_h4a7cf45_openblas.conda +build_number: 7 +sha256: 081c850f99bc355821fac9c6e3727d40b3f8ce3beb50a5437cf03726b611ff39 +md5: 955b44e8b00b7f7ef4ce0130cef12394 +depends: +- libopenblas >=0.3.33,<0.3.34.0a0 +- libopenblas >=0.3.33,<1.0a0 +constrains: +- libcblas 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapack 3.11.0 7*_openblas +- liblapacke 3.11.0 7*_openblas +- mkl <2027 +license: BSD-3-Clause +license_family: BSD +size: 18716 +timestamp: 1778489854108 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h0358290_openblas.conda +build_number: 7 +sha256: 956ae0bb1ec8b0c3663d75b151aceb0521b54e513bf97f621a035f9c87037970 +md5: 0675639dc24cb0032f199e7ff68e4633 +depends: +- libblas 3.11.0 7_h4a7cf45_openblas +constrains: +- liblapacke 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapack 3.11.0 7*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18675 +timestamp: 1778489861559 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 +md5: 6c77a605a7a689d17d4819c0f8ac9a00 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 73490 +timestamp: 1761979956660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_0.conda +sha256: 363018b25fdb5534c79783d912bd4b685a3547f4fc5996357ad548899b0ee8e7 +md5: 93764a5ca80616e9c10106cdaec92f74 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- expat 2.8.1.* +license: MIT +license_family: MIT +size: 77294 +timestamp: 1779278686680 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 +md5: a360c33a5abe61c07959e449fa1453eb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 58592 +timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 +md5: e289f3d17880e44b633ba911d57a321b +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8049 +timestamp: 1774298163029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d +md5: fb16b4b69e3f1dcfe79d80db8fd0c55d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 384575 +timestamp: 1774298162622 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +sha256: 8e0a3b5e41272e5678499b5dfc4cddb673f9e935de01eb0767ce857001229f46 +md5: 57736f29cc2b0ec0b6c2952d3f101b6a +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_19 +- libgomp 15.2.0 he0feb66_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1041084 +timestamp: 1778269013026 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda +sha256: 9dcf54adfaa5e861123c2da4f2f0451a685464ea7e5a41ad91cf67b31d658d98 +md5: 331ee9b72b9dff570d56b1302c5ab37d +depends: +- libgcc 15.2.0 he0feb66_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27694 +timestamp: 1778269016987 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda +sha256: 561a42758ef25b9ce308c4e2cf56daee4f06138385a17e29a492cd928e00be6f +md5: 42bf7eca1a951735fa06c0e3c0d5c8e6 +depends: +- libgfortran5 15.2.0 h68bc16d_19 +constrains: +- libgfortran-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27655 +timestamp: 1778269042954 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda +sha256: 057978bb69fea29ed715a9b98adf71015c31baecc4aeb2bfc20d4fd5d83579d4 +md5: 85072b0ad177c966294f129b7c04a2d5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=15.2.0 +constrains: +- libgfortran 15.2.0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 2483673 +timestamp: 1778269025089 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +sha256: 5abe4ab9d93f6c9757d654f1969ae2267d4505315c1f2f8fe705fd60af084f1b +md5: faac990cb7aedc7f3a2224f2c9b0c26c +depends: +- __glibc >=2.17,<3.0.a0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 603817 +timestamp: 1778268942614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda +sha256: 10056646c28115b174de81a44e23e3a0a3b95b5347d2e6c45cc6d49d35294256 +md5: 6178c6f2fb254558238ef4e6c56fb782 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 633831 +timestamp: 1775962768273 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h47877c9_openblas.conda +build_number: 7 +sha256: 96962084921f197c9ad13fb7f8b324f2351d50ff3d8d962148751ad532f54a01 +md5: 6569b4f273740e25dc0dc7e3232c2a6c +depends: +- libblas 3.11.0 7_h4a7cf45_openblas +constrains: +- liblapacke 3.11.0 7*_openblas +- libcblas 3.11.0 7*_openblas +- blas 2.307 openblas +license: BSD-3-Clause +license_family: BSD +size: 18694 +timestamp: 1778489869038 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda +sha256: ec30e52a3c1bf7d0425380a189d209a52baa03f22fb66dd3eb587acaa765bd6d +md5: b88d90cad08e6bc8ad540cb310a761fb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- xz 5.8.3.* +license: 0BSD +size: 113478 +timestamp: 1775825492909 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_1.conda +sha256: fe171ed5cf5959993d43ff72de7596e8ac2853e9021dec0344e583734f1e0843 +md5: 2c21e66f50753a083cbe6b80f38268fa +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-2-Clause +license_family: BSD +size: 92400 +timestamp: 1769482286018 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda +sha256: 3d9aa85648e5e18a6d66db98b8c4317cc426721ad7a220aa86330d1ccedc8903 +md5: 2d3278b721e40468295ca755c3b84070 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libgfortran +- libgfortran5 >=14.3.0 +constrains: +- openblas >=0.3.33,<0.3.34.0a0 +license: BSD-3-Clause +license_family: BSD +size: 5931919 +timestamp: 1776993658641 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda +sha256: 377cfe037f3eeb3b1bf3ad333f724a64d32f315ee1958581fc671891d63d3f89 +md5: eba48a68a1a2b9d3c0d9511548db85db +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: zlib-acknowledgement +size: 317729 +timestamp: 1776315175087 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.1-h0c1763c_0.conda +sha256: 54cdcd3214313b62c2a8ee277e6f42150d9b748264c1b70d958bf735e420ef8d +md5: 7dc38adcbf71e6b38748e919e16e0dce +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: blessing +size: 954962 +timestamp: 1777986471789 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda +sha256: dff1058c76ec6b8759e41cefa2508162d00e4a5e6721aa68ec3fd10094e702dc +md5: 5794b3bdc38177caf969dabd3af08549 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc 15.2.0 he0feb66_19 +constrains: +- libstdcxx-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5852044 +timestamp: 1778269036376 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda +sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 +md5: cd5a90476766d53e901500df9215e927 +depends: +- __glibc >=2.17,<3.0.a0 +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 435273 +timestamp: 1762022005702 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.1-h5347b49_0.conda +sha256: 3f0edf1280e2f6684a986f821eaa3e123d2694a00b31b96ca0d4a4c12c129231 +md5: 7d0a66598195ef00b6efc55aefc7453b +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 40163 +timestamp: 1779118517630 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b +md5: aea31d2e5b1091feca96fcfe945c3cf9 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 429011 +timestamp: 1752159441324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa +md5: 92ed62436b625154323d40d5f2f11dd7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 395888 +timestamp: 1727278577118 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 +md5: d87ff7921124eccd67248aa483c23fec +depends: +- __glibc >=2.17,<3.0.a0 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 63629 +timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +sha256: 20e0892592a3e7c683e3d66df704a9425d731486a97c34fc56af4da1106b2b6b +md5: ba0a9221ce1063f31692c07370d062f3 +depends: +- importlib-metadata >=4.4 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 85893 +timestamp: 1770694658918 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +sha256: 0c4c35376fe920714390d46e4b8d31c876d65f18e1655899e0763ec25f2a902f +md5: 6d03368f2b2b0a5fb6839df53b2eb5e0 +depends: +- mdurl >=0.1,<1 +- python >=3.10 +license: MIT +license_family: MIT +size: 69017 +timestamp: 1778169663339 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py314h67df5f8_1.conda +sha256: c279be85b59a62d5c52f5dd9a4cd43ebd08933809a8416c22c3131595607d4cf +md5: 9a17c4307d23318476d7fbf0fedc0cde +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- jinja2 >=3.0.0 +license: BSD-3-Clause +license_family: BSD +size: 27424 +timestamp: 1772445227915 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mathjax-2.7.7-ha770c72_3.tar.bz2 +sha256: 02fef69bde69db264a12f21386612262f545b6e3e68d8f1ccec19f3eaae58edf +md5: 86e69bd82c2a2c6fd29f5ab7e02b3691 +license: Apache-2.0 +license_family: Apache +size: 22281629 +timestamp: 1662784498331 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 +md5: 592132998493b3ff25fd7479396e8351 +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 14465 +timestamp: 1733255681319 +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +sha256: e86033aa55a9e915e2d0957e770bdb81e3feb26a227d1adb17f9d6c528da6a71 +md5: cdb20309681ba3ce8f52c110e214d4f3 +depends: +- click +- coloredlogs +- humanize +- importlib-metadata +- jinja2 >=3.0.0 +- jsonschema +- markdown +- natsort +- numpy +- packaging +- pillow >=10.2.0 +- plotly >=5.18 +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 +- pyaml-env +- pydantic >=2.7.1 +- python >=3.9,!=3.14.1 +- python-dotenv +- python-kaleido 0.2.1 +- pyyaml >=4 +- requests +- rich >=10 +- rich-click +- spectra >=0.0.10 +- tiktoken +- tqdm +- typeguard >=4 +license: GPL-3.0-or-later +license_family: GPL3 +size: 4282188 +timestamp: 1779465338806 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +sha256: 70f43d62450927d51673eecd8823e14f5b3cfebdb43cda1d502eba97162bab42 +md5: 6687827c332121727ce383919e1ec8c2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 284323 +timestamp: 1778929680962 +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 +md5: e941e85e273121222580723010bd4fa2 +depends: +- python >=3.9 +- python +license: MIT +license_family: MIT +size: 39262 +timestamp: 1770905275632 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda +sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 +md5: fc21868a1a5aacc937e7a18747acb8a5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: X11 AND BSD-3-Clause +size: 918956 +timestamp: 1777422145199 +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 +md5: a2c1eeadae7a309daed9d62c96012a2b +depends: +- python >=3.11 +- python +constrains: +- numpy >=1.25 +- scipy >=1.11.2 +- matplotlib-base >=3.8 +- pandas >=2.0 +license: BSD-3-Clause +license_family: BSD +size: 1587439 +timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nspr-4.38-h29cc59b_0.conda +sha256: e3664264bd936c357523b55c71ed5a30263c6ba278d726a75b1eb112e6fb0b64 +md5: e235d5566c9cc8970eb2798dd4ecf62f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: MPL-2.0 +license_family: MOZILLA +size: 228588 +timestamp: 1762348634537 +- conda: https://conda.anaconda.org/conda-forge/linux-64/nss-3.118-h445c969_0.conda +sha256: 44dd98ffeac859d84a6dcba79a2096193a42fc10b29b28a5115687a680dd6aea +md5: 567fbeed956c200c1db5782a424e58ee +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libsqlite >=3.51.0,<4.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- nspr >=4.38,<5.0a0 +license: MPL-2.0 +license_family: MOZILLA +size: 2057773 +timestamp: 1763485556350 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.4.6-py314h2b28147_0.conda +sha256: bc61ae892973751a6b0e6ecea57ed6d7053224bddcb007165d6ceb1d7344ad47 +md5: f49b5f950379e0b97c35ca97682f7c6a +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- liblapack >=3.9.0,<4.0a0 +- python_abi 3.14.* *_cp314 +- libblas >=3.9.0,<4.0a0 +- libcblas >=3.9.0,<4.0a0 +constrains: +- numpy-base <0a0 +license: BSD-3-Clause +license_family: BSD +size: 8928909 +timestamp: 1779169198391 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda +sha256: 3900f9f2dbbf4129cf3ad6acf4e4b6f7101390b53843591c53b00f034343bc4d +md5: 11b3379b191f63139e29c0d19dee24cd +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.50,<1.7.0a0 +- libstdcxx >=14 +- libtiff >=4.7.1,<4.8.0a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-2-Clause +license_family: BSD +size: 355400 +timestamp: 1758489294972 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.2-h35e630c_0.conda +sha256: c0ef482280e38c71a08ad6d71448194b719630345b0c9c60744a2010e8a8e0cb +md5: da1b85b6a87e141f5140bb9924cecab0 +depends: +- __glibc >=2.17,<3.0.a0 +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3167099 +timestamp: 1775587756857 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 +md5: 4c06a92e74452cfa53623a81592e8934 +depends: +- python >=3.8 +- python +license: Apache-2.0 +license_family: APACHE +size: 91574 +timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.2.0-py314h8ec4b1a_0.conda +sha256: 123d8a7c16c88658b4f29e9f115a047598c941708dade74fbaff373a32dbec5e +md5: 76c4757c0ec9d11f969e8eb44899307b +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libtiff >=4.7.1,<4.8.0a0 +- openjpeg >=2.5.4,<3.0a0 +- libxcb >=1.17.0,<2.0a0 +- libwebp-base >=1.6.0,<2.0a0 +- zlib-ng >=2.3.3,<2.4.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- python_abi 3.14.* *_cp314 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +- lcms2 >=2.18,<3.0a0 +- tk >=8.6.13,<8.7.0a0 +license: HPND +size: 1082797 +timestamp: 1775060059882 +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 +md5: 3e9427ee186846052e81fadde8ebe96a +depends: +- narwhals >=1.15.1 +- packaging +- python >=3.10 +constrains: +- ipywidgets >=7.6 +license: MIT +license_family: MIT +size: 5251872 +timestamp: 1772628857717 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +sha256: 70fc56877c4a095ee658d61924d8019768fbae4a48437058d181fc94b0a7c4d8 +md5: 25a883fed9f1f3f21ff317a3e7c92ac4 +depends: +- polars-runtime-32 ==1.41.0 +- python >=3.10 +- python +constrains: +- numpy >=1.16.0 +- pyarrow >=7.0.0 +- fastexcel >=0.9 +- openpyxl >=3.0.0 +- xlsx2csv >=0.8.0 +- connectorx >=0.3.2 +- deltalake >=1.0.0 +- pyiceberg >=0.7.1 +- altair >=5.4.0 +- great_tables >=0.8.0 +- polars-runtime-32 ==1.41.0 +- polars-runtime-64 ==1.41.0 +- polars-runtime-compat ==1.41.0 +license: MIT +size: 539656 +timestamp: 1779630790562 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-32-1.41.0-py310h49dadd8_0.conda +noarch: python +sha256: e51ee3fe5259f2e115b2f78f8fbe3554e419c7c82b0c110878e12a5ff95ce3ab +md5: 7682765a1588e5ac887c99736d297c93 +depends: +- python +- __glibc >=2.17,<3.0.a0 +- libstdcxx >=14 +- libgcc >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +size: 42578921 +timestamp: 1779630790562 +- conda: https://conda.anaconda.org/conda-forge/linux-64/polars-runtime-compat-1.41.0-py310hcbd6021_0.conda +noarch: python +sha256: 29c3831c92394af11d9f7d04882dda9479ffbb76a3d36ba155d52159d67805fa +md5: cb0b620c9914a07a9022cb8b183ea9ee +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +size: 41864944 +timestamp: 1779630722548 +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d +md5: f2c23a77b25efcad57d377b34bd84941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 593603 +timestamp: 1769710381284 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 +md5: b3c17d95b5a10c6e64a21fa17573e70e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 8252 +timestamp: 1726802366959 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +sha256: 58994e0d2ea8584cb399546e6f6896d771995e6121d1a7b6a2c9948388358932 +md5: e17be1016bcc3516827b836cd3e4d9dc +depends: +- python >=3.9 +- pyyaml >=5.0,<=7.0 +license: MIT +license_family: MIT +size: 14645 +timestamp: 1736766960536 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +sha256: 69700e31165df070e9716315e042196aa92525dae5deb5107785847ab9f4189f +md5: 729843edafc0899b3348bd3f19525b9d +depends: +- typing-inspection >=0.4.2 +- typing_extensions >=4.14.1 +- python >=3.10 +- annotated-types >=0.6.0 +- pydantic-core ==2.46.4 +- python +license: MIT +license_family: MIT +size: 346511 +timestamp: 1778103405862 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pydantic-core-2.46.4-py314h2e6c369_0.conda +sha256: 802e216c39f1359aed60823b6e11d8ccd812b0ae1c81ae5ac1c81f99446409ab +md5: 0c96993dbeadf3a277cf757b9f1c9412 +depends: +- python +- typing-extensions >=4.6.0,!=4.7.0 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 1895020 +timestamp: 1778084229247 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 +md5: 16c18772b340887160c79a6acc022db0 +depends: +- python >=3.10 +license: BSD-2-Clause +license_family: BSD +size: 893031 +timestamp: 1774796815820 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 +md5: 461219d1a5bd61342293efa2c0c90eac +depends: +- __unix +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 21085 +timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.14.5-habeac84_100_cp314.conda +build_number: 100 +sha256: 55eed9bf2a3f6e90311276f0834737fe7c2d9ec3e5e2e557507858df4c7521e6 +md5: da92e59ff92f2d5ede4f612af20f583f +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- ld_impl_linux-64 >=2.36.1 +- libexpat >=2.8.0,<3.0a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- liblzma >=5.8.3,<6.0a0 +- libmpdec >=4.0.0,<5.0a0 +- libsqlite >=3.53.1,<4.0a0 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- openssl >=3.5.6,<4.0a0 +- python_abi 3.14.* *_cp314 +- readline >=8.3,<9.0a0 +- tk >=8.6.13,<8.7.0a0 +- tzdata +- zstd >=1.5.7,<1.6.0a0 +license: Python-2.0 +size: 36745188 +timestamp: 1779236923603 +python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 +md5: 130584ad9f3a513cdd71b1fdc1244e9c +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 27848 +timestamp: 1772388605021 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +sha256: 41dd7da285d71d519257fa7dacb1cae060d5ebfaa5f92cba5994899d2978e943 +md5: 41954747ba952ec4b01e16c2c9e8d8ff +depends: +- cpython 3.14.5.* +- python_abi * *_cp314 +license: Python-2.0 +size: 50212 +timestamp: 1779236703009 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 +md5: 310259a5b03ff02289d7705f39e2b1d2 +depends: +- kaleido-core 0.2.1.* +- python >=3.5 +license: MIT +license_family: MIT +size: 18320 +timestamp: 1615204747600 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +build_number: 8 +sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 +md5: 0539938c55b6b1a59b560e843ad864a4 +constrains: +- python 3.14.* *_cp314 +license: BSD-3-Clause +license_family: BSD +size: 6989 +timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py314h67df5f8_1.conda +sha256: b318fb070c7a1f89980ef124b80a0b5ccf3928143708a85e0053cde0169c699d +md5: 2035f68f96be30dc60a5dfd7452c7941 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- yaml >=0.2.5,<0.3.0a0 +license: MIT +license_family: MIT +size: 202391 +timestamp: 1770223462836 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda +sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 +md5: d7d95fc8287ea7bf33e0e7116d2b95ec +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-3.0-only +license_family: GPL +size: 345073 +timestamp: 1765813471974 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 +md5: 870293df500ca7e18bedefa5838a22ab +depends: +- attrs >=22.2.0 +- python >=3.10 +- rpds-py >=0.7.0 +- typing_extensions >=4.4.0 +- python +license: MIT +license_family: MIT +size: 51788 +timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2026.5.9-py314h5bd0f2a_0.conda +sha256: c7a4aca4977c15c82d053b06cbc676460974c1b25757cfeea8a9a2497ac911f8 +md5: 9dd235b6ac69a0198080dac39f9891aa +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +license: Apache-2.0 AND CNRI-Python +license_family: PSF +size: 413611 +timestamp: 1778374155646 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +sha256: 1715246b19c9f85ee022933b4845f2fc14ac9184981b7b7d9b728bec8e9588da +md5: 4a85203c1d80c1059086ae860836ffb9 +depends: +- python >=3.10 +- certifi >=2023.5.7 +- charset-normalizer >=2,<4 +- idna >=2.5,<4 +- urllib3 >=1.26,<3 +- python +constrains: +- chardet >=3.0.2,<8 +license: Apache-2.0 +license_family: APACHE +size: 68709 +timestamp: 1778851103479 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +sha256: 3d6ba2c0fcdac3196ba2f0615b4104e532525ffa1335b50a2878be5ff488814a +md5: 0242025a3c804966bf71aa04eee82f66 +depends: +- markdown-it-py >=2.2.0 +- pygments >=2.13.0,<3.0.0 +- python >=3.10 +- typing_extensions >=4.0.0,<5.0.0 +- python +license: MIT +license_family: MIT +size: 208577 +timestamp: 1775991661559 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 +md5: 0c20a8ebcddb24a45da89d5e917e6cb9 +depends: +- python >=3.10 +- rich >=12 +- click >=8 +- typing-extensions >=4 +- __unix +- python +license: MIT +license_family: MIT +size: 64356 +timestamp: 1769850479089 +- conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.30.0-py314h2e6c369_0.conda +sha256: e53b0cbf3b324eaa03ca1fe1a688fdf4ab42cea9c25270b0a7307d8aaaa4f446 +md5: c1c368b5437b0d1a68f372ccf01cb133 +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 376121 +timestamp: 1764543122774 +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +sha256: 7c65782d2511738e62c70462e89d65da4fa54d5a7e47c46667bcd27a59f81876 +md5: 472239e4eb7b5a84bb96b3ed7e3a596a +depends: +- colormath >=3.0.0 +- python >=3.9 +license: MIT +license_family: MIT +size: 22284 +timestamp: 1735770589188 +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.1-hbc0de68_0.conda +sha256: d167fa92781bcdcd3b9aaa6bb1cd50c5b108f6190c170098a118b5cf5df2f881 +md5: 8e0b8654ead18e50af552e54b5a08a61 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libsqlite 3.53.1 h0c1763c_0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- readline >=8.3,<9.0a0 +license: blessing +size: 205399 +timestamp: 1777986477546 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tiktoken-0.12.0-py314h67fec18_3.conda +sha256: 7e395d67fd249d901beb1ae269057763c0d8c3ee5f7a348694bdb16d158a37d9 +md5: d705f9d8a1185a2b01cced191177a028 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- regex >=2022.1.18 +- requests >=2.26.0 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 939648 +timestamp: 1764028306357 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda +sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac +md5: cffd3bdd58090148f4cfcd831f4b26ab +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +constrains: +- xorg-libx11 >=1.8.12,<2.0a0 +license: TCL +license_family: BSD +size: 3301196 +timestamp: 1769460227866 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 +md5: e5ce43272193b38c2e9037446c1d9206 +depends: +- python >=3.10 +- __unix +- python +license: MPL-2.0 and MIT +size: 94132 +timestamp: 1770153424136 +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +sha256: 59d7851d32fddb5b510272e6557aa982edeb927d349648dac27f5bf01d18bb26 +md5: 4460f039b7dedf15f7df086446ca75ae +depends: +- typing_extensions >=4.14.0 +- python >=3.10 +- importlib-metadata >=3.6 +- python +constrains: +- pytest >=7 +license: MIT +license_family: MIT +size: 38297 +timestamp: 1778779291237 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c +md5: edd329d7d3a4ab45dcf905899a7a6115 +depends: +- typing_extensions ==4.15.0 pyhcf101f3_0 +license: PSF-2.0 +license_family: PSF +size: 91383 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +sha256: 8b90d2f19f9458b8c58a55e1fcdc1d90c1603a847a47654d8a454549413ba60a +md5: 53f5409c5cfd6c5a66417d68e3f0a864 +depends: +- python >=3.10 +- typing_extensions >=4.12.0 +- python +license: MIT +license_family: MIT +size: 20935 +timestamp: 1777105465795 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 +md5: 0caa1af407ecff61170c9437a808404d +depends: +- python >=3.10 +- python +license: PSF-2.0 +license_family: PSF +size: 51692 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c +md5: ad659d0a2b3e47e38d829aa8cad2d610 +license: LicenseRef-Public-Domain +size: 119135 +timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 +md5: cbb88288f74dbe6ada1c6c7d0a97223e +depends: +- backports.zstd >=1.0.0 +- brotli-python >=1.2.0 +- h2 >=4,<5 +- pysocks >=1.5.6,<2.0,!=1.5.7 +- python >=3.10 +license: MIT +license_family: MIT +size: 103560 +timestamp: 1778188657149 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b +md5: b2895afaf55bf96a8c8282a2e47a5de0 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 15321 +timestamp: 1762976464266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 +md5: 1dafce8548e38671bea82e3f5c6ce22f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 20591 +timestamp: 1762976546182 +- conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda +sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad +md5: a77f85f77be52ff59391544bfe73390a +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +license: MIT +license_family: MIT +size: 85189 +timestamp: 1753484064210 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +sha256: 210bd31c22bb88f5e2a167df24c95bb5f152b2ada7502f9b8c49d1f5366db423 +md5: ba3dcdc8584155c97c648ae9c044b7a3 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 24190 +timestamp: 1779159948016 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-ng-2.3.3-hceb46e0_1.conda +sha256: ea4e50c465d70236408cb0bfe0115609fd14db1adcd8bd30d8918e0291f8a75f +md5: 2aadb0d17215603a82a2a6b0afd9a4cb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: Zlib +license_family: Other +size: 122618 +timestamp: 1770167931827 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda +sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 +md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 +depends: +- __glibc >=2.17,<3.0.a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 601375 +timestamp: 1764777111296 diff --git a/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt new file mode 100644 index 0000000..3d5b93d --- /dev/null +++ b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt @@ -0,0 +1,1476 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-aarch64: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.18.0-hba86a56_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.19.1-h9d5b58d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-7_haddc8a3_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-7_hd72aa62_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-7_h88aeb00_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.33-pthreads_h9d3fd7e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.1-h022381a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.6-py314he1698a1_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.2.0-py314hac3e5ec_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.41.0-py310h32c7c23_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.41.0-py310hc0e61be_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.46.4-py314h451b6cc_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.5-hfd9ac0a_100_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.5.9-py314h51f160d_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.1-he8854b5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +packages: +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda +build_number: 20 +sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 +md5: 468fd3bb9e1f671d36c2cbc677e56f1d +depends: +- libgomp >=7.5.0 +constrains: +- openmp_impl <0.0a0 +license: BSD-3-Clause +license_family: BSD +size: 28926 +timestamp: 1770939656741 +- conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda +sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 +md5: aaa2a381ccc56eac91d63b6c1240312f +depends: +- cpython +- python-gil +license: MIT +license_family: MIT +size: 8191 +timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda +sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 +md5: 2934f256a8acfe48f6ebb4fce6cde29c +depends: +- python >=3.9 +- typing-extensions >=4.0.0 +license: MIT +license_family: MIT +size: 18074 +timestamp: 1733247158254 +- conda: https://conda.anaconda.org/conda-forge/noarch/attrs-26.1.0-pyhcf101f3_0.conda +sha256: 1b6124230bb4e571b1b9401537ecff575b7b109cc3a21ee019f65e083b8399ab +md5: c6b0543676ecb1fb2d7643941fe375f2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 64927 +timestamp: 1773935801332 +- conda: https://conda.anaconda.org/conda-forge/noarch/backports.zstd-1.5.0-py314h680f03e_0.conda +noarch: generic +sha256: a1c97297e867776760489537bc5ae36fa83a154be30e3b79385a39ca4cb058fe +md5: 1133126d840e75287d83947be3fc3e71 +depends: +- python >=3.14 +license: BSD-3-Clause AND MIT AND EPL-2.0 +size: 7533 +timestamp: 1778594057496 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.2.0-py314h352cb57_1.conda +sha256: 5a5b0cdcd7ed89c6a8fb830924967f6314a2b71944bc1ebc2c105781ba97aa75 +md5: a1b5c571a0923a205d663d8678df4792 +depends: +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +constrains: +- libbrotlicommon 1.2.0 he30d5cf_1 +license: MIT +license_family: MIT +size: 373193 +timestamp: 1764017486851 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda +sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c +md5: 840d8fc0d7b3209be93080bc20e07f2d +depends: +- libgcc >=14 +license: bzip2-1.0.6 +license_family: BSD +size: 192412 +timestamp: 1771350241232 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.5.20-hbd8a1cb_0.conda +sha256: 9812a303a1395e1dafbd92e5bc8a1ff6013bcbba0a09c7f03a8d23e43560aa9b +md5: 489b8e97e666c93f68fdb35c3c9b957f +depends: +- __unix +license: ISC +size: 129868 +timestamp: 1779289852439 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.5.20-pyhd8ed1ab_0.conda +sha256: 645655a3510e38e625da136595f3f16f2130c3263630cc3bc8f60f619ddbe490 +md5: 9fefff2f745ea1cc2ef15211a20c054a +depends: +- python >=3.10 +license: ISC +size: 134201 +timestamp: 1779285131141 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.7-pyhd8ed1ab_0.conda +sha256: 3f9483d62ce24ecd063f8a5a714448445dc8d9e201147c46699fc0033e824457 +md5: a9167b9571f3baa9d448faa2139d1089 +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 58872 +timestamp: 1775127203018 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.4.0-pyhc90fa1f_0.conda +sha256: 99ab8ef815c4520cce3a7482c2513f377c14348206857661d84c76a55e030f97 +md5: 003767c47f1f0a474c4de268b57839c3 +depends: +- __unix +- python +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 104631 +timestamp: 1779108494556 +- conda: https://conda.anaconda.org/conda-forge/noarch/coloredlogs-15.0.1-pyhd8ed1ab_4.conda +sha256: 8021c76eeadbdd5784b881b165242db9449783e12ce26d6234060026fd6a8680 +md5: b866ff7007b934d564961066c8195983 +depends: +- humanfriendly >=9.1 +- python >=3.9 +license: MIT +license_family: MIT +size: 43758 +timestamp: 1733928076798 +- conda: https://conda.anaconda.org/conda-forge/noarch/colormath-3.0.0-pyhd8ed1ab_4.conda +sha256: 59c9e29800b483b390467f90e82b0da3a4fbf0612efe1c90813fca232780e160 +md5: 071cf7b0ce333c81718b054066c15102 +depends: +- networkx >=2.0 +- numpy +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 39326 +timestamp: 1735759976140 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.14.5-py314hd8ed1ab_100.conda +noarch: generic +sha256: 777882d2685f368417f31bbe1b28f73687fc6c8f6a5768bda20ffeefa6b07f5b +md5: a749029ce5d0632a913db19d17f944ab +depends: +- python >=3.14,<3.15.0a0 +- python_abi * *_cp314 +license: Python-2.0 +size: 50212 +timestamp: 1779236682725 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/expat-2.8.1-hfae3067_0.conda +sha256: a9cd5eb1700e11cc39acc36630a2d72a4e317943bd7c5695cd8804419f04ff42 +md5: 89f0247b3cea528d8ad1a6664a313153 +depends: +- libexpat 2.8.1 hfae3067_0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 140114 +timestamp: 1779278679081 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.18.0-hba86a56_0.conda +sha256: 1805f4ab3d9e1734a5a17abccc2cb0fdade51d4d5f29bdc410600ea0115ec050 +md5: b660d59a9d0fb3297327418624acaec3 +depends: +- libexpat >=2.8.1,<3.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +- libgcc >=14 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 293348 +timestamp: 1779421661332 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 +md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 +depends: +- python >=3.10 +- hyperframe >=6.1,<7 +- hpack >=4.1,<5 +- python +license: MIT +license_family: MIT +size: 95967 +timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda +sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba +md5: 0a802cb9888dd14eeefc611f05c40b6e +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 30731 +timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanfriendly-10.0-pyh707e725_8.conda +sha256: fa2071da7fab758c669e78227e6094f6b3608228740808a6de5d6bce83d9e52d +md5: 7fe569c10905402ed47024fc481bb371 +depends: +- __unix +- python >=3.9 +license: MIT +license_family: MIT +size: 73563 +timestamp: 1733928021866 +- conda: https://conda.anaconda.org/conda-forge/noarch/humanize-4.15.0-pyhd8ed1ab_0.conda +sha256: 6c4343b376d0b12a4c75ab992640970d36c933cad1fd924f6a1181fa91710e80 +md5: daddf757c3ecd6067b9af1df1f25d89e +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 67994 +timestamp: 1766267728652 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda +sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 +md5: 8e6923fc12f1fe8f8c4e5c9f343256ac +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 17397 +timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.15-pyhcf101f3_0.conda +sha256: 3d25f9f6f7ab3e1ce6429fc8c8aae0335cf446692e715068488536d220cc43de +md5: 1b9083b7f00609605d1483dbc6071a81 +depends: +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 62642 +timestamp: 1779294335905 +- conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-9.0.0-pyhcf101f3_0.conda +sha256: 43e2a5497cad1598ff88a3e69f69bc88b7b8f141fa63c60eab5db296317318b8 +md5: ffc17e785d64e12fc311af9184221839 +depends: +- python >=3.10 +- zipp >=3.20 +- python +license: Apache-2.0 +size: 34766 +timestamp: 1779714582554 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda +sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b +md5: 04558c96691bed63104678757beb4f8d +depends: +- markupsafe >=2.0 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 120685 +timestamp: 1764517220861 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.26.0-pyhcf101f3_0.conda +sha256: db973a37d75db8e19b5f44bbbdaead0c68dde745407f281e2a7fe4db74ec51d7 +md5: ada41c863af263cc4c5fcbaff7c3e4dc +depends: +- attrs >=22.2.0 +- jsonschema-specifications >=2023.3.6 +- python >=3.10 +- referencing >=0.28.4 +- rpds-py >=0.25.0 +- python +license: MIT +license_family: MIT +size: 82356 +timestamp: 1767839954256 +- conda: https://conda.anaconda.org/conda-forge/noarch/jsonschema-specifications-2025.9.1-pyhcf101f3_0.conda +sha256: 0a4f3b132f0faca10c89fdf3b60e15abb62ded6fa80aebfc007d05965192aa04 +md5: 439cd0f567d697b20a8f45cb70a1005a +depends: +- python >=3.10 +- referencing >=0.31.0 +- python +license: MIT +license_family: MIT +size: 19236 +timestamp: 1757335715225 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/kaleido-core-0.2.1-he5a581e_0.tar.bz2 +sha256: d3c7f4797566e6f983d16c2a87063a18e4b2d819a66230190a21584d70042755 +md5: 4f0d284f5d11e04277b552eb1c172c7f +depends: +- __glibc >=2.17,<3.0.a0 +- expat >=2.2.10,<3.0.0a0 +- fontconfig +- fonts-conda-forge +- libgcc-ng >=9.3.0 +- mathjax 2.7.* +- nspr >=4.29,<5.0a0 +- nss >=3.62,<4.0a0 +- sqlite >=3.34.0,<4.0a0 +license: MIT +license_family: MIT +size: 65750397 +timestamp: 1615199465742 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.19.1-h9d5b58d_0.conda +sha256: 1e5f68e4b36a0e1a278c6dc026bc3d7775518a15832cbc9d7fc1c0e4c47784b1 +md5: b1f8bee3c53a6d2c103fb4a1ae44f5c4 +depends: +- libgcc >=14 +- libjpeg-turbo >=3.1.4.1,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 296899 +timestamp: 1778079402392 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.45.1-default_h1979696_102.conda +sha256: 7abd913d81a9bf00abb699e8987966baa2065f5132e37e815f92d90fc6bba530 +md5: a21644fc4a83da26452a718dc9468d5f +depends: +- zstd >=1.5.7,<1.6.0a0 +constrains: +- binutils_impl_linux-aarch64 2.45.1 +license: GPL-3.0-only +license_family: GPL +size: 875596 +timestamp: 1774197520746 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda +sha256: 8957fd460c1c132c8031f65fd5f56ec3807fd71b7cab2c5e2b0937b13404ab36 +md5: d13423b06447113a90b5b1366d4da171 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Apache-2.0 +license_family: Apache +size: 240444 +timestamp: 1773114901155 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.11.0-7_haddc8a3_openblas.conda +build_number: 7 +sha256: f27ba323c2f1e1731b5e880fe520f178f55047f25be94f77e649605b2343c066 +md5: e8d07b777f6ff1fab69665336561910b +depends: +- libopenblas >=0.3.33,<0.3.34.0a0 +- libopenblas >=0.3.33,<1.0a0 +constrains: +- liblapack 3.11.0 7*_openblas +- libcblas 3.11.0 7*_openblas +- mkl <2027 +- blas 2.307 openblas +- liblapacke 3.11.0 7*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18696 +timestamp: 1778489796402 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.11.0-7_hd72aa62_openblas.conda +build_number: 7 +sha256: c8f0192362966df0828419f042d6f94c079e5df00ad6bd05b5e84c12b42f8cc7 +md5: 90ac57b82c055faa9be25031864b7d8f +depends: +- libblas 3.11.0 7_haddc8a3_openblas +constrains: +- liblapack 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapacke 3.11.0 7*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18664 +timestamp: 1778489802790 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda +sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 +md5: a9138815598fe6b91a1d6782ca657b0c +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 71117 +timestamp: 1761979776756 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.8.1-hfae3067_0.conda +sha256: 1fc392b997c6ee2bd3226a7cd870d0edbcbb367e25f9f18dd4a7025fced6efc0 +md5: 513dd884361dfb8a554298ed69b58823 +depends: +- libgcc >=14 +constrains: +- expat 2.8.1.* +license: MIT +license_family: MIT +size: 77140 +timestamp: 1779278671302 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda +sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 +md5: 2f364feefb6a7c00423e80dcb12db62a +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 55952 +timestamp: 1769456078358 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda +sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a +md5: a229e22d4d8814a07702b0919d8e6701 +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8125 +timestamp: 1774301094057 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda +sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c +md5: b99ed99e42dafb27889483b3098cace7 +depends: +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 422941 +timestamp: 1774301093473 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_19.conda +sha256: 4592b096e553f67799ae70d4b6167eeda3ec74587d68c7aecbf4e7b1df136681 +md5: f35b3f52d0a2ec4ffe3c89ba135cdb9a +depends: +- _openmp_mutex >=4.5 +constrains: +- libgomp 15.2.0 h8acb6b2_19 +- libgcc-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 622462 +timestamp: 1778268755949 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_19.conda +sha256: 1137f93f477f56199ded24117430045a0c02cbe8b10031beac3b9ad2138539d3 +md5: 770cf892e5530f43e63cadc673e85653 +depends: +- libgcc 15.2.0 h8acb6b2_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27738 +timestamp: 1778268759211 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-15.2.0-he9431aa_19.conda +sha256: e5ad94be72634233510b33ba792a3339921bd468f0b8bc6961ea05eded251d9b +md5: c7a5b5decf969ead5ecada83654164cf +depends: +- libgfortran5 15.2.0 h1b7bec0_19 +constrains: +- libgfortran-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27728 +timestamp: 1778268784621 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-15.2.0-h1b7bec0_19.conda +sha256: af8e9bdcaa77f133a8ee4c1ef57ef564d9c45aa262abf9f5ef9b50eb99d96407 +md5: 779dbb494de6d3d6477cab52eb34285a +depends: +- libgcc >=15.2.0 +constrains: +- libgfortran 15.2.0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1487244 +timestamp: 1778268767295 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_19.conda +sha256: 2370ef0ffcbae5bede3c4bf136add4abc257245eb91f724c99bb4a43116c5a83 +md5: c5e8a379c4a2ec2aea4ba22758c001d9 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 587387 +timestamp: 1778268674393 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.4.1-he30d5cf_0.conda +sha256: e97ec2af5f09f8f6ea8ecd550055c95ae80fae22015fcfadaa94eafe025c9ccc +md5: a85ba48648f6868016f2741fd9170250 +depends: +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 693143 +timestamp: 1775962625956 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.11.0-7_h88aeb00_openblas.conda +build_number: 7 +sha256: 20b38a0156200ac65f597bf0a93914c565435f2cc58b1042581854231a99ac35 +md5: 5899cbd743cc74fd655c1ed2af7120f3 +depends: +- libblas 3.11.0 7_haddc8a3_openblas +constrains: +- libcblas 3.11.0 7*_openblas +- blas 2.307 openblas +- liblapacke 3.11.0 7*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18685 +timestamp: 1778489809140 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.3-he30d5cf_0.conda +sha256: d61962b9cd54c3554361550203c64d5b65b71e3058a285b66e4b04b9769f0a5c +md5: 76298a9e6d71ee6e832a8d0d7373b261 +depends: +- libgcc >=14 +constrains: +- xz 5.8.3.* +license: 0BSD +size: 126102 +timestamp: 1775828008518 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libmpdec-4.0.0-he30d5cf_1.conda +sha256: 57c0dd12d506e84541c4e877898bd2a59cca141df493d34036f18b2751e0a453 +md5: 7b9813e885482e3ccb1fa212b86d7fd0 +depends: +- libgcc >=14 +license: BSD-2-Clause +license_family: BSD +size: 114056 +timestamp: 1769482343003 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.33-pthreads_h9d3fd7e_0.conda +sha256: b018ecfb05e75a8eea3f21f6b5c5c2a54b5178bdcf19e2e2df2735740214a8c8 +md5: 58a66cd95e9692f08abe89f55a6f3f12 +depends: +- libgcc >=14 +- libgfortran +- libgfortran5 >=14.3.0 +constrains: +- openblas >=0.3.33,<0.3.34.0a0 +license: BSD-3-Clause +license_family: BSD +size: 5121336 +timestamp: 1776993423004 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.58-h1abf092_0.conda +sha256: 483eaa53da40a6a3e558709d9f7b1ca388735364ae21a1ba58cf942514649c92 +md5: f51503ac45a4888bce71af9027a2ecc9 +depends: +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: zlib-acknowledgement +size: 341202 +timestamp: 1776315188425 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.53.1-h022381a_0.conda +sha256: ad03b7d8e4d08001f0df88ee7a56108bb35bae4795a42b9a04cc1abfa822bd07 +md5: 2ec1119217d8f0d086e9a62f3cb0e5ea +depends: +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: blessing +size: 955361 +timestamp: 1777986487553 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_19.conda +sha256: 1dadc45e599f510dd5f97141dddcdbb9844d9f1430c1f3a38075cf1c58f87b4e +md5: 543fbc8d71f2a0baf04cf88ce96cb8bb +depends: +- libgcc 15.2.0 h8acb6b2_19 +constrains: +- libstdcxx-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5546559 +timestamp: 1778268777463 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda +sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 +md5: 8c6fd84f9c87ac00636007c6131e457d +depends: +- lerc >=4.0.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- liblzma >=5.8.1,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 488407 +timestamp: 1762022048105 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.42.1-h1022ec0_0.conda +sha256: 1628839b062e98b2192857d4da8496ac9ac6b0dbb77aa040c34efc9192c440ee +md5: 0f42f9fedd2a32d798de95a7f65c456f +depends: +- libgcc >=14 +license: BSD-3-Clause +license_family: BSD +size: 43453 +timestamp: 1779118526838 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda +sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 +md5: 24e92d0942c799db387f5c9d7b81f1af +depends: +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 359496 +timestamp: 1752160685488 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda +sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b +md5: cd14ee5cca2464a425b1dbfc24d90db2 +depends: +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 397493 +timestamp: 1727280745441 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda +sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f +md5: 502006882cf5461adced436e410046d1 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 69833 +timestamp: 1774072605429 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.10.2-pyhcf101f3_0.conda +sha256: 20e0892592a3e7c683e3d66df704a9425d731486a97c34fc56af4da1106b2b6b +md5: ba0a9221ce1063f31692c07370d062f3 +depends: +- importlib-metadata >=4.4 +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 85893 +timestamp: 1770694658918 +- conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.2.0-pyhd8ed1ab_0.conda +sha256: 0c4c35376fe920714390d46e4b8d31c876d65f18e1655899e0763ec25f2a902f +md5: 6d03368f2b2b0a5fb6839df53b2eb5e0 +depends: +- mdurl >=0.1,<1 +- python >=3.10 +license: MIT +license_family: MIT +size: 69017 +timestamp: 1778169663339 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.3-py314hb76de3f_1.conda +sha256: 383c188496d13a55658c06e61e7d4cdff2c9f9d5a0648769fca8250bece7e0ef +md5: e5de3c36dd548b35ff2a8aa49208dcb3 +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +constrains: +- jinja2 >=3.0.0 +license: BSD-3-Clause +license_family: BSD +size: 27913 +timestamp: 1772446407659 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mathjax-2.7.7-h8af1aa0_3.tar.bz2 +sha256: 8fd4c79d6eda3d4cba73783114305a53a154ada4d1e334d4e02cb3521429599b +md5: 7b08314a6867a9d5648a1c3265e9eb8e +license: Apache-2.0 +license_family: Apache +size: 22257008 +timestamp: 1662784555011 +- conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_1.conda +sha256: 78c1bbe1723449c52b7a9df1af2ee5f005209f67e40b6e1d3c7619127c43b1c7 +md5: 592132998493b3ff25fd7479396e8351 +depends: +- python >=3.9 +license: MIT +license_family: MIT +size: 14465 +timestamp: 1733255681319 +- conda: https://conda.anaconda.org/bioconda/noarch/multiqc-1.35-pyhdfd78af_1.conda +sha256: e86033aa55a9e915e2d0957e770bdb81e3feb26a227d1adb17f9d6c528da6a71 +md5: cdb20309681ba3ce8f52c110e214d4f3 +depends: +- click +- coloredlogs +- humanize +- importlib-metadata +- jinja2 >=3.0.0 +- jsonschema +- markdown +- natsort +- numpy +- packaging +- pillow >=10.2.0 +- plotly >=5.18 +- polars >=1.34.0 +- polars-runtime-compat >=1.34.0 +- pyaml-env +- pydantic >=2.7.1 +- python >=3.9,!=3.14.1 +- python-dotenv +- python-kaleido 0.2.1 +- pyyaml >=4 +- requests +- rich >=10 +- rich-click +- spectra >=0.0.10 +- tiktoken +- tqdm +- typeguard >=4 +license: GPL-3.0-or-later +license_family: GPL3 +size: 4282188 +timestamp: 1779465338806 +- conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.21.2-pyhcf101f3_0.conda +sha256: 70f43d62450927d51673eecd8823e14f5b3cfebdb43cda1d502eba97162bab42 +md5: 6687827c332121727ce383919e1ec8c2 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 284323 +timestamp: 1778929680962 +- conda: https://conda.anaconda.org/conda-forge/noarch/natsort-8.4.0-pyhcf101f3_2.conda +sha256: aeb1548eb72e4f198e72f19d242fb695b35add2ac7b2c00e0d83687052867680 +md5: e941e85e273121222580723010bd4fa2 +depends: +- python >=3.9 +- python +license: MIT +license_family: MIT +size: 39262 +timestamp: 1770905275632 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.6-hf8d1292_0.conda +sha256: 369db85c5cd8d99dde364ce70725d76511d9c8199e5b820c740414091bf5bcca +md5: b2a43456aa56fe80c2477a5094899eff +depends: +- libgcc >=14 +license: X11 AND BSD-3-Clause +size: 960036 +timestamp: 1777422174534 +- conda: https://conda.anaconda.org/conda-forge/noarch/networkx-3.6.1-pyhcf101f3_0.conda +sha256: f6a82172afc50e54741f6f84527ef10424326611503c64e359e25a19a8e4c1c6 +md5: a2c1eeadae7a309daed9d62c96012a2b +depends: +- python >=3.11 +- python +constrains: +- numpy >=1.25 +- scipy >=1.11.2 +- matplotlib-base >=3.8 +- pandas >=2.0 +license: BSD-3-Clause +license_family: BSD +size: 1587439 +timestamp: 1765215107045 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nspr-4.38-h3ad9384_0.conda +sha256: 78a06e89285fef242e272998b292c1e621e3ee3dd4fba62ec014e503c7ec118f +md5: 6dd4f07147774bf720075a210f8026b9 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: MPL-2.0 +license_family: MOZILLA +size: 235140 +timestamp: 1762350120355 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nss-3.118-h544fa81_0.conda +sha256: 48942696889367ffd448f8dccfc080fb7e130b9938a4a3b6b20ef8e6af856463 +md5: 4540f9570d12db2150f42ba036154552 +depends: +- libgcc >=14 +- libsqlite >=3.51.0,<4.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- nspr >=4.38,<5.0a0 +license: MPL-2.0 +license_family: MOZILLA +size: 2061869 +timestamp: 1763490303490 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-2.4.6-py314he1698a1_0.conda +sha256: 04af718b911f8a3a0095481c7e283aa081a175fe626eccbc2c5644bcb2aba9a1 +md5: 8b173772deea177b45d2a133b509b3f7 +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- python_abi 3.14.* *_cp314 +- libblas >=3.9.0,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- libcblas >=3.9.0,<4.0a0 +constrains: +- numpy-base <0a0 +license: BSD-3-Clause +license_family: BSD +size: 8002900 +timestamp: 1779169206742 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjpeg-2.5.4-h5da879a_0.conda +sha256: bd1bc8bdde5e6c5cbac42d462b939694e40b59be6d0698f668515908640c77b8 +md5: cea962410e327262346d48d01f05936c +depends: +- libgcc >=14 +- libpng >=1.6.50,<1.7.0a0 +- libstdcxx >=14 +- libtiff >=4.7.1,<4.8.0a0 +- libzlib >=1.3.1,<2.0a0 +license: BSD-2-Clause +license_family: BSD +size: 392636 +timestamp: 1758489353577 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.2-h546c87b_0.conda +sha256: 348cb74c1530ac241215d047ef65d134cf797af935c97a68655319362b7e6a01 +md5: 3b129669089e4d6a5c6871dbb4669b99 +depends: +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3706406 +timestamp: 1775589602258 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 +md5: 4c06a92e74452cfa53623a81592e8934 +depends: +- python >=3.8 +- python +license: Apache-2.0 +license_family: APACHE +size: 91574 +timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pillow-12.2.0-py314hac3e5ec_0.conda +sha256: 96b26c2657275ffe84ab510edf0865e21999d791485d12794edd4a71b837beb6 +md5: 87d58d103b47c4a8567b3d7666647684 +depends: +- python +- libgcc >=14 +- python 3.14.* *_cp314 +- openjpeg >=2.5.4,<3.0a0 +- libxcb >=1.17.0,<2.0a0 +- libwebp-base >=1.6.0,<2.0a0 +- zlib-ng >=2.3.3,<2.4.0a0 +- python_abi 3.14.* *_cp314 +- lcms2 >=2.18,<3.0a0 +- tk >=8.6.13,<8.7.0a0 +- libtiff >=4.7.1,<4.8.0a0 +- libjpeg-turbo >=3.1.2,<4.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +license: HPND +size: 1062080 +timestamp: 1775060067775 +- conda: https://conda.anaconda.org/conda-forge/noarch/plotly-6.6.0-pyhd8ed1ab_0.conda +sha256: c418d325359fc7a0074cea7f081ef1bce26e114d2da8a0154c5d27ecc87a08e7 +md5: 3e9427ee186846052e81fadde8ebe96a +depends: +- narwhals >=1.15.1 +- packaging +- python >=3.10 +constrains: +- ipywidgets >=7.6 +license: MIT +license_family: MIT +size: 5251872 +timestamp: 1772628857717 +- conda: https://conda.anaconda.org/conda-forge/noarch/polars-1.41.0-pyh58ad624_0.conda +sha256: 70fc56877c4a095ee658d61924d8019768fbae4a48437058d181fc94b0a7c4d8 +md5: 25a883fed9f1f3f21ff317a3e7c92ac4 +depends: +- polars-runtime-32 ==1.41.0 +- python >=3.10 +- python +constrains: +- numpy >=1.16.0 +- pyarrow >=7.0.0 +- fastexcel >=0.9 +- openpyxl >=3.0.0 +- xlsx2csv >=0.8.0 +- connectorx >=0.3.2 +- deltalake >=1.0.0 +- pyiceberg >=0.7.1 +- altair >=5.4.0 +- great_tables >=0.8.0 +- polars-runtime-32 ==1.41.0 +- polars-runtime-64 ==1.41.0 +- polars-runtime-compat ==1.41.0 +license: MIT +size: 539656 +timestamp: 1779630790562 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-32-1.41.0-py310h32c7c23_0.conda +noarch: python +sha256: d903b774ec09189e164207328aac157eee82fed8cc5c9ace46aeb5d1c15cb5b3 +md5: 8c08c506ed1ea8ce0ca37af5e918c58d +depends: +- python +- libgcc >=14 +- libstdcxx >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +size: 38704429 +timestamp: 1779630794932 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/polars-runtime-compat-1.41.0-py310hc0e61be_0.conda +noarch: python +sha256: 101696adff43a654146376c62ef9611bf7946b95fa46f604fe247d77eefc6267 +md5: 65b73e4260677ee5162bdbb252e28e06 +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- _python_abi3_support 1.* +- cpython >=3.10 +constrains: +- __glibc >=2.17 +license: MIT +size: 38651498 +timestamp: 1779630714016 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda +sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 +md5: ab7288cc39545556d1bc5e71ab2df9a9 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-2.0-or-later AND LGPL-2.0-or-later +license_family: GPL +size: 636733 +timestamp: 1769712412683 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda +sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba +md5: bb5a90c93e3bac3d5690acf76b4a6386 +depends: +- libgcc >=13 +license: MIT +license_family: MIT +size: 8342 +timestamp: 1726803319942 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyaml-env-1.2.2-pyhd8ed1ab_0.conda +sha256: 58994e0d2ea8584cb399546e6f6896d771995e6121d1a7b6a2c9948388358932 +md5: e17be1016bcc3516827b836cd3e4d9dc +depends: +- python >=3.9 +- pyyaml >=5.0,<=7.0 +license: MIT +license_family: MIT +size: 14645 +timestamp: 1736766960536 +- conda: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.13.4-pyhcf101f3_0.conda +sha256: 69700e31165df070e9716315e042196aa92525dae5deb5107785847ab9f4189f +md5: 729843edafc0899b3348bd3f19525b9d +depends: +- typing-inspection >=0.4.2 +- typing_extensions >=4.14.1 +- python >=3.10 +- annotated-types >=0.6.0 +- pydantic-core ==2.46.4 +- python +license: MIT +license_family: MIT +size: 346511 +timestamp: 1778103405862 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pydantic-core-2.46.4-py314h451b6cc_0.conda +sha256: 1a7c6b18e404c13c4d959888ecb48a9ed9de0e41be2872932b83a35278088df0 +md5: 9c3ace6aba6df14b943256095ac1281e +depends: +- python +- typing-extensions >=4.6.0,!=4.7.0 +- libgcc >=14 +- python 3.14.* *_cp314 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 1780773 +timestamp: 1778084251775 +- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.20.0-pyhd8ed1ab_0.conda +sha256: cf70b2f5ad9ae472b71235e5c8a736c9316df3705746de419b59d442e8348e86 +md5: 16c18772b340887160c79a6acc022db0 +depends: +- python >=3.10 +license: BSD-2-Clause +license_family: BSD +size: 893031 +timestamp: 1774796815820 +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda +sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 +md5: 461219d1a5bd61342293efa2c0c90eac +depends: +- __unix +- python >=3.9 +license: BSD-3-Clause +license_family: BSD +size: 21085 +timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.14.5-hfd9ac0a_100_cp314.conda +build_number: 100 +sha256: d37bad5447365346166c72950ea8f49689aa49cecc1b0623d00458427627b8df +md5: d956e09feb806f5974675ce92ad81d45 +depends: +- bzip2 >=1.0.8,<2.0a0 +- ld_impl_linux-aarch64 >=2.36.1 +- libexpat >=2.8.0,<3.0a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- liblzma >=5.8.3,<6.0a0 +- libmpdec >=4.0.0,<5.0a0 +- libsqlite >=3.53.1,<4.0a0 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- openssl >=3.5.6,<4.0a0 +- python_abi 3.14.* *_cp314 +- readline >=8.3,<9.0a0 +- tk >=8.6.13,<8.7.0a0 +- tzdata +- zstd >=1.5.7,<1.6.0a0 +license: Python-2.0 +size: 37510439 +timestamp: 1779236267040 +python_site_packages_path: lib/python3.14/site-packages +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dotenv-1.2.2-pyhcf101f3_0.conda +sha256: 74e417a768f59f02a242c25e7db0aa796627b5bc8c818863b57786072aeb85e5 +md5: 130584ad9f3a513cdd71b1fdc1244e9c +depends: +- python >=3.10 +license: BSD-3-Clause +license_family: BSD +size: 27848 +timestamp: 1772388605021 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.5-h4df99d1_100.conda +sha256: 41dd7da285d71d519257fa7dacb1cae060d5ebfaa5f92cba5994899d2978e943 +md5: 41954747ba952ec4b01e16c2c9e8d8ff +depends: +- cpython 3.14.5.* +- python_abi * *_cp314 +license: Python-2.0 +size: 50212 +timestamp: 1779236703009 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-kaleido-0.2.1-pyhd8ed1ab_0.tar.bz2 +sha256: e17bf63a30aec33432f1ead86e15e9febde9fc40a7f869c0e766be8d2db44170 +md5: 310259a5b03ff02289d7705f39e2b1d2 +depends: +- kaleido-core 0.2.1.* +- python >=3.5 +license: MIT +license_family: MIT +size: 18320 +timestamp: 1615204747600 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda +build_number: 8 +sha256: ad6d2e9ac39751cc0529dd1566a26751a0bf2542adb0c232533d32e176e21db5 +md5: 0539938c55b6b1a59b560e843ad864a4 +constrains: +- python 3.14.* *_cp314 +license: BSD-3-Clause +license_family: BSD +size: 6989 +timestamp: 1752805904792 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyyaml-6.0.3-py314h807365f_1.conda +sha256: 496b5e65dfdd0aaaaa5de0dcaaf3bceea00fcb4398acf152f89e567c82ec1046 +md5: 9ae2c92975118058bd720e9ba2bb7c58 +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +- yaml >=0.2.5,<0.3.0a0 +license: MIT +license_family: MIT +size: 195678 +timestamp: 1770223441816 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.3-hb682ff5_0.conda +sha256: fe695f9d215e9a2e3dd0ca7f56435ab4df24f5504b83865e3d295df36e88d216 +md5: 3d49cad61f829f4f0e0611547a9cda12 +depends: +- libgcc >=14 +- ncurses >=6.5,<7.0a0 +license: GPL-3.0-only +license_family: GPL +size: 357597 +timestamp: 1765815673644 +- conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.37.0-pyhcf101f3_0.conda +sha256: 0577eedfb347ff94d0f2fa6c052c502989b028216996b45c7f21236f25864414 +md5: 870293df500ca7e18bedefa5838a22ab +depends: +- attrs >=22.2.0 +- python >=3.10 +- rpds-py >=0.7.0 +- typing_extensions >=4.4.0 +- python +license: MIT +license_family: MIT +size: 51788 +timestamp: 1760379115194 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/regex-2026.5.9-py314h51f160d_0.conda +sha256: 05ef55f09f31eabd0a205f6b065e13fc746675f41924620977692ef0ffe5aad8 +md5: 34ed7bc9febeca70f55b757ca09c354d +depends: +- libgcc >=14 +- python >=3.14,<3.15.0a0 +- python >=3.14,<3.15.0a0 *_cp314 +- python_abi 3.14.* *_cp314 +license: Apache-2.0 AND CNRI-Python +license_family: PSF +size: 409780 +timestamp: 1778374195988 +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +sha256: 1715246b19c9f85ee022933b4845f2fc14ac9184981b7b7d9b728bec8e9588da +md5: 4a85203c1d80c1059086ae860836ffb9 +depends: +- python >=3.10 +- certifi >=2023.5.7 +- charset-normalizer >=2,<4 +- idna >=2.5,<4 +- urllib3 >=1.26,<3 +- python +constrains: +- chardet >=3.0.2,<8 +license: Apache-2.0 +license_family: APACHE +size: 68709 +timestamp: 1778851103479 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda +sha256: 3d6ba2c0fcdac3196ba2f0615b4104e532525ffa1335b50a2878be5ff488814a +md5: 0242025a3c804966bf71aa04eee82f66 +depends: +- markdown-it-py >=2.2.0 +- pygments >=2.13.0,<3.0.0 +- python >=3.10 +- typing_extensions >=4.0.0,<5.0.0 +- python +license: MIT +license_family: MIT +size: 208577 +timestamp: 1775991661559 +- conda: https://conda.anaconda.org/conda-forge/noarch/rich-click-1.9.7-pyh8f84b5b_0.conda +sha256: aa3fcb167321bae51998de2e94d199109c9024f25a5a063cb1c28d8f1af33436 +md5: 0c20a8ebcddb24a45da89d5e917e6cb9 +depends: +- python >=3.10 +- rich >=12 +- click >=8 +- typing-extensions >=4 +- __unix +- python +license: MIT +license_family: MIT +size: 64356 +timestamp: 1769850479089 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rpds-py-0.30.0-py314h02b7a91_0.conda +sha256: a587240f16eac7c6a80f9585cef679cd1cb9a287b8dfcdd36dcef1f7e7db15dc +md5: e7f6ed9e60043bb5cbcc527764897f0d +depends: +- python +- libgcc >=14 +- python_abi 3.14.* *_cp314 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 376332 +timestamp: 1764543345455 +- conda: https://conda.anaconda.org/conda-forge/noarch/spectra-0.0.11-pyhd8ed1ab_2.conda +sha256: 7c65782d2511738e62c70462e89d65da4fa54d5a7e47c46667bcd27a59f81876 +md5: 472239e4eb7b5a84bb96b3ed7e3a596a +depends: +- colormath >=3.0.0 +- python >=3.9 +license: MIT +license_family: MIT +size: 22284 +timestamp: 1735770589188 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/sqlite-3.53.1-he8854b5_0.conda +sha256: 27467e4bfb0681546f149718c33b806fec078185fbaa6a4d17d440bc8f56185c +md5: 46009bdca2315a99e0a3a7d0ba1af3b9 +depends: +- libgcc >=14 +- libsqlite 3.53.1 h022381a_0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- readline >=8.3,<9.0a0 +license: blessing +size: 209964 +timestamp: 1777986493350 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tiktoken-0.12.0-py314h6a36e60_3.conda +sha256: c1da41c79262b27efa168407cfecc47b20270e5fc071a8307f95a2c85fb94170 +md5: 55bf7b559202236157b14323b40f19e6 +depends: +- libgcc >=14 +- libstdcxx >=14 +- python >=3.14,<3.15.0a0 +- python_abi 3.14.* *_cp314 +- regex >=2022.1.18 +- requests >=2.26.0 +constrains: +- __glibc >=2.17 +license: MIT +license_family: MIT +size: 914402 +timestamp: 1764030357702 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-noxft_h0dc03b3_103.conda +sha256: e25c314b52764219f842b41aea2c98a059f06437392268f09b03561e4f6e5309 +md5: 7fc6affb9b01e567d2ef1d05b84aa6ed +depends: +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +constrains: +- xorg-libx11 >=1.8.12,<2.0a0 +license: TCL +license_family: BSD +size: 3368666 +timestamp: 1769464148928 +- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda +sha256: 9ef8e47cf00e4d6dcc114eb32a1504cc18206300572ef14d76634ba29dfe1eb6 +md5: e5ce43272193b38c2e9037446c1d9206 +depends: +- python >=3.10 +- __unix +- python +license: MPL-2.0 and MIT +size: 94132 +timestamp: 1770153424136 +- conda: https://conda.anaconda.org/conda-forge/noarch/typeguard-4.5.2-pyhcf101f3_0.conda +sha256: 59d7851d32fddb5b510272e6557aa982edeb927d349648dac27f5bf01d18bb26 +md5: 4460f039b7dedf15f7df086446ca75ae +depends: +- typing_extensions >=4.14.0 +- python >=3.10 +- importlib-metadata >=3.6 +- python +constrains: +- pytest >=7 +license: MIT +license_family: MIT +size: 38297 +timestamp: 1778779291237 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda +sha256: 7c2df5721c742c2a47b2c8f960e718c930031663ac1174da67c1ed5999f7938c +md5: edd329d7d3a4ab45dcf905899a7a6115 +depends: +- typing_extensions ==4.15.0 pyhcf101f3_0 +license: PSF-2.0 +license_family: PSF +size: 91383 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing-inspection-0.4.2-pyhcf101f3_2.conda +sha256: 8b90d2f19f9458b8c58a55e1fcdc1d90c1603a847a47654d8a454549413ba60a +md5: 53f5409c5cfd6c5a66417d68e3f0a864 +depends: +- python >=3.10 +- typing_extensions >=4.12.0 +- python +license: MIT +license_family: MIT +size: 20935 +timestamp: 1777105465795 +- conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda +sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 +md5: 0caa1af407ecff61170c9437a808404d +depends: +- python >=3.10 +- python +license: PSF-2.0 +license_family: PSF +size: 51692 +timestamp: 1756220668932 +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda +sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c +md5: ad659d0a2b3e47e38d829aa8cad2d610 +license: LicenseRef-Public-Domain +size: 119135 +timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 +md5: cbb88288f74dbe6ada1c6c7d0a97223e +depends: +- backports.zstd >=1.0.0 +- brotli-python >=1.2.0 +- h2 >=4,<5 +- pysocks >=1.5.6,<2.0,!=1.5.7 +- python >=3.10 +license: MIT +license_family: MIT +size: 103560 +timestamp: 1778188657149 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda +sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 +md5: 1c246e1105000c3660558459e2fd6d43 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 16317 +timestamp: 1762977521691 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda +sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1 +md5: bff06dcde4a707339d66d45d96ceb2e2 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 21039 +timestamp: 1762979038025 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yaml-0.2.5-h80f16a2_3.conda +sha256: 66265e943f32ce02396ad214e27cb35f5b0490b3bd4f064446390f9d67fa5d88 +md5: 032d8030e4a24fe1f72c74423a46fb88 +depends: +- libgcc >=14 +license: MIT +license_family: MIT +size: 88088 +timestamp: 1753484092643 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-4.1.0-pyhcf101f3_0.conda +sha256: 210bd31c22bb88f5e2a167df24c95bb5f152b2ada7502f9b8c49d1f5366db423 +md5: ba3dcdc8584155c97c648ae9c044b7a3 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 24190 +timestamp: 1779159948016 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-ng-2.3.3-ha7cb516_1.conda +sha256: 638a3a41a4fbfed52d3c60c8ef5a3693b3f12a5b1a3f58fa29f5698d0a0702e2 +md5: f731af71c723065d91b4c01bb822641b +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Zlib +license_family: Other +size: 121046 +timestamp: 1770167944449 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda +sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 +md5: c3655f82dcea2aa179b291e7099c1fcc +depends: +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 614429 +timestamp: 1764777145593 diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index 37e7612..7a970e2 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.34 + - bioconda::multiqc=1.35 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index e80e8cd..c4bc715 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -4,8 +4,8 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data' - : 'community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6'}" + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' + : 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc'}" input: tuple val(meta), path(multiqc_files, stageAs: "?/*"), path(multiqc_config, stageAs: "?/*"), path(multiqc_logo), path(replace_names), path(sample_names) diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index 2facc62..27ce18d 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -110,24 +110,24 @@ maintainers: containers: conda: linux/amd64: - lock_file: modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt + lock_file: modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt linux/arm64: - lock_file: modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt + lock_file: modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt docker: linux/amd64: - name: community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6 - build_id: bd-db7c73dae76bc9e6_1 - scan_id: sc-66fc7138dbf1cf48_1 + name: community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc + build_id: bd-c17fb751507e9dfc_1 + scan_id: sc-3b1b3932f9846892_1 linux/arm64: - name: community.wave.seqera.io/library/multiqc:1.34--d167b8012595a136 - build_id: bd-d167b8012595a136_1 - scan_id: sc-ac701dfa631a2af9_1 + name: community.wave.seqera.io/library/multiqc:1.35--5c84a5000a226ab5 + build_id: bd-5c84a5000a226ab5_1 + scan_id: sc-0d39df41e9737bbd_1 singularity: linux/amd64: - name: oras://community.wave.seqera.io/library/multiqc:1.34--4fc8657c816047c0 - build_id: bd-4fc8657c816047c0_1 - https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data + name: oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2 + build_id: bd-c680f2aea25ccec2_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data linux/arm64: - name: oras://community.wave.seqera.io/library/multiqc:1.34--7fbd82d945c06726 - build_id: bd-7fbd82d945c06726_1 - https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/9a/9a1fec9662a152683e6fcae440d0ce20920b3b89dc62d1e3a52e73f92eba0969/data + name: oras://community.wave.seqera.io/library/multiqc:1.35--c0468833d65b2f81 + build_id: bd-c0468833d65b2f81_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e4/e48aa28aebc881254a499b24c3e1ce77b8df1b85a5432699ed6f72eb17ac7fb5/data diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index 7c2f370..4489921 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -81,7 +81,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } @@ -175,7 +175,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } @@ -221,7 +221,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } @@ -314,7 +314,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } @@ -408,7 +408,7 @@ [ "MULTIQC", "multiqc", - "1.34" + "1.35" ] ] } diff --git a/nextflow.config b/nextflow.config index 1b1ea2e..5c6d641 100644 --- a/nextflow.config +++ b/nextflow.config @@ -255,7 +255,7 @@ manifest { mainScript = 'main.nf' defaultBranch = 'main' nextflowVersion = '!>=25.10.4' - version = '1.0dev' + version = '1.0.0' doi = '' } diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 29e366a..9f28599 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -21,9 +21,9 @@ { "@id": "./", "@type": "Dataset", - "creativeWorkStatus": "InProgress", - "datePublished": "2026-07-24T12:35:36+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "creativeWorkStatus": "Stable", + "datePublished": "2026-09-01T12:58:22+00:00", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with 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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#48344b18-cfae-44a4-ad69-b23734224749" + "@id": "#46ef1a98-d6c6-4e65-914f-1d0afeab3aa8" } ], "name": "nf-core/datasync" @@ -128,7 +128,7 @@ } ], "dateCreated": "", - "dateModified": "2026-07-24T12:35:36Z", + "dateModified": "2026-09-01T12:58:22Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": ["nf-core", "nextflow"], "license": ["MIT"], @@ -139,8 +139,8 @@ "sdPublisher": { "@id": "https://nf-co.re/" }, - "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/dev/"], - "version": ["1.0dev"] + "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/1.0.0/"], + "version": ["1.0.0"] }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", @@ -155,11 +155,11 @@ "version": "!>=25.10.4" }, { - "@id": "#48344b18-cfae-44a4-ad69-b23734224749", + "@id": "#46ef1a98-d6c6-4e65-914f-1d0afeab3aa8", "@type": "TestSuite", "instance": [ { - "@id": "#867a3285-b1be-4cd0-8b71-8341c5d037f8" + "@id": "#7a5ce052-0c99-4239-9251-2c7352bf2a92" } ], "mainEntity": { @@ -168,7 +168,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#867a3285-b1be-4cd0-8b71-8341c5d037f8", + "@id": "#7a5ce052-0c99-4239-9251-2c7352bf2a92", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/nf-test.yml", diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index e9e92f3..8843f02 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -88,7 +88,8 @@ workflow PIPELINE_INITIALISATION { show_hidden, before_text, after_text, - command + command, + false ) // diff --git a/subworkflows/nf-core/utils_nfschema_plugin/main.nf b/subworkflows/nf-core/utils_nfschema_plugin/main.nf index 1df8b76..9ff0681 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/main.nf +++ b/subworkflows/nf-core/utils_nfschema_plugin/main.nf @@ -22,6 +22,7 @@ workflow UTILS_NFSCHEMA_PLUGIN { before_text // string: text to show before the help message and parameters summary after_text // string: text to show after the help message and parameters summary command // string: an example command of the pipeline + cli_typecast // boolean: whether to perform typecasting of CLI parameters. Set this to `null` to use the default behaviour main: @@ -34,11 +35,11 @@ workflow UTILS_NFSCHEMA_PLUGIN { fullHelp: help_full, ] if(parameters_schema) { - help_options << [parametersSchema: parameters_schema] + help_options << [parameters_schema: parameters_schema] } log.info paramsHelp( help_options, - (params.help instanceof String && params.help != "true") ? params.help : "", + (help instanceof String && help != "true") ? help : "", ) exit 0 } @@ -50,7 +51,7 @@ workflow UTILS_NFSCHEMA_PLUGIN { summary_options = [:] if(parameters_schema) { - summary_options << [parametersSchema: parameters_schema] + summary_options << [parameters_schema: parameters_schema] } log.info before_text log.info paramsSummaryLog(summary_options, input_workflow) @@ -63,7 +64,10 @@ workflow UTILS_NFSCHEMA_PLUGIN { if(validate_params) { validateOptions = [:] if(parameters_schema) { - validateOptions << [parametersSchema: parameters_schema] + validateOptions << [parameters_schema: parameters_schema] + } + if(cli_typecast != null) { + validateOptions << [cast_cli_params: cli_typecast] } validateParameters(validateOptions) } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/meta.yml b/subworkflows/nf-core/utils_nfschema_plugin/meta.yml index f7d9f02..1d8c75a 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/meta.yml +++ b/subworkflows/nf-core/utils_nfschema_plugin/meta.yml @@ -25,6 +25,30 @@ input: option. When this input is empty it will automatically use the configured schema or "${projectDir}/nextflow_schema.json" as default. The schema should not be given in this way for meta pipelines. + - help: + type: boolean, string + description: | + Show the help message and exit. When a parameter name is given, show the help message for that parameter instead of the general help message. + - help_full: + type: boolean + description: Show the full help message and exit. + - show_hidden: + type: boolean + description: Show hidden parameters in the help message. + - before_text: + type: string + description: Text to show before the parameters summary and help message. + - after_text: + type: string + description: Text to show after the parameters summary and help message. + - command: + type: string + description: An example command to run the pipeline, to show in the help message and the summary. + - cli_typecast: + type: boolean + description: | + Whether to apply typecasting to the parameters given via the CLI before validation. + Set this to `null` to use the default behavior. output: - dummy_emit: type: boolean diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test index c977917..1fd1eac 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test @@ -31,6 +31,7 @@ nextflow_workflow { input[6] = "" input[7] = "" input[8] = "" + input[9] = null """ } } @@ -63,6 +64,7 @@ nextflow_workflow { input[6] = "" input[7] = "" input[8] = "" + input[9] = null """ } } @@ -95,6 +97,7 @@ nextflow_workflow { input[6] = "" input[7] = "" input[8] = "" + input[9] = null """ } } @@ -127,6 +130,7 @@ nextflow_workflow { input[6] = "" input[7] = "" input[8] = "" + input[9] = null """ } } @@ -160,6 +164,7 @@ nextflow_workflow { input[6] = "Before" input[7] = "After" input[8] = "nextflow run test/test" + input[9] = null """ } } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config index f6537cc..fd71cb8 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.6.1" + id "nf-schema@2.7.2" } validation { diff --git a/tests/nextflow.config b/tests/nextflow.config index da48321..0d106d0 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -8,7 +8,8 @@ // Or any resources requirements params { modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' - pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/' + pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/datasync/' } -aws.client.anonymous = true // fixes S3 access issues on self-hosted runners +// Fixes S3 access issues on self-hosted runners +aws.client.anonymous = true From 2b98f3575d953b4aae1c12984e89980e65cbb2bc Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 1 Sep 2026 15:56:46 +0200 Subject: [PATCH 297/334] Apply literal match for rclone_coopy whn requested --- conf/modules.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/modules.config b/conf/modules.config index 9f1711f..6f699e9 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -51,7 +51,7 @@ process { base_args.add('--dry-run') } if (params.copy_matching_only) { - base_args.add("--include-from ${filter_file}") + base_args.add("--files-from ${filter_file}") } base_args.join(' ') } From 50b86cb1866a3feec391b8df9b4fae3ae59977a0 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 1 Sep 2026 20:51:33 +0200 Subject: [PATCH 298/334] Touch all output files to avoid losing error code --- modules/nf-core/rclone/check/main.nf | 12 ++++++++++-- modules/nf-core/rclone/checksum/main.nf | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/modules/nf-core/rclone/check/main.nf b/modules/nf-core/rclone/check/main.nf index 3b3d77e..b9223d3 100644 --- a/modules/nf-core/rclone/check/main.nf +++ b/modules/nf-core/rclone/check/main.nf @@ -30,6 +30,14 @@ process RCLONE_CHECK { def configArg = rclone_config ? "--config ${rclone_config}" : '' """ + touch \\ + ${prefix}.combined.txt \\ + ${prefix}.differ.txt \\ + ${prefix}.missing_on_dst.txt \\ + ${prefix}.missing_on_src.txt \\ + ${prefix}.match.txt \\ + ${prefix}.error.txt + rclone check ${configArg} \\ $args \\ --combined ${prefix}.combined.txt \\ @@ -40,8 +48,8 @@ process RCLONE_CHECK { --error ${prefix}.error.txt \\ --checkers $task.cpus \\ ${source} \\ - ${destination} \ - && echo 0 > ${prefix}.exit_code.txt \ + ${destination} \\ + && echo 0 > ${prefix}.exit_code.txt \\ || echo \$? > ${prefix}.exit_code.txt sort -k2 ${prefix}.combined.txt -o ${prefix}.combined.txt diff --git a/modules/nf-core/rclone/checksum/main.nf b/modules/nf-core/rclone/checksum/main.nf index 78a0533..0d97830 100644 --- a/modules/nf-core/rclone/checksum/main.nf +++ b/modules/nf-core/rclone/checksum/main.nf @@ -30,6 +30,14 @@ process RCLONE_CHECKSUM { def configArg = rclone_config ? "--config ${rclone_config}" : '' """ + touch \\ + ${prefix}.combined.txt \\ + ${prefix}.differ.txt \\ + ${prefix}.missing_on_dst.txt \\ + ${prefix}.missing_on_src.txt \\ + ${prefix}.match.txt \\ + ${prefix}.error.txt + rclone checksum ${configArg} \\ --copy-links \\ $args \\ @@ -42,8 +50,8 @@ process RCLONE_CHECKSUM { --checkers $task.cpus \\ $hash \\ $sumfile \\ - ${destination} \ - && echo 0 > ${prefix}.exit_code.txt \ + ${destination} \\ + && echo 0 > ${prefix}.exit_code.txt \\ || echo \$? > ${prefix}.exit_code.txt sort -k2 ${prefix}.combined.txt -o ${prefix}.combined.txt From 2a50d9be8719eabda9c92c143310fd2f0a707bb1 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 1 Sep 2026 21:30:51 +0200 Subject: [PATCH 299/334] Raise clear error message --- modules/nf-core/rclone/copy/main.nf | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/nf-core/rclone/copy/main.nf b/modules/nf-core/rclone/copy/main.nf index 8cb4eaa..fb99e85 100644 --- a/modules/nf-core/rclone/copy/main.nf +++ b/modules/nf-core/rclone/copy/main.nf @@ -30,9 +30,12 @@ process RCLONE_COPY { def http_url_arg = '' if (source_string ==~ /^https?:\/\/.*/) { - def matcher = (source_string =~ /^(https?:\/\/[^\/]+)(\/.*)$/) + def matcher = (source_string =~ /^(https?:\/\/[^\/]+)(\/.*)?$/) + if (!matcher.matches()) { + throw new IllegalArgumentException("Invalid HTTP(S) source '${source_string}' for sample '${meta.id}'.") + } http_url_arg = "--http-url '${matcher[0][1]}'" - rclone_source = ":http:${matcher[0][2].replaceFirst('^/', '')}" + rclone_source = ":http:${(matcher[0][2] ?: '/').replaceFirst('^/', '')}" } else { rclone_source = source_string.replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') } From 31cb76fd2cb5201dcedb2e3b014a779ce8b7f267 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 1 Sep 2026 22:14:30 +0200 Subject: [PATCH 300/334] Add local module to generate files_to_copy for rclone_copy --- modules/local/create_filter_list/main.nf | 18 ++++++++++++++ workflows/datasync.nf | 30 +++++++++++------------- 2 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 modules/local/create_filter_list/main.nf diff --git a/modules/local/create_filter_list/main.nf b/modules/local/create_filter_list/main.nf new file mode 100644 index 0000000..b82caed --- /dev/null +++ b/modules/local/create_filter_list/main.nf @@ -0,0 +1,18 @@ +process CREATE_FILTER_LIST { + tag "$meta.id" + + input: + tuple val(meta), val(common) + + output: + tuple val(meta), path('files_to_copy.txt') + + script: + def content = common.join('\n') + + """ + cat > files_to_copy.txt <<'EOF' +${content} +EOF + """ +} diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 31f7758..015006e 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -7,6 +7,7 @@ include { MULTIQC } from '../modules/nf-core/mu include { RCLONE_COPY } from '../modules/nf-core/rclone/copy/main' include { RCLONE_CHECK } from '../modules/nf-core/rclone/check/main' include { RCLONE_CHECKSUM } from '../modules/nf-core/rclone/checksum/main' +include { CREATE_FILTER_LIST } from '../modules/local/create_filter_list/main' include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' @@ -92,37 +93,34 @@ workflow DATASYNC { if(params.copy_matching_only) { // Compute expected group size per meta.id from the input ch_with_size = ch_checksum - .map { meta, _checksum, _hash, _source -> [ meta.subMap(meta.keySet() - 'check_format'), 1 ] } + .map { meta, _checksum, _hash, _source -> + [ meta.subMap(meta.keySet() - 'check_format'), 1 ] + } .groupTuple() .map { meta, ones -> tuple(meta, ones.size()) } - files_to_copy = RCLONE_CHECKSUM.out.match.map { + ch_files_to_copy = RCLONE_CHECKSUM.out.match + .map { meta, match -> [ meta.subMap(meta.keySet() - 'check_format'), match ] } .combine(ch_with_size, by: 0) - .map { meta, match, size -> tuple(groupKey(meta, size), match) } + .map { meta, match, size -> + tuple(groupKey(meta, size), match) + } .groupTuple() - .map{ meta, files -> + .map { meta, files -> def common = files .collect { file_to_copy -> file_to_copy.readLines() } .inject { a, b -> a.intersect(b) } - if (!common) { - return null - } - - def copy_files = java.nio.file.Files.createTempFile( - "${meta.id}_files_to_copy_", - ".txt" - ) - copy_files.text = common.join('\n') + '\n' - - tuple(meta, copy_files) + common ? tuple(meta, common) : null } .filter { it != null } + CREATE_FILTER_LIST(ch_files_to_copy) + ch_rclone_copy = ch_samplesheet.rclone - .join(files_to_copy) + .join(CREATE_FILTER_LIST.out) } else { ch_rclone_copy = ch_samplesheet.rclone.map { meta, source, destination -> [ meta, source, destination, [] ] } } From 18d85edb328406ce8f951d6bb1b0dc2c4edf83b3 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 1 Sep 2026 22:17:36 +0200 Subject: [PATCH 301/334] Update docs to accept only local and URI paths --- README.md | 4 ++-- assets/schema_input.json | 10 ++++++++-- docs/usage.md | 19 +++++++------------ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index d5b4495..1927806 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,11 @@ 3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and 4. produces detailed `rclone` status files and a consolidated MultiQC report. -Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. +Sources may be local paths, HTTP(S) URLs, or object-storage URIs. Destinations may be local paths or object-storage URIs such as Amazon S3, S3-compatible storage, or Azure Blob Storage; rclone's HTTP backend is read-only. The current tested use case for this pipeline is transfer between S3 buckets. -Pass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). +Pass an `rclone` configuration with `--rclone_config` whenever a source or destination URI needs credentials or provider settings. Samplesheet paths use local paths or standard URIs such as `s3://bucket/path`, not rclone's `remote:path` syntax. For non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). ![nf-core/datasync metro map](docs/images/datasync-metromap.png) diff --git a/assets/schema_input.json b/assets/schema_input.json index 424ec88..f4443ad 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -17,12 +17,18 @@ "input": { "type": "string", "pattern": "^\\S+$", - "errorMessage": "Input path must be provided and cannot contain spaces" + "not": { + "pattern": "^[a-zA-Z][a-zA-Z0-9_.+-]*:(?!//).*$" + }, + "errorMessage": "Input must be a local path or URI such as s3://bucket/path; rclone remote:path syntax is not supported" }, "output_path": { "type": "string", "pattern": "^\\S+$", - "errorMessage": "Output path for rclone copy must be provided and cannot contain spaces" + "not": { + "pattern": "^[a-zA-Z][a-zA-Z0-9_.+-]*:(?!//).*$" + }, + "errorMessage": "Output path must be a local path or URI such as s3://bucket/path; rclone remote:path syntax is not supported" }, "checksum_md5": { "type": "string", diff --git a/docs/usage.md b/docs/usage.md index 418adef..edd5f9d 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -23,8 +23,8 @@ Each row describes an independent transfer. The header names are fixed; columns | Column | Required | Description | | -------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `sample` | Yes | Unique identifier used in task labels and output report names. It must not contain whitespace. Use a unique value for each row to prevent published report files from colliding. | -| `input` | Yes | Source file or directory. This can be a local path, HTTP(S) URL, object-storage URL such as `s3://bucket/prefix`, or configured remote such as `source_s3:bucket/prefix` or `source_azure:container/prefix`. Whitespace is not allowed. | -| `output_path` | Yes | Destination directory understood by rclone, such as `/archive/runs`, `s3://bucket/prefix`, or a configured `remote:path`. Whitespace is not allowed. | +| `input` | Yes | Source file or directory. This can be a local path, HTTP(S) URL, or object-storage URI such as `s3://bucket/prefix`. Rclone-specific `remote:path` syntax is not accepted. Whitespace is not allowed. | +| `output_path` | Yes | Destination directory. Use a local path such as `/archive/runs` or an object-storage URI such as `s3://bucket/prefix`. Rclone-specific `remote:path` syntax is not accepted. Whitespace is not allowed. | | `checksum_md5` | One checksum column | Path or URL to an MD5 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using SHA-256 only. | | `checksum_sha` | One checksum column | Path or URL to a SHA-256 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using MD5 only. | @@ -45,7 +45,7 @@ Example samplesheet: sample,input,output_path,checksum_md5,checksum_sha run_001,/data/run_001,s3://archive/runs,/data/checksums/run_001_md5.tsv, reference,https://example.org/reference.fa,/data/references,,/data/checksums/reference_sha256.tsv -run_002,/data/run_002,archive:runs,/data/checksums/run_002_md5.tsv,/data/checksums/run_002_sha256.tsv +run_002,/data/run_002,s3://archive/runs,/data/checksums/run_002_md5.tsv,/data/checksums/run_002_sha256.tsv ``` For the `run_001` directory example, `/data/checksums/run_001_md5.tsv` could contain: @@ -70,17 +70,12 @@ An [example samplesheet](../assets/samplesheet.csv) is included in the repositor The file supplied with `--rclone_config` uses `rclone`'s INI-style format. -Each `[name]` section defines a remote, and samplesheet paths refer to it as `name:path`. The remote name is an arbitrary local label; it does not need to match the provider or bucket name. +Each `[name]` section defines an rclone remote used internally by the pipeline. Samplesheet paths must use local paths or standard URIs such as `s3://bucket/path`; `name:path` values are not accepted. For an `s3://` URI, configure the matching `[s3]` remote in the rclone configuration. > [!NOTE] > The pipeline's documented and tested configuration pattern is S3-to-S3 transfer. -One file may contain several sections, so other cloud-to-cloud transfers can define both providers in the same file, but provider-specific options should be taken from the relevant `rclone` documentation. This is an example using S3: - -```text -source_s3:incoming/run_001 -archive_azure:research-archive/run_001 -``` +One file may contain several sections for different providers, but samplesheet URIs select the remote that has the matching scheme name. Provider-specific options should be taken from the relevant `rclone` documentation. Create the file interactively where possible: @@ -112,9 +107,9 @@ secret_access_key = YOUR_SECRET_ACCESS_KEY region = eu-central-1 ``` -The corresponding input values could be `source_s3:incoming/run_001` and `institutional_s3:project/run_002`. Provider-specific settings vary: consult the [`rclone` S3 documentation](https://rclone.org/s3/) and your storage provider's endpoint, region, addressing-style, and credential documentation rather than copying example values unchanged. +Use `s3://bucket/path` for S3 sources and destinations in the samplesheet. The pipeline converts this to rclone's internal `s3:bucket/path` form, so ensure rclone has credentials and provider settings for the `[s3]` remote. Provider-specific settings vary: consult the [`rclone` S3 documentation](https://rclone.org/s3/) and your storage provider's endpoint, region, addressing-style, and credential documentation rather than copying example values unchanged. -The pipeline also accepts an `s3://bucket/path` source or destination. In that form, ensure credentials and provider settings are available to both Nextflow and `rclone` in the execution environment. A named remote such as `source_s3:bucket/path` makes the selected configuration section explicit and is preferable when a config file contains multiple S3 providers. +Because samplesheet paths use URI schemes rather than rclone remote names, a single samplesheet cannot select multiple differently configured S3 remotes. Use one `[s3]` configuration for the run, or run separate transfers when providers require different rclone configurations. ## SHA256 checksum verification for remote inputs From 33bd607ccd93c1ae401b5a390857c8749a41ac35 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 2 Sep 2026 17:48:19 +0200 Subject: [PATCH 302/334] Add normalization for http paths in rclone check and checksum --- modules/nf-core/rclone/check/main.nf | 16 +++++++++++++++- modules/nf-core/rclone/checksum/main.nf | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/modules/nf-core/rclone/check/main.nf b/modules/nf-core/rclone/check/main.nf index b9223d3..e913b29 100644 --- a/modules/nf-core/rclone/check/main.nf +++ b/modules/nf-core/rclone/check/main.nf @@ -29,6 +29,19 @@ process RCLONE_CHECK { prefix = task.ext.prefix ?: "${meta.id}" def configArg = rclone_config ? "--config ${rclone_config}" : '' + def sourceString = source.toString() + def normalizedSource = sourceString.replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') + def sourceHttpUrlArg = '' + + if (sourceString ==~ /^https?:\/\/.*/) { + def sourceMatcher = (sourceString =~ /^(https?:\/\/[^\/]+)(\/.*)?$/) + if (!sourceMatcher.matches()) { + throw new IllegalArgumentException("Invalid HTTP(S) source '${sourceString}' for sample '${meta.id}'.") + } + sourceHttpUrlArg = "--http-url '${sourceMatcher[0][1]}'" + normalizedSource = ":http:${(sourceMatcher[0][2] ?: '/').replaceFirst('^/', '')}" + } + """ touch \\ ${prefix}.combined.txt \\ @@ -39,6 +52,7 @@ process RCLONE_CHECK { ${prefix}.error.txt rclone check ${configArg} \\ + ${sourceHttpUrlArg} \\ $args \\ --combined ${prefix}.combined.txt \\ --differ ${prefix}.differ.txt \\ @@ -47,7 +61,7 @@ process RCLONE_CHECK { --match ${prefix}.match.txt \\ --error ${prefix}.error.txt \\ --checkers $task.cpus \\ - ${source} \\ + "${normalizedSource}" \\ ${destination} \\ && echo 0 > ${prefix}.exit_code.txt \\ || echo \$? > ${prefix}.exit_code.txt diff --git a/modules/nf-core/rclone/checksum/main.nf b/modules/nf-core/rclone/checksum/main.nf index 0d97830..3b43e5e 100644 --- a/modules/nf-core/rclone/checksum/main.nf +++ b/modules/nf-core/rclone/checksum/main.nf @@ -29,6 +29,19 @@ process RCLONE_CHECKSUM { prefix = task.ext.prefix ?: "${meta.id}" def configArg = rclone_config ? "--config ${rclone_config}" : '' + def destinationString = destination.toString() + def normalizedDestination = destinationString.replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') + def destinationHttpUrlArg = '' + + if (destinationString ==~ /^https?:\/\/.*/) { + def destinationMatcher = (destinationString =~ /^(https?:\/\/[^\/]+)(\/.*)?$/) + if (!destinationMatcher.matches()) { + throw new IllegalArgumentException("Invalid HTTP(S) destination '${destinationString}' for sample '${meta.id}'.") + } + destinationHttpUrlArg = "--http-url '${destinationMatcher[0][1]}'" + normalizedDestination = ":http:${(destinationMatcher[0][2] ?: '/').replaceFirst('^/', '')}" + } + """ touch \\ ${prefix}.combined.txt \\ @@ -40,6 +53,7 @@ process RCLONE_CHECKSUM { rclone checksum ${configArg} \\ --copy-links \\ + ${destinationHttpUrlArg} \\ $args \\ --combined ${prefix}.combined.txt \\ --differ ${prefix}.differ.txt \\ @@ -50,7 +64,7 @@ process RCLONE_CHECKSUM { --checkers $task.cpus \\ $hash \\ $sumfile \\ - ${destination} \\ + "${normalizedDestination}" \\ && echo 0 > ${prefix}.exit_code.txt \\ || echo \$? > ${prefix}.exit_code.txt From 78bcc98a9dbef2aff11aa68a36ec156fa87af92a Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 2 Sep 2026 16:15:12 +0000 Subject: [PATCH 303/334] Do not accept `http` paths as source or destination paths --- README.md | 4 ++-- assets/schema_input.json | 34 ++++++++++++++++++++++++++-------- docs/usage.md | 8 +++++--- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1927806..0dcd130 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ 3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and 4. produces detailed `rclone` status files and a consolidated MultiQC report. -Sources may be local paths, HTTP(S) URLs, or object-storage URIs. Destinations may be local paths or object-storage URIs such as Amazon S3, S3-compatible storage, or Azure Blob Storage; rclone's HTTP backend is read-only. +Sources and destinations may be local paths or object-storage URIs such as Amazon S3, S3-compatible storage, or Azure Blob Storage. HTTP(S) URLs are not currently supported for samplesheet `input` or `output_path` values. The current tested use case for this pipeline is transfer between S3 buckets. @@ -58,7 +58,7 @@ To run the pipeline on your own data, create a samplesheet containing one transf ```csv sample,input,output_path,checksum_md5,checksum_sha run_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv -reference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv +reference,/data/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv ``` Then launch the pipeline using: diff --git a/assets/schema_input.json b/assets/schema_input.json index f4443ad..6d286fd 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -17,18 +17,36 @@ "input": { "type": "string", "pattern": "^\\S+$", - "not": { - "pattern": "^[a-zA-Z][a-zA-Z0-9_.+-]*:(?!//).*$" - }, - "errorMessage": "Input must be a local path or URI such as s3://bucket/path; rclone remote:path syntax is not supported" + "allOf": [ + { + "not": { + "pattern": "^[a-zA-Z][a-zA-Z0-9_.+-]*:(?!//).*$" + } + }, + { + "not": { + "pattern": "^https?://.*$" + } + } + ], + "errorMessage": "Input must be a local path or object-storage URI such as s3://bucket/path; HTTP(S) URLs and rclone remote:path syntax are not supported" }, "output_path": { "type": "string", "pattern": "^\\S+$", - "not": { - "pattern": "^[a-zA-Z][a-zA-Z0-9_.+-]*:(?!//).*$" - }, - "errorMessage": "Output path must be a local path or URI such as s3://bucket/path; rclone remote:path syntax is not supported" + "allOf": [ + { + "not": { + "pattern": "^[a-zA-Z][a-zA-Z0-9_.+-]*:(?!//).*$" + } + }, + { + "not": { + "pattern": "^https?://.*$" + } + } + ], + "errorMessage": "Output path must be a local path or object-storage URI such as s3://bucket/path; HTTP(S) URLs and rclone remote:path syntax are not supported" }, "checksum_md5": { "type": "string", diff --git a/docs/usage.md b/docs/usage.md index edd5f9d..a9620b2 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -23,11 +23,13 @@ Each row describes an independent transfer. The header names are fixed; columns | Column | Required | Description | | -------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `sample` | Yes | Unique identifier used in task labels and output report names. It must not contain whitespace. Use a unique value for each row to prevent published report files from colliding. | -| `input` | Yes | Source file or directory. This can be a local path, HTTP(S) URL, or object-storage URI such as `s3://bucket/prefix`. Rclone-specific `remote:path` syntax is not accepted. Whitespace is not allowed. | -| `output_path` | Yes | Destination directory. Use a local path such as `/archive/runs` or an object-storage URI such as `s3://bucket/prefix`. Rclone-specific `remote:path` syntax is not accepted. Whitespace is not allowed. | +| `input` | Yes | Source file or directory. Use a local path or object-storage URI such as `s3://bucket/prefix`. HTTP(S) URLs and rclone-specific `remote:path` syntax are not supported. Whitespace is not allowed. | +| `output_path` | Yes | Destination directory. Use a local path such as `/archive/runs` or an object-storage URI such as `s3://bucket/prefix`. HTTP(S) URLs and rclone-specific `remote:path` syntax are not supported. Whitespace is not allowed. | | `checksum_md5` | One checksum column | Path or URL to an MD5 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using SHA-256 only. | | `checksum_sha` | One checksum column | Path or URL to a SHA-256 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using MD5 only. | +HTTP(S) URLs are not currently supported for `input` or `output_path`. The pipeline validates checksum manifests before copying and verifies the copied content afterwards; HTTP checksum behavior is not yet defined and tested for this workflow. Download HTTP-hosted data locally before including it in a samplesheet. + At least one checksum manifest is required on every row. If both are supplied, both validations run. Checksum files must use the format accepted by [`rclone checksum`](https://rclone.org/commands/rclone_checksum/): one checksum record per line with the hash value followed by two spaces and then the file path. Paths must be relative to the source root from the `input` column, not absolute paths. For a directory input, the source root is the directory named in the samplesheet. For example, if the samplesheet `input` is `/data/run_001` and one file in that directory is `/data/run_001/reads/sample_R1.fastq.gz`, the checksum manifest path must be `reads/sample_R1.fastq.gz`. Do not write `/data/run_001/reads/sample_R1.fastq.gz` in the manifest. For a single-file input, use the input file name as the manifest path. @@ -44,7 +46,7 @@ Example samplesheet: ```csv title="samplesheet.csv" sample,input,output_path,checksum_md5,checksum_sha run_001,/data/run_001,s3://archive/runs,/data/checksums/run_001_md5.tsv, -reference,https://example.org/reference.fa,/data/references,,/data/checksums/reference_sha256.tsv +reference,/data/reference.fa,/data/references,,/data/checksums/reference_sha256.tsv run_002,/data/run_002,s3://archive/runs,/data/checksums/run_002_md5.tsv,/data/checksums/run_002_sha256.tsv ``` From 5a945afb8a29e3f72cf28de05ab78f78249eecfb Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 2 Sep 2026 16:17:25 +0000 Subject: [PATCH 304/334] Normalize input and destination paths --- workflows/datasync.nf | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 015006e..63ab937 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -40,19 +40,20 @@ workflow DATASYNC { ch_samplesheet = ch_samplesheet.multiMap { meta, input_path, output_path, md5, sha -> - def source = file(input_path) + def normalized_input_path = input_path.toString().replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') + def normalized_output_path = output_path.toString().replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') - def source_uri = source.toUriString() + def source = file(input_path) def rclone_destination = source.isFile() - ? output_path.toString().replaceAll('/+$', '') - : "${output_path.toString().replaceAll('/+$', '')}/${source.name}" + ? normalized_output_path.replaceAll('/+$', '') + : "${normalized_output_path.replaceAll('/+$', '')}/${source.name}" def rclone_check = source.isFile() - ? input_path.replaceFirst('/[^/]+$', '') - : input_path.toString().replaceAll('/+$', '') + ? normalized_input_path.replaceFirst('/[^/]+$', '') + : normalized_input_path.replaceAll('/+$', '') - rclone: [ meta, source_uri, rclone_destination ] + rclone: [ meta, normalized_input_path, rclone_destination ] checksum: [ meta, md5, sha, rclone_check ] } From 2088f3fa84bdd6339b096c57c17712577d8624a3 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 2 Sep 2026 18:42:23 +0200 Subject: [PATCH 305/334] Update snapshots --- tests/default.nf.test.snap | 14 +++++++++---- tests/edge.nf.test.snap | 38 +++++++++++++++++++++++++++--------- tests/main_full.nf.test.snap | 12 ++++++++---- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index a7a2cd2..b546a15 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -9,7 +9,7 @@ "rclone": "1.74.3-DEV" }, "RCLONE_COPY": { - "rclone": "1.65.0-DEV" + "rclone": "1.74.3-DEV" }, "Workflow": { "nf-core/datasync": "v1.0.0" @@ -36,13 +36,16 @@ "rclone/check", "rclone/check/Illumina_annotation", "rclone/check/Illumina_annotation/Illumina_annotation_check.combined.txt", + "rclone/check/Illumina_annotation/Illumina_annotation_check.exit_code.txt", "rclone/check/Illumina_annotation/Illumina_annotation_check.match.txt", "rclone/check/benchmark_bed", "rclone/check/benchmark_bed/benchmark_bed_check.combined.txt", + "rclone/check/benchmark_bed/benchmark_bed_check.exit_code.txt", "rclone/check/benchmark_bed/benchmark_bed_check.match.txt", "rclone/checksum", "rclone/checksum/Illumina_annotation", "rclone/checksum/Illumina_annotation/Illumina_annotation_checksum_MD5.combined.txt", + "rclone/checksum/Illumina_annotation/Illumina_annotation_checksum_MD5.exit_code.txt", "rclone/checksum/Illumina_annotation/Illumina_annotation_checksum_MD5.match.txt", "rclone/checksum/benchmark_bed", "rclone/checksum/benchmark_bed/benchmark_bed_checksum_MD5.combined.txt", @@ -57,13 +60,16 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", "multiqc_rclone_checksum_md5.txt:md5,c7127de966d1be295ef6697dba648c79", - "multiqc_rclone_exit_codes.txt:md5,f50e1acf7abee71274f0f92508576cb1", + "multiqc_rclone_exit_codes.txt:md5,d970d9335584ff1e7349036e62f5e8d4", "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4", "Illumina_annotation_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "Illumina_annotation_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", "benchmark_bed_check.combined.txt:md5,dcd2c539696adba720986251dcd1aaef", + "benchmark_bed_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "benchmark_bed_check.match.txt:md5,12608858576bec12c65ff338a99803c3", "Illumina_annotation_checksum_MD5.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_checksum_MD5.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "Illumina_annotation_checksum_MD5.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", "benchmark_bed_checksum_MD5.combined.txt:md5,592b2b2af44551686a8057f585309413", "benchmark_bed_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", @@ -71,10 +77,10 @@ "benchmark_bed_checksum_MD5.missing_on_src.txt:md5,7bf2def3eed9eff615a0f29ae1652254" ] ], - "timestamp": "2026-08-18T14:12:12.191208475", + "timestamp": "2026-09-02T18:25:59.629051707", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index 66deaa7..76b160e 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -9,13 +9,15 @@ "rclone": "1.74.3-DEV" }, "RCLONE_COPY": { - "rclone": "1.65.0-DEV" + "rclone": "1.74.3-DEV" }, "Workflow": { "nf-core/datasync": "v1.0.0" } }, [ + "create", + "create/files_to_copy.txt", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", @@ -37,10 +39,16 @@ "rclone/check", "rclone/check/Illumina_annotation_incorrect", "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt", "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt", "rclone/check/Illumina_annotation_missing", "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt", "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt", + "rclone/check/Illumina_annotation_sha_only", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt", "rclone/checksum", "rclone/checksum/Illumina_annotation_incorrect", "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt", @@ -62,16 +70,22 @@ "rclone/copy/Illumina_annotation_missing-rclone-copy.log" ], [ + "files_to_copy.txt:md5,df576e44dfe5a24521997ef162cba157", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_rclone_check.txt:md5,4b2a6990836593f69e8e81a82c3daf42", + "multiqc_rclone_check.txt:md5,c8f13c10aa4f0e4b356c5c08a9ae7ee9", "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", - "multiqc_rclone_exit_codes.txt:md5,e72c745debdc6ed04aa9b13b068d897c", + "multiqc_rclone_exit_codes.txt:md5,3dd8d4741882ff589545c2f2fcc99520", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_incorrect_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", "Illumina_annotation_missing_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_missing_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "Illumina_annotation_missing_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_sha_only_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "Illumina_annotation_sha_only_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", "Illumina_annotation_incorrect_checksum_MD5.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", "Illumina_annotation_incorrect_checksum_MD5.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", "Illumina_annotation_incorrect_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", @@ -86,10 +100,10 @@ "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-18T14:13:27.670540243", + "timestamp": "2026-09-02T18:26:55.720186858", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } }, "-profile test edge cases": { @@ -102,7 +116,7 @@ "rclone": "1.74.3-DEV" }, "RCLONE_COPY": { - "rclone": "1.65.0-DEV" + "rclone": "1.74.3-DEV" }, "Workflow": { "nf-core/datasync": "v1.0.0" @@ -130,12 +144,15 @@ "rclone/check", "rclone/check/Illumina_annotation_incorrect", "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt", "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt", "rclone/check/Illumina_annotation_missing", "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt", "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt", "rclone/check/Illumina_annotation_sha_only", "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt", "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt", "rclone/checksum", "rclone/checksum/Illumina_annotation_incorrect", @@ -163,13 +180,16 @@ "multiqc_rclone_check.txt:md5,c8f13c10aa4f0e4b356c5c08a9ae7ee9", "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", - "multiqc_rclone_exit_codes.txt:md5,e72c745debdc6ed04aa9b13b068d897c", + "multiqc_rclone_exit_codes.txt:md5,3dd8d4741882ff589545c2f2fcc99520", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_incorrect_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", "Illumina_annotation_missing_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_missing_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "Illumina_annotation_missing_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", "Illumina_annotation_sha_only_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_sha_only_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "Illumina_annotation_sha_only_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", "Illumina_annotation_incorrect_checksum_MD5.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", "Illumina_annotation_incorrect_checksum_MD5.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", @@ -185,10 +205,10 @@ "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-18T14:12:50.690727768", + "timestamp": "2026-09-02T18:26:27.114460768", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 40952d5..7dfd8da 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -9,7 +9,7 @@ "rclone": "1.74.3-DEV" }, "RCLONE_COPY": { - "rclone": "1.65.0-DEV" + "rclone": "1.74.3-DEV" }, "Workflow": { "nf-core/datasync": "v1.0.0" @@ -37,6 +37,7 @@ "rclone/check", "rclone/check/demultiplex", "rclone/check/demultiplex/demultiplex_check.combined.txt", + "rclone/check/demultiplex/demultiplex_check.exit_code.txt", "rclone/check/demultiplex/demultiplex_check.match.txt", "rclone/checksum", "rclone/checksum/demultiplex", @@ -45,6 +46,7 @@ "rclone/checksum/demultiplex/demultiplex_checksum_MD5.match.txt", "rclone/checksum/demultiplex/demultiplex_checksum_MD5.missing_on_src.txt", "rclone/checksum/demultiplex/demultiplex_checksum_SHA256.combined.txt", + "rclone/checksum/demultiplex/demultiplex_checksum_SHA256.exit_code.txt", "rclone/checksum/demultiplex/demultiplex_checksum_SHA256.match.txt", "rclone/copy", "rclone/copy/demultiplex-rclone-copy.log" @@ -54,22 +56,24 @@ "multiqc_rclone_check.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_rclone_checksum_md5.txt:md5,a68bd0275b5b6cb62ec966b68121b0e1", "multiqc_rclone_checksum_sha.txt:md5,03a73f087a286ec6580aada2a5db2e7c", - "multiqc_rclone_exit_codes.txt:md5,9bf4a8961b2d370bb06a09ccf65e0f7e", + "multiqc_rclone_exit_codes.txt:md5,2bc7209227358c54fa71dc3adb38d159", "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca", "demultiplex_check.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", + "demultiplex_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "demultiplex_check.match.txt:md5,902e4715d579b7f43a5463a220df8db0", "demultiplex_checksum_MD5.combined.txt:md5,9250a5e20244b4beb397eab1a2003c3a", "demultiplex_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", "demultiplex_checksum_MD5.match.txt:md5,644b95db936b45b931143faefb15be7f", "demultiplex_checksum_MD5.missing_on_src.txt:md5,b9f072c9e776951c6759590a8259f765", "demultiplex_checksum_SHA256.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", + "demultiplex_checksum_SHA256.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", "demultiplex_checksum_SHA256.match.txt:md5,902e4715d579b7f43a5463a220df8db0" ] ], - "timestamp": "2026-08-18T14:16:39.079934709", + "timestamp": "2026-09-02T18:28:53.331210181", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.6" + "nextflow": "26.04.1" } } } \ No newline at end of file From 9178433b42b78ccfa57893b7462a8f1d3939b930 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Thu, 3 Sep 2026 12:46:52 +0000 Subject: [PATCH 306/334] Update rclone modules --- modules.json | 6 +++--- .../rclone/check/tests/main.nf.test.snap | 11 ++++++++--- .../rclone/checksum/tests/main.nf.test.snap | 11 ++++++++--- .../rclone/copy/tests/main.nf.test.snap | 18 +++++++++--------- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/modules.json b/modules.json index 5da0eab..7bc7690 100644 --- a/modules.json +++ b/modules.json @@ -12,17 +12,17 @@ }, "rclone/check": { "branch": "master", - "git_sha": "fef5b8209601b7746f9705f63e5856cd2b5be708", + "git_sha": "0f1a09cd10bb7a05bfedb3d8780f985751f9c614", "installed_by": ["modules"] }, "rclone/checksum": { "branch": "master", - "git_sha": "fef5b8209601b7746f9705f63e5856cd2b5be708", + "git_sha": "0f1a09cd10bb7a05bfedb3d8780f985751f9c614", "installed_by": ["modules"] }, "rclone/copy": { "branch": "master", - "git_sha": "b34acd9d361bb226be8f0cf446b8b3a20ad0e3da", + "git_sha": "0f1a09cd10bb7a05bfedb3d8780f985751f9c614", "installed_by": ["modules"] } } diff --git a/modules/nf-core/rclone/check/tests/main.nf.test.snap b/modules/nf-core/rclone/check/tests/main.nf.test.snap index e19d7bf..423a41f 100644 --- a/modules/nf-core/rclone/check/tests/main.nf.test.snap +++ b/modules/nf-core/rclone/check/tests/main.nf.test.snap @@ -17,7 +17,12 @@ ], "exit_code": [ - + [ + { + "id": "test" + }, + "test.exit_code.txt:md5,897316929176464ebc9ad085f31e7284" + ] ], "match": [ [ @@ -42,10 +47,10 @@ ] } ], - "timestamp": "2026-08-04T11:26:36.792274751", + "timestamp": "2026-09-02T19:03:10.104368524", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.0" + "nextflow": "26.04.6" } }, "sarscov2 - fastq - stub": { diff --git a/modules/nf-core/rclone/checksum/tests/main.nf.test.snap b/modules/nf-core/rclone/checksum/tests/main.nf.test.snap index fc45ed0..f0d6ace 100644 --- a/modules/nf-core/rclone/checksum/tests/main.nf.test.snap +++ b/modules/nf-core/rclone/checksum/tests/main.nf.test.snap @@ -17,7 +17,12 @@ ], "exit_code": [ - + [ + { + "id": "test" + }, + "test.exit_code.txt:md5,897316929176464ebc9ad085f31e7284" + ] ], "match": [ [ @@ -42,10 +47,10 @@ ] } ], - "timestamp": "2026-08-04T11:27:09.176178267", + "timestamp": "2026-09-02T19:03:42.461174852", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.0" + "nextflow": "26.04.6" } }, "test - md5 - differs": { diff --git a/modules/nf-core/rclone/copy/tests/main.nf.test.snap b/modules/nf-core/rclone/copy/tests/main.nf.test.snap index a430eb4..d23bb7d 100644 --- a/modules/nf-core/rclone/copy/tests/main.nf.test.snap +++ b/modules/nf-core/rclone/copy/tests/main.nf.test.snap @@ -14,15 +14,15 @@ [ "RCLONE_COPY", "rclone", - "1.65.0-DEV" + "1.74.3-DEV" ] ] } ], - "timestamp": "2026-07-13T23:23:37.720920849", + "timestamp": "2026-09-02T19:04:23.232858558", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.4" + "nextflow": "26.04.6" } }, "homo_sapiens - gvcf - copy from https - dry-run": { @@ -40,15 +40,15 @@ [ "RCLONE_COPY", "rclone", - "1.65.0-DEV" + "1.74.3-DEV" ] ] } ], - "timestamp": "2026-07-15T14:53:00.158291805", + "timestamp": "2026-09-02T19:04:05.861448709", "meta": { "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nextflow": "26.04.6" } }, "homo_sapiens - gvcf - filter - dry-run": { @@ -66,15 +66,15 @@ [ "RCLONE_COPY", "rclone", - "1.65.0-DEV" + "1.74.3-DEV" ] ] } ], - "timestamp": "2026-07-28T15:53:02.864977147", + "timestamp": "2026-09-02T19:04:13.800329186", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.6" } } } \ No newline at end of file From 29f8ee91bc133f6b2d3bc8572acae29cfbb558be Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Thu, 3 Sep 2026 12:51:37 +0000 Subject: [PATCH 307/334] Run prek --- docs/usage.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index a9620b2..51e6158 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -20,13 +20,13 @@ Supply a comma-separated samplesheet with `--input`: Each row describes an independent transfer. The header names are fixed; columns may be in any order. -| Column | Required | Description | -| -------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `sample` | Yes | Unique identifier used in task labels and output report names. It must not contain whitespace. Use a unique value for each row to prevent published report files from colliding. | -| `input` | Yes | Source file or directory. Use a local path or object-storage URI such as `s3://bucket/prefix`. HTTP(S) URLs and rclone-specific `remote:path` syntax are not supported. Whitespace is not allowed. | +| Column | Required | Description | +| -------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `sample` | Yes | Unique identifier used in task labels and output report names. It must not contain whitespace. Use a unique value for each row to prevent published report files from colliding. | +| `input` | Yes | Source file or directory. Use a local path or object-storage URI such as `s3://bucket/prefix`. HTTP(S) URLs and rclone-specific `remote:path` syntax are not supported. Whitespace is not allowed. | | `output_path` | Yes | Destination directory. Use a local path such as `/archive/runs` or an object-storage URI such as `s3://bucket/prefix`. HTTP(S) URLs and rclone-specific `remote:path` syntax are not supported. Whitespace is not allowed. | -| `checksum_md5` | One checksum column | Path or URL to an MD5 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using SHA-256 only. | -| `checksum_sha` | One checksum column | Path or URL to a SHA-256 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using MD5 only. | +| `checksum_md5` | One checksum column | Path or URL to an MD5 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using SHA-256 only. | +| `checksum_sha` | One checksum column | Path or URL to a SHA-256 checksum manifest used to validate `input` before copying. The manifest format is described below. Leave empty when using MD5 only. | HTTP(S) URLs are not currently supported for `input` or `output_path`. The pipeline validates checksum manifests before copying and verifies the copied content afterwards; HTTP checksum behavior is not yet defined and tested for this workflow. Download HTTP-hosted data locally before including it in a samplesheet. From 46d463644739e15795e8d11d299df2b8600fb227 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Thu, 3 Sep 2026 11:21:28 -0300 Subject: [PATCH 308/334] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6943092..b8bc0f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Fixed` +- [[#84](https://github.com/nf-core/datasync/pull/84)] - Update `RCLONE_` modules, enhance source and destination path handling, add local `create_filter_list` module and other small fixes ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#83](https://github.com/nf-core/datasync/pull/83)] - Add apptainer version to avoid error in CI test ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#78](https://github.com/nf-core/datasync/pull/78)] - Fixed linting issues reported by nf-core and Nextflow, and updated `rclone` modules and nf-tests to sort generated report files for deterministic snapshots ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#76](https://github.com/nf-core/datasync/pull/76)] - Remove `--one-way` from rclone/checksum confi ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). From 412a67da99dd82a6d2d5ab85bfc9748a033a806c Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 4 Sep 2026 14:01:46 +0000 Subject: [PATCH 309/334] Add local test profile --- conf/test_copy.config | 24 ++++++++++++++++++++++++ nextflow.config | 1 + tests/assets/real_copy_samplesheet.csv | 5 +++++ 3 files changed, 30 insertions(+) create mode 100644 conf/test_copy.config create mode 100644 tests/assets/real_copy_samplesheet.csv diff --git a/conf/test_copy.config b/conf/test_copy.config new file mode 100644 index 0000000..a81ba42 --- /dev/null +++ b/conf/test_copy.config @@ -0,0 +1,24 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running a real copy test +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a real copy test. + + Use as follows: + nextflow run nf-core/datasync -profile test_copy, --outdir + +---------------------------------------------------------------------------------------- +*/ + +params { + config_profile_name = 'Real copy test profile' + config_profile_description = 'Minimal test dataset to test copying to a local test destination' + + input = "${projectDir}/tests/assets/real_copy_samplesheet.csv" + + // Rclone options + rclone_config = params.pipelines_testdata_base_path + "test-data/rclone.conf" + copy_matching_only = true + download = true +} + diff --git a/nextflow.config b/nextflow.config index 274b93f..a2e4e93 100644 --- a/nextflow.config +++ b/nextflow.config @@ -173,6 +173,7 @@ profiles { } test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } + test_copy { includeConfig 'conf/test_copy.config' } } // Load nf-core custom profiles from different institutions diff --git a/tests/assets/real_copy_samplesheet.csv b/tests/assets/real_copy_samplesheet.csv new file mode 100644 index 0000000..80bba7b --- /dev/null +++ b/tests/assets/real_copy_samplesheet.csv @@ -0,0 +1,5 @@ +sample,input,output_path,checksum_md5,checksum_sha +Illumina_annotation_missing,s3://ngi-igenomes/igenomes/PhiX/Illumina/RTA/Annotation/Archives/,./results/destination/,https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/Illumina_annotation_missing_md5.tsv, +Illumina_annotation_incorrect,s3://ngi-igenomes/igenomes/PhiX/Illumina/RTA/Annotation/Archives/,./results/destination/,https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/Illumina_annotation_incorrect_md5.tsv, +Illumina_annotation_sha_only,s3://ngi-igenomes/igenomes/PhiX/Illumina/RTA/Annotation/Archives/,./results/destination/,,https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/Illumina_annotation_incorrect_sha.tsv +benchmark_bed,gs://deepvariant/GIAB_v5q0/HG002_GRCh38_v5.0q_smvar.benchmark.bed,./results/destination/,https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/bed_md5.tsv \ No newline at end of file From 4cf61054f2fc40cc8937cb80bec43d0d18e4cb02 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 4 Sep 2026 15:40:36 +0000 Subject: [PATCH 310/334] Fix linting --- conf/test_copy.config | 8 ++++---- tests/assets/real_copy_samplesheet.csv | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/conf/test_copy.config b/conf/test_copy.config index a81ba42..bc06271 100644 --- a/conf/test_copy.config +++ b/conf/test_copy.config @@ -14,11 +14,11 @@ params { config_profile_name = 'Real copy test profile' config_profile_description = 'Minimal test dataset to test copying to a local test destination' - input = "${projectDir}/tests/assets/real_copy_samplesheet.csv" + // Input data + input = "${projectDir}/tests/assets/real_copy_samplesheet.csv" // Rclone options - rclone_config = params.pipelines_testdata_base_path + "test-data/rclone.conf" + rclone_config = params.pipelines_testdata_base_path + "test-data/rclone.conf" copy_matching_only = true - download = true + download = true } - diff --git a/tests/assets/real_copy_samplesheet.csv b/tests/assets/real_copy_samplesheet.csv index 80bba7b..0704889 100644 --- a/tests/assets/real_copy_samplesheet.csv +++ b/tests/assets/real_copy_samplesheet.csv @@ -2,4 +2,4 @@ sample,input,output_path,checksum_md5,checksum_sha Illumina_annotation_missing,s3://ngi-igenomes/igenomes/PhiX/Illumina/RTA/Annotation/Archives/,./results/destination/,https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/Illumina_annotation_missing_md5.tsv, Illumina_annotation_incorrect,s3://ngi-igenomes/igenomes/PhiX/Illumina/RTA/Annotation/Archives/,./results/destination/,https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/Illumina_annotation_incorrect_md5.tsv, Illumina_annotation_sha_only,s3://ngi-igenomes/igenomes/PhiX/Illumina/RTA/Annotation/Archives/,./results/destination/,,https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/Illumina_annotation_incorrect_sha.tsv -benchmark_bed,gs://deepvariant/GIAB_v5q0/HG002_GRCh38_v5.0q_smvar.benchmark.bed,./results/destination/,https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/bed_md5.tsv \ No newline at end of file +benchmark_bed,gs://deepvariant/GIAB_v5q0/HG002_GRCh38_v5.0q_smvar.benchmark.bed,./results/destination/,https://raw.githubusercontent.com/nf-core/test-datasets/datasync/test-data/bed_md5.tsv From d68d8bf6c23650b9824d17098c536dad5333292f Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 4 Sep 2026 15:46:29 +0000 Subject: [PATCH 311/334] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8bc0f7..bc790b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` +- [[#87](https://github.com/nf-core/datasync/pull/87)] - Add local test profile ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#79](https://github.com/nf-core/datasync/pull/79)] - Add exit status for `RCLONE` modules in multiqc report ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#74](https://github.com/nf-core/datasync/pull/74)] - Implement warning and `--download` parameter when working with remote directories and SHA checksums ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila), [@apeltzer](https://github.com/apeltzer) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#67](https://github.com/nf-core/datasync/pull/67)] - Copy only files which are successfully validated ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). From 23161e193783c4db846081c10dd85d41dcc0a18a Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 4 Sep 2026 16:33:25 +0000 Subject: [PATCH 312/334] Addexplanation for real data test profile --- docs/usage.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/usage.md b/docs/usage.md index 51e6158..eda3957 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -208,6 +208,19 @@ genome: 'GRCh37' You can also generate such `YAML`/`JSON` files via [nf-core/launch](https://nf-co.re/launch). +### Real copy example + +The `test_copy` profile provides a small real-transfer example that can be used to test the pipeline locally. It copies public test directories to `results/destination`and verifies the copied files: + +```bash +nextflow run nf-core/datasync \ + -r \ + -profile test_copy,docker \ + --outdir /data/datasync-test-copy-results +``` + +This profile does not use `--rclone_dry_run`; it transfers data to your local environment. Although the data is small, the run accesses cloud-hosted data and may incur network or cloud egress charges. Review your environment's costs before running this test profile. + ### Parameter files Frequently reused settings can be stored in YAML or JSON and loaded with `-params-file`: From 5cd483ddfa61b40d577a26cb0089af2cfa3d090a Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 8 Sep 2026 17:13:56 +0200 Subject: [PATCH 313/334] Implement review suggestions --- .github/workflows/awsfulltest.yml | 2 -- README.md | 4 ---- assets/samplesheet.csv | 2 +- assets/samplesheet_full.csv | 2 -- bin/create_test_files.sh | 8 -------- conf/igenomes.config | 0 conf/igenomes_ignored.config | 0 modules/local/create_filter_list/main.nf | 11 +++-------- nextflow_schema.json | 8 ++++---- .../local/utils_nfcore_datasync_pipeline/main.nf | 1 + 10 files changed, 9 insertions(+), 29 deletions(-) delete mode 100644 assets/samplesheet_full.csv delete mode 100644 bin/create_test_files.sh delete mode 100644 conf/igenomes.config delete mode 100644 conf/igenomes_ignored.config diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 4190c08..5a8075d 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -24,8 +24,6 @@ jobs: - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@51565b514bff1827cf34620de25d0055759f1fc9 # v2 - # Add full size test data (but still relatively small datasets for few samples) - # on the `test_full.config` test runs with only one set of parameters with: workspace_id: ${{ vars.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} diff --git a/README.md b/README.md index 0dcd130..3b88fa4 100644 --- a/README.md +++ b/README.md @@ -9,16 +9,12 @@ [![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml) [![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) - [![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.10.4-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-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3) - [![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/datasync) - [![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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 diff --git a/assets/samplesheet.csv b/assets/samplesheet.csv index 6d48fd6..9abae2c 100644 --- a/assets/samplesheet.csv +++ b/assets/samplesheet.csv @@ -1,2 +1,2 @@ sample,input,output_path,checksum_md5 -sample,path/to/file,output_path,path/to/file +sample,s3://foo/path/to/files/,output_path/data,path/to/checksum.md5 diff --git a/assets/samplesheet_full.csv b/assets/samplesheet_full.csv deleted file mode 100644 index 9ed843e..0000000 --- a/assets/samplesheet_full.csv +++ /dev/null @@ -1,2 +0,0 @@ -sample,input,checksum_md5,checksum_sha -demultiplex,s3://nf-core-awsmegatests/demultiplex/results-fbec8e442f0599f8b74876e62263af05b9a41d33/,checksum_md5.tsv,checksum_sha.tsv diff --git a/bin/create_test_files.sh b/bin/create_test_files.sh deleted file mode 100644 index ddb0120..0000000 --- a/bin/create_test_files.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -# This script expects a single folder $1 with several subfolders that then need to be synchronized and checksummed to another location $2 -mkdir -p $1 -mkdir -p $2 -touch $1/DemuxDone #Note this needs to be configured as a pattern to look for in the pipeline configuration, otherwise this trigger won't work. -touch $1/fake_file.fastq.gz -touch $1/fake_file2.fastq.gz -echo "Sync me to another place" > $1/SampleSheet.csv diff --git a/conf/igenomes.config b/conf/igenomes.config deleted file mode 100644 index e69de29..0000000 diff --git a/conf/igenomes_ignored.config b/conf/igenomes_ignored.config deleted file mode 100644 index e69de29..0000000 diff --git a/modules/local/create_filter_list/main.nf b/modules/local/create_filter_list/main.nf index b82caed..1da22b7 100644 --- a/modules/local/create_filter_list/main.nf +++ b/modules/local/create_filter_list/main.nf @@ -7,12 +7,7 @@ process CREATE_FILTER_LIST { output: tuple val(meta), path('files_to_copy.txt') - script: - def content = common.join('\n') - - """ - cat > files_to_copy.txt <<'EOF' -${content} -EOF - """ + exec: + def outFile = task.workDir.resolve('files_to_copy.txt') + outFile.text = common.join('\n') + '\n' } diff --git a/nextflow_schema.json b/nextflow_schema.json index 738538e..a4a5f43 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -47,24 +47,24 @@ "exists": true, "description": "Path to the rclone config file used for cloud storage authentication.", "help_text": "Provide an rclone config file to support cloud providers such as AWS S3 or Azure Blob Storage. This file is loaded by rclone when copying data.", - "fa_icon": "fas fa-file" + "fa_icon": "fas fa-cog" }, "rclone_dry_run": { "type": "boolean", "description": "Perform a dry run of the rclone copy command.", - "fa_icon": "fas fa-eye", + "fa_icon": "fas fa-forward", "help_text": "If set, the pipeline will not actually copy any files to the destination. Instead, it will print out what would have been copied. This is useful for testing and debugging." }, "copy_matching_only": { "type": "boolean", "description": "Only copy files that matched their provided input checksums.", - "fa_icon": "fas fa-eye", + "fa_icon": "fas fa-copy", "help_text": "If set, the pipeline will only copy files that were correctly validated and will skip any file that did not match their input checksum." }, "download": { "type": "boolean", "description": "Download remote files for sha256 checksum verification in `RCLONE_CHECKSUM`.", - "fa_icon": "fas fa-eye", + "fa_icon": "fas fa-cloud-download-alt", "help_text": "If set, `RCLONE_CHECKSUM` will download remote files for any sample for which a SHA256 file was provided." } } diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index dca6fc9..2f42376 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -11,6 +11,7 @@ include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' include { paramsSummaryMap } from 'plugin/nf-schema' include { samplesheetToList } from 'plugin/nf-schema' +include { paramsHelp } from 'plugin/nf-schema' include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' From e4372d99d95b3eb1e5d80239e23b8f1e19dafc86 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 8 Sep 2026 15:38:53 +0000 Subject: [PATCH 314/334] Template update for nf-core/tools version 4.1.0 --- ro-crate-metadata.json | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 9f28599..5deec59 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -22,7 +22,7 @@ "@id": "./", "@type": "Dataset", "creativeWorkStatus": "Stable", - "datePublished": "2026-09-01T12:58:22+00:00", + "datePublished": "2026-09-08T15:38:46+00:00", "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with 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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { @@ -99,7 +99,7 @@ }, "mentions": [ { - "@id": "#46ef1a98-d6c6-4e65-914f-1d0afeab3aa8" + "@id": "#77ce8e20-3bfe-48e3-a2ef-1e81d74d71b6" } ], "name": "nf-core/datasync" @@ -121,26 +121,42 @@ }, { "@id": "main.nf", - "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "@type": [ + "File", + "SoftwareSourceCode", + "ComputationalWorkflow" + ], "contributor": [ { "@id": "https://orcid.org/0000-0002-6503-2180" } ], "dateCreated": "", - "dateModified": "2026-09-01T12:58:22Z", + "dateModified": "2026-09-08T15:38:46Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", - "keywords": ["nf-core", "nextflow"], - "license": ["MIT"], - "name": ["nf-core/datasync"], + "keywords": [ + "nf-core", + "nextflow" + ], + "license": [ + "MIT" + ], + "name": [ + "nf-core/datasync" + ], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" }, "sdPublisher": { "@id": "https://nf-co.re/" }, - "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/1.0.0/"], - "version": ["1.0.0"] + "url": [ + "https://github.com/nf-core/datasync", + "https://nf-co.re/datasync/1.0.0/" + ], + "version": [ + "1.0.0" + ] }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", @@ -155,11 +171,11 @@ "version": "!>=25.10.4" }, { - "@id": "#46ef1a98-d6c6-4e65-914f-1d0afeab3aa8", + "@id": "#77ce8e20-3bfe-48e3-a2ef-1e81d74d71b6", "@type": "TestSuite", "instance": [ { - "@id": "#7a5ce052-0c99-4239-9251-2c7352bf2a92" + "@id": "#c23bf1c1-9211-4368-a804-064620c06a63" } ], "mainEntity": { @@ -168,7 +184,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#7a5ce052-0c99-4239-9251-2c7352bf2a92", + "@id": "#c23bf1c1-9211-4368-a804-064620c06a63", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/nf-test.yml", @@ -303,4 +319,4 @@ "name": "Alexander Peltzer" } ] -} +} \ No newline at end of file From a3bfda8693905a3f74f048df1b0fad34d7820f64 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 8 Sep 2026 16:09:52 +0000 Subject: [PATCH 315/334] Change default branch and update rclone checksum --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- modules.json | 3 +-- modules/nf-core/rclone/checksum/meta.yml | 20 +++++++++---------- ro-crate-metadata.json | 13 +----------- .../tests/nextflow_schema.json | 2 +- 5 files changed, 15 insertions(+), 27 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d43c74d..87aab4d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). diff --git a/modules.json b/modules.json index f414aa6..ef4f2b6 100644 --- a/modules.json +++ b/modules.json @@ -17,7 +17,7 @@ }, "rclone/checksum": { "branch": "master", - "git_sha": "0f1a09cd10bb7a05bfedb3d8780f985751f9c614", + "git_sha": "6ef220fd9252b42fb3c50348bbdbcb6246730686", "installed_by": ["modules"] }, "rclone/copy": { @@ -42,7 +42,6 @@ "utils_nfschema_plugin": { "branch": "master", "git_sha": "a7b27fd25bfa8dcc07d299e88bd790585901a436", - "git_sha": "a7b27fd25bfa8dcc07d299e88bd790585901a436", "installed_by": ["subworkflows"] } } diff --git a/modules/nf-core/rclone/checksum/meta.yml b/modules/nf-core/rclone/checksum/meta.yml index 40a8f87..bec4f79 100644 --- a/modules/nf-core/rclone/checksum/meta.yml +++ b/modules/nf-core/rclone/checksum/meta.yml @@ -125,16 +125,6 @@ output: pattern: "*.error.txt" ontologies: - edam: "http://edamontology.org/data_3671" - versions_rclone: - - - ${task.process}: - type: string - description: The name of the process - - rclone: - type: string - description: The name of the tool - - rclone --version | sed -n '1s/^rclone v//p': - type: eval - description: The expression to obtain the version of the tool exit_code: - - meta: type: map @@ -147,6 +137,16 @@ output: pattern: "*.exit_code.txt" ontologies: - edam: "http://edamontology.org/data_3671" + versions_rclone: + - - ${task.process}: + type: string + description: The name of the process + - rclone: + type: string + description: The name of the tool + - rclone --version | sed -n '1s/^rclone v//p': + type: eval + description: The expression to obtain the version of the tool topics: versions: - - ${task.process}: diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 02360a3..8ca15e3 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "Stable", "datePublished": "2026-09-08T15:38:46+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with 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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with 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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths or object-storage URIs such as Amazon S3, S3-compatible storage, or Azure Blob Storage. HTTP(S) URLs are not currently supported for samplesheet `input` or `output_path` values.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination URI needs credentials or provider settings. Samplesheet paths use local paths or standard URIs such as `s3://bucket/path`, not rclone's `remote:path` syntax. For non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,/data/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n- Julian Schwab\n- Gregor Sturm\n- Antonia Saracco\n- Delfina Terradas\n- Anabella Trigila\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -129,17 +129,6 @@ "SoftwareSourceCode", "ComputationalWorkflow" ], - "contributor": [ - { - "@id": "https://orcid.org/0000-0002-6503-2180" - }, - { - "@id": "#39fa8409-1f04-4472-9f46-7d3b03303768" - }, - { - "@id": "https://orcid.org/0000-0001-9584-7842" - } - ], "contributor": [ { "@id": "#be129ed0-c83e-444b-85dd-6db2c42dc277" diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json index 331e0d2..e1fa4e2 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://raw.githubusercontent.com/./master/nextflow_schema.json", + "$id": "https://raw.githubusercontent.com/./main/nextflow_schema.json", "title": ". pipeline parameters", "description": "", "type": "object", From 51174703f09604b88a64177453b2a649e0c8955b Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 8 Sep 2026 16:13:47 +0000 Subject: [PATCH 316/334] Fix linting --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index a44c64e..14d8a81 100644 --- a/docs/output.md +++ b/docs/output.md @@ -145,4 +145,4 @@ These files provide operational provenance and help diagnose performance or fail The supplied rclone configuration is an input credential file and is not intentionally copied to `--outdir`. Nevertheless, execution logs may contain remote names and object paths. Review logs before sharing them, and manage `rclone.conf` separately as a secret. -[Nextflow](https://docs.seqera.io/platform-cloud/reports/overview) provides excellent functionality for generating various reports relevant to the running and execution of the pipeline. This will allow you to troubleshoot errors with the running of the pipeline, and also provide you with other information such as launch commands, run times and resource usage. \ No newline at end of file +[Nextflow](https://docs.seqera.io/platform-cloud/reports/overview) provides excellent functionality for generating various reports relevant to the running and execution of the pipeline. This will allow you to troubleshoot errors with the running of the pipeline, and also provide you with other information such as launch commands, run times and resource usage. From ba00df59bce808700f7b6d629309df2278c59f0c Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 8 Sep 2026 14:19:21 -0300 Subject: [PATCH 317/334] Skip linting for PULL_REQUEST_TEMPLATE.md --- .nf-core.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.nf-core.yml b/.nf-core.yml index 7e1597e..046dfb2 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -4,6 +4,7 @@ lint: files_unchanged: - .github/workflows/branch.yml - .github/workflows/linting.yml + - .github/PULL_REQUEST_TEMPLATE.md multiqc_config: false nf_core_version: 4.1.0 repository_type: pipeline From bcfdc6abdc8a89bc41aa7e977e66058f0a787b0d Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 8 Sep 2026 19:32:40 +0200 Subject: [PATCH 318/334] Update changelog for first release --- CHANGELOG.md | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc790b5..1bf1fa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,28 +9,15 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` -- [[#87](https://github.com/nf-core/datasync/pull/87)] - Add local test profile ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#79](https://github.com/nf-core/datasync/pull/79)] - Add exit status for `RCLONE` modules in multiqc report ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#74](https://github.com/nf-core/datasync/pull/74)] - Implement warning and `--download` parameter when working with remote directories and SHA checksums ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila), [@apeltzer](https://github.com/apeltzer) and [@antoniasaracco](https://github.com/antoniasaracco)). -- [[#67](https://github.com/nf-core/datasync/pull/67)] - Copy only files which are successfully validated ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). -- [[#57](https://github.com/nf-core/datasync/pull/57)] - Add nf-tests with edge cases([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). -- [[#55](https://github.com/nf-core/datasync/pull/55)] - Add subdirectories with sample id to results. Improvements to MultiQC report (width of columns, sections and sub-section headers)colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). -- [[#54](https://github.com/nf-core/datasync/pull/54)] - Add colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). -- [[#31](https://github.com/nf-core/datasync/pull/31)] - Compute checksum for each input file ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#35](https://github.com/nf-core/datasync/pull/35)] - Compare generated checksum to given checksum in input and update test profiles ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#46](https://github.com/nf-core/datasync/pull/46)] - Import Rclone module from nf-core([@antoniasaracco](https://github.com/antoniasaracco), review by [@delfiterradas](https://github.com/delfiterradas)). -- [[#41](https://github.com/nf-core/datasync/pull/41)] - Generate MultiQC Report with comparechecksum tables and input samplesheet ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#49](https://github.com/nf-core/datasync/pull/49)] - Install `RCLONE_CHECK` and `RCLONE_CHECKSUM` modules from nf-core ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). -- [[#59](https://github.com/nf-core/datasync/pull/59)] - Create pipeline documentation ([@antoniasaracco](https://github.com/antoniasaracco), review by [@atrigila](https://github.com/atrigila) and [@delfiterradas](https://github.com/delfiterradas)). +- Samplesheet-driven copying of files and directories between local paths and rclone-supported object storage locations. +- Validation of source data against supplied MD5 and SHA-256 checksum manifests before transfer. +- The ability to copy only files that pass checksum validation, and to download remote files when SHA-256 verification is required. +- Post-transfer comparison of copied data against the source, with detailed rclone status files for each sample. +- A MultiQC report covering the input samplesheet, validation summary, checksum validation, and post-transfer checks. +- A local test profile to explore the pipeline and its outputs. ### `Fixed` -- [[#84](https://github.com/nf-core/datasync/pull/84)] - Update `RCLONE_` modules, enhance source and destination path handling, add local `create_filter_list` module and other small fixes ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#83](https://github.com/nf-core/datasync/pull/83)] - Add apptainer version to avoid error in CI test ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). -- [[#78](https://github.com/nf-core/datasync/pull/78)] - Fixed linting issues reported by nf-core and Nextflow, and updated `rclone` modules and nf-tests to sort generated report files for deterministic snapshots ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas) and [@antoniasaracco](https://github.com/antoniasaracco)). -- [[#76](https://github.com/nf-core/datasync/pull/76)] - Remove `--one-way` from rclone/checksum confi ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). -- [[#73](https://github.com/nf-core/datasync/pull/73)] - Create tmp `files_to_copy.tx` avoiding error with write permissions in work directory ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - ### `Dependencies` ### `Deprecated` From 4cbf1464f628d9e62d21f41319ba09a1dabcc2f4 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 8 Sep 2026 20:53:34 +0200 Subject: [PATCH 319/334] Add nf-metro plot --- README.md | 2 +- docs/images/datasync-metromap.png | Bin 58840 -> 0 bytes docs/images/datasync-nf-metro.mmd | 33 ++++++++++ docs/images/datasync_nf-metro.svg | 98 ++++++++++++++++++++++++++++++ ro-crate-metadata.json | 2 +- 5 files changed, 133 insertions(+), 2 deletions(-) delete mode 100644 docs/images/datasync-metromap.png create mode 100644 docs/images/datasync-nf-metro.mmd create mode 100644 docs/images/datasync_nf-metro.svg diff --git a/README.md b/README.md index 7a63602..96f62ea 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ The current tested use case for this pipeline is transfer between S3 buckets. Pass an `rclone` configuration with `--rclone_config` whenever a source or destination URI needs credentials or provider settings. Samplesheet paths use local paths or standard URIs such as `s3://bucket/path`, not rclone's `remote:path` syntax. For non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). -![nf-core/datasync metro map](docs/images/datasync-metromap.png) +![nf-core/datasync metro map](docs/images/datasync_nf-metro.svg) ## Quick start diff --git a/docs/images/datasync-metromap.png b/docs/images/datasync-metromap.png deleted file mode 100644 index 108bbc0d85c982f1fb48c6bff7b73099f2f236e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58840 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 diff --git a/docs/images/datasync-nf-metro.mmd b/docs/images/datasync-nf-metro.mmd new file mode 100644 index 0000000..c4558dd --- /dev/null +++ b/docs/images/datasync-nf-metro.mmd @@ -0,0 +1,33 @@ +%%metro title: nf-core/datasync +%%metro mode: dark +%%metro style: nfcore +%%metro diamond_style: symmetric +%%metro line: main | Pipeline | #4CAF50 + +%%metro file: ref_in | CSV | Input\nSamplesheet | banner +%%metro file: reads_in | Config | Rclone\nConfig | banner +%%metro file: report_out | HTML | Report | banner +%%metro grid: datasync | 0,0 + +graph LR + subgraph datasync [Datasync pipeline] + ref_in[Input] + reads_in[ ] + node1[Rclone\nChecksum] + node2[Create\nFilter List] + node3[Rclone\nCheck] + node4[Rclone\nCopy] + node5[MultiQC] + Rclone\nChecksum[Rclone\nChecksum] + ref_in -->|main| Rclone\nChecksum + reads_in -->|main| Rclone\nChecksum + report_out[Output] + ref_in -->|main| node1 + reads_in -->|main| node1 + node1 -->|main| node2 + node2 -->|main| node4 + node4 -->|main| node3 + node3 -->|main| node5 + node1 -->|main| node4 + node5 -->|main| report_out + end diff --git a/docs/images/datasync_nf-metro.svg b/docs/images/datasync_nf-metro.svg new file mode 100644 index 0000000..21982fe --- /dev/null +++ b/docs/images/datasync_nf-metro.svg @@ -0,0 +1,98 @@ + + + + +{"groups":[{"color":"#4CAF50","id":"main","label":"Pipeline"}],"height":419,"match":{"flags":"i","target":"fqProcessName","type":"regex"},"nodes":[{"groups":["main"],"h":10.0,"id":"ref_in","label":"Input","patterns":[],"r":5.0,"region":"datasync","rx":5.0,"w":10.0,"x":80.0,"y":133.6},{"groups":["main"],"h":10.0,"id":"reads_in","label":"reads_in","patterns":[],"r":5.0,"region":"datasync","rx":5.0,"w":10.0,"x":80.0,"y":267.2},{"groups":["main"],"h":10.0,"id":"node1","label":"Rclone\nChecksum","patterns":[],"r":5.0,"region":"datasync","rx":5.0,"w":10.0,"x":176.0,"y":200.4},{"groups":["main"],"h":10.0,"id":"node2","label":"Create\nFilter List","patterns":[],"r":5.0,"region":"datasync","rx":5.0,"w":10.0,"x":236.0,"y":167.0},{"groups":["main"],"h":10.0,"id":"node3","label":"Rclone\nCheck","patterns":[],"r":5.0,"region":"datasync","rx":5.0,"w":10.0,"x":356.0,"y":200.4},{"groups":["main"],"h":10.0,"id":"node4","label":"Rclone\nCopy","patterns":[],"r":5.0,"region":"datasync","rx":5.0,"w":10.0,"x":296.0,"y":200.4},{"groups":["main"],"h":10.0,"id":"node5","label":"MultiQC","patterns":[],"r":5.0,"region":"datasync","rx":5.0,"w":10.0,"x":416.0,"y":200.4},{"groups":["main"],"h":10.0,"id":"report_out","label":"Output","patterns":[],"r":5.0,"region":"datasync","rx":5.0,"w":10.0,"x":476.0,"y":200.4}],"regions":[{"id":"datasync","label":"Datasync pipeline"}],"title":"nf-core/datasync","version":"1.0","width":594} + + +nf-core/datasync + + +1 + + + + + + + + + + + + + + + + +CSV +InputSamplesheet + + + + + + + + + +Config +RcloneConfig + + + + + + + + + + + + + + + + + + + + + + + + +HTML +Report + + + +RcloneChecksum + +CreateFilter List + +RcloneCopy + +RcloneCheck + +MultiQC + + +Pipeline +created with nf-metro v2.0.0 + \ No newline at end of file diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 8ca15e3..919556e 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "Stable", "datePublished": "2026-09-08T15:38:46+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with 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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths or object-storage URIs such as Amazon S3, S3-compatible storage, or Azure Blob Storage. HTTP(S) URLs are not currently supported for samplesheet `input` or `output_path` values.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination URI needs credentials or provider settings. Samplesheet paths use local paths or standard URIs such as `s3://bucket/path`, not rclone's `remote:path` syntax. For non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,/data/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n- Julian Schwab\n- Gregor Sturm\n- Antonia Saracco\n- Delfina Terradas\n- Anabella Trigila\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\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", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with 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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths or object-storage URIs such as Amazon S3, S3-compatible storage, or Azure Blob Storage. HTTP(S) URLs are not currently supported for samplesheet `input` or `output_path` values.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination URI needs credentials or provider settings. Samplesheet paths use local paths or standard URIs such as `s3://bucket/path`, not rclone's `remote:path` syntax. For non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync_nf-metro.svg)\n\n## Quick start\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,/data/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n- Julian Schwab\n- Gregor Sturm\n- Antonia Saracco\n- Delfina Terradas\n- Anabella Trigila\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\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", "hasPart": [ { "@id": "main.nf" From c43ec123643414cdb698195501af632a7e6d35af Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 8 Sep 2026 19:02:11 +0000 Subject: [PATCH 320/334] Fix linting --- docs/images/datasync_nf-metro.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/images/datasync_nf-metro.svg b/docs/images/datasync_nf-metro.svg index 21982fe..62f95c3 100644 --- a/docs/images/datasync_nf-metro.svg +++ b/docs/images/datasync_nf-metro.svg @@ -95,4 +95,4 @@ Copy" data-section-id="datasync" data-section-name="Datasync pipeline" /> Pipeline created with nf-metro v2.0.0 - \ No newline at end of file + From 89905cbf7e3105340ea267a59a411548b4b1b943 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Wed, 9 Sep 2026 10:51:17 -0300 Subject: [PATCH 321/334] Clean up CHANGELOG by removing empty sections --- CHANGELOG.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13174ac..70658fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,9 +15,3 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - Post-transfer comparison of copied data against the source, with detailed rclone status files for each sample. - A MultiQC report covering the input samplesheet, validation summary, checksum validation, and post-transfer checks. - A local test profile to explore the pipeline and its outputs. - -### `Fixed` - -### `Dependencies` - -### `Deprecated` From d6056fc33e799cb70e3499b4cfb00e20583eae25 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 9 Sep 2026 17:30:07 +0200 Subject: [PATCH 322/334] Add memory definition to avoid failing on seqera platform --- conf/modules.config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/conf/modules.config b/conf/modules.config index ff411a5..f0b5db2 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -37,6 +37,11 @@ process { ] } + withName: 'CREATE_FILTER_LIST' { + cpus = 1 + memory = { 100.MB * task.attempt } + } + withName: 'RCLONE_COPY' { ext.args = { def base_args = [ From 4af74f212d37861d27bd8981775ef9ccb9908ca3 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 23 Sep 2026 18:16:14 +0000 Subject: [PATCH 323/334] Implement suggestions to documentation and minor changes in outputs --- CHANGELOG.md | 2 +- conf/modules.config | 13 +++++-------- docs/output.md | 16 ++++++++-------- docs/usage.md | 12 ++++++------ 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70658fa..16e19d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v1.0.0 - 2026-09-10 +## v1.0.0 - 2026-09-25 Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re/) template. diff --git a/conf/modules.config b/conf/modules.config index f0b5db2..e13b34f 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -31,9 +31,8 @@ process { base_args.join(' ') } publishDir = [ - path: { "${params.outdir}/rclone/checksum/${meta.id}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + path: { "${params.outdir}/rclone/checksum_before/${meta.id}" }, + mode: params.publish_dir_mode ] } @@ -62,8 +61,7 @@ process { } publishDir = [ path: { "${params.outdir}/rclone/copy" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + mode: params.publish_dir_mode ] } @@ -77,9 +75,8 @@ process { base_args.join(' ') } publishDir = [ - path: { "${params.outdir}/rclone/check/${meta.id}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + path: { "${params.outdir}/rclone/check_after/${meta.id}" }, + mode: params.publish_dir_mode ] } diff --git a/docs/output.md b/docs/output.md index 14d8a81..7dab8aa 100644 --- a/docs/output.md +++ b/docs/output.md @@ -14,7 +14,7 @@ This document describes the reports produced by nf-core/datasync. Paths below ar ├── rclone/ │ ├── copy/ │ │ └── -rclone-copy.log -│ ├── checksum/ +│ ├── checksum_before/ │ │ └── / │ │ ├── .combined.txt │ │ ├── .match.txt @@ -22,7 +22,7 @@ This document describes the reports produced by nf-core/datasync. Paths below ar │ │ ├── .missing_on_dst.txt │ │ ├── .missing_on_src.txt │ │ └── .error.txt -│ └── check/ +│ └── check_after/ │ └── / │ ├── .combined.txt │ ├── .match.txt @@ -38,7 +38,7 @@ This document describes the reports produced by nf-core/datasync. Paths below ar └── execution_* / pipeline_dag_* ``` -The `rclone/` directory is split by module stage. Copy logs are published to `rclone/copy/`, pre-copy checksum validation reports are published to `rclone/checksum//`, and post-copy source-to-destination comparison reports are published to `rclone/check//`. The `` directory name is taken from the `sample` value in the samplesheet row. +The `rclone/` directory is split by module stage. Copy logs are published to `rclone/copy/`, pre-copy checksum validation reports are published to `rclone/checksum_before//`, and post-copy source-to-destination comparison reports are published to `rclone/check_after//`. The `` directory name is taken from the `sample` value in the samplesheet row. ## `rclone` directory @@ -47,14 +47,14 @@ The `rclone/` directory is split by module stage. Copy logs are published to `rc - `rclone/copy/` - `-rclone-copy.log`: informational log from the copy operation. -- `rclone/checksum//` +- `rclone/checksum_before//` - `.combined.txt`: combined pre-copy checksum-validation status, one path per line. - `.match.txt`: paths whose content matched the supplied checksum manifest (`=`). - `.differ.txt`: paths present in the source and manifest but with different content (`*`). - `.missing_on_dst.txt`: paths present in the checksum manifest but absent from the checked source (`-`). - `.missing_on_src.txt`: paths present in the checked source but absent from the checksum manifest (`+`). - `.error.txt`: paths that could not be read or hashed (`!`). -- `rclone/check//` +- `rclone/check_after//` - `.combined.txt`: combined post-copy source-to-destination comparison status, one path per line. - `.match.txt`: paths whose content matched between source and destination (`=`). - `.differ.txt`: paths present on both sides but with different content (`*`). @@ -66,8 +66,8 @@ The `rclone/` directory is split by module stage. Copy logs are published to `rc Two integrity stages create reports: -1. **Pre-copy checksum validation** uses each supplied MD5 and/or SHA-256 manifest to check the source and publishes reports under `rclone/checksum//`. -2. **Post-copy validation** compares the source with the destination after the copy task finishes and publishes reports under `rclone/check//`. +1. **Pre-copy checksum validation** uses each supplied MD5 and/or SHA-256 manifest to check the source and publishes reports under `rclone/checksum_before//`. +2. **Post-copy validation** compares the source with the destination after the copy task finishes and publishes reports under `rclone/check_after//`. Both stages use the same `.*.txt` naming convention and publish to `rclone/`. When a row supplies a checksum manifest, similarly named pre-copy and post-copy files may target the same published path; use the consolidated MultiQC sections for the stage-specific summary and retain the Nextflow work directory if both raw report sets must be audited independently. @@ -114,7 +114,7 @@ Exit codes are reported using their corresponding rclone descriptions to make it The MD5 and SHA-256 input-validation sections show the results from [`rclone checksum`](https://rclone.org/commands/rclone_checksum/). Use these sections to confirm that each source file matched the checksum manifest supplied in `checksum_md5` and/or `checksum_sha` before copying. -When a samplesheet `input` points to S3, `rclone checksum` can normally validate MD5 manifests from S3 object hashes, but S3 does not provide SHA-256 object hashes for rclone to read remotely. SHA-256 validation for S3 inputs therefore requires `rclone checksum --download`, which downloads object data and calculates the hash locally during validation. Configure the checksum process to pass `--download` when SHA-256 validation is required for S3 inputs; see the [`rclone checksum` --download documentation](https://rclone.org/commands/rclone_checksum/). +When a samplesheet `input` points to S3, `rclone checksum` can normally validate MD5 manifests from S3 object hashes, but S3 does not provide SHA-256 object hashes for rclone to read remotely. SHA-256 validation for S3 inputs therefore requires the `--download` pipeline parameter to be enabled, which allows `rclone checksum` to download object data and calculate the hash locally during validation. ![nf-core/multiqc checksum md5](images/datasync-multiqc-checksum-md5.png) diff --git a/docs/usage.md b/docs/usage.md index ddeb6b5..38c74fb 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -154,9 +154,9 @@ A typical local-to-cloud run is: nextflow run nf-core/datasync \ -r \ -profile docker \ - --input /data/samplesheet.csv \ - --outdir /data/datasync-results \ - --rclone_config /secure/rclone.conf + --input ./data/samplesheet.csv \ + --outdir ./data/datasync-results \ + --rclone_config ./secure/rclone.conf ``` `--outdir` stores logs, integrity reports, MultiQC, and execution metadata. It does **not** override the transfer destinations in the samplesheet. @@ -167,9 +167,9 @@ To inspect the proposed copy without writing destination data: nextflow run nf-core/datasync \ -r \ -profile docker \ - --input /data/samplesheet.csv \ - --outdir /data/datasync-dry-run \ - --rclone_config /secure/rclone.conf \ + --input ./data/samplesheet.csv \ + --outdir ./data/datasync-dry-run \ + --rclone_config ./secure/rclone.conf \ --rclone_dry_run ``` From fc37342b65c4269998f65c8a527b8a0377eaec01 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 24 Sep 2026 18:52:07 +0000 Subject: [PATCH 324/334] Add documentation to create md5 and shasums --- docs/usage.md | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 38c74fb..f853a50 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -32,14 +32,33 @@ HTTP(S) URLs are not currently supported for `input` or `output_path`. The pipel At least one checksum manifest is required on every row. If both are supplied, both validations run. Checksum files must use the format accepted by [`rclone checksum`](https://rclone.org/commands/rclone_checksum/): one checksum record per line with the hash value followed by two spaces and then the file path. Paths must be relative to the source root from the `input` column, not absolute paths. -For a directory input, the source root is the directory named in the samplesheet. For example, if the samplesheet `input` is `/data/run_001` and one file in that directory is `/data/run_001/reads/sample_R1.fastq.gz`, the checksum manifest path must be `reads/sample_R1.fastq.gz`. Do not write `/data/run_001/reads/sample_R1.fastq.gz` in the manifest. For a single-file input, use the input file name as the manifest path. +For a directory input, paths are relative to the directory named in the samplesheet. For example, if `input` is `/data/run_001` and it contains `/data/run_001/reads/sample_R1.fastq.gz`, the checksum manifest path must be `reads/sample_R1.fastq.gz`, not the absolute path. For a single-file input, the pipeline checks the manifest against the file's parent directory, so the manifest path must be the file name. For example, an `input` of `/data/reference.fa` requires a manifest entry ending in `reference.fa`. + +You can generate a correctly formatted MD5 manifest with `rclone md5sum`. Write the manifest outside the input directory so that it is not included among the files being hashed: + +```bash +rclone md5sum ./data/run_001 > ./data/checksums/run_001_md5.txt +rclone md5sum ./data/reference.fa > ./data/checksums/reference_md5.txt +``` + +For SHA-256, use `rclone hashsum SHA256`: + +```bash +rclone hashsum SHA256 ./data/run_001 > ./data/checksums/run_001_sha256.txt +``` + +For an object-storage source, use the corresponding configured rclone remote syntax when generating the manifest. For example, the samplesheet input `s3://bucket/prefix` corresponds to `s3:bucket/prefix` when the rclone configuration contains an `[s3]` remote: + +```bash +rclone md5sum --config ./secure/rclone.conf s3:bucket/prefix > run_001_md5.txt +``` Checksum manifests may use a `.tsv`, `.txt`, `.md5` or `.sha256` filename extension, but their contents are not tab-separated or comma-separated tables and must not include a header. Each record is plain text with the hash and path separated by exactly **two spaces**. The required fields are: -| Field | Required | Description | -| ----- | -------- | ----------------------------------------------------------------------------------------------- | -| Hash | Yes | MD5 hash for `checksum_md5` files or SHA-256 hash for `checksum_sha` files. | -| Path | Yes | Relative path to the file being validated, resolved from the corresponding `input` source root. | +| Field | Required | Description | +| ----- | -------- | ------------------------------------------------------------------------------------------------------------------------ | +| Hash | Yes | MD5 hash for `checksum_md5` files or SHA-256 hash for `checksum_sha` files. | +| Path | Yes | Path relative to a directory `input`, or the file name (without parent directories) for a single-file `input`. | Example samplesheet: @@ -216,7 +235,7 @@ The `test_copy` profile provides a small real-transfer example that can be used nextflow run nf-core/datasync \ -r \ -profile test_copy,docker \ - --outdir /data/datasync-test-copy-results + --outdir ./data/datasync-test-copy-results ``` This profile does not use `--rclone_dry_run`; it transfers data to your local environment. Although the data is small, the run accesses cloud-hosted data and may incur network or cloud egress charges. Review your environment's costs before running this test profile. From 3024ac026c9b64adda76f3e7360bc4fe9e394ce0 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 24 Sep 2026 19:47:35 +0000 Subject: [PATCH 325/334] Create prepareSamplesheet function --- .../utils_nfcore_datasync_pipeline/main.nf | 23 +++++++++++++++ workflows/datasync.nf | 28 ++++--------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 2f42376..965bc4c 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -167,6 +167,29 @@ workflow PIPELINE_COMPLETION { FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +// +// Prepare samplesheet channels for rclone operations +// +def prepareSamplesheet(samplesheet) { + samplesheet.multiMap { meta, input_path, output_path, md5, sha -> + def normalized_input_path = input_path.toString().replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') + def normalized_output_path = output_path.toString().replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') + + def source = file(input_path) + + def rclone_destination = source.isFile() + ? normalized_output_path.replaceAll('/+$', '') + : "${normalized_output_path.replaceAll('/+$', '')}/${source.name}" + + def rclone_check = source.isFile() + ? normalized_input_path.replaceFirst('/[^/]+$', '') + : normalized_input_path.replaceAll('/+$', '') + + rclone: [ meta, normalized_input_path, rclone_destination ] + checksum: [ meta, md5, sha, rclone_check ] + } +} + // // Check and validate pipeline parameters // diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 63ab937..3c1a12c 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -14,6 +14,7 @@ include { softwareVersionsToYAML } from '../subworkflows/nf-co include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_datasync_pipeline' include { parseRcloneCheck } from '../subworkflows/local/utils_nfcore_datasync_pipeline' include { createExitSummary } from '../subworkflows/local/utils_nfcore_datasync_pipeline' +include { prepareSamplesheet } from '../subworkflows/local/utils_nfcore_datasync_pipeline' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -37,25 +38,8 @@ workflow DATASYNC { ch_multiqc_files = channel.empty() ch_rclone_config = rclone_config ? file(rclone_config, checkIfExists: true) : [] - ch_samplesheet = ch_samplesheet.multiMap { - meta, input_path, output_path, md5, sha -> - - def normalized_input_path = input_path.toString().replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') - def normalized_output_path = output_path.toString().replaceFirst('^([a-zA-Z][a-zA-Z0-9+.-]*)://', '$1:') - - def source = file(input_path) - - def rclone_destination = source.isFile() - ? normalized_output_path.replaceAll('/+$', '') - : "${normalized_output_path.replaceAll('/+$', '')}/${source.name}" - - def rclone_check = source.isFile() - ? normalized_input_path.replaceFirst('/[^/]+$', '') - : normalized_input_path.replaceAll('/+$', '') - - rclone: [ meta, normalized_input_path, rclone_destination ] - checksum: [ meta, md5, sha, rclone_check ] - } + ch_samplesheet = prepareSamplesheet(ch_samplesheet) + ch_rclone = ch_samplesheet.rclone // Group input md5sum/shasum with their respective generated checksum ch_checksum = ch_samplesheet.checksum @@ -120,10 +104,10 @@ workflow DATASYNC { CREATE_FILTER_LIST(ch_files_to_copy) - ch_rclone_copy = ch_samplesheet.rclone + ch_rclone_copy = ch_rclone .join(CREATE_FILTER_LIST.out) } else { - ch_rclone_copy = ch_samplesheet.rclone.map { meta, source, destination -> [ meta, source, destination, [] ] } + ch_rclone_copy = ch_rclone.map { meta, source, destination -> [ meta, source, destination, [] ] } } RCLONE_COPY( @@ -132,7 +116,7 @@ workflow DATASYNC { ) // Wait for file copy to finish before running RCLONE_CHECK - ch_rclone_check = ch_samplesheet.rclone + ch_rclone_check = ch_rclone .join(RCLONE_COPY.out.log, remainder: true) .map { meta, input, output, _log -> [ meta, input, output ] } From 520599b79a2803c53475977d98ddee27e5b5597b Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 24 Sep 2026 21:04:15 +0000 Subject: [PATCH 326/334] Add test assertions --- tests/.nftignore | 1 + tests/default.nf.test | 27 ++++- tests/default.nf.test.snap | 70 ++++++------ tests/edge.nf.test | 58 +++++++++- tests/edge.nf.test.snap | 208 +++++++++++++++++------------------ tests/initialisation.nf.test | 75 +++++++++++++ tests/main_full.nf.test | 26 ++++- tests/main_full.nf.test.snap | 55 +++++---- workflows/datasync.nf | 2 +- 9 files changed, 341 insertions(+), 181 deletions(-) create mode 100644 tests/initialisation.nf.test diff --git a/tests/.nftignore b/tests/.nftignore index b1e73cd..0c88efe 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -11,3 +11,4 @@ multiqc/multiqc_report.html fastqc/*_fastqc.{html,zip} pipeline_info/*.{html,json,txt,yml} rclone/**/*.log +rclone/**/*.txt diff --git a/tests/default.nf.test b/tests/default.nf.test index 666d370..0bc508e 100644 --- a/tests/default.nf.test +++ b/tests/default.nf.test @@ -18,15 +18,38 @@ nextflow_pipeline { def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) // stable_content: All files in ${params.outdir}/ with stable content def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') - assert workflow.success + // Summarise rclone outputs by line count and verify exit codes explicitly + def outdir_path = new File(params.outdir.toString()).toPath() + def rclone_line_counts = [] + def rclone_exit_codes = [:] + new File(params.outdir.toString(), 'rclone').eachFileRecurse { output_file -> + if (output_file.isFile() && output_file.name.endsWith('.txt')) { + def relative_path = outdir_path.relativize(output_file.toPath()).toString() + if (output_file.name.endsWith('.exit_code.txt')) { + rclone_exit_codes[relative_path] = output_file.text.trim() + } else { + rclone_line_counts << "${relative_path}:lines,${output_file.readLines().size()}" + } + } + } + rclone_line_counts.sort() assertAll( + { assert workflow.success }, + { assert rclone_exit_codes == [ + 'rclone/check_after/Illumina_annotation/Illumina_annotation_check.exit_code.txt': '0', + 'rclone/check_after/benchmark_bed/benchmark_bed_check.exit_code.txt': '0', + 'rclone/checksum_before/Illumina_annotation/Illumina_annotation_checksum_MD5.exit_code.txt': '0', + 'rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.exit_code.txt': '1', + ] }, { assert snapshot( // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), // All stable path name, with a relative path stable_path, // All files with stable contents - stable_content + stable_content, + // Number of lines in each rclone check and checksum output + rclone_line_counts ).match() } ) } diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index b546a15..d9521ce 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -33,25 +33,25 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", - "rclone/check", - "rclone/check/Illumina_annotation", - "rclone/check/Illumina_annotation/Illumina_annotation_check.combined.txt", - "rclone/check/Illumina_annotation/Illumina_annotation_check.exit_code.txt", - "rclone/check/Illumina_annotation/Illumina_annotation_check.match.txt", - "rclone/check/benchmark_bed", - "rclone/check/benchmark_bed/benchmark_bed_check.combined.txt", - "rclone/check/benchmark_bed/benchmark_bed_check.exit_code.txt", - "rclone/check/benchmark_bed/benchmark_bed_check.match.txt", - "rclone/checksum", - "rclone/checksum/Illumina_annotation", - "rclone/checksum/Illumina_annotation/Illumina_annotation_checksum_MD5.combined.txt", - "rclone/checksum/Illumina_annotation/Illumina_annotation_checksum_MD5.exit_code.txt", - "rclone/checksum/Illumina_annotation/Illumina_annotation_checksum_MD5.match.txt", - "rclone/checksum/benchmark_bed", - "rclone/checksum/benchmark_bed/benchmark_bed_checksum_MD5.combined.txt", - "rclone/checksum/benchmark_bed/benchmark_bed_checksum_MD5.exit_code.txt", - "rclone/checksum/benchmark_bed/benchmark_bed_checksum_MD5.match.txt", - "rclone/checksum/benchmark_bed/benchmark_bed_checksum_MD5.missing_on_src.txt", + "rclone/check_after", + "rclone/check_after/Illumina_annotation", + "rclone/check_after/Illumina_annotation/Illumina_annotation_check.combined.txt", + "rclone/check_after/Illumina_annotation/Illumina_annotation_check.exit_code.txt", + "rclone/check_after/Illumina_annotation/Illumina_annotation_check.match.txt", + "rclone/check_after/benchmark_bed", + "rclone/check_after/benchmark_bed/benchmark_bed_check.combined.txt", + "rclone/check_after/benchmark_bed/benchmark_bed_check.exit_code.txt", + "rclone/check_after/benchmark_bed/benchmark_bed_check.match.txt", + "rclone/checksum_before", + "rclone/checksum_before/Illumina_annotation", + "rclone/checksum_before/Illumina_annotation/Illumina_annotation_checksum_MD5.combined.txt", + "rclone/checksum_before/Illumina_annotation/Illumina_annotation_checksum_MD5.exit_code.txt", + "rclone/checksum_before/Illumina_annotation/Illumina_annotation_checksum_MD5.match.txt", + "rclone/checksum_before/benchmark_bed", + "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.combined.txt", + "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.exit_code.txt", + "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.match.txt", + "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.missing_on_src.txt", "rclone/copy", "rclone/copy/Illumina_annotation-rclone-copy.log", "rclone/copy/benchmark_bed-rclone-copy.log" @@ -61,26 +61,24 @@ "multiqc_rclone_check.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", "multiqc_rclone_checksum_md5.txt:md5,c7127de966d1be295ef6697dba648c79", "multiqc_rclone_exit_codes.txt:md5,d970d9335584ff1e7349036e62f5e8d4", - "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4", - "Illumina_annotation_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "Illumina_annotation_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "benchmark_bed_check.combined.txt:md5,dcd2c539696adba720986251dcd1aaef", - "benchmark_bed_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "benchmark_bed_check.match.txt:md5,12608858576bec12c65ff338a99803c3", - "Illumina_annotation_checksum_MD5.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_checksum_MD5.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "Illumina_annotation_checksum_MD5.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "benchmark_bed_checksum_MD5.combined.txt:md5,592b2b2af44551686a8057f585309413", - "benchmark_bed_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "benchmark_bed_checksum_MD5.match.txt:md5,12608858576bec12c65ff338a99803c3", - "benchmark_bed_checksum_MD5.missing_on_src.txt:md5,7bf2def3eed9eff615a0f29ae1652254" + "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4" + ], + [ + "rclone/check_after/Illumina_annotation/Illumina_annotation_check.combined.txt:lines,15", + "rclone/check_after/Illumina_annotation/Illumina_annotation_check.match.txt:lines,15", + "rclone/check_after/benchmark_bed/benchmark_bed_check.combined.txt:lines,1", + "rclone/check_after/benchmark_bed/benchmark_bed_check.match.txt:lines,1", + "rclone/checksum_before/Illumina_annotation/Illumina_annotation_checksum_MD5.combined.txt:lines,15", + "rclone/checksum_before/Illumina_annotation/Illumina_annotation_checksum_MD5.match.txt:lines,15", + "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.combined.txt:lines,10", + "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.match.txt:lines,1", + "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.missing_on_src.txt:lines,9" ] ], - "timestamp": "2026-09-02T18:25:59.629051707", + "timestamp": "2026-09-24T19:40:39.867871956", "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nf-test": "0.9.4", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/edge.nf.test b/tests/edge.nf.test index f5c5188..291f494 100644 --- a/tests/edge.nf.test +++ b/tests/edge.nf.test @@ -21,15 +21,40 @@ nextflow_pipeline { def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) // stable_content: All files in ${params.outdir}/ with stable content def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') - assert workflow.success + // Summarise rclone outputs by line count and verify exit codes explicitly + def outdir_path = new File(params.outdir.toString()).toPath() + def rclone_line_counts = [] + def rclone_exit_codes = [:] + new File(params.outdir.toString(), 'rclone').eachFileRecurse { output_file -> + if (output_file.isFile() && output_file.name.endsWith('.txt')) { + def relative_path = outdir_path.relativize(output_file.toPath()).toString() + if (output_file.name.endsWith('.exit_code.txt')) { + rclone_exit_codes[relative_path] = output_file.text.trim() + } else { + rclone_line_counts << "${relative_path}:lines,${output_file.readLines().size()}" + } + } + } + rclone_line_counts.sort() assertAll( + { assert workflow.success }, + { assert rclone_exit_codes == [ + 'rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt': '0', + 'rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt': '0', + 'rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt': '0', + 'rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt': '1', + 'rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt': '1', + 'rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt': '1', + ] }, { assert snapshot( // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), // All stable path name, with a relative path stable_path, // All files with stable contents - stable_content + stable_content, + // Number of lines in each rclone check and checksum output + rclone_line_counts ).match() } ) } @@ -51,15 +76,40 @@ nextflow_pipeline { def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) // stable_content: All files in ${params.outdir}/ with stable content def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') - assert workflow.success + // Summarise rclone outputs by line count and verify exit codes explicitly + def outdir_path = new File(params.outdir.toString()).toPath() + def rclone_line_counts = [] + def rclone_exit_codes = [:] + new File(params.outdir.toString(), 'rclone').eachFileRecurse { output_file -> + if (output_file.isFile() && output_file.name.endsWith('.txt')) { + def relative_path = outdir_path.relativize(output_file.toPath()).toString() + if (output_file.name.endsWith('.exit_code.txt')) { + rclone_exit_codes[relative_path] = output_file.text.trim() + } else { + rclone_line_counts << "${relative_path}:lines,${output_file.readLines().size()}" + } + } + } + rclone_line_counts.sort() assertAll( + { assert workflow.success }, + { assert rclone_exit_codes == [ + 'rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt': '0', + 'rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt': '0', + 'rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt': '0', + 'rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt': '1', + 'rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt': '1', + 'rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt': '1', + ] }, { assert snapshot( // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), // All stable path name, with a relative path stable_path, // All files with stable contents - stable_content + stable_content, + // Number of lines in each rclone check and checksum output + rclone_line_counts ).match() } ) } diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index 76b160e..73b1649 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -36,35 +36,35 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", - "rclone/check", - "rclone/check/Illumina_annotation_incorrect", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt", - "rclone/check/Illumina_annotation_missing", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt", - "rclone/check/Illumina_annotation_sha_only", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt", - "rclone/checksum", - "rclone/checksum/Illumina_annotation_incorrect", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt", - "rclone/checksum/Illumina_annotation_missing", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt", - "rclone/checksum/Illumina_annotation_sha_only", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt", + "rclone/check_after", + "rclone/check_after/Illumina_annotation_incorrect", + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt", + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt", + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt", + "rclone/check_after/Illumina_annotation_missing", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt", + "rclone/check_after/Illumina_annotation_sha_only", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt", + "rclone/checksum_before", + "rclone/checksum_before/Illumina_annotation_incorrect", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt", + "rclone/checksum_before/Illumina_annotation_missing", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt", + "rclone/checksum_before/Illumina_annotation_sha_only", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt", "rclone/copy", "rclone/copy/Illumina_annotation_incorrect-rclone-copy.log", "rclone/copy/Illumina_annotation_missing-rclone-copy.log" @@ -76,34 +76,30 @@ "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_rclone_exit_codes.txt:md5,3dd8d4741882ff589545c2f2fcc99520", - "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", - "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_incorrect_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_missing_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_missing_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "Illumina_annotation_missing_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_sha_only_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_sha_only_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "Illumina_annotation_sha_only_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_incorrect_checksum_MD5.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", - "Illumina_annotation_incorrect_checksum_MD5.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", - "Illumina_annotation_incorrect_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "Illumina_annotation_incorrect_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing_checksum_MD5.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", - "Illumina_annotation_missing_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "Illumina_annotation_missing_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", - "Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", - "Illumina_annotation_sha_only_checksum_SHA256.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", - "Illumina_annotation_sha_only_checksum_SHA256.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" + "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" + ], + [ + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt:lines,15", + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt:lines,15", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt:lines,15", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt:lines,15", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt:lines,15", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt:lines,15", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt:lines,15", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt:lines,5", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt:lines,10", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt:lines,16", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt:lines,10", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:lines,1", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:lines,5", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt:lines,15", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt:lines,15" ] ], - "timestamp": "2026-09-02T18:26:55.720186858", + "timestamp": "2026-09-24T19:43:28.768757814", "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nf-test": "0.9.4", + "nextflow": "25.10.4" } }, "-profile test edge cases": { @@ -141,35 +137,35 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", - "rclone/check", - "rclone/check/Illumina_annotation_incorrect", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt", - "rclone/check/Illumina_annotation_missing", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt", - "rclone/check/Illumina_annotation_sha_only", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt", - "rclone/checksum", - "rclone/checksum/Illumina_annotation_incorrect", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt", - "rclone/checksum/Illumina_annotation_missing", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt", - "rclone/checksum/Illumina_annotation_sha_only", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt", + "rclone/check_after", + "rclone/check_after/Illumina_annotation_incorrect", + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt", + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt", + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt", + "rclone/check_after/Illumina_annotation_missing", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt", + "rclone/check_after/Illumina_annotation_sha_only", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt", + "rclone/checksum_before", + "rclone/checksum_before/Illumina_annotation_incorrect", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt", + "rclone/checksum_before/Illumina_annotation_missing", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt", + "rclone/checksum_before/Illumina_annotation_sha_only", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt", "rclone/copy", "rclone/copy/Illumina_annotation_incorrect-rclone-copy.log", "rclone/copy/Illumina_annotation_missing-rclone-copy.log", @@ -181,34 +177,30 @@ "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_rclone_exit_codes.txt:md5,3dd8d4741882ff589545c2f2fcc99520", - "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", - "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_incorrect_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_missing_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_missing_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "Illumina_annotation_missing_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_sha_only_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_sha_only_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "Illumina_annotation_sha_only_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_incorrect_checksum_MD5.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", - "Illumina_annotation_incorrect_checksum_MD5.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", - "Illumina_annotation_incorrect_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "Illumina_annotation_incorrect_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing_checksum_MD5.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", - "Illumina_annotation_missing_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "Illumina_annotation_missing_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", - "Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", - "Illumina_annotation_sha_only_checksum_SHA256.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", - "Illumina_annotation_sha_only_checksum_SHA256.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" + "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" + ], + [ + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt:lines,15", + "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt:lines,15", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt:lines,15", + "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt:lines,15", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt:lines,15", + "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt:lines,15", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt:lines,15", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt:lines,5", + "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt:lines,10", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt:lines,16", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt:lines,10", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:lines,1", + "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:lines,5", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt:lines,15", + "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt:lines,15" ] ], - "timestamp": "2026-09-02T18:26:27.114460768", + "timestamp": "2026-09-24T19:43:04.550413387", "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nf-test": "0.9.4", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/initialisation.nf.test b/tests/initialisation.nf.test new file mode 100644 index 0000000..a843425 --- /dev/null +++ b/tests/initialisation.nf.test @@ -0,0 +1,75 @@ +nextflow_workflow { + + name "Test PIPELINE_INITIALISATION" + script "../subworkflows/local/utils_nfcore_datasync_pipeline/main.nf" + workflow "PIPELINE_INITIALISATION" + tag "subworkflows" + tag "subworkflows_local" + tag "initialisation" + + test("Warn when remote SHA256 verification enables downloads") { + + when { + params { + input = "https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/test-data/samplesheet_edge.csv" + outdir = "$outputDir" + download = true + } + workflow { + """ + input[0] = false // version + input[1] = false // validate_params + input[2] = true // monochrome_logs + input[3] = [] // nextflow_cli_args + input[4] = params.outdir + input[5] = params.input + input[6] = false // help + input[7] = false // help_full + input[8] = false // show_hidden + """ + } + } + + then { + def nextflow_log = path("${launchDir}/meta/nextflow.log").text + assertAll( + { assert workflow.success }, + { assert nextflow_log.contains("The `--download` parameter is enabled") }, + { assert nextflow_log.contains("it may incur substantial cloud costs") } + ) + } + } + + test("Fail when remote SHA256 verification disables downloads") { + + when { + params { + input = "https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/test-data/samplesheet_edge.csv" + outdir = "$outputDir" + download = false + } + workflow { + """ + input[0] = false // version + input[1] = false // validate_params + input[2] = true // monochrome_logs + input[3] = [] // nextflow_cli_args + input[4] = params.outdir + input[5] = params.input + input[6] = false // help + input[7] = false // help_full + input[8] = false // show_hidden + """ + } + } + + then { + def nextflow_log = path("${launchDir}/meta/nextflow.log").text + assertAll( + { assert workflow.failed }, + { assert nextflow_log.contains("A SHA checksum file was provided for one or more remote files") }, + { assert nextflow_log.contains("Enable `--download` to proceed") } + ) + } + } +} diff --git a/tests/main_full.nf.test b/tests/main_full.nf.test index 640485d..e0cee16 100644 --- a/tests/main_full.nf.test +++ b/tests/main_full.nf.test @@ -18,15 +18,37 @@ nextflow_pipeline { def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) // stable_content: All files in ${params.outdir}/ with stable content def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') - assert workflow.success + // Summarise rclone outputs by line count and verify exit codes explicitly + def outdir_path = new File(params.outdir.toString()).toPath() + def rclone_line_counts = [] + def rclone_exit_codes = [:] + new File(params.outdir.toString(), 'rclone').eachFileRecurse { output_file -> + if (output_file.isFile() && output_file.name.endsWith('.txt')) { + def relative_path = outdir_path.relativize(output_file.toPath()).toString() + if (output_file.name.endsWith('.exit_code.txt')) { + rclone_exit_codes[relative_path] = output_file.text.trim() + } else { + rclone_line_counts << "${relative_path}:lines,${output_file.readLines().size()}" + } + } + } + rclone_line_counts.sort() assertAll( + { assert workflow.success }, + { assert rclone_exit_codes == [ + 'rclone/check_after/demultiplex/demultiplex_check.exit_code.txt': '0', + 'rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.exit_code.txt': '1', + 'rclone/checksum_before/demultiplex/demultiplex_checksum_SHA256.exit_code.txt': '0', + ] }, { assert snapshot( // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), // All stable path name, with a relative path stable_path, // All files with stable contents - stable_content + stable_content, + // Number of lines in each rclone check and checksum output + rclone_line_counts ).match() } ) } diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 7dfd8da..607914a 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -34,20 +34,20 @@ "pipeline_info", "pipeline_info/nf_core_datasync_software_mqc_versions.yml", "rclone", - "rclone/check", - "rclone/check/demultiplex", - "rclone/check/demultiplex/demultiplex_check.combined.txt", - "rclone/check/demultiplex/demultiplex_check.exit_code.txt", - "rclone/check/demultiplex/demultiplex_check.match.txt", - "rclone/checksum", - "rclone/checksum/demultiplex", - "rclone/checksum/demultiplex/demultiplex_checksum_MD5.combined.txt", - "rclone/checksum/demultiplex/demultiplex_checksum_MD5.exit_code.txt", - "rclone/checksum/demultiplex/demultiplex_checksum_MD5.match.txt", - "rclone/checksum/demultiplex/demultiplex_checksum_MD5.missing_on_src.txt", - "rclone/checksum/demultiplex/demultiplex_checksum_SHA256.combined.txt", - "rclone/checksum/demultiplex/demultiplex_checksum_SHA256.exit_code.txt", - "rclone/checksum/demultiplex/demultiplex_checksum_SHA256.match.txt", + "rclone/check_after", + "rclone/check_after/demultiplex", + "rclone/check_after/demultiplex/demultiplex_check.combined.txt", + "rclone/check_after/demultiplex/demultiplex_check.exit_code.txt", + "rclone/check_after/demultiplex/demultiplex_check.match.txt", + "rclone/checksum_before", + "rclone/checksum_before/demultiplex", + "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.combined.txt", + "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.exit_code.txt", + "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.match.txt", + "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.missing_on_src.txt", + "rclone/checksum_before/demultiplex/demultiplex_checksum_SHA256.combined.txt", + "rclone/checksum_before/demultiplex/demultiplex_checksum_SHA256.exit_code.txt", + "rclone/checksum_before/demultiplex/demultiplex_checksum_SHA256.match.txt", "rclone/copy", "rclone/copy/demultiplex-rclone-copy.log" ], @@ -57,23 +57,22 @@ "multiqc_rclone_checksum_md5.txt:md5,a68bd0275b5b6cb62ec966b68121b0e1", "multiqc_rclone_checksum_sha.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_rclone_exit_codes.txt:md5,2bc7209227358c54fa71dc3adb38d159", - "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca", - "demultiplex_check.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", - "demultiplex_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "demultiplex_check.match.txt:md5,902e4715d579b7f43a5463a220df8db0", - "demultiplex_checksum_MD5.combined.txt:md5,9250a5e20244b4beb397eab1a2003c3a", - "demultiplex_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "demultiplex_checksum_MD5.match.txt:md5,644b95db936b45b931143faefb15be7f", - "demultiplex_checksum_MD5.missing_on_src.txt:md5,b9f072c9e776951c6759590a8259f765", - "demultiplex_checksum_SHA256.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", - "demultiplex_checksum_SHA256.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", - "demultiplex_checksum_SHA256.match.txt:md5,902e4715d579b7f43a5463a220df8db0" + "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" + ], + [ + "rclone/check_after/demultiplex/demultiplex_check.combined.txt:lines,538", + "rclone/check_after/demultiplex/demultiplex_check.match.txt:lines,538", + "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.combined.txt:lines,538", + "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.match.txt:lines,502", + "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.missing_on_src.txt:lines,36", + "rclone/checksum_before/demultiplex/demultiplex_checksum_SHA256.combined.txt:lines,538", + "rclone/checksum_before/demultiplex/demultiplex_checksum_SHA256.match.txt:lines,538" ] ], - "timestamp": "2026-09-02T18:28:53.331210181", + "timestamp": "2026-09-24T19:45:47.394224218", "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nf-test": "0.9.4", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 3c1a12c..cb7a6d9 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -100,7 +100,7 @@ workflow DATASYNC { common ? tuple(meta, common) : null } - .filter { it != null } + .filter { common -> common != null } CREATE_FILTER_LIST(ch_files_to_copy) From b3b9581994acfc5031d03971c8a50ee89e815e82 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 25 Sep 2026 18:29:37 +0000 Subject: [PATCH 327/334] Move warning checks to edge test --- tests/edge.nf.test | 10 ++++- tests/initialisation.nf.test | 75 ------------------------------------ 2 files changed, 9 insertions(+), 76 deletions(-) delete mode 100644 tests/initialisation.nf.test diff --git a/tests/edge.nf.test b/tests/edge.nf.test index 291f494..c76c3f1 100644 --- a/tests/edge.nf.test +++ b/tests/edge.nf.test @@ -21,6 +21,7 @@ nextflow_pipeline { def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) // stable_content: All files in ${params.outdir}/ with stable content def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + def nextflow_log = path("${launchDir}/meta/nextflow.log").text // Summarise rclone outputs by line count and verify exit codes explicitly def outdir_path = new File(params.outdir.toString()).toPath() def rclone_line_counts = [] @@ -38,6 +39,8 @@ nextflow_pipeline { rclone_line_counts.sort() assertAll( { assert workflow.success }, + { assert nextflow_log.contains("The `--download` parameter is enabled") }, + { assert nextflow_log.contains("it may incur substantial cloud costs") }, { assert rclone_exit_codes == [ 'rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt': '0', 'rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt': '0', @@ -125,7 +128,12 @@ nextflow_pipeline { } then { - assert workflow.failed + def nextflow_log = path("${launchDir}/meta/nextflow.log").text + assertAll( + { assert workflow.failed }, + { assert nextflow_log.contains("A SHA checksum file was provided for one or more remote files") }, + { assert nextflow_log.contains("Enable `--download` to proceed") } + ) } } } diff --git a/tests/initialisation.nf.test b/tests/initialisation.nf.test deleted file mode 100644 index a843425..0000000 --- a/tests/initialisation.nf.test +++ /dev/null @@ -1,75 +0,0 @@ -nextflow_workflow { - - name "Test PIPELINE_INITIALISATION" - script "../subworkflows/local/utils_nfcore_datasync_pipeline/main.nf" - workflow "PIPELINE_INITIALISATION" - tag "subworkflows" - tag "subworkflows_local" - tag "initialisation" - - test("Warn when remote SHA256 verification enables downloads") { - - when { - params { - input = "https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/test-data/samplesheet_edge.csv" - outdir = "$outputDir" - download = true - } - workflow { - """ - input[0] = false // version - input[1] = false // validate_params - input[2] = true // monochrome_logs - input[3] = [] // nextflow_cli_args - input[4] = params.outdir - input[5] = params.input - input[6] = false // help - input[7] = false // help_full - input[8] = false // show_hidden - """ - } - } - - then { - def nextflow_log = path("${launchDir}/meta/nextflow.log").text - assertAll( - { assert workflow.success }, - { assert nextflow_log.contains("The `--download` parameter is enabled") }, - { assert nextflow_log.contains("it may incur substantial cloud costs") } - ) - } - } - - test("Fail when remote SHA256 verification disables downloads") { - - when { - params { - input = "https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/test-data/samplesheet_edge.csv" - outdir = "$outputDir" - download = false - } - workflow { - """ - input[0] = false // version - input[1] = false // validate_params - input[2] = true // monochrome_logs - input[3] = [] // nextflow_cli_args - input[4] = params.outdir - input[5] = params.input - input[6] = false // help - input[7] = false // help_full - input[8] = false // show_hidden - """ - } - } - - then { - def nextflow_log = path("${launchDir}/meta/nextflow.log").text - assertAll( - { assert workflow.failed }, - { assert nextflow_log.contains("A SHA checksum file was provided for one or more remote files") }, - { assert nextflow_log.contains("Enable `--download` to proceed") } - ) - } - } -} From e71380801b913aac935f5d36e5ddd9bdd2397844 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 25 Sep 2026 20:08:29 +0000 Subject: [PATCH 328/334] Fix linting --- docs/usage.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index f853a50..0ec72f6 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -55,10 +55,10 @@ rclone md5sum --config ./secure/rclone.conf s3:bucket/prefix > run_001_md5.txt Checksum manifests may use a `.tsv`, `.txt`, `.md5` or `.sha256` filename extension, but their contents are not tab-separated or comma-separated tables and must not include a header. Each record is plain text with the hash and path separated by exactly **two spaces**. The required fields are: -| Field | Required | Description | -| ----- | -------- | ------------------------------------------------------------------------------------------------------------------------ | -| Hash | Yes | MD5 hash for `checksum_md5` files or SHA-256 hash for `checksum_sha` files. | -| Path | Yes | Path relative to a directory `input`, or the file name (without parent directories) for a single-file `input`. | +| Field | Required | Description | +| ----- | -------- | ----------------------------------------------------------------------------------------------- | +| Hash | Yes | MD5 hash for `checksum_md5` files or SHA-256 hash for `checksum_sha` files. | +| Path | Yes | Path relative to a directory `input`, or the file name (without parent directories) for a single-file `input`. | Example samplesheet: From 29a298742480e2c34e9311b3f435a51a70e82dd6 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 25 Sep 2026 20:14:05 +0000 Subject: [PATCH 329/334] Fix linting --- docs/usage.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 0ec72f6..8966c72 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -55,9 +55,9 @@ rclone md5sum --config ./secure/rclone.conf s3:bucket/prefix > run_001_md5.txt Checksum manifests may use a `.tsv`, `.txt`, `.md5` or `.sha256` filename extension, but their contents are not tab-separated or comma-separated tables and must not include a header. Each record is plain text with the hash and path separated by exactly **two spaces**. The required fields are: -| Field | Required | Description | -| ----- | -------- | ----------------------------------------------------------------------------------------------- | -| Hash | Yes | MD5 hash for `checksum_md5` files or SHA-256 hash for `checksum_sha` files. | +| Field | Required | Description | +| ----- | -------- | -------------------------------------------------------------------------------------------------------------- | +| Hash | Yes | MD5 hash for `checksum_md5` files or SHA-256 hash for `checksum_sha` files. | | Path | Yes | Path relative to a directory `input`, or the file name (without parent directories) for a single-file `input`. | Example samplesheet: From fc53e8290d018760668733e9aa69303b5d00dd57 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 25 Sep 2026 21:07:31 +0000 Subject: [PATCH 330/334] Update release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16e19d8..f8048c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v1.0.0 - 2026-09-25 +## v1.0.0 - 2026-10-01 Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re/) template. From b6a189de31ed5a483133beff0530743ad68dfad2 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 25 Sep 2026 21:12:37 +0000 Subject: [PATCH 331/334] Use nft-csv for assertion of line counts for rclone output files --- nf-test.config | 1 + tests/default.nf.test | 24 ++----------- tests/default.nf.test.snap | 20 +++++------ tests/edge.nf.test | 52 ++++----------------------- tests/edge.nf.test.snap | 70 +++++++++++++++++++----------------- tests/main_full.nf.test | 23 ++---------- tests/main_full.nf.test.snap | 16 ++++----- 7 files changed, 69 insertions(+), 137 deletions(-) diff --git a/nf-test.config b/nf-test.config index f7aaeb4..c0c14da 100644 --- a/nf-test.config +++ b/nf-test.config @@ -34,5 +34,6 @@ config { // load the necessary plugins plugins { load "nft-utils@0.0.3" + load "nft-csv@0.1.0" } } diff --git a/tests/default.nf.test b/tests/default.nf.test index 0bc508e..0178b64 100644 --- a/tests/default.nf.test +++ b/tests/default.nf.test @@ -18,29 +18,11 @@ nextflow_pipeline { def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) // stable_content: All files in ${params.outdir}/ with stable content def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') - // Summarise rclone outputs by line count and verify exit codes explicitly - def outdir_path = new File(params.outdir.toString()).toPath() - def rclone_line_counts = [] - def rclone_exit_codes = [:] - new File(params.outdir.toString(), 'rclone').eachFileRecurse { output_file -> - if (output_file.isFile() && output_file.name.endsWith('.txt')) { - def relative_path = outdir_path.relativize(output_file.toPath()).toString() - if (output_file.name.endsWith('.exit_code.txt')) { - rclone_exit_codes[relative_path] = output_file.text.trim() - } else { - rclone_line_counts << "${relative_path}:lines,${output_file.readLines().size()}" - } - } - } - rclone_line_counts.sort() + // Summarise rclone outputs by line count + def rclone_reports = getAllFilesFromDir(params.outdir, relative: true, include: ['rclone/**/*.txt']) + def rclone_line_counts = rclone_reports.findAll { !it.endsWith('.exit_code.txt') }.collect { file -> "${file.tokenize('/').last()}:lines,${path("${params.outdir}/${file}").csv(header: false).rowCount}" } assertAll( { assert workflow.success }, - { assert rclone_exit_codes == [ - 'rclone/check_after/Illumina_annotation/Illumina_annotation_check.exit_code.txt': '0', - 'rclone/check_after/benchmark_bed/benchmark_bed_check.exit_code.txt': '0', - 'rclone/checksum_before/Illumina_annotation/Illumina_annotation_checksum_MD5.exit_code.txt': '0', - 'rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.exit_code.txt': '1', - ] }, { assert snapshot( // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index d9521ce..3eb8676 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -64,18 +64,18 @@ "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4" ], [ - "rclone/check_after/Illumina_annotation/Illumina_annotation_check.combined.txt:lines,15", - "rclone/check_after/Illumina_annotation/Illumina_annotation_check.match.txt:lines,15", - "rclone/check_after/benchmark_bed/benchmark_bed_check.combined.txt:lines,1", - "rclone/check_after/benchmark_bed/benchmark_bed_check.match.txt:lines,1", - "rclone/checksum_before/Illumina_annotation/Illumina_annotation_checksum_MD5.combined.txt:lines,15", - "rclone/checksum_before/Illumina_annotation/Illumina_annotation_checksum_MD5.match.txt:lines,15", - "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.combined.txt:lines,10", - "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.match.txt:lines,1", - "rclone/checksum_before/benchmark_bed/benchmark_bed_checksum_MD5.missing_on_src.txt:lines,9" + "Illumina_annotation_check.combined.txt:lines,15", + "Illumina_annotation_check.match.txt:lines,15", + "benchmark_bed_check.combined.txt:lines,1", + "benchmark_bed_check.match.txt:lines,1", + "Illumina_annotation_checksum_MD5.combined.txt:lines,15", + "Illumina_annotation_checksum_MD5.match.txt:lines,15", + "benchmark_bed_checksum_MD5.combined.txt:lines,10", + "benchmark_bed_checksum_MD5.match.txt:lines,1", + "benchmark_bed_checksum_MD5.missing_on_src.txt:lines,9" ] ], - "timestamp": "2026-09-24T19:40:39.867871956", + "timestamp": "2026-09-25T20:57:06.12156578", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" diff --git a/tests/edge.nf.test b/tests/edge.nf.test index c76c3f1..b6e3fef 100644 --- a/tests/edge.nf.test +++ b/tests/edge.nf.test @@ -22,33 +22,13 @@ nextflow_pipeline { // stable_content: All files in ${params.outdir}/ with stable content def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') def nextflow_log = path("${launchDir}/meta/nextflow.log").text - // Summarise rclone outputs by line count and verify exit codes explicitly - def outdir_path = new File(params.outdir.toString()).toPath() - def rclone_line_counts = [] - def rclone_exit_codes = [:] - new File(params.outdir.toString(), 'rclone').eachFileRecurse { output_file -> - if (output_file.isFile() && output_file.name.endsWith('.txt')) { - def relative_path = outdir_path.relativize(output_file.toPath()).toString() - if (output_file.name.endsWith('.exit_code.txt')) { - rclone_exit_codes[relative_path] = output_file.text.trim() - } else { - rclone_line_counts << "${relative_path}:lines,${output_file.readLines().size()}" - } - } - } - rclone_line_counts.sort() + // Summarise rclone outputs by line count + def rclone_reports = getAllFilesFromDir(params.outdir, relative: true, include: ['rclone/**/*.txt']) + def rclone_line_counts = rclone_reports.findAll { !it.endsWith('.exit_code.txt') }.collect { file -> "${file.tokenize('/').last()}:lines,${path("${params.outdir}/${file}").csv(header: false).rowCount}" } assertAll( { assert workflow.success }, { assert nextflow_log.contains("The `--download` parameter is enabled") }, { assert nextflow_log.contains("it may incur substantial cloud costs") }, - { assert rclone_exit_codes == [ - 'rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt': '0', - 'rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt': '0', - 'rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt': '0', - 'rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt': '1', - 'rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt': '1', - 'rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt': '1', - ] }, { assert snapshot( // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), @@ -79,31 +59,11 @@ nextflow_pipeline { def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) // stable_content: All files in ${params.outdir}/ with stable content def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') - // Summarise rclone outputs by line count and verify exit codes explicitly - def outdir_path = new File(params.outdir.toString()).toPath() - def rclone_line_counts = [] - def rclone_exit_codes = [:] - new File(params.outdir.toString(), 'rclone').eachFileRecurse { output_file -> - if (output_file.isFile() && output_file.name.endsWith('.txt')) { - def relative_path = outdir_path.relativize(output_file.toPath()).toString() - if (output_file.name.endsWith('.exit_code.txt')) { - rclone_exit_codes[relative_path] = output_file.text.trim() - } else { - rclone_line_counts << "${relative_path}:lines,${output_file.readLines().size()}" - } - } - } - rclone_line_counts.sort() + // Summarise rclone outputs by line count + def rclone_line_counts = getAllFilesFromDir(params.outdir, relative: true, include: ['rclone/**/*.txt']) + rclone_line_counts = rclone_line_counts.collect { file -> "${file.tokenize('/').last()}:lines,${path("${params.outdir}/${file}").csv(header: false).rowCount}" } assertAll( { assert workflow.success }, - { assert rclone_exit_codes == [ - 'rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.exit_code.txt': '0', - 'rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.exit_code.txt': '0', - 'rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.exit_code.txt': '0', - 'rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt': '1', - 'rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt': '1', - 'rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt': '1', - ] }, { assert snapshot( // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index 73b1649..53d3698 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -79,24 +79,30 @@ "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" ], [ - "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt:lines,15", - "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt:lines,15", - "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt:lines,15", - "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt:lines,15", - "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt:lines,15", - "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt:lines,15", - "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt:lines,15", - "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt:lines,5", - "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt:lines,10", - "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt:lines,16", - "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt:lines,10", - "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:lines,1", - "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:lines,5", - "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt:lines,15", - "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt:lines,15" + "Illumina_annotation_incorrect_check.combined.txt:lines,15", + "Illumina_annotation_incorrect_check.exit_code.txt:lines,1", + "Illumina_annotation_incorrect_check.match.txt:lines,15", + "Illumina_annotation_missing_check.combined.txt:lines,15", + "Illumina_annotation_missing_check.exit_code.txt:lines,1", + "Illumina_annotation_missing_check.match.txt:lines,15", + "Illumina_annotation_sha_only_check.combined.txt:lines,15", + "Illumina_annotation_sha_only_check.exit_code.txt:lines,1", + "Illumina_annotation_sha_only_check.match.txt:lines,15", + "Illumina_annotation_incorrect_checksum_MD5.combined.txt:lines,15", + "Illumina_annotation_incorrect_checksum_MD5.differ.txt:lines,5", + "Illumina_annotation_incorrect_checksum_MD5.exit_code.txt:lines,1", + "Illumina_annotation_incorrect_checksum_MD5.match.txt:lines,10", + "Illumina_annotation_missing_checksum_MD5.combined.txt:lines,16", + "Illumina_annotation_missing_checksum_MD5.exit_code.txt:lines,1", + "Illumina_annotation_missing_checksum_MD5.match.txt:lines,10", + "Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:lines,1", + "Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:lines,5", + "Illumina_annotation_sha_only_checksum_SHA256.combined.txt:lines,15", + "Illumina_annotation_sha_only_checksum_SHA256.differ.txt:lines,15", + "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:lines,1" ] ], - "timestamp": "2026-09-24T19:43:28.768757814", + "timestamp": "2026-09-25T21:08:28.030377512", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" @@ -180,24 +186,24 @@ "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" ], [ - "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt:lines,15", - "rclone/check_after/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt:lines,15", - "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt:lines,15", - "rclone/check_after/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt:lines,15", - "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt:lines,15", - "rclone/check_after/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt:lines,15", - "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt:lines,15", - "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt:lines,5", - "rclone/checksum_before/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt:lines,10", - "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt:lines,16", - "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt:lines,10", - "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:lines,1", - "rclone/checksum_before/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:lines,5", - "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt:lines,15", - "rclone/checksum_before/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt:lines,15" + "Illumina_annotation_incorrect_check.combined.txt:lines,15", + "Illumina_annotation_incorrect_check.match.txt:lines,15", + "Illumina_annotation_missing_check.combined.txt:lines,15", + "Illumina_annotation_missing_check.match.txt:lines,15", + "Illumina_annotation_sha_only_check.combined.txt:lines,15", + "Illumina_annotation_sha_only_check.match.txt:lines,15", + "Illumina_annotation_incorrect_checksum_MD5.combined.txt:lines,15", + "Illumina_annotation_incorrect_checksum_MD5.differ.txt:lines,5", + "Illumina_annotation_incorrect_checksum_MD5.match.txt:lines,10", + "Illumina_annotation_missing_checksum_MD5.combined.txt:lines,16", + "Illumina_annotation_missing_checksum_MD5.match.txt:lines,10", + "Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:lines,1", + "Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:lines,5", + "Illumina_annotation_sha_only_checksum_SHA256.combined.txt:lines,15", + "Illumina_annotation_sha_only_checksum_SHA256.differ.txt:lines,15" ] ], - "timestamp": "2026-09-24T19:43:04.550413387", + "timestamp": "2026-09-25T21:08:07.665367476", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" diff --git a/tests/main_full.nf.test b/tests/main_full.nf.test index e0cee16..42b21df 100644 --- a/tests/main_full.nf.test +++ b/tests/main_full.nf.test @@ -18,28 +18,11 @@ nextflow_pipeline { def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) // stable_content: All files in ${params.outdir}/ with stable content def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') - // Summarise rclone outputs by line count and verify exit codes explicitly - def outdir_path = new File(params.outdir.toString()).toPath() - def rclone_line_counts = [] - def rclone_exit_codes = [:] - new File(params.outdir.toString(), 'rclone').eachFileRecurse { output_file -> - if (output_file.isFile() && output_file.name.endsWith('.txt')) { - def relative_path = outdir_path.relativize(output_file.toPath()).toString() - if (output_file.name.endsWith('.exit_code.txt')) { - rclone_exit_codes[relative_path] = output_file.text.trim() - } else { - rclone_line_counts << "${relative_path}:lines,${output_file.readLines().size()}" - } - } - } - rclone_line_counts.sort() + // Summarise rclone outputs by line count + def rclone_reports = getAllFilesFromDir(params.outdir, relative: true, include: ['rclone/**/*.txt']) + def rclone_line_counts = rclone_reports.findAll { !it.endsWith('.exit_code.txt') }.collect { file -> "${file.tokenize('/').last()}:lines,${path("${params.outdir}/${file}").csv(header: false).rowCount}" } assertAll( { assert workflow.success }, - { assert rclone_exit_codes == [ - 'rclone/check_after/demultiplex/demultiplex_check.exit_code.txt': '0', - 'rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.exit_code.txt': '1', - 'rclone/checksum_before/demultiplex/demultiplex_checksum_SHA256.exit_code.txt': '0', - ] }, { assert snapshot( // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 607914a..c45febe 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -60,16 +60,16 @@ "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" ], [ - "rclone/check_after/demultiplex/demultiplex_check.combined.txt:lines,538", - "rclone/check_after/demultiplex/demultiplex_check.match.txt:lines,538", - "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.combined.txt:lines,538", - "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.match.txt:lines,502", - "rclone/checksum_before/demultiplex/demultiplex_checksum_MD5.missing_on_src.txt:lines,36", - "rclone/checksum_before/demultiplex/demultiplex_checksum_SHA256.combined.txt:lines,538", - "rclone/checksum_before/demultiplex/demultiplex_checksum_SHA256.match.txt:lines,538" + "demultiplex_check.combined.txt:lines,538", + "demultiplex_check.match.txt:lines,538", + "demultiplex_checksum_MD5.combined.txt:lines,538", + "demultiplex_checksum_MD5.match.txt:lines,502", + "demultiplex_checksum_MD5.missing_on_src.txt:lines,36", + "demultiplex_checksum_SHA256.combined.txt:lines,538", + "demultiplex_checksum_SHA256.match.txt:lines,538" ] ], - "timestamp": "2026-09-24T19:45:47.394224218", + "timestamp": "2026-09-25T21:10:24.321051089", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" From bd709bf56f902c12f36a5e9bffaba7bafa2c85d5 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 25 Sep 2026 22:12:56 +0000 Subject: [PATCH 332/334] Add back md5 snapshots --- tests/.nftignore | 1 - tests/default.nf.test.snap | 17 ++++++++++-- tests/edge.nf.test.snap | 50 +++++++++++++++++++++++++++++++++--- tests/main_full.nf.test.snap | 14 ++++++++-- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/tests/.nftignore b/tests/.nftignore index 0c88efe..b1e73cd 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -11,4 +11,3 @@ multiqc/multiqc_report.html fastqc/*_fastqc.{html,zip} pipeline_info/*.{html,json,txt,yml} rclone/**/*.log -rclone/**/*.txt diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 3eb8676..1b63cec 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -61,7 +61,20 @@ "multiqc_rclone_check.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", "multiqc_rclone_checksum_md5.txt:md5,c7127de966d1be295ef6697dba648c79", "multiqc_rclone_exit_codes.txt:md5,d970d9335584ff1e7349036e62f5e8d4", - "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4" + "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4", + "Illumina_annotation_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "Illumina_annotation_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "benchmark_bed_check.combined.txt:md5,dcd2c539696adba720986251dcd1aaef", + "benchmark_bed_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "benchmark_bed_check.match.txt:md5,12608858576bec12c65ff338a99803c3", + "Illumina_annotation_checksum_MD5.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_checksum_MD5.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "Illumina_annotation_checksum_MD5.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "benchmark_bed_checksum_MD5.combined.txt:md5,592b2b2af44551686a8057f585309413", + "benchmark_bed_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "benchmark_bed_checksum_MD5.match.txt:md5,12608858576bec12c65ff338a99803c3", + "benchmark_bed_checksum_MD5.missing_on_src.txt:md5,7bf2def3eed9eff615a0f29ae1652254" ], [ "Illumina_annotation_check.combined.txt:lines,15", @@ -75,7 +88,7 @@ "benchmark_bed_checksum_MD5.missing_on_src.txt:lines,9" ] ], - "timestamp": "2026-09-25T20:57:06.12156578", + "timestamp": "2026-09-25T22:09:52.86634064", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index 53d3698..fe36703 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -76,7 +76,28 @@ "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_rclone_exit_codes.txt:md5,3dd8d4741882ff589545c2f2fcc99520", - "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" + "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", + "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_incorrect_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_missing_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_missing_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "Illumina_annotation_missing_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_sha_only_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "Illumina_annotation_sha_only_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_incorrect_checksum_MD5.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", + "Illumina_annotation_incorrect_checksum_MD5.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_incorrect_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_incorrect_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing_checksum_MD5.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", + "Illumina_annotation_missing_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_missing_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", + "Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_sha_only_checksum_SHA256.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", + "Illumina_annotation_sha_only_checksum_SHA256.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ], [ "Illumina_annotation_incorrect_check.combined.txt:lines,15", @@ -102,7 +123,7 @@ "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:lines,1" ] ], - "timestamp": "2026-09-25T21:08:28.030377512", + "timestamp": "2026-09-25T22:10:33.913797083", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" @@ -183,7 +204,28 @@ "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_rclone_exit_codes.txt:md5,3dd8d4741882ff589545c2f2fcc99520", - "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" + "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", + "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_incorrect_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_missing_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_missing_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "Illumina_annotation_missing_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_sha_only_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "Illumina_annotation_sha_only_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_incorrect_checksum_MD5.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", + "Illumina_annotation_incorrect_checksum_MD5.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_incorrect_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_incorrect_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing_checksum_MD5.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", + "Illumina_annotation_missing_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_missing_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", + "Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_sha_only_checksum_SHA256.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", + "Illumina_annotation_sha_only_checksum_SHA256.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ], [ "Illumina_annotation_incorrect_check.combined.txt:lines,15", @@ -203,7 +245,7 @@ "Illumina_annotation_sha_only_checksum_SHA256.differ.txt:lines,15" ] ], - "timestamp": "2026-09-25T21:08:07.665367476", + "timestamp": "2026-09-25T22:10:13.501072101", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index c45febe..fc2adf1 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -57,7 +57,17 @@ "multiqc_rclone_checksum_md5.txt:md5,a68bd0275b5b6cb62ec966b68121b0e1", "multiqc_rclone_checksum_sha.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_rclone_exit_codes.txt:md5,2bc7209227358c54fa71dc3adb38d159", - "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" + "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca", + "demultiplex_check.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", + "demultiplex_check.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "demultiplex_check.match.txt:md5,902e4715d579b7f43a5463a220df8db0", + "demultiplex_checksum_MD5.combined.txt:md5,9250a5e20244b4beb397eab1a2003c3a", + "demultiplex_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "demultiplex_checksum_MD5.match.txt:md5,644b95db936b45b931143faefb15be7f", + "demultiplex_checksum_MD5.missing_on_src.txt:md5,b9f072c9e776951c6759590a8259f765", + "demultiplex_checksum_SHA256.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", + "demultiplex_checksum_SHA256.exit_code.txt:md5,897316929176464ebc9ad085f31e7284", + "demultiplex_checksum_SHA256.match.txt:md5,902e4715d579b7f43a5463a220df8db0" ], [ "demultiplex_check.combined.txt:lines,538", @@ -69,7 +79,7 @@ "demultiplex_checksum_SHA256.match.txt:lines,538" ] ], - "timestamp": "2026-09-25T21:10:24.321051089", + "timestamp": "2026-09-25T22:12:32.711478602", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.4" From ba46be6f6e7a7cf7cc629f0b3c402e9d33c8293e Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Mon, 28 Sep 2026 09:38:01 -0300 Subject: [PATCH 333/334] Clarify output_path usage in documentation --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index 7dab8aa..b37a1d7 100644 --- a/docs/output.md +++ b/docs/output.md @@ -5,7 +5,7 @@ This document describes the reports produced by nf-core/datasync. Paths below are relative to the directory supplied with `--outdir`. > [!IMPORTANT] -> The copied payload is written to each samplesheet row's `output_path`. It is not placed in `--outdir` unless `output_path` explicitly points there. +> The copied payload is written to each samplesheet row's `output_path`. It is not placed in `--outdir` unless `output_path` explicitly points to the same path as the one specified for `--outdir`. ## Output overview From e6869120c9f6e09c2fdc7f2ba26218a1281f668c Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Mon, 28 Sep 2026 16:12:20 -0300 Subject: [PATCH 334/334] Change release date for v1.0.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8048c1..c978e73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v1.0.0 - 2026-10-01 +## v1.0.0 - 2026-09-28 Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re/) template.
    Output files From 70519cc902a14b158fef9efbf161142e77e66990 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 12:03:52 -0300 Subject: [PATCH 205/334] Update docs/output.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index bdbfdcd..51e9334 100644 --- a/docs/output.md +++ b/docs/output.md @@ -71,7 +71,7 @@ Two integrity stages create reports: Both stages use the same `.*.txt` naming convention and publish to `rclone/`. When a row supplies a checksum manifest, similarly named pre-copy and post-copy files may target the same published path; use the consolidated MultiQC sections for the stage-specific summary and retain the Nextflow work directory if both raw report sets must be audited independently. -The combined files use rclone's one-character status prefixes: +The combined files use `rclone`'s one-character status prefixes: | Prefix | Meaning | Action | | ------ | ------------------------ | --------------------------------------------------------------------------------------------------------------------------- | From 1983a4fe5d4162655cbe70e23f1d7571f1e0c7ca Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 12:04:03 -0300 Subject: [PATCH 206/334] Update docs/output.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index 51e9334..dd3c212 100644 --- a/docs/output.md +++ b/docs/output.md @@ -81,7 +81,7 @@ The combined files use `rclone`'s one-character status prefixes: | `*` | Content differs | Re-copy or investigate source/destination mutation. | | `!` | Read/hash error | Inspect permissions, credentials, connectivity, and the copy log. | -Empty category files mean that rclone reported no entries in that category. The commands are designed to preserve these reports rather than terminate the whole workflow on comparison differences. Always inspect the reports; workflow success alone is not an integrity guarantee. +Empty category files mean that `rclone` reported no entries in that category. The commands are designed to preserve these reports rather than terminate the whole workflow on comparison differences. Always inspect the reports; workflow success alone is not an integrity guarantee. ## MultiQC From e9a292a5870a501f2079995209d8cef70061b194 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 12:04:16 -0300 Subject: [PATCH 207/334] Update docs/usage.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index f3a1288..c498483 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -66,7 +66,7 @@ ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad reports/qc_sum An [example samplesheet](../assets/samplesheet.csv) is included in the repository. -## Configuring rclone remotes +## Configuring `rclone` remotes The file supplied with `--rclone_config` uses rclone's INI-style format. Each `[name]` section defines a remote, and samplesheet paths refer to it as `name:path`. The remote name is an arbitrary local label; it does not need to match the provider or bucket name. The pipeline's documented and tested configuration pattern is S3-to-S3 transfer. One file may contain several sections, so other cloud-to-cloud transfers can define both providers in the same file, but provider-specific options should be taken from the relevant rclone documentation rather than inferred from the S3 example: From e5dd0178b2cc7bfeb2db69c6a2abf0ad0164c692 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:04:30 -0300 Subject: [PATCH 208/334] Delete docs/images/datasync-metromap.drawio.png --- docs/images/datasync-metromap.drawio.png | Bin 59786 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png deleted file mode 100644 index 2f17a1e3af56ca896c5835c690f6387dba354e61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59786 zcmeEv2S8Iv`ZypWtX)y8fFgrL-u?FO_U`Yl?!GrOZ|0k?&3t7h#|-tgmj1NiCk_sd zr6_H6V-61PCE$6Cmk0b;6j$lQ!4arR(XgZt16=V07YYZ>dp3DYl5)DrvIElhFr6pjXO3VW9i6!}y!K1z@_>UwE z6eCo@6R41pVmt=ONbLkADqda$7Yi3>T|DSlQyL*Ffsg^kV!GOBPwT5wT>hA2!0G==^k)R-s% zFP=_dY&xn80anDBpX0HNGG7l%H?l7Uujg)|udN?oX63FUKEF3spTqzyA15z2GzsfM z03Blkm;lMkGdsmnnI&@aQVb|@KCFS5O`rl3JdFvFG_#d29_vD8e#HdQB#2hNA& z>xpH|`=1(~Z06;uui+bjLThSUtGc?wNh+%1l0ZNpOuArMB$}bwEI_{pIGI9aNrsCj zRt4e)fPPPsCjed5jY1@VH%ahFhu#I^3+Rmuq|Rf8*piR}U=*p52qcD7A>dNZFs43$ zAY?-a1oH1wZkB#pEF$q# zFbjww2@g~v9LAJdad{>LOqmszgu$34tg*->UmuJM^E(Iyf1m7(;r`~JaHhbs#*~+r zmyl&nnl&oL$p_~``6ot20ClVhbQB9izfU1%Yr1&-y_Vld;dfb?i9M#0a&l&|C9|Ae z!u}vbLn7zJkdJxX2iVcYhvLH0z<&ZmveXhevdu>2*3RK zRQQhi_&sW|sSlvLy&yTn6Y0x^suS6ZvDmoc10cnr%B)bwI#HZN5h{#VxF*>TCkj^$ z0GbA_W~eSNc?0bO=_K#sq6MRfLnJF$twX@O47y zyIWbR5>RSxB&@cvzX4v(4~xJe^oX-{dPI4uHC4_Fr3RxI;z+uN+WK&7e-aJ_^WP%+zCv1OgVO zucqRUQbz^oxodzvtPtRtrss|eK)ajyqw$RX=3ycLg`>mZWevW^Agn$0X=pgB zt&5f<+1V2fu;2#6YOBcTQRTs`FuqtC+SeJOfU{Gjic{QztS_+n^YG%OMG z$G&ryg61h_tz}Nc(D9*yLunB_3{7-AtSzi*03JyL6BJI5#%wpY4cW?)K)|?b;MMTp zJAf|?!dTi_3!fnGsSny3 z6Li(l2t9Wd7@z|JP4%asO^y8Z+)-2mQw@Z!2@2u_#z=Au>M=%jvM>T8Vgd}*jie0J zU^G2b)C@#`!Y~X`(-#A`_QMci@+eQn=+0W2Fl!SW7{Lmz=WZpXPcxF%Q#S&mTT%7Z zJ*4%i9_)S4u-XK&HGmfIEDfU-;O1iL<>gEa0DsN!fTQTMhcJl&{W_`4yh9wupe|Id z4*I59QS{Yd{(7cXZ2d!6(TBNM1P}n`iB1*)WCOfD(VG6Rl`Oz2)frA9=viXDthJ3v z2JR}pXm_-~K23!>gH?ciFcw5P3QAprhQ>=lScB{1{iOltN~7H|pgjtQ#j8+(3K>8?YW@KKQc?z{W>RPXvlUgvAB+ug0$g9+42-Qp zL90no_1%r2w$QUA+T8=p$q1)ss^Y6}3c-sZ)1PS`fQ!wjC@p_bXXFcLivV~5b!cA$ zFegBFDU=qP{vF!g3Rpon`ghD{DKLL9t{I&J88FbF;reQH7^DDR0ng2a0pJwOQwoMw zH-qV$s8GOMq|r2tB*3pbqdyG&T~A#Fj0?054dQSVdG0*e%1xwbXa)^%Xf=OGLL~J~ z%_IRH{Pol|U_j#ppiMRW8SgV12+$s?2l!y%0DQ~D6V)GRDKr(}j0$*Vc6`=2cvTWg z9Ru)#M(CSr;8^fOcmjO@{DE>cf1vGH-$MAD!8;D{7Xw}sfEU&?#4lPfw)tw10gZsh zrPD(SrGdktP0>^)ufb88RyZ&YfB}U-tK(oOEvOzE14l#C&=4Pkd1K%}yE6C#%o9!1 z0Pw0vp`d4X6`H;&dJaz6=Fg%jpd&O_z!x+in_#XkOic}GvpE{gQy=INc^_*NN#=?{ zg7}dJX{tXg2Sjssthxr^X`p9JtpIKqtHL*95v{$Pwfrd4qUv2pCT^q@C${ph0Prs8R|Ck1DjckqU_3Jz;By@4UrOK9hziQV*ecMs zaL^vclsWLMfdDcGt+W9^A24}}IS$Zm09HvLXF#uOfR#iA=ykfBLA(XzRRh6%p942T zSC~mNb3L7yzx0l%}st_A~r<0SRfQP8-oXP|Q+d7w9E&F^(Ne=Mlc%y^8-zxCzZvF3gV)%~sS z<^ehPLwe=+znojj{u#Yy{!Cc2U{uZpc5dA~fY>YNjtOeOAISgq9V7eSYUZ#EP<9jh zKV!oHOhCwBw;2DR4FgO<;8bGwd(3rfF#RIHpGshPI+#UH1U$|YNEQaTfgr!4Dr8{d zfsaguSwX~Ov5-lt>hFf9xR`i3VIX74A9w^o*{pYk;Y{xW1u<)M$$0xh zUNCxvIGOGjgnXD_?!f2-Ji)35WtbVy%xodTmHyA1c93-@4hO{m7ATt;3HAL&%<~REKaqD@6=< z7$^dm|E>~1Fum0CJVd|m)0*|r&A7|{V*W`<1cTL>oF@*s3gr>NN6GvLtRn23_~-j7 zCFSNp@U4UNzt&aB^27d>z3%@vvH2g925|(4QP3HlT^?klSkeH4{mbP+96ld}|0RK# z3HANMQ74w$m`ri;#NY{He%6*)3<-_XKv}rD5h%d5h&KV=5PgIc+R4nz!wI9W;vww| zSI2pKO6t(`CCTcBE-pIG@)l?*s-CWn4$)Op4TW-(varI#jQotSD&|ya4_AL0g{Eg^ zVqmRdrHwO{rQ$TbbfkQxeRQNSzyYr5W2gdmmUN{O zO=#LMvXM7NPR`ZTOx6hx!ZNDvAX=_UlCr=A=t%nzWUbBR%`6Soq5YOIOw-p-)!Gtf z>FQ;mMZlZOO2f=Fsos_(BR4mKmnu$!Y~*BSDdkVXBi!-2Dy~i%Xd^k`4kGD$$QgRd z`kGl$td;vhVsr>eJxEH zV{?RYfS;QYv_ISlmf`PhY1v|j--#A}X9qoZr!5Kx0Yp_s0Pzo-s*q^}{ROhl{L3j{x0|0NsxO9V=S+BS80k3zT77{LAf4mdV0qZ?f_b|3X#_ zGrj$vv10y5LUfXn|Fa=F*sRSt8}Va%qDSzIF$5^b{2vM7F`|7~ydNtH$oiTY7X9yx zaDE3{jOgo3H1|8K!is9nghjv83&0LDI?TeC8p+cY4}6XPK-hGq=^V5}j-Wp~f%<aY zo)Kt}6$i4l;ntQqG$#vrUyuh4WhjA6ZEG*!*;jK$;N(&6P}Y|Ultmi=GUz}~vd3)3 zAjl-Nwjg*qX@d-1cVx?@ZRM70B+wNdlZn>ZzN7EHEe|RYMY` zZ8eJzkmacFj`jtaZD^2H2QoR0;2_f$Y7g*-gRhjAyl0~|s*;r<42dIq5kipF?HtD$i8ENM?wH>?&8WIBS( zP*XDs$hM<^eDgW@Vq};xu`H*D031YG;5}QfLDq^WA1gl_HO-V9sw7-s;VjY(I=d*6;2Qq&r7fhNt=UD>={^L+ABiHTQ z|3cRZFprtC4#i4=GyC&m+4Ayo5^}QenSYq^OBPrC`FUqj^6+nAV4gQ;jrw1kcqYw^ z!vFIk@Z-2QuwDPopYL$CfpL(EnaeX6lI_oD5|q z1LFqrsj#ikti_H+X!cVTef3R`v0B?$x6@p z|G@GBBx?hZ2&IIQPy01hC6gRlYMKr{s$5C#WJ>Bscp;8;1s zH9`c3x-HD9;J7=;&YW>Ffn%VC+H|MM?>JDvk!JkN(QAKjj9Ch;jshe4vz$rLg#gfz zRp9WUA4g_)-Y|}PgR2g}QSzCi-UfIy-H`*FIWuLm$G=g&^rO$}=-E08=qS25xClW- z#>&$ihE=D4BkMYTPH;1dGjz>@g_oa`g_Ml51px*eS!~})dSSK9sh|zT$Tf{uH{4kCla`FSfB5Jh6fV$Y9k|kVA^5pK2hV^T460yW79|PY+5^3_j;&!`T%COB zhpPT_Rw!#7U|OLvuz9wFBuw%@=__;7wU#ESJE(gSjlD_YMqY+87)jRsU;q5J` ztXs4G4K}Dt0G?tA%wfo73O!q~JU zR6y@bLP|!KRWREjR6W}x^ftds21~LZ-TE#qn0w)QG4(&PJA!ujf7O#)f8?OZpKoih zjx@3F3jZ6gmijKEFsVJYH{HK4GlFUKfjeZ}F)Xtf+=WBWtoSxNLfr$7CeF){VB8-C zeS?^19?zJ-?Aa1C#_OMyApzYV2JYp8p=l~KkRd?>@6cUh;7&1(`56+D^D`ts_62(e z1$R|i=vf8ai~|BI0g?t+qZCK~g9;lTc7 zU84rofs5VTDB@Tr9}h7foU<4(b0F)H^*>-jLa$H_9J=uVdSQRq30<54z?_$(Px1mc zl6(*L|CBk&Tvh)gV(?valIhm^-`Q@l5`viJ|wzjfcki~_K^nOKVwbKfJyx)+Uo-^17m{YQxK-F1p}Lg4SNQ%q{H z?RtK!Q$NiCzbu=Oxj_F%*4pphlE8F>urIYt7}>&*rqC}o(A_0}B(>q2goW=8%=9q* z{=gamATu6%$t?3^ZVRp0+L}VCeS4xfAZud|Ip<1@ScDE)S24< z_a}}5_Rb%mIQ@q(|He-OGk+wL?Z=nd^P1?jte<;kR4_k)el?r%JGCFTZB60eSiu2) zTFNwlv-|R*1Dl?X4#!{UEI7PDCzYF(_GCJx4dtg!u|;#`hOq(9Bi1Jl5D*Vi7-z_q+MZe|X3>?s8)y zd}`N)hsz6EroEqv-pR{vEWPiwB7}omn1hoS$-zZ`e61X+a`T}h%nj>u_Wh!!6G!b% zb)+C%(HA{=N7`Ws?{-#%>6=Fv<9bsZeugTrtzvrCzXiXX>ewTSq zT9IJz^QyK8*kC7Tb93qZAFso6ZJYg2 z%GWP^5}W4Cmm_pP?+WP^TKJlbfLe)Sd7SZn0mDc^zT5B1G(RCT%P8rnIX4ZRa&Q z&oRED<1hzLnEk^Qw&vUy`)$2JTUKs+ui5~WI zTdD0p>hnfO0z9}J@anXV=k^<_83%kchuO4wzbxlk(Xl<`Q9_Kyb;47tebM53bkooB z9p9>iIun^2+Y@J3H;$6S-fXAN`?Lie&9If&X08l= zt`)bu0GPWbxD&?N;JTn15~K=vX5A*xSy+qNvfK9>lV7bhmpW)iDc4wBe(|cSAuq>U zPA0z~kF89|fj;lo15n0sMr!wIC|fnTT|3o(D!pTU>qd@`YD^Af`uzM+aoK$l+rm_Y@NkxnIHShJzYsu}(9g?1sh-xqj8Eyvth5&^ zaPFcjmCztQM_7lzNj*36)BGuPW-6mwk#yt>g8{aLJaWX|4>wJ+34FRE_l@nQqOU?; z4>`?u?i+Zm)^4!ib=tMm^9RT?%Iu6XSHu#=)WlXoqTY&JdM|2Gz|^o^A!Tz{3FWJ; zZ>5>}&fL$rU2QM8-;MvI@N{yKZOZ*2FP895t`g>CkSf6zU{b7Fq`omlXuQp|dX+@O zL*BdH&pjyzD;QcZv}7xiw1ugcJ0PxKt-e06D8jqBzcEwfs~snUPmmAz4EM9huOq^N^!xYtBJs}aD`JmCS{zV+^ z)6T$mp^LinnkPN0q%_vvC!Wnb+QwoHCIn*Z0DCV~Q`)-bREb4WsYKpgVn(^<&^4h+ zv2xcKqHEyioSSxjwJv@ijwv-IUXoHf^791?`&x5bZw(vA(1qtxw@%ACoXrkzgD5UW z<)X0EZ0H97bV5Kl8kN!gWVv$2dHsFQWtsvodA$$DSE)VB?Mn7g=uQo53>xnlD%qV< z)0I-_89Z9*K&U{=_I#>XrMt(;w)Kc3o<6i9_ zC!Fg&CEJvWi=#eUrZix9{_KZCizQOCn`ou`CkIT%yBwz7k8bkOwumCoC;jl3)d`#| zhKg7TDLo2ID}DF$c=I&jb3@MBqO^mfA0wY%!HEgF5QVEl6)Dyr-5z0*DSTTc58lxywy zD3S46_1KmV02JD}psz1RMSqh>r9)G^lk+Fm!kci8&(zGPy>t8v-=6g1t$v?w-`u{N zOR7A${j&eLN-kQ_qaE=FoNjAyGr^b6_FAQd;9DH%-&YkYC<@-}_o7}9^5U|6-HTUGSp39mV>#BD?0e;=BaMI6N zZ=~Z|__?BuRrZ0zH7DrOpP*Lf$2}2V|+7;r5}~BEB>&FA9eLFSH-B24~f~0t}kA^c%H|b z)!?H$K9pTZw8p27d^k}rk=K1LKhd!+1E1A-BW62tpyQCB>>2NOfz9Lg=QP7N7t1A7 zE;w$m>c&J20(ZJ#dTM;TL$AgqnA4%l)V8SSfvW|BM&3t65FiyVX2m77X=V}OUjsNp z!&goxQ8M>y%G%OG(0})_9dX)%N@vQE%JCyjfxS^dO7DLWIh|TCRJWUozw)M3_)85Y zyms;4e8-K1)KEL0=b|?RME8%jp1f4xBHT^YyI>RG5=h;Bw!otZOQcq5MobKn5c<*QH zhX7CQqsl%?&ifpl-~4Xk>#OYZ2K#H1^ZQGF19Rt*Z3?)yIpAHW-_tb~HJAOH@a=Jd zp8Z^EM32lvCpqEBiK*ejYydFqw(jWQgD?|)`KLDw;yoiBf~dw*E#b=hoj2WD2i8Vm zF3Or2+?YbzVvXNJa;2TpzJv>$V>{Ig?jb*ZdU}{9Zu_ z1D%(J1-Qi)%m9yc{1qtYb)6!}Nk|Lq3gtNX^UMmeLQEdg{h!a2J3@pIF$h`9rYR$o z!Mr~PpX}TM1`VC!T>(*TM$-ubdJP~|A3E|L7_V=Znbi9bKRtnqQ3}jb8tb^`_Xf42 zHoa6r;ga*Yj1v;MZvBW;LO~-}AYFs98Z-O3s><93VCcNm1W*V(sv%M=9R-cBZa*0L z3C=Q2)NNJpP%W+==u2GlM4Rktkw^Z8<8~FV#7=Kk@Oy0w^rHCq`{luI*ECP1J4}yN z4}CbX*LqV?n8eW~E5sDIC=e=VrYnL>aOeK?YYBWy>S$X`jQP3=paipko^Hrcbvz-S zmAcd9MvcQ%zkmW*G|{`c_fJod0gTn>F7P&wHw|~^e|>om7k{wIK6uhMu;r9&cN8uz zt-?ULaXUI1+m)P``~oQMtR`AlEr7z4-2M`6zVU8Wox9)UVD%17?vF+}aPwRGEz7x} zjW{HOEYK48!Qw7<_?qdj#JAgmt{h&Q4mh$l2PpJVk(XRn90Gf#__bz{&;du2oBEl6=*2+VrbWZI zGyv{@{u5V{|lv)C`p;w^^E*jqMzM zD&TO*e6_k!QOThU)qVaEIIxP!D%E`fD$MuD2NlNX7E5q`Ev}ffWrar^mFgdY6+&9nOi-D*4K&_p1|(3qs05~k32ulp`@QMylTmj zs31udo<#*I$X;zrTIcme=PzftXoh^Akrn!2hrt#t0T!!u=i>7G4>`&C_p`EOJn(o) zCDqivXB&6yl_$8lX$Nujft6NUaOdli1qHEQ^~7v+ldmx5&=QWQrEhkHm8GVp6m1Ur z8q-`8JU#AE@0r(gZl8snZ{>>12GfP3dt%d9b3yXNzN3vmnw`x$;rj9PL-Cy5cW@|N ztoM=5$mIhj$HxX2jKT%=F2S}?JKtO3F1sLbFZF`9sO*(^8@PC2|AK=qc=%u%>$^#xfhxIqIe2Q+ zuS~LN+k>Ef!wWlYkA&6LS)WgPcjc&HdUkVAJyuxmV}ywwPgs#qaKmLnfua$f48p;MQC1M-F8iPl;mT8-BZV2ox*sk{5eeV`M&0~s`Piyy* z7gy&cr~6QN=JXNr5DBSWvD-mR}>@j{5O}d08F6%y|dYC25a~ z1^p$vv&KFp#+Ywia{UF^{*CTgiYz+)IP2?+>$c7V7Q-hR%lFSJUOMKeA|a22Np2_7 z-^mu3`RBnKBWc(K^^(QI+4Ccn2{r1jR?xiBI7z{bWe_M3+B)O znea2TiGLraRk2t%q>hb)phweHfI=528J!-xIO#hWcHT}{4y{cgYNk6^CM3-fUBHQF zbfL8gbw1rkE9Bg~UXhOK5R!~0E||zG9iGFsV8MB_6$nhmX^XUsi+=3GK{^2$1)&47S~(YU z05-z`u;48jUtu&4PJqRP3CK26ywN?gg`7pLqYDZ4Zryh(U;$j$U194EEPu|jrrA0M ztN+Q=M~<(1L>GKBI}Wae!e?y4R5&;2t(lK)K&sYwWIRvUgoVMBxm6C~lm*9ArySNe#kj4S z)6noVx6ZEybPM$3{U{S3Tl?Dr!^iyJ8P9dv(04=;9y~x%(6Hm5tDguKM0N!y>-f|7 zoi-l*a+Tc?!?5x$1A0*o-9q;A^nU%2eCzR`S?{#kJolR6MedHbh7c3(lJ948zR>v% z`JT@Z^9Wj**SYV4{1A+O8E6gFRZFWhJC1 zpP{uV#JY&;wvuK4Xv@v2>QjAg~wCnqlk{h4pj00k?wT6hK16wB$>d;{rpSHV_GWz|_S`pXl6V_(Gk~~ena1E zLnhJ@m|zRxGg1VlJOd7LKd<3-dOxOn0IRME?C6wZb$dZOWIvNCJUSdcF5KSYKB~%GqystHw zO_@v0Ra5K!OR^MYi!BYdDcBv=$}9&lvU6p^QwBLgS3z3$=jBbjGLt+hfyZ|@e_ogJ z&SIulG2Yj_%w9zy=OIcsxUR{pSYS8Jm*L75+s6fV zrA$ayLOv<=zDSLaIkE5BpKuthJ=4hz@D%DJj1*#_T}&L1UZ*QyjfV%hk5^^Ckhhq* zXU1aC2Xg1?gdP?TM#uw_xCDhPu2CxZ^~+k5|1Bfqx<4ac{y`ut-&KGKuj3tIi*t%4Fz`>KW$lpKjpXx z8eD!=f&puAWWsB}_59HRqt%i5_fy@^j*jAd%tsvDOTsvJs5J5J89FabJl0d) zV>AUHC%7#>*p;aCm=98iXZCV|P2&uBU@Zj!l2<1;g$bvY1#PT7)NFZWchOblJ6WRc zh2@#AcpwsOSs~0WQ=E{raJ2rEE^A}31O<9)5La^S9PI{zhGtN3-F=g z748n18A^m8B_RAWVsOjUmM^BV&ukihrwzOk24_Vyxu*#L?%LbPo<)F?POOl(0SU2&IPqEv& z!R(Hw4QWIqIVIO?;r1087l(H96_~#g;VZbh4#GQ%Dj|*y_MiL+AG% z)WCR3Qv2gI=a5pVYj{?MZ{zR36%lMVuwu?9#p^?xmhjkoynE#AUN?EtV@&c3yZc-# zf8iNf7AAMcIunV$8og>8@;p0$U_BE#^TIJzJFD&FW`&{K&Xt0J-F=Y+qCTHVyx^C~ z0^9psD}HHlL-xW_<)-{Nqt(_tRS7X?;{os}sxBP!NVtR$%&#G2M}8sQC6IVS|MJ*0 zyuP7y%2#mzqr;_$P`T4WLfUJL%m&2seA|r{pmd|1!IpxJFCdk(9l&Dva?-3>e=t}) zS*JVCKM&?6g7O#vmmtUGEw}pP}1fI8?Lh&!JD*?ky}P=7N9Kb@f}Oq z83)Yh!*;_?o&}pXPu`8+p4D8wtYk~5(NKG6#0>$VyrV+$bC8+=8Yq&4i?O! zN7f|;TDF-Iwx@XyZMAY@^csfu$$uy?s=}cUF`V4 zHWm9%Q)eT`6smtp*71Gv$v<$??4Ed59*?Q^rasHZA;`0=RgI}fkyCtF#5!zZ=B=eX zwHsoeq-GZENs_WGn}mCbygn=@c$j5@h8c#bXl5O+ zw<`)%d}?+encG@w$MMetu2a>ODJMkigKG9}TQyfKR)}$ghHhBWpVd~#aj?v6O=ixn zTPZ#zlAoW}wPoi!EU_OWJu-xW@8+cP`1ujL(F`gjL^ zM`!@VpVHDvr&<*5y`R}KG3Wb`cV#g!z^>egP|eKnzQx@(O$bVY1soI}ZRDU>4knEU zxd`J?^Q>eJuF)+(?9TM~9n4Cd$Z+GmE|J@DRjt^?HLTR^?Gm2q3y*IGc}A8hpWH)@ zRGGe@RsN|j-|Q~DBc6ZfJoalng_H?X$tpP>l%8L%xzQ@?NIUE<2%4s*jPAVS9-^Gm zk*Q@=ITD?>q40Ce+^{;3;dPu`3#8YbL{<89tz?Ji;uF8nB~A1>NmFx(_V z?QeA|J+(~qxp3jnWD^>pPh)}j&h(Cu=&U1Xp6EErJRTH2qrjym%iWs1G{RJc+qF8Y z!8t8+X-27cS>6(!lH>E6`=Am^9nX}i?p(}uaMh(Ei44x^rwZoTGMgmdwQgfy*r4Sz zbU)t`sa5n{ssxU^E}Il2mflekDzFZH+mqOUf7gkc-2u_@oZ!scnsja5lKvwX4~=hw z$xY~Ig)r|GAJ2g(JG5D0s6$}D zhVYsiZ>9TDPTWmN>3P#1xAX&UtwOX=k6~k7fLDfn4Go7&w}e^^z8DYiHpu1azABfC8#p-`L3&8lX2iP}?npgTeM_J! z`P~#3*oT)~=4d~VBjhw@5y18Kk_T6Gwf%>~LpQ%Fo?008i1WeM2VIfL7`rIXxWwe# zl3g0rcK(g|Q5**xoNnHq4(VD`EtnjdJF57;RmI)Kz(LZ}6uY#k*1&dwpOLArudjzm z)>q$$E@xJ7E!>)VrTSiBmtM7L^_t`gyYZZ<_{EDteYSit>n#q5Y?A$&J1&$n_3=$s za^K$ZA)>@V!Ha+}p~gEN$~%10Iy1EV!o&W!w3oj5UCxm~@JZF-;I_J|%wKmWig^9T z=jKWKCHty!XWl-^brUtKJvj1y9={*D@-=o!(;zq5Ls;KD78U0O8@qS2`Jvg$&xh;U z3avJkdPx^gJ;Rx0OF!QyQ+#0CQDhU}-FE4Y#RKBQ)9>C0bb5d8QWR>R;!9o|xxZ^~ zPVmLVy2D{02jKPa6~VoMl^at8>OQ}FV7}&lWSeX3*#aHh1av%<|^0|Y;>wS1GT=;E8@q$p7g0e*0 zVBgLSR}MCJS0sH(vld5`PJXr9)9A;0|J)W~%t%F3U4dPg?;`4v+T6-stQd5P#E9o~r4A9|B)w|Y!<;Ngz)8`qUi@Lx?on|!UnGkS@n^)scK z8wZ{w?W(TIkZH10!YD6s3cIc~_I}lCV?}fvPx{q_!rXzw6E+4J_W-v!Z%Yu!YiwD1 z{%l!6x99Z>=ILe@c9kH0;$jm-Rr(yQWQV)8Ak%N4^~LK3B(XFMwKad>Z7e6R8`$-FJ5HFvtAgc%@s(cDV^`JH@Jza0RDd0^E(W( zO7|8vfLJg*21ItDu=~)3lmpjsM?RmiIY{0J{AN!zk^a#^my(Q{$EvakZ+=A$frvNc za>jvh^f}1kJk)*fRo#N+ijGB_{bQ3dtE_9&cj@hY9eradcj#6Tuk+bEy5tMNswCPz z0mA8Sz4>2H7kqiV_*m0{ujo9GdeZ|UznLTuiHK85Y>9n!{JJyOiGpht1)(uHwEG~| zTm)r3Kw-2Vke#4ye>(VcPW$%4J2$@wuFqZIH-J7xYIt&i3+#=qdqw2d-&%Rm{!EsN zzu~B7PC0UKS+0Mv(#e)d&8I`-pQ@f!RL9niWNwL6)8rjMJ01*w@UrqrQsLB?-%I)S z8nD_qgQy!Bo}l>U;ewuoux05W7*Xj70{!DXq+pMmu|CHSPIfu;o-ITmUAi_ex||oV z0_+;bMnBe-ncuzt;rKD5yGcpneTCDLy-{ ze0q6Dy>(iP;4&@^6=8s&I`>4;_OYe14QEDTh*?o)X1>dl+T(+R>U~PZd+y$QnGW(h znoi5Nt+N5iB=>xOA@ARK;oOqliJA_b1+@(q+SXcOSJs2LS~m#$rZ!K0_V??1Dp3Fa zsE{WbjfQe5>fhcr>3J~zS@(l~^TFYa{GAF4<5@xCB}%qwt2-XtSre#>cMvu-+N(yn z7HWUd$Gl@=#R2gxicb23SEu6215A89TJ-(8US2z5xXeoU^~TVhwOfap0!ev8bspzA zKU6=c$}7-0atO*&Nq#W)3Hwy#V){T-dsN{bN8Sx9xjbk|H*?-J)On;3K~jdjGk-

    dqnSHMR~anZ$C2_o06QIRiUpSF5jNn=y2^p-zn0z z_VMRC;u~VhL&y)5e-T;fkmKvFS{Up)Y(W-@^8DGYEd9x{0_C&YuRXpbiRlI@k*Eh7 zv4$`AlnxJi7%BS*S+sKBIa2>1exh~9(3dC6>jCc*K<-8UWv@f0C%trE5T`0F9F%g- zUwKppqB?Pwfn*!CN4gbxt9P}z{NgDkw?93gAyup>3&|f<7MpGMDtmqKf|)sL$wKAH z&UeAZ?hW_7QB9(e-A>C}V)s6Lbp1Hz>eqWie-*8|q?zcFVGI|)8h#l>rC*)i_vuz^ zY_-3}#a~z7`+21)miq`1c4i@}YP+4HuK=;OTQ^BFqdxcimBktQ5cj{ys<}#NI_h7h zs4FotZnn44JEojCPLiRywzMU_avLd(uDT&qogqD?zIQ6olUVm=$1@wi8ySP2l1|mX zZ75GAz8JXCiX!cw)_yuag;(Uz}Qy4Lx+91*i@Fuz4< z3Kp*1&=URyetMJAwZ2>BNlUd}ox1vTVq0$cg~c}oN;V5TEx&fnIq+U?X6J&G;Y^?= zZWbsPe$5T;t-tIZ&@e1C{6#q+Z|YsoDCX#fxG#Q6?|XvZ49DNad*s7O(eGWBYb2pf zJjTl1!e7O2xUuirRAp7b(+<r2twleQ{4Fi@$-}UvE5VK zn&UfqVl5HZ`nHkke=bKvZwCleG`a)+b0s&aGe9{!e7L9Oj!n$z3+{Crg3K$b0!~I! z%Q~uVT$>EotW>8=jvFfe)QQ%jQME?eN4!#6z5s}xxLa>53colIMXYaD&RaT$st8N8 z*=UDe1okR|9r)z~87=PC!^#g!6&{w>2WKR6633;f)Km8MVK?!&JUwb&mDbCibx_cJ zRYMZ8)5@PH5G8fl+s8RzCiYcS4VV-Lb)R+9Z24^8&26Nq~60-s=*%YUSlH3U7wPcW}o)-m^j?Ue;d%Hb(wT*_eTnu;1Sz8em*~G zvts=QgZ}<~Z`<@t?$Z zhx_`w20L0Wjb;YY+Pyu9Znhr}Ngf?PcKdq8XI}+zHIO($@P8UUgm5Ne%+K zZpp$dA%`RnC;SsQAIleDcz?g^7-FNry2iS`%@-=;%ilF)&N=u`*4dojd9eD0TlamL zo1WRyajotCK9iq2WvTZ)G%-cK_SNHhpmJn?@j$(ztvm5c@3Py^Cn=+Y3Zp^m8>=og z#+Q42>fo=;kdCdpa>L|uFTUV5jn>lnGRyyko7|H^ghD0d$k$$TkCv#o?B&w2A7kHS zv`REbcitq2D+t2*yFucmpme~FmMbyWZS?CYKSebU$7ALup6ty9!< zCq^4L#<)t^8;WP<#B02qdQ6eFlgmvqNjfDkO1-pQSy145hja7GU8FA2NM6t(t|yyugil^HTwZbepNT0D4<1dIf1!%LUBqpyzt?k=npQjLK=Sd z*zz1BLi?rKcj(c$+ra{RKMW?fc2;GI)z$17OOEp0RaacLMq{Hjb|WoNro(VxGpXAD zs+hI%al*m&tl%d8+NnN6Y#(Qk#K7(1idKVi&X>1>pUS)pCuNrnpFo+lg*|m6PVY(T zX`k4qBBcCv?Ec>7QLpv7qc$KRg$QM(t}(aVB1-X!fp2hwMMrggwU|bXmC8=ZKC-&p z+TMU_iaXYH5fx;w?-QJEbs*h};OI``W}&n8AJBZ5v&(7Ihji*{9|otv=k>FH2(4eCk$ zr05ycz5nvy&_a9H=!%j{2ZtMF#R*~x<0I{w&nDmI_X&{Kj*o=zZSHP=`r_rjQNi?_ zzP)9Ik*l7TCvA^vY#Uwml-yF^qJ1Z~aeebji`va+pH}4k+Pg0@{%F#%J9jIo*`ja! zop0vHDzs30mYpCbN<@)#z4J3~`fJ!7Z?BWV!G4=Eq`yHLCn?SY=zdrE<{CNZF#%aapK9N!xAU_Pv*78 zBgjv0ysFiA{fyg{br~qq;|FZg?GzRB%A|Iq&JPD>#~t@Okz|tA^SMXA+O}RKOHV_v z?Rd}4xczpn%9l6R$EgTSe{>jIv!K^Jo1U=?vc$CfAFjyuYd+{-aVqO=H(7bqIdu8- zh|bir)oI~7cy><5O36K0x@c=}>F}PR-t~5i!v-eLqscu3#d}6ie;P6wy4LYl>@1`_ zyNagXN_9rZqSG!ruN7@Rsx(>i#O^G5sH+pZxO&1=IUOZfZIX6WcP%{Wjzp87l zZGuk?Q5INXt}QkLx&78=$7=?lcghI;s^HbsMXY7`|tZ3-^>?7v$ke&a~&zBM**(`6=|zHpd#ERF2)bw|S?^wr&54#FTA#a7P|z4hZCjrQGL~tIstI}PL2^ns zaCfQQz`0e~q_k*^+#x}UU^bTqx4VkR$hVwCbdR)zXS-bNTvzRZFEh6xUTCe1DH*)4 z>aL*UJ^ruz*|}p?1pd5|BUE+e$OtKA_?FII$+Fmi0d1)ejsoEUE#)zz@Q8TD#(OUX zkMV{e<9M+O?U_26;SQtgymSZFj!uskPIsMsaQEe?V1YM8%!g$jZ&FdoWzk zD@rPVs|(9e)HrC1IVHVHl~L@dOcd$6Vp853V+>1xc5SD!HUX6S?SVC31zgvq`I5=xrp?EH@ds;w@SB%z3R?v z>CIRkRBzvZaJ}K8hO&0^Y)(DYrR{+g{>)*x^w4}!Sqy?B6sM@ zEnjN8{R7`7q71?xZsEc1-feSPZBHCw#X69j)ZV;3h5+yIp_P7lA~cn%Wtz1waNC9} z9CyTnx#Fj;wZG81d=q5x`Rec6D{`+b?Dk>&vah41z1Mlt?6BPZ&al_pY|qos?*hA0 zE_RokNuWf(C8a*%k#RR2imdL!MNx{-y+XXJr<+QWTEC2x<_uLWTwYt4GI=d(``eGp zt|f-=krf+OvpYFCK2bRwD5ZO(OfXb!$(bt%gh$psL`CZI&;u(+KD<~?<1cuBWaAL; zM)!x=4+fJ2tqKDYahH`=0rD%ZELLn6uyo`s9XcI##XM!BMHF>$z)PI@i~Zbsi5C%) zZW^aN@4FsZ?h;&SW|3J|^vd*Q`}A0fqUo>D1hjj)K<+Qz8lBqUQ!2WnxGV}md>Jdh zR^u#wO{o3`rC|l&i`iZ~1#;vs1wAp@yQJct1T8{kB`qxduJQZ61&0T38YoY`&2V-C zY;zA}uu7tmp}gj8gTd_z&1pO00=Dw)y&2s5Y9yv0s4j)@`KCjJN%mOB37ci9>jxek zy=A-l7v*>iS$SellI408^5`!nS?O*0!`{}HyO9Zo+-*T0ns=l*c$n<6b-#T*S8!OD zPq5$BQv8zj!-nwv28}KoxfY6?>4~jgnr7Q{|4ohDJvBAuc7(385Leg^Si7=P(fa7~ zOCS8&M20e>mA1C$Pou(NT*rZ9btzBUa@hW{4w1m|p6ni>=@G5|)hFu&xRQ{T&c{SE zYDL$t-aj>hfikl7!nb5(X4W1R3cB=Lm#pHToJzWh_4FGptA%dkMFs`#y|zPcobJ2M z?fOaozV;Xzq4_g%;$y7fpr#QPcy$cIzg*#QgI|o2wJC_g*BnLK^I|1SK8@SSF7z>T zs7gGUpaxlbNttZ=#~M{#d-Ax5<7mjz-Mc^t*|)SSI#?P!0Z zZQ}*=W{|>7BIWmKTGx2_0bkq;!CEcxTqHoCupuv3?MrGwjP3@V$=d!2a8TmY$};(8 zkQ=pdo1wIGOH5qL9WK9^J7Zf6y~0$KdpcJpDXcrUbzq__|8ls5n~=+nRO}=z>%-6D zXa~Pq6H`O6)yIF@S97?_UFuGWrg)B{^u@pOGk{kWop6a5A#9 z4oUW28OKT4BgsB?LL_7zdt@9V=VWtmgk)uplRdJIV;+v#;dl9b?%#cX|2)@q#&uoq z^?JSD&&TuVT)ElTcTQd0KauTuICcN)7m9li--XGZ?jpbW#IA7!{oUcPQljhh>g#WK z*)JVoCV#{!{G2>>rO~(rK>Y6W^E~L@&(!l+k%fy+WutV-oskfS;hr zvHP%E*OuW#`DxB79Tlw4=Ckq*wYUI4#a-xq%bvzW_};3^0_@Ve>-Oe7wqJNf+VQQ( zZFM~{og@M8AB8o0zv+7GzMG?hT0UIJv%Gd~5FB!3fV4Vv9Pc%oRQ22Eo7H&y`ZC`^8ys} zsg~BP%AaxN5kR%IzqP`WjUmyppA|no2Y_kq=QT;w8kUcIkm6#;+#}5M`TVjhi*=Pz z`on4x_QoX1b}+zpAB1hX(SC6F_Ym&JG`;cjeS_?&Abs=j!z|pSi>;oMwZ#1x7qsiF zm2IsbdeWlycwZ>LbHQBp)OHrr<(aqA(DD#H^9$*|i2Zp3`e)L_oQX8G@Y_ZJGrR7o zxqDdp@*^_3x6sVmBt;pXK5lbE84hcLKP`tWxUrnLp*!z23_L`C?@3vhTv54^$ h zcL8_wNKclmKNK~&m5n=P_OEWo$<O1o{lqH{)Pfr!p?+6V3-923C z=+9^J2540Cy5)RIde|<&B~&MzGM;sl&(AKtghrR)Y%7dwxjqL10XPqFgTPiC*fLuas<=Kssm50*(_he>=kL`rA zUUsbv2=0Bm()8=2>_&T*G5W`_h2!awct8weJKWC?`K=SV?P2ihBP#l@=$1=UH$H9b zuG7AlKvrS{3RM=YyeX%N%}jp@zB<#9E=Lmh zJboM5?3=3N_jmY)vQEQUG~QHa_bdD)!}^BY3NA~s(ylQkGQQR>-c+{hVVdHRfh$1?Y<#bV*t}L&bpW&o!+$8axz8Vg{Wa>M-FcLxiV?ie>dnQ?f>tkN@pO^5|qjEJSn_KtO*;NF= z+T}ex_54u}Kd<2AZI?TG#b?z&f>%je?$SE$JA^qvuHVlAKvh*0)uOYG8ej(HK>=23a3ZuF^vD)rMn+0)#W7B=?^a7dpZdF3ka9bYMw4*dZd{r{j&DuP`f0Ks6S^?31>b&_jC@l#m@Xs zA8*GSOrZjapp)sXK=^f$s$KwDg71H)px^7XsNVKpd7S+>n(yUJk9ym|7Te`lxt2`I z2hS0ID`B-b>7pIe^BT<#$vxFy#fF%-DkjvwgoQNkAD2HC(2`%??f34ee(Whz6H}f8 zZ7z#=d6wmYV;91~vWq);%q7}61aUI=^<=x^x8h!d30t9;26he6TmHGbvCz70)iV zxB)~p!!to(l1X97jnu8#-G{Zm2i=?_8--Me15>NK2@mCm>JO0oGOY{iZ}%e*AbHs+ z85^&Z>v`FOjYBn!lrjkb;659H&Rx18w&TLTt=lU!}K1j>D)&Q^=F2I(UIy#T#F2D>m z6+*S*S_!OW{J*^>T>#c;{Hpxni<52>>CI>M1E=ujzwK3;hvz&F){ntj`1kpK4omZ4 zSeJc{@}~#YE4!&A$>vEv5jhhNuQ~j zN+*O1)^f73sl#<^UZx6LJ#y@oi6}cbd{l`~_ukvcoWQ4f?|U@Vc@a0J^G!Vk8vOop zU`PhotSna{orYT1*i56z#{PA5azKDz^ZtYb-3Czrx%_O_)e+@1KKqA01tRG(wT@n< zX!;c@JKM71*&E?Ap=38I9-D16D?9V&YC2^0ZC%Hm`5hG)o66DtVC7oj?LQ8I%P!!W zCgf7x{_V6_SCso`ZN}VbB!^_nZl+j6jqjJ0^byNh+40@X^+|+J69P7lfcxhM=Ll9aGTK$akWUW}-n_DU!1#0IT@CW1w?*;ZVnJdIs;ivumQhAe0O z-@Zj+PaZ?DB3=DBwc}gAkgks%jLS-qzO4^U{2;rL8^?_!+QW7~!Qj)!B~FiDdy%SM z*9ej3Ea$ckC*)54X^HwT8sS$n?ZL(!zGsCymEUpqO=yAF| zEkJu;@|_5koertQoBix1^#A=ju}m?6H{0LRbx%Mz?1_EaKtEeG)5A7qBc`##oA`i9 z1kg8}BMLXBEoU3yi0Ph#0}mW}cX*uG>*oXPZ|pTRcoFvfhlk5ncJRJ_i$QI*SfUsn zR*zSmiS?A7p5Qp8L;W!<2HGw0s+LSUes!5Qxq9JoS*TsW?o**sB{qwuUo;ypZyIj- zJ3-L$p2a}>en*e}JI7-s?*Mh47tpPBCy3{8%wCOmk;IbJq2~}PqH8Awg7r^1uxqU4 z*7GA(MgLjAj!T0jA`5S?f4xe8NyqB#hRjHUjnNW1H&>Q!<^19HO>c-b&AcOtZNUC@ zy8`Ar`?L1;d>5~}s>)-7-bQJ5nE!sy2}4%UZU*%1H>$h=*cjhRF2eYlxCTY6rFriN zJJ=n_j8+))H3Eucu^pully*Ol}j>fY>|PKM^?L zW%(0!`dDod*F0E&UUu~{bATKS8_ib4UHu zz;2qQYs8wrc}aFnc{g!dr7FHa!xl`JYbUiXlTZ<=+ z+F~WWi~2~f%hp`XNBqjIi z*J*2Ab5ufSuisneNPKcK!=l;m`1rp|!o+gSR;Xt4Oj`lk;dJ_L7_cbJqB6S7+^m!-dC)# zQ?zQgi>&jBCF|6ZoVMP=fYL2~vdMgyHh~6=Zq~JJ)U)|62Ob_(19L?`JprSM%Y8Il zSf$}9z*2Qka63)N8PzXn7o>+a6HGIjEk-YYB+0Jd1@o{xn6R4Q4*XhCx?iGUhpq7_ zovD=>wZ!_H&ZaE`%S5$LN@>l}<+GSIO6uE9)BX5&n{gov*3E=Qqnth&FOYe3|pZSZ!7oI!__vn{9@bJ_YQbhwM1X}ZO zh?i-_%N)><^7H|PaeZ}5PtSJkc~8m_@;=SxbF>QpNm8yj7s zkNDkzw7&L!jMTj&J{9h<>5u2&wbz8hg9d7MP5 zVWhOwV@OFHzg#wwCFS-d^Gz#FVaFAbKb0F!SyF+2eemtVUzuee*!8G9ce}<~(~?t% zHn>)HRC_?UBxt%g)duKu?`zJzL7mx{qzx0A00HXcRq557#dhQI%|^%XzJRJQl`2D| zZvW-OxZJtUs@Cz4@155N2!mHD#OGJQXZ0K3+OF0BHR9jQCKjJrw`T#yeeu~lS{ig) z{%9cJZqg*sWn2!c$I4A8v^`Lud3+bpt6=X}VgWS^;oT;nSsbnEHUhaoeV3U103A-k z5*7_IH!*>;UV-`UJ)>L9V7X|hNx5gMlL>cl8Tte%;~oC=a{5-^K4WBe&gj%ihI@=S zVC5_sNK}2-D(Vrp)&F)rDkGSd%Kc;Gr}nAFGv+$Cpo3$~60G&y6(=e*IN8prz27di zcaWu&M+fDyq|)jd6-rXlyKaRMwQIVgKxUQmYY ziAszDYNavyr3jUM68_mu7i&PV=|})spnu}8jn~xFEZ(+g63cYQun1GeN|8Z6`u)}a zU{(OV{CNFan{z0g#J94V34T)>q|qy2aK*ZyafLNY$>tM)^;tUcVqf>xP^G;|eJqF! z5C<+Udy9k*nwq`@d>^cacN+-R;OK?Rsh%)0(4VF7i|@6J7+ASNROCow$O8-0X+|B{ z&yBYa0aqNcCcgqecXj%A1#G7^$ySuDIXPCF?LE(_8%@dHsJBx0c1e5t-Cj|qU(&*= zUF0=DAy`iF%soQuMUaqH38>U>w^ve2$Z71O0zx~}5w=sg><&0XG*=XE(aH`7kf!qd z>hw7|Lt7kX281B@m-p7;$-Le7#BG12RC#kmKhHZxJr@E?HJ@2OR=bPe^|HJ!B}G8xJ{y@Uow;HTv!%N?4YE=h2895c zS?*gl$0_OxU?G^HBd{4%eZ6vUw_9qR18GRz2}~L$>AsfU_?fF>AeeZ753lYyO{y<#osPKCaX9KewqVWQNystoE&dYVt9!`~bOnbN-oI!i> zk8A-)bwfYti#x!oH8IR(Y+a;nvC()Db+Dc;n0c~EHv#$cc+A$ETB)zwjPw_Sl1z0rLFw#fP6lwsme6JrAo?-jn*Ta`FBRbqhQS9vO7*%`# zK+gYICdEuElHlcv;F}_>4xH^hbeFa=R`}R2nZGV@f@PAXs$(Kl1QaUuoiy>ufnlhkpoFa04DLfK4laE-TIH zSbnl3H~Vv1A}FUXF-D@W@T(78AJSrkoDnsynDuTd*4?|8<6CANu!mUu=~>v4^Wj*} zSZgrvB6?DUwaLtwa+Q{nKRtMcF)v$XL?2_TlFRLj9xmY?$9x3l2ikub4_!w}%N;8G z=L-B37R50&cS?cGl}*NtziC$mxR*y9%oG2?NO|4J#qRt^aUL=R5Q8~;v3KSEBS2qF z|DP3`ZU`VkHJnpK^!y`F*Tqq;{*T>W%?5z8Q?}3K|9+G16s7&`|4Pg|DFDT$Z?O93 ze|7C4^9-Cq|2@e|1weRF^SlF8|3EOjcI10>{}sR|asi*@_Wf-y_RsszEe8MRHj<s+lO{TT?K?ns2yzZHQ`MFgYvVJd&u>TmFF|-N%#CL7 zDFNV1!jl)wLPT5aJ*2*e$OTy(9kerPt&flyVNoz4_j1ar(ci z{bb-KD&(p>XvvvX<|wvyJ_=4}!gsz)G9s4t%#82k%YfCM-Z@L;$%mt4&hFN8_zvXJ z$9HQ7_$!>;%`~R4Hwq?bsG}P1$`7BFUn<%VVVJ^Awq$PH#MX{5rgy_fHo3m- zW>4g8a~5nwuMrX-{OI5)k=?ZM>_$};2Xy^H$(L^NE0B!L)Fv+*WDI>skLHT6Nm{dR(eXEV#&7i=Z^25un8QD#;!0>SPq`7in~ zj=tdIl|2b+s9oZNQ$1Iy7eX}bnk}G`E~Rb1UJGIO0Oq8sMJS^s+ilFBN8R_KCo)GE zD*sK-dfnHmmC+qVF}i)O0YQ53Zap)tD1!&zIg+HRJx8re`-9}}!M7PkS-KA(3G<3e zVVH=Hn~B;1;7-Qkt+kKG`Iur7zmkL81d||G^+be=cY~EavHW|JAi}@<4i|-r$s(u3 zlgDOyxz3KL2>}P0ZKGTN_$N}6qhDWoRcKt^OH>!7YZbW#UY|!J(b%@GId)9mll*R% zgUnyD$FDU=Sp(ifEm_*y*w<`XNhT-p3!@y6gX-Ax-ny6wbkmH5d|`lrdrxEE%EnWg zRut4bnHOoB672Y;G_pS5C05%#%^5VuboL-G)Q<=HjGB&`_&d0jODij=j1GGR`M{zj z?5$YbaNczhM|*~%Lk7FTrg=5*?qh@1>eHowEjTpQPe@D{~K9t0h+a)R#ufphzrM200LC{r=)ofPB9Hi8F4+Yp}>+R8M zy`Rf;O>ZHSp1nh!hVxNCZGV&bMb&>Huot+Z_%nOT555j=x^deUdSsIlFS_awGP%@VJ<|s^ed2u{k4;PVj zzyY_Yk+=6PNiOD>H?n$}$)4QrLT4!cg3gnYB9vDAuI5h)tvzwot5z+lxg^6^;rl20 zxhGf?^AEs8&z}&CfxdHlPT9IhdOJ%)WiBUDxOM-CBV)N$TqpcOfNNOi#{eap9_rjA z3QW2b1guow!khl|uvxbj*(NfeKCxe9?V0L-e&@jDRy3E~$v?yi_CA#llY*SRt^Hy8UydIU{!J_3hksPAZ z@pSSWL{une>@0Be;S8Xgy#w&B|3IF;4*=9Ihb*6J*db{apcf{MqBsC^x3XdB+45b~ z)mVU>RJeA1fbx0lwITV5$*B(azN%I5lmcdKvDbVI(@s8ZImDxAkjWjO zSpN;YcI?^?7YVH!lN{+tK)!t^#@BBg+IjN5FDz~SIYQjiM`P1FBO~gSnU}1!Kge}56)xqn zM>~L3dsO|**%*fMkNH(Ri;yF4s+C>T=`^Otf_1#-Z0fY=Oh}IKZY{bkCv##EW<<;} zc7nNEFS~+hw4vI|Qe*Q?m(6S^XT@f;@Yi3nux|}^y0_zNn3okJWv0(cX%F6TKh3Fa zfzo(}6g~mGf?GXxsV=aoiHFdHUtqHm1r2)Y&Z=F;RvX~BUGQco6-FjW1{|yuUrZ>8 z=G3|@Ue2z{mS1c^Zl=cyLm36ZEQHtTvDhQ*TA2O%lBF?1%+)vgbzvQLsnt$xRumF~ z$qkqu7^v&>Zpe^#6{#W`nV7tk2-nGx3~foAXMq@V`!6&N_WRaH00WMo_=3U4QKVFc zpI}hwpj$}ubz#v7x|1daddMrTZNqDU8KQEySGJuq;xkP%q`}DT0*YPJueYiXa(vFK zgqiqKhsl>Y<5$6j>f=o;H$d8$eeR?(;cCc6hB z@W4668hL8*O%tYPa0H|6l97eXaY|yB#_-!2zBybhaHCG(PJLKUwbv;!r*_RKYgB@u6my5 z@ihh~_wqt$v(vs)cJVR{Q7Sn)rts{Ez{2-Zmu$7a8731zP2Izo{2E?VD|b?H1#<*v z+^6q;98x{ZGeY@Y4IItM*K&K?3^F-N2fLZs$ez?~?twG|sjpy$!c^$QBeD0TE*ngY z$ih&c*Wl$EAbKL(Wt-J0>>3*zqjjflo&QFULQa23Ykr)BsD&G^&bf;~5&Gs|=qHW- zuUYGX-0IH~#2dHF_7?zfCrLdx@E>mmPTB>*ozvC&!4a}dD&GnEq3?qUMBG0?7D0(h zE}=x4E2+$8SpB{OIDdG~Xtwe)Jkiou$zKBMovq(v5SWyZX6&NptLW(T!Q`k!g?%OD z?x%g`6-9^;*@ggA6;bu?takk{R&res&NByNQuID(UOs_k4~uTHv|gkLMvjWWY{u9) zR%n_jum9bii5b}w$?19%$NtlcgJ#c0Shw2s1T4oQJ5EwhjOMAp_yQKvy!Xk^4TXw4 z$kA*$E6>^$DMYm9+93DB)L`1uo)ureaccF6ZyTgB@Id>MZI|`r_{~F&3O?_pWb;h% zt5BFur|Q?`@5P>kFHGa-tsf4kca9Jep-V-wHo7-QZn#_m_Q%{+^WKblhDk^lkaTO4 zf3Lkx+2o3-u{W(BD#~yUo#}hIeI5+}hM|y^QO>3gPKyp}&e5m~Vf04m6O;;7B3RZj zM|gw&8SKu7WeYR8$_%^2Ee<3r^`4zDZ@9z|kR9aQA%A)v#ItgdX}$ME0PY6F>$Q2( zyH2TyRwjg4al%p`S0uttMO+PgK_^sa=`$*TPF1{E=epPFm8Ebo*m&|9_0s#0!t?N{ zTfAlKSJrY^ZI2U8=@9;PD#59~G`Xqdb+uxuSez02Xu)YwZ;64MVu_HrR*^Xs85>m< z$_o_0D>+4H!1_;gv`$%-rhrw@`XRaI?EDDQ;qggZoZMUD8jAJYA|yOd;U;ICcCg%e zR&&IY6ZwtjM~MpKYXP0n7y1cr!uYf)G=QL4!|1tSNj5oMzfKSKf?=q<0GJME^OU+7 zlbjw-oa}l;)YoLq}-05dysrQ8d-jMxa1Nk{$1dV>B(J-Nkuco!bYn*;QsT_ zhE2F#={qge`H+r^QFxwZ_946ppR^|~OkDlqDMH(+kfZpztX992PV9RUS*y3(`5V>W z1=ChoT}M*&ya7=lYbyCzX~gQWL?QDuhC+NpG?^7R9fdYTAaf=C$k}MDN0Q1DM`+wH zT%apH{~rM}mn)#|R&N7gVP1>aU%tsd9L%jm9y-a;EJDv6xjTiR>Ov~ydwf_*Ywoe0 zo~mdmxDEc}Q*V$>Dm(f1+sH{U}eD_ul()8!q4r=%){ z3f;c`@IlS(?!o&P&2Tv?6z}$4mj3cbYZQ7pFo$wz={CwYOCJ!~23ELeEk{{4K%b7? z<0LGsMuT0=9J7sLW^N(32L#!u3~PqMyl>|(oBR_#0>+;2@o5w1>pfyZ+ekGJk3bfq zv(}E`X@#{eWtIa6YIU21g$5AVp4Ke=U5M?tNMHAd9DlR<2ZQF_||bH-Nr1>>bX5 z7?$W3JYSCViiCmt7Z9-q%)z?{bCLyzF61r%j!8HQ%9Mk(Z_j;rmUT~n7B<^ z&u8Ag>_raW3nLpgThBwLkCi^&+?%iNCo)pS@ju`t`s)ZhiM?k(01PGe9R6mibjQ#& zp**B9|j`Ji+wc9U-$s>{(smjzDyNA4rlz<5DUJkyx@6pjjKin|z?pl}037_{O z&FXQHQ;JzU3^E)T7Z|`vJVrPz z6+1|jf8T}mv#VNDoP|uN_yXopoc+Okm^sR#Z&lRx-%*jyu275m^-ny>^W$~_WMK^{ z?fV6JUI20fU<30#=H9ODPaTfeKJpB!mxhF7tt407w!DlGQ8!Ifb)2jG!6}owtGSZi z*Pv)CaIy#+gRYo6s)!d&_EA*Obu$(AYfDMWnJ$RM_0))PM*bq`EEQcHO=2&rDbgyo zvN8|t)AE1d$xys|(!f#3OtzUikyB$Yqv~RmZe&MoAV137JrwBpSp5Nol6|)E&G*tw z5&z7lATkJu_!|CZdbnES)um5Ctwf`Qw;Mh5qyeIVRXjm^o7yEpj9_r!sbwS`rWOTn zt+CsBo9d9nqYAog-8jbjz?wRM+F`MDogo%_0Z7a*Ur6N-R|;;l(Nus^r?EQaARB_# zN_fy_kSH z!y1?^>CJFf^O^sABdLlL8P2aU+KF#9)V4?P2s$EK#Rik^Fb(aEv9M7yAz11hf;k=H zaza8e{zlp_%Fv-tZZh4O5CVQ@AxUCS1+(w@^@qizbRfU^P)+L(&2__{3I(tvNmWk} z%70pXtY(uRkNnnJm2HL~*o>9_+Yl`^DogNCv4J(0?*(M}3-81(jLd11HU*$--}R3Y zwQ&V+W^hx(HLZqO-CA-iN-2a(#RBTH=^h-V(Q)$CF>xv`G&_XRF$VY=-u*^*x3RY4 z#IOFBj<+WN31ozUwbT}WqBu*VBovnM_}pr1MV0TH4*An3IqAV!CSyIXE1DRzyhG@5 z+K%Y^Uukjx$hO$^eZf+iaJX9jrF25X%BO0fFtw_hP_g;OhwFQPoZk7u5qca4=!}W{ zE*Fzv*Y)`!5xaxy@U&+M6Xx*)dqKHit9yykZi9|w1y>W2PLHoAQ$)F?R5?Al<5NsW z?-wG%4}`WOg6*CcY2PSysQ*f`uyG{k0cOgVUf(3Bcy~0H5YEyV>As0Ro@$v&of4A{ z%?@o}YvF;T!d-1=rf|-IJ7mDFTwj6Veaj%<4?;i%WPeqLSM}$Rv)o8^X{{LgbWQr! zf+$@Yzs^#)&rylV{CK`p!JxP$w%OT%8VHg(g`I(Z6#nU3#g&``239IEEf}#e&9bJj z;YX^nL+ZE9%Z_a23u4brIMgP)OI_N-XsU^*$9V;Vm#^3mu`DDH{qrYr zR%bVsGurf{ShHMThHKi!=p?>V@$Z$T4<8SCOOMM$fQY%ubTU9~W7v<%Fs9ppjZlqZ z;fW0Cqf5HBHaczJbU`P8PIE-4-N`7@*qXPgPc+lDcqOLw8fC?`xLmaaX|__2(@#53 ztqR_|F7Uq(=2@1$q~B2LRKaslY!$#3+)?Ci`(%W)ru}OIM}XHVPL!}ZnOrox&FSU z~jskt_Z%+b5XT|wh!C7YsQ@*1v; z?mZk#2GQ{7Q=RA=dzCpX9pN$E>BV8wqx9VO+Ca5(xH?h&r%vV-wAX6dS9c|>Tf5r% zLz*5XO0tR>#ngDxja|OMb^(}-stu_0+b^{hwHgHu{KQ-{HrQC6WW92W9LOFz?*L2K z(JOOG?qN#mMCOndZCL{ulwvl|k2F@h2J?ip8q|ic9`?H)PHbny+Soh1>duIXxw!Di zb$!yy7U`_JwDJL>y#?%7^r5X1ahUhVZBH#3@3=% zqZN>p2jq%CUR@CKWwQveJeUswT`}}p7O`K_vn<#u6AE$hsn0$xby-ro-C6Rm8WKA6 zg0ibIy+E;?ppi?Plps{RAtF_@wNP4fu~>jT4)ke3>E=kR^GYz)HhaoPJ5>ecBay};@6K}tREZqE)2D@C*n*Pq~4W}*8bR2K7aO0jutzJd2y^<~b*D}g`?q?k*q zr78ZI&f$d6mZMKamc-ai?Q0lo8C(=lt+S*4AS{WNL{#=J`oXnlL>jF*MiIn9jD3ss z{R|O=F8U2a`6YN&S>3!U3IDNDYAwZjAL2qsq9>NhIl_-#2-p{FET=<#<+OL zFK4sF>CIYtlXP`KGsd2+lnRl{@Q5Z>;sbn5%_i5wF=C-g0D3Z!oCr=RZr#0mJ7ENE z6mk4T-a)1@RBAl@hb!SsxCK8I~aCnCjdG{{F3@gOuM3m#qLoN_om6*RW+c-wlgjS)LZP7Db zI^w+V#r{{=MzKZ$K|MiJfr5kXy_mw#Q|(cQfqeMKu!5D#!;5;}FM;C7QB|}hF458| zo~KUz0pFP+{fJkJ^)ZsKiNI%Z*@jhUz^~#m{}cM5k}gg#5v;Gfx1PMXxX~ z-ZBDjW`33a@2j}#>|&sVxKSz;1y7Vuyvwte*IMxFuR6kuS5Wl?$gsf)4!lrYqRJ8| zGv6gF?3A}`pIPvg3N#~0+oohDCl2a1&dM)asZ+e6+ju^qOK%y5w=$gfWDGF8lO5xX z&Da8JcRz(#s(4H%?C3wE=uei?+P7I8@zfwg|Lppfv%$%x?I}QeQj8&Vb><`)hdwex zB)6P9JOY0RWEj(u17+d@9>=rbU@8@M1qZfeYQt>fg5*@~gSZ3>_Nn@a9*U69i(mhZ zOk_Pi-2?0uMYuWh6ooCj;e(Q_SHyBnQvME*;w+y9GZbzyvpq^Oj^8m$IAsum;+RW^{695?o@!coRIb zaQ-0l&q2V{6X@)~t)1_q6Rd@Ke From 359a1b0ca91ec21eb499f6bc91fa784a35fe2cd4 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:04:49 -0300 Subject: [PATCH 209/334] Add files via upload --- docs/images/datasync-metromap.drawio.png | Bin 0 -> 59029 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..7abc1a5f89873a68f9ef871750b6ee539a242506 GIT binary patch literal 59029 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 ONJ~xsK0@Wu>;D5zvjOD* literal 0 HcmV?d00001 From 2b553c3b4dc0d8fb12c649c243c505b7f64b6b4f Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:06:02 -0300 Subject: [PATCH 210/334] Delete docs/images/datasync-metromap.drawio.png --- docs/images/datasync-metromap.drawio.png | Bin 59029 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png deleted file mode 100644 index 7abc1a5f89873a68f9ef871750b6ee539a242506..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59029 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 ONJ~xsK0@Wu>;D5zvjOD* From c6dcf3d09e406e012c7aebeba0e3250f0f3132bd Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:06:20 -0300 Subject: [PATCH 211/334] Add files via upload --- docs/images/datasync-metromap.drawio.png | Bin 0 -> 58840 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..108bbc0d85c982f1fb48c6bff7b73099f2f236e3 GIT binary patch literal 58840 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 literal 0 HcmV?d00001 From 2ff8c9197a7cbb06314aa73249de53ffd8702c88 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:07:30 -0300 Subject: [PATCH 212/334] Delete docs/images/datasync-metromap.drawio.png --- docs/images/datasync-metromap.drawio.png | Bin 58840 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png deleted file mode 100644 index 108bbc0d85c982f1fb48c6bff7b73099f2f236e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58840 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 From d11002a419336b15c156ae824a87aaffb522e4d0 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:08:00 -0300 Subject: [PATCH 213/334] Add files via upload --- docs/images/datasync-metromap.drawio.png | Bin 0 -> 58840 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..108bbc0d85c982f1fb48c6bff7b73099f2f236e3 GIT binary patch literal 58840 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 literal 0 HcmV?d00001 From a720a7bad32f47f4320564c39155e20ba91eae3f Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:08:42 -0300 Subject: [PATCH 214/334] Delete docs/images/datasync-metromap.drawio.png --- docs/images/datasync-metromap.drawio.png | Bin 58840 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png deleted file mode 100644 index 108bbc0d85c982f1fb48c6bff7b73099f2f236e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58840 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 From c38ce423a0963fea9f1328988c59615f90a29618 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:09:46 -0300 Subject: [PATCH 215/334] Add files via upload --- docs/images/datasync-metromap.drawio.png | Bin 0 -> 58840 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..108bbc0d85c982f1fb48c6bff7b73099f2f236e3 GIT binary patch literal 58840 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 literal 0 HcmV?d00001 From 316efd36ad6927193d4313e900de3ef0a561002c Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:10:34 -0300 Subject: [PATCH 216/334] Delete docs/images/datasync-metromap.drawio.png --- docs/images/datasync-metromap.drawio.png | Bin 58840 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/images/datasync-metromap.drawio.png diff --git a/docs/images/datasync-metromap.drawio.png b/docs/images/datasync-metromap.drawio.png deleted file mode 100644 index 108bbc0d85c982f1fb48c6bff7b73099f2f236e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58840 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 From 1a69b5e2b2ed9d2dcaf501cb08db42167ca802d9 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:10:52 -0300 Subject: [PATCH 217/334] Add files via upload --- docs/images/datasync-metromap.png | Bin 0 -> 58840 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/datasync-metromap.png diff --git a/docs/images/datasync-metromap.png b/docs/images/datasync-metromap.png new file mode 100644 index 0000000000000000000000000000000000000000..108bbc0d85c982f1fb48c6bff7b73099f2f236e3 GIT binary patch literal 58840 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 literal 0 HcmV?d00001 From 589fb05c2d0963306b57b1529e27729b43427aa1 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:11:37 -0300 Subject: [PATCH 218/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b681bad..b0c0ae7 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). -![nf-core/datasync metro map](docs/images/datasync-metromap.drawio.png) +![nf-core/datasync metro map](docs/images/datasync-metromap.png) ## Quick start From 3fe2a486180fc5aa5c9a060608a4ebe3fc88cf60 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:13:39 -0300 Subject: [PATCH 219/334] Update output.md --- docs/output.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index dd3c212..af52f1a 100644 --- a/docs/output.md +++ b/docs/output.md @@ -103,7 +103,9 @@ The MultiQC report consolidates: ### `rclone checksum` section (source integrity checks) -The MD5 and SHA-256 input-validation sections show the results from `rclone checksum`. Use these sections to confirm that each source file matched the checksum manifest supplied in `checksum_md5` and/or `checksum_sha` before copying. +The MD5 and SHA-256 input-validation sections show the results from [`rclone checksum`](https://rclone.org/commands/rclone_checksum/). Use these sections to confirm that each source file matched the checksum manifest supplied in `checksum_md5` and/or `checksum_sha` before copying. + +When a samplesheet `input` points to S3, `rclone checksum` can normally validate MD5 manifests from S3 object hashes, but S3 does not provide SHA-256 object hashes for rclone to read remotely. SHA-256 validation for S3 inputs therefore requires `rclone checksum --download`, which downloads object data and calculates the hash locally during validation. Configure the checksum process to pass `--download` when SHA-256 validation is required for S3 inputs; see the [`rclone checksum --download` documentation](https://rclone.org/commands/rclone_checksum/) and the [rclone S3 hash documentation](https://rclone.org/s3/#hashes). ![nf-core/multiqc checksum md5](images/datasync-multiqc-checksum-md5.png) From 1da035b43d639ff0213aa85f00972451b21472d7 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Fri, 24 Jul 2026 13:16:09 -0300 Subject: [PATCH 220/334] Update output.md --- docs/output.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/output.md b/docs/output.md index af52f1a..548f2e0 100644 --- a/docs/output.md +++ b/docs/output.md @@ -105,7 +105,7 @@ The MultiQC report consolidates: The MD5 and SHA-256 input-validation sections show the results from [`rclone checksum`](https://rclone.org/commands/rclone_checksum/). Use these sections to confirm that each source file matched the checksum manifest supplied in `checksum_md5` and/or `checksum_sha` before copying. -When a samplesheet `input` points to S3, `rclone checksum` can normally validate MD5 manifests from S3 object hashes, but S3 does not provide SHA-256 object hashes for rclone to read remotely. SHA-256 validation for S3 inputs therefore requires `rclone checksum --download`, which downloads object data and calculates the hash locally during validation. Configure the checksum process to pass `--download` when SHA-256 validation is required for S3 inputs; see the [`rclone checksum --download` documentation](https://rclone.org/commands/rclone_checksum/) and the [rclone S3 hash documentation](https://rclone.org/s3/#hashes). +When a samplesheet `input` points to S3, `rclone checksum` can normally validate MD5 manifests from S3 object hashes, but S3 does not provide SHA-256 object hashes for rclone to read remotely. SHA-256 validation for S3 inputs therefore requires `rclone checksum --download`, which downloads object data and calculates the hash locally during validation. Configure the checksum process to pass `--download` when SHA-256 validation is required for S3 inputs; see the [`rclone checksum` --download documentation](https://rclone.org/commands/rclone_checksum/). ![nf-core/multiqc checksum md5](images/datasync-multiqc-checksum-md5.png) From d881783eeb285f3dbfcfd838ec43c8447c72f5f4 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 27 Jul 2026 16:13:36 +0200 Subject: [PATCH 221/334] Implement only copying files that matched their checksum --- conf/modules.config | 24 +++++++++++ modules/nf-core/rclone/copy/main.nf | 2 +- nextflow.config | 1 + nextflow_schema.json | 6 +++ workflows/datasync.nf | 67 +++++++++++++++++++++-------- 5 files changed, 81 insertions(+), 19 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 3a376b6..847d32d 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,6 +18,29 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] + withName: 'RCLONE_COPY_MATCHING_ONLY' { + ext.args = { + def base_args = [ + '--log-level INFO', + '--stats 30s', + '--stats-one-line', + '--stats-log-level INFO', + '--s3-chunk-size 64M', + '--no-check-certificate', + "--include-from ${filter_file}" + ] + if (params.rclone_dry_run) { + base_args.add('--dry-run') + } + base_args.join(' ') + } + publishDir = [ + path: { "${params.outdir}/rclone/copy" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + withName: 'RCLONE_COPY' { ext.args = { def base_args = [ @@ -56,6 +79,7 @@ process { } withName: 'RCLONE_CHECKSUM' { + tag = { "${meta.id}_${hash}" } ext.args = { def base_args = [ '--no-check-certificate', diff --git a/modules/nf-core/rclone/copy/main.nf b/modules/nf-core/rclone/copy/main.nf index 2c97b43..a063abf 100644 --- a/modules/nf-core/rclone/copy/main.nf +++ b/modules/nf-core/rclone/copy/main.nf @@ -8,7 +8,7 @@ process RCLONE_COPY { : 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be'}" input: - tuple val(meta), val(source_path), val(destination_path) + tuple val(meta), val(source_path), val(destination_path), path(filter_file) path rclone_config output: diff --git a/nextflow.config b/nextflow.config index e87a679..216b3fc 100644 --- a/nextflow.config +++ b/nextflow.config @@ -23,6 +23,7 @@ params { // Rclone options rclone_config = null rclone_dry_run = false + copy_matching_only = false // Boilerplate options outdir = null diff --git a/nextflow_schema.json b/nextflow_schema.json index e17f7cb..a8dc091 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -54,6 +54,12 @@ "description": "Perform a dry run of the rclone copy command.", "fa_icon": "fas fa-eye", "help_text": "If set, the pipeline will not actually copy any files to the destination. Instead, it will print out what would have been copied. This is useful for testing and debugging." + }, + "copy_matching_only": { + "type": "boolean", + "description": "Only copy files that matched their provided input checksums.", + "fa_icon": "fas fa-eye", + "help_text": "If set, the pipeline will only copy files that were correctly validated and will skip any file that did not match their input checksum." } } }, diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 23eb696..b35058a 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -3,15 +3,16 @@ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { MULTIQC } from '../modules/nf-core/multiqc/main' -include { RCLONE_COPY } from '../modules/nf-core/rclone/copy/main' -include { RCLONE_CHECK } from '../modules/nf-core/rclone/check/main' -include { RCLONE_CHECKSUM } from '../modules/nf-core/rclone/checksum/main' -include { paramsSummaryMap } from 'plugin/nf-schema' -include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' -include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' -include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_datasync_pipeline' -include { parseRcloneCheck } from '../subworkflows/local/utils_nfcore_datasync_pipeline' +include { MULTIQC } from '../modules/nf-core/multiqc/main' +include { RCLONE_COPY } from '../modules/nf-core/rclone/copy/main' +include { RCLONE_COPY as RCLONE_COPY_MATCHING_ONLY } from '../modules/nf-core/rclone/copy/main' +include { RCLONE_CHECK } from '../modules/nf-core/rclone/check/main' +include { RCLONE_CHECKSUM } from '../modules/nf-core/rclone/checksum/main' +include { paramsSummaryMap } from 'plugin/nf-schema' +include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' +include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' +include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_datasync_pipeline' +include { parseRcloneCheck } from '../subworkflows/local/utils_nfcore_datasync_pipeline' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -88,19 +89,49 @@ workflow DATASYNC { // // MODULE: Rclone data copying // - RCLONE_COPY( - ch_samplesheet.rclone, - ch_rclone_config - ) + if(params.copy_matching_only) { + files_to_copy = RCLONE_CHECKSUM.out.match.map { + meta, match -> [ meta.subMap(meta.keySet() - 'check_format'), match ] + } + .groupTuple() + .map{ meta, files -> + def common = files + .collect { it.readLines() } + .inject { a, b -> a.intersect(b) } + + def copy_files = file("${outdir}/${meta.id}_files_to_copy.txt") + copy_files.text = common.join('\n') + '\n' + + tuple(meta, copy_files) + } + + ch_rclone_copy = ch_samplesheet.rclone + .join(files_to_copy) + + RCLONE_COPY_MATCHING_ONLY( + ch_rclone_copy, + ch_rclone_config, + ) + + // Wait for file copy to finish before running RCLONE_CHECK + ch_rclone_check = ch_samplesheet.rclone + .join(RCLONE_COPY_MATCHING_ONLY.out.log) + .map { meta, input, output, log -> [ meta, input, output ]} + } else { + RCLONE_COPY( + ch_samplesheet.rclone.map { meta, source, destination -> [ meta, source, destination, [] ]}, + ch_rclone_config, + ) + + // Wait for file copy to finish before running RCLONE_CHECK + ch_rclone_check = ch_samplesheet.rclone + .join(RCLONE_COPY.out.log) + .map { meta, input, output, log -> [ meta, input, output ]} + } // // File transfer validation // - // Wait for file copy to finish before running RCLONE_CHECK - ch_rclone_check = ch_samplesheet.rclone - .join(RCLONE_COPY.out.log) - .map { meta, input, output, log -> [ meta, input, output ]} - RCLONE_CHECK( ch_rclone_check, ch_rclone_config From 999dca5225ed51460925a21ee8a34e2d56e5bcb2 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 27 Jul 2026 19:45:48 +0200 Subject: [PATCH 222/334] Compute siz to avoid silent data loss --- workflows/datasync.nf | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index b35058a..e201b82 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -90,9 +90,18 @@ workflow DATASYNC { // MODULE: Rclone data copying // if(params.copy_matching_only) { + // Compute expected group size per meta.id from the input + ch_with_size = ch_checksum + .map { meta, checksum, hash, source -> [ meta.subMap(meta.keySet() - 'check_format'), 1 ] } + .groupTuple() + .map { meta, ones -> tuple(meta, ones.size()) } + .view() + files_to_copy = RCLONE_CHECKSUM.out.match.map { meta, match -> [ meta.subMap(meta.keySet() - 'check_format'), match ] } + .combine(ch_with_size, by: 0) + .map { meta, match, size -> tuple(groupKey(meta, size), match) } .groupTuple() .map{ meta, files -> def common = files From 32dcb749eb7d0fa159ce4b1f6933ac1ad41213e0 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 27 Jul 2026 20:37:53 +0200 Subject: [PATCH 223/334] Refactor to only use rclone_copy once --- conf/modules.config | 26 +++----------------------- workflows/datasync.nf | 34 ++++++++++++---------------------- 2 files changed, 15 insertions(+), 45 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 847d32d..794c4d9 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,29 +18,6 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] - withName: 'RCLONE_COPY_MATCHING_ONLY' { - ext.args = { - def base_args = [ - '--log-level INFO', - '--stats 30s', - '--stats-one-line', - '--stats-log-level INFO', - '--s3-chunk-size 64M', - '--no-check-certificate', - "--include-from ${filter_file}" - ] - if (params.rclone_dry_run) { - base_args.add('--dry-run') - } - base_args.join(' ') - } - publishDir = [ - path: { "${params.outdir}/rclone/copy" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } - ] - } - withName: 'RCLONE_COPY' { ext.args = { def base_args = [ @@ -54,6 +31,9 @@ process { if (params.rclone_dry_run) { base_args.add('--dry-run') } + if (params.copy_matching_only) { + base_args.add("--include-from ${filter_file}") + } base_args.join(' ') } publishDir = [ diff --git a/workflows/datasync.nf b/workflows/datasync.nf index e201b82..7f64a97 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -5,7 +5,6 @@ */ include { MULTIQC } from '../modules/nf-core/multiqc/main' include { RCLONE_COPY } from '../modules/nf-core/rclone/copy/main' -include { RCLONE_COPY as RCLONE_COPY_MATCHING_ONLY } from '../modules/nf-core/rclone/copy/main' include { RCLONE_CHECK } from '../modules/nf-core/rclone/check/main' include { RCLONE_CHECKSUM } from '../modules/nf-core/rclone/checksum/main' include { paramsSummaryMap } from 'plugin/nf-schema' @@ -95,7 +94,6 @@ workflow DATASYNC { .map { meta, checksum, hash, source -> [ meta.subMap(meta.keySet() - 'check_format'), 1 ] } .groupTuple() .map { meta, ones -> tuple(meta, ones.size()) } - .view() files_to_copy = RCLONE_CHECKSUM.out.match.map { meta, match -> [ meta.subMap(meta.keySet() - 'check_format'), match ] @@ -108,7 +106,7 @@ workflow DATASYNC { .collect { it.readLines() } .inject { a, b -> a.intersect(b) } - def copy_files = file("${outdir}/${meta.id}_files_to_copy.txt") + def copy_files = file("${workDir}/${meta.id}_files_to_copy.txt") copy_files.text = common.join('\n') + '\n' tuple(meta, copy_files) @@ -116,28 +114,20 @@ workflow DATASYNC { ch_rclone_copy = ch_samplesheet.rclone .join(files_to_copy) - - RCLONE_COPY_MATCHING_ONLY( - ch_rclone_copy, - ch_rclone_config, - ) - - // Wait for file copy to finish before running RCLONE_CHECK - ch_rclone_check = ch_samplesheet.rclone - .join(RCLONE_COPY_MATCHING_ONLY.out.log) - .map { meta, input, output, log -> [ meta, input, output ]} } else { - RCLONE_COPY( - ch_samplesheet.rclone.map { meta, source, destination -> [ meta, source, destination, [] ]}, - ch_rclone_config, - ) - - // Wait for file copy to finish before running RCLONE_CHECK - ch_rclone_check = ch_samplesheet.rclone - .join(RCLONE_COPY.out.log) - .map { meta, input, output, log -> [ meta, input, output ]} + ch_rclone_copy = ch_samplesheet.rclone.map { meta, source, destination -> [ meta, source, destination, [] ] } } + RCLONE_COPY( + ch_rclone_copy, + ch_rclone_config, + ) + + // Wait for file copy to finish before running RCLONE_CHECK + ch_rclone_check = ch_samplesheet.rclone + .join(RCLONE_COPY.out.log) + .map { meta, input, output, log -> [ meta, input, output ] } + // // File transfer validation // From e0d1df971a7320f7f4d3f8305a35d7d24e779320 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 27 Jul 2026 22:02:00 +0200 Subject: [PATCH 224/334] Bump nf-schema to 2.7.2 to fix errors in validation of boolean parameters in CLI --- nextflow.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow.config b/nextflow.config index 216b3fc..2423a8a 100644 --- a/nextflow.config +++ b/nextflow.config @@ -260,7 +260,7 @@ manifest { // Nextflow plugins plugins { - id 'nf-schema@2.5.1' // Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-schema@2.7.2' // Validation of pipeline parameters and creation of an input channel from a sample sheet } validation { From 556e2baa8d8ca06c0418b0cad186c95153beb14f Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 28 Jul 2026 14:17:39 +0200 Subject: [PATCH 225/334] Remove vulnerable PR-comment artifact pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pipeline's TEMPLATE branch never received the nf-core/tools 4.0.3 sync, so the patch was taken from nf-core/abotyper's TEMPLATE branch with the repository identity in branch.yml rewritten for this pipeline. That identity is the only pipeline-specific content the template renders into any of the patched workflows, so this is the same change this pipeline's own sync would have produced — but the substituted source is worth a look. --- .github/workflows/branch.yml | 60 +++++++++----- .github/workflows/linting.yml | 18 ++++ .github/workflows/linting_comment.yml | 28 ------- .github/workflows/nf-test.yml | 57 +++++++++++++ .github/workflows/pr-comment.yml | 82 +++++++++++++++++++ .../workflows/template-version-comment.yml | 56 ++++++++----- .nf-core.yml | 8 +- 7 files changed, 236 insertions(+), 73 deletions(-) delete mode 100644 .github/workflows/linting_comment.yml create mode 100644 .github/workflows/pr-comment.yml diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 7716a7b..720e16c 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -2,11 +2,13 @@ name: nf-core branch protection # This workflow is triggered on PRs to `main`/`master` branch on the repository # It fails when someone tries to make a PR against the nf-core `main`/`master` branch instead of `dev` on: - pull_request_target: + pull_request: branches: - main - master +permissions: {} + jobs: test: runs-on: ubuntu-latest @@ -14,33 +16,47 @@ jobs: # PRs to the nf-core repo main/master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches - name: Check PRs if: github.repository == 'nf-core/datasync' + env: + HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} run: | - { [[ ${{github.event.pull_request.head.repo.full_name }} == nf-core/datasync ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] + { [[ "$HEAD_REPO" == nf-core/datasync ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] - # If the above check failed, post a comment on the PR explaining the failure - # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets - - name: Post PR comment + # If the above check failed, build a comment to be posted by the shared poster workflow + - name: Build PR comment if: failure() - uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3 - with: - message: | - ## This PR is against the `${{github.event.pull_request.base.ref}}` branch :x: + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + BASE_REF: ${{ github.event.pull_request.base.ref }} + HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} + PR_USER: ${{ github.event.pull_request.user.login }} + run: | + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "branch" > pr-comment/header.txt + cat > pr-comment/comment.md < pr-comment/pr_number.txt + echo "lint" > pr-comment/header.txt + [ -f lint_results.md ] && cp lint_results.md pr-comment/comment.md || true + + - name: Upload PR comment artifact + if: ${{ always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pr-comment + path: pr-comment/ diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml deleted file mode 100644 index 5b0c24f..0000000 --- a/.github/workflows/linting_comment.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: nf-core linting comment -# This workflow is triggered after the linting action is complete -# It posts an automated comment to the PR, even if the PR is coming from a fork - -on: - workflow_run: - workflows: ["nf-core linting"] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Download lint results - uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 - with: - workflow: linting.yml - workflow_conclusion: completed - - - name: Get PR number - id: pr_number - run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - - - name: Post PR comment - uses: marocchino/sticky-pull-request-comment@70d2764d1a7d5d9560b100cbea0077fc8f633987 # v3 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - number: ${{ steps.pr_number.outputs.pr_number }} - path: linting-logs/lint_results.md diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml index efd72d6..4de681a 100644 --- a/.github/workflows/nf-test.yml +++ b/.github/workflows/nf-test.yml @@ -116,6 +116,22 @@ jobs: fi fi + # continue-on-error keeps latest-everything from failing the job, so it never shows up in + # `needs.nf-test.result` downstream and CI stays green. Surface it via a PR comment instead; + # other NXF_VER failures already fail the job/CI directly, so no comment is needed for those. + - name: Prepare PR comment fragment + if: ${{ always() && steps.run_nf_test.outcome == 'failure' && matrix.NXF_VER == 'latest-everything' }} + run: | + mkdir -p pr-comment-fragment + echo "* ❌ \`${{ matrix.profile }}\` | \`${{ matrix.NXF_VER }}\` | Shard ${{ matrix.shard }}/${{ env.TOTAL_SHARDS }}" > pr-comment-fragment/fragment.md + + - name: Upload PR comment fragment + if: ${{ always() && steps.run_nf_test.outcome == 'failure' && matrix.NXF_VER == 'latest-everything' }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pr-comment-fragment-${{ strategy.job-index }} + path: pr-comment-fragment/ + confirm-pass: needs: [nf-test] if: always() @@ -142,3 +158,44 @@ jobs: echo "DEBUG: toJSON(needs) = ${{ toJSON(needs) }}" echo "DEBUG: toJSON(needs.*.result) = ${{ toJSON(needs.*.result) }}" echo "::endgroup::" + + - name: Download PR comment fragments + if: ${{ always() }} + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + continue-on-error: true + with: + pattern: pr-comment-fragment-* + path: pr-comment-fragments + merge-multiple: true + + # Build a comment for the shared pr-comment.yml poster to publish on the PR. + # Based on the fragments above (not needs.*.result) so non-blocking failures are still reported. + - name: Prepare PR comment + if: ${{ always() }} + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "nf-test" > pr-comment/header.txt + if [ -d pr-comment-fragments ] && [ -n "$(ls -A pr-comment-fragments)" ]; then + { + echo "## ❌ nf-test failed with latest Nextflow version" + echo "" + echo "> [!NOTE]" + echo "> Tests with Nextflow's latest version failed but it will not cause a CI workflow failure." + echo "> Please check if the failure is expected with newer (edge-)releases of Nextflow or if it needs fixing." + echo "" + cat pr-comment-fragments/*.md + echo "" + echo "See the [full run](${RUN_URL}) for details." + } > pr-comment/comment.md + fi + + - name: Upload PR comment artifact + if: ${{ always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pr-comment + path: pr-comment/ diff --git a/.github/workflows/pr-comment.yml b/.github/workflows/pr-comment.yml new file mode 100644 index 0000000..ab7b59d --- /dev/null +++ b/.github/workflows/pr-comment.yml @@ -0,0 +1,82 @@ +name: Post PR comment +# Shared, privileged comment poster. +# +# This is the single workflow that runs with a write token. It is triggered +# after any of the listed "producer" workflows complete on a pull request. +# Each producer runs untrusted PR code (if any) with a read-only token and +# uploads a `pr-comment` artifact describing the comment to post; this workflow +# only ever reads that plain-text artifact, so no PR code is executed here. +# +# Artifact contract (uploaded by producers under the name `pr-comment`): +# pr_number.txt - the pull request number +# header.txt - sticky-comment identifier (keeps comment types separate) +# comment.md - the Markdown body (omit the file to post nothing) + +on: + workflow_run: + workflows: + - "nf-core linting" + - "nf-core template version comment" + - "nf-core branch protection" + - "Run nf-test" + +permissions: + actions: read + contents: read + pull-requests: write + +jobs: + post-comment: + runs-on: ubuntu-latest + if: github.event.workflow_run.event == 'pull_request' + steps: + - name: Download PR comment artifact + uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 + with: + run_id: ${{ github.event.workflow_run.id }} + name: pr-comment + path: pr-comment + if_no_artifact_found: ignore + + - name: Read comment metadata + id: meta + run: | + echo "::group::Downloaded pr-comment contents" + ls -la pr-comment 2>/dev/null || echo "No pr-comment/ directory was downloaded." + echo "::endgroup::" + + if [ ! -d pr-comment ]; then + echo "No pr-comment artifact found; nothing to post." + exit 0 + fi + + if [ ! -f pr-comment/comment.md ]; then + echo "Artifact present but no comment.md; nothing to post." + exit 0 + fi + + pr_number=$(cat pr-comment/pr_number.txt) + header=$(cat pr-comment/header.txt) + echo "Found comment.md (header='$header', pr_number='$pr_number')." + + # Guard against anything unexpected ending up in the PR number. + case "$pr_number" in + ''|*[!0-9]*) + echo "Invalid PR number: '$pr_number'" + exit 1 + ;; + esac + + echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" + echo "header=$header" >> "$GITHUB_OUTPUT" + echo "post=true" >> "$GITHUB_OUTPUT" + echo "Will post comment to PR #${pr_number}." + + - name: Post PR comment + if: steps.meta.outputs.post == 'true' + uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + number: ${{ steps.meta.outputs.pr_number }} + header: ${{ steps.meta.outputs.header }} + path: pr-comment/comment.md diff --git a/.github/workflows/template-version-comment.yml b/.github/workflows/template-version-comment.yml index ea30827..ee102f7 100644 --- a/.github/workflows/template-version-comment.yml +++ b/.github/workflows/template-version-comment.yml @@ -2,10 +2,13 @@ name: nf-core template version comment # This workflow is triggered on PRs to check if the pipeline template version matches the latest nf-core version. # It posts a comment to the PR, even if it comes from a fork. -on: pull_request_target +on: + pull_request: + +permissions: {} jobs: - template_version: + check_template_version: runs-on: ubuntu-latest steps: - name: Check out pipeline code @@ -22,25 +25,36 @@ jobs: - name: Install nf-core run: | python -m pip install --upgrade pip - pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} + pip install nf-core + + - name: Build PR comment if template is outdated + # The fork-controlled version is passed via the environment and only ever + # used as quoted shell data (never interpolated into a command), so it + # cannot be used for script injection. + env: + PR_VERSION: ${{ steps.read_yml.outputs['nf_core_version'] }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "template-version" > pr-comment/header.txt + + latest_version=$(nf-core --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1) - - name: Check nf-core outdated - id: nf_core_outdated - run: echo "OUTPUT=$(pip list --outdated | grep nf-core)" >> ${GITHUB_ENV} + if [ -n "$PR_VERSION" ] && [ -n "$latest_version" ] && [ "$PR_VERSION" != "$latest_version" ]; then + cat > pr-comment/comment.md < [!WARNING] + > Newer version of the nf-core template is available. + > + > Your pipeline is using an old version of the nf-core template: ${PR_VERSION}. + > Please update your pipeline to the latest version. + > + > For more documentation on how to update your pipeline, please see the [Synchronisation documentation](https://nf-co.re/docs/developing/template-syncs/overview). + EOF + fi - - name: Post nf-core template version comment - uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3 - if: | - contains(env.OUTPUT, 'nf-core') + - name: Upload PR comment artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - repo-token: ${{ secrets.NF_CORE_BOT_AUTH_TOKEN }} - allow-repeats: false - message: | - > [!WARNING] - > Newer version of the nf-core template is available. - > - > Your pipeline is using an old version of the nf-core template: ${{ steps.read_yml.outputs['nf_core_version'] }}. - > Please update your pipeline to the latest version. - > - > For more documentation on how to update your pipeline, please see the [Synchronisation documentation](https://nf-co.re/docs/developing/template-syncs/overview). - # + name: pr-comment + path: pr-comment/ diff --git a/.nf-core.yml b/.nf-core.yml index cf24bd7..c75165a 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -2,8 +2,7 @@ nf_core_version: 4.0.2 repository_type: pipeline template: author: Alexander Peltzer - description: A simple sysops pipeline that can be used to synchronize, integrity - check and permanently archive data. + description: A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data. force: false is_nfcore: true name: datasync @@ -12,3 +11,8 @@ template: version: 1.0dev lint: multiqc_config: false + files_exist: + - .github/workflows/linting_comment.yml + files_unchanged: + - .github/workflows/branch.yml + - .github/workflows/linting.yml From 426b319502d6a412c0860ea2e28560125f38d07d Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Tue, 28 Jul 2026 16:53:40 +0200 Subject: [PATCH 226/334] Apply suggestions from code review Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- README.md | 13 ++++++++----- docs/usage.md | 25 ++++++++++++++++--------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index b0c0ae7..0690703 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,13 @@ 1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/); 2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/); 3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and -4. produces detailed rclone status files and a consolidated MultiQC report. +4. produces detailed `rclone` status files and a consolidated MultiQC report. -Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. Pass an rclone configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). +Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. + +The current tested use case for this pipeline is transfer between S3 buckets. + +Pass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). ![nf-core/datasync metro map](docs/images/datasync-metromap.png) @@ -44,12 +48,11 @@ To explore the pipeline outputs before preparing your own data, run the bundled ```bash nextflow run nf-core/datasync \ - -r \ -profile test,docker \ --outdir results ``` -The `test` profile supplies a small samplesheet and rclone configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data. +The `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data. To run the pipeline on your own data, create a samplesheet containing one transfer per row: @@ -70,7 +73,7 @@ nextflow run nf-core/datasync \ --rclone_config /path/to/rclone.conf ``` -`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [rclone configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination. +`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination. See the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters). diff --git a/docs/usage.md b/docs/usage.md index c498483..c3d20cf 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -68,7 +68,14 @@ An [example samplesheet](../assets/samplesheet.csv) is included in the repositor ## Configuring `rclone` remotes -The file supplied with `--rclone_config` uses rclone's INI-style format. Each `[name]` section defines a remote, and samplesheet paths refer to it as `name:path`. The remote name is an arbitrary local label; it does not need to match the provider or bucket name. The pipeline's documented and tested configuration pattern is S3-to-S3 transfer. One file may contain several sections, so other cloud-to-cloud transfers can define both providers in the same file, but provider-specific options should be taken from the relevant rclone documentation rather than inferred from the S3 example: +The file supplied with `--rclone_config` uses `rclone`'s INI-style format. + +Each `[name]` section defines a remote, and samplesheet paths refer to it as `name:path`. The remote name is an arbitrary local label; it does not need to match the provider or bucket name. + +> [!NOTE] +> The pipeline's documented and tested configuration pattern is S3-to-S3 transfer. + +One file may contain several sections, so other cloud-to-cloud transfers can define both providers in the same file, but provider-specific options should be taken from the relevant `rclone` documentation. This is an example using S3: ```text source_s3:incoming/run_001 @@ -105,18 +112,18 @@ secret_access_key = YOUR_SECRET_ACCESS_KEY region = eu-central-1 ``` -The corresponding input values could be `source_s3:incoming/run_001` and `institutional_s3:project/run_002`. Provider-specific settings vary: consult the [rclone S3 documentation](https://rclone.org/s3/) and your storage provider's endpoint, region, addressing-style, and credential documentation rather than copying example values unchanged. +The corresponding input values could be `source_s3:incoming/run_001` and `institutional_s3:project/run_002`. Provider-specific settings vary: consult the [`rclone` S3 documentation](https://rclone.org/s3/) and your storage provider's endpoint, region, addressing-style, and credential documentation rather than copying example values unchanged. -The pipeline also accepts an `s3://bucket/path` source or destination. In that form, ensure credentials and provider settings are available to both Nextflow and rclone in the execution environment. A named remote such as `source_s3:bucket/path` makes the selected configuration section explicit and is preferable when a config file contains multiple S3 providers. +The pipeline also accepts an `s3://bucket/path` source or destination. In that form, ensure credentials and provider settings are available to both Nextflow and `rclone` in the execution environment. A named remote such as `source_s3:bucket/path` makes the selected configuration section explicit and is preferable when a config file contains multiple S3 providers. ## Destination layout The pipeline preserves the source basename: -- for a file source, rclone copies the file into `output_path`, and validation expects `output_path/`; +- for a file source, `rclone` copies the file into `output_path`, and validation expects `output_path/`; - for a directory source, the pipeline appends the source directory name, so `/data/run_001` with `output_path=/archive/runs` is copied and checked at `/archive/runs/run_001`. -A trailing slash on `output_path` is removed before these paths are constructed. Ensure that a destination does not already contain unrelated files: post-copy validation uses `rclone check --one-way`, which checks that source content exists and matches at the destination while tolerating destination-only files. +A trailing slash on `output_path` is removed before these paths are constructed. Ensure that a destination does not already contain unrelated files: post-copy validation uses `rclone check --one-way`, which checks that source content exists and matches at the destination while tolerating destination-only files. You can override this behavior by providing your own config file with external arguments for `rclone check`. ## Running the pipeline @@ -199,7 +206,7 @@ Do not use `-c` for pipeline parameters. Use it only for Nextflow executor, reso ### Common integrity outcomes -The workflow is designed to collect rclone reports even when rclone detects differences. The table below summarises common edge cases and how to interpret them in the published reports and MultiQC. +The workflow is designed to collect `rclone` reports even when `rclone` detects differences. The table below summarises common edge cases and how to interpret them in the published reports and MultiQC. | Situation | Where it is detected | Report status | Pipeline behaviour and action | | ------------------------------------------------------------------ | ---------------------------------------------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -215,7 +222,7 @@ The workflow is designed to collect rclone reports even when rclone detects diff ### Including or excluding files -Filter files by passing additional rclone filter flags to the relevant rclone module through a Nextflow configuration file. Rclone supports flags such as `--include`, `--exclude`, `--filter`, `--files-from`, and related rule files; see the [rclone filtering documentation](https://rclone.org/filtering/) for rule syntax and ordering. +Filter files by passing additional `rclone` filter flags to the relevant rclone module through a Nextflow configuration file. `rclone` supports flags such as `--include`, `--exclude`, `--filter`, `--files-from`, and related rule files; see the [`rclone` filtering documentation](https://rclone.org/filtering/) for rule syntax and ordering. For example, to copy and check only FASTQ files while excluding temporary files, create a small infrastructure config: @@ -254,11 +261,11 @@ process { } ``` -Run it with `-c rclone_filters.config` in addition to your normal profile and parameters. Because `ext.args` overrides module defaults, include the default rclone flags you still need when adding filters. Keep checksum manifests consistent with the same filtering rules: if a file is intentionally excluded from copy/check, remove it from the checksum manifest or generate a manifest for only the included files. +Run it with `-c rclone_filters.config` in addition to your normal profile and parameters. Because `ext.args` overrides module defaults, include the default `rclone` flags you still need when adding filters. Keep checksum manifests consistent with the same filtering rules: if a file is intentionally excluded from copy/check, remove it from the checksum manifest or generate a manifest for only the included files. ## Understanding completion and integrity -For each row, the pipeline first validates supplied checksum manifests, performs the copy, and then compares source and destination. Rclone comparison commands write status reports even when differences are found, allowing all results to be collected in MultiQC. Therefore, a successful Nextflow run means the workflow completed; it does **not by itself** prove every object matched. Review `multiqc/multiqc_report.html` and the reports under `rclone/`, especially lines marked `-`, `+`, `*`, or `!` (see [output documentation](output.md)). +For each row, the pipeline first validates supplied checksum manifests, performs the copy, and then compares source and destination. `rclone` comparison commands write status reports even when differences are found, allowing all results to be collected in MultiQC. Therefore, a successful Nextflow run means the workflow completed; it does **not by itself** prove every object matched. Review `multiqc/multiqc_report.html` and the reports under `rclone/`, especially lines marked `-`, `+`, `*`, or `!` (see [output documentation](output.md)). ### Reproducibility From 35778f5c1634edc538ff9e3e79a8acd5dae8fbed Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 28 Jul 2026 12:15:50 -0300 Subject: [PATCH 227/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0690703..e8ba9cd 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ 3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and 4. produces detailed `rclone` status files and a consolidated MultiQC report. -Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. +Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. From 3c365be12d60fed716ac4d8e86edeb80fd77ba53 Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 28 Jul 2026 12:19:09 -0300 Subject: [PATCH 228/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8ba9cd..ce077c1 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. -The current tested use case for this pipeline is transfer between S3 buckets. +The current tested use case for this pipeline is transfer between S3 buckets. Pass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/). From 71318c9891bf22507710df3b9e6017950d593abc Mon Sep 17 00:00:00 2001 From: Maria Antonia Saracco Date: Tue, 28 Jul 2026 12:20:22 -0300 Subject: [PATCH 229/334] Update usage.md --- docs/usage.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index c3d20cf..2e7c6fb 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -68,12 +68,12 @@ An [example samplesheet](../assets/samplesheet.csv) is included in the repositor ## Configuring `rclone` remotes -The file supplied with `--rclone_config` uses `rclone`'s INI-style format. +The file supplied with `--rclone_config` uses `rclone`'s INI-style format. -Each `[name]` section defines a remote, and samplesheet paths refer to it as `name:path`. The remote name is an arbitrary local label; it does not need to match the provider or bucket name. +Each `[name]` section defines a remote, and samplesheet paths refer to it as `name:path`. The remote name is an arbitrary local label; it does not need to match the provider or bucket name. > [!NOTE] -> The pipeline's documented and tested configuration pattern is S3-to-S3 transfer. +> The pipeline's documented and tested configuration pattern is S3-to-S3 transfer. One file may contain several sections, so other cloud-to-cloud transfers can define both providers in the same file, but provider-specific options should be taken from the relevant `rclone` documentation. This is an example using S3: @@ -123,7 +123,7 @@ The pipeline preserves the source basename: - for a file source, `rclone` copies the file into `output_path`, and validation expects `output_path/`; - for a directory source, the pipeline appends the source directory name, so `/data/run_001` with `output_path=/archive/runs` is copied and checked at `/archive/runs/run_001`. -A trailing slash on `output_path` is removed before these paths are constructed. Ensure that a destination does not already contain unrelated files: post-copy validation uses `rclone check --one-way`, which checks that source content exists and matches at the destination while tolerating destination-only files. You can override this behavior by providing your own config file with external arguments for `rclone check`. +A trailing slash on `output_path` is removed before these paths are constructed. Ensure that a destination does not already contain unrelated files: post-copy validation uses `rclone check --one-way`, which checks that source content exists and matches at the destination while tolerating destination-only files. You can override this behavior by providing your own config file with external arguments for `rclone check`. ## Running the pipeline From f892c202c9fd24004d518b7c6727a804799beebf Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 28 Jul 2026 21:51:33 +0200 Subject: [PATCH 230/334] Add test scenario copying only matching files --- tests/edge.nf.test | 29 +++++++++++++++++ tests/edge.nf.test.snap | 70 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/tests/edge.nf.test b/tests/edge.nf.test index d69a8f8..5fce38e 100644 --- a/tests/edge.nf.test +++ b/tests/edge.nf.test @@ -33,4 +33,33 @@ nextflow_pipeline { ) } } + + test("-profile test copy matching files only") { + + when { + params { + input = "https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/test-data/samplesheet_edge.csv" + outdir = "$outputDir" + copy_matching_only = true + } + } + + then { + // stable_path: All files + folders in ${params.outdir}/ with a stable path (including file name) + def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_content: All files in ${params.outdir}/ with stable content + def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + assert workflow.success + assertAll( + { assert snapshot( + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_datasync_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_path, + // All files with stable contents + stable_content + ).match() } + ) + } + } } diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index 517b27b..ea3559b 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -1,4 +1,74 @@ { + "-profile test copy matching files only": { + "content": [ + { + "RCLONE_CHECK": { + "rclone": "1.74.3-DEV" + }, + "RCLONE_CHECKSUM": { + "rclone": "1.74.3-DEV" + }, + "RCLONE_COPY": { + "rclone": "1.65.0-DEV" + }, + "Workflow": { + "nf-core/datasync": "v1.0dev" + } + }, + [ + "multiqc", + "multiqc/multiqc_data", + "multiqc/multiqc_data/llms-full.txt", + "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc.parquet", + "multiqc/multiqc_data/multiqc_citations.txt", + "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_rclone_check.txt", + "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", + "multiqc/multiqc_data/multiqc_samplesheet.txt", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_datasync_software_mqc_versions.yml", + "rclone", + "rclone/check", + "rclone/check/Illumina_annotation_incorrect", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", + "rclone/check/Illumina_annotation_missing", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", + "rclone/checksum", + "rclone/checksum/Illumina_annotation_incorrect", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.differ.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.exit_code.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", + "rclone/checksum/Illumina_annotation_missing", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.exit_code.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", + "rclone/checksum/Illumina_annotation_sha_only", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.exit_code.txt", + "rclone/copy", + "rclone/copy/Illumina_annotation_incorrect-rclone-copy.log", + "rclone/copy/Illumina_annotation_missing-rclone-copy.log" + ], + [ + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "multiqc_rclone_check.txt:md5,4b2a6990836593f69e8e81a82c3daf42", + "multiqc_rclone_checksum_md5.txt:md5,cf92203df21f04ddf8315fc606812e0b", + "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" + ] + ], + "timestamp": "2026-07-28T21:45:08.268780076", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.1" + } + }, "-profile test edge cases": { "content": [ { From fe97a5c2a459e3c6d9c936a5eb8015637ef00be9 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 28 Jul 2026 14:17:39 +0200 Subject: [PATCH 231/334] Remove vulnerable PR-comment artifact pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pipeline's TEMPLATE branch never received the nf-core/tools 4.0.3 sync, so the patch was taken from nf-core/abotyper's TEMPLATE branch with the repository identity in branch.yml rewritten for this pipeline. That identity is the only pipeline-specific content the template renders into any of the patched workflows, so this is the same change this pipeline's own sync would have produced — but the substituted source is worth a look. --- .github/workflows/branch.yml | 60 +++++++++----- .github/workflows/linting.yml | 18 ++++ .github/workflows/linting_comment.yml | 28 ------- .github/workflows/nf-test.yml | 57 +++++++++++++ .github/workflows/pr-comment.yml | 82 +++++++++++++++++++ .../workflows/template-version-comment.yml | 56 ++++++++----- .nf-core.yml | 8 +- 7 files changed, 236 insertions(+), 73 deletions(-) delete mode 100644 .github/workflows/linting_comment.yml create mode 100644 .github/workflows/pr-comment.yml diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 7716a7b..720e16c 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -2,11 +2,13 @@ name: nf-core branch protection # This workflow is triggered on PRs to `main`/`master` branch on the repository # It fails when someone tries to make a PR against the nf-core `main`/`master` branch instead of `dev` on: - pull_request_target: + pull_request: branches: - main - master +permissions: {} + jobs: test: runs-on: ubuntu-latest @@ -14,33 +16,47 @@ jobs: # PRs to the nf-core repo main/master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches - name: Check PRs if: github.repository == 'nf-core/datasync' + env: + HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} run: | - { [[ ${{github.event.pull_request.head.repo.full_name }} == nf-core/datasync ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] + { [[ "$HEAD_REPO" == nf-core/datasync ]] && [[ $GITHUB_HEAD_REF == "dev" ]]; } || [[ $GITHUB_HEAD_REF == "patch" ]] - # If the above check failed, post a comment on the PR explaining the failure - # NOTE - this doesn't currently work if the PR is coming from a fork, due to limitations in GitHub actions secrets - - name: Post PR comment + # If the above check failed, build a comment to be posted by the shared poster workflow + - name: Build PR comment if: failure() - uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3 - with: - message: | - ## This PR is against the `${{github.event.pull_request.base.ref}}` branch :x: + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + BASE_REF: ${{ github.event.pull_request.base.ref }} + HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} + PR_USER: ${{ github.event.pull_request.user.login }} + run: | + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "branch" > pr-comment/header.txt + cat > pr-comment/comment.md < pr-comment/pr_number.txt + echo "lint" > pr-comment/header.txt + [ -f lint_results.md ] && cp lint_results.md pr-comment/comment.md || true + + - name: Upload PR comment artifact + if: ${{ always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pr-comment + path: pr-comment/ diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml deleted file mode 100644 index 5b0c24f..0000000 --- a/.github/workflows/linting_comment.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: nf-core linting comment -# This workflow is triggered after the linting action is complete -# It posts an automated comment to the PR, even if the PR is coming from a fork - -on: - workflow_run: - workflows: ["nf-core linting"] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Download lint results - uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 - with: - workflow: linting.yml - workflow_conclusion: completed - - - name: Get PR number - id: pr_number - run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - - - name: Post PR comment - uses: marocchino/sticky-pull-request-comment@70d2764d1a7d5d9560b100cbea0077fc8f633987 # v3 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - number: ${{ steps.pr_number.outputs.pr_number }} - path: linting-logs/lint_results.md diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml index efd72d6..4de681a 100644 --- a/.github/workflows/nf-test.yml +++ b/.github/workflows/nf-test.yml @@ -116,6 +116,22 @@ jobs: fi fi + # continue-on-error keeps latest-everything from failing the job, so it never shows up in + # `needs.nf-test.result` downstream and CI stays green. Surface it via a PR comment instead; + # other NXF_VER failures already fail the job/CI directly, so no comment is needed for those. + - name: Prepare PR comment fragment + if: ${{ always() && steps.run_nf_test.outcome == 'failure' && matrix.NXF_VER == 'latest-everything' }} + run: | + mkdir -p pr-comment-fragment + echo "* ❌ \`${{ matrix.profile }}\` | \`${{ matrix.NXF_VER }}\` | Shard ${{ matrix.shard }}/${{ env.TOTAL_SHARDS }}" > pr-comment-fragment/fragment.md + + - name: Upload PR comment fragment + if: ${{ always() && steps.run_nf_test.outcome == 'failure' && matrix.NXF_VER == 'latest-everything' }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pr-comment-fragment-${{ strategy.job-index }} + path: pr-comment-fragment/ + confirm-pass: needs: [nf-test] if: always() @@ -142,3 +158,44 @@ jobs: echo "DEBUG: toJSON(needs) = ${{ toJSON(needs) }}" echo "DEBUG: toJSON(needs.*.result) = ${{ toJSON(needs.*.result) }}" echo "::endgroup::" + + - name: Download PR comment fragments + if: ${{ always() }} + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + continue-on-error: true + with: + pattern: pr-comment-fragment-* + path: pr-comment-fragments + merge-multiple: true + + # Build a comment for the shared pr-comment.yml poster to publish on the PR. + # Based on the fragments above (not needs.*.result) so non-blocking failures are still reported. + - name: Prepare PR comment + if: ${{ always() }} + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "nf-test" > pr-comment/header.txt + if [ -d pr-comment-fragments ] && [ -n "$(ls -A pr-comment-fragments)" ]; then + { + echo "## ❌ nf-test failed with latest Nextflow version" + echo "" + echo "> [!NOTE]" + echo "> Tests with Nextflow's latest version failed but it will not cause a CI workflow failure." + echo "> Please check if the failure is expected with newer (edge-)releases of Nextflow or if it needs fixing." + echo "" + cat pr-comment-fragments/*.md + echo "" + echo "See the [full run](${RUN_URL}) for details." + } > pr-comment/comment.md + fi + + - name: Upload PR comment artifact + if: ${{ always() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: pr-comment + path: pr-comment/ diff --git a/.github/workflows/pr-comment.yml b/.github/workflows/pr-comment.yml new file mode 100644 index 0000000..ab7b59d --- /dev/null +++ b/.github/workflows/pr-comment.yml @@ -0,0 +1,82 @@ +name: Post PR comment +# Shared, privileged comment poster. +# +# This is the single workflow that runs with a write token. It is triggered +# after any of the listed "producer" workflows complete on a pull request. +# Each producer runs untrusted PR code (if any) with a read-only token and +# uploads a `pr-comment` artifact describing the comment to post; this workflow +# only ever reads that plain-text artifact, so no PR code is executed here. +# +# Artifact contract (uploaded by producers under the name `pr-comment`): +# pr_number.txt - the pull request number +# header.txt - sticky-comment identifier (keeps comment types separate) +# comment.md - the Markdown body (omit the file to post nothing) + +on: + workflow_run: + workflows: + - "nf-core linting" + - "nf-core template version comment" + - "nf-core branch protection" + - "Run nf-test" + +permissions: + actions: read + contents: read + pull-requests: write + +jobs: + post-comment: + runs-on: ubuntu-latest + if: github.event.workflow_run.event == 'pull_request' + steps: + - name: Download PR comment artifact + uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151 # v21 + with: + run_id: ${{ github.event.workflow_run.id }} + name: pr-comment + path: pr-comment + if_no_artifact_found: ignore + + - name: Read comment metadata + id: meta + run: | + echo "::group::Downloaded pr-comment contents" + ls -la pr-comment 2>/dev/null || echo "No pr-comment/ directory was downloaded." + echo "::endgroup::" + + if [ ! -d pr-comment ]; then + echo "No pr-comment artifact found; nothing to post." + exit 0 + fi + + if [ ! -f pr-comment/comment.md ]; then + echo "Artifact present but no comment.md; nothing to post." + exit 0 + fi + + pr_number=$(cat pr-comment/pr_number.txt) + header=$(cat pr-comment/header.txt) + echo "Found comment.md (header='$header', pr_number='$pr_number')." + + # Guard against anything unexpected ending up in the PR number. + case "$pr_number" in + ''|*[!0-9]*) + echo "Invalid PR number: '$pr_number'" + exit 1 + ;; + esac + + echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" + echo "header=$header" >> "$GITHUB_OUTPUT" + echo "post=true" >> "$GITHUB_OUTPUT" + echo "Will post comment to PR #${pr_number}." + + - name: Post PR comment + if: steps.meta.outputs.post == 'true' + uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + number: ${{ steps.meta.outputs.pr_number }} + header: ${{ steps.meta.outputs.header }} + path: pr-comment/comment.md diff --git a/.github/workflows/template-version-comment.yml b/.github/workflows/template-version-comment.yml index ea30827..ee102f7 100644 --- a/.github/workflows/template-version-comment.yml +++ b/.github/workflows/template-version-comment.yml @@ -2,10 +2,13 @@ name: nf-core template version comment # This workflow is triggered on PRs to check if the pipeline template version matches the latest nf-core version. # It posts a comment to the PR, even if it comes from a fork. -on: pull_request_target +on: + pull_request: + +permissions: {} jobs: - template_version: + check_template_version: runs-on: ubuntu-latest steps: - name: Check out pipeline code @@ -22,25 +25,36 @@ jobs: - name: Install nf-core run: | python -m pip install --upgrade pip - pip install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} + pip install nf-core + + - name: Build PR comment if template is outdated + # The fork-controlled version is passed via the environment and only ever + # used as quoted shell data (never interpolated into a command), so it + # cannot be used for script injection. + env: + PR_VERSION: ${{ steps.read_yml.outputs['nf_core_version'] }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + mkdir -p pr-comment + echo "$PR_NUMBER" > pr-comment/pr_number.txt + echo "template-version" > pr-comment/header.txt + + latest_version=$(nf-core --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1) - - name: Check nf-core outdated - id: nf_core_outdated - run: echo "OUTPUT=$(pip list --outdated | grep nf-core)" >> ${GITHUB_ENV} + if [ -n "$PR_VERSION" ] && [ -n "$latest_version" ] && [ "$PR_VERSION" != "$latest_version" ]; then + cat > pr-comment/comment.md < [!WARNING] + > Newer version of the nf-core template is available. + > + > Your pipeline is using an old version of the nf-core template: ${PR_VERSION}. + > Please update your pipeline to the latest version. + > + > For more documentation on how to update your pipeline, please see the [Synchronisation documentation](https://nf-co.re/docs/developing/template-syncs/overview). + EOF + fi - - name: Post nf-core template version comment - uses: mshick/add-pr-comment@8e4927817251f1ff60c001f04568532b38e0b4a0 # v3 - if: | - contains(env.OUTPUT, 'nf-core') + - name: Upload PR comment artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - repo-token: ${{ secrets.NF_CORE_BOT_AUTH_TOKEN }} - allow-repeats: false - message: | - > [!WARNING] - > Newer version of the nf-core template is available. - > - > Your pipeline is using an old version of the nf-core template: ${{ steps.read_yml.outputs['nf_core_version'] }}. - > Please update your pipeline to the latest version. - > - > For more documentation on how to update your pipeline, please see the [Synchronisation documentation](https://nf-co.re/docs/developing/template-syncs/overview). - # + name: pr-comment + path: pr-comment/ diff --git a/.nf-core.yml b/.nf-core.yml index cf24bd7..c75165a 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -2,8 +2,7 @@ nf_core_version: 4.0.2 repository_type: pipeline template: author: Alexander Peltzer - description: A simple sysops pipeline that can be used to synchronize, integrity - check and permanently archive data. + description: A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data. force: false is_nfcore: true name: datasync @@ -12,3 +11,8 @@ template: version: 1.0dev lint: multiqc_config: false + files_exist: + - .github/workflows/linting_comment.yml + files_unchanged: + - .github/workflows/branch.yml + - .github/workflows/linting.yml From cac46ddc7192eb8899842a597fced988e9cf0793 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 28 Jul 2026 21:56:30 +0200 Subject: [PATCH 232/334] Update changelog.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01faa82..739d9d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` +- [[#67](https://github.com/nf-core/datasync/pull/67)] - Copy only files which are successfully validated ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#57](https://github.com/nf-core/datasync/pull/57)] - Add nf-tests with edge cases([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#55](https://github.com/nf-core/datasync/pull/55)] - Add subdirectories with sample id to results. Improvements to MultiQC report (width of columns, sections and sub-section headers)colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#54](https://github.com/nf-core/datasync/pull/54)] - Add colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). From 6cb7cac6c58643c12a074bfddf41f15bf8f1af83 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 29 Jul 2026 15:19:00 +0200 Subject: [PATCH 233/334] Update rclone_copy --- modules.json | 2 +- modules/nf-core/rclone/copy/meta.yml | 7 ++++ .../nf-core/rclone/copy/tests/main.nf.test | 42 +++++++++++++++++-- .../rclone/copy/tests/main.nf.test.snap | 26 ++++++++++++ .../nf-core/rclone/copy/tests/nextflow.config | 9 +++- 5 files changed, 81 insertions(+), 5 deletions(-) diff --git a/modules.json b/modules.json index 66e3022..df30276 100644 --- a/modules.json +++ b/modules.json @@ -22,7 +22,7 @@ }, "rclone/copy": { "branch": "master", - "git_sha": "a554e54c63c3f03f91c88a18ece7b89eca5a5212", + "git_sha": "b34acd9d361bb226be8f0cf446b8b3a20ad0e3da", "installed_by": ["modules"] } } diff --git a/modules/nf-core/rclone/copy/meta.yml b/modules/nf-core/rclone/copy/meta.yml index 93ed4f9..18c5bf1 100644 --- a/modules/nf-core/rclone/copy/meta.yml +++ b/modules/nf-core/rclone/copy/meta.yml @@ -36,6 +36,13 @@ input: path internally. Examples: `results/output`, `s3:bucket/output`, `gs:bucket/output`, `remote:path/to/output`. + - filter_file: + type: file + description: | + Optional plain text file containing one file path or pattern per line to be + passed to Rclone copy as a filter list (e.g. via `--files-from` or + `--include-from`). This input is only used when the corresponding rclone + filtering option is enabled through the module configuration. - rclone_config: type: file description: | diff --git a/modules/nf-core/rclone/copy/tests/main.nf.test b/modules/nf-core/rclone/copy/tests/main.nf.test index b9f0a77..85d92a0 100644 --- a/modules/nf-core/rclone/copy/tests/main.nf.test +++ b/modules/nf-core/rclone/copy/tests/main.nf.test @@ -3,6 +3,7 @@ nextflow_process { name "Test RCLONE_COPY" script "../main.nf" process "RCLONE_COPY" + config "./nextflow.config" tag "modules" tag "modules_nfcore" @@ -11,15 +12,46 @@ nextflow_process { test("homo_sapiens - gvcf - copy from https - dry-run") { - config "./nextflow.config" + when { + params { + exclude_from = false + } + process { + """ + input[0] = [ + [ id:'test' ], + params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf.gz', + '/tmp/', + [] + ] + input[1] = [] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["log"])).match() } + ) + } + } + + test("homo_sapiens - gvcf - filter - dry-run") { when { + params { + exclude_from = true + } process { """ + file('exclude.txt').text = 'test.genome.vcf.gz' + input[0] = [ [ id:'test' ], params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf.gz', - '/tmp/' + '/tmp/', + file('exclude.txt') ] input[1] = [] """ @@ -39,12 +71,16 @@ nextflow_process { options "-stub" when { + params { + exclude_from = true + } process { """ input[0] = [ [ id:'test' ], params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf.gz', - '/tmp/' + '/tmp/', + [] ] input[1] = [] """ diff --git a/modules/nf-core/rclone/copy/tests/main.nf.test.snap b/modules/nf-core/rclone/copy/tests/main.nf.test.snap index eeaef63..a430eb4 100644 --- a/modules/nf-core/rclone/copy/tests/main.nf.test.snap +++ b/modules/nf-core/rclone/copy/tests/main.nf.test.snap @@ -50,5 +50,31 @@ "nf-test": "0.9.5", "nextflow": "25.10.4" } + }, + "homo_sapiens - gvcf - filter - dry-run": { + "content": [ + { + "log": [ + [ + { + "id": "test" + }, + "test-rclone-copy.log" + ] + ], + "versions_rclone": [ + [ + "RCLONE_COPY", + "rclone", + "1.65.0-DEV" + ] + ] + } + ], + "timestamp": "2026-07-28T15:53:02.864977147", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.1" + } } } \ No newline at end of file diff --git a/modules/nf-core/rclone/copy/tests/nextflow.config b/modules/nf-core/rclone/copy/tests/nextflow.config index 0e911db..dd7038e 100644 --- a/modules/nf-core/rclone/copy/tests/nextflow.config +++ b/modules/nf-core/rclone/copy/tests/nextflow.config @@ -1,7 +1,14 @@ process { withName: 'RCLONE_COPY' { ext.args = { - "--dry-run --no-check-certificate" + def base_args = [ + '--dry-run', + '--no-check-certificate' + ] + if (params.exclude_from) { + base_args.add("--exclude-from ${filter_file}") + } + base_args.join(' ') } } } From 371ae90a646b24c9d80b4ca78171907ae9f2250b Mon Sep 17 00:00:00 2001 From: Alexander Peltzer Date: Thu, 30 Jul 2026 11:54:24 +0200 Subject: [PATCH 234/334] Fix linting --- README.md | 5 ----- nextflow.config | 1 - 2 files changed, 6 deletions(-) diff --git a/README.md b/README.md index 1bb3d5a..8dfbbe6 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,11 @@ **nf-core/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline: - 1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/); 2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/); 3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and 4. produces detailed `rclone` status files and a consolidated MultiQC report. - Sources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage. The current tested use case for this pipeline is transfer between S3 buckets. @@ -49,7 +47,6 @@ Pass an `rclone` configuration with `--rclone_config` whenever a source or desti > If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required. - To explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile: ```bash @@ -58,10 +55,8 @@ nextflow run nf-core/datasync \ --outdir results ``` - The `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data. - To run the pipeline on your own data, create a samplesheet containing one transfer per row: ```csv diff --git a/nextflow.config b/nextflow.config index 1a16598..2423a8a 100644 --- a/nextflow.config +++ b/nextflow.config @@ -266,4 +266,3 @@ plugins { validation { monochromeLogs = params.monochrome_logs } - From 65b7dfe3451dcc8b1e575a444b8df71a4d012f0f Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 30 Jul 2026 15:14:00 +0200 Subject: [PATCH 235/334] Create temp file avoiding errors with write permissions in workdir --- workflows/datasync.nf | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 7f64a97..a601e0d 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -106,7 +106,10 @@ workflow DATASYNC { .collect { it.readLines() } .inject { a, b -> a.intersect(b) } - def copy_files = file("${workDir}/${meta.id}_files_to_copy.txt") + def copy_files = java.nio.file.Files.createTempFile( + "${meta.id}_files_to_copy_", + ".txt" + ) copy_files.text = common.join('\n') + '\n' tuple(meta, copy_files) From 790b8fe8be8972bc4116e38846acd336130bf9c0 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 30 Jul 2026 15:22:11 +0200 Subject: [PATCH 236/334] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 739d9d0..050aa02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#49](https://github.com/nf-core/datasync/pull/49)] - Install `RCLONE_CHECK` and `RCLONE_CHECKSUM` modules from nf-core ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). ### `Fixed` +- [[#73](https://github.com/nf-core/datasync/pull/73)] - Create tmp `files_to_copy.tx` avoiding error with write permissions in work directory ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). ### `Dependencies` From 05b139e6f70cd625fd0ca1bdf63f3244fe372780 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 30 Jul 2026 15:23:56 +0200 Subject: [PATCH 237/334] Fix linting --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 050aa02..852306a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re - [[#49](https://github.com/nf-core/datasync/pull/49)] - Install `RCLONE_CHECK` and `RCLONE_CHECKSUM` modules from nf-core ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). ### `Fixed` + - [[#73](https://github.com/nf-core/datasync/pull/73)] - Create tmp `files_to_copy.tx` avoiding error with write permissions in work directory ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). ### `Dependencies` From 4a705aa420364fc30ef043d62096b49d234f96a0 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 30 Jul 2026 20:38:47 +0200 Subject: [PATCH 238/334] Add download parameter when using shasums --- conf/modules.config | 35 +++++++++++++++++++---------------- nextflow.config | 1 + nextflow_schema.json | 6 ++++++ 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 794c4d9..701c4a7 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -18,6 +18,25 @@ process { saveAs: { filename -> filename.equals('versions.yml') ? null : filename } ] + withName: 'RCLONE_CHECKSUM' { + tag = { "${meta.id}_${hash}" } + ext.args = { + def base_args = [ + '--no-check-certificate', + "--one-way" + ] + if (params.download && meta.check_format == 'sha') { + base_args.add("--download") + } + base_args.join(' ') + } + publishDir = [ + path: { "${params.outdir}/rclone/checksum/${meta.id}" }, + mode: params.publish_dir_mode, + saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + ] + } + withName: 'RCLONE_COPY' { ext.args = { def base_args = [ @@ -58,22 +77,6 @@ process { ] } - withName: 'RCLONE_CHECKSUM' { - tag = { "${meta.id}_${hash}" } - ext.args = { - def base_args = [ - '--no-check-certificate', - "--one-way" - ] - base_args.join(' ') - } - publishDir = [ - path: { "${params.outdir}/rclone/checksum/${meta.id}" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } - ] - } - withName: 'MULTIQC' { ext.args = { def args = ['--custom-css-file */multiqc_custom.css'] diff --git a/nextflow.config b/nextflow.config index 2423a8a..75c2071 100644 --- a/nextflow.config +++ b/nextflow.config @@ -24,6 +24,7 @@ params { rclone_config = null rclone_dry_run = false copy_matching_only = false + download = false // Boilerplate options outdir = null diff --git a/nextflow_schema.json b/nextflow_schema.json index a8dc091..7e8a2a4 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -60,6 +60,12 @@ "description": "Only copy files that matched their provided input checksums.", "fa_icon": "fas fa-eye", "help_text": "If set, the pipeline will only copy files that were correctly validated and will skip any file that did not match their input checksum." + }, + "download": { + "type": "boolean", + "description": "Download remote files for sha256 checksum verification.", + "fa_icon": "fas fa-eye", + "help_text": "If set, rclone checksum will download remote files for any sample for which a shasum file was provided." } } }, From fa6dd326683af1195eea065148159738ad55f18d Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 30 Jul 2026 20:39:49 +0200 Subject: [PATCH 239/334] Add validation when using shasums --- workflows/datasync.nf | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index a601e0d..2262557 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -38,6 +38,15 @@ workflow DATASYNC { ch_samplesheet = ch_samplesheet.multiMap { meta, input_path, output_path, md5, sha -> + if (sha && input_path.contains('://')) { + if (params.download) { + log.warn("The `--download` parameter is enabled. RCLONE_CHECKSUM will download remote files. Make sure this is what you want, as it may incur substantial cloud costs !") + } else { + log.error("A SHA checksum file was provided, but `--download` is not enabled. Rclone cannot verify SHA checksums for remote files without downloading them. Enable `--download` to proceed.") + System.exit(1) + } + } + def source = file(input_path) def source_uri = source.toUriString() From 0ed68fc4bdbb726e98578fc60a4b42989799f764 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 30 Jul 2026 20:42:08 +0200 Subject: [PATCH 240/334] Checksums cannot be csvs and accept additional formats --- assets/schema_input.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/schema_input.json b/assets/schema_input.json index 5985ddb..0eff487 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -26,13 +26,13 @@ "checksum_md5": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.(csv|tsv)$", + "pattern": "^\\S+\\.(tsv|txt|md5)$", "errorMessage": "Checksum_md5 cannot contain spaces" }, "checksum_sha": { "type": "string", "format": "file-path", - "pattern": "^\\S+\\.(csv|tsv)$", + "pattern": "^\\S+\\.(tsv|txt|sha256)$", "errorMessage": "Checksum_sha cannot contain spaces" } }, From 447fc7beac921bff979b38eaf832ef2a62edf94f Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 30 Jul 2026 20:46:38 +0200 Subject: [PATCH 241/334] Update tests and snapshots --- conf/test_full.config | 3 ++- tests/edge.nf.test | 2 ++ tests/edge.nf.test.snap | 12 ++++++++++-- tests/main_full.nf.test.snap | 5 +++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/conf/test_full.config b/conf/test_full.config index af92cc7..58cf51e 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -20,6 +20,7 @@ params { input = params.pipelines_testdata_base_path + "test-data/samplesheet_full.csv" //Rclone options - rclone_config = params.pipelines_testdata_base_path + "test-data/rclone.conf" + rclone_config = params.pipelines_testdata_base_path + "test-data/rclone.conf" rclone_dry_run = true + download = true } diff --git a/tests/edge.nf.test b/tests/edge.nf.test index 5fce38e..4e626ae 100644 --- a/tests/edge.nf.test +++ b/tests/edge.nf.test @@ -12,6 +12,7 @@ nextflow_pipeline { params { input = "https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/test-data/samplesheet_edge.csv" outdir = "$outputDir" + download = true } } @@ -41,6 +42,7 @@ nextflow_pipeline { input = "https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/test-data/samplesheet_edge.csv" outdir = "$outputDir" copy_matching_only = true + download = true } } diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index ea3559b..52620b3 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -25,6 +25,7 @@ "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_rclone_check.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", + "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -51,6 +52,8 @@ "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", "rclone/checksum/Illumina_annotation_sha_only", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.exit_code.txt", "rclone/copy", "rclone/copy/Illumina_annotation_incorrect-rclone-copy.log", @@ -60,10 +63,11 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,4b2a6990836593f69e8e81a82c3daf42", "multiqc_rclone_checksum_md5.txt:md5,cf92203df21f04ddf8315fc606812e0b", + "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" ] ], - "timestamp": "2026-07-28T21:45:08.268780076", + "timestamp": "2026-07-30T20:44:41.242808343", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" @@ -95,6 +99,7 @@ "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_rclone_check.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", + "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -124,6 +129,8 @@ "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", "rclone/checksum/Illumina_annotation_sha_only", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.exit_code.txt", "rclone/copy", "rclone/copy/Illumina_annotation_incorrect-rclone-copy.log", @@ -134,10 +141,11 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,c8f13c10aa4f0e4b356c5c08a9ae7ee9", "multiqc_rclone_checksum_md5.txt:md5,cf92203df21f04ddf8315fc606812e0b", + "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" ] ], - "timestamp": "2026-07-22T22:01:06.286788462", + "timestamp": "2026-07-30T20:44:11.000298059", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 7bc1eeb..96249fd 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -25,6 +25,7 @@ "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_rclone_check.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", + "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -39,7 +40,6 @@ "rclone/checksum", "rclone/checksum/demultiplex", "rclone/checksum/demultiplex/demultiplex.combined.txt", - "rclone/checksum/demultiplex/demultiplex.exit_code.txt", "rclone/checksum/demultiplex/demultiplex.match.txt", "rclone/copy", "rclone/copy/demultiplex-rclone-copy.log" @@ -48,10 +48,11 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_rclone_checksum_md5.txt:md5,d7c7dd71a9ff75955dd0e508d1ad9968", + "multiqc_rclone_checksum_sha.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" ] ], - "timestamp": "2026-07-22T22:01:43.699965019", + "timestamp": "2026-07-30T20:46:20.306063412", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From 726112672d6466f0fe95837bb6f4d0b100edcfee Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 30 Jul 2026 21:45:08 +0200 Subject: [PATCH 242/334] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 852306a..de791fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` +- [[#74](https://github.com/nf-core/datasync/pull/74)] - Implement warning and `--download` parameter when working with remote directories and SHA checksums ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#67](https://github.com/nf-core/datasync/pull/67)] - Copy only files which are successfully validated ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#57](https://github.com/nf-core/datasync/pull/57)] - Add nf-tests with edge cases([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#55](https://github.com/nf-core/datasync/pull/55)] - Add subdirectories with sample id to results. Improvements to MultiQC report (width of columns, sections and sub-section headers)colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). From e3e47d2e753578b4e67bc45e19e6e8bf91ce8c9c Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 31 Jul 2026 18:20:34 +0200 Subject: [PATCH 243/334] Update usage documentation --- docs/usage.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 2e7c6fb..21f97e7 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -32,7 +32,7 @@ At least one checksum manifest is required on every row. If both are supplied, b For a directory input, the source root is the directory named in the samplesheet. For example, if the samplesheet `input` is `/data/run_001` and one file in that directory is `/data/run_001/reads/sample_R1.fastq.gz`, the checksum manifest path must be `reads/sample_R1.fastq.gz`. Do not write `/data/run_001/reads/sample_R1.fastq.gz` in the manifest. For a single-file input, use the input file name as the manifest path. -Checksum manifests may use a `.tsv` or `.csv` filename extension, but their contents are not tab-separated or comma-separated tables and must not include a header. Each record is plain text with the hash and path separated by exactly two spaces. The required fields are: +Checksum manifests may use a `.tsv`, `.txt`, `.md5` or `.sha256` filename extension, but their contents are not tab-separated or comma-separated tables and must not include a header. Each record is plain text with the hash and path separated by exactly **two spaces**. The required fields are: | Field | Required | Description | | ----- | -------- | ----------------------------------------------------------------------------------------------- | @@ -116,6 +116,30 @@ The corresponding input values could be `source_s3:incoming/run_001` and `instit The pipeline also accepts an `s3://bucket/path` source or destination. In that form, ensure credentials and provider settings are available to both Nextflow and `rclone` in the execution environment. A named remote such as `source_s3:bucket/path` makes the selected configuration section explicit and is preferable when a config file contains multiple S3 providers. +## SHA checksum verification for remote inputs + +When validating files stored on cloud storage providers (e.g. S3, azure, google cloud), only MD5 hashes are typically available through the storage provider. SHA checksums are not exposed by the remote API, so they cannot be verified directly. + +In order to validate SHA checksums for remote inputs, `rclone checksum` must download each file and compute its SHA checksum locally. If a `checksum_sha` file is provided for remote inputs, the `--download` parameter must be enabled. Otherwise, SHA checksum verification cannot be performed and the pipeline will terminate with an error. + +> [!NOTE] +> Providing `--download` does not force all files to be downloaded. It is only used when verifying SHA checksum files for remote source directories. + +> [!WARNING] +> Enabling `--download` may incur substantial cloud data transfer and egress costs, particularly when validating large datasets. Make sure this is the intended behaviour before running the pipeline. + +## Copying only successfully validated files + +By default, the pipeline will copy all files in the source directory, regardless of whether they were successfully validated against the provided checksum or not. + +However, it is possible to restrict copying of files to only the ones that successfully pass checksum validation by enabling the `--copy_matching_only` parameter: + +- If only an MD5 checksum file is provided, only files that successfully match their MD5 checksum will be copied. +- If only a SHA checksum file is provided, only files that successfully match their SHA checksum will be copied. +- If both MD5 and SHA checksum files are provided, the pipeline will copy only files that successfully pass **both** checksum validations. + +Files that fail checksum validation, are missing, or cannot be verified are excluded from the copy operation when this parameter is enabled. + ## Destination layout The pipeline preserves the source basename: From 97e6f57159878d1a57c6b3a6fab34d6e97a684a0 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:12:58 -0300 Subject: [PATCH 244/334] Update checksum verification documentation to SHA256 --- docs/usage.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 21f97e7..a28bb96 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -116,11 +116,11 @@ The corresponding input values could be `source_s3:incoming/run_001` and `instit The pipeline also accepts an `s3://bucket/path` source or destination. In that form, ensure credentials and provider settings are available to both Nextflow and `rclone` in the execution environment. A named remote such as `source_s3:bucket/path` makes the selected configuration section explicit and is preferable when a config file contains multiple S3 providers. -## SHA checksum verification for remote inputs +## SHA256 checksum verification for remote inputs -When validating files stored on cloud storage providers (e.g. S3, azure, google cloud), only MD5 hashes are typically available through the storage provider. SHA checksums are not exposed by the remote API, so they cannot be verified directly. +When validating files stored on cloud storage providers (e.g. S3, azure, google cloud), only MD5 hashes are typically available through the storage provider (see [Overview of cloud storage systems](https://rclone.org/overview/)). SHA256 checksums are not exposed by the remote API, so they cannot be verified directly. -In order to validate SHA checksums for remote inputs, `rclone checksum` must download each file and compute its SHA checksum locally. If a `checksum_sha` file is provided for remote inputs, the `--download` parameter must be enabled. Otherwise, SHA checksum verification cannot be performed and the pipeline will terminate with an error. +In order to validate SHA256 checksums for remote inputs, `rclone checksum` must download each file and compute its SHA256 checksum locally. If a `checksum_sha` file is provided for remote inputs, the `--download` parameter must be enabled. Otherwise, SHA checksum verification cannot be performed and the pipeline will terminate with an error. > [!NOTE] > Providing `--download` does not force all files to be downloaded. It is only used when verifying SHA checksum files for remote source directories. @@ -135,8 +135,8 @@ By default, the pipeline will copy all files in the source directory, regardless However, it is possible to restrict copying of files to only the ones that successfully pass checksum validation by enabling the `--copy_matching_only` parameter: - If only an MD5 checksum file is provided, only files that successfully match their MD5 checksum will be copied. -- If only a SHA checksum file is provided, only files that successfully match their SHA checksum will be copied. -- If both MD5 and SHA checksum files are provided, the pipeline will copy only files that successfully pass **both** checksum validations. +- If only a SHA256 checksum file is provided, only files that successfully match their SHA256 checksum will be copied. +- If both MD5 and SHA256 checksum files are provided, the pipeline will copy only files that successfully pass **both** checksum validations. Files that fail checksum validation, are missing, or cannot be verified are excluded from the copy operation when this parameter is enabled. From 3621357c836dbefa32370bccba75ad5b0e776965 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 31 Jul 2026 15:26:33 -0300 Subject: [PATCH 245/334] Update docs/usage.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index a28bb96..418adef 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -123,7 +123,7 @@ When validating files stored on cloud storage providers (e.g. S3, azure, google In order to validate SHA256 checksums for remote inputs, `rclone checksum` must download each file and compute its SHA256 checksum locally. If a `checksum_sha` file is provided for remote inputs, the `--download` parameter must be enabled. Otherwise, SHA checksum verification cannot be performed and the pipeline will terminate with an error. > [!NOTE] -> Providing `--download` does not force all files to be downloaded. It is only used when verifying SHA checksum files for remote source directories. +> Providing `--download` does not force all files to be downloaded in all modules. It is only used when verifying SHA256 checksum files for remote source directories in `RCLONE_CHECKSUM`. > [!WARNING] > Enabling `--download` may incur substantial cloud data transfer and egress costs, particularly when validating large datasets. Make sure this is the intended behaviour before running the pipeline. From b91df99e5f7b7ccbeda32bc52920a1f30e8040d4 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 31 Jul 2026 15:27:00 -0300 Subject: [PATCH 246/334] Update workflows/datasync.nf Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- workflows/datasync.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 2262557..201706c 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -40,7 +40,7 @@ workflow DATASYNC { if (sha && input_path.contains('://')) { if (params.download) { - log.warn("The `--download` parameter is enabled. RCLONE_CHECKSUM will download remote files. Make sure this is what you want, as it may incur substantial cloud costs !") + log.warn("The `--download` parameter is enabled. `RCLONE_CHECKSUM` will download remote files. Make sure this is what you want, as it may incur substantial cloud costs !") } else { log.error("A SHA checksum file was provided, but `--download` is not enabled. Rclone cannot verify SHA checksums for remote files without downloading them. Enable `--download` to proceed.") System.exit(1) From 0bb34e3b66d3fc67a49a026ba24a43bc17053353 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 31 Jul 2026 15:27:11 -0300 Subject: [PATCH 247/334] Update CHANGELOG.md Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a581188..d7938a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` -- [[#74](https://github.com/nf-core/datasync/pull/74)] - Implement warning and `--download` parameter when working with remote directories and SHA checksums ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). +- [[#74](https://github.com/nf-core/datasync/pull/74)] - Implement warning and `--download` parameter when working with remote directories and SHA checksums ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila), [@apeltzer](https://github.com/apeltzer) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#67](https://github.com/nf-core/datasync/pull/67)] - Copy only files which are successfully validated ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#57](https://github.com/nf-core/datasync/pull/57)] - Add nf-tests with edge cases([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). - [[#55](https://github.com/nf-core/datasync/pull/55)] - Add subdirectories with sample id to results. Improvements to MultiQC report (width of columns, sections and sub-section headers)colors to multiqc results and display first errors in tables ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). From fff74fc2b222e7fcb4338f9e40856337d600a2d0 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 31 Jul 2026 15:27:27 -0300 Subject: [PATCH 248/334] Update workflows/datasync.nf Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- workflows/datasync.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 201706c..966fc23 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -42,7 +42,7 @@ workflow DATASYNC { if (params.download) { log.warn("The `--download` parameter is enabled. `RCLONE_CHECKSUM` will download remote files. Make sure this is what you want, as it may incur substantial cloud costs !") } else { - log.error("A SHA checksum file was provided, but `--download` is not enabled. Rclone cannot verify SHA checksums for remote files without downloading them. Enable `--download` to proceed.") + log.error("A SHA checksum file was provided, but `--download` is not enabled. `RCLONE_CHECKSUM` cannot verify SHA256 checksums for remote files without downloading them. Enable `--download` to proceed.") System.exit(1) } } From a7c7f0887a87db105245540c3e8a9327e979610e Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 31 Jul 2026 15:27:39 -0300 Subject: [PATCH 249/334] Update nextflow_schema.json Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- nextflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 7e8a2a4..807710c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -63,7 +63,7 @@ }, "download": { "type": "boolean", - "description": "Download remote files for sha256 checksum verification.", + "description": "Download remote files for sha256 checksum verification in `RCLONE_CHECKSUM`.", "fa_icon": "fas fa-eye", "help_text": "If set, rclone checksum will download remote files for any sample for which a shasum file was provided." } From d5b06b4739a4ec621be5d0b9f8dc206e1f08a3f7 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 31 Jul 2026 15:52:57 -0300 Subject: [PATCH 250/334] Update nextflow_schema.json Co-authored-by: Anabella Trigila <18577080+atrigila@users.noreply.github.com> --- nextflow_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nextflow_schema.json b/nextflow_schema.json index 807710c..738538e 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -65,7 +65,7 @@ "type": "boolean", "description": "Download remote files for sha256 checksum verification in `RCLONE_CHECKSUM`.", "fa_icon": "fas fa-eye", - "help_text": "If set, rclone checksum will download remote files for any sample for which a shasum file was provided." + "help_text": "If set, `RCLONE_CHECKSUM` will download remote files for any sample for which a SHA256 file was provided." } } }, From 8cbd838c0db14524a1473c91957bb67b9769729a Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 31 Jul 2026 20:25:13 +0200 Subject: [PATCH 251/334] Add failing test scenario --- tests/edge.nf.test | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/edge.nf.test b/tests/edge.nf.test index 4e626ae..b30aa79 100644 --- a/tests/edge.nf.test +++ b/tests/edge.nf.test @@ -64,4 +64,22 @@ nextflow_pipeline { ) } } + + test("-profile test remote source with SHA256 checksums - fail") { + + when { + params { + input = "https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/datasync/test-data/samplesheet_edge.csv" + outdir = "$outputDir" + } + } + + then { + // stable_path: All files + folders in ${params.outdir}/ with a stable path (including file name) + def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_content: All files in ${params.outdir}/ with stable content + def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + assert workflow.failed + } + } } From c80269523f3d6f865adfbe5936fbbcdc78dfe45a Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Fri, 31 Jul 2026 16:26:33 -0300 Subject: [PATCH 252/334] Clean up edge.nf.test by removing unused variables --- tests/edge.nf.test | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/edge.nf.test b/tests/edge.nf.test index b30aa79..f5c5188 100644 --- a/tests/edge.nf.test +++ b/tests/edge.nf.test @@ -75,10 +75,6 @@ nextflow_pipeline { } then { - // stable_path: All files + folders in ${params.outdir}/ with a stable path (including file name) - def stable_path = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) - // stable_content: All files in ${params.outdir}/ with stable content - def stable_content = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') assert workflow.failed } } From c6ea9c6d3aa057d6092436ad150ea436ca5f3181 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Mon, 3 Aug 2026 18:13:24 +0000 Subject: [PATCH 253/334] fix linting --- ro-crate-metadata.json | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 29e366a..cddeead 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "InProgress", "datePublished": "2026-07-24T12:35:36+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\n\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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> [!WARNING]\n> nf-core/datasync is under active development and is not yet recommended for production data transfers. Validate its behaviour with representative data before relying on it.\n\n**nf-core/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -121,7 +121,11 @@ }, { "@id": "main.nf", - "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "@type": [ + "File", + "SoftwareSourceCode", + "ComputationalWorkflow" + ], "contributor": [ { "@id": "https://orcid.org/0000-0002-6503-2180" @@ -130,17 +134,29 @@ "dateCreated": "", "dateModified": "2026-07-24T12:35:36Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", - "keywords": ["nf-core", "nextflow"], - "license": ["MIT"], - "name": ["nf-core/datasync"], + "keywords": [ + "nf-core", + "nextflow" + ], + "license": [ + "MIT" + ], + "name": [ + "nf-core/datasync" + ], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" }, "sdPublisher": { "@id": "https://nf-co.re/" }, - "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/dev/"], - "version": ["1.0dev"] + "url": [ + "https://github.com/nf-core/datasync", + "https://nf-co.re/datasync/dev/" + ], + "version": [ + "1.0dev" + ] }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", @@ -303,4 +319,4 @@ "name": "Alexander Peltzer" } ] -} +} \ No newline at end of file From 39eb94352b3961a4383135142f31f1848826ab8a Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Mon, 3 Aug 2026 18:14:14 +0000 Subject: [PATCH 254/334] fix container config linting --- conf/containers_conda_lock_files_amd64.config | 8 ++++---- conf/containers_conda_lock_files_arm64.config | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index fbe762b..584667d 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1,4 +1,4 @@ -process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } -process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } -process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } +process { withName: 'MULTIQC' { conda = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } +process { withName: 'RCLONE_CHECK' { conda = 'modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { conda = 'modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } +process { withName: 'RCLONE_COPY' { conda = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index b425a8d..028f0ed 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1,4 +1,4 @@ -process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } -process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } -process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } +process { withName: 'MULTIQC' { conda = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } +process { withName: 'RCLONE_CHECK' { conda = 'modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { conda = 'modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } +process { withName: 'RCLONE_COPY' { conda = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } From 6949fb1873e7d1ad1d76c1aac362a3c6f6b8575f Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Mon, 3 Aug 2026 18:30:38 +0000 Subject: [PATCH 255/334] Revert linting fixes and container issues --- conf/containers_conda_lock_files_amd64.config | 8 ++--- conf/containers_conda_lock_files_arm64.config | 8 ++--- ro-crate-metadata.json | 32 +++++-------------- 3 files changed, 16 insertions(+), 32 deletions(-) diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index 584667d..fbe762b 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1,4 +1,4 @@ -process { withName: 'MULTIQC' { conda = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } -process { withName: 'RCLONE_CHECK' { conda = 'modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } -process { withName: 'RCLONE_CHECKSUM' { conda = 'modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } -process { withName: 'RCLONE_COPY' { conda = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } +process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } +process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } +process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index 028f0ed..b425a8d 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1,4 +1,4 @@ -process { withName: 'MULTIQC' { conda = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } -process { withName: 'RCLONE_CHECK' { conda = 'modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } -process { withName: 'RCLONE_CHECKSUM' { conda = 'modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } -process { withName: 'RCLONE_COPY' { conda = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } +process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } +process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } +process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index cddeead..29e366a 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "InProgress", "datePublished": "2026-07-24T12:35:36+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\n\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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> [!WARNING]\n> nf-core/datasync is under active development and is not yet recommended for production data transfers. Validate its behaviour with representative data before relying on it.\n\n**nf-core/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -121,11 +121,7 @@ }, { "@id": "main.nf", - "@type": [ - "File", - "SoftwareSourceCode", - "ComputationalWorkflow" - ], + "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], "contributor": [ { "@id": "https://orcid.org/0000-0002-6503-2180" @@ -134,29 +130,17 @@ "dateCreated": "", "dateModified": "2026-07-24T12:35:36Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", - "keywords": [ - "nf-core", - "nextflow" - ], - "license": [ - "MIT" - ], - "name": [ - "nf-core/datasync" - ], + "keywords": ["nf-core", "nextflow"], + "license": ["MIT"], + "name": ["nf-core/datasync"], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" }, "sdPublisher": { "@id": "https://nf-co.re/" }, - "url": [ - "https://github.com/nf-core/datasync", - "https://nf-co.re/datasync/dev/" - ], - "version": [ - "1.0dev" - ] + "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/dev/"], + "version": ["1.0dev"] }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", @@ -319,4 +303,4 @@ "name": "Alexander Peltzer" } ] -} \ No newline at end of file +} From 080bef869ea6634dc0617f5762f18be2e2079fe1 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Mon, 3 Aug 2026 18:32:04 +0000 Subject: [PATCH 256/334] fix pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 87aab4d..d43c74d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). From 66f5df3386c466f2ea889ec4b9974d597531d44b Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:28:55 -0300 Subject: [PATCH 257/334] remove todos --- .github/workflows/awsfulltest.yml | 1 - assets/methods_description_template.yml | 1 - conf/base.config | 2 - conf/test.config | 2 - conf/test_full.config | 2 - docs/CONTRIBUTING.md | 2 +- nextflow.config | 49 ++++++++++++++++--- .../utils_nfcore_datasync_pipeline/main.nf | 10 +--- tests/nextflow.config | 1 - 9 files changed, 45 insertions(+), 25 deletions(-) diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index b498008..4190c08 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -24,7 +24,6 @@ jobs: - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@51565b514bff1827cf34620de25d0055759f1fc9 # v2 - # TODO nf-core: You can customise AWS full pipeline tests as required # Add full size test data (but still relatively small datasets for few samples) # on the `test_full.config` test runs with only one set of parameters with: diff --git a/assets/methods_description_template.yml b/assets/methods_description_template.yml index b03e887..b42f558 100644 --- a/assets/methods_description_template.yml +++ b/assets/methods_description_template.yml @@ -3,7 +3,6 @@ description: "Suggested text and references to use when describing pipeline usag section_name: "nf-core/datasync Methods Description" section_href: "https://github.com/nf-core/datasync" plot_type: "html" -## TODO nf-core: Update the HTML below to your preferred methods description, e.g. add publication citation for this pipeline ## You inject any metadata in the Nextflow '${workflow}' object data: |

    Methods

    diff --git a/conf/base.config b/conf/base.config index 84af848..7355150 100644 --- a/conf/base.config +++ b/conf/base.config @@ -10,7 +10,6 @@ process { - // TODO nf-core: Check the defaults for all processes cpus = { 1 * task.attempt } memory = { 6.GB * task.attempt } time = { 4.h * task.attempt } @@ -24,7 +23,6 @@ process { // These labels are used and recognised by default in DSL2 files hosted on nf-core/modules. // If possible, it would be nice to keep the same label naming convention when // adding in your local modules too. - // TODO nf-core: Customise requirements for specific processes. // See https://www.nextflow.io/docs/latest/config.html#config-process-selectors withLabel:process_single { cpus = { 1 } diff --git a/conf/test.config b/conf/test.config index e82bcec..f152167 100644 --- a/conf/test.config +++ b/conf/test.config @@ -23,8 +23,6 @@ params { config_profile_description = 'Minimal test dataset to check pipeline function' // Input data - // TODO nf-core: Specify the paths to your test data on nf-core/test-datasets - // TODO nf-core: Give any required params for the test so that command line flags are not needed input = params.pipelines_testdata_base_path + "test-data/samplesheet.csv" rclone_config = params.pipelines_testdata_base_path + "test-data/rclone.conf" rclone_dry_run = true diff --git a/conf/test_full.config b/conf/test_full.config index 58cf51e..d081678 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -15,8 +15,6 @@ params { config_profile_description = 'Full test dataset to check pipeline function' // Input data for full size test - // TODO nf-core: Specify the paths to your full test data ( on nf-core/test-datasets or directly in repositories, e.g. SRA) - // TODO nf-core: Give any required params for the test so that command line flags are not needed input = params.pipelines_testdata_base_path + "test-data/samplesheet_full.csv" //Rclone options diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 3e8477b..4113b53 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -182,4 +182,4 @@ If you update images or graphics, follow the nf-core [style guidelines](https:// ## Pipeline specific contribution guidelines - +Pipeline-specific changes should include focused updates to the pipeline code, schema, documentation, and nf-test coverage where behaviour changes. diff --git a/nextflow.config b/nextflow.config index 75c2071..e113e2e 100644 --- a/nextflow.config +++ b/nextflow.config @@ -9,7 +9,6 @@ // Global default params, used in configs params { - // TODO nf-core: Specify your pipeline's command line flags // Input options input = null @@ -101,7 +100,7 @@ profiles { } arm64 { process.arch = 'arm64' - // TODO https://github.com/nf-core/modules/issues/6694 + // See https://github.com/nf-core/modules/issues/6694 // For now if you're using arm64 you have to use wave for the sake of the maintainers // wave profile apptainer.ociAutoPull = true @@ -183,8 +182,7 @@ profiles { includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !params.custom_config_base.startsWith('http')) ? "${params.custom_config_base}/nfcore_custom.config" : "/dev/null" -// Load nf-core/datasync custom profiles from different institutions. -// TODO nf-core: Optionally, you can add a pipeline-specific nf-core config at https://github.com/nf-core/configs +// Load nf-core/datasync custom profiles from nf-core/configs when available. // includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !params.custom_config_base.startsWith('http')) ? "${params.custom_config_base}/pipeline/datasync.config" : "/dev/null" // Set default registry for Apptainer, Docker, Podman, Charliecloud and Singularity independent of -profile @@ -240,13 +238,52 @@ dag { manifest { name = 'nf-core/datasync' contributors = [ - // TODO nf-core: Update the field with the details of the contributors to your pipeline. New with Nextflow version 24.10.0 [ name: 'Alexander Peltzer', affiliation: '', email: '', github: '', - contribution: [], // List of contribution types ('author', 'maintainer' or 'contributor') + contribution: ['author'], + orcid: '' + ], + [ + name: 'Antonia Saracco', + affiliation: '', + email: '', + github: '', + contribution: ['contributor'], + orcid: '' + ], + [ + name: 'Delfina Terradas', + affiliation: '', + email: '', + github: '', + contribution: ['contributor'], + orcid: '' + ], + [ + name: 'Anabella Trigila', + affiliation: '', + email: '', + github: '', + contribution: ['contributor'], + orcid: '' + ], + [ + name: 'Julian Schwab', + affiliation: '', + email: '', + github: '', + contribution: ['author'], + orcid: '' + ], + [ + name: 'Gregor Sturm', + affiliation: '', + email: '', + github: '', + contribution: ['author'], orcid: '' ], ] diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 57723c5..a4d2d48 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -11,7 +11,6 @@ include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' include { paramsSummaryMap } from 'plugin/nf-schema' include { samplesheetToList } from 'plugin/nf-schema' -include { paramsHelp } from 'plugin/nf-schema' include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' @@ -192,7 +191,7 @@ def parseRcloneCheck(meta, check_file) { ] return check_file.readLines() - .findAll { it.trim() } + .findAll { line -> line.trim() } .collect { line -> def fields = line.split(/ /, 2) def status = status_map.get(fields[0], fields[0]) @@ -206,9 +205,6 @@ def parseRcloneCheck(meta, check_file) { // Generate methods description for MultiQC // def toolCitationText() { - // TODO nf-core: Optionally add in-text citation tools to this list. - // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "Tool (Foo et al. 2023)" : "", - // Uncomment function in methodsDescriptionText to render in MultiQC report def citation_text = [ "Tools used in the workflow included:", "Files were transferred to the specified destination using Rclone (Craig-Wood, 2023), which supports data movement across local and cloud storage backends.", @@ -221,9 +217,6 @@ def toolCitationText() { } def toolBibliographyText() { - // TODO nf-core: Optionally add bibliographic entries to this list. - // Can use ternary operators to dynamically construct based conditions, e.g. params["run_xyz"] ? "
  • Author (2023) Pub name, Journal, DOI
  • " : "", - // Uncomment function in methodsDescriptionText to render in MultiQC report def reference_text = [ "
  • Craig-Wood, N. (2023). Rclone: Rsync for cloud storage (Vers. 1.65.0). Computer software. https://rclone.org
  • ", "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics, 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " @@ -256,7 +249,6 @@ def methodsDescriptionText(mqc_methods_yaml) { meta["tool_citations"] = "" meta["tool_bibliography"] = "" - // TODO nf-core: Only uncomment below if logic in toolCitationText/toolBibliographyText has been filled! meta["tool_citations"] = toolCitationText().replaceAll(", \\.", ".").replaceAll("\\. \\.", ".").replaceAll(", \\.", ".") meta["tool_bibliography"] = toolBibliographyText() diff --git a/tests/nextflow.config b/tests/nextflow.config index da48321..20c7ba5 100644 --- a/tests/nextflow.config +++ b/tests/nextflow.config @@ -4,7 +4,6 @@ ======================================================================================== */ -// TODO nf-core: Specify any additional parameters here // Or any resources requirements params { modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' From 292d6737457a5fdfc87ff4f3babaf06f01353063 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:31:30 -0300 Subject: [PATCH 258/334] add missing subworkflow meta.yml --- .../utils_nfcore_datasync_pipeline/meta.yml | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 subworkflows/local/utils_nfcore_datasync_pipeline/meta.yml diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/meta.yml b/subworkflows/local/utils_nfcore_datasync_pipeline/meta.yml new file mode 100644 index 0000000..ae7144f --- /dev/null +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/meta.yml @@ -0,0 +1,69 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "PIPELINE_INITIALISATION" +description: Local utility subworkflow and functions for nf-core/datasync initialisation, completion, rclone report parsing, and MultiQC methods text. +keywords: + - utility + - datasync + - rclone + - multiqc +components: + - utils_nfschema_plugin + - completionemail + - completionsummary + - utils_nfcore_pipeline + - utils_nextflow_pipeline +input: + - version: + type: boolean + description: Display version and exit. + - validate_params: + type: boolean + description: Validate parameters against the schema at runtime. + - monochrome_logs: + type: boolean + description: Disable coloured log output. + - nextflow_cli_args: + type: list + description: Nextflow CLI positional arguments. + - outdir: + type: string + description: Output directory where results are saved. + - input: + type: string + description: Path to the input samplesheet. + - help: + type: boolean + description: Display help message and exit. + - help_full: + type: boolean + description: Display full help message. + - show_hidden: + type: boolean + description: Show hidden parameters in the help message. + - email: + type: string + description: Completion email address. + - email_on_fail: + type: string + description: Failure email address. + - plaintext_email: + type: boolean + description: Send plain-text email instead of HTML. + - multiqc_report: + type: file + description: MultiQC report emitted by the pipeline. +output: + - samplesheet: + type: file + description: Parsed samplesheet channel. + - versions: + type: file + description: Software versions channel. +authors: + - "@asaracco" + - "@delfiterradas" + - "@atrigila" +maintainers: + - "@asaracco" + - "@delfiterradas" + - "@atrigila" From fd4e5a2faf98b05dbc65b0effba5717f47dd37fc Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:32:00 -0300 Subject: [PATCH 259/334] fix nextflow lint issues --- workflows/datasync.nf | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 966fc23..cf68fe7 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -42,8 +42,7 @@ workflow DATASYNC { if (params.download) { log.warn("The `--download` parameter is enabled. `RCLONE_CHECKSUM` will download remote files. Make sure this is what you want, as it may incur substantial cloud costs !") } else { - log.error("A SHA checksum file was provided, but `--download` is not enabled. `RCLONE_CHECKSUM` cannot verify SHA256 checksums for remote files without downloading them. Enable `--download` to proceed.") - System.exit(1) + throw new IllegalArgumentException("A SHA checksum file was provided, but `--download` is not enabled. `RCLONE_CHECKSUM` cannot verify SHA256 checksums for remote files without downloading them. Enable `--download` to proceed.") } } @@ -100,7 +99,7 @@ workflow DATASYNC { if(params.copy_matching_only) { // Compute expected group size per meta.id from the input ch_with_size = ch_checksum - .map { meta, checksum, hash, source -> [ meta.subMap(meta.keySet() - 'check_format'), 1 ] } + .map { meta, _checksum, _hash, _source -> [ meta.subMap(meta.keySet() - 'check_format'), 1 ] } .groupTuple() .map { meta, ones -> tuple(meta, ones.size()) } @@ -112,7 +111,7 @@ workflow DATASYNC { .groupTuple() .map{ meta, files -> def common = files - .collect { it.readLines() } + .collect { file_to_copy -> file_to_copy.readLines() } .inject { a, b -> a.intersect(b) } def copy_files = java.nio.file.Files.createTempFile( @@ -138,7 +137,7 @@ workflow DATASYNC { // Wait for file copy to finish before running RCLONE_CHECK ch_rclone_check = ch_samplesheet.rclone .join(RCLONE_COPY.out.log) - .map { meta, input, output, log -> [ meta, input, output ] } + .map { meta, input, output, _log -> [ meta, input, output ] } // // File transfer validation @@ -192,7 +191,7 @@ workflow DATASYNC { // // MODULE: MultiQC // - ch_multiqc_files = ch_multiqc_files.mix(Channel.fromPath(params.input).collectFile(name: 'samplesheet.csv')) + ch_multiqc_files = ch_multiqc_files.mix(channel.fromPath(params.input).collectFile(name: 'samplesheet.csv')) ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) def ch_summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") def ch_workflow_summary = channel.value(paramsSummaryMultiqc(ch_summary_params)) From ff429db5a61c3f87c2b8c121db1a033e12e5cd4a Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:32:31 -0300 Subject: [PATCH 260/334] fix linting warnings --- .nf-core.yml | 2 +- conf/igenomes.config | 0 conf/igenomes_ignored.config | 0 ro-crate-metadata.json | 32 ++++++++++++++++++++++++-------- 4 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 conf/igenomes.config create mode 100644 conf/igenomes_ignored.config diff --git a/.nf-core.yml b/.nf-core.yml index f3c151a..da73ac4 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 4.0.3 +nf_core_version: 4.1.0 repository_type: pipeline template: author: Alexander Peltzer diff --git a/conf/igenomes.config b/conf/igenomes.config new file mode 100644 index 0000000..e69de29 diff --git a/conf/igenomes_ignored.config b/conf/igenomes_ignored.config new file mode 100644 index 0000000..e69de29 diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 29e366a..cddeead 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "InProgress", "datePublished": "2026-07-24T12:35:36+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-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-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\n\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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> [!WARNING]\n> nf-core/datasync is under active development and is not yet recommended for production data transfers. Validate its behaviour with representative data before relying on it.\n\n**nf-core/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -121,7 +121,11 @@ }, { "@id": "main.nf", - "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "@type": [ + "File", + "SoftwareSourceCode", + "ComputationalWorkflow" + ], "contributor": [ { "@id": "https://orcid.org/0000-0002-6503-2180" @@ -130,17 +134,29 @@ "dateCreated": "", "dateModified": "2026-07-24T12:35:36Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", - "keywords": ["nf-core", "nextflow"], - "license": ["MIT"], - "name": ["nf-core/datasync"], + "keywords": [ + "nf-core", + "nextflow" + ], + "license": [ + "MIT" + ], + "name": [ + "nf-core/datasync" + ], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" }, "sdPublisher": { "@id": "https://nf-co.re/" }, - "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/dev/"], - "version": ["1.0dev"] + "url": [ + "https://github.com/nf-core/datasync", + "https://nf-co.re/datasync/dev/" + ], + "version": [ + "1.0dev" + ] }, { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", @@ -303,4 +319,4 @@ "name": "Alexander Peltzer" } ] -} +} \ No newline at end of file From 4cb4feb6c498188b55629e10ae21d510633ee253 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:42:52 -0300 Subject: [PATCH 261/334] remove todos --- README.md | 11 +++++------ ro-crate-metadata.json | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8dfbbe6..24a0feb 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,6 @@ ## Introduction -> [!WARNING] -> nf-core/datasync is under active development and is not yet recommended for production data transfers. Validate its behaviour with representative data before relying on it. - **nf-core/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline: 1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/); @@ -90,7 +87,11 @@ nf-core/datasync was originally written by Alexander Peltzer. We thank the following people for their extensive assistance in the development of this pipeline: - +Julian Schwab +Gregor Sturm +Antonia Saracco +Delfina Terradas +Anabella Trigila ## Contributions and Support @@ -103,8 +104,6 @@ For further information or help, don't hesitate to get in touch on the [Slack `# - - An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. You can cite the `nf-core` publication as follows: diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index cddeead..25eac8e 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "InProgress", "datePublished": "2026-07-24T12:35:36+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\n\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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> [!WARNING]\n> nf-core/datasync is under active development and is not yet recommended for production data transfers. Validate its behaviour with representative data before relying on it.\n\n**nf-core/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\n\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\nJulian Schwab\nGregor Sturm\nAntonia Saracco\nDelfina Terradas\nAnabella Trigila\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", "hasPart": [ { "@id": "main.nf" From b2b267bf2d8dad405db0ea662e015178993a8202 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:47:26 -0300 Subject: [PATCH 262/334] update subworkflows to latest versions --- modules.json | 4 ++-- .../nf-core/utils_nextflow_pipeline/main.nf | 20 ++++++++++++---- .../nf-core/utils_nfschema_plugin/main.nf | 12 ++++++---- .../nf-core/utils_nfschema_plugin/meta.yml | 24 +++++++++++++++++++ .../utils_nfschema_plugin/tests/main.nf.test | 5 ++++ .../tests/nextflow.config | 2 +- 6 files changed, 56 insertions(+), 11 deletions(-) diff --git a/modules.json b/modules.json index df30276..8d99a6d 100644 --- a/modules.json +++ b/modules.json @@ -31,7 +31,7 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "05954dab2ff481bcb999f24455da29a5828af08d", + "git_sha": "1a545fcbd762911c21a64ced3dbef99b2b51ac75", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { @@ -41,7 +41,7 @@ }, "utils_nfschema_plugin": { "branch": "master", - "git_sha": "fdc08b8b1ae74f56686ce21f7ea11ad11990ce57", + "git_sha": "a7b27fd25bfa8dcc07d299e88bd790585901a436", "installed_by": ["subworkflows"] } } diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf index d6e593e..37939ac 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf @@ -73,11 +73,23 @@ def getWorkflowVersion() { def dumpParametersToJSON(outdir) { def timestamp = new java.util.Date().format('yyyy-MM-dd_HH-mm-ss') def filename = "params_${timestamp}.json" - def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") - def jsonStr = groovy.json.JsonOutput.toJson(params) + def temp_pf = workflow.launchDir.resolve(".${filename}") + def jsonGenerator = new groovy.json.JsonGenerator.Options() + .excludeNulls() + .addConverter(Path) { Path path -> path.toUriString() } + .addConverter(Duration) { Duration duration -> duration.toMillis() } + .addConverter(MemoryUnit) { MemoryUnit memory -> memory.toBytes() } + .addConverter(nextflow.script.types.VersionNumber) { nextflow.script.types.VersionNumber version -> version.toString() } + .build() + def jsonStr = jsonGenerator.toJson(params) temp_pf.text = groovy.json.JsonOutput.prettyPrint(jsonStr) - - nextflow.extension.FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") + if (outdir instanceof Path) { + temp_pf.copyTo(outdir.resolve("pipeline_info/${filename}")) + } else if (outdir instanceof String) { + temp_pf.copyTo("${outdir}/pipeline_info/params_${timestamp}.json") + } else { + log.warn("Could not determine type of outdir, parameters JSON file will not be copied to output directory!") + } temp_pf.delete() } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/main.nf b/subworkflows/nf-core/utils_nfschema_plugin/main.nf index 1df8b76..9ff0681 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/main.nf +++ b/subworkflows/nf-core/utils_nfschema_plugin/main.nf @@ -22,6 +22,7 @@ workflow UTILS_NFSCHEMA_PLUGIN { before_text // string: text to show before the help message and parameters summary after_text // string: text to show after the help message and parameters summary command // string: an example command of the pipeline + cli_typecast // boolean: whether to perform typecasting of CLI parameters. Set this to `null` to use the default behaviour main: @@ -34,11 +35,11 @@ workflow UTILS_NFSCHEMA_PLUGIN { fullHelp: help_full, ] if(parameters_schema) { - help_options << [parametersSchema: parameters_schema] + help_options << [parameters_schema: parameters_schema] } log.info paramsHelp( help_options, - (params.help instanceof String && params.help != "true") ? params.help : "", + (help instanceof String && help != "true") ? help : "", ) exit 0 } @@ -50,7 +51,7 @@ workflow UTILS_NFSCHEMA_PLUGIN { summary_options = [:] if(parameters_schema) { - summary_options << [parametersSchema: parameters_schema] + summary_options << [parameters_schema: parameters_schema] } log.info before_text log.info paramsSummaryLog(summary_options, input_workflow) @@ -63,7 +64,10 @@ workflow UTILS_NFSCHEMA_PLUGIN { if(validate_params) { validateOptions = [:] if(parameters_schema) { - validateOptions << [parametersSchema: parameters_schema] + validateOptions << [parameters_schema: parameters_schema] + } + if(cli_typecast != null) { + validateOptions << [cast_cli_params: cli_typecast] } validateParameters(validateOptions) } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/meta.yml b/subworkflows/nf-core/utils_nfschema_plugin/meta.yml index f7d9f02..1d8c75a 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/meta.yml +++ b/subworkflows/nf-core/utils_nfschema_plugin/meta.yml @@ -25,6 +25,30 @@ input: option. When this input is empty it will automatically use the configured schema or "${projectDir}/nextflow_schema.json" as default. The schema should not be given in this way for meta pipelines. + - help: + type: boolean, string + description: | + Show the help message and exit. When a parameter name is given, show the help message for that parameter instead of the general help message. + - help_full: + type: boolean + description: Show the full help message and exit. + - show_hidden: + type: boolean + description: Show hidden parameters in the help message. + - before_text: + type: string + description: Text to show before the parameters summary and help message. + - after_text: + type: string + description: Text to show after the parameters summary and help message. + - command: + type: string + description: An example command to run the pipeline, to show in the help message and the summary. + - cli_typecast: + type: boolean + description: | + Whether to apply typecasting to the parameters given via the CLI before validation. + Set this to `null` to use the default behavior. output: - dummy_emit: type: boolean diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test index c977917..1fd1eac 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test @@ -31,6 +31,7 @@ nextflow_workflow { input[6] = "" input[7] = "" input[8] = "" + input[9] = null """ } } @@ -63,6 +64,7 @@ nextflow_workflow { input[6] = "" input[7] = "" input[8] = "" + input[9] = null """ } } @@ -95,6 +97,7 @@ nextflow_workflow { input[6] = "" input[7] = "" input[8] = "" + input[9] = null """ } } @@ -127,6 +130,7 @@ nextflow_workflow { input[6] = "" input[7] = "" input[8] = "" + input[9] = null """ } } @@ -160,6 +164,7 @@ nextflow_workflow { input[6] = "Before" input[7] = "After" input[8] = "nextflow run test/test" + input[9] = null """ } } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config index f6537cc..fd71cb8 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.6.1" + id "nf-schema@2.7.2" } validation { From 91d22646ec44de3e6db718491d5e0d4c0a2d82a3 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:48:23 -0300 Subject: [PATCH 263/334] fix rocrate --- ro-crate-metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 25eac8e..cf4913a 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "InProgress", "datePublished": "2026-07-24T12:35:36+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\n\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\nJulian Schwab\nGregor Sturm\nAntonia Saracco\nDelfina Terradas\nAnabella Trigila\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\n\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\nJulian Schwab\nGregor Sturm\nAntonia Saracco\nDelfina Terradas\nAnabella Trigila\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\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", "hasPart": [ { "@id": "main.nf" From f03a0100641d0404c88818f3e2b633135c0f2850 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:52:31 -0300 Subject: [PATCH 264/334] fix nextflow lint --- subworkflows/local/utils_nfcore_datasync_pipeline/main.nf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index a4d2d48..f135898 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -87,7 +87,8 @@ workflow PIPELINE_INITIALISATION { show_hidden, before_text, after_text, - command + command, + null ) // From 3110f6a7a5601186bfccd554302e35647ee82138 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:54:03 -0300 Subject: [PATCH 265/334] delete unused modules --- modules/local/sync/sync.nf | 40 - .../linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt | 822 ------------------ .../linux_arm64-bd-e455e32f745abe68_1.txt | 769 ---------------- 3 files changed, 1631 deletions(-) delete mode 100644 modules/local/sync/sync.nf delete mode 100644 modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt delete mode 100644 modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt diff --git a/modules/local/sync/sync.nf b/modules/local/sync/sync.nf deleted file mode 100644 index dd8d0b2..0000000 --- a/modules/local/sync/sync.nf +++ /dev/null @@ -1,40 +0,0 @@ -process SYNC { - label 'process_single' - - conda "conda-forge::python=3.8.3" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/python:3.8.3' : - 'biocontainers/python:3.8.3'}" - - input: - tuple val(run_id), path(origin), path(sync) // [run_id, rundir, origin] - - output: //We do not really have outputs, this happens in the directories already as they are just "mounted" and copied over from - tuple val(run_id), path("${run_id}_sha256_checksums.txt") , emit: synced - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: // This script is bundled with the pipeline, in pipelines/archivetmcp/bin/ - """ - //Run checksums first - for file in $(find ${origin} -type f) - do - sha256sum file >> ${run_id}_sha256_checksums.txt - touch ${origin}/CHECKSUM_DONE ##Needs to be parameterized , currently always creates this - done - fi - - //Run actual sync step - rsync -crptgo ${origin} ${sync} - - //Touch SYNC DONE - touch ${origin}/SYNC_DONE - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - python: \$(python --version | sed 's/Python //g') - END_VERSIONS - """ -} diff --git a/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt deleted file mode 100644 index 7770ccd..0000000 --- a/modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt +++ /dev/null @@ -1,822 +0,0 @@ - -version: 6 -environments: -default: -channels: -- url: https://conda.anaconda.org/conda-forge/ -- url: https://conda.anaconda.org/bioconda/ -- url: https://conda.anaconda.org/bioconda/ -options: -pypi-prerelease-mode: if-necessary-or-explicit -packages: -linux-64: -- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda -- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda -packages: -- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda -build_number: 20 -sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 -md5: a9f577daf3de00bca7c3c76c0ecbd1de -depends: -- __glibc >=2.17,<3.0.a0 -- libgomp >=7.5.0 -constrains: -- openmp_impl <0.0a0 -license: BSD-3-Clause -license_family: BSD -size: 28948 -timestamp: 1770939786096 -- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda -sha256: d88aa7ae766cf584e180996e92fef2aa7d8e0a0a5ab1d4d49c32390c1b5fff31 -md5: dcdc58c15961dbf17a0621312b01f5cb -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: LGPL-2.1-or-later -license_family: GPL -size: 584660 -timestamp: 1768327524772 -- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda -sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 -md5: d2ffd7602c02f2b316fd921d39876885 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: bzip2-1.0.6 -license_family: BSD -size: 260182 -timestamp: 1771350215188 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc -md5: 4492fd26db29495f0ba23f146cd5638d -depends: -- __unix -license: ISC -size: 147413 -timestamp: 1772006283803 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-he90730b_1.conda -sha256: 06525fa0c4e4f56e771a3b986d0fdf0f0fc5a3270830ee47e127a5105bde1b9a -md5: bb6c4808bfa69d6f7f6b07e5846ced37 -depends: -- __glibc >=2.17,<3.0.a0 -- fontconfig >=2.15.0,<3.0a0 -- fonts-conda-ecosystem -- icu >=78.1,<79.0a0 -- libexpat >=2.7.3,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- libgcc >=14 -- libglib >=2.86.3,<3.0a0 -- libpng >=1.6.53,<1.7.0a0 -- libstdcxx >=14 -- libxcb >=1.17.0,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- pixman >=0.46.4,<1.0a0 -- xorg-libice >=1.1.2,<2.0a0 -- xorg-libsm >=1.2.6,<2.0a0 -- xorg-libx11 >=1.8.12,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -license: LGPL-2.1-only or MPL-1.1 -size: 989514 -timestamp: 1766415934926 -- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 -sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c -md5: c9f6a4b12229f7331f79c9a00dd6e240 -depends: -- font-ttf-dejavu-sans-mono -- fontconfig -- openjdk >=8.0.144 -- perl -license: GPL >=3 -size: 11664291 -timestamp: 1677946722445 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 -sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b -md5: 0c96522c6bdaed4b1566d11387caaf45 -license: BSD-3-Clause -license_family: BSD -size: 397370 -timestamp: 1566932522327 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 -sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c -md5: 34893075a5c9e55cdafac56607368fc6 -license: OFL-1.1 -license_family: Other -size: 96530 -timestamp: 1620479909603 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 -sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 -md5: 4d59c254e01d9cde7957100457e2d5fb -license: OFL-1.1 -license_family: Other -size: 700814 -timestamp: 1620479612257 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 -md5: 49023d73832ef61042f6a237cb2687e7 -license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 -license_family: Other -size: 1620504 -timestamp: 1727511233259 -- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.17.1-h27c8c51_0.conda -sha256: aa4a44dba97151221100a637c7f4bde619567afade9c0265f8e1c8eed8d7bd8c -md5: 867127763fbe935bab59815b6e0b7b5c -depends: -- __glibc >=2.17,<3.0.a0 -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- libgcc >=14 -- libuuid >=2.41.3,<3.0a0 -- libzlib >=1.3.1,<2.0a0 -license: MIT -license_family: MIT -size: 270705 -timestamp: 1771382710863 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 -sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 -md5: fee5683a3f04bd15cbd8318b096a27ab -depends: -- fonts-conda-forge -license: BSD-3-Clause -license_family: BSD -size: 3667 -timestamp: 1566974674465 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda -sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 -md5: a7970cd949a077b7cb9696379d338681 -depends: -- font-ttf-ubuntu -- font-ttf-inconsolata -- font-ttf-dejavu-sans-mono -- font-ttf-source-code-pro -license: BSD-3-Clause -license_family: BSD -size: 4059 -timestamp: 1762351264405 -- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda -sha256: aac402a8298f0c0cc528664249170372ef6b37ac39fdc92b40601a6aed1e32ff -md5: 3bf7b9fd5a7136126e0234db4b87c8b6 -depends: -- libgcc-ng >=12 -license: MIT -license_family: MIT -size: 77248 -timestamp: 1712692454246 -- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.14-hecca717_2.conda -sha256: 25ba37da5c39697a77fce2c9a15e48cf0a84f1464ad2aafbe53d8357a9f6cc8c -md5: 2cd94587f3a401ae05e03a6caf09539d -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libstdcxx >=14 -license: LGPL-2.0-or-later -license_family: LGPL -size: 99596 -timestamp: 1755102025473 -- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-13.2.1-h6083320_0.conda -sha256: 477f2c553f72165020d3c56740ba354be916c2f0b76fd9f535e83d698277d5ec -md5: 14470902326beee192e33719a2e8bb7f -depends: -- __glibc >=2.17,<3.0.a0 -- cairo >=1.18.4,<2.0a0 -- graphite2 >=1.3.14,<2.0a0 -- icu >=78.3,<79.0a0 -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.2 -- libfreetype6 >=2.14.2 -- libgcc >=14 -- libglib >=2.86.4,<3.0a0 -- libstdcxx >=14 -- libzlib >=1.3.2,<2.0a0 -license: MIT -license_family: MIT -size: 2384060 -timestamp: 1774276284520 -- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.3-h33c6efd_0.conda -sha256: fbf86c4a59c2ed05bbffb2ba25c7ed94f6185ec30ecb691615d42342baa1a16a -md5: c80d8a3b84358cb967fa81e7075fbc8a -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libstdcxx >=14 -license: MIT -license_family: MIT -size: 12723451 -timestamp: 1773822285671 -- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda -sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 -md5: b38117a3c920364aff79f870c984b4a3 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -license: LGPL-2.1-or-later -size: 134088 -timestamp: 1754905959823 -- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda -sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 -md5: fb53fb07ce46a575c5d004bbc96032c2 -depends: -- __glibc >=2.17,<3.0.a0 -- keyutils >=1.6.3,<2.0a0 -- libedit >=3.1.20250104,<3.2.0a0 -- libedit >=3.1.20250104,<4.0a0 -- libgcc >=14 -- libstdcxx >=14 -- openssl >=3.5.5,<4.0a0 -license: MIT -license_family: MIT -size: 1386730 -timestamp: 1769769569681 -- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.18-h0c24ade_0.conda -sha256: 836ec4b895352110335b9fdcfa83a8dcdbe6c5fb7c06c4929130600caea91c0a -md5: 6f2e2c8f58160147c4d1c6f4c14cbac4 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libjpeg-turbo >=3.1.2,<4.0a0 -- libtiff >=4.7.1,<4.8.0a0 -license: MIT -license_family: MIT -size: 249959 -timestamp: 1768184673131 -- conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.1.0-hdb68285_0.conda -sha256: f84cb54782f7e9cea95e810ea8fef186e0652d0fa73d3009914fa2c1262594e1 -md5: a752488c68f2e7c456bcbd8f16eec275 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libstdcxx >=14 -license: Apache-2.0 -license_family: Apache -size: 261513 -timestamp: 1773113328888 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda -sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c -md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 -depends: -- __glibc >=2.17,<3.0.a0 -- krb5 >=1.22.2,<1.23.0a0 -- libgcc >=14 -- libstdcxx >=14 -- libzlib >=1.3.1,<2.0a0 -license: Apache-2.0 -license_family: Apache -size: 4518030 -timestamp: 1770902209173 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda -sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 -md5: 6c77a605a7a689d17d4819c0f8ac9a00 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: MIT -license_family: MIT -size: 73490 -timestamp: 1761979956660 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda -sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 -md5: c277e0a4d549b03ac1e9d6cbbe3d017b -depends: -- ncurses -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- ncurses >=6.5,<7.0a0 -license: BSD-2-Clause -license_family: BSD -size: 134676 -timestamp: 1738479519902 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda -sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 -md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -constrains: -- expat 2.7.4.* -license: MIT -license_family: MIT -size: 76798 -timestamp: 1771259418166 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda -sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 -md5: a360c33a5abe61c07959e449fa1453eb -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: MIT -license_family: MIT -size: 58592 -timestamp: 1769456073053 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda -sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 -md5: e289f3d17880e44b633ba911d57a321b -depends: -- libfreetype6 >=2.14.3 -license: GPL-2.0-only OR FTL -size: 8049 -timestamp: 1774298163029 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda -sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d -md5: fb16b4b69e3f1dcfe79d80db8fd0c55d -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libpng >=1.6.55,<1.7.0a0 -- libzlib >=1.3.2,<2.0a0 -constrains: -- freetype >=2.14.3 -license: GPL-2.0-only OR FTL -size: 384575 -timestamp: 1774298162622 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda -sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 -md5: 0aa00f03f9e39fb9876085dee11a85d4 -depends: -- __glibc >=2.17,<3.0.a0 -- _openmp_mutex >=4.5 -constrains: -- libgcc-ng ==15.2.0=*_18 -- libgomp 15.2.0 he0feb66_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 1041788 -timestamp: 1771378212382 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda -sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 -md5: d5e96b1ed75ca01906b3d2469b4ce493 -depends: -- libgcc 15.2.0 he0feb66_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 27526 -timestamp: 1771378224552 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.86.4-h6548e54_1.conda -sha256: a27e44168a1240b15659888ce0d9b938ed4bdb49e9ea68a7c1ff27bcea8b55ce -md5: bb26456332b07f68bf3b7622ed71c0da -depends: -- __glibc >=2.17,<3.0.a0 -- libffi >=3.5.2,<3.6.0a0 -- libgcc >=14 -- libiconv >=1.18,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- pcre2 >=10.47,<10.48.0a0 -constrains: -- glib 2.86.4 *_1 -license: LGPL-2.1-or-later -size: 4398701 -timestamp: 1771863239578 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda -sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 -md5: 239c5e9546c38a1e884d69effcf4c882 -depends: -- __glibc >=2.17,<3.0.a0 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 603262 -timestamp: 1771378117851 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda -sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f -md5: 915f5995e94f60e9a4826e0b0920ee88 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: LGPL-2.1-only -size: 790176 -timestamp: 1754908768807 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda -sha256: cc9aba923eea0af8e30e0f94f2ad7156e2984d80d1e8e7fe6be5a1f257f0eb32 -md5: 8397539e3a0bbd1695584fb4f927485a -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -constrains: -- jpeg <0.0.0a -license: IJG AND BSD-3-Clause AND Zlib -size: 633710 -timestamp: 1762094827865 -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda -sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb -md5: c7c83eecbb72d88b940c249af56c8b17 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -constrains: -- xz 5.8.2.* -license: 0BSD -size: 113207 -timestamp: 1768752626120 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda -sha256: 36ade759122cdf0f16e2a2562a19746d96cf9c863ffaa812f2f5071ebbe9c03c -md5: 5f13ffc7d30ffec87864e678df9957b4 -depends: -- libgcc >=14 -- __glibc >=2.17,<3.0.a0 -- libzlib >=1.3.1,<2.0a0 -license: zlib-acknowledgement -size: 317669 -timestamp: 1770691470744 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda -sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e -md5: 1b08cd684f34175e4514474793d44bcb -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc 15.2.0 he0feb66_18 -constrains: -- libstdcxx-ng ==15.2.0=*_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 5852330 -timestamp: 1771378262446 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.1-h9d88235_1.conda -sha256: e5f8c38625aa6d567809733ae04bb71c161a42e44a9fa8227abe61fa5c60ebe0 -md5: cd5a90476766d53e901500df9215e927 -depends: -- __glibc >=2.17,<3.0.a0 -- lerc >=4.0.0,<5.0a0 -- libdeflate >=1.25,<1.26.0a0 -- libgcc >=14 -- libjpeg-turbo >=3.1.0,<4.0a0 -- liblzma >=5.8.1,<6.0a0 -- libstdcxx >=14 -- libwebp-base >=1.6.0,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- zstd >=1.5.7,<1.6.0a0 -license: HPND -size: 435273 -timestamp: 1762022005702 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda -sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee -md5: db409b7c1720428638e7c0d509d3e1b5 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: BSD-3-Clause -license_family: BSD -size: 40311 -timestamp: 1766271528534 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda -sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b -md5: aea31d2e5b1091feca96fcfe945c3cf9 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -constrains: -- libwebp 1.6.0 -license: BSD-3-Clause -license_family: BSD -size: 429011 -timestamp: 1752159441324 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda -sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa -md5: 92ed62436b625154323d40d5f2f11dd7 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- pthread-stubs -- xorg-libxau >=1.0.11,<2.0a0 -- xorg-libxdmcp -license: MIT -license_family: MIT -size: 395888 -timestamp: 1727278577118 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda -sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c -md5: 5aa797f8787fe7a17d1b0821485b5adc -depends: -- libgcc-ng >=12 -license: LGPL-2.1-or-later -size: 100393 -timestamp: 1702724383534 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda -sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 -md5: d87ff7921124eccd67248aa483c23fec -depends: -- __glibc >=2.17,<3.0.a0 -constrains: -- zlib 1.3.2 *_2 -license: Zlib -license_family: Other -size: 63629 -timestamp: 1774072609062 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda -sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 -md5: 47e340acb35de30501a76c7c799c41d7 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -license: X11 AND BSD-3-Clause -size: 891641 -timestamp: 1738195959188 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.2-ha668962_0.conda -sha256: 3825a4c84676a8a5cc23b397a2911e4efa4a805daf2af764153bd904e142ec41 -md5: a41092b0177362dbe5eb2a18501e86c0 -depends: -- xorg-libx11 -- xorg-libxext -- xorg-libxi -- xorg-libxrender -- xorg-libxtst -- libstdcxx >=14 -- libgcc >=14 -- __glibc >=2.17,<3.0.a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- xorg-libxrender >=0.9.12,<0.10.0a0 -- libjpeg-turbo >=3.1.2,<4.0a0 -- giflib >=5.2.2,<5.3.0a0 -- xorg-libxrandr >=1.5.5,<2.0a0 -- harfbuzz >=12.3.2 -- fontconfig >=2.17.1,<3.0a0 -- fonts-conda-ecosystem -- xorg-libxtst >=1.2.5,<2.0a0 -- xorg-libxi >=1.8.2,<2.0a0 -- lcms2 >=2.18,<3.0a0 -- alsa-lib >=1.2.15.3,<1.3.0a0 -- libpng >=1.6.55,<1.7.0a0 -- xorg-libxt >=1.3.1,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- xorg-libxext >=1.3.7,<2.0a0 -- xorg-libx11 >=1.8.13,<2.0a0 -- libcups >=2.3.3,<2.4.0a0 -license: GPL-2.0-or-later WITH Classpath-exception-2.0 -license_family: GPL -size: 122465031 -timestamp: 1771443671180 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda -sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c -md5: f61eb8cd60ff9057122a3d338b99c00f -depends: -- __glibc >=2.17,<3.0.a0 -- ca-certificates -- libgcc >=14 -license: Apache-2.0 -license_family: Apache -size: 3164551 -timestamp: 1769555830639 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda -sha256: 5e6f7d161356fefd981948bea5139c5aa0436767751a6930cb1ca801ebb113ff -md5: 7a3bff861a6583f1889021facefc08b1 -depends: -- __glibc >=2.17,<3.0.a0 -- bzip2 >=1.0.8,<2.0a0 -- libgcc >=14 -- libzlib >=1.3.1,<2.0a0 -license: BSD-3-Clause -license_family: BSD -size: 1222481 -timestamp: 1763655398280 -- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda -build_number: 7 -sha256: 9ec32b6936b0e37bcb0ed34f22ec3116e75b3c0964f9f50ecea5f58734ed6ce9 -md5: f2cfec9406850991f4e3d960cc9e3321 -depends: -- libgcc-ng >=12 -- libxcrypt >=4.4.36 -license: GPL-1.0-or-later OR Artistic-1.0-Perl -size: 13344463 -timestamp: 1703310653947 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda -sha256: 43d37bc9ca3b257c5dd7bf76a8426addbdec381f6786ff441dc90b1a49143b6a -md5: c01af13bdc553d1a8fbfff6e8db075f0 -depends: -- libgcc >=14 -- libstdcxx >=14 -- libgcc >=14 -- __glibc >=2.17,<3.0.a0 -license: MIT -license_family: MIT -size: 450960 -timestamp: 1754665235234 -- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda -sha256: 4ce2e1ee31a6217998f78c31ce7dc0a3e0557d9238b51d49dd20c52d467a126d -md5: f2c23a77b25efcad57d377b34bd84941 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- ncurses >=6.5,<7.0a0 -license: GPL-2.0-or-later AND LGPL-2.0-or-later -license_family: GPL -size: 593603 -timestamp: 1769710381284 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda -sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 -md5: b3c17d95b5a10c6e64a21fa17573e70e -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -license: MIT -license_family: MIT -size: 8252 -timestamp: 1726802366959 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda -sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b -md5: fb901ff28063514abb6046c9ec2c4a45 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -license: MIT -license_family: MIT -size: 58628 -timestamp: 1734227592886 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda -sha256: 277841c43a39f738927145930ff963c5ce4c4dacf66637a3d95d802a64173250 -md5: 1c74ff8c35dcadf952a16f752ca5aa49 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- libuuid >=2.38.1,<3.0a0 -- xorg-libice >=1.1.2,<2.0a0 -license: MIT -license_family: MIT -size: 27590 -timestamp: 1741896361728 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda -sha256: 516d4060139dbb4de49a4dcdc6317a9353fb39ebd47789c14e6fe52de0deee42 -md5: 861fb6ccbc677bb9a9fb2468430b9c6a -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- libxcb >=1.17.0,<2.0a0 -license: MIT -license_family: MIT -size: 839652 -timestamp: 1770819209719 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda -sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b -md5: b2895afaf55bf96a8c8282a2e47a5de0 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: MIT -license_family: MIT -size: 15321 -timestamp: 1762976464266 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda -sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 -md5: 1dafce8548e38671bea82e3f5c6ce22f -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -license: MIT -license_family: MIT -size: 20591 -timestamp: 1762976546182 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda -sha256: 79c60fc6acfd3d713d6340d3b4e296836a0f8c51602327b32794625826bd052f -md5: 34e54f03dfea3e7a2dcf1453a85f1085 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -license: MIT -license_family: MIT -size: 50326 -timestamp: 1769445253162 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda -sha256: 83c4c99d60b8784a611351220452a0a85b080668188dce5dfa394b723d7b64f4 -md5: ba231da7fccf9ea1e768caf5c7099b84 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -license: MIT -license_family: MIT -size: 20071 -timestamp: 1759282564045 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.2-hb9d3cd8_0.conda -sha256: 1a724b47d98d7880f26da40e45f01728e7638e6ec69f35a3e11f92acd05f9e7a -md5: 17dcc85db3c7886650b8908b183d6876 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- xorg-libx11 >=1.8.10,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxfixes >=6.0.1,<7.0a0 -license: MIT -license_family: MIT -size: 47179 -timestamp: 1727799254088 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda -sha256: 80ed047a5cb30632c3dc5804c7716131d767089f65877813d4ae855ee5c9d343 -md5: e192019153591938acf7322b6459d36e -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -license: MIT -license_family: MIT -size: 30456 -timestamp: 1769445263457 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda -sha256: 044c7b3153c224c6cedd4484dd91b389d2d7fd9c776ad0f4a34f099b3389f4a1 -md5: 96d57aba173e878a2089d5638016dc5e -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- xorg-libx11 >=1.8.10,<2.0a0 -license: MIT -license_family: MIT -size: 33005 -timestamp: 1734229037766 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda -sha256: a8afba4a55b7b530eb5c8ad89737d60d60bc151a03fbef7a2182461256953f0e -md5: 279b0de5f6ba95457190a1c459a64e31 -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- xorg-libice >=1.1.1,<2.0a0 -- xorg-libsm >=1.2.4,<2.0a0 -- xorg-libx11 >=1.8.10,<2.0a0 -license: MIT -license_family: MIT -size: 379686 -timestamp: 1731860547604 -- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda -sha256: 752fdaac5d58ed863bbf685bb6f98092fe1a488ea8ebb7ed7b606ccfce08637a -md5: 7bbe9a0cc0df0ac5f5a8ad6d6a11af2f -depends: -- __glibc >=2.17,<3.0.a0 -- libgcc >=13 -- xorg-libx11 >=1.8.10,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxi >=1.7.10,<2.0a0 -license: MIT -license_family: MIT -size: 32808 -timestamp: 1727964811275 -- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda -sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 -md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 -depends: -- __glibc >=2.17,<3.0.a0 -- libzlib >=1.3.1,<2.0a0 -license: BSD-3-Clause -license_family: BSD -size: 601375 -timestamp: 1764777111296 diff --git a/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt b/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt deleted file mode 100644 index cdc434c..0000000 --- a/modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt +++ /dev/null @@ -1,769 +0,0 @@ - -version: 6 -environments: -default: -channels: -- url: https://conda.anaconda.org/conda-forge/ -- url: https://conda.anaconda.org/bioconda/ -- url: https://conda.anaconda.org/bioconda/ -options: -pypi-prerelease-mode: if-necessary-or-explicit -packages: -linux-aarch64: -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda -- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda -packages: -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda -build_number: 20 -sha256: a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068 -md5: 468fd3bb9e1f671d36c2cbc677e56f1d -depends: -- libgomp >=7.5.0 -constrains: -- openmp_impl <0.0a0 -license: BSD-3-Clause -license_family: BSD -size: 28926 -timestamp: 1770939656741 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/alsa-lib-1.2.15.3-he30d5cf_0.conda -sha256: ea2233e2db9908c2e5f29d3ca420a546b4583253f4f70abb5494cdd676866d42 -md5: 4a98cbc4ade694520227402ff8880630 -depends: -- libgcc >=14 -license: LGPL-2.1-or-later -license_family: GPL -size: 615729 -timestamp: 1768327548407 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h4777abc_9.conda -sha256: b3495077889dde6bb370938e7db82be545c73e8589696ad0843a32221520ad4c -md5: 840d8fc0d7b3209be93080bc20e07f2d -depends: -- libgcc >=14 -license: bzip2-1.0.6 -license_family: BSD -size: 192412 -timestamp: 1771350241232 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda -sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc -md5: 4492fd26db29495f0ba23f146cd5638d -depends: -- __unix -license: ISC -size: 147413 -timestamp: 1772006283803 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cairo-1.18.4-h0b6afd8_1.conda -sha256: 675db823f3d6fb6bf747fab3b0170ba99b269a07cf6df1e49fff2f9972be9cd1 -md5: 043c13ed3a18396994be9b4fab6572ad -depends: -- fontconfig >=2.15.0,<3.0a0 -- fonts-conda-ecosystem -- icu >=78.1,<79.0a0 -- libexpat >=2.7.3,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- libgcc >=14 -- libglib >=2.86.3,<3.0a0 -- libpng >=1.6.53,<1.7.0a0 -- libstdcxx >=14 -- libxcb >=1.17.0,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- pixman >=0.46.4,<1.0a0 -- xorg-libice >=1.1.2,<2.0a0 -- xorg-libsm >=1.2.6,<2.0a0 -- xorg-libx11 >=1.8.12,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -license: LGPL-2.1-only or MPL-1.1 -size: 927045 -timestamp: 1766416003626 -- conda: https://conda.anaconda.org/bioconda/noarch/fastqc-0.12.1-hdfd78af_0.tar.bz2 -sha256: 7cc26225d590540ae95cd24940ff42f2da7479dd4cd22ae9ab9298665d06790c -md5: c9f6a4b12229f7331f79c9a00dd6e240 -depends: -- font-ttf-dejavu-sans-mono -- fontconfig -- openjdk >=8.0.144 -- perl -license: GPL >=3 -size: 11664291 -timestamp: 1677946722445 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 -sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b -md5: 0c96522c6bdaed4b1566d11387caaf45 -license: BSD-3-Clause -license_family: BSD -size: 397370 -timestamp: 1566932522327 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 -sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c -md5: 34893075a5c9e55cdafac56607368fc6 -license: OFL-1.1 -license_family: Other -size: 96530 -timestamp: 1620479909603 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 -sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 -md5: 4d59c254e01d9cde7957100457e2d5fb -license: OFL-1.1 -license_family: Other -size: 700814 -timestamp: 1620479612257 -- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda -sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 -md5: 49023d73832ef61042f6a237cb2687e7 -license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 -license_family: Other -size: 1620504 -timestamp: 1727511233259 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/fontconfig-2.17.1-hba86a56_0.conda -sha256: 835aff8615dd8d8fff377679710ce81b8a2c47b6404e21a92fb349fda193a15c -md5: 0fed1ff55f4938a65907f3ecf62609db -depends: -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- libgcc >=14 -- libuuid >=2.41.3,<3.0a0 -- libzlib >=1.3.1,<2.0a0 -license: MIT -license_family: MIT -size: 279044 -timestamp: 1771382728182 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 -sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 -md5: fee5683a3f04bd15cbd8318b096a27ab -depends: -- fonts-conda-forge -license: BSD-3-Clause -license_family: BSD -size: 3667 -timestamp: 1566974674465 -- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda -sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 -md5: a7970cd949a077b7cb9696379d338681 -depends: -- font-ttf-ubuntu -- font-ttf-inconsolata -- font-ttf-dejavu-sans-mono -- font-ttf-source-code-pro -license: BSD-3-Clause -license_family: BSD -size: 4059 -timestamp: 1762351264405 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/giflib-5.2.2-h31becfc_0.conda -sha256: a79dc3bd54c4fb1f249942ee2d5b601a76ecf9614774a4cff9af49adfa458db2 -md5: 2f809afaf0ba1ea4135dce158169efac -depends: -- libgcc-ng >=12 -license: MIT -license_family: MIT -size: 82124 -timestamp: 1712692444545 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/graphite2-1.3.14-hfae3067_2.conda -sha256: c9b1781fe329e0b77c5addd741e58600f50bef39321cae75eba72f2f381374b7 -md5: 4aa540e9541cc9d6581ab23ff2043f13 -depends: -- libgcc >=14 -- libstdcxx >=14 -license: LGPL-2.0-or-later -license_family: LGPL -size: 102400 -timestamp: 1755102000043 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/harfbuzz-13.2.1-h1134a53_0.conda -sha256: e22f485fddaaea3ff4b6cae98e0197b9dccd2ed2770337ad6ff38a92afe04e59 -md5: 05d65a2cf410adc331c9ea61f59f1013 -depends: -- cairo >=1.18.4,<2.0a0 -- graphite2 >=1.3.14,<2.0a0 -- icu >=78.3,<79.0a0 -- libexpat >=2.7.4,<3.0a0 -- libfreetype >=2.14.2 -- libfreetype6 >=2.14.2 -- libgcc >=14 -- libglib >=2.86.4,<3.0a0 -- libstdcxx >=14 -- libzlib >=1.3.2,<2.0a0 -license: MIT -license_family: MIT -size: 2345732 -timestamp: 1774281448329 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-78.3-hcab7f73_0.conda -sha256: 49ba6aed2c6b482bb0ba41078057555d29764299bc947b990708617712ef6406 -md5: 546da38c2fa9efacf203e2ad3f987c59 -depends: -- libgcc >=14 -- libstdcxx >=14 -license: MIT -license_family: MIT -size: 12837286 -timestamp: 1773822650615 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.3-h86ecc28_0.conda -sha256: 5ce830ca274b67de11a7075430a72020c1fb7d486161a82839be15c2b84e9988 -md5: e7df0aab10b9cbb73ab2a467ebfaf8c7 -depends: -- libgcc >=13 -license: LGPL-2.1-or-later -size: 129048 -timestamp: 1754906002667 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.22.2-hfd895c2_0.conda -sha256: b53999d888dda53c506b264e8c02b5f5c8e022c781eda0718f007339e6bc90ba -md5: d9ca108bd680ea86a963104b6b3e95ca -depends: -- keyutils >=1.6.3,<2.0a0 -- libedit >=3.1.20250104,<3.2.0a0 -- libedit >=3.1.20250104,<4.0a0 -- libgcc >=14 -- libstdcxx >=14 -- openssl >=3.5.5,<4.0a0 -license: MIT -license_family: MIT -size: 1517436 -timestamp: 1769773395215 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lcms2-2.18-h9d5b58d_0.conda -sha256: 379ef5e91a587137391a6149755d0e929f1a007d2dcb211318ac670a46c8596f -md5: bb960f01525b5e001608afef9d47b79c -depends: -- libgcc >=14 -- libjpeg-turbo >=3.1.2,<4.0a0 -- libtiff >=4.7.1,<4.8.0a0 -license: MIT -license_family: MIT -size: 293039 -timestamp: 1768184778398 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lerc-4.1.0-h52b7260_0.conda -sha256: 8957fd460c1c132c8031f65fd5f56ec3807fd71b7cab2c5e2b0937b13404ab36 -md5: d13423b06447113a90b5b1366d4da171 -depends: -- libgcc >=14 -- libstdcxx >=14 -license: Apache-2.0 -license_family: Apache -size: 240444 -timestamp: 1773114901155 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcups-2.3.3-h4f2b762_6.conda -sha256: 41b04f995c9f63af8c4065a35931e46cbc2fdd6b9bf7e4c19f90d53cbb2bc8e5 -md5: 67828c963b17db7dc989fe5d509ef04a -depends: -- krb5 >=1.22.2,<1.23.0a0 -- libgcc >=14 -- libstdcxx >=14 -- libzlib >=1.3.1,<2.0a0 -license: Apache-2.0 -license_family: Apache -size: 4553739 -timestamp: 1770903929794 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libdeflate-1.25-h1af38f5_0.conda -sha256: 48814b73bd462da6eed2e697e30c060ae16af21e9fbed30d64feaf0aad9da392 -md5: a9138815598fe6b91a1d6782ca657b0c -depends: -- libgcc >=14 -license: MIT -license_family: MIT -size: 71117 -timestamp: 1761979776756 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20250104-pl5321h976ea20_0.conda -sha256: c0b27546aa3a23d47919226b3a1635fccdb4f24b94e72e206a751b33f46fd8d6 -md5: fb640d776fc92b682a14e001980825b1 -depends: -- ncurses -- libgcc >=13 -- ncurses >=6.5,<7.0a0 -license: BSD-2-Clause -license_family: BSD -size: 148125 -timestamp: 1738479808948 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.7.4-hfae3067_0.conda -sha256: 995ce3ad96d0f4b5ed6296b051a0d7b6377718f325bc0e792fbb96b0e369dad7 -md5: 57f3b3da02a50a1be2a6fe847515417d -depends: -- libgcc >=14 -constrains: -- expat 2.7.4.* -license: MIT -license_family: MIT -size: 76564 -timestamp: 1771259530958 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.5.2-h376a255_0.conda -sha256: 3df4c539449aabc3443bbe8c492c01d401eea894603087fca2917aa4e1c2dea9 -md5: 2f364feefb6a7c00423e80dcb12db62a -depends: -- libgcc >=14 -license: MIT -license_family: MIT -size: 55952 -timestamp: 1769456078358 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype-2.14.3-h8af1aa0_0.conda -sha256: 752e4f66283d7deb4c6fd47d88df644d8daa2aaa825a54f3bf350a625190192a -md5: a229e22d4d8814a07702b0919d8e6701 -depends: -- libfreetype6 >=2.14.3 -license: GPL-2.0-only OR FTL -size: 8125 -timestamp: 1774301094057 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libfreetype6-2.14.3-hdae7a39_0.conda -sha256: 8e6b27fe4eec4c2fa7b7769a21973734c8dba1de80086fb0213e58375ac09f4c -md5: b99ed99e42dafb27889483b3098cace7 -depends: -- libgcc >=14 -- libpng >=1.6.55,<1.7.0a0 -- libzlib >=1.3.2,<2.0a0 -constrains: -- freetype >=2.14.3 -license: GPL-2.0-only OR FTL -size: 422941 -timestamp: 1774301093473 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-15.2.0-h8acb6b2_18.conda -sha256: 43df385bedc1cab11993c4369e1f3b04b4ca5d0ea16cba6a0e7f18dbc129fcc9 -md5: 552567ea2b61e3a3035759b2fdb3f9a6 -depends: -- _openmp_mutex >=4.5 -constrains: -- libgcc-ng ==15.2.0=*_18 -- libgomp 15.2.0 h8acb6b2_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 622900 -timestamp: 1771378128706 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-15.2.0-he9431aa_18.conda -sha256: 83bb0415f59634dccfa8335d4163d1f6db00a27b36666736f9842b650b92cf2f -md5: 4feebd0fbf61075a1a9c2e9b3936c257 -depends: -- libgcc 15.2.0 h8acb6b2_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 27568 -timestamp: 1771378136019 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libglib-2.86.4-hf53f6bf_1.conda -sha256: afc503dbd04a5bf2709aa9d8318a03a8c4edb389f661ff280c3494bfef4341ec -md5: 4ac4372fc4d7f20630a91314cdac8afd -depends: -- libffi >=3.5.2,<3.6.0a0 -- libgcc >=14 -- libiconv >=1.18,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- pcre2 >=10.47,<10.48.0a0 -constrains: -- glib 2.86.4 *_1 -license: LGPL-2.1-or-later -size: 4512186 -timestamp: 1771863220969 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-15.2.0-h8acb6b2_18.conda -sha256: fc716f11a6a8525e27a5d332ef6a689210b0d2a4dd1133edc0f530659aa9faa6 -md5: 4faa39bf919939602e594253bd673958 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 588060 -timestamp: 1771378040807 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.18-h90929bb_2.conda -sha256: 1473451cd282b48d24515795a595801c9b65b567fe399d7e12d50b2d6cdb04d9 -md5: 5a86bf847b9b926f3a4f203339748d78 -depends: -- libgcc >=14 -license: LGPL-2.1-only -size: 791226 -timestamp: 1754910975665 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libjpeg-turbo-3.1.2-he30d5cf_0.conda -sha256: 84064c7c53a64291a585d7215fe95ec42df74203a5bf7615d33d49a3b0f08bb6 -md5: 5109d7f837a3dfdf5c60f60e311b041f -depends: -- libgcc >=14 -constrains: -- jpeg <0.0.0a -license: IJG AND BSD-3-Clause AND Zlib -size: 691818 -timestamp: 1762094728337 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblzma-5.8.2-he30d5cf_0.conda -sha256: 843c46e20519651a3e357a8928352b16c5b94f4cd3d5481acc48be2e93e8f6a3 -md5: 96944e3c92386a12755b94619bae0b35 -depends: -- libgcc >=14 -constrains: -- xz 5.8.2.* -license: 0BSD -size: 125916 -timestamp: 1768754941722 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libpng-1.6.55-h1abf092_0.conda -sha256: c7378c6b79de4d571d00ad1caf0a4c19d43c9c94077a761abb6ead44d891f907 -md5: be4088903b94ea297975689b3c3aeb27 -depends: -- libgcc >=14 -- libzlib >=1.3.1,<2.0a0 -license: zlib-acknowledgement -size: 340156 -timestamp: 1770691477245 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-15.2.0-hef695bb_18.conda -sha256: 31fdb9ffafad106a213192d8319b9f810e05abca9c5436b60e507afb35a6bc40 -md5: f56573d05e3b735cb03efeb64a15f388 -depends: -- libgcc 15.2.0 h8acb6b2_18 -constrains: -- libstdcxx-ng ==15.2.0=*_18 -license: GPL-3.0-only WITH GCC-exception-3.1 -license_family: GPL -size: 5541411 -timestamp: 1771378162499 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libtiff-4.7.1-hdb009f0_1.conda -sha256: 7ff79470db39e803e21b8185bc8f19c460666d5557b1378d1b1e857d929c6b39 -md5: 8c6fd84f9c87ac00636007c6131e457d -depends: -- lerc >=4.0.0,<5.0a0 -- libdeflate >=1.25,<1.26.0a0 -- libgcc >=14 -- libjpeg-turbo >=3.1.0,<4.0a0 -- liblzma >=5.8.1,<6.0a0 -- libstdcxx >=14 -- libwebp-base >=1.6.0,<2.0a0 -- libzlib >=1.3.1,<2.0a0 -- zstd >=1.5.7,<1.6.0a0 -license: HPND -size: 488407 -timestamp: 1762022048105 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.41.3-h1022ec0_0.conda -sha256: c37a8e89b700646f3252608f8368e7eb8e2a44886b92776e57ad7601fc402a11 -md5: cf2861212053d05f27ec49c3784ff8bb -depends: -- libgcc >=14 -license: BSD-3-Clause -license_family: BSD -size: 43453 -timestamp: 1766271546875 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libwebp-base-1.6.0-ha2e29f5_0.conda -sha256: b03700a1f741554e8e5712f9b06dd67e76f5301292958cd3cb1ac8c6fdd9ed25 -md5: 24e92d0942c799db387f5c9d7b81f1af -depends: -- libgcc >=14 -constrains: -- libwebp 1.6.0 -license: BSD-3-Clause -license_family: BSD -size: 359496 -timestamp: 1752160685488 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcb-1.17.0-h262b8f6_0.conda -sha256: 461cab3d5650ac6db73a367de5c8eca50363966e862dcf60181d693236b1ae7b -md5: cd14ee5cca2464a425b1dbfc24d90db2 -depends: -- libgcc >=13 -- pthread-stubs -- xorg-libxau >=1.0.11,<2.0a0 -- xorg-libxdmcp -license: MIT -license_family: MIT -size: 397493 -timestamp: 1727280745441 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda -sha256: 6b46c397644091b8a26a3048636d10b989b1bf266d4be5e9474bf763f828f41f -md5: b4df5d7d4b63579d081fd3a4cf99740e -depends: -- libgcc-ng >=12 -license: LGPL-2.1-or-later -size: 114269 -timestamp: 1702724369203 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.3.2-hdc9db2a_2.conda -sha256: eb111e32e5a7313a5bf799c7fb2419051fa2fe7eff74769fac8d5a448b309f7f -md5: 502006882cf5461adced436e410046d1 -constrains: -- zlib 1.3.2 *_2 -license: Zlib -license_family: Other -size: 69833 -timestamp: 1774072605429 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-ha32ae93_3.conda -sha256: 91cfb655a68b0353b2833521dc919188db3d8a7f4c64bea2c6a7557b24747468 -md5: 182afabe009dc78d8b73100255ee6868 -depends: -- libgcc >=13 -license: X11 AND BSD-3-Clause -size: 926034 -timestamp: 1738196018799 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openjdk-25.0.2-h488f50d_0.conda -sha256: 6fd2c872b275fa5d42a61a4b6dc28a819cde29f9048adb547363597432e0720e -md5: 27fdd5d67e235c20d23b2d66406497d3 -depends: -- xorg-libx11 -- xorg-libxext -- xorg-libxi -- xorg-libxrender -- xorg-libxtst -- libstdcxx >=14 -- libgcc >=14 -- libzlib >=1.3.1,<2.0a0 -- xorg-libxtst >=1.2.5,<2.0a0 -- libpng >=1.6.55,<1.7.0a0 -- alsa-lib >=1.2.15.3,<1.3.0a0 -- xorg-libx11 >=1.8.13,<2.0a0 -- xorg-libxi >=1.8.2,<2.0a0 -- xorg-libxrandr >=1.5.5,<2.0a0 -- lcms2 >=2.18,<3.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -- libcups >=2.3.3,<2.4.0a0 -- libfreetype >=2.14.1 -- libfreetype6 >=2.14.1 -- harfbuzz >=12.3.2 -- xorg-libxext >=1.3.7,<2.0a0 -- giflib >=5.2.2,<5.3.0a0 -- xorg-libxt >=1.3.1,<2.0a0 -- libjpeg-turbo >=3.1.2,<4.0a0 -- fontconfig >=2.17.1,<3.0a0 -- fonts-conda-ecosystem -license: GPL-2.0-or-later WITH Classpath-exception-2.0 -license_family: GPL -size: 106988620 -timestamp: 1771443741031 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.6.1-h546c87b_1.conda -sha256: 7f8048c0e75b2620254218d72b4ae7f14136f1981c5eb555ef61645a9344505f -md5: 25f5885f11e8b1f075bccf4a2da91c60 -depends: -- ca-certificates -- libgcc >=14 -license: Apache-2.0 -license_family: Apache -size: 3692030 -timestamp: 1769557678657 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pcre2-10.47-hf841c20_0.conda -sha256: 04df2cee95feba440387f33f878e9f655521e69f4be33a0cd637f07d3d81f0f9 -md5: 1a30c42e32ca0ea216bd0bfe6f842f0b -depends: -- bzip2 >=1.0.8,<2.0a0 -- libgcc >=14 -- libzlib >=1.3.1,<2.0a0 -license: BSD-3-Clause -license_family: BSD -size: 1166552 -timestamp: 1763655534263 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/perl-5.32.1-7_h31becfc_perl5.conda -build_number: 7 -sha256: d78296134263b5bf476cad838ded65451e7162db756f9997c5d06b08122572ed -md5: 17d019cb2a6c72073c344e98e40dfd61 -depends: -- libgcc-ng >=12 -- libxcrypt >=4.4.36 -license: GPL-1.0-or-later OR Artistic-1.0-Perl -size: 13338804 -timestamp: 1703310557094 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pixman-0.46.4-h7ac5ae9_1.conda -sha256: e6b0846a998f2263629cfeac7bca73565c35af13251969f45d385db537a514e4 -md5: 1587081d537bd4ae77d1c0635d465ba5 -depends: -- libgcc >=14 -- libstdcxx >=14 -- libgcc >=14 -license: MIT -license_family: MIT -size: 357913 -timestamp: 1754665583353 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/procps-ng-4.0.6-h1779866_0.conda -sha256: e9cbcbc94e151ada3d6dc365380aaaf591f65012c16d9a2abaea4b9b90adc402 -md5: ab7288cc39545556d1bc5e71ab2df9a9 -depends: -- libgcc >=14 -- ncurses >=6.5,<7.0a0 -license: GPL-2.0-or-later AND LGPL-2.0-or-later -license_family: GPL -size: 636733 -timestamp: 1769712412683 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pthread-stubs-0.4-h86ecc28_1002.conda -sha256: 977dfb0cb3935d748521dd80262fe7169ab82920afd38ed14b7fee2ea5ec01ba -md5: bb5a90c93e3bac3d5690acf76b4a6386 -depends: -- libgcc >=13 -license: MIT -license_family: MIT -size: 8342 -timestamp: 1726803319942 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libice-1.1.2-h86ecc28_0.conda -sha256: a2ba1864403c7eb4194dacbfe2777acf3d596feae43aada8d1b478617ce45031 -md5: c8d8ec3e00cd0fd8a231789b91a7c5b7 -depends: -- libgcc >=13 -license: MIT -license_family: MIT -size: 60433 -timestamp: 1734229908988 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libsm-1.2.6-h0808dbd_0.conda -sha256: b86a819cd16f90c01d9d81892155126d01555a20dabd5f3091da59d6309afd0a -md5: 2d1409c50882819cb1af2de82e2b7208 -depends: -- libgcc >=13 -- libuuid >=2.38.1,<3.0a0 -- xorg-libice >=1.1.2,<2.0a0 -license: MIT -license_family: MIT -size: 28701 -timestamp: 1741897678254 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libx11-1.8.13-h63a1b12_0.conda -sha256: cf886160e2ff580d77f7eb8ec1a77c41c2c5b05343e329bc35f0ddf40b8d92ab -md5: 22dd10425ef181e80e130db50675d615 -depends: -- libgcc >=14 -- libxcb >=1.17.0,<2.0a0 -license: MIT -license_family: MIT -size: 869058 -timestamp: 1770819244991 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxau-1.0.12-he30d5cf_1.conda -sha256: e9f6e931feeb2f40e1fdbafe41d3b665f1ab6cb39c5880a1fcf9f79a3f3c84a5 -md5: 1c246e1105000c3660558459e2fd6d43 -depends: -- libgcc >=14 -license: MIT -license_family: MIT -size: 16317 -timestamp: 1762977521691 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxdmcp-1.1.5-he30d5cf_1.conda -sha256: 128d72f36bcc8d2b4cdbec07507542e437c7d67f677b7d77b71ed9eeac7d6df1 -md5: bff06dcde4a707339d66d45d96ceb2e2 -depends: -- libgcc >=14 -license: MIT -license_family: MIT -size: 21039 -timestamp: 1762979038025 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxext-1.3.7-he30d5cf_0.conda -sha256: db2188bc0d844d4e9747bac7f6c1d067e390bd769c5ad897c93f1df759dc5dba -md5: fb42b683034619915863d68dd9df03a3 -depends: -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -license: MIT -license_family: MIT -size: 52409 -timestamp: 1769446753771 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxfixes-6.0.2-he30d5cf_0.conda -sha256: 8cb9c88e25c57e47419e98f04f9ef3154ad96b9f858c88c570c7b91216a64d0e -md5: e8b4056544341daf1d415eaeae7a040c -depends: -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -license: MIT -license_family: MIT -size: 20704 -timestamp: 1759284028146 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxi-1.8.2-h57736b2_0.conda -sha256: 7b587407ecb9ccd2bbaf0fb94c5dbdde4d015346df063e9502dc0ce2b682fb5e -md5: eeee3bdb31c6acde2b81ad1b8c287087 -depends: -- libgcc >=13 -- xorg-libx11 >=1.8.9,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxfixes >=6.0.1,<7.0a0 -license: MIT -license_family: MIT -size: 48197 -timestamp: 1727801059062 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrandr-1.5.5-he30d5cf_0.conda -sha256: 9f5196665a8d72f4f119c40dcc4bafeb0b540b102cc7b8b299c2abf599e7919f -md5: 1f64c613f0b8d67e9fb0e165d898fb6b -depends: -- libgcc >=14 -- xorg-libx11 >=1.8.12,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxrender >=0.9.12,<0.10.0a0 -license: MIT -license_family: MIT -size: 31122 -timestamp: 1769445286951 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxrender-0.9.12-h86ecc28_0.conda -sha256: ffd77ee860c9635a28cfda46163dcfe9224dc6248c62404c544ae6b564a0be1f -md5: ae2c2dd0e2d38d249887727db2af960e -depends: -- libgcc >=13 -- xorg-libx11 >=1.8.10,<2.0a0 -license: MIT -license_family: MIT -size: 33649 -timestamp: 1734229123157 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxt-1.3.1-h57736b2_0.conda -sha256: 7c109792b60720809a580612aba7f8eb2a0bd425b9fc078748a9d6ffc97cbfa8 -md5: a9e4852c8e0b68ee783e7240030b696f -depends: -- libgcc >=13 -- xorg-libice >=1.1.1,<2.0a0 -- xorg-libsm >=1.2.4,<2.0a0 -- xorg-libx11 >=1.8.9,<2.0a0 -license: MIT -license_family: MIT -size: 384752 -timestamp: 1731860572314 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xorg-libxtst-1.2.5-h57736b2_3.conda -sha256: 6eaffce5a34fc0a16a21ddeaefb597e792a263b1b0c387c1ce46b0a967d558e1 -md5: c05698071b5c8e0da82a282085845860 -depends: -- libgcc >=13 -- xorg-libx11 >=1.8.9,<2.0a0 -- xorg-libxext >=1.3.6,<2.0a0 -- xorg-libxi >=1.7.10,<2.0a0 -license: MIT -license_family: MIT -size: 33786 -timestamp: 1727964907993 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.7-h85ac4a6_6.conda -sha256: 569990cf12e46f9df540275146da567d9c618c1e9c7a0bc9d9cfefadaed20b75 -md5: c3655f82dcea2aa179b291e7099c1fcc -depends: -- libzlib >=1.3.1,<2.0a0 -license: BSD-3-Clause -license_family: BSD -size: 614429 -timestamp: 1764777145593 From fffea3cf6c9ae0161f88669b3a4994cb307eda49 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 13:49:05 -0300 Subject: [PATCH 266/334] update rclone modules --- modules.json | 4 +- modules/nf-core/rclone/check/main.nf | 7 +++ .../nf-core/rclone/check/tests/main.nf.test | 8 ++-- .../rclone/check/tests/main.nf.test.snap | 46 +++++++++---------- modules/nf-core/rclone/checksum/main.nf | 7 +++ .../rclone/checksum/tests/main.nf.test | 6 +-- .../rclone/checksum/tests/main.nf.test.snap | 32 ++++++------- 7 files changed, 62 insertions(+), 48 deletions(-) diff --git a/modules.json b/modules.json index 8d99a6d..5da0eab 100644 --- a/modules.json +++ b/modules.json @@ -12,12 +12,12 @@ }, "rclone/check": { "branch": "master", - "git_sha": "a554e54c63c3f03f91c88a18ece7b89eca5a5212", + "git_sha": "fef5b8209601b7746f9705f63e5856cd2b5be708", "installed_by": ["modules"] }, "rclone/checksum": { "branch": "master", - "git_sha": "a554e54c63c3f03f91c88a18ece7b89eca5a5212", + "git_sha": "fef5b8209601b7746f9705f63e5856cd2b5be708", "installed_by": ["modules"] }, "rclone/copy": { diff --git a/modules/nf-core/rclone/check/main.nf b/modules/nf-core/rclone/check/main.nf index ee1d36b..ec1444e 100644 --- a/modules/nf-core/rclone/check/main.nf +++ b/modules/nf-core/rclone/check/main.nf @@ -42,6 +42,13 @@ process RCLONE_CHECK { ${source} \\ ${destination} || echo \$? > ${prefix}.exit_code.txt + sort -k2 ${prefix}.combined.txt -o ${prefix}.combined.txt + sort ${prefix}.differ.txt -o ${prefix}.differ.txt + sort ${prefix}.missing_on_dst.txt -o ${prefix}.missing_on_dst.txt + sort ${prefix}.missing_on_src.txt -o ${prefix}.missing_on_src.txt + sort ${prefix}.match.txt -o ${prefix}.match.txt + sort ${prefix}.error.txt -o ${prefix}.error.txt + # Do not emit empty output files for f in *.txt; do [ -s "\$f" ] || rm -f "\$f" diff --git a/modules/nf-core/rclone/check/tests/main.nf.test b/modules/nf-core/rclone/check/tests/main.nf.test index 312d631..88d545f 100644 --- a/modules/nf-core/rclone/check/tests/main.nf.test +++ b/modules/nf-core/rclone/check/tests/main.nf.test @@ -25,7 +25,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "match", "missing_on_dst", "missing_on_src", "error"])).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } @@ -45,7 +45,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "match", "differ", "missing_on_dst", "missing_on_src", "error"])).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } @@ -65,7 +65,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "match", "missing_on_dst", "missing_on_src", "error"])).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } @@ -85,7 +85,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "differ", "missing_on_dst", "missing_on_src", "error"])).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } diff --git a/modules/nf-core/rclone/check/tests/main.nf.test.snap b/modules/nf-core/rclone/check/tests/main.nf.test.snap index 031a7c7..e19d7bf 100644 --- a/modules/nf-core/rclone/check/tests/main.nf.test.snap +++ b/modules/nf-core/rclone/check/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test" }, - "test.combined.txt" + "test.combined.txt:md5,6518ec1170e94cd1e9d2ef4a4ba5a9e8" ] ], "differ": [ @@ -24,7 +24,7 @@ { "id": "test" }, - "test.match.txt" + "test.match.txt:md5,66c7833b0fd04a059b29a116474c021c" ] ], "missing_on_dst": [ @@ -42,10 +42,10 @@ ] } ], - "timestamp": "2026-07-22T14:46:30.042575576", + "timestamp": "2026-08-04T11:26:36.792274751", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } }, "sarscov2 - fastq - stub": { @@ -56,7 +56,7 @@ { "id": "test" }, - "test.combined.txt" + "test.combined.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "differ": [ @@ -64,7 +64,7 @@ { "id": "test" }, - "test.differ.txt" + "test.differ.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "error": [ @@ -72,7 +72,7 @@ { "id": "test" }, - "test.error.txt" + "test.error.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "exit_code": [ @@ -83,7 +83,7 @@ { "id": "test" }, - "test.match.txt" + "test.match.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "missing_on_dst": [ @@ -91,7 +91,7 @@ { "id": "test" }, - "test.missing_on_dst.txt" + "test.missing_on_dst.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "missing_on_src": [ @@ -99,7 +99,7 @@ { "id": "test" }, - "test.missing_on_src.txt" + "test.missing_on_src.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "versions_rclone": [ @@ -111,10 +111,10 @@ ] } ], - "timestamp": "2026-07-21T21:03:37.410543015", + "timestamp": "2026-08-04T11:26:42.333790108", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } }, "different files": { @@ -125,7 +125,7 @@ { "id": "test" }, - "test.combined.txt" + "test.combined.txt:md5,750454d95092af361bdb1c3e8c113251" ] ], "differ": [ @@ -150,7 +150,7 @@ { "id": "test" }, - "test.missing_on_dst.txt" + "test.missing_on_dst.txt:md5,66c7833b0fd04a059b29a116474c021c" ] ], "missing_on_src": [ @@ -158,7 +158,7 @@ { "id": "test" }, - "test.missing_on_src.txt" + "test.missing_on_src.txt:md5,1dd18b615ae0c9abf940ad0739fb8950" ] ], "versions_rclone": [ @@ -170,10 +170,10 @@ ] } ], - "timestamp": "2026-07-21T21:03:45.979925514", + "timestamp": "2026-08-04T11:26:48.79499383", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } }, "differ and missing": { @@ -184,7 +184,7 @@ { "id": "test" }, - "test.combined.txt" + "test.combined.txt:md5,74c774156fdfa62f1ba14c780adf89f4" ] ], "differ": [ @@ -192,7 +192,7 @@ { "id": "test" }, - "test.differ.txt" + "test.differ.txt:md5,ac036608c5c402f92926505d0f0ab0e4" ] ], "error": [ @@ -214,7 +214,7 @@ { "id": "test" }, - "test.missing_on_dst.txt" + "test.missing_on_dst.txt:md5,6435d60effdac7ca6fbdfad40ffe2535" ] ], "missing_on_src": [ @@ -222,7 +222,7 @@ { "id": "test" }, - "test.missing_on_src.txt" + "test.missing_on_src.txt:md5,89fcd615fd22b904204dafd407daf015" ] ], "versions_rclone": [ @@ -234,10 +234,10 @@ ] } ], - "timestamp": "2026-07-22T14:46:52.993591106", + "timestamp": "2026-08-04T11:26:55.797148658", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } } } \ No newline at end of file diff --git a/modules/nf-core/rclone/checksum/main.nf b/modules/nf-core/rclone/checksum/main.nf index bef4c5e..1f506c0 100644 --- a/modules/nf-core/rclone/checksum/main.nf +++ b/modules/nf-core/rclone/checksum/main.nf @@ -44,6 +44,13 @@ process RCLONE_CHECKSUM { $sumfile \\ ${destination} || echo \$? > ${prefix}.exit_code.txt + sort -k2 ${prefix}.combined.txt -o ${prefix}.combined.txt + sort ${prefix}.differ.txt -o ${prefix}.differ.txt + sort ${prefix}.missing_on_dst.txt -o ${prefix}.missing_on_dst.txt + sort ${prefix}.missing_on_src.txt -o ${prefix}.missing_on_src.txt + sort ${prefix}.match.txt -o ${prefix}.match.txt + sort ${prefix}.error.txt -o ${prefix}.error.txt + # Do not emit empty output files for f in *.txt; do [ -s "\$f" ] || rm -f "\$f" diff --git a/modules/nf-core/rclone/checksum/tests/main.nf.test b/modules/nf-core/rclone/checksum/tests/main.nf.test index bbfab84..746d594 100644 --- a/modules/nf-core/rclone/checksum/tests/main.nf.test +++ b/modules/nf-core/rclone/checksum/tests/main.nf.test @@ -26,7 +26,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "match", "differ", "missing_on_dst", "missing_on_src", "error"]) ).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } @@ -48,7 +48,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["match", "combined", "differ", "missing_on_dst", "missing_on_src", "error"]) ).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } @@ -69,7 +69,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(sanitizeOutput(process.out, unstableKeys: ["combined", "match", "missing_on_dst", "missing_on_src", "error"]) ).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } diff --git a/modules/nf-core/rclone/checksum/tests/main.nf.test.snap b/modules/nf-core/rclone/checksum/tests/main.nf.test.snap index a100d10..fc45ed0 100644 --- a/modules/nf-core/rclone/checksum/tests/main.nf.test.snap +++ b/modules/nf-core/rclone/checksum/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test" }, - "test.combined.txt" + "test.combined.txt:md5,4b849f0b6831d6561da709ca6f626b7d" ] ], "differ": [ @@ -24,7 +24,7 @@ { "id": "test" }, - "test.match.txt" + "test.match.txt:md5,2458aa282a426dec085359d209d5077c" ] ], "missing_on_dst": [ @@ -42,10 +42,10 @@ ] } ], - "timestamp": "2026-07-21T23:18:32.247989694", + "timestamp": "2026-08-04T11:27:09.176178267", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } }, "test - md5 - differs": { @@ -56,7 +56,7 @@ { "id": "test" }, - "test.combined.txt" + "test.combined.txt:md5,d79adc0e541e01c95735769c919ae993" ] ], "differ": [ @@ -81,7 +81,7 @@ { "id": "test" }, - "test.missing_on_dst.txt" + "test.missing_on_dst.txt:md5,a438474115db37daf9d8e1307c06eb4a" ] ], "missing_on_src": [ @@ -96,10 +96,10 @@ ] } ], - "timestamp": "2026-07-21T23:20:27.477738495", + "timestamp": "2026-08-04T11:27:20.066820454", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } }, "test - md5 - stub": { @@ -110,7 +110,7 @@ { "id": "test" }, - "test.combined.txt" + "test.combined.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "differ": [ @@ -118,7 +118,7 @@ { "id": "test" }, - "test.differ.txt" + "test.differ.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "error": [ @@ -126,7 +126,7 @@ { "id": "test" }, - "test.error.txt" + "test.error.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "exit_code": [ @@ -137,7 +137,7 @@ { "id": "test" }, - "test.match.txt" + "test.match.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "missing_on_dst": [ @@ -145,7 +145,7 @@ { "id": "test" }, - "test.missing_on_dst.txt" + "test.missing_on_dst.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "missing_on_src": [ @@ -153,7 +153,7 @@ { "id": "test" }, - "test.missing_on_src.txt" + "test.missing_on_src.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], "versions_rclone": [ @@ -165,10 +165,10 @@ ] } ], - "timestamp": "2026-07-21T23:19:49.064384002", + "timestamp": "2026-08-04T11:27:14.250267458", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } } } \ No newline at end of file From 6fb53873c4607c580c867f27eed9d2b536c15b1e Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 13:49:38 -0300 Subject: [PATCH 267/334] update snapshots --- tests/.nftignore | 1 - tests/default.nf.test.snap | 14 +++++++++--- tests/edge.nf.test.snap | 44 +++++++++++++++++++++++++++++++----- tests/main_full.nf.test.snap | 10 +++++--- 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/tests/.nftignore b/tests/.nftignore index 12ea18a..b1e73cd 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -10,5 +10,4 @@ multiqc/multiqc_plots/{svg,pdf,png}/*.{svg,pdf,png} multiqc/multiqc_report.html fastqc/*_fastqc.{html,zip} pipeline_info/*.{html,json,txt,yml} -rclone/**/*.txt rclone/**/*.log diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 2b27518..924ee4f 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -54,13 +54,21 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", "multiqc_rclone_checksum_md5.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", - "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4" + "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4", + "Illumina_annotation.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "benchmark_bed.combined.txt:md5,dcd2c539696adba720986251dcd1aaef", + "benchmark_bed.match.txt:md5,12608858576bec12c65ff338a99803c3", + "Illumina_annotation.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "benchmark_bed.combined.txt:md5,dcd2c539696adba720986251dcd1aaef", + "benchmark_bed.match.txt:md5,12608858576bec12c65ff338a99803c3" ] ], - "timestamp": "2026-07-22T22:00:27.445840436", + "timestamp": "2026-08-04T13:37:52.28474364", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } } } \ No newline at end of file diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index 52620b3..334660f 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -64,13 +64,28 @@ "multiqc_rclone_check.txt:md5,4b2a6990836593f69e8e81a82c3daf42", "multiqc_rclone_checksum_md5.txt:md5,cf92203df21f04ddf8315fc606812e0b", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", - "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" + "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", + "Illumina_annotation_incorrect.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_incorrect.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_missing.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_missing.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_incorrect.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", + "Illumina_annotation_incorrect.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_incorrect.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_incorrect.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing.combined.txt:md5,62c42261ec9b9812c862bc2d5e71fd38", + "Illumina_annotation_missing.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_missing.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", + "Illumina_annotation_sha_only.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", + "Illumina_annotation_sha_only.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-07-30T20:44:41.242808343", + "timestamp": "2026-08-04T13:39:20.808292484", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } }, "-profile test edge cases": { @@ -142,13 +157,30 @@ "multiqc_rclone_check.txt:md5,c8f13c10aa4f0e4b356c5c08a9ae7ee9", "multiqc_rclone_checksum_md5.txt:md5,cf92203df21f04ddf8315fc606812e0b", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", - "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" + "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", + "Illumina_annotation_incorrect.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_incorrect.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_missing.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_missing.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_sha_only.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_incorrect.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", + "Illumina_annotation_incorrect.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_incorrect.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_incorrect.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing.combined.txt:md5,62c42261ec9b9812c862bc2d5e71fd38", + "Illumina_annotation_missing.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_missing.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", + "Illumina_annotation_sha_only.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", + "Illumina_annotation_sha_only.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-07-30T20:44:11.000298059", + "timestamp": "2026-08-04T13:38:39.104449891", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } } } \ No newline at end of file diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 96249fd..6b8cf29 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -49,13 +49,17 @@ "multiqc_rclone_check.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_rclone_checksum_md5.txt:md5,d7c7dd71a9ff75955dd0e508d1ad9968", "multiqc_rclone_checksum_sha.txt:md5,03a73f087a286ec6580aada2a5db2e7c", - "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" + "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca", + "demultiplex.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", + "demultiplex.match.txt:md5,902e4715d579b7f43a5463a220df8db0", + "demultiplex.combined.txt:md5,7c44b320b7f629aaade5c1b6395d6c9b", + "demultiplex.match.txt:md5,644b95db936b45b931143faefb15be7f" ] ], - "timestamp": "2026-07-30T20:46:20.306063412", + "timestamp": "2026-08-04T13:48:52.775725114", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.0" } } } \ No newline at end of file From ef3f45f428ad505bf3e425ed9b6e619a7faadbc5 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Tue, 4 Aug 2026 13:49:48 -0300 Subject: [PATCH 268/334] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7938a9..24c10f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Fixed` +- [[#75](https://github.com/nf-core/datasync/pull/75)] - Fixed linting issues reported by nf-core and Nextflow, and updated `rclone` modules and nf-tests to sort generated report files for deterministic snapshots ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#73](https://github.com/nf-core/datasync/pull/73)] - Create tmp `files_to_copy.tx` avoiding error with write permissions in work directory ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). ### `Dependencies` From 71af415295ddc8cb53e2df5745189625f5d599fe Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Wed, 5 Aug 2026 09:48:31 -0300 Subject: [PATCH 269/334] Bugfix: Rclone checksum should check if any files are present in source but not in checksum file --- conf/modules.config | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index 701c4a7..bc47584 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -22,8 +22,7 @@ process { tag = { "${meta.id}_${hash}" } ext.args = { def base_args = [ - '--no-check-certificate', - "--one-way" + '--no-check-certificate' ] if (params.download && meta.check_format == 'sha') { base_args.add("--download") From 16acce40ec0eaf84528edc7686e2eba25b2f3515 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 5 Aug 2026 15:18:21 +0200 Subject: [PATCH 270/334] Update snapshot --- tests/default.nf.test.snap | 6 ++++-- tests/edge.nf.test.snap | 10 ++++++---- tests/main_full.nf.test.snap | 6 ++++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 2b27518..c7d9955 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -45,7 +45,9 @@ "rclone/checksum/Illumina_annotation/Illumina_annotation.match.txt", "rclone/checksum/benchmark_bed", "rclone/checksum/benchmark_bed/benchmark_bed.combined.txt", + "rclone/checksum/benchmark_bed/benchmark_bed.exit_code.txt", "rclone/checksum/benchmark_bed/benchmark_bed.match.txt", + "rclone/checksum/benchmark_bed/benchmark_bed.missing_on_src.txt", "rclone/copy", "rclone/copy/Illumina_annotation-rclone-copy.log", "rclone/copy/benchmark_bed-rclone-copy.log" @@ -53,11 +55,11 @@ [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", - "multiqc_rclone_checksum_md5.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", + "multiqc_rclone_checksum_md5.txt:md5,c7127de966d1be295ef6697dba648c79", "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4" ] ], - "timestamp": "2026-07-22T22:00:27.445840436", + "timestamp": "2026-08-05T15:09:10.284238596", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index 52620b3..13aeb90 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -51,6 +51,7 @@ "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.exit_code.txt", "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_src.txt", "rclone/checksum/Illumina_annotation_sha_only", "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", @@ -62,12 +63,12 @@ [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,4b2a6990836593f69e8e81a82c3daf42", - "multiqc_rclone_checksum_md5.txt:md5,cf92203df21f04ddf8315fc606812e0b", + "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" ] ], - "timestamp": "2026-07-30T20:44:41.242808343", + "timestamp": "2026-08-05T15:10:18.931695751", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" @@ -128,6 +129,7 @@ "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.exit_code.txt", "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_src.txt", "rclone/checksum/Illumina_annotation_sha_only", "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", @@ -140,12 +142,12 @@ [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,c8f13c10aa4f0e4b356c5c08a9ae7ee9", - "multiqc_rclone_checksum_md5.txt:md5,cf92203df21f04ddf8315fc606812e0b", + "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5" ] ], - "timestamp": "2026-07-30T20:44:11.000298059", + "timestamp": "2026-08-05T15:09:41.763856779", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 96249fd..b6b5cd9 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -40,19 +40,21 @@ "rclone/checksum", "rclone/checksum/demultiplex", "rclone/checksum/demultiplex/demultiplex.combined.txt", + "rclone/checksum/demultiplex/demultiplex.exit_code.txt", "rclone/checksum/demultiplex/demultiplex.match.txt", + "rclone/checksum/demultiplex/demultiplex.missing_on_src.txt", "rclone/copy", "rclone/copy/demultiplex-rclone-copy.log" ], [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,03a73f087a286ec6580aada2a5db2e7c", - "multiqc_rclone_checksum_md5.txt:md5,d7c7dd71a9ff75955dd0e508d1ad9968", + "multiqc_rclone_checksum_md5.txt:md5,a68bd0275b5b6cb62ec966b68121b0e1", "multiqc_rclone_checksum_sha.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca" ] ], - "timestamp": "2026-07-30T20:46:20.306063412", + "timestamp": "2026-08-05T15:12:45.951559208", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From 1967cd27c63a7f8710730a519f3b9492670a24fd Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Wed, 5 Aug 2026 15:33:10 +0200 Subject: [PATCH 271/334] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7938a9..81483e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Fixed` +- [[#76](https://github.com/nf-core/datasync/pull/76)] - Remove `--one-way` from rclone/checksum confi ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#73](https://github.com/nf-core/datasync/pull/73)] - Create tmp `files_to_copy.tx` avoiding error with write permissions in work directory ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). ### `Dependencies` From 807a6474644131a9a2592fbee76ca84ee2ce75e2 Mon Sep 17 00:00:00 2001 From: Anabella Trigila <18577080+atrigila@users.noreply.github.com> Date: Thu, 6 Aug 2026 11:46:05 -0300 Subject: [PATCH 272/334] fix container config --- conf/containers_conda_lock_files_amd64.config | 8 ++++---- conf/containers_conda_lock_files_arm64.config | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index fbe762b..584667d 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1,4 +1,4 @@ -process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } -process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } -process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } +process { withName: 'MULTIQC' { conda = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } +process { withName: 'RCLONE_CHECK' { conda = 'modules/nf-core/rclone/check/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { conda = 'modules/nf-core/rclone/checksum/.conda-lock/linux_amd64-bd-2ef33c5b9132aa97_1.txt' } } +process { withName: 'RCLONE_COPY' { conda = 'modules/nf-core/rclone/copy/.conda-lock/linux_amd64-bd-ff88b2e0040147be_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index b425a8d..028f0ed 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1,4 +1,4 @@ -process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } -process { withName: 'RCLONE_CHECK' { container = 'modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } -process { withName: 'RCLONE_CHECKSUM' { container = 'modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } -process { withName: 'RCLONE_COPY' { container = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } +process { withName: 'MULTIQC' { conda = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } +process { withName: 'RCLONE_CHECK' { conda = 'modules/nf-core/rclone/check/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } +process { withName: 'RCLONE_CHECKSUM' { conda = 'modules/nf-core/rclone/checksum/.conda-lock/linux_arm64-bd-351f8e39202b129a_1.txt' } } +process { withName: 'RCLONE_COPY' { conda = 'modules/nf-core/rclone/copy/.conda-lock/linux_arm64-bd-ff88b2e0040147be_1.txt' } } From 800f6d46f1fab4caaa11c9c6d82e082e33bdb342 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 7 Aug 2026 15:55:30 +0200 Subject: [PATCH 273/334] Add exit code summary to report --- assets/multiqc_config.yml | 58 +++++++++++++++++++ assets/multiqc_custom.css | 4 ++ .../utils_nfcore_datasync_pipeline/main.nf | 22 +++++++ workflows/datasync.nf | 19 ++++++ 4 files changed, 103 insertions(+) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index cd549e8..f67271f 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -17,6 +17,7 @@ disable_version_detection: true custom_content: order: - samplesheet + - rclone_exit_codes - rclone_checksum_md5 - rclone_checksum_sha - rclone_check @@ -41,6 +42,61 @@ custom_data: checksum_sha: title: Sha256 checksum file + rclone_exit_codes: + section_name: "Validation Summary" + description: > + This table summarizes the exit codes returned by `RCLONE_CHECK` and `RCLONE_CHECKSUM` for each processed sample. Reviewing these exit codes + can help identify files that were not successfully validated or where unexpected errors occurred during integrity checking + plot_type: "table" + file_format: "tsv" + headers: + Row: + title: Row + hidden: true + Sample: + title: Sample ID + description: "Sample name from the input samplesheet" + Module: + title: Module + Exit code: + title: Exit Code + description: "Exit code reported by the corresponding Rclone module for each processed Sample ID" + cond_formatting_rules: + success: + - s_eq: "0 - Success" + error: + - s_eq: "1 - Error" + syntax_error: + - s_eq: "2 - Syntax or usage error" + directory_not_found: + - s_eq: "3 - Directory not found" + file_not_found: + - s_eq: "4 - File not found" + temporary_error: + - s_eq: "5 - Temporary error" + less_serious_error: + - s_eq: "6 - Less serious error" + fatal_error: + - s_eq: "7 - Fatal error" + transfer_limit_exceeded: + - s_eq: "8 - Transfer limit exceeded" + no_files_transferred: + - s_eq: "9 - No files transferred" + duration_limit_exceeded: + - s_eq: "10 - Duration limit exceeded" + cond_formatting_colours: + - success: "#5cb85c" + - error: "#d9534f" + - syntax_error: "#f0ad4e" + - directory_not_found: "#f0ad4e" + - file_not_found: "#f0ad4e" + - temporary_error: "#5bc0de" + - less_serious_error: "#5bc0de" + - fatal_error: "#8b0000" + - transfer_limit_exceeded: "#9370db" + - no_files_transferred: "#808080" + - duration_limit_exceeded: "#6f42c1" + rclone_checksum_md5: parent_id: source_path_checksum_validation parent_name: "Source checks" @@ -197,6 +253,8 @@ custom_data: sp: samplesheet: fn: "samplesheet.csv" + rclone_exit_codes: + fn: "rclone_exit_codes.tsv" rclone_checksum_md5: fn: "*_md5_rclone_checksum_mqc.tsv" rclone_checksum_sha: diff --git a/assets/multiqc_custom.css b/assets/multiqc_custom.css index 777ea04..3c56370 100644 --- a/assets/multiqc_custom.css +++ b/assets/multiqc_custom.css @@ -1,4 +1,5 @@ /* Keep the internal row identifier available to MultiQC without displaying it. */ +#rclone_exit_codes-section-plot_table .rowheader, #rclone_checksum_md5-plot_table .rowheader, #rclone_checksum_sha-plot_table .rowheader, #rclone_check-plot_table .rowheader { @@ -7,6 +8,7 @@ /* Distinguish major sections from their result subsections. */ #samplesheet, +#rclone_exit_codes, #source_path_checksum_validation, #file_transfer_integrity_check { font-size: 2rem; @@ -34,6 +36,7 @@ width: 1%; } +#rclone_exit_codes-section-plot_table .File .val, #rclone_checksum_md5-plot_table .File .val, #rclone_checksum_sha-plot_table .File .val, #rclone_check-plot_table .File .val { @@ -41,6 +44,7 @@ white-space: normal; } +#rclone_exit_codes-section-plot_table_container .mqc-table-responsive, #rclone_checksum_md5-plot_table_container .mqc-table-responsive, #rclone_checksum_sha-plot_table_container .mqc-table-responsive, #rclone_check-plot_table_container .mqc-table-responsive { diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index f135898..0884ac5 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -172,6 +172,28 @@ workflow PIPELINE_COMPLETION { def validateInputParameters() { } +// +// Create exit code summary +// +def createExitSummary(meta, exit_file, module) { + def code_map = [ + "0": "0 - Success", + "1": "1 - Error", + "2": "2 - Syntax or usage error", + "3": "3 - Directory not found", + "4": "4 - File not found", + "5": "5 - Temporary error", + "6": "6 - Less serious error", + "7": "7 - Fatal error", + "8": "8 - Transfer limit exceeded", + "9": "9 - No files transferred", + "10": "10 - Duration limit exceeded" + ] + def exit_code = exit_file.text.trim() + def code = code_map.get(exit_code, exit_code) + + [meta, "${meta.id}:${module}\t${meta.id}\t${module}\t${code}"] +} // // Parse Rclone check and checksum combined.txt file // diff --git a/workflows/datasync.nf b/workflows/datasync.nf index cf68fe7..643f029 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -12,6 +12,7 @@ include { paramsSummaryMultiqc } from '../subworkflows/nf-co include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_datasync_pipeline' include { parseRcloneCheck } from '../subworkflows/local/utils_nfcore_datasync_pipeline' +include { createExitSummary } from '../subworkflows/local/utils_nfcore_datasync_pipeline' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -159,6 +160,24 @@ workflow DATASYNC { } ) + ch_multiqc_files = ch_multiqc_files.mix( + RCLONE_CHECK.out.exit_code + .map { meta, exit_file -> [ meta, exit_file, "CHECK" ] } + .mix(RCLONE_CHECKSUM.out.exit_code + .map { meta, exit_file -> [ meta, exit_file, "CHECKSUM" ] } + ) + .map { meta, exit_file, module -> + createExitSummary(meta, exit_file, module) + } + .collectFile( + seed: "Row\tSample\tModule\tExit code", + sort: false, + newLine: true + ) { meta, exit_code -> + return [ "rclone_exit_codes.tsv", exit_code ] + } + ) + // // Collate and save software versions // From ad8271931dd9902221570b35d946193738818108 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 7 Aug 2026 16:04:30 +0200 Subject: [PATCH 274/334] Update snapshots --- tests/default.nf.test.snap | 14 +++++++++----- tests/edge.nf.test.snap | 18 ++++++++++++------ tests/main_full.nf.test.snap | 12 ++++++++---- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 0f336b2..94cd3ee 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -25,6 +25,7 @@ "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_rclone_check.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", + "multiqc/multiqc_data/multiqc_rclone_exit_codes.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -55,7 +56,8 @@ [ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", - "multiqc_rclone_checksum_md5.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", + "multiqc_rclone_checksum_md5.txt:md5,c7127de966d1be295ef6697dba648c79", + "multiqc_rclone_exit_codes.txt:md5,b4733136a04fe8e27f0679906ef6bdfc", "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4", "Illumina_annotation.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", "Illumina_annotation.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", @@ -63,14 +65,16 @@ "benchmark_bed.match.txt:md5,12608858576bec12c65ff338a99803c3", "Illumina_annotation.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", "Illumina_annotation.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "benchmark_bed.combined.txt:md5,dcd2c539696adba720986251dcd1aaef", - "benchmark_bed.match.txt:md5,12608858576bec12c65ff338a99803c3" + "benchmark_bed.combined.txt:md5,592b2b2af44551686a8057f585309413", + "benchmark_bed.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "benchmark_bed.match.txt:md5,12608858576bec12c65ff338a99803c3", + "benchmark_bed.missing_on_src.txt:md5,7bf2def3eed9eff615a0f29ae1652254" ] ], - "timestamp": "2026-08-04T13:37:52.28474364", + "timestamp": "2026-08-07T16:10:07.404279435", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.0" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index a10ab05..f08f81e 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -26,6 +26,7 @@ "multiqc/multiqc_data/multiqc_rclone_check.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", + "multiqc/multiqc_data/multiqc_rclone_exit_codes.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -65,6 +66,7 @@ "multiqc_rclone_check.txt:md5,4b2a6990836593f69e8e81a82c3daf42", "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", + "multiqc_rclone_exit_codes.txt:md5,ced662f083d7fbc2e5838b4697bcd8db", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", "Illumina_annotation_incorrect.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", "Illumina_annotation_incorrect.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", @@ -74,19 +76,20 @@ "Illumina_annotation_incorrect.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", "Illumina_annotation_incorrect.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", "Illumina_annotation_incorrect.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing.combined.txt:md5,62c42261ec9b9812c862bc2d5e71fd38", + "Illumina_annotation_missing.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", "Illumina_annotation_missing.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", "Illumina_annotation_missing.match.txt:md5,df576e44dfe5a24521997ef162cba157", "Illumina_annotation_missing.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", + "Illumina_annotation_missing.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", "Illumina_annotation_sha_only.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", "Illumina_annotation_sha_only.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", "Illumina_annotation_sha_only.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-04T13:39:20.808292484", + "timestamp": "2026-08-07T16:11:55.119615747", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.0" + "nextflow": "26.04.1" } }, "-profile test edge cases": { @@ -116,6 +119,7 @@ "multiqc/multiqc_data/multiqc_rclone_check.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", + "multiqc/multiqc_data/multiqc_rclone_exit_codes.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -159,6 +163,7 @@ "multiqc_rclone_check.txt:md5,c8f13c10aa4f0e4b356c5c08a9ae7ee9", "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", + "multiqc_rclone_exit_codes.txt:md5,ced662f083d7fbc2e5838b4697bcd8db", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", "Illumina_annotation_incorrect.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", "Illumina_annotation_incorrect.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", @@ -170,19 +175,20 @@ "Illumina_annotation_incorrect.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", "Illumina_annotation_incorrect.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", "Illumina_annotation_incorrect.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing.combined.txt:md5,62c42261ec9b9812c862bc2d5e71fd38", + "Illumina_annotation_missing.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", "Illumina_annotation_missing.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", "Illumina_annotation_missing.match.txt:md5,df576e44dfe5a24521997ef162cba157", "Illumina_annotation_missing.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", + "Illumina_annotation_missing.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", "Illumina_annotation_sha_only.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", "Illumina_annotation_sha_only.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", "Illumina_annotation_sha_only.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-04T13:38:39.104449891", + "timestamp": "2026-08-07T16:10:54.127705046", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.0" + "nextflow": "26.04.1" } } } \ No newline at end of file diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index bc105b5..31005e5 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -26,6 +26,7 @@ "multiqc/multiqc_data/multiqc_rclone_check.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_md5.txt", "multiqc/multiqc_data/multiqc_rclone_checksum_sha.txt", + "multiqc/multiqc_data/multiqc_rclone_exit_codes.txt", "multiqc/multiqc_data/multiqc_samplesheet.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", @@ -51,17 +52,20 @@ "multiqc_rclone_check.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_rclone_checksum_md5.txt:md5,a68bd0275b5b6cb62ec966b68121b0e1", "multiqc_rclone_checksum_sha.txt:md5,03a73f087a286ec6580aada2a5db2e7c", + "multiqc_rclone_exit_codes.txt:md5,2225d8315890c9250549e57575ff5388", "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca", "demultiplex.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", "demultiplex.match.txt:md5,902e4715d579b7f43a5463a220df8db0", - "demultiplex.combined.txt:md5,7c44b320b7f629aaade5c1b6395d6c9b", - "demultiplex.match.txt:md5,644b95db936b45b931143faefb15be7f" + "demultiplex.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", + "demultiplex.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "demultiplex.match.txt:md5,902e4715d579b7f43a5463a220df8db0", + "demultiplex.missing_on_src.txt:md5,b9f072c9e776951c6759590a8259f765" ] ], - "timestamp": "2026-08-04T13:48:52.775725114", + "timestamp": "2026-08-07T16:16:10.761833639", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.0" + "nextflow": "26.04.1" } } } \ No newline at end of file From 4e15bfe3625b330b8b1119d592920d63dac2f89f Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 7 Aug 2026 16:19:59 +0200 Subject: [PATCH 275/334] Fix minor format issues in readme file --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 24a0feb..d5b4495 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,6 @@ Pass an `rclone` configuration with `--rclone_config` whenever a source or desti ## Quick start > [!NOTE] - > If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required. To explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile: @@ -87,11 +86,11 @@ nf-core/datasync was originally written by Alexander Peltzer. We thank the following people for their extensive assistance in the development of this pipeline: -Julian Schwab -Gregor Sturm -Antonia Saracco -Delfina Terradas -Anabella Trigila +- Julian Schwab +- Gregor Sturm +- Antonia Saracco +- Delfina Terradas +- Anabella Trigila ## Contributions and Support From 17d50d8545a454f7d6b81b827947c5b06c803cd5 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 7 Aug 2026 16:30:41 +0200 Subject: [PATCH 276/334] Update changlelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62f8d5e..75ca574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Added` +- [[#79](https://github.com/nf-core/datasync/pull/79)] - Add exit status for `RCLONE` modules in multiqc report ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#74](https://github.com/nf-core/datasync/pull/74)] - Implement warning and `--download` parameter when working with remote directories and SHA checksums ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila), [@apeltzer](https://github.com/apeltzer) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#67](https://github.com/nf-core/datasync/pull/67)] - Copy only files which are successfully validated ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#57](https://github.com/nf-core/datasync/pull/57)] - Add nf-tests with edge cases([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas)). From b41718e20ce24da1cb5195479bac482d76e31902 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 7 Aug 2026 17:42:02 +0200 Subject: [PATCH 277/334] Add module name to prefix and update tests --- conf/modules.config | 2 + tests/default.nf.test.snap | 42 +++++------ tests/edge.nf.test.snap | 140 +++++++++++++++++------------------ tests/main_full.nf.test.snap | 30 ++++---- 4 files changed, 110 insertions(+), 104 deletions(-) diff --git a/conf/modules.config b/conf/modules.config index bc47584..9f1711f 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -20,6 +20,7 @@ process { withName: 'RCLONE_CHECKSUM' { tag = { "${meta.id}_${hash}" } + ext.prefix = { "${meta.id}_checksum_${hash}" } ext.args = { def base_args = [ '--no-check-certificate' @@ -62,6 +63,7 @@ process { } withName: 'RCLONE_CHECK' { + ext.prefix = { "${meta.id}_check" } ext.args = { def base_args = [ '--no-check-certificate', diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 94cd3ee..0d7b7a1 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -35,20 +35,20 @@ "rclone", "rclone/check", "rclone/check/Illumina_annotation", - "rclone/check/Illumina_annotation/Illumina_annotation.combined.txt", - "rclone/check/Illumina_annotation/Illumina_annotation.match.txt", + "rclone/check/Illumina_annotation/Illumina_annotation_check.combined.txt", + "rclone/check/Illumina_annotation/Illumina_annotation_check.match.txt", "rclone/check/benchmark_bed", - "rclone/check/benchmark_bed/benchmark_bed.combined.txt", - "rclone/check/benchmark_bed/benchmark_bed.match.txt", + "rclone/check/benchmark_bed/benchmark_bed_check.combined.txt", + "rclone/check/benchmark_bed/benchmark_bed_check.match.txt", "rclone/checksum", "rclone/checksum/Illumina_annotation", - "rclone/checksum/Illumina_annotation/Illumina_annotation.combined.txt", - "rclone/checksum/Illumina_annotation/Illumina_annotation.match.txt", + "rclone/checksum/Illumina_annotation/Illumina_annotation_checksum_MD5.combined.txt", + "rclone/checksum/Illumina_annotation/Illumina_annotation_checksum_MD5.match.txt", "rclone/checksum/benchmark_bed", - "rclone/checksum/benchmark_bed/benchmark_bed.combined.txt", - "rclone/checksum/benchmark_bed/benchmark_bed.exit_code.txt", - "rclone/checksum/benchmark_bed/benchmark_bed.match.txt", - "rclone/checksum/benchmark_bed/benchmark_bed.missing_on_src.txt", + "rclone/checksum/benchmark_bed/benchmark_bed_checksum_MD5.combined.txt", + "rclone/checksum/benchmark_bed/benchmark_bed_checksum_MD5.exit_code.txt", + "rclone/checksum/benchmark_bed/benchmark_bed_checksum_MD5.match.txt", + "rclone/checksum/benchmark_bed/benchmark_bed_checksum_MD5.missing_on_src.txt", "rclone/copy", "rclone/copy/Illumina_annotation-rclone-copy.log", "rclone/copy/benchmark_bed-rclone-copy.log" @@ -59,19 +59,19 @@ "multiqc_rclone_checksum_md5.txt:md5,c7127de966d1be295ef6697dba648c79", "multiqc_rclone_exit_codes.txt:md5,b4733136a04fe8e27f0679906ef6bdfc", "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4", - "Illumina_annotation.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "benchmark_bed.combined.txt:md5,dcd2c539696adba720986251dcd1aaef", - "benchmark_bed.match.txt:md5,12608858576bec12c65ff338a99803c3", - "Illumina_annotation.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "benchmark_bed.combined.txt:md5,592b2b2af44551686a8057f585309413", - "benchmark_bed.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "benchmark_bed.match.txt:md5,12608858576bec12c65ff338a99803c3", - "benchmark_bed.missing_on_src.txt:md5,7bf2def3eed9eff615a0f29ae1652254" + "Illumina_annotation_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "benchmark_bed_check.combined.txt:md5,dcd2c539696adba720986251dcd1aaef", + "benchmark_bed_check.match.txt:md5,12608858576bec12c65ff338a99803c3", + "Illumina_annotation_checksum_MD5.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_checksum_MD5.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "benchmark_bed_checksum_MD5.combined.txt:md5,592b2b2af44551686a8057f585309413", + "benchmark_bed_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "benchmark_bed_checksum_MD5.match.txt:md5,12608858576bec12c65ff338a99803c3", + "benchmark_bed_checksum_MD5.missing_on_src.txt:md5,7bf2def3eed9eff615a0f29ae1652254" ] ], - "timestamp": "2026-08-07T16:10:07.404279435", + "timestamp": "2026-08-07T17:29:56.049522268", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index f08f81e..a92f2f1 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -36,27 +36,27 @@ "rclone", "rclone/check", "rclone/check/Illumina_annotation_incorrect", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt", "rclone/check/Illumina_annotation_missing", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt", "rclone/checksum", "rclone/checksum/Illumina_annotation_incorrect", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.differ.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.exit_code.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt", "rclone/checksum/Illumina_annotation_missing", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.exit_code.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_src.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt", "rclone/checksum/Illumina_annotation_sha_only", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.exit_code.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt", "rclone/copy", "rclone/copy/Illumina_annotation_incorrect-rclone-copy.log", "rclone/copy/Illumina_annotation_missing-rclone-copy.log" @@ -68,25 +68,25 @@ "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_rclone_exit_codes.txt:md5,ced662f083d7fbc2e5838b4697bcd8db", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", - "Illumina_annotation_incorrect.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_incorrect.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_missing.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_missing.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_incorrect.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", - "Illumina_annotation_incorrect.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", - "Illumina_annotation_incorrect.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "Illumina_annotation_incorrect.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", - "Illumina_annotation_missing.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "Illumina_annotation_missing.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", - "Illumina_annotation_missing.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", - "Illumina_annotation_sha_only.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", - "Illumina_annotation_sha_only.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_sha_only.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" + "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_missing_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_missing_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_incorrect_checksum_MD5.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", + "Illumina_annotation_incorrect_checksum_MD5.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_incorrect_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_incorrect_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing_checksum_MD5.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", + "Illumina_annotation_missing_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_missing_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", + "Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_sha_only_checksum_SHA256.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", + "Illumina_annotation_sha_only_checksum_SHA256.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-07T16:11:55.119615747", + "timestamp": "2026-08-07T17:35:07.085224284", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" @@ -129,30 +129,30 @@ "rclone", "rclone/check", "rclone/check/Illumina_annotation_incorrect", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", - "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.combined.txt", + "rclone/check/Illumina_annotation_incorrect/Illumina_annotation_incorrect_check.match.txt", "rclone/check/Illumina_annotation_missing", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", - "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.combined.txt", + "rclone/check/Illumina_annotation_missing/Illumina_annotation_missing_check.match.txt", "rclone/check/Illumina_annotation_sha_only", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", - "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only.match.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.combined.txt", + "rclone/check/Illumina_annotation_sha_only/Illumina_annotation_sha_only_check.match.txt", "rclone/checksum", "rclone/checksum/Illumina_annotation_incorrect", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.combined.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.differ.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.exit_code.txt", - "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect.match.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.combined.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.differ.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.exit_code.txt", + "rclone/checksum/Illumina_annotation_incorrect/Illumina_annotation_incorrect_checksum_MD5.match.txt", "rclone/checksum/Illumina_annotation_missing", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.combined.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.exit_code.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.match.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_dst.txt", - "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing.missing_on_src.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.combined.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.exit_code.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.match.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt", + "rclone/checksum/Illumina_annotation_missing/Illumina_annotation_missing_checksum_MD5.missing_on_src.txt", "rclone/checksum/Illumina_annotation_sha_only", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.combined.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.differ.txt", - "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only.exit_code.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.combined.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.differ.txt", + "rclone/checksum/Illumina_annotation_sha_only/Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt", "rclone/copy", "rclone/copy/Illumina_annotation_incorrect-rclone-copy.log", "rclone/copy/Illumina_annotation_missing-rclone-copy.log", @@ -165,27 +165,27 @@ "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", "multiqc_rclone_exit_codes.txt:md5,ced662f083d7fbc2e5838b4697bcd8db", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", - "Illumina_annotation_incorrect.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_incorrect.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_missing.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_missing.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_sha_only.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", - "Illumina_annotation_sha_only.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_incorrect.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", - "Illumina_annotation_incorrect.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", - "Illumina_annotation_incorrect.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "Illumina_annotation_incorrect.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", - "Illumina_annotation_missing.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "Illumina_annotation_missing.match.txt:md5,df576e44dfe5a24521997ef162cba157", - "Illumina_annotation_missing.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", - "Illumina_annotation_missing.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", - "Illumina_annotation_sha_only.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", - "Illumina_annotation_sha_only.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", - "Illumina_annotation_sha_only.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" + "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_missing_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_missing_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", + "Illumina_annotation_sha_only_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_incorrect_checksum_MD5.combined.txt:md5,34ecbd1fa8f707c75898ee45cadf45d6", + "Illumina_annotation_incorrect_checksum_MD5.differ.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_incorrect_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_incorrect_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing_checksum_MD5.combined.txt:md5,4030b978509bbd39819efab4d91d7f32", + "Illumina_annotation_missing_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "Illumina_annotation_missing_checksum_MD5.match.txt:md5,df576e44dfe5a24521997ef162cba157", + "Illumina_annotation_missing_checksum_MD5.missing_on_dst.txt:md5,793e4b78c8b125e4421cb20ed0c232d5", + "Illumina_annotation_missing_checksum_MD5.missing_on_src.txt:md5,e5fdf362a1dc4ac877f92ee769e47fd8", + "Illumina_annotation_sha_only_checksum_SHA256.combined.txt:md5,0d2bc4aeee4fded37d5cfebfadfb2fd2", + "Illumina_annotation_sha_only_checksum_SHA256.differ.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", + "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-07T16:10:54.127705046", + "timestamp": "2026-08-07T17:34:27.914054654", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 31005e5..8dce7c2 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -36,14 +36,16 @@ "rclone", "rclone/check", "rclone/check/demultiplex", - "rclone/check/demultiplex/demultiplex.combined.txt", - "rclone/check/demultiplex/demultiplex.match.txt", + "rclone/check/demultiplex/demultiplex_check.combined.txt", + "rclone/check/demultiplex/demultiplex_check.match.txt", "rclone/checksum", "rclone/checksum/demultiplex", - "rclone/checksum/demultiplex/demultiplex.combined.txt", - "rclone/checksum/demultiplex/demultiplex.exit_code.txt", - "rclone/checksum/demultiplex/demultiplex.match.txt", - "rclone/checksum/demultiplex/demultiplex.missing_on_src.txt", + "rclone/checksum/demultiplex/demultiplex_checksum_MD5.combined.txt", + "rclone/checksum/demultiplex/demultiplex_checksum_MD5.exit_code.txt", + "rclone/checksum/demultiplex/demultiplex_checksum_MD5.match.txt", + "rclone/checksum/demultiplex/demultiplex_checksum_MD5.missing_on_src.txt", + "rclone/checksum/demultiplex/demultiplex_checksum_SHA256.combined.txt", + "rclone/checksum/demultiplex/demultiplex_checksum_SHA256.match.txt", "rclone/copy", "rclone/copy/demultiplex-rclone-copy.log" ], @@ -54,15 +56,17 @@ "multiqc_rclone_checksum_sha.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_rclone_exit_codes.txt:md5,2225d8315890c9250549e57575ff5388", "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca", - "demultiplex.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", - "demultiplex.match.txt:md5,902e4715d579b7f43a5463a220df8db0", - "demultiplex.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", - "demultiplex.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", - "demultiplex.match.txt:md5,902e4715d579b7f43a5463a220df8db0", - "demultiplex.missing_on_src.txt:md5,b9f072c9e776951c6759590a8259f765" + "demultiplex_check.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", + "demultiplex_check.match.txt:md5,902e4715d579b7f43a5463a220df8db0", + "demultiplex_checksum_MD5.combined.txt:md5,9250a5e20244b4beb397eab1a2003c3a", + "demultiplex_checksum_MD5.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1", + "demultiplex_checksum_MD5.match.txt:md5,644b95db936b45b931143faefb15be7f", + "demultiplex_checksum_MD5.missing_on_src.txt:md5,b9f072c9e776951c6759590a8259f765", + "demultiplex_checksum_SHA256.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", + "demultiplex_checksum_SHA256.match.txt:md5,902e4715d579b7f43a5463a220df8db0" ] ], - "timestamp": "2026-08-07T16:16:10.761833639", + "timestamp": "2026-08-07T17:39:25.926149676", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From 442e237dc88c4420cb9f981b12fc0263b8c80150 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 7 Aug 2026 18:03:46 +0200 Subject: [PATCH 278/334] Bugfix: Add hash to module name in exit code summary --- workflows/datasync.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 643f029..fb2ee3a 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -164,7 +164,7 @@ workflow DATASYNC { RCLONE_CHECK.out.exit_code .map { meta, exit_file -> [ meta, exit_file, "CHECK" ] } .mix(RCLONE_CHECKSUM.out.exit_code - .map { meta, exit_file -> [ meta, exit_file, "CHECKSUM" ] } + .map { meta, exit_file -> [ meta, exit_file, "CHECKSUM_${meta.check_format.toUpperCase()}" ] } ) .map { meta, exit_file, module -> createExitSummary(meta, exit_file, module) From 16eade4000b7e32d70148cf3f98fef75196a35a6 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 7 Aug 2026 18:15:11 +0200 Subject: [PATCH 279/334] Update snapshots --- tests/default.nf.test.snap | 4 ++-- tests/edge.nf.test.snap | 8 ++++---- tests/main_full.nf.test.snap | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 0d7b7a1..abec1e6 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -57,7 +57,7 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_rclone_check.txt:md5,f9dc48d3c4d35cd7297b0a16227c3bcd", "multiqc_rclone_checksum_md5.txt:md5,c7127de966d1be295ef6697dba648c79", - "multiqc_rclone_exit_codes.txt:md5,b4733136a04fe8e27f0679906ef6bdfc", + "multiqc_rclone_exit_codes.txt:md5,f50e1acf7abee71274f0f92508576cb1", "multiqc_samplesheet.txt:md5,373d903a41ab29bd26db35a3041626e4", "Illumina_annotation_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", "Illumina_annotation_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", @@ -71,7 +71,7 @@ "benchmark_bed_checksum_MD5.missing_on_src.txt:md5,7bf2def3eed9eff615a0f29ae1652254" ] ], - "timestamp": "2026-08-07T17:29:56.049522268", + "timestamp": "2026-08-07T18:08:21.744003325", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index a92f2f1..115ad6e 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -66,7 +66,7 @@ "multiqc_rclone_check.txt:md5,4b2a6990836593f69e8e81a82c3daf42", "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", - "multiqc_rclone_exit_codes.txt:md5,ced662f083d7fbc2e5838b4697bcd8db", + "multiqc_rclone_exit_codes.txt:md5,e72c745debdc6ed04aa9b13b068d897c", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", @@ -86,7 +86,7 @@ "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-07T17:35:07.085224284", + "timestamp": "2026-08-07T18:09:48.856944607", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" @@ -163,7 +163,7 @@ "multiqc_rclone_check.txt:md5,c8f13c10aa4f0e4b356c5c08a9ae7ee9", "multiqc_rclone_checksum_md5.txt:md5,40ef26b67a9f5c4943a12d412f4e632f", "multiqc_rclone_checksum_sha.txt:md5,8d38305a4ad03c7ea18aa9827d34a396", - "multiqc_rclone_exit_codes.txt:md5,ced662f083d7fbc2e5838b4697bcd8db", + "multiqc_rclone_exit_codes.txt:md5,e72c745debdc6ed04aa9b13b068d897c", "multiqc_samplesheet.txt:md5,bbfc817ff43c49cde14a2b33f46b5ae5", "Illumina_annotation_incorrect_check.combined.txt:md5,bbb93addf748c7c6cbe5ad1e25bf54bb", "Illumina_annotation_incorrect_check.match.txt:md5,eb40be996bfbcf8070103efaa6bfa4c5", @@ -185,7 +185,7 @@ "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-07T17:34:27.914054654", + "timestamp": "2026-08-07T18:08:58.211993458", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index 8dce7c2..d2a80b0 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -54,7 +54,7 @@ "multiqc_rclone_check.txt:md5,03a73f087a286ec6580aada2a5db2e7c", "multiqc_rclone_checksum_md5.txt:md5,a68bd0275b5b6cb62ec966b68121b0e1", "multiqc_rclone_checksum_sha.txt:md5,03a73f087a286ec6580aada2a5db2e7c", - "multiqc_rclone_exit_codes.txt:md5,2225d8315890c9250549e57575ff5388", + "multiqc_rclone_exit_codes.txt:md5,9bf4a8961b2d370bb06a09ccf65e0f7e", "multiqc_samplesheet.txt:md5,00788a52d1a014c12ac4ed554b0b44ca", "demultiplex_check.combined.txt:md5,3ae32d27ed8a8e14c3b9b954e23c3839", "demultiplex_check.match.txt:md5,902e4715d579b7f43a5463a220df8db0", @@ -66,7 +66,7 @@ "demultiplex_checksum_SHA256.match.txt:md5,902e4715d579b7f43a5463a220df8db0" ] ], - "timestamp": "2026-08-07T17:39:25.926149676", + "timestamp": "2026-08-07T18:14:55.558259399", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.1" From 7d1f26d968efa58207e86f681fd0945f469db8b1 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Fri, 7 Aug 2026 21:39:47 +0200 Subject: [PATCH 280/334] Add validation summary section to output documentation --- assets/multiqc_config.yml | 2 +- .../images/datasync-multiqc-exit-code-table.png | Bin 0 -> 56782 bytes docs/output.md | 9 +++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 docs/images/datasync-multiqc-exit-code-table.png diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index f67271f..b8543cb 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -45,7 +45,7 @@ custom_data: rclone_exit_codes: section_name: "Validation Summary" description: > - This table summarizes the exit codes returned by `RCLONE_CHECK` and `RCLONE_CHECKSUM` for each processed sample. Reviewing these exit codes + This table summarises the exit codes returned by `RCLONE_CHECK` and `RCLONE_CHECKSUM` for each processed sample. Reviewing these exit codes can help identify files that were not successfully validated or where unexpected errors occurred during integrity checking plot_type: "table" file_format: "tsv" diff --git a/docs/images/datasync-multiqc-exit-code-table.png b/docs/images/datasync-multiqc-exit-code-table.png new file mode 100644 index 0000000000000000000000000000000000000000..56d0c604e0aa07557873f9ae6c127391b34dd9bb GIT binary patch literal 56782 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 Date: Tue, 18 Aug 2026 13:57:53 +0000 Subject: [PATCH 281/334] Bump version --- .nf-core.yml | 2 +- CHANGELOG.md | 2 +- assets/multiqc_config.yml | 4 +-- nextflow.config | 2 +- ro-crate-metadata.json | 76 +++++++++++++++++++++++++++++++++------ 5 files changed, 69 insertions(+), 17 deletions(-) diff --git a/.nf-core.yml b/.nf-core.yml index da73ac4..a238791 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -8,7 +8,7 @@ template: name: datasync org: nf-core outdir: . - version: 1.0dev + version: 1.0.0 lint: multiqc_config: false files_exist: diff --git a/CHANGELOG.md b/CHANGELOG.md index 75ca574..1cc6cc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v1.0dev - [date] +## v1.0.0 - [date] Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re/) template. diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index b8543cb..e41beed 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,5 @@ report_comment: > - This report has been generated by the
    nf-core/datasync - analysis pipeline. For information about how to interpret these results, please see the - documentation. + This report has been generated by the nf-core/datasync analysis pipeline. For information about how to interpret these results, please see the documentation. report_section_order: "nf-core-datasync-methods-description": order: -1000 diff --git a/nextflow.config b/nextflow.config index e113e2e..3009c97 100644 --- a/nextflow.config +++ b/nextflow.config @@ -292,7 +292,7 @@ manifest { mainScript = 'main.nf' defaultBranch = 'main' nextflowVersion = '!>=25.10.4' - version = '1.0dev' + version = '1.0.0' doi = '' } diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index cf4913a..c64671d 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -21,9 +21,9 @@ { "@id": "./", "@type": "Dataset", - "creativeWorkStatus": "InProgress", - "datePublished": "2026-07-24T12:35:36+00:00", - "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\n\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\nJulian Schwab\nGregor Sturm\nAntonia Saracco\nDelfina Terradas\nAnabella Trigila\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\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", + "creativeWorkStatus": "Stable", + "datePublished": "2026-08-18T13:53:53+00:00", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/datasync)\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3)\n\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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a Nextflow pipeline for copying files and directories between storage locations and documenting their integrity. For every row in an input samplesheet, the pipeline:\n\n1. validates the source against a supplied MD5 and/or SHA-256 checksum manifest using [`rclone checksum`](https://rclone.org/commands/rclone_checksum/);\n2. copies the source to the requested destination with [`rclone copy`](https://rclone.org/);\n3. compares the copied data with the source using [`rclone check`](https://rclone.org/commands/rclone_check/); and\n4. produces detailed `rclone` status files and a consolidated MultiQC report.\n\nSources and destinations may be local paths, HTTP(S) URLs, or rclone-supported remote storage such as Amazon S3, S3-compatible object storage, or Azure Blob Storage.\n\nThe current tested use case for this pipeline is transfer between S3 buckets.\n\nPass an `rclone` configuration with `--rclone_config` whenever a source or destination needs a configured remote, endpoint, or credentials. A single configuration file can contain separate named remotes for multiple providers; for non-S3 layouts, design and validate the provider-specific configuration using the upstream [rclone documentation](https://rclone.org/docs/).\n\n![nf-core/datasync metro map](docs/images/datasync-metromap.png)\n\n## Quick start\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, see the [nf-core environment setup guide](https://nf-co.re/docs/get_started/environment_setup/overview). Nextflow 25.10.4 or later is required.\n\nTo explore the pipeline outputs before preparing your own data, run the bundled `test` profile with a container profile:\n\n```bash\nnextflow run nf-core/datasync \\\n -profile test,docker \\\n --outdir results\n```\n\nThe `test` profile supplies a small samplesheet and `rclone` configuration automatically. It also enables `--rclone_dry_run`, so no files are actually transferred. This makes it useful for exploring the `rclone/` output folders and `multiqc/multiqc_report.html`; remember that post-copy comparison reports describe whatever is already present at the destination because the dry run does not write transfer data.\n\nTo run the pipeline on your own data, create a samplesheet containing one transfer per row:\n\n```csv\nsample,input,output_path,checksum_md5,checksum_sha\nrun_001,/data/run_001,s3://archive/runs,/data/manifests/run_001_md5.tsv\nreference,https://example.org/reference.fa,/data/references,,/data/manifests/reference_sha256.tsv\n```\n\nThen launch the pipeline using:\n\n```bash\nnextflow run nf-core/datasync \\\n -r \\\n -profile docker \\\n --input samplesheet.csv \\\n --outdir results \\\n --rclone_config /path/to/rclone.conf\n```\n\n`--rclone_config` is optional only when every source and destination is accessible without a configured rclone remote. See the [`rclone` configuration section](docs/usage.md#configuring-rclone-remotes) for the tested S3-to-S3 use case and guidance on adapting rclone configuration files for other providers. To preview copy operations without transferring data, add `--rclone_dry_run`; note that subsequent comparison reports will then describe the unchanged destination.\n\nSee the [usage documentation](docs/usage.md) for samplesheet rules, destination semantics, remote configuration, and reproducible execution. The complete generated parameter reference is available on the [nf-core pipeline page](https://nf-co.re/datasync/parameters).\n\n## Pipeline output\n\nResults are written below `--outdir`. See the [output documentation](docs/output.md) for file names and status-code interpretation.\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n- Julian Schwab\n- Gregor Sturm\n- Antonia Saracco\n- Delfina Terradas\n- Anabella Trigila\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\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", "hasPart": [ { "@id": "main.nf" @@ -31,6 +31,9 @@ { "@id": "assets/" }, + { + "@id": "bin/" + }, { "@id": "conf/" }, @@ -99,7 +102,7 @@ }, "mentions": [ { - "@id": "#48344b18-cfae-44a4-ad69-b23734224749" + "@id": "#e63d4c18-24de-41a5-bc4a-600d20b57fe5" } ], "name": "nf-core/datasync" @@ -126,13 +129,30 @@ "SoftwareSourceCode", "ComputationalWorkflow" ], - "contributor": [ + "author": [ { "@id": "https://orcid.org/0000-0002-6503-2180" + }, + { + "@id": "#39fa8409-1f04-4472-9f46-7d3b03303768" + }, + { + "@id": "https://orcid.org/0000-0001-9584-7842" + } + ], + "contributor": [ + { + "@id": "#be129ed0-c83e-444b-85dd-6db2c42dc277" + }, + { + "@id": "#b293152b-1358-4678-a5a5-8603ccb89cd0" + }, + { + "@id": "#6e1f504a-fae3-4fca-a7b7-8d84fff28bbd" } ], "dateCreated": "", - "dateModified": "2026-07-24T12:35:36Z", + "dateModified": "2026-08-18T13:53:53Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": [ "nf-core", @@ -152,10 +172,10 @@ }, "url": [ "https://github.com/nf-core/datasync", - "https://nf-co.re/datasync/dev/" + "https://nf-co.re/datasync/1.0.0/" ], "version": [ - "1.0dev" + "1.0.0" ] }, { @@ -171,11 +191,11 @@ "version": "!>=25.10.4" }, { - "@id": "#48344b18-cfae-44a4-ad69-b23734224749", + "@id": "#e63d4c18-24de-41a5-bc4a-600d20b57fe5", "@type": "TestSuite", "instance": [ { - "@id": "#867a3285-b1be-4cd0-8b71-8341c5d037f8" + "@id": "#70a7c21e-2e03-48b3-bf84-601b6e12abd9" } ], "mainEntity": { @@ -184,7 +204,7 @@ "name": "Test suite for nf-core/datasync" }, { - "@id": "#867a3285-b1be-4cd0-8b71-8341c5d037f8", + "@id": "#70a7c21e-2e03-48b3-bf84-601b6e12abd9", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/datasync", "resource": "repos/nf-core/datasync/actions/workflows/nf-test.yml", @@ -206,6 +226,11 @@ "@type": "Dataset", "description": "Additional files" }, + { + "@id": "bin/", + "@type": "Dataset", + "description": "Scripts that must be callable from a pipeline process" + }, { "@id": "conf/", "@type": "Dataset", @@ -317,6 +342,35 @@ "@type": "Person", "email": "alexander.peltzer@boehringer-ingelheim.com", "name": "Alexander Peltzer" + }, + { + "@id": "#be129ed0-c83e-444b-85dd-6db2c42dc277", + "@type": "Person", + "email": "antonia.saracco@zs.com", + "name": "Antonia Saracco" + }, + { + "@id": "#b293152b-1358-4678-a5a5-8603ccb89cd0", + "@type": "Person", + "email": "155591053+delfiterradas@users.noreply.github.com", + "name": "Delfina Terradas" + }, + { + "@id": "#6e1f504a-fae3-4fca-a7b7-8d84fff28bbd", + "@type": "Person", + "email": "18577080+atrigila@users.noreply.github.com", + "name": "Anabella Trigila" + }, + { + "@id": "#39fa8409-1f04-4472-9f46-7d3b03303768", + "@type": "Person", + "name": "Julian Schwab" + }, + { + "@id": "https://orcid.org/0000-0001-9584-7842", + "@type": "Person", + "email": "mail@gregor-sturm.de", + "name": "Gregor Sturm" } ] } \ No newline at end of file From b17c85c239032eb671edca3a7f4bac6fde4cc4b0 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:10:05 +0000 Subject: [PATCH 282/334] Fix linting --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- nextflow.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d43c74d..87aab4d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). diff --git a/nextflow.config b/nextflow.config index 3009c97..274b93f 100644 --- a/nextflow.config +++ b/nextflow.config @@ -183,7 +183,7 @@ includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !pa // Load nf-core/datasync custom profiles from nf-core/configs when available. -// includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !params.custom_config_base.startsWith('http')) ? "${params.custom_config_base}/pipeline/datasync.config" : "/dev/null" +includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !params.custom_config_base.startsWith('http')) ? "${params.custom_config_base}/pipeline/datasync.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 From 220c860edb14bf6194beac8ea87a699d94c1501e Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:10:21 +0000 Subject: [PATCH 283/334] Add release dat to changlelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cc6cc8..b2fe9b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v1.0.0 - [date] +## v1.0.0 - 2026-08-20 Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re/) template. From bdf1f34129a6b350e31072ccae6e7250267ddebd Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:17:38 +0000 Subject: [PATCH 284/334] Update tests --- tests/default.nf.test.snap | 6 +++--- tests/edge.nf.test.snap | 12 ++++++------ tests/main_full.nf.test.snap | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index abec1e6..a7a2cd2 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -12,7 +12,7 @@ "rclone": "1.65.0-DEV" }, "Workflow": { - "nf-core/datasync": "v1.0dev" + "nf-core/datasync": "v1.0.0" } }, [ @@ -71,10 +71,10 @@ "benchmark_bed_checksum_MD5.missing_on_src.txt:md5,7bf2def3eed9eff615a0f29ae1652254" ] ], - "timestamp": "2026-08-07T18:08:21.744003325", + "timestamp": "2026-08-18T14:12:12.191208475", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.6" } } } \ No newline at end of file diff --git a/tests/edge.nf.test.snap b/tests/edge.nf.test.snap index 115ad6e..66deaa7 100644 --- a/tests/edge.nf.test.snap +++ b/tests/edge.nf.test.snap @@ -12,7 +12,7 @@ "rclone": "1.65.0-DEV" }, "Workflow": { - "nf-core/datasync": "v1.0dev" + "nf-core/datasync": "v1.0.0" } }, [ @@ -86,10 +86,10 @@ "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-07T18:09:48.856944607", + "timestamp": "2026-08-18T14:13:27.670540243", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.6" } }, "-profile test edge cases": { @@ -105,7 +105,7 @@ "rclone": "1.65.0-DEV" }, "Workflow": { - "nf-core/datasync": "v1.0dev" + "nf-core/datasync": "v1.0.0" } }, [ @@ -185,10 +185,10 @@ "Illumina_annotation_sha_only_checksum_SHA256.exit_code.txt:md5,b026324c6904b2a9cb4b88d6d61c81d1" ] ], - "timestamp": "2026-08-07T18:08:58.211993458", + "timestamp": "2026-08-18T14:12:50.690727768", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.6" } } } \ No newline at end of file diff --git a/tests/main_full.nf.test.snap b/tests/main_full.nf.test.snap index d2a80b0..40952d5 100644 --- a/tests/main_full.nf.test.snap +++ b/tests/main_full.nf.test.snap @@ -12,7 +12,7 @@ "rclone": "1.65.0-DEV" }, "Workflow": { - "nf-core/datasync": "v1.0dev" + "nf-core/datasync": "v1.0.0" } }, [ @@ -66,10 +66,10 @@ "demultiplex_checksum_SHA256.match.txt:md5,902e4715d579b7f43a5463a220df8db0" ] ], - "timestamp": "2026-08-07T18:14:55.558259399", + "timestamp": "2026-08-18T14:16:39.079934709", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.04.6" } } } \ No newline at end of file From 23ae865c6a1eb84db76b84876c14eaf05d7174e8 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:44:43 +0000 Subject: [PATCH 285/334] Fix linting --- workflows/datasync.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index fb2ee3a..83a571c 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -173,7 +173,7 @@ workflow DATASYNC { seed: "Row\tSample\tModule\tExit code", sort: false, newLine: true - ) { meta, exit_code -> + ) { _meta, exit_code -> return [ "rclone_exit_codes.tsv", exit_code ] } ) From 3d999431362228cbe0c64da2a1dfdac283b58788 Mon Sep 17 00:00:00 2001 From: Delfina Terradas <155591053+delfiterradas@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:10:54 -0300 Subject: [PATCH 286/334] Update PR template links to use master branch --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 87aab4d..d43c74d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,14 +8,14 @@ These are the most common things requested on pull requests (PRs). Remember that PRs should be made against the dev branch, unless you're preparing a pipeline release. -Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) +Learn more about contributing: [CONTRIBUTING.md](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) --> ## PR checklist - [ ] This comment contains a description of changes (with reason). - [ ] If you've fixed a bug or added code that should be tested, add tests! -- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/main/docs/CONTRIBUTING.md) +- [ ] If you've added a new tool - have you followed the pipeline conventions in the [contribution docs](https://github.com/nf-core/datasync/tree/master/docs/CONTRIBUTING.md) - [ ] If necessary, also make a PR on the nf-core/datasync _branch_ on the [nf-core/test-datasets](https://github.com/nf-core/test-datasets) repository. - [ ] Make sure your code lints (`nf-core pipelines lint`). - [ ] Ensure the test suite passes (`nextflow run . -profile test,docker --outdir `). From fb32bbf5531ed8bf3adf0dfe9feb88bd7ea0ecfe Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 20 Aug 2026 19:28:43 +0200 Subject: [PATCH 287/334] Add apptainer version to avoid error in CI test --- .github/actions/nf-test/action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/actions/nf-test/action.yml b/.github/actions/nf-test/action.yml index 945c56f..886a8b3 100644 --- a/.github/actions/nf-test/action.yml +++ b/.github/actions/nf-test/action.yml @@ -38,6 +38,8 @@ runs: - name: Setup apptainer if: contains(inputs.profile, 'singularity') uses: eWaterCycle/setup-apptainer@4bb22c52d4f63406c49e94c804632975787312b3 # v2.0.0 + with: + apptainer-version: 1.4.5 - name: Set up Singularity if: contains(inputs.profile, 'singularity') From 7bc7797cc859135470a5c9e97a52b93b7034ce18 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Thu, 20 Aug 2026 19:38:22 +0200 Subject: [PATCH 288/334] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2fe9b8..6943092 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re ### `Fixed` +- [[#83](https://github.com/nf-core/datasync/pull/83)] - Add apptainer version to avoid error in CI test ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila)). - [[#78](https://github.com/nf-core/datasync/pull/78)] - Fixed linting issues reported by nf-core and Nextflow, and updated `rclone` modules and nf-tests to sort generated report files for deterministic snapshots ([@atrigila](https://github.com/atrigila), review by [@delfiterradas](https://github.com/delfiterradas) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#76](https://github.com/nf-core/datasync/pull/76)] - Remove `--one-way` from rclone/checksum confi ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). - [[#73](https://github.com/nf-core/datasync/pull/73)] - Create tmp `files_to_copy.tx` avoiding error with write permissions in work directory ([@delfiterradas](https://github.com/delfiterradas), review by [@atrigila](https://github.com/atrigila) and [@antoniasaracco](https://github.com/antoniasaracco)). From 671114865d0141d35945f9630efd7befbf44fd51 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 25 Aug 2026 15:46:42 +0200 Subject: [PATCH 289/334] Make sample column a unique entry --- assets/schema_input.json | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/schema_input.json b/assets/schema_input.json index 0eff487..424ec88 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -4,6 +4,7 @@ "title": "nf-core/datasync pipeline - params.input schema", "description": "Schema for the file provided with params.input", "type": "array", + "uniqueEntries": ["sample"], "items": { "type": "object", "properties": { From 229af6b2b6726f1739ba7d49f0d13899ff6f7d03 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 25 Aug 2026 15:56:01 +0200 Subject: [PATCH 290/334] Avoid silenlty dropping samples --- workflows/datasync.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 83a571c..92762f4 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -137,7 +137,7 @@ workflow DATASYNC { // Wait for file copy to finish before running RCLONE_CHECK ch_rclone_check = ch_samplesheet.rclone - .join(RCLONE_COPY.out.log) + .join(RCLONE_COPY.out.log, remainder: true) .map { meta, input, output, _log -> [ meta, input, output ] } // From c14cd93c5d5ba5d0b7d5c4453f5ef549298d5cb2 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 25 Aug 2026 16:20:46 +0200 Subject: [PATCH 291/334] Move samplesheet validation to utils subworkflow and get a single warning instead of one per row --- .../utils_nfcore_datasync_pipeline/main.nf | 22 +++++++++++++++++++ workflows/datasync.nf | 8 ------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 0884ac5..9513321 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -170,6 +170,28 @@ workflow PIPELINE_COMPLETION { // Check and validate pipeline parameters // def validateInputParameters() { + + def samples = samplesheetToList(params.input, "${projectDir}/assets/schema_input.json") + + def requires_download = samples.any { meta, input_path, output_path, md5, sha -> + sha && input_path.contains('://') + } + + if (requires_download && params.download) { + log.warn( + "The `--download` parameter is enabled. `RCLONE_CHECKSUM` will download remote files. " + + "Make sure this is what you want, as it may incur substantial cloud costs!" + ) + } + + if (requires_download && !params.download) { + log.error( + "A SHA checksum file was provided for one or more remote files, but `--download` " + + "is not enabled. `RCLONE_CHECKSUM` cannot verify SHA256 checksums for remote files " + + "without downloading them. Enable `--download` to proceed." + ) + exit 1 + } } // diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 92762f4..80dcb9c 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -39,14 +39,6 @@ workflow DATASYNC { ch_samplesheet = ch_samplesheet.multiMap { meta, input_path, output_path, md5, sha -> - if (sha && input_path.contains('://')) { - if (params.download) { - log.warn("The `--download` parameter is enabled. `RCLONE_CHECKSUM` will download remote files. Make sure this is what you want, as it may incur substantial cloud costs !") - } else { - throw new IllegalArgumentException("A SHA checksum file was provided, but `--download` is not enabled. `RCLONE_CHECKSUM` cannot verify SHA256 checksums for remote files without downloading them. Enable `--download` to proceed.") - } - } - def source = file(input_path) def source_uri = source.toUriString() From 26f7d59942a22741126ff342bf5bdd462f5f0f05 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 25 Aug 2026 20:09:50 +0200 Subject: [PATCH 292/334] Skip RCLONE_COPY if there are no files in common in files_to_copy --- workflows/datasync.nf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 80dcb9c..31f7758 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -107,6 +107,10 @@ workflow DATASYNC { .collect { file_to_copy -> file_to_copy.readLines() } .inject { a, b -> a.intersect(b) } + if (!common) { + return null + } + def copy_files = java.nio.file.Files.createTempFile( "${meta.id}_files_to_copy_", ".txt" @@ -115,6 +119,7 @@ workflow DATASYNC { tuple(meta, copy_files) } + .filter { it != null } ch_rclone_copy = ch_samplesheet.rclone .join(files_to_copy) From 2194875954162249e8f4dfe261468e690b1d9650 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 25 Aug 2026 21:22:35 +0200 Subject: [PATCH 293/334] Modify regex to capture inputs with ":" --- subworkflows/local/utils_nfcore_datasync_pipeline/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 9513321..9285f83 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -174,7 +174,7 @@ def validateInputParameters() { def samples = samplesheetToList(params.input, "${projectDir}/assets/schema_input.json") def requires_download = samples.any { meta, input_path, output_path, md5, sha -> - sha && input_path.contains('://') + sha && (input_path ==~ /^[a-zA-Z][a-zA-Z0-9+.-]*:.*/) } if (requires_download && params.download) { From cb6bd9f689a21a4bcea70a86fe70763c589bc837 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Tue, 25 Aug 2026 21:22:55 +0200 Subject: [PATCH 294/334] Capture 0 exit code status --- modules/nf-core/rclone/check/main.nf | 4 +++- modules/nf-core/rclone/checksum/main.nf | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/nf-core/rclone/check/main.nf b/modules/nf-core/rclone/check/main.nf index ec1444e..3b3d77e 100644 --- a/modules/nf-core/rclone/check/main.nf +++ b/modules/nf-core/rclone/check/main.nf @@ -40,7 +40,9 @@ process RCLONE_CHECK { --error ${prefix}.error.txt \\ --checkers $task.cpus \\ ${source} \\ - ${destination} || echo \$? > ${prefix}.exit_code.txt + ${destination} \ + && echo 0 > ${prefix}.exit_code.txt \ + || echo \$? > ${prefix}.exit_code.txt sort -k2 ${prefix}.combined.txt -o ${prefix}.combined.txt sort ${prefix}.differ.txt -o ${prefix}.differ.txt diff --git a/modules/nf-core/rclone/checksum/main.nf b/modules/nf-core/rclone/checksum/main.nf index 1f506c0..78a0533 100644 --- a/modules/nf-core/rclone/checksum/main.nf +++ b/modules/nf-core/rclone/checksum/main.nf @@ -42,7 +42,9 @@ process RCLONE_CHECKSUM { --checkers $task.cpus \\ $hash \\ $sumfile \\ - ${destination} || echo \$? > ${prefix}.exit_code.txt + ${destination} \ + && echo 0 > ${prefix}.exit_code.txt \ + || echo \$? > ${prefix}.exit_code.txt sort -k2 ${prefix}.combined.txt -o ${prefix}.combined.txt sort ${prefix}.differ.txt -o ${prefix}.differ.txt From 1720b8542eb6616a53210a6aba6a9bdc5019e7f5 Mon Sep 17 00:00:00 2001 From: delfiterradas Date: Mon, 31 Aug 2026 18:27:21 +0200 Subject: [PATCH 295/334] Update rclone_copy version --- modules/nf-core/rclone/copy/environment.yml | 3 +-- modules/nf-core/rclone/copy/main.nf | 6 +++--- subworkflows/local/utils_nfcore_datasync_pipeline/main.nf | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/nf-core/rclone/copy/environment.yml b/modules/nf-core/rclone/copy/environment.yml index d6f401d..ea96315 100644 --- a/modules/nf-core/rclone/copy/environment.yml +++ b/modules/nf-core/rclone/copy/environment.yml @@ -2,6 +2,5 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json channels: - conda-forge - - bioconda dependencies: - - conda-forge::rclone=1.65.0 + - "conda-forge::rclone=1.74.3" diff --git a/modules/nf-core/rclone/copy/main.nf b/modules/nf-core/rclone/copy/main.nf index a063abf..8cb4eaa 100644 --- a/modules/nf-core/rclone/copy/main.nf +++ b/modules/nf-core/rclone/copy/main.nf @@ -3,9 +3,9 @@ process RCLONE_COPY { label 'process_low' conda "${moduleDir}/environment.yml" - container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container - ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c9/c947c1a7171daf074310295417d0f0afe879275e1543fa5fc2a9711e7c2c72ab/data' - : 'community.wave.seqera.io/library/rclone:1.65.0--ff88b2e0040147be'}" + container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/5d/5dfd28fd0090c69f57c9bd93ea3235d8df194e8f269b5cb3027b6b59bff567d5/data' + : 'community.wave.seqera.io/library/rclone:1.74.3--2ef33c5b9132aa97' }" input: tuple val(meta), val(source_path), val(destination_path), path(filter_file) diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 9285f83..dca6fc9 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -263,7 +263,7 @@ def toolCitationText() { def toolBibliographyText() { def reference_text = [ - "
  • Craig-Wood, N. (2023). Rclone: Rsync for cloud storage (Vers. 1.65.0). Computer software. https://rclone.org
  • ", + "
  • Craig-Wood, N. (2023). Rclone: Rsync for cloud storage (Vers. 1.74.3). Computer software. https://rclone.org
  • ", "
  • Ewels, P., Magnusson, M., Lundin, S., & Käller, M. (2016). MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics, 32(19), 3047–3048. doi: /10.1093/bioinformatics/btw354
  • " ].join(' ').trim() From dc2ee3895b16e38c21c229aff72425bfebe8c850 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Tue, 1 Sep 2026 12:58:25 +0000 Subject: [PATCH 296/334] Template update for nf-core/tools version 4.1.0 --- .github/actions/nf-test/action.yml | 6 +- .github/workflows/clean-up.yml | 2 +- .github/workflows/download_pipeline.yml | 6 +- .github/workflows/fix_linting.yml | 6 +- .github/workflows/linting.yml | 16 +- .github/workflows/nf-test.yml | 4 +- .../workflows/template-version-comment.yml | 2 +- .hooks/block_pipeline_outdir.sh | 44 + .nf-core.yml | 9 +- .pre-commit-config.yaml | 19 +- CHANGELOG.md | 2 +- README.md | 2 +- assets/multiqc_config.yml | 4 +- conf/base.config | 3 + conf/containers_conda_lock_files_amd64.config | 4 +- conf/containers_conda_lock_files_arm64.config | 4 +- conf/containers_docker_amd64.config | 2 +- conf/containers_docker_arm64.config | 2 +- .../containers_singularity_https_amd64.config | 2 +- .../containers_singularity_https_arm64.config | 2 +- conf/containers_singularity_oras_amd64.config | 2 +- conf/containers_singularity_oras_arm64.config | 2 +- conf/igenomes.config | 856 +++++---- conf/modules.config | 3 +- docs/CONTRIBUTING.md | 8 +- docs/output.md | 2 +- docs/usage.md | 2 +- modules.json | 6 +- .../linux_amd64-bd-c17fb751507e9dfc_1.txt | 1526 +++++++++++++++++ .../linux_arm64-bd-5c84a5000a226ab5_1.txt | 1476 ++++++++++++++++ modules/nf-core/multiqc/environment.yml | 2 +- modules/nf-core/multiqc/main.nf | 4 +- modules/nf-core/multiqc/meta.yml | 28 +- .../nf-core/multiqc/tests/main.nf.test.snap | 10 +- nextflow.config | 2 +- ro-crate-metadata.json | 20 +- .../utils_nfcore_datasync_pipeline/main.nf | 3 +- .../nf-core/utils_nfschema_plugin/main.nf | 12 +- .../nf-core/utils_nfschema_plugin/meta.yml | 24 + .../utils_nfschema_plugin/tests/main.nf.test | 5 + .../tests/nextflow.config | 2 +- tests/nextflow.config | 5 +- 42 files changed, 3622 insertions(+), 519 deletions(-) create mode 100755 .hooks/block_pipeline_outdir.sh create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt create mode 100644 modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt diff --git a/.github/actions/nf-test/action.yml b/.github/actions/nf-test/action.yml index 945c56f..4175e3c 100644 --- a/.github/actions/nf-test/action.yml +++ b/.github/actions/nf-test/action.yml @@ -20,12 +20,12 @@ runs: using: "composite" steps: - name: Setup Nextflow - uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 + uses: nf-core/setup-nextflow@893c28b667aedeba26e37f296d260ccc5bc4d914 # v3 with: version: "${{ env.NXF_VERSION }}" - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 with: python-version: "3.14" @@ -37,7 +37,7 @@ runs: - name: Setup apptainer if: contains(inputs.profile, 'singularity') - uses: eWaterCycle/setup-apptainer@4bb22c52d4f63406c49e94c804632975787312b3 # v2.0.0 + uses: eWaterCycle/setup-apptainer@3f706d898c9db585b1d741b4692e66755f3a1b40 # v2.0.0 - name: Set up Singularity if: contains(inputs.profile, 'singularity') diff --git a/.github/workflows/clean-up.yml b/.github/workflows/clean-up.yml index 172de6f..b694012 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@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10 + - uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11 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 a7bf4fc..ca2eb82 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -39,15 +39,15 @@ jobs: needs: configure steps: - name: Check out pipeline code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Install Nextflow - uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 + uses: nf-core/setup-nextflow@893c28b667aedeba26e37f296d260ccc5bc4d914 # v3 - name: Disk space cleanup uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 with: python-version: "3.14" architecture: "x64" diff --git a/.github/workflows/fix_linting.yml b/.github/workflows/fix_linting.yml index 8837738..8579c6f 100644 --- a/.github/workflows/fix_linting.yml +++ b/.github/workflows/fix_linting.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: token: ${{ secrets.nf_core_bot_auth_token }} @@ -32,12 +32,12 @@ jobs: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} - name: Install Nextflow - uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 + uses: nf-core/setup-nextflow@893c28b667aedeba26e37f296d260ccc5bc4d914 # v3 # Install and run prek - name: Run prek id: prek - uses: j178/prek-action@6ad80277337ad479fe43bd70701c3f7f8aa74db3 # v2 + uses: j178/prek-action@5337cb91e0fa35a7ff31b9ca345126d8bbbcdf16 # v2 continue-on-error: true # indication that the linting has finished diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index bc32219..277f12f 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -11,30 +11,30 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Install Nextflow - uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 + uses: nf-core/setup-nextflow@893c28b667aedeba26e37f296d260ccc5bc4d914 # v3 - name: Run prek - uses: j178/prek-action@6ad80277337ad479fe43bd70701c3f7f8aa74db3 # v2 + uses: j178/prek-action@5337cb91e0fa35a7ff31b9ca345126d8bbbcdf16 # v2 nf-core: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Install Nextflow - uses: nf-core/setup-nextflow@b4ec1bc7c16a94435159de94a05253542fddf6ef # v3 + uses: nf-core/setup-nextflow@893c28b667aedeba26e37f296d260ccc5bc4d914 # v3 - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7 with: python-version: "3.14" architecture: "x64" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 - name: read .nf-core.yml uses: pietrobolcato/action-read-yaml@9f13718d61111b69f30ab4ac683e67a56d254e1d # 1.1.0 @@ -46,7 +46,7 @@ jobs: run: uv tool install nf-core==${{ steps.read_yml.outputs['nf_core_version'] }} - name: Run nf-core pipelines lint - if: ${{ github.base_ref != 'master' || github.base_ref != 'main' }} + if: ${{ github.base_ref != 'master' && github.base_ref != 'main' }} env: GITHUB_COMMENTS_URL: ${{ github.event.pull_request.comments_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml index 4de681a..e363215 100644 --- a/.github/workflows/nf-test.yml +++ b/.github/workflows/nf-test.yml @@ -40,7 +40,7 @@ jobs: rm -rf ./* || true rm -rf ./.??* || true ls -la ./ - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: fetch-depth: 0 @@ -85,7 +85,7 @@ jobs: TOTAL_SHARDS: ${{ needs.nf-test-changes.outputs.total_shards }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: fetch-depth: 0 diff --git a/.github/workflows/template-version-comment.yml b/.github/workflows/template-version-comment.yml index ee102f7..149e285 100644 --- a/.github/workflows/template-version-comment.yml +++ b/.github/workflows/template-version-comment.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ github.event.pull_request.head.sha }} diff --git a/.hooks/block_pipeline_outdir.sh b/.hooks/block_pipeline_outdir.sh new file mode 100755 index 0000000..e9ba4f9 --- /dev/null +++ b/.hooks/block_pipeline_outdir.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# This hook is used to block commits if they include staged files inside a directory +# which also contains a subdirectory called `pipeline_info`. The purpose of this is to +# prevent users from inadvertently committing output from pipeline test runs inside the +# development directory. + +set -e + +status=0 +seen_dirs="" + +while IFS= read -r file; do + # The offending output bundle's root is the ancestor directory that has + # `pipeline_info` as an immediate child, so callers can restore it in one go. + if [[ "$file" == pipeline_info/* ]]; then + top_dir="pipeline_info" + elif [[ "$file" == */pipeline_info/* ]]; then + top_dir="${file%%/pipeline_info/*}" + else + top_dir="" + dir=$(dirname "$file") + while [[ "$dir" != "." && "$dir" != "/" ]]; do + if [[ -d "$dir/pipeline_info" ]]; then + top_dir="$dir" + break + fi + dir=$(dirname "$dir") + done + fi + + if [[ -n "$top_dir" ]]; then + echo "❌ Commit blocked: Please do not commit output from pipeline test runs to the pipeline code itself: $file" + status=1 + case "$seen_dirs" in + *"|$top_dir|"*) ;; + *) + echo "Run 'git restore --staged $top_dir' to remove the whole output folder from the staging area." + seen_dirs="$seen_dirs|$top_dir|" + ;; + esac + fi +done < <(git diff --cached --name-only) + +exit "$status" diff --git a/.nf-core.yml b/.nf-core.yml index d72e474..63f9d2c 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,6 +1,11 @@ lint: + files_exist: + - .github/workflows/linting_comment.yml + files_unchanged: + - .github/workflows/branch.yml + - .github/workflows/linting.yml multiqc_config: false -nf_core_version: 4.0.3 +nf_core_version: 4.1.0 repository_type: pipeline template: author: Alexander Peltzer @@ -11,4 +16,4 @@ template: name: datasync org: nf-core outdir: . - version: 1.0dev + version: 1.0.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f51e1a2..e9503db 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.8.3 + - prettier@3.9.6 - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: @@ -25,9 +25,26 @@ repos: subworkflows/(?!local/).*| .*\.snap$ )$ + - id: check-added-large-files + args: [--maxkb=5000] + exclude: | + (?x)^( + .*ro-crate-metadata.json$| + .*\.snap$| + lib/nfcore_external_java_deps.jar$| + docs/.*\.(svg|pdf)$| + assets/.*$ + )$ + - id: check-merge-conflict - repo: https://github.com/seqeralabs/nf-lint-pre-commit rev: v0.3.0 hooks: - id: nextflow-lint files: '\.nf$|nextflow\.config$' args: ["-output", "json"] + - repo: local + hooks: + - id: block-pipeline-outdir + name: Prevent committing output from pipeline test runs to the pipeline code itself + entry: ./.hooks/block_pipeline_outdir.sh + language: script diff --git a/CHANGELOG.md b/CHANGELOG.md index 60dad40..ff434cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 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). -## v1.0dev - [date] +## v1.0.0 - [unreleased] Initial release of nf-core/datasync, created with the [nf-core](https://nf-co.re/) template. diff --git a/README.md b/README.md index 3d20e4c..e1a4fd6 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) [![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.10.4-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-4.0.3-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.0.3) +[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0) [![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/) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index dc1af56..856910b 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -1,7 +1,7 @@ report_comment: > - This report has been generated by the nf-core/datasync + This report has been generated by the nf-core/datasync analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-datasync-methods-description": order: -1000 diff --git a/conf/base.config b/conf/base.config index 84af848..53d0fd3 100644 --- a/conf/base.config +++ b/conf/base.config @@ -49,6 +49,9 @@ process { withLabel:process_long { time = { 20.h * task.attempt } } + withLabel:process_low_memory { + memory = { 1.GB * task.attempt } + } withLabel:process_high_memory { memory = { 200.GB * task.attempt } } diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index d3ee1b4..df04a4b 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1,2 +1,2 @@ -process { withName: 'FASTQC' { container = 'modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt' } } -process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-db7c73dae76bc9e6_1.txt' } } +process { withName: 'FASTQC' { conda = 'modules/nf-core/fastqc/.conda-lock/linux_amd64-bd-5cb1a2fa2f18c7c2_1.txt' } } +process { withName: 'MULTIQC' { conda = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } diff --git a/conf/containers_conda_lock_files_arm64.config b/conf/containers_conda_lock_files_arm64.config index 2b90ac4..7ed29f3 100644 --- a/conf/containers_conda_lock_files_arm64.config +++ b/conf/containers_conda_lock_files_arm64.config @@ -1,2 +1,2 @@ -process { withName: 'FASTQC' { container = 'modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt' } } -process { withName: 'MULTIQC' { container = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-d167b8012595a136_1.txt' } } +process { withName: 'FASTQC' { conda = 'modules/nf-core/fastqc/.conda-lock/linux_arm64-bd-e455e32f745abe68_1.txt' } } +process { withName: 'MULTIQC' { conda = 'modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-5c84a5000a226ab5_1.txt' } } diff --git a/conf/containers_docker_amd64.config b/conf/containers_docker_amd64.config index 65f1814..a66e3d1 100644 --- a/conf/containers_docker_amd64.config +++ b/conf/containers_docker_amd64.config @@ -1,2 +1,2 @@ process { withName: 'FASTQC' { container = 'community.wave.seqera.io/library/fastqc:0.12.1--5cb1a2fa2f18c7c2' } } -process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6' } } +process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc' } } diff --git a/conf/containers_docker_arm64.config b/conf/containers_docker_arm64.config index 6c845ba..215f686 100644 --- a/conf/containers_docker_arm64.config +++ b/conf/containers_docker_arm64.config @@ -1,2 +1,2 @@ process { withName: 'FASTQC' { container = 'community.wave.seqera.io/library/fastqc:0.12.1--e455e32f745abe68' } } -process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.34--d167b8012595a136' } } +process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--5c84a5000a226ab5' } } diff --git a/conf/containers_singularity_https_amd64.config b/conf/containers_singularity_https_amd64.config index 838f248..2fb11a3 100644 --- a/conf/containers_singularity_https_amd64.config +++ b/conf/containers_singularity_https_amd64.config @@ -1,2 +1,2 @@ process { withName: 'FASTQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/f2/f20b021476d1d87658820f971ebecc1e8cdbde0f338eb0d9cea2b0a8fc54a54b/data' } } -process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/1b/1bef8af6be88c5733461959c46ac8ef73d18f65277f62a1695d0e1633054f9c2/data' } } +process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' } } diff --git a/conf/containers_singularity_https_arm64.config b/conf/containers_singularity_https_arm64.config index 090173b..5fa5b4f 100644 --- a/conf/containers_singularity_https_arm64.config +++ b/conf/containers_singularity_https_arm64.config @@ -1,2 +1,2 @@ process { withName: 'FASTQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/46/46daf2dad0169afd2ae047c3e50ed3776259f664bf07e5e06b045dc23449e994/data' } } -process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/9a/9a1fec9662a152683e6fcae440d0ce20920b3b89dc62d1e3a52e73f92eba0969/data' } } +process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/e4/e48aa28aebc881254a499b24c3e1ce77b8df1b85a5432699ed6f72eb17ac7fb5/data' } } diff --git a/conf/containers_singularity_oras_amd64.config b/conf/containers_singularity_oras_amd64.config index 773f369..b334375 100644 --- a/conf/containers_singularity_oras_amd64.config +++ b/conf/containers_singularity_oras_amd64.config @@ -1,2 +1,2 @@ process { withName: 'FASTQC' { container = 'oras://community.wave.seqera.io/library/fastqc:0.12.1--5c4bd442468d75dd' } } -process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.34--4fc8657c816047c0' } } +process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2' } } diff --git a/conf/containers_singularity_oras_arm64.config b/conf/containers_singularity_oras_arm64.config index 798cc63..661c656 100644 --- a/conf/containers_singularity_oras_arm64.config +++ b/conf/containers_singularity_oras_arm64.config @@ -1,2 +1,2 @@ process { withName: 'FASTQC' { container = 'oras://community.wave.seqera.io/library/fastqc:0.12.1--127a87fc06499035' } } -process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.34--7fbd82d945c06726' } } +process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c0468833d65b2f81' } } diff --git a/conf/igenomes.config b/conf/igenomes.config index 3f11437..b8c8154 100644 --- a/conf/igenomes.config +++ b/conf/igenomes.config @@ -8,433 +8,431 @@ ---------------------------------------------------------------------------------------- */ -params { +params.genomes = [ // illumina iGenomes reference file paths - genomes { - 'GRCh37' { - fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" - } - 'GRCh38' { - fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'CHM13' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAIndex/" - bwamem2 = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAmem2Index/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/CHM13/Annotation/Genes/genes.gtf" - gff = "ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/009/914/755/GCF_009914755.1_T2T-CHM13v2.0/GCF_009914755.1_T2T-CHM13v2.0_genomic.gff.gz" - mito_name = "chrM" - } - 'GRCm38' { - fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" - } - 'TAIR10' { - fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" - mito_name = "Mt" - } - 'EB2' { - fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" - } - 'UMD3.1' { - fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" - mito_name = "MT" - } - 'WBcel235' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" - mito_name = "MtDNA" - macs_gsize = "9e7" - } - 'CanFam3.1' { - fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" - mito_name = "MT" - } - 'GRCz10' { - fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'BDGP6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" - mito_name = "M" - macs_gsize = "1.2e8" - } - 'EquCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" - mito_name = "MT" - } - 'EB1' { - fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" - } - 'Galgal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Gm01' { - fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" - } - 'Mmul_1' { - fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" - mito_name = "MT" - } - 'IRGSP-1.0' { - fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'CHIMP2.1.4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" - mito_name = "MT" - } - 'Rnor_5.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Rnor_6.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'R64-1-1' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" - mito_name = "MT" - macs_gsize = "1.2e7" - } - 'EF2' { - fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.21e7" - } - 'Sbi1' { - fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" - } - 'Sscrofa10.2' { - fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" - mito_name = "MT" - } - 'AGPv3' { - fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'hg38' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'hg19' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" - } - 'mm10' { - fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" - } - 'bosTau8' { - fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'ce10' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "9e7" - } - 'canFam3' { - fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" - mito_name = "chrM" - } - 'danRer10' { - fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.37e9" - } - 'dm6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.2e8" - } - 'equCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" - mito_name = "chrM" - } - 'galGal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" - mito_name = "chrM" - } - 'panTro4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" - mito_name = "chrM" - } - 'rn6' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'sacCer3' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" - readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.2e7" - } - 'susScr3' { - fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" - mito_name = "chrM" - } - } -} + 'GRCh37' : [ + fasta : "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt", + mito_name : "MT", + macs_gsize : "2.7e9", + blacklist : "${projectDir}/assets/blacklists/GRCh37-blacklist.bed", + ], + 'GRCh38' : [ + fasta : "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed", + mito_name : "chrM", + macs_gsize : "2.7e9", + blacklist : "${projectDir}/assets/blacklists/hg38-blacklist.bed", + ], + 'CHM13' : [ + fasta : "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAIndex/", + bwamem2 : "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAmem2Index/", + gtf : "${params.igenomes_base}/Homo_sapiens/NCBI/CHM13/Annotation/Genes/genes.gtf", + gff : "ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/009/914/755/GCF_009914755.1_T2T-CHM13v2.0/GCF_009914755.1_T2T-CHM13v2.0_genomic.gff.gz", + mito_name : "chrM", + ], + 'GRCm38' : [ + fasta : "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt", + mito_name : "MT", + macs_gsize : "1.87e9", + blacklist : "${projectDir}/assets/blacklists/GRCm38-blacklist.bed", + ], + 'TAIR10' : [ + fasta : "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt", + mito_name : "Mt", + ], + 'EB2' : [ + fasta : "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt", + ], + 'UMD3.1' : [ + fasta : "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt", + mito_name : "MT", + ], + 'WBcel235' : [ + fasta : "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed", + mito_name : "MtDNA", + macs_gsize : "9e7", + ], + 'CanFam3.1' : [ + fasta : "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt", + mito_name : "MT", + ], + 'GRCz10' : [ + fasta : "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed", + mito_name : "MT", + ], + 'BDGP6' : [ + fasta : "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed", + mito_name : "M", + macs_gsize : "1.2e8", + ], + 'EquCab2' : [ + fasta : "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt", + mito_name : "MT", + ], + 'EB1' : [ + fasta : "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt", + ], + 'Galgal4' : [ + fasta : "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed", + mito_name : "MT", + ], + 'Gm01' : [ + fasta : "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt", + ], + 'Mmul_1' : [ + fasta : "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt", + mito_name : "MT", + ], + 'IRGSP-1.0' : [ + fasta : "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed", + mito_name : "Mt", + ], + 'CHIMP2.1.4' : [ + fasta : "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt", + mito_name : "MT", + ], + 'Rnor_5.0' : [ + fasta : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed", + mito_name : "MT", + ], + 'Rnor_6.0' : [ + fasta : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed", + mito_name : "MT", + ], + 'R64-1-1' : [ + fasta : "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed", + mito_name : "MT", + macs_gsize : "1.2e7", + ], + 'EF2' : [ + fasta : "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt", + mito_name : "MT", + macs_gsize : "1.21e7", + ], + 'Sbi1' : [ + fasta : "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt", + ], + 'Sscrofa10.2' : [ + fasta : "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt", + mito_name : "MT", + ], + 'AGPv3' : [ + fasta : "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed", + mito_name : "Mt", + ], + 'hg38' : [ + fasta : "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed", + mito_name : "chrM", + macs_gsize : "2.7e9", + blacklist : "${projectDir}/assets/blacklists/hg38-blacklist.bed", + ], + 'hg19' : [ + fasta : "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt", + mito_name : "chrM", + macs_gsize : "2.7e9", + blacklist : "${projectDir}/assets/blacklists/hg19-blacklist.bed", + ], + 'mm10' : [ + fasta : "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt", + mito_name : "chrM", + macs_gsize : "1.87e9", + blacklist : "${projectDir}/assets/blacklists/mm10-blacklist.bed", + ], + 'bosTau8' : [ + fasta : "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed", + mito_name : "chrM", + ], + 'ce10' : [ + fasta : "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt", + mito_name : "chrM", + macs_gsize : "9e7", + ], + 'canFam3' : [ + fasta : "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt", + mito_name : "chrM", + ], + 'danRer10' : [ + fasta : "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed", + mito_name : "chrM", + macs_gsize : "1.37e9", + ], + 'dm6' : [ + fasta : "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed", + mito_name : "chrM", + macs_gsize : "1.2e8", + ], + 'equCab2' : [ + fasta : "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt", + mito_name : "chrM", + ], + 'galGal4' : [ + fasta : "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt", + mito_name : "chrM", + ], + 'panTro4' : [ + fasta : "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt", + mito_name : "chrM", + ], + 'rn6' : [ + fasta : "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed", + mito_name : "chrM", + ], + 'sacCer3' : [ + fasta : "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/", + readme : "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt", + mito_name : "chrM", + macs_gsize : "1.2e7", + ], + 'susScr3' : [ + fasta : "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa", + bwa : "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/", + bowtie2 : "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/", + star : "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/", + bismark : "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/", + gtf : "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf", + bed12 : "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed", + readme : "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt", + mito_name : "chrM", + ], +] diff --git a/conf/modules.config b/conf/modules.config index d203d2b..d4e90be 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -26,8 +26,7 @@ process { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ path: { "${params.outdir}/multiqc" }, - mode: params.publish_dir_mode, - saveAs: { filename -> filename.equals('versions.yml') ? null : filename } + mode: params.publish_dir_mode ] } diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 3e8477b..9a32d34 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -40,12 +40,12 @@ The nf-core stance on the use of AI and LLMs is that humans are still ultimately If you’re using AI tools, try to stick by these guidelines: -- Keep PRs as small and focussed as possible +- Keep PRs as small and focused as possible - Avoid any unnecessary changes, such as moving or refactoring code (unless that is the explicit intention of the PR) - Review all generated code yourself before opening a PR, and ensure that you understand it - Engage with the community review process and expect to make revisions -For more detail, see the the [blog post](https://nf-co.re/blog/2026/statement-on-ai) for a statement from the nf-core/core team. +For more detail, see the [blog post](https://nf-co.re/blog/2026/statement-on-ai) for a statement from the nf-core/core team. ### Getting help @@ -128,7 +128,7 @@ Please also refer to the [pipeline-specific contribution guidelines](#pipeline-s - [ ] Perform local tests to validate that the new code works as expected. - [ ] If applicable, add a new test in the `tests` directory. - [ ] Update `usage.md`, `output.md`, and `citation.md` as appropriate. -- [ ] [Lint](lint) the code with nf-core/tools. +- [ ] [Lint](#lint-tests) the code with nf-core/tools. - [ ] Update any diagrams or pipeline images as necessary. - [ ] Update MultiQC config `assets/multiqc_config.yml` so relevant suffixes, file name cleanup, and module plots are in the appropriate order. - [ ] If applicable, create a [MultiQC](https://seqera.io/multiqc/) module. @@ -166,7 +166,7 @@ Specify these with generic `withLabel:` selectors, so they can be shared across nf-core provides a set of standard labels that you should follow where possible, as seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/main/nf_core/pipeline-template/conf/base.config). These labels define resource defaults for single-core processes, modules that require a GPU, and different levels of multi-core configurations with increasing memory requirements. -Values assigned within these labels can be dynamically passed to a tool using the the `${task.cpus}` and `${task.memory}` Nextflow variables in the `script:` block of a module (see an example in the [modules repository](https://github.com/nf-core/modules/blob/bd1b6a40f55933d94b8c9ca94ec8c1ea0eaf4b82/modules/nf-core/samtools/bam2fq/main.nf#L30)). +Values assigned within these labels can be dynamically passed to a tool using the `${task.cpus}` and `${task.memory}` Nextflow variables in the `script:` block of a module (see an example in the [modules repository](https://github.com/nf-core/modules/blob/bd1b6a40f55933d94b8c9ca94ec8c1ea0eaf4b82/modules/nf-core/samtools/bam2fq/main.nf#L30)). #### Nextflow version bumping diff --git a/docs/output.md b/docs/output.md index 1b7eb8b..ff46877 100644 --- a/docs/output.md +++ b/docs/output.md @@ -58,4 +58,4 @@ Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQ
    diff --git a/docs/usage.md b/docs/usage.md index 21a383f..37bfe04 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -85,9 +85,9 @@ The above pipeline run specified with a params file in yaml format: nextflow run nf-core/datasync -profile docker -params-file params.yaml ``` -with `params.yaml` containing: +with: -```yaml +```yaml title="params.yaml" input: './samplesheet.csv' outdir: './results/' genome: 'GRCh37' @@ -199,14 +199,6 @@ See the main [Nextflow documentation](https://www.nextflow.io/docs/latest/config If you have any questions or issues please send us a message on [Slack](https://nf-co.re/join/slack) on the [`#configs` channel](https://nfcore.slack.com/channels/configs). -## Azure Resource Requests - -To be used with the `azurebatch` profile by specifying the `-profile azurebatch`. -We recommend providing a compute `params.vm_type` of `Standard_D16_v3` VMs by default but these options can be changed if required. - -Note that the choice of VM size depends on your quota and the overall workload during the analysis. -For a thorough list, please refer the [Azure Sizes for virtual machines in Azure](https://docs.microsoft.com/en-us/azure/virtual-machines/sizes). - ## Running in the background Nextflow handles job submissions and supervises the running jobs. The Nextflow process must run until the pipeline is finished. diff --git a/main.nf b/main.nf index e0833f6..f0ac265 100644 --- a/main.nf +++ b/main.nf @@ -9,8 +9,6 @@ ---------------------------------------------------------------------------------------- */ -nextflow.enable.dsl = 2 - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS / WORKFLOWS @@ -20,7 +18,6 @@ nextflow.enable.dsl = 2 include { DATASYNC } from './workflows/datasync' include { PIPELINE_INITIALISATION } from './subworkflows/local/utils_nfcore_datasync_pipeline' include { PIPELINE_COMPLETION } from './subworkflows/local/utils_nfcore_datasync_pipeline' - include { getGenomeAttribute } from './subworkflows/local/utils_nfcore_datasync_pipeline' /* @@ -56,10 +53,8 @@ workflow NFCORE_DATASYNC { DATASYNC ( samplesheet ) - emit: multiqc_report = DATASYNC.out.multiqc_report // channel: /path/to/multiqc_report.html - } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -70,27 +65,24 @@ workflow NFCORE_DATASYNC { workflow { main: - // // SUBWORKFLOW: Run initialisation tasks // PIPELINE_INITIALISATION ( params.version, - params.help, params.validate_params, params.monochrome_logs, args, params.outdir, params.input ) - + // // WORKFLOW: Run main workflow // NFCORE_DATASYNC ( PIPELINE_INITIALISATION.out.samplesheet ) - // // SUBWORKFLOW: Run completion tasks // diff --git a/modules.json b/modules.json index 1f795b3..ca4f5d9 100644 --- a/modules.json +++ b/modules.json @@ -7,12 +7,12 @@ "nf-core": { "fastqc": { "branch": "master", - "git_sha": "285a50500f9e02578d90b3ce6382ea3c30216acd", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "b7ebe95761cd389603f9cc0e0dc384c0f663815a", + "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", "installed_by": ["modules"] } } @@ -21,17 +21,17 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "git_sha": "d20fb2a9cc3e2835e9d067d1046a63252eb17352", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "92de218a329bfc9a9033116eb5f65fd270e72ba3", + "git_sha": "2fdce49d30c0254f76bc0f13c55c17455c1251ab", "installed_by": ["subworkflows"] }, - "utils_nfvalidation_plugin": { + "utils_nfschema_plugin": { "branch": "master", - "git_sha": "5caf7640a9ef1d18d765d55339be751bb0969dfa", + "git_sha": "bbd5a41f4535a8defafe6080e00ea74c45f4f96c", "installed_by": ["subworkflows"] } } diff --git a/modules/nf-core/fastqc/environment.yml b/modules/nf-core/fastqc/environment.yml index 1787b38..691d4c7 100644 --- a/modules/nf-core/fastqc/environment.yml +++ b/modules/nf-core/fastqc/environment.yml @@ -1,7 +1,5 @@ -name: fastqc channels: - conda-forge - bioconda - - defaults dependencies: - bioconda::fastqc=0.12.1 diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index d79f1c8..d8989f4 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -26,7 +26,10 @@ process FASTQC { def rename_to = old_new_pairs*.join(' ').join(' ') def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ') - def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') + // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) + // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 + // Dividing the task.memory by task.cpu allows to stick to requested amount of RAM in the label + def memory_in_mb = MemoryUnit.of("${task.memory}").toUnit('MB') / task.cpus // FastQC memory value allowed range (100 - 10000) def fastqc_memory = memory_in_mb > 10000 ? 10000 : (memory_in_mb < 100 ? 100 : memory_in_mb) diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml index ee5507e..4827da7 100644 --- a/modules/nf-core/fastqc/meta.yml +++ b/modules/nf-core/fastqc/meta.yml @@ -16,35 +16,44 @@ tools: homepage: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/ documentation: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/Help/ licence: ["GPL-2.0-only"] + identifier: biotools:fastqc input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - reads: - type: file - description: | - List of input FastQ files of size 1 and 2 for single-end and paired-end data, - respectively. + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - reads: + type: file + description: | + List of input FastQ files of size 1 and 2 for single-end and paired-end data, + respectively. output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - html: - type: file - description: FastQC report - pattern: "*_{fastqc.html}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.html": + type: file + description: FastQC report + pattern: "*_{fastqc.html}" - zip: - type: file - description: FastQC report archive - pattern: "*_{fastqc.zip}" + - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.zip": + type: file + description: FastQC report archive + pattern: "*_{fastqc.zip}" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@drpatelh" - "@grst" diff --git a/modules/nf-core/fastqc/tests/main.nf.test b/modules/nf-core/fastqc/tests/main.nf.test index 70edae4..e9d79a0 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test +++ b/modules/nf-core/fastqc/tests/main.nf.test @@ -23,17 +23,14 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. - // looks like this:
    Mon 2 Oct 2023
    test.gz
    - // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 - - { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_single") } + { assert process.success }, + // NOTE The report contains the date inside it, which means that the md5sum is stable per day, but not longer than that. So you can't md5sum it. + // looks like this:
    Mon 2 Oct 2023
    test.gz
    + // https://github.com/nf-core/modules/pull/3903#issuecomment-1743620039 + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -54,16 +51,14 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, - { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, - { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, - { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, - { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_paired") } + { assert process.success }, + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -83,13 +78,11 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_interleaved") } + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -109,13 +102,11 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_bam") } + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/test_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/test_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -138,22 +129,20 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, - { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, - { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, - { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, - { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, - { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, - { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, - { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, - { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, - { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_multiple") } + { assert process.success }, + { assert process.out.html[0][1][0] ==~ ".*/test_1_fastqc.html" }, + { assert process.out.html[0][1][1] ==~ ".*/test_2_fastqc.html" }, + { assert process.out.html[0][1][2] ==~ ".*/test_3_fastqc.html" }, + { assert process.out.html[0][1][3] ==~ ".*/test_4_fastqc.html" }, + { assert process.out.zip[0][1][0] ==~ ".*/test_1_fastqc.zip" }, + { assert process.out.zip[0][1][1] ==~ ".*/test_2_fastqc.zip" }, + { assert process.out.zip[0][1][2] ==~ ".*/test_3_fastqc.zip" }, + { assert process.out.zip[0][1][3] ==~ ".*/test_4_fastqc.zip" }, + { assert path(process.out.html[0][1][0]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][1]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][2]).text.contains("File typeConventional base calls") }, + { assert path(process.out.html[0][1][3]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } @@ -173,21 +162,18 @@ nextflow_process { then { assertAll ( - { assert process.success }, - - { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, - { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, - { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, - - { assert snapshot(process.out.versions).match("fastqc_versions_custom_prefix") } + { assert process.success }, + { assert process.out.html[0][1] ==~ ".*/mysample_fastqc.html" }, + { assert process.out.zip[0][1] ==~ ".*/mysample_fastqc.zip" }, + { assert path(process.out.html[0][1]).text.contains("File typeConventional base calls") }, + { assert snapshot(process.out.versions).match() } ) } } test("sarscov2 single-end [fastq] - stub") { - options "-stub" - + options "-stub" when { process { """ @@ -201,12 +187,123 @@ nextflow_process { then { assertAll ( - { assert process.success }, - { assert snapshot(process.out.html.collect { file(it[1]).getName() } + - process.out.zip.collect { file(it[1]).getName() } + - process.out.versions ).match("fastqc_stub") } + { assert process.success }, + { assert snapshot(process.out).match() } ) } } + test("sarscov2 paired-end [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 interleaved [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_interleaved.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 paired-end [bam] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 multiple [fastq] - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [id: 'test', single_end: false], // meta map + [ file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_2.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_1.fastq.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test2_2.fastq.gz', checkIfExists: true) ] + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } + + test("sarscov2 custom_prefix - stub") { + + options "-stub" + when { + process { + """ + input[0] = Channel.of([ + [ id:'mysample', single_end:true ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ]) + """ + } + } + + then { + assertAll ( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + } } diff --git a/modules/nf-core/fastqc/tests/main.nf.test.snap b/modules/nf-core/fastqc/tests/main.nf.test.snap index 86f7c31..d5db309 100644 --- a/modules/nf-core/fastqc/tests/main.nf.test.snap +++ b/modules/nf-core/fastqc/tests/main.nf.test.snap @@ -1,88 +1,392 @@ { - "fastqc_versions_interleaved": { + "sarscov2 custom_prefix": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:40:07.293713" + "timestamp": "2024-07-22T11:02:16.374038" }, - "fastqc_stub": { + "sarscov2 single-end [fastq] - stub": { "content": [ - [ - "test.html", - "test.zip", - "versions.yml:md5,e1cc25ca8af856014824abd842e93978" - ] + { + "0": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": true + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": true + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:24.993809" + }, + "sarscov2 custom_prefix - stub": { + "content": [ + { + "0": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "mysample", + "single_end": true + }, + "mysample.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:31:01.425198" + "timestamp": "2024-07-22T11:03:10.93942" }, - "fastqc_versions_multiple": { + "sarscov2 interleaved [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:40:55.797907" + "timestamp": "2024-07-22T11:01:42.355718" }, - "fastqc_versions_bam": { + "sarscov2 paired-end [bam]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:40:26.795862" + "timestamp": "2024-07-22T11:01:53.276274" }, - "fastqc_versions_single": { + "sarscov2 multiple [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:39:27.043675" + "timestamp": "2024-07-22T11:02:05.527626" }, - "fastqc_versions_paired": { + "sarscov2 paired-end [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:31.188871" + }, + "sarscov2 paired-end [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:34.273566" + }, + "sarscov2 multiple [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:39:47.584191" + "timestamp": "2024-07-22T11:03:02.304411" }, - "fastqc_versions_custom_prefix": { + "sarscov2 single-end [fastq]": { "content": [ [ "versions.yml:md5,e1cc25ca8af856014824abd842e93978" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:01:19.095607" + }, + "sarscov2 interleaved [fastq] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" + }, + "timestamp": "2024-07-22T11:02:44.640184" + }, + "sarscov2 paired-end [bam] - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "html": [ + [ + { + "id": "test", + "single_end": false + }, + "test.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,e1cc25ca8af856014824abd842e93978" + ], + "zip": [ + [ + { + "id": "test", + "single_end": false + }, + "test.zip:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.0", + "nextflow": "24.04.3" }, - "timestamp": "2024-01-31T17:41:14.576531" + "timestamp": "2024-07-22T11:02:53.550742" } } \ No newline at end of file diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index ca39fb6..f1cd99b 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -1,7 +1,5 @@ -name: multiqc channels: - conda-forge - bioconda - - defaults dependencies: - - bioconda::multiqc=1.21 + - bioconda::multiqc=1.24.1 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 47ac352..b9ccebd 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -3,14 +3,16 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.21--pyhdfd78af_0' : - 'biocontainers/multiqc:1.21--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.25--pyhdfd78af_0' : + 'biocontainers/multiqc:1.25--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" path(multiqc_config) path(extra_multiqc_config) path(multiqc_logo) + path(replace_names) + path(sample_names) output: path "*multiqc_report.html", emit: report @@ -23,16 +25,22 @@ process MULTIQC { script: def args = task.ext.args ?: '' + def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' def config = multiqc_config ? "--config $multiqc_config" : '' def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' - def logo = multiqc_logo ? /--cl-config 'custom_logo: "${multiqc_logo}"'/ : '' + def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' + def replace = replace_names ? "--replace-names ${replace_names}" : '' + def samples = sample_names ? "--sample-names ${sample_names}" : '' """ multiqc \\ --force \\ $args \\ $config \\ + $prefix \\ $extra_config \\ $logo \\ + $replace \\ + $samples \\ . cat <<-END_VERSIONS > versions.yml diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index 45a9bc3..b16c187 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -1,5 +1,6 @@ name: multiqc -description: Aggregate results from bioinformatics analyses across many samples into a single report +description: Aggregate results from bioinformatics analyses across many samples into + a single report keywords: - QC - bioinformatics tools @@ -12,40 +13,59 @@ tools: homepage: https://multiqc.info/ documentation: https://multiqc.info/docs/ licence: ["GPL-3.0-or-later"] + identifier: biotools:multiqc input: - - multiqc_files: - type: file - description: | - List of reports / files recognised by MultiQC, for example the html and zip output of FastQC - - multiqc_config: - type: file - description: Optional config yml for MultiQC - pattern: "*.{yml,yaml}" - - extra_multiqc_config: - type: file - description: Second optional config yml for MultiQC. Will override common sections in multiqc_config. - pattern: "*.{yml,yaml}" - - multiqc_logo: - type: file - description: Optional logo file for MultiQC - pattern: "*.{png}" + - - multiqc_files: + type: file + description: | + List of reports / files recognised by MultiQC, for example the html and zip output of FastQC + - - multiqc_config: + type: file + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + - - extra_multiqc_config: + type: file + description: Second optional config yml for MultiQC. Will override common sections + in multiqc_config. + pattern: "*.{yml,yaml}" + - - multiqc_logo: + type: file + description: Optional logo file for MultiQC + pattern: "*.{png}" + - - replace_names: + type: file + description: | + Optional two-column sample renaming file. First column a set of + patterns, second column a set of corresponding replacements. Passed via + MultiQC's `--replace-names` option. + pattern: "*.{tsv}" + - - sample_names: + type: file + description: | + Optional TSV file with headers, passed to the MultiQC --sample_names + argument. + pattern: "*.{tsv}" output: - report: - type: file - description: MultiQC report file - pattern: "multiqc_report.html" + - "*multiqc_report.html": + type: file + description: MultiQC report file + pattern: "multiqc_report.html" - data: - type: directory - description: MultiQC data dir - pattern: "multiqc_data" + - "*_data": + type: directory + description: MultiQC data dir + pattern: "multiqc_data" - plots: - type: file - description: Plots created by MultiQC - pattern: "*_data" + - "*_plots": + type: file + description: Plots created by MultiQC + pattern: "*_data" - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" authors: - "@abhi18av" - "@bunop" diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test index f1c4242..33316a7 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -8,6 +8,8 @@ nextflow_process { tag "modules_nfcore" tag "multiqc" + config "./nextflow.config" + test("sarscov2 single-end [fastqc]") { when { @@ -17,6 +19,8 @@ nextflow_process { input[1] = [] input[2] = [] input[3] = [] + input[4] = [] + input[5] = [] """ } } @@ -41,6 +45,8 @@ nextflow_process { input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) input[2] = [] input[3] = [] + input[4] = [] + input[5] = [] """ } } @@ -66,6 +72,8 @@ nextflow_process { input[1] = [] input[2] = [] input[3] = [] + input[4] = [] + input[5] = [] """ } } diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index bfebd80..b779e46 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "multiqc_versions_single": { "content": [ [ - "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + "versions.yml:md5,8c8724363a5efe0c6f43ab34faa57efd" ] ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-29T08:48:55.657331" + "timestamp": "2024-07-10T12:41:34.562023" }, "multiqc_stub": { "content": [ @@ -17,25 +17,25 @@ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + "versions.yml:md5,8c8724363a5efe0c6f43ab34faa57efd" ] ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-29T08:49:49.071937" + "timestamp": "2024-07-10T11:27:11.933869532" }, "multiqc_versions_config": { "content": [ [ - "versions.yml:md5,21f35ee29416b9b3073c28733efe4b7d" + "versions.yml:md5,8c8724363a5efe0c6f43ab34faa57efd" ] ], "meta": { "nf-test": "0.8.4", - "nextflow": "23.10.1" + "nextflow": "24.04.2" }, - "timestamp": "2024-02-29T08:49:25.457567" + "timestamp": "2024-07-10T11:26:56.709849369" } -} \ No newline at end of file +} diff --git a/modules/nf-core/multiqc/tests/nextflow.config b/modules/nf-core/multiqc/tests/nextflow.config new file mode 100644 index 0000000..c537a6a --- /dev/null +++ b/modules/nf-core/multiqc/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: 'MULTIQC' { + ext.prefix = null + } +} diff --git a/nextflow.config b/nextflow.config index e227b16..660415f 100644 --- a/nextflow.config +++ b/nextflow.config @@ -16,7 +16,6 @@ params { genome = null igenomes_base = 's3://ngi-igenomes/igenomes/' igenomes_ignore = false - // MultiQC options multiqc_config = null multiqc_title = null @@ -33,48 +32,26 @@ params { monochrome_logs = false hook_url = null help = false + help_full = false + show_hidden = false version = false pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' - // Config options config_profile_name = null config_profile_description = null + custom_config_version = 'master' custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" config_profile_contact = null config_profile_url = null - - // Max resource options - // Defaults only, expecting to be overwritten - max_memory = '128.GB' - max_cpus = 16 - max_time = '240.h' - // Schema validation default options - validationFailUnrecognisedParams = false - validationLenientMode = false - validationSchemaIgnoreParams = 'genomes,igenomes_base' - validationShowHiddenParams = false - validate_params = true - + validate_params = true + } // Load base.config by default for all pipelines includeConfig 'conf/base.config' -// Load nf-core custom profiles from different Institutions -try { - includeConfig "${params.custom_config_base}/nfcore_custom.config" -} catch (Exception e) { - System.err.println("WARNING: Could not load nf-core/config profiles: ${params.custom_config_base}/nfcore_custom.config") -} - -// Load nf-core/datasync custom profiles from different institutions. -try { - includeConfig "${params.custom_config_base}/pipeline/datasync.config" -} catch (Exception e) { - System.err.println("WARNING: Could not load nf-core/config/datasync profiles: ${params.custom_config_base}/pipeline/datasync.config") -} profiles { debug { dumpHashes = true @@ -89,7 +66,7 @@ profiles { podman.enabled = false shifter.enabled = false charliecloud.enabled = false - conda.channels = ['conda-forge', 'bioconda', 'defaults'] + conda.channels = ['conda-forge', 'bioconda'] apptainer.enabled = false } mamba { @@ -178,25 +155,23 @@ profiles { test_full { includeConfig 'conf/test_full.config' } } -// Set default registry for Apptainer, Docker, Podman and Singularity independent of -profile -// Will not be used unless Apptainer / Docker / Podman / Singularity are enabled -// Set to your registry if you have a mirror of containers -apptainer.registry = 'quay.io' -docker.registry = 'quay.io' -podman.registry = 'quay.io' -singularity.registry = 'quay.io' +// 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" -// Nextflow plugins -plugins { - id 'nf-validation@1.1.3' // Validation of pipeline parameters and creation of an input channel from a sample sheet -} +// Load nf-core/datasync custom profiles from different institutions. +// TODO nf-core: Optionally, you can add a pipeline-specific nf-core config at https://github.com/nf-core/configs +// includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${params.custom_config_base}/pipeline/datasync.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 +// Set to your registry if you have a mirror of containers +apptainer.registry = 'quay.io' +docker.registry = 'quay.io' +podman.registry = 'quay.io' +singularity.registry = 'quay.io' +charliecloud.registry = 'quay.io' // Load igenomes.config if required -if (!params.igenomes_ignore) { - includeConfig 'conf/igenomes.config' -} else { - params.genomes = [:] -} +includeConfig !params.igenomes_ignore ? 'conf/igenomes.config' : 'conf/igenomes_ignored.config' // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. @@ -208,8 +183,15 @@ env { JULIA_DEPOT_PATH = "/usr/local/share/julia" } -// Capture exit codes from upstream processes when piping -process.shell = ['/bin/bash', '-euo', 'pipefail'] +// Set bash options +process.shell = """\ +bash + +set -e # Exit if a tool returns a non-zero status/exit code +set -u # Treat unset variables and parameters as an error +set -o pipefail # Returns the status of the last command to exit with a non-zero status or zero if all successfully execute +set -C # No clobber - prevent output redirection from overwriting files. +""" // Disable process selector warnings by default. Use debug profile to enable warnings. nextflow.enable.configProcessNamesValidation = false @@ -238,43 +220,47 @@ manifest { homePage = 'https://github.com/nf-core/datasync' description = """A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.""" mainScript = 'main.nf' - nextflowVersion = '!>=23.04.0' + nextflowVersion = '!>=24.04.2' version = '1.0dev' doi = '' } -// Load modules.config for DSL2 module specific options -includeConfig 'conf/modules.config' +// Nextflow plugins +plugins { + id 'nf-schema@2.1.1' // Validation of pipeline parameters and creation of an input channel from a sample sheet +} + +validation { + defaultIgnoreParams = ["genomes"] + help { + enabled = true + command = "nextflow run $manifest.name -profile --input samplesheet.csv --outdir " + fullParameter = "help_full" + showHiddenParameter = "show_hidden" + beforeText = """ +-\033[2m----------------------------------------------------\033[0m- + \033[0;32m,--.\033[0;30m/\033[0;32m,-.\033[0m +\033[0;34m ___ __ __ __ ___ \033[0;32m/,-._.--~\'\033[0m +\033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m +\033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m + \033[0;32m`._,._,\'\033[0m +\033[0;35m ${manifest.name} ${manifest.version}\033[0m +-\033[2m----------------------------------------------------\033[0m- +""" + afterText = """${manifest.doi ? "* The pipeline\n" : ""}${manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${manifest.doi ? "\n" : ""} +* The nf-core framework + https://doi.org/10.1038/s41587-020-0439-x -// Function to ensure that resource requirements don't go beyond -// a maximum limit -def check_max(obj, type) { - if (type == 'memory') { - try { - if (obj.compareTo(params.max_memory as nextflow.util.MemoryUnit) == 1) - return params.max_memory as nextflow.util.MemoryUnit - else - return obj - } catch (all) { - println " ### ERROR ### Max memory '${params.max_memory}' is not valid! Using default value: $obj" - return obj - } - } else if (type == 'time') { - try { - if (obj.compareTo(params.max_time as nextflow.util.Duration) == 1) - return params.max_time as nextflow.util.Duration - else - return obj - } catch (all) { - println " ### ERROR ### Max time '${params.max_time}' is not valid! Using default value: $obj" - return obj - } - } else if (type == 'cpus') { - try { - return Math.min( obj, params.max_cpus as int ) - } catch (all) { - println " ### ERROR ### Max cpus '${params.max_cpus}' is not valid! Using default value: $obj" - return obj - } +* Software dependencies + https://github.com/${manifest.name}/blob/master/CITATIONS.md +""" + } + summary { + beforeText = validation.help.beforeText + afterText = validation.help.afterText } } + +// Load modules.config for DSL2 module specific options +includeConfig 'conf/modules.config' + diff --git a/nextflow_schema.json b/nextflow_schema.json index d7abdbb..f9cb916 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -1,10 +1,10 @@ { - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://raw.githubusercontent.com/nf-core/datasync/master/nextflow_schema.json", "title": "nf-core/datasync pipeline parameters", "description": "A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.", "type": "object", - "definitions": { + "$defs": { "input_output_options": { "title": "Input/output options", "type": "object", @@ -71,6 +71,14 @@ "fa_icon": "fas fa-ban", "hidden": true, "help_text": "Do not load `igenomes.config` when running the pipeline. You may choose this option if you observe clashes between custom parameters and those supplied in `igenomes.config`." + }, + "igenomes_base": { + "type": "string", + "format": "directory-path", + "description": "The base path to the igenomes reference files", + "fa_icon": "fas fa-ban", + "hidden": true, + "default": "s3://ngi-igenomes/igenomes/" } } }, @@ -122,41 +130,6 @@ } } }, - "max_job_request_options": { - "title": "Max job request options", - "type": "object", - "fa_icon": "fab fa-acquisitions-incorporated", - "description": "Set the top limit for requested resources for any single job.", - "help_text": "If you are running on a smaller system, a pipeline step requesting more resources than are available may cause the Nextflow to stop the run with an error. These options allow you to cap the maximum resources requested by any single job so that the pipeline will run on your system.\n\nNote that you can not _increase_ the resources requested by any job using these options. For that you will need your own configuration file. See [the nf-core website](https://nf-co.re/usage/configuration) for details.", - "properties": { - "max_cpus": { - "type": "integer", - "description": "Maximum number of CPUs that can be requested for any single job.", - "default": 16, - "fa_icon": "fas fa-microchip", - "hidden": true, - "help_text": "Use to set an upper-limit for the CPU requirement for each process. Should be an integer e.g. `--max_cpus 1`" - }, - "max_memory": { - "type": "string", - "description": "Maximum amount of memory that can be requested for any single job.", - "default": "128.GB", - "fa_icon": "fas fa-memory", - "pattern": "^\\d+(\\.\\d+)?\\.?\\s*(K|M|G|T)?B$", - "hidden": true, - "help_text": "Use to set an upper-limit for the memory requirement for each process. Should be a string in the format integer-unit e.g. `--max_memory '8.GB'`" - }, - "max_time": { - "type": "string", - "description": "Maximum amount of time that can be requested for any single job.", - "default": "240.h", - "fa_icon": "far fa-clock", - "pattern": "^(\\d+\\.?\\s*(s|m|h|d|day)\\s*)+$", - "hidden": true, - "help_text": "Use to set an upper-limit for the time requirement for each process. Should be a string in the format integer-unit e.g. `--max_time '2.h'`" - } - } - }, "generic_options": { "title": "Generic options", "type": "object", @@ -164,12 +137,6 @@ "description": "Less common options for the pipeline, typically set in a config file.", "help_text": "These options are common to all nf-core pipelines and allow you to customise some of the core preferences for how the pipeline runs.\n\nTypically these options would be set in a Nextflow config file loaded for all pipeline runs, such as `~/.nextflow/config`.", "properties": { - "help": { - "type": "boolean", - "description": "Display help text.", - "fa_icon": "fas fa-question-circle", - "hidden": true - }, "version": { "type": "boolean", "description": "Display version and exit.", @@ -245,27 +212,6 @@ "fa_icon": "fas fa-check-square", "hidden": true }, - "validationShowHiddenParams": { - "type": "boolean", - "fa_icon": "far fa-eye-slash", - "description": "Show all params when using `--help`", - "hidden": true, - "help_text": "By default, parameters set as _hidden_ in the schema are not shown on the command line when a user runs with `--help`. Specifying this option will tell the pipeline to show all parameters." - }, - "validationFailUnrecognisedParams": { - "type": "boolean", - "fa_icon": "far fa-check-circle", - "description": "Validation of parameters fails when an unrecognised parameter is found.", - "hidden": true, - "help_text": "By default, when an unrecognised parameter is found, it returns a warinig." - }, - "validationLenientMode": { - "type": "boolean", - "fa_icon": "far fa-check-circle", - "description": "Validation of parameters in lenient more.", - "hidden": true, - "help_text": "Allows string values that are parseable as numbers or booleans. For further information see [JSONSchema docs](https://github.com/everit-org/json-schema#lenient-mode)." - }, "pipelines_testdata_base_path": { "type": "string", "fa_icon": "far fa-check-circle", @@ -278,19 +224,16 @@ }, "allOf": [ { - "$ref": "#/definitions/input_output_options" - }, - { - "$ref": "#/definitions/reference_genome_options" + "$ref": "#/$defs/input_output_options" }, { - "$ref": "#/definitions/institutional_config_options" + "$ref": "#/$defs/reference_genome_options" }, { - "$ref": "#/definitions/max_job_request_options" + "$ref": "#/$defs/institutional_config_options" }, { - "$ref": "#/definitions/generic_options" + "$ref": "#/$defs/generic_options" } ] } diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index c1ba8c9..52a31fd 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -8,17 +8,14 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -include { UTILS_NFVALIDATION_PLUGIN } from '../../nf-core/utils_nfvalidation_plugin' -include { paramsSummaryMap } from 'plugin/nf-validation' -include { fromSamplesheet } from 'plugin/nf-validation' -include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' +include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' +include { paramsSummaryMap } from 'plugin/nf-schema' +include { samplesheetToList } from 'plugin/nf-schema' include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' -include { dashedLine } from '../../nf-core/utils_nfcore_pipeline' -include { nfCoreLogo } from '../../nf-core/utils_nfcore_pipeline' include { imNotification } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' -include { workflowCitation } from '../../nf-core/utils_nfcore_pipeline' +include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' /* ======================================================================================== @@ -30,7 +27,6 @@ workflow PIPELINE_INITIALISATION { take: version // boolean: Display version and exit - help // boolean: Display help text validate_params // boolean: Boolean whether to validate parameters against the schema at runtime monochrome_logs // boolean: Do not use coloured log outputs nextflow_cli_args // array: List of positional nextflow CLI args @@ -51,20 +47,16 @@ workflow PIPELINE_INITIALISATION { workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1 ) + // // Validate parameters and generate parameter summary to stdout // - pre_help_text = nfCoreLogo(monochrome_logs) - post_help_text = '\n' + workflowCitation() + '\n' + dashedLine(monochrome_logs) - def String workflow_command = "nextflow run ${workflow.manifest.name} -profile --input samplesheet.csv --outdir " - UTILS_NFVALIDATION_PLUGIN ( - help, - workflow_command, - pre_help_text, - post_help_text, + UTILS_NFSCHEMA_PLUGIN ( + workflow, validate_params, - "nextflow_schema.json" + null ) + // // Check config provided to the pipeline @@ -80,8 +72,9 @@ workflow PIPELINE_INITIALISATION { // // Create channel from input file provided through params.input // + Channel - .fromSamplesheet("input") + .fromList(samplesheetToList(params.input, "${projectDir}/assets/schema_input.json")) .map { meta, fastq_1, fastq_2 -> if (!fastq_2) { @@ -91,8 +84,8 @@ workflow PIPELINE_INITIALISATION { } } .groupTuple() - .map { - validateInputSamplesheet(it) + .map { samplesheet -> + validateInputSamplesheet(samplesheet) } .map { meta, fastqs -> @@ -117,13 +110,13 @@ workflow PIPELINE_COMPLETION { email // string: email address email_on_fail // string: email address sent on pipeline failure plaintext_email // boolean: Send plain-text email instead of HTML + outdir // path: Path to output directory where results will be published monochrome_logs // boolean: Disable ANSI colour codes in log output hook_url // string: hook URL for notifications multiqc_report // string: Path to MultiQC report main: - summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") // @@ -131,11 +124,18 @@ workflow PIPELINE_COMPLETION { // workflow.onComplete { if (email || email_on_fail) { - completionEmail(summary_params, email, email_on_fail, plaintext_email, outdir, monochrome_logs, multiqc_report.toList()) + completionEmail( + summary_params, + email, + email_on_fail, + plaintext_email, + outdir, + monochrome_logs, + multiqc_report.toList() + ) } completionSummary(monochrome_logs) - if (hook_url) { imNotification(summary_params, hook_url) } @@ -165,7 +165,7 @@ def validateInputSamplesheet(input) { def (metas, fastqs) = input[1..2] // Check that multiple runs of the same sample are of the same datatype i.e. single-end / paired-end - def endedness_ok = metas.collect{ it.single_end }.unique().size == 1 + def endedness_ok = metas.collect{ meta -> meta.single_end }.unique().size == 1 if (!endedness_ok) { error("Please check input samplesheet -> Multiple runs of a sample must be of the same datatype i.e. single-end or paired-end: ${metas[0].id}") } @@ -197,7 +197,6 @@ def genomeExistsError() { error(error_string) } } - // // Generate methods description for MultiQC // @@ -239,8 +238,10 @@ def methodsDescriptionText(mqc_methods_yaml) { // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers // Removing ` ` since the manifest.doi is a string and not a proper list def temp_doi_ref = "" - String[] manifest_doi = meta.manifest_map.doi.tokenize(",") - for (String doi_ref: manifest_doi) temp_doi_ref += "(doi:
    ${doi_ref.replace("https://doi.org/", "").replace(" ", "")}), " + def manifest_doi = meta.manifest_map.doi.tokenize(",") + manifest_doi.each { doi_ref -> + temp_doi_ref += "(doi: ${doi_ref.replace("https://doi.org/", "").replace(" ", "")}), " + } meta["doi_text"] = temp_doi_ref.substring(0, temp_doi_ref.length() - 2) } else meta["doi_text"] = "" meta["nodoi_text"] = meta.manifest_map.doi ? "" : "
  • If available, make sure to update the text to include the Zenodo DOI of version of the pipeline used.
  • " @@ -261,3 +262,4 @@ def methodsDescriptionText(mqc_methods_yaml) { return description_html.toString() } + diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf index ac31f28..28e32b2 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf @@ -2,10 +2,6 @@ // Subworkflow with functionality that may be useful for any Nextflow pipeline // -import org.yaml.snakeyaml.Yaml -import groovy.json.JsonOutput -import nextflow.extension.FilesEx - /* ======================================================================================== SUBWORKFLOW DEFINITION @@ -58,7 +54,7 @@ workflow UTILS_NEXTFLOW_PIPELINE { // Generate version string // def getWorkflowVersion() { - String version_string = "" + def version_string = "" as String if (workflow.manifest.version) { def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' version_string += "${prefix_v}${workflow.manifest.version}" @@ -79,10 +75,10 @@ def dumpParametersToJSON(outdir) { def timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') def filename = "params_${timestamp}.json" def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") - def jsonStr = JsonOutput.toJson(params) - temp_pf.text = JsonOutput.prettyPrint(jsonStr) + def jsonStr = groovy.json.JsonOutput.toJson(params) + temp_pf.text = groovy.json.JsonOutput.prettyPrint(jsonStr) - FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") + nextflow.extension.FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") temp_pf.delete() } @@ -90,7 +86,7 @@ def dumpParametersToJSON(outdir) { // When running with -profile conda, warn if channels have not been set-up appropriately // def checkCondaChannels() { - Yaml parser = new Yaml() + def parser = new org.yaml.snakeyaml.Yaml() def channels = [] try { def config = parser.load("conda config --show channels".execute().text) @@ -102,14 +98,16 @@ def checkCondaChannels() { // Check that all channels are present // This channel list is ordered by required channel priority. - def required_channels_in_order = ['conda-forge', 'bioconda', 'defaults'] + def required_channels_in_order = ['conda-forge', 'bioconda'] def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean // Check that they are in the right order def channel_priority_violation = false - def n = required_channels_in_order.size() - for (int i = 0; i < n - 1; i++) { - channel_priority_violation |= !(channels.indexOf(required_channels_in_order[i]) < channels.indexOf(required_channels_in_order[i+1])) + + required_channels_in_order.eachWithIndex { channel, index -> + if (index < required_channels_in_order.size() - 1) { + channel_priority_violation |= !(channels.indexOf(channel) < channels.indexOf(required_channels_in_order[index+1])) + } } if (channels_missing | channel_priority_violation) { diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config b/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config index d0a926b..a09572e 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config @@ -3,7 +3,7 @@ manifest { author = """nf-core""" homePage = 'https://127.0.0.1' description = """Dummy pipeline""" - nextflowVersion = '!>=23.04.0' + nextflowVersion = '!>=23.04.0' version = '9.9.9' doi = 'https://doi.org/10.5281/zenodo.5070524' } diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index 14558c3..cbd8495 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -2,9 +2,6 @@ // Subworkflow with utility functions specific to the nf-core pipeline template // -import org.yaml.snakeyaml.Yaml -import nextflow.extension.FilesEx - /* ======================================================================================== SUBWORKFLOW DEFINITION @@ -34,7 +31,7 @@ workflow UTILS_NFCORE_PIPELINE { // Warn if a -profile or Nextflow config has not been provided to run the pipeline // def checkConfigProvided() { - valid_config = true + def valid_config = true as Boolean if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + @@ -66,11 +63,13 @@ def checkProfileProvided(nextflow_cli_args) { // def workflowCitation() { def temp_doi_ref = "" - String[] manifest_doi = workflow.manifest.doi.tokenize(",") + def manifest_doi = workflow.manifest.doi.tokenize(",") // Using a loop to handle multiple DOIs // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers // Removing ` ` since the manifest.doi is a string and not a proper list - for (String doi_ref: manifest_doi) temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" + manifest_doi.each { doi_ref -> + temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" + } return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + "* The pipeline\n" + temp_doi_ref + "\n" + @@ -84,7 +83,7 @@ def workflowCitation() { // Generate workflow version string // def getWorkflowVersion() { - String version_string = "" + def version_string = "" as String if (workflow.manifest.version) { def prefix_v = workflow.manifest.version[0] != 'v' ? 'v' : '' version_string += "${prefix_v}${workflow.manifest.version}" @@ -102,8 +101,8 @@ def getWorkflowVersion() { // Get software versions for pipeline // def processVersionsFromYAML(yaml_file) { - Yaml yaml = new Yaml() - versions = yaml.load(yaml_file).collectEntries { k, v -> [ k.tokenize(':')[-1], v ] } + def yaml = new org.yaml.snakeyaml.Yaml() + def versions = yaml.load(yaml_file).collectEntries { k, v -> [ k.tokenize(':')[-1], v ] } return yaml.dumpAsMap(versions).trim() } @@ -124,7 +123,7 @@ def workflowVersionToYAML() { def softwareVersionsToYAML(ch_versions) { return ch_versions .unique() - .map { processVersionsFromYAML(it) } + .map { version -> processVersionsFromYAML(version) } .unique() .mix(Channel.of(workflowVersionToYAML())) } @@ -134,19 +133,19 @@ def softwareVersionsToYAML(ch_versions) { // def paramsSummaryMultiqc(summary_params) { def summary_section = '' - for (group in summary_params.keySet()) { + summary_params.keySet().each { group -> def group_params = summary_params.get(group) // This gets the parameters of that particular group if (group_params) { summary_section += "

    $group

    \n" summary_section += "
    \n" - for (param in group_params.keySet()) { + group_params.keySet().sort().each { param -> summary_section += "
    $param
    ${group_params.get(param) ?: 'N/A'}
    \n" } summary_section += "
    \n" } } - String yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" + def yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" as String yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" @@ -161,7 +160,7 @@ def paramsSummaryMultiqc(summary_params) { // nf-core logo // def nfCoreLogo(monochrome_logs=true) { - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map String.format( """\n ${dashedLine(monochrome_logs)} @@ -180,7 +179,7 @@ def nfCoreLogo(monochrome_logs=true) { // Return dashed line // def dashedLine(monochrome_logs=true) { - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map return "-${colors.dim}----------------------------------------------------${colors.reset}-" } @@ -188,7 +187,7 @@ def dashedLine(monochrome_logs=true) { // ANSII colours used for terminal logging // def logColours(monochrome_logs=true) { - Map colorcodes = [:] + def colorcodes = [:] as Map // Reset / Meta colorcodes['reset'] = monochrome_logs ? '' : "\033[0m" @@ -287,7 +286,7 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi } def summary = [:] - for (group in summary_params.keySet()) { + summary_params.keySet().sort().each { group -> summary << summary_params[group] } @@ -344,10 +343,10 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi def sendmail_html = sendmail_template.toString() // Send the HTML e-mail - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map if (email_address) { try { - if (plaintext_email) { throw GroovyException('Send plaintext e-mail, not HTML') } + if (plaintext_email) { throw new org.codehaus.groovy.GroovyException('Send plaintext e-mail, not HTML') } // Try to send HTML e-mail using sendmail def sendmail_tf = new File(workflow.launchDir.toString(), ".sendmail_tmp.html") sendmail_tf.withWriter { w -> w << sendmail_html } @@ -364,13 +363,13 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi // Write summary e-mail HTML to a file def output_hf = new File(workflow.launchDir.toString(), ".pipeline_report.html") output_hf.withWriter { w -> w << email_html } - FilesEx.copyTo(output_hf.toPath(), "${outdir}/pipeline_info/pipeline_report.html"); + nextflow.extension.FilesEx.copyTo(output_hf.toPath(), "${outdir}/pipeline_info/pipeline_report.html"); output_hf.delete() // Write summary e-mail TXT to a file def output_tf = new File(workflow.launchDir.toString(), ".pipeline_report.txt") output_tf.withWriter { w -> w << email_txt } - FilesEx.copyTo(output_tf.toPath(), "${outdir}/pipeline_info/pipeline_report.txt"); + nextflow.extension.FilesEx.copyTo(output_tf.toPath(), "${outdir}/pipeline_info/pipeline_report.txt"); output_tf.delete() } @@ -378,7 +377,7 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi // Print pipeline summary on completion // def completionSummary(monochrome_logs=true) { - Map colors = logColours(monochrome_logs) + def colors = logColours(monochrome_logs) as Map if (workflow.success) { if (workflow.stats.ignoredCount == 0) { log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" @@ -395,7 +394,7 @@ def completionSummary(monochrome_logs=true) { // def imNotification(summary_params, hook_url) { def summary = [:] - for (group in summary_params.keySet()) { + summary_params.keySet().sort().each { group -> summary << summary_params[group] } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/main.nf b/subworkflows/nf-core/utils_nfschema_plugin/main.nf new file mode 100644 index 0000000..4994303 --- /dev/null +++ b/subworkflows/nf-core/utils_nfschema_plugin/main.nf @@ -0,0 +1,46 @@ +// +// Subworkflow that uses the nf-schema plugin to validate parameters and render the parameter summary +// + +include { paramsSummaryLog } from 'plugin/nf-schema' +include { validateParameters } from 'plugin/nf-schema' + +workflow UTILS_NFSCHEMA_PLUGIN { + + take: + input_workflow // workflow: the workflow object used by nf-schema to get metadata from the workflow + validate_params // boolean: validate the parameters + parameters_schema // string: path to the parameters JSON schema. + // this has to be the same as the schema given to `validation.parametersSchema` + // when this input is empty it will automatically use the configured schema or + // "${projectDir}/nextflow_schema.json" as default. This input should not be empty + // for meta pipelines + + main: + + // + // Print parameter summary to stdout. This will display the parameters + // that differ from the default given in the JSON schema + // + if(parameters_schema) { + log.info paramsSummaryLog(input_workflow, parameters_schema:parameters_schema) + } else { + log.info paramsSummaryLog(input_workflow) + } + + // + // Validate the parameters using nextflow_schema.json or the schema + // given via the validation.parametersSchema configuration option + // + if(validate_params) { + if(parameters_schema) { + validateParameters(parameters_schema:parameters_schema) + } else { + validateParameters() + } + } + + emit: + dummy_emit = true +} + diff --git a/subworkflows/nf-core/utils_nfschema_plugin/meta.yml b/subworkflows/nf-core/utils_nfschema_plugin/meta.yml new file mode 100644 index 0000000..f7d9f02 --- /dev/null +++ b/subworkflows/nf-core/utils_nfschema_plugin/meta.yml @@ -0,0 +1,35 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "utils_nfschema_plugin" +description: Run nf-schema to validate parameters and create a summary of changed parameters +keywords: + - validation + - JSON schema + - plugin + - parameters + - summary +components: [] +input: + - input_workflow: + type: object + description: | + The workflow object of the used pipeline. + This object contains meta data used to create the params summary log + - validate_params: + type: boolean + description: Validate the parameters and error if invalid. + - parameters_schema: + type: string + description: | + Path to the parameters JSON schema. + This has to be the same as the schema given to the `validation.parametersSchema` config + option. When this input is empty it will automatically use the configured schema or + "${projectDir}/nextflow_schema.json" as default. The schema should not be given in this way + for meta pipelines. +output: + - dummy_emit: + type: boolean + description: Dummy emit to make nf-core subworkflows lint happy +authors: + - "@nvnieuwk" +maintainers: + - "@nvnieuwk" diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test new file mode 100644 index 0000000..842dc43 --- /dev/null +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test @@ -0,0 +1,117 @@ +nextflow_workflow { + + name "Test Subworkflow UTILS_NFSCHEMA_PLUGIN" + script "../main.nf" + workflow "UTILS_NFSCHEMA_PLUGIN" + + tag "subworkflows" + tag "subworkflows_nfcore" + tag "subworkflows/utils_nfschema_plugin" + tag "plugin/nf-schema" + + config "./nextflow.config" + + test("Should run nothing") { + + when { + + params { + test_data = '' + } + + workflow { + """ + validate_params = false + input[0] = workflow + input[1] = validate_params + input[2] = "" + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } + + test("Should validate params") { + + when { + + params { + test_data = '' + outdir = 1 + } + + workflow { + """ + validate_params = true + input[0] = workflow + input[1] = validate_params + input[2] = "" + """ + } + } + + then { + assertAll( + { assert workflow.failed }, + { assert workflow.stdout.any { it.contains('ERROR ~ Validation of pipeline parameters failed!') } } + ) + } + } + + test("Should run nothing - custom schema") { + + when { + + params { + test_data = '' + } + + workflow { + """ + validate_params = false + input[0] = workflow + input[1] = validate_params + input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } + + test("Should validate params - custom schema") { + + when { + + params { + test_data = '' + outdir = 1 + } + + workflow { + """ + validate_params = true + input[0] = workflow + input[1] = validate_params + input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + """ + } + } + + then { + assertAll( + { assert workflow.failed }, + { assert workflow.stdout.any { it.contains('ERROR ~ Validation of pipeline parameters failed!') } } + ) + } + } +} diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config new file mode 100644 index 0000000..0907ac5 --- /dev/null +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config @@ -0,0 +1,8 @@ +plugins { + id "nf-schema@2.1.0" +} + +validation { + parametersSchema = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + monochromeLogs = true +} \ No newline at end of file diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json similarity index 95% rename from subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json rename to subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json index 7626c1c..331e0d2 100644 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/nextflow_schema.json +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json @@ -1,10 +1,10 @@ { - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://raw.githubusercontent.com/./master/nextflow_schema.json", "title": ". pipeline parameters", "description": "", "type": "object", - "definitions": { + "$defs": { "input_output_options": { "title": "Input/output options", "type": "object", @@ -87,10 +87,10 @@ }, "allOf": [ { - "$ref": "#/definitions/input_output_options" + "$ref": "#/$defs/input_output_options" }, { - "$ref": "#/definitions/generic_options" + "$ref": "#/$defs/generic_options" } ] } diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/main.nf b/subworkflows/nf-core/utils_nfvalidation_plugin/main.nf deleted file mode 100644 index 2585b65..0000000 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/main.nf +++ /dev/null @@ -1,62 +0,0 @@ -// -// Subworkflow that uses the nf-validation plugin to render help text and parameter summary -// - -/* -======================================================================================== - IMPORT NF-VALIDATION PLUGIN -======================================================================================== -*/ - -include { paramsHelp } from 'plugin/nf-validation' -include { paramsSummaryLog } from 'plugin/nf-validation' -include { validateParameters } from 'plugin/nf-validation' - -/* -======================================================================================== - SUBWORKFLOW DEFINITION -======================================================================================== -*/ - -workflow UTILS_NFVALIDATION_PLUGIN { - - take: - print_help // boolean: print help - workflow_command // string: default commmand used to run pipeline - pre_help_text // string: string to be printed before help text and summary log - post_help_text // string: string to be printed after help text and summary log - validate_params // boolean: validate parameters - schema_filename // path: JSON schema file, null to use default value - - main: - - log.debug "Using schema file: ${schema_filename}" - - // Default values for strings - pre_help_text = pre_help_text ?: '' - post_help_text = post_help_text ?: '' - workflow_command = workflow_command ?: '' - - // - // Print help message if needed - // - if (print_help) { - log.info pre_help_text + paramsHelp(workflow_command, parameters_schema: schema_filename) + post_help_text - System.exit(0) - } - - // - // Print parameter summary to stdout - // - log.info pre_help_text + paramsSummaryLog(workflow, parameters_schema: schema_filename) + post_help_text - - // - // Validate parameters relative to the parameter JSON schema - // - if (validate_params){ - validateParameters(parameters_schema: schema_filename) - } - - emit: - dummy_emit = true -} diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml b/subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml deleted file mode 100644 index 3d4a6b0..0000000 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/meta.yml +++ /dev/null @@ -1,44 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json -name: "UTILS_NFVALIDATION_PLUGIN" -description: Use nf-validation to initiate and validate a pipeline -keywords: - - utility - - pipeline - - initialise - - validation -components: [] -input: - - print_help: - type: boolean - description: | - Print help message and exit - - workflow_command: - type: string - description: | - The command to run the workflow e.g. "nextflow run main.nf" - - pre_help_text: - type: string - description: | - Text to print before the help message - - post_help_text: - type: string - description: | - Text to print after the help message - - validate_params: - type: boolean - description: | - Validate the parameters and error if invalid. - - schema_filename: - type: string - description: | - The filename of the schema to validate against. -output: - - dummy_emit: - type: boolean - description: | - Dummy emit to make nf-core subworkflows lint happy -authors: - - "@adamrtalbot" -maintainers: - - "@adamrtalbot" - - "@maxulysse" diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test deleted file mode 100644 index 5784a33..0000000 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/main.nf.test +++ /dev/null @@ -1,200 +0,0 @@ -nextflow_workflow { - - name "Test Workflow UTILS_NFVALIDATION_PLUGIN" - script "../main.nf" - workflow "UTILS_NFVALIDATION_PLUGIN" - tag "subworkflows" - tag "subworkflows_nfcore" - tag "plugin/nf-validation" - tag "'plugin/nf-validation'" - tag "utils_nfvalidation_plugin" - tag "subworkflows/utils_nfvalidation_plugin" - - test("Should run nothing") { - - when { - - params { - monochrome_logs = true - test_data = '' - } - - workflow { - """ - help = false - workflow_command = null - pre_help_text = null - post_help_text = null - validate_params = false - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.success } - ) - } - } - - test("Should run help") { - - - when { - - params { - monochrome_logs = true - test_data = '' - } - workflow { - """ - help = true - workflow_command = null - pre_help_text = null - post_help_text = null - validate_params = false - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.success }, - { assert workflow.exitStatus == 0 }, - { assert workflow.stdout.any { it.contains('Input/output options') } }, - { assert workflow.stdout.any { it.contains('--outdir') } } - ) - } - } - - test("Should run help with command") { - - when { - - params { - monochrome_logs = true - test_data = '' - } - workflow { - """ - help = true - workflow_command = "nextflow run noorg/doesntexist" - pre_help_text = null - post_help_text = null - validate_params = false - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.success }, - { assert workflow.exitStatus == 0 }, - { assert workflow.stdout.any { it.contains('nextflow run noorg/doesntexist') } }, - { assert workflow.stdout.any { it.contains('Input/output options') } }, - { assert workflow.stdout.any { it.contains('--outdir') } } - ) - } - } - - test("Should run help with extra text") { - - - when { - - params { - monochrome_logs = true - test_data = '' - } - workflow { - """ - help = true - workflow_command = "nextflow run noorg/doesntexist" - pre_help_text = "pre-help-text" - post_help_text = "post-help-text" - validate_params = false - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.success }, - { assert workflow.exitStatus == 0 }, - { assert workflow.stdout.any { it.contains('pre-help-text') } }, - { assert workflow.stdout.any { it.contains('nextflow run noorg/doesntexist') } }, - { assert workflow.stdout.any { it.contains('Input/output options') } }, - { assert workflow.stdout.any { it.contains('--outdir') } }, - { assert workflow.stdout.any { it.contains('post-help-text') } } - ) - } - } - - test("Should validate params") { - - when { - - params { - monochrome_logs = true - test_data = '' - outdir = 1 - } - workflow { - """ - help = false - workflow_command = null - pre_help_text = null - post_help_text = null - validate_params = true - schema_filename = "$moduleTestDir/nextflow_schema.json" - - input[0] = help - input[1] = workflow_command - input[2] = pre_help_text - input[3] = post_help_text - input[4] = validate_params - input[5] = schema_filename - """ - } - } - - then { - assertAll( - { assert workflow.failed }, - { assert workflow.stdout.any { it.contains('ERROR ~ ERROR: Validation of pipeline parameters failed!') } } - ) - } - } -} diff --git a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml b/subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml deleted file mode 100644 index 60b1cff..0000000 --- a/subworkflows/nf-core/utils_nfvalidation_plugin/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -subworkflows/utils_nfvalidation_plugin: - - subworkflows/nf-core/utils_nfvalidation_plugin/** diff --git a/workflows/datasync.nf b/workflows/datasync.nf index a1e07fe..72a96bf 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -3,10 +3,9 @@ IMPORT MODULES / SUBWORKFLOWS / FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - include { FASTQC } from '../modules/nf-core/fastqc/main' include { MULTIQC } from '../modules/nf-core/multiqc/main' -include { paramsSummaryMap } from 'plugin/nf-validation' +include { paramsSummaryMap } from 'plugin/nf-schema' include { paramsSummaryMultiqc } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { softwareVersionsToYAML } from '../subworkflows/nf-core/utils_nfcore_pipeline' include { methodsDescriptionText } from '../subworkflows/local/utils_nfcore_datasync_pipeline' @@ -21,12 +20,10 @@ workflow DATASYNC { take: ch_samplesheet // channel: samplesheet read in from --input - main: ch_versions = Channel.empty() ch_multiqc_files = Channel.empty() - // // MODULE: Run FastQC // @@ -42,11 +39,12 @@ workflow DATASYNC { softwareVersionsToYAML(ch_versions) .collectFile( storeDir: "${params.outdir}/pipeline_info", - name: 'nf_core_pipeline_software_mqc_versions.yml', + name: 'nf_core_' + 'pipeline_software_' + 'mqc_' + 'versions.yml', sort: true, newLine: true ).set { ch_collated_versions } + // // MODULE: MultiQC // @@ -59,18 +57,19 @@ workflow DATASYNC { Channel.fromPath(params.multiqc_logo, checkIfExists: true) : Channel.empty() + summary_params = paramsSummaryMap( workflow, parameters_schema: "nextflow_schema.json") ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) - + ch_multiqc_files = ch_multiqc_files.mix( + ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) + ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) ch_methods_description = Channel.value( methodsDescriptionText(ch_multiqc_custom_methods_description)) - ch_multiqc_files = ch_multiqc_files.mix( - ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) ch_multiqc_files = ch_multiqc_files.mix( ch_methods_description.collectFile( @@ -83,12 +82,14 @@ workflow DATASYNC { ch_multiqc_files.collect(), ch_multiqc_config.toList(), ch_multiqc_custom_config.toList(), - ch_multiqc_logo.toList() + ch_multiqc_logo.toList(), + [], + [] ) - emit: - multiqc_report = MULTIQC.out.report.toList() // channel: /path/to/multiqc_report.html + emit:multiqc_report = MULTIQC.out.report.toList() // channel: /path/to/multiqc_report.html versions = ch_versions // channel: [ path(versions.yml) ] + } /* From 5569a071ea29bd3b7419388fe7259d9f4c068a2f Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Wed, 9 Oct 2024 11:05:35 +0000 Subject: [PATCH 006/334] Template update for nf-core/tools version 3.0.1 --- .editorconfig | 4 - .github/CONTRIBUTING.md | 2 +- .github/workflows/awsfulltest.yml | 6 +- .github/workflows/linting.yml | 4 +- .nf-core.yml | 2 +- .prettierignore | 1 - docs/output.md | 1 - modules.json | 6 +- modules/nf-core/multiqc/environment.yml | 2 +- modules/nf-core/multiqc/main.nf | 4 +- .../nf-core/multiqc/tests/main.nf.test.snap | 26 +- nextflow.config | 8 +- .../utils_nfcore_datasync_pipeline/main.nf | 12 +- .../nf-core/utils_nextflow_pipeline/main.nf | 46 ++- .../nf-core/utils_nfcore_pipeline/main.nf | 279 ++++++++++-------- 15 files changed, 209 insertions(+), 194 deletions(-) diff --git a/.editorconfig b/.editorconfig index e105881..72dda28 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,7 +11,6 @@ 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 @@ -26,12 +25,9 @@ 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 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e904891..3825d0f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -90,7 +90,7 @@ Once there, use `nf-core pipelines schema build` to add to `nextflow_schema.json ### Default processes resource requirements -Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/master/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. +Sensible defaults for process resource requirements (CPUs / memory / time) for a process should be defined in `conf/base.config`. These should generally be specified generic with `withLabel:` selectors so they can be shared across multiple processes/steps of the pipeline. A nf-core standard set of labels that should be followed where possible can be seen in the [nf-core pipeline template](https://github.com/nf-core/tools/blob/main/nf_core/pipeline-template/conf/base.config), which has the default process as a single core-process, and then different levels of multi-core configurations for increasingly large memory requirements defined with standardised labels. The process resources can be passed on to the tool dynamically within the process with the `${task.cpus}` and `${task.memory}` variables in the `script:` block. diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 2f90ed1..d01f992 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -14,16 +14,18 @@ on: jobs: run-platform: name: Run AWS full tests - if: github.repository == 'nf-core/datasync' && github.event.review.state == 'approved' + # run only if the PR is approved by at least 2 reviewers and against the master branch or manually triggered + if: github.repository == 'nf-core/datasync' && github.event.review.state == 'approved' && github.event.pull_request.base.ref == 'master' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: - uses: octokit/request-action@v2.x id: check_approvals with: - route: GET /repos/${{ github.repository }}/pulls/${{ github.event.review.number }}/reviews + route: GET /repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - id: test_variables + if: github.event_name != 'workflow_dispatch' run: | JSON_RESPONSE='${{ steps.check_approvals.outputs.data }}' CURRENT_APPROVALS_COUNT=$(echo $JSON_RESPONSE | jq -c '[.[] | select(.state | contains("APPROVED")) ] | length') diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index b882838..a502573 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -42,10 +42,10 @@ jobs: architecture: "x64" - name: read .nf-core.yml - uses: pietrobolcato/action-read-yaml@1.0.0 + uses: pietrobolcato/action-read-yaml@1.1.0 id: read_yml with: - config: ${{ github.workspace }}/.nf-core.yaml + config: ${{ github.workspace }}/.nf-core.yml - name: Install dependencies run: | diff --git a/.nf-core.yml b/.nf-core.yml index 020096b..3ff21da 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,6 +1,6 @@ bump_version: null lint: null -nf_core_version: 3.0.0 +nf_core_version: 3.0.1 org_path: null repository_type: pipeline template: diff --git a/.prettierignore b/.prettierignore index 610e506..437d763 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,3 @@ - email_template.html adaptivecard.json slackreport.json diff --git a/docs/output.md b/docs/output.md index 3734de7..1b7eb8b 100644 --- a/docs/output.md +++ b/docs/output.md @@ -14,7 +14,6 @@ The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes d - [FastQC](#fastqc) - Raw read QC - [MultiQC](#multiqc) - Aggregate report describing results and QC from the whole pipeline - - [Pipeline information](#pipeline-information) - Report metrics generated during the workflow execution ### FastQC diff --git a/modules.json b/modules.json index ca4f5d9..1ad83c6 100644 --- a/modules.json +++ b/modules.json @@ -12,7 +12,7 @@ }, "multiqc": { "branch": "master", - "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", + "git_sha": "b8d36829fa84b6e404364abff787e8b07f6d058c", "installed_by": ["modules"] } } @@ -21,12 +21,12 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "d20fb2a9cc3e2835e9d067d1046a63252eb17352", + "git_sha": "9d05360da397692321d377b6102d2fb22507c6ef", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "2fdce49d30c0254f76bc0f13c55c17455c1251ab", + "git_sha": "772684d9d66f37b650c8ba5146ac1ee3ecba2acb", "installed_by": ["subworkflows"] }, "utils_nfschema_plugin": { diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index f1cd99b..6f5b867 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -2,4 +2,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.24.1 + - bioconda::multiqc=1.25.1 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index b9ccebd..9724d2f 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -3,8 +3,8 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.25--pyhdfd78af_0' : - 'biocontainers/multiqc:1.25--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/multiqc:1.25.1--pyhdfd78af_0' : + 'biocontainers/multiqc:1.25.1--pyhdfd78af_0' }" input: path multiqc_files, stageAs: "?/*" diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index b779e46..2fcbb5f 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "multiqc_versions_single": { "content": [ [ - "versions.yml:md5,8c8724363a5efe0c6f43ab34faa57efd" + "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.2" + "nf-test": "0.9.0", + "nextflow": "24.04.4" }, - "timestamp": "2024-07-10T12:41:34.562023" + "timestamp": "2024-10-02T17:51:46.317523" }, "multiqc_stub": { "content": [ @@ -17,25 +17,25 @@ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,8c8724363a5efe0c6f43ab34faa57efd" + "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.2" + "nf-test": "0.9.0", + "nextflow": "24.04.4" }, - "timestamp": "2024-07-10T11:27:11.933869532" + "timestamp": "2024-10-02T17:52:20.680978" }, "multiqc_versions_config": { "content": [ [ - "versions.yml:md5,8c8724363a5efe0c6f43ab34faa57efd" + "versions.yml:md5,41f391dcedce7f93ca188f3a3ffa0916" ] ], "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.2" + "nf-test": "0.9.0", + "nextflow": "24.04.4" }, - "timestamp": "2024-07-10T11:26:56.709849369" + "timestamp": "2024-10-02T17:52:09.185842" } -} +} \ No newline at end of file diff --git a/nextflow.config b/nextflow.config index 660415f..243891f 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,10 +12,12 @@ params { // TODO nf-core: Specify your pipeline's command line flags // Input options input = null + // References genome = null igenomes_base = 's3://ngi-igenomes/igenomes/' igenomes_ignore = false + // MultiQC options multiqc_config = null multiqc_title = null @@ -36,6 +38,7 @@ params { show_hidden = false version = false pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' + // Config options config_profile_name = null config_profile_description = null @@ -44,9 +47,9 @@ params { custom_config_base = "https://raw.githubusercontent.com/nf-core/configs/${params.custom_config_version}" config_profile_contact = null config_profile_url = null + // Schema validation default options validate_params = true - } // Load base.config by default for all pipelines @@ -161,6 +164,7 @@ includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${pa // Load nf-core/datasync custom profiles from different institutions. // TODO nf-core: Optionally, you can add a pipeline-specific nf-core config at https://github.com/nf-core/configs // includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${params.custom_config_base}/pipeline/datasync.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 // Set to your registry if you have a mirror of containers @@ -172,6 +176,7 @@ charliecloud.registry = 'quay.io' // Load igenomes.config if required includeConfig !params.igenomes_ignore ? 'conf/igenomes.config' : 'conf/igenomes_ignored.config' + // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. @@ -263,4 +268,3 @@ validation { // Load modules.config for DSL2 module specific options includeConfig 'conf/modules.config' - diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 52a31fd..1cd554a 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -18,9 +18,9 @@ include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW TO INITIALISE PIPELINE -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow PIPELINE_INITIALISATION { @@ -99,9 +99,9 @@ workflow PIPELINE_INITIALISATION { } /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW FOR PIPELINE COMPLETION -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow PIPELINE_COMPLETION { @@ -147,9 +147,9 @@ workflow PIPELINE_COMPLETION { } /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FUNCTIONS -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ // // Check and validate pipeline parameters diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf index 28e32b2..2b0dc67 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf @@ -3,13 +3,12 @@ // /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW DEFINITION -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow UTILS_NEXTFLOW_PIPELINE { - take: print_version // boolean: print version dump_parameters // boolean: dump parameters @@ -22,7 +21,7 @@ workflow UTILS_NEXTFLOW_PIPELINE { // Print workflow version and exit on --version // if (print_version) { - log.info "${workflow.manifest.name} ${getWorkflowVersion()}" + log.info("${workflow.manifest.name} ${getWorkflowVersion()}") System.exit(0) } @@ -45,9 +44,9 @@ workflow UTILS_NEXTFLOW_PIPELINE { } /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FUNCTIONS -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ // @@ -72,11 +71,11 @@ def getWorkflowVersion() { // Dump pipeline parameters to a JSON file // def dumpParametersToJSON(outdir) { - def timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') - def filename = "params_${timestamp}.json" - def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") - def jsonStr = groovy.json.JsonOutput.toJson(params) - temp_pf.text = groovy.json.JsonOutput.prettyPrint(jsonStr) + def timestamp = new java.util.Date().format('yyyy-MM-dd_HH-mm-ss') + def filename = "params_${timestamp}.json" + def temp_pf = new File(workflow.launchDir.toString(), ".${filename}") + def jsonStr = groovy.json.JsonOutput.toJson(params) + temp_pf.text = groovy.json.JsonOutput.prettyPrint(jsonStr) nextflow.extension.FilesEx.copyTo(temp_pf.toPath(), "${outdir}/pipeline_info/params_${timestamp}.json") temp_pf.delete() @@ -91,9 +90,14 @@ def checkCondaChannels() { try { def config = parser.load("conda config --show channels".execute().text) channels = config.channels - } catch(NullPointerException | IOException e) { - log.warn "Could not verify conda channel configuration." - return + } + catch (NullPointerException e) { + log.warn("Could not verify conda channel configuration.") + return null + } + catch (IOException e) { + log.warn("Could not verify conda channel configuration.") + return null } // Check that all channels are present @@ -106,19 +110,13 @@ def checkCondaChannels() { required_channels_in_order.eachWithIndex { channel, index -> if (index < required_channels_in_order.size() - 1) { - channel_priority_violation |= !(channels.indexOf(channel) < channels.indexOf(required_channels_in_order[index+1])) + channel_priority_violation |= !(channels.indexOf(channel) < channels.indexOf(required_channels_in_order[index + 1])) } } if (channels_missing | channel_priority_violation) { - log.warn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + - " There is a problem with your Conda configuration!\n\n" + - " You will need to set-up the conda-forge and bioconda channels correctly.\n" + - " Please refer to https://bioconda.github.io/\n" + - " The observed channel order is \n" + - " ${channels}\n" + - " but the following channel order is required:\n" + - " ${required_channels_in_order}\n" + - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + log.warn( + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " There is a problem with your Conda configuration!\n\n" + " You will need to set-up the conda-forge and bioconda channels correctly.\n" + " Please refer to https://bioconda.github.io/\n" + " The observed channel order is \n" + " ${channels}\n" + " but the following channel order is required:\n" + " ${required_channels_in_order}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + ) } } diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index cbd8495..b78273c 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -3,13 +3,12 @@ // /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW DEFINITION -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow UTILS_NFCORE_PIPELINE { - take: nextflow_cli_args @@ -22,9 +21,9 @@ workflow UTILS_NFCORE_PIPELINE { } /* -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FUNCTIONS -======================================================================================== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ // @@ -33,12 +32,9 @@ workflow UTILS_NFCORE_PIPELINE { def checkConfigProvided() { def valid_config = true as Boolean if (workflow.profile == 'standard' && workflow.configFiles.size() <= 1) { - log.warn "[$workflow.manifest.name] You are attempting to run the pipeline without any custom configuration!\n\n" + - "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + - " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + - " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + - " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + - "Please refer to the quick start section and usage docs for the pipeline.\n " + log.warn( + "[${workflow.manifest.name}] You are attempting to run the pipeline without any custom configuration!\n\n" + "This will be dependent on your local compute environment but can be achieved via one or more of the following:\n" + " (1) Using an existing pipeline profile e.g. `-profile docker` or `-profile singularity`\n" + " (2) Using an existing nf-core/configs for your Institution e.g. `-profile crick` or `-profile uppmax`\n" + " (3) Using your own local custom config e.g. `-c /path/to/your/custom.config`\n\n" + "Please refer to the quick start section and usage docs for the pipeline.\n " + ) valid_config = false } return valid_config @@ -49,12 +45,14 @@ def checkConfigProvided() { // def checkProfileProvided(nextflow_cli_args) { if (workflow.profile.endsWith(',')) { - error "The `-profile` option cannot end with a trailing comma, please remove it and re-run the pipeline!\n" + - "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + error( + "The `-profile` option cannot end with a trailing comma, please remove it and re-run the pipeline!\n" + "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + ) } if (nextflow_cli_args[0]) { - log.warn "nf-core pipelines do not accept positional arguments. The positional argument `${nextflow_cli_args[0]}` has been detected.\n" + - "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + log.warn( + "nf-core pipelines do not accept positional arguments. The positional argument `${nextflow_cli_args[0]}` has been detected.\n" + "HINT: A common mistake is to provide multiple values separated by spaces e.g. `-profile test, docker`.\n" + ) } } @@ -70,13 +68,7 @@ def workflowCitation() { manifest_doi.each { doi_ref -> temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" } - return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + - "* The pipeline\n" + - temp_doi_ref + "\n" + - "* The nf-core framework\n" + - " https://doi.org/10.1038/s41587-020-0439-x\n\n" + - "* Software dependencies\n" + - " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" + return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + "* The pipeline\n" + temp_doi_ref + "\n" + "* The nf-core framework\n" + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + "* Software dependencies\n" + " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" } // @@ -102,7 +94,7 @@ def getWorkflowVersion() { // def processVersionsFromYAML(yaml_file) { def yaml = new org.yaml.snakeyaml.Yaml() - def versions = yaml.load(yaml_file).collectEntries { k, v -> [ k.tokenize(':')[-1], v ] } + def versions = yaml.load(yaml_file).collectEntries { k, v -> [k.tokenize(':')[-1], v] } return yaml.dumpAsMap(versions).trim() } @@ -112,8 +104,8 @@ def processVersionsFromYAML(yaml_file) { def workflowVersionToYAML() { return """ Workflow: - $workflow.manifest.name: ${getWorkflowVersion()} - Nextflow: $workflow.nextflow.version + ${workflow.manifest.name}: ${getWorkflowVersion()} + Nextflow: ${workflow.nextflow.version} """.stripIndent().trim() } @@ -121,11 +113,7 @@ def workflowVersionToYAML() { // Get channel of software versions used in pipeline in YAML format // def softwareVersionsToYAML(ch_versions) { - return ch_versions - .unique() - .map { version -> processVersionsFromYAML(version) } - .unique() - .mix(Channel.of(workflowVersionToYAML())) + return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(Channel.of(workflowVersionToYAML())) } // @@ -133,25 +121,31 @@ def softwareVersionsToYAML(ch_versions) { // def paramsSummaryMultiqc(summary_params) { def summary_section = '' - summary_params.keySet().each { group -> - def group_params = summary_params.get(group) // This gets the parameters of that particular group - if (group_params) { - summary_section += "

    $group

    \n" - summary_section += "
    \n" - group_params.keySet().sort().each { param -> - summary_section += "
    $param
    ${group_params.get(param) ?: 'N/A'}
    \n" + summary_params + .keySet() + .each { group -> + def group_params = summary_params.get(group) + // This gets the parameters of that particular group + if (group_params) { + summary_section += "

    ${group}

    \n" + summary_section += "
    \n" + group_params + .keySet() + .sort() + .each { param -> + summary_section += "
    ${param}
    ${group_params.get(param) ?: 'N/A'}
    \n" + } + summary_section += "
    \n" } - summary_section += "
    \n" } - } - def yaml_file_text = "id: '${workflow.manifest.name.replace('/','-')}-summary'\n" as String - yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" - yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" - yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" - yaml_file_text += "plot_type: 'html'\n" - yaml_file_text += "data: |\n" - yaml_file_text += "${summary_section}" + def yaml_file_text = "id: '${workflow.manifest.name.replace('/', '-')}-summary'\n" as String + yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n" + yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n" + yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n" + yaml_file_text += "plot_type: 'html'\n" + yaml_file_text += "data: |\n" + yaml_file_text += "${summary_section}" return yaml_file_text } @@ -199,54 +193,54 @@ def logColours(monochrome_logs=true) { colorcodes['hidden'] = monochrome_logs ? '' : "\033[8m" // Regular Colors - colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" - colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" - colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" - colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" - colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" - colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" - colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" - colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" + colorcodes['black'] = monochrome_logs ? '' : "\033[0;30m" + colorcodes['red'] = monochrome_logs ? '' : "\033[0;31m" + colorcodes['green'] = monochrome_logs ? '' : "\033[0;32m" + colorcodes['yellow'] = monochrome_logs ? '' : "\033[0;33m" + colorcodes['blue'] = monochrome_logs ? '' : "\033[0;34m" + colorcodes['purple'] = monochrome_logs ? '' : "\033[0;35m" + colorcodes['cyan'] = monochrome_logs ? '' : "\033[0;36m" + colorcodes['white'] = monochrome_logs ? '' : "\033[0;37m" // Bold - colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" - colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" - colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" - colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" - colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" - colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" - colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" - colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" + colorcodes['bblack'] = monochrome_logs ? '' : "\033[1;30m" + colorcodes['bred'] = monochrome_logs ? '' : "\033[1;31m" + colorcodes['bgreen'] = monochrome_logs ? '' : "\033[1;32m" + colorcodes['byellow'] = monochrome_logs ? '' : "\033[1;33m" + colorcodes['bblue'] = monochrome_logs ? '' : "\033[1;34m" + colorcodes['bpurple'] = monochrome_logs ? '' : "\033[1;35m" + colorcodes['bcyan'] = monochrome_logs ? '' : "\033[1;36m" + colorcodes['bwhite'] = monochrome_logs ? '' : "\033[1;37m" // Underline - colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" - colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" - colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" - colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" - colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" - colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" - colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" - colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" + colorcodes['ublack'] = monochrome_logs ? '' : "\033[4;30m" + colorcodes['ured'] = monochrome_logs ? '' : "\033[4;31m" + colorcodes['ugreen'] = monochrome_logs ? '' : "\033[4;32m" + colorcodes['uyellow'] = monochrome_logs ? '' : "\033[4;33m" + colorcodes['ublue'] = monochrome_logs ? '' : "\033[4;34m" + colorcodes['upurple'] = monochrome_logs ? '' : "\033[4;35m" + colorcodes['ucyan'] = monochrome_logs ? '' : "\033[4;36m" + colorcodes['uwhite'] = monochrome_logs ? '' : "\033[4;37m" // High Intensity - colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" - colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" - colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" - colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" - colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" - colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" - colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" - colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" + colorcodes['iblack'] = monochrome_logs ? '' : "\033[0;90m" + colorcodes['ired'] = monochrome_logs ? '' : "\033[0;91m" + colorcodes['igreen'] = monochrome_logs ? '' : "\033[0;92m" + colorcodes['iyellow'] = monochrome_logs ? '' : "\033[0;93m" + colorcodes['iblue'] = monochrome_logs ? '' : "\033[0;94m" + colorcodes['ipurple'] = monochrome_logs ? '' : "\033[0;95m" + colorcodes['icyan'] = monochrome_logs ? '' : "\033[0;96m" + colorcodes['iwhite'] = monochrome_logs ? '' : "\033[0;97m" // Bold High Intensity - colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" - colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" - colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" - colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" - colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" - colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" - colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" - colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" + colorcodes['biblack'] = monochrome_logs ? '' : "\033[1;90m" + colorcodes['bired'] = monochrome_logs ? '' : "\033[1;91m" + colorcodes['bigreen'] = monochrome_logs ? '' : "\033[1;92m" + colorcodes['biyellow'] = monochrome_logs ? '' : "\033[1;93m" + colorcodes['biblue'] = monochrome_logs ? '' : "\033[1;94m" + colorcodes['bipurple'] = monochrome_logs ? '' : "\033[1;95m" + colorcodes['bicyan'] = monochrome_logs ? '' : "\033[1;96m" + colorcodes['biwhite'] = monochrome_logs ? '' : "\033[1;97m" return colorcodes } @@ -261,14 +255,15 @@ def attachMultiqcReport(multiqc_report) { mqc_report = multiqc_report.getVal() if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { if (mqc_report.size() > 1) { - log.warn "[$workflow.manifest.name] Found multiple reports from process 'MULTIQC', will use only one" + log.warn("[${workflow.manifest.name}] Found multiple reports from process 'MULTIQC', will use only one") } mqc_report = mqc_report[0] } } - } catch (all) { + } + catch (Exception all) { if (multiqc_report) { - log.warn "[$workflow.manifest.name] Could not attach MultiQC report to summary email" + log.warn("[${workflow.manifest.name}] Could not attach MultiQC report to summary email") } } return mqc_report @@ -280,26 +275,35 @@ def attachMultiqcReport(multiqc_report) { def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdir, monochrome_logs=true, multiqc_report=null) { // Set up the e-mail variables - def subject = "[$workflow.manifest.name] Successful: $workflow.runName" + def subject = "[${workflow.manifest.name}] Successful: ${workflow.runName}" if (!workflow.success) { - subject = "[$workflow.manifest.name] FAILED: $workflow.runName" + subject = "[${workflow.manifest.name}] FAILED: ${workflow.runName}" } def summary = [:] - summary_params.keySet().sort().each { group -> - summary << summary_params[group] - } + summary_params + .keySet() + .sort() + .each { group -> + summary << summary_params[group] + } def misc_fields = [:] misc_fields['Date Started'] = workflow.start misc_fields['Date Completed'] = workflow.complete misc_fields['Pipeline script file path'] = workflow.scriptFile misc_fields['Pipeline script hash ID'] = workflow.scriptId - if (workflow.repository) misc_fields['Pipeline repository Git URL'] = workflow.repository - if (workflow.commitId) misc_fields['Pipeline repository Git Commit'] = workflow.commitId - if (workflow.revision) misc_fields['Pipeline Git branch/tag'] = workflow.revision - misc_fields['Nextflow Version'] = workflow.nextflow.version - misc_fields['Nextflow Build'] = workflow.nextflow.build + if (workflow.repository) { + misc_fields['Pipeline repository Git URL'] = workflow.repository + } + if (workflow.commitId) { + misc_fields['Pipeline repository Git Commit'] = workflow.commitId + } + if (workflow.revision) { + misc_fields['Pipeline Git branch/tag'] = workflow.revision + } + misc_fields['Nextflow Version'] = workflow.nextflow.version + misc_fields['Nextflow Build'] = workflow.nextflow.build misc_fields['Nextflow Compile Timestamp'] = workflow.nextflow.timestamp def email_fields = [:] @@ -337,7 +341,7 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi // Render the sendmail template def max_multiqc_email_size = (params.containsKey('max_multiqc_email_size') ? params.max_multiqc_email_size : 0) as nextflow.util.MemoryUnit - def smail_fields = [ email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "${workflow.projectDir}", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes() ] + def smail_fields = [email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "${workflow.projectDir}", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes()] def sf = new File("${workflow.projectDir}/assets/sendmail_template.txt") def sendmail_template = engine.createTemplate(sf).make(smail_fields) def sendmail_html = sendmail_template.toString() @@ -346,30 +350,32 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi def colors = logColours(monochrome_logs) as Map if (email_address) { try { - if (plaintext_email) { throw new org.codehaus.groovy.GroovyException('Send plaintext e-mail, not HTML') } + if (plaintext_email) { +new org.codehaus.groovy.GroovyException('Send plaintext e-mail, not HTML') } // Try to send HTML e-mail using sendmail def sendmail_tf = new File(workflow.launchDir.toString(), ".sendmail_tmp.html") sendmail_tf.withWriter { w -> w << sendmail_html } - [ 'sendmail', '-t' ].execute() << sendmail_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (sendmail)-" - } catch (all) { + ['sendmail', '-t'].execute() << sendmail_html + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Sent summary e-mail to ${email_address} (sendmail)-") + } + catch (Exception all) { // Catch failures and try with plaintext - def mail_cmd = [ 'mail', '-s', subject, '--content-type=text/html', email_address ] + def mail_cmd = ['mail', '-s', subject, '--content-type=text/html', email_address] mail_cmd.execute() << email_html - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Sent summary e-mail to $email_address (mail)-" + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Sent summary e-mail to ${email_address} (mail)-") } } // Write summary e-mail HTML to a file def output_hf = new File(workflow.launchDir.toString(), ".pipeline_report.html") output_hf.withWriter { w -> w << email_html } - nextflow.extension.FilesEx.copyTo(output_hf.toPath(), "${outdir}/pipeline_info/pipeline_report.html"); + nextflow.extension.FilesEx.copyTo(output_hf.toPath(), "${outdir}/pipeline_info/pipeline_report.html") output_hf.delete() // Write summary e-mail TXT to a file def output_tf = new File(workflow.launchDir.toString(), ".pipeline_report.txt") output_tf.withWriter { w -> w << email_txt } - nextflow.extension.FilesEx.copyTo(output_tf.toPath(), "${outdir}/pipeline_info/pipeline_report.txt"); + nextflow.extension.FilesEx.copyTo(output_tf.toPath(), "${outdir}/pipeline_info/pipeline_report.txt") output_tf.delete() } @@ -380,12 +386,14 @@ def completionSummary(monochrome_logs=true) { def colors = logColours(monochrome_logs) as Map if (workflow.success) { if (workflow.stats.ignoredCount == 0) { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.green} Pipeline completed successfully${colors.reset}-" - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-" + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Pipeline completed successfully${colors.reset}-") + } + else { + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.yellow} Pipeline completed successfully, but with errored process(es) ${colors.reset}-") } - } else { - log.info "-${colors.purple}[$workflow.manifest.name]${colors.red} Pipeline completed with errors${colors.reset}-" + } + else { + log.info("-${colors.purple}[${workflow.manifest.name}]${colors.red} Pipeline completed with errors${colors.reset}-") } } @@ -394,21 +402,30 @@ def completionSummary(monochrome_logs=true) { // def imNotification(summary_params, hook_url) { def summary = [:] - summary_params.keySet().sort().each { group -> - summary << summary_params[group] - } + summary_params + .keySet() + .sort() + .each { group -> + summary << summary_params[group] + } def misc_fields = [:] - misc_fields['start'] = workflow.start - misc_fields['complete'] = workflow.complete - misc_fields['scriptfile'] = workflow.scriptFile - misc_fields['scriptid'] = workflow.scriptId - if (workflow.repository) misc_fields['repository'] = workflow.repository - if (workflow.commitId) misc_fields['commitid'] = workflow.commitId - if (workflow.revision) misc_fields['revision'] = workflow.revision - misc_fields['nxf_version'] = workflow.nextflow.version - misc_fields['nxf_build'] = workflow.nextflow.build - misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp + misc_fields['start'] = workflow.start + misc_fields['complete'] = workflow.complete + misc_fields['scriptfile'] = workflow.scriptFile + misc_fields['scriptid'] = workflow.scriptId + if (workflow.repository) { + misc_fields['repository'] = workflow.repository + } + if (workflow.commitId) { + misc_fields['commitid'] = workflow.commitId + } + if (workflow.revision) { + misc_fields['revision'] = workflow.revision + } + misc_fields['nxf_version'] = workflow.nextflow.version + misc_fields['nxf_build'] = workflow.nextflow.build + misc_fields['nxf_timestamp'] = workflow.nextflow.timestamp def msg_fields = [:] msg_fields['version'] = getWorkflowVersion() @@ -433,13 +450,13 @@ def imNotification(summary_params, hook_url) { def json_message = json_template.toString() // POST - def post = new URL(hook_url).openConnection(); + def post = new URL(hook_url).openConnection() post.setRequestMethod("POST") post.setDoOutput(true) post.setRequestProperty("Content-Type", "application/json") - post.getOutputStream().write(json_message.getBytes("UTF-8")); - def postRC = post.getResponseCode(); - if (! postRC.equals(200)) { - log.warn(post.getErrorStream().getText()); + post.getOutputStream().write(json_message.getBytes("UTF-8")) + def postRC = post.getResponseCode() + if (!postRC.equals(200)) { + log.warn(post.getErrorStream().getText()) } } From 30a4a938a5881cd2557d325197f268e02df90757 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Fri, 11 Oct 2024 12:33:24 +0000 Subject: [PATCH 007/334] Template update for nf-core/tools version 3.0.2 --- .github/workflows/ci.yml | 60 +++++++++++++------ .../workflows/template_version_comment.yml | 21 ++++--- .gitignore | 1 + .nf-core.yml | 2 +- main.nf | 2 +- modules.json | 6 +- modules/nf-core/multiqc/main.nf | 2 +- nextflow.config | 4 +- .../utils_nfcore_datasync_pipeline/main.nf | 4 +- .../nf-core/utils_nextflow_pipeline/main.nf | 30 +++++----- .../nf-core/utils_nfcore_pipeline/main.nf | 10 ++-- workflows/datasync.nf | 2 - 12 files changed, 86 insertions(+), 58 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0775ffc..a85f12c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,8 @@ on: env: NXF_ANSI_LOG: false + NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity + NXF_SINGULARITY_LIBRARYDIR: ${{ github.workspace }}/.singularity concurrency: group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" @@ -18,7 +20,7 @@ concurrency: jobs: test: - name: Run pipeline with test data + name: "Run pipeline with test data (${{ matrix.NXF_VER }} | ${{ matrix.test_name }} | ${{ matrix.profile }})" # Only run on push if this is the nf-core dev branch (merged PRs) if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/datasync') }}" runs-on: ubuntu-latest @@ -27,33 +29,57 @@ jobs: NXF_VER: - "24.04.2" - "latest-everything" + profile: + - "conda" + - "docker" + - "singularity" + test_name: + - "test" + isMaster: + - ${{ github.base_ref == 'master' }} + # Exclude conda and singularity on dev + exclude: + - isMaster: false + profile: "conda" + - isMaster: false + profile: "singularity" steps: - name: Check out pipeline code uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - - name: Install Nextflow + - name: Set up Nextflow uses: nf-core/setup-nextflow@v2 with: version: "${{ matrix.NXF_VER }}" - - name: Disk space cleanup - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 + - name: Set up Apptainer + if: matrix.profile == 'singularity' + uses: eWaterCycle/setup-apptainer@main - - name: Run pipeline with test data (docker) - # TODO nf-core: You can customise CI pipeline run tests as required - # For example: adding multiple test runs with different parameters - # Remember that you can parallelise this by using strategy.matrix + - name: Set up Singularity + if: matrix.profile == 'singularity' run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results + mkdir -p $NXF_SINGULARITY_CACHEDIR + mkdir -p $NXF_SINGULARITY_LIBRARYDIR + + - 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: Run pipeline with test data (singularity) - # TODO nf-core: You can customise CI pipeline run tests as required + - name: Set up Conda + if: matrix.profile == 'conda' run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,singularity --outdir ./results - if: "${{ github.base_ref == 'master' }}" + echo $(realpath $CONDA)/condabin >> $GITHUB_PATH + echo $(realpath python) >> $GITHUB_PATH + + - name: Clean up Disk space + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - name: Run pipeline with test data (conda) - # TODO nf-core: You can customise CI pipeline run tests as required + - name: "Run pipeline with test data ${{ matrix.NXF_VER }} | ${{ matrix.test_name }} | ${{ matrix.profile }}" run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,conda --outdir ./results - if: "${{ github.base_ref == 'master' }}" + nextflow run ${GITHUB_WORKSPACE} -profile ${{ matrix.test_name }},${{ matrix.profile }} --outdir ./results diff --git a/.github/workflows/template_version_comment.yml b/.github/workflows/template_version_comment.yml index 9dea41f..e8aafe4 100644 --- a/.github/workflows/template_version_comment.yml +++ b/.github/workflows/template_version_comment.yml @@ -10,9 +10,11 @@ jobs: steps: - name: Check out pipeline code uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: Read template version from .nf-core.yml - uses: pietrobolcato/action-read-yaml@1.0.0 + uses: nichmor/minimal-read-yaml@v0.0.2 id: read_yml with: config: ${{ github.workspace }}/.nf-core.yml @@ -24,20 +26,21 @@ jobs: - name: Check nf-core outdated id: nf_core_outdated - run: pip list --outdated | grep nf-core + run: echo "OUTPUT=$(pip list --outdated | grep nf-core)" >> ${GITHUB_ENV} - name: Post nf-core template version comment uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 if: | - ${{ steps.nf_core_outdated.outputs.stdout }} =~ 'nf-core' + contains(env.OUTPUT, 'nf-core') with: repo-token: ${{ secrets.NF_CORE_BOT_AUTH_TOKEN }} allow-repeats: false message: | - ## :warning: Newer version of the nf-core template is available. - - Your pipeline is using an old version of the nf-core template: ${{ steps.read_yml.outputs['nf_core_version'] }}. - Please update your pipeline to the latest version. - - For more documentation on how to update your pipeline, please see the [nf-core documentation](https://github.com/nf-core/tools?tab=readme-ov-file#sync-a-pipeline-with-the-template) and [Synchronisation documentation](https://nf-co.re/docs/contributing/sync). + > [!WARNING] + > Newer version of the nf-core template is available. + > + > Your pipeline is using an old version of the nf-core template: ${{ steps.read_yml.outputs['nf_core_version'] }}. + > Please update your pipeline to the latest version. + > + > For more documentation on how to update your pipeline, please see the [nf-core documentation](https://github.com/nf-core/tools?tab=readme-ov-file#sync-a-pipeline-with-the-template) and [Synchronisation documentation](https://nf-co.re/docs/contributing/sync). # diff --git a/.gitignore b/.gitignore index 5124c9a..a42ce01 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ results/ testing/ testing* *.pyc +null/ diff --git a/.nf-core.yml b/.nf-core.yml index 3ff21da..ca377ca 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,6 +1,6 @@ bump_version: null lint: null -nf_core_version: 3.0.1 +nf_core_version: 3.0.2 org_path: null repository_type: pipeline template: diff --git a/main.nf b/main.nf index f0ac265..e23a4c6 100644 --- a/main.nf +++ b/main.nf @@ -76,7 +76,7 @@ workflow { params.outdir, params.input ) - + // // WORKFLOW: Run main workflow // diff --git a/modules.json b/modules.json index 1ad83c6..3341e8c 100644 --- a/modules.json +++ b/modules.json @@ -12,7 +12,7 @@ }, "multiqc": { "branch": "master", - "git_sha": "b8d36829fa84b6e404364abff787e8b07f6d058c", + "git_sha": "cf17ca47590cc578dfb47db1c2a44ef86f89976d", "installed_by": ["modules"] } } @@ -21,12 +21,12 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "9d05360da397692321d377b6102d2fb22507c6ef", + "git_sha": "3aa0aec1d52d492fe241919f0c6100ebf0074082", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "772684d9d66f37b650c8ba5146ac1ee3ecba2acb", + "git_sha": "1b6b9a3338d011367137808b49b923515080e3ba", "installed_by": ["subworkflows"] }, "utils_nfschema_plugin": { diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 9724d2f..cc0643e 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -52,7 +52,7 @@ process MULTIQC { stub: """ mkdir multiqc_data - touch multiqc_plots + mkdir multiqc_plots touch multiqc_report.html cat <<-END_VERSIONS > versions.yml diff --git a/nextflow.config b/nextflow.config index 243891f..bca2a3d 100644 --- a/nextflow.config +++ b/nextflow.config @@ -254,10 +254,10 @@ validation { """ afterText = """${manifest.doi ? "* The pipeline\n" : ""}${manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${manifest.doi ? "\n" : ""} * The nf-core framework - https://doi.org/10.1038/s41587-020-0439-x + https://doi.org/10.1038/s41587-020-0439-x * Software dependencies - https://github.com/${manifest.name}/blob/master/CITATIONS.md + https://github.com/${manifest.name}/blob/master/CITATIONS.md """ } summary { diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index 1cd554a..e9c4b16 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -47,7 +47,6 @@ workflow PIPELINE_INITIALISATION { workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1 ) - // // Validate parameters and generate parameter summary to stdout // @@ -56,7 +55,6 @@ workflow PIPELINE_INITIALISATION { validate_params, null ) - // // Check config provided to the pipeline @@ -64,6 +62,7 @@ workflow PIPELINE_INITIALISATION { UTILS_NFCORE_PIPELINE ( nextflow_cli_args ) + // // Custom validation for pipeline parameters // @@ -110,7 +109,6 @@ workflow PIPELINE_COMPLETION { email // string: email address email_on_fail // string: email address sent on pipeline failure plaintext_email // boolean: Send plain-text email instead of HTML - outdir // path: Path to output directory where results will be published monochrome_logs // boolean: Disable ANSI colour codes in log output hook_url // string: hook URL for notifications diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf index 2b0dc67..0fcbf7b 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf @@ -3,9 +3,9 @@ // /* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW DEFINITION -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow UTILS_NEXTFLOW_PIPELINE { @@ -44,9 +44,9 @@ workflow UTILS_NEXTFLOW_PIPELINE { } /* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FUNCTIONS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ // @@ -106,17 +106,19 @@ def checkCondaChannels() { def channels_missing = ((required_channels_in_order as Set) - (channels as Set)) as Boolean // Check that they are in the right order - def channel_priority_violation = false - - required_channels_in_order.eachWithIndex { channel, index -> - if (index < required_channels_in_order.size() - 1) { - channel_priority_violation |= !(channels.indexOf(channel) < channels.indexOf(required_channels_in_order[index + 1])) - } - } + def channel_priority_violation = required_channels_in_order != channels.findAll { ch -> ch in required_channels_in_order } if (channels_missing | channel_priority_violation) { - log.warn( - "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" + " There is a problem with your Conda configuration!\n\n" + " You will need to set-up the conda-forge and bioconda channels correctly.\n" + " Please refer to https://bioconda.github.io/\n" + " The observed channel order is \n" + " ${channels}\n" + " but the following channel order is required:\n" + " ${required_channels_in_order}\n" + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - ) + log.warn """\ + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + There is a problem with your Conda configuration! + You will need to set-up the conda-forge and bioconda channels correctly. + Please refer to https://bioconda.github.io/ + The observed channel order is + ${channels} + but the following channel order is required: + ${required_channels_in_order} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + """.stripIndent(true) } } diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index b78273c..5cb7baf 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -3,9 +3,9 @@ // /* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBWORKFLOW DEFINITION -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ workflow UTILS_NFCORE_PIPELINE { @@ -21,9 +21,9 @@ workflow UTILS_NFCORE_PIPELINE { } /* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FUNCTIONS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ // @@ -62,7 +62,7 @@ def checkProfileProvided(nextflow_cli_args) { def workflowCitation() { def temp_doi_ref = "" def manifest_doi = workflow.manifest.doi.tokenize(",") - // Using a loop to handle multiple DOIs + // Handling multiple DOIs // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers // Removing ` ` since the manifest.doi is a string and not a proper list manifest_doi.each { doi_ref -> diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 72a96bf..43f6b82 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -57,13 +57,11 @@ workflow DATASYNC { Channel.fromPath(params.multiqc_logo, checkIfExists: true) : Channel.empty() - summary_params = paramsSummaryMap( workflow, parameters_schema: "nextflow_schema.json") ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) ch_multiqc_files = ch_multiqc_files.mix( ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) - ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) From 978ec0458138d863c57f52b9929d03e305ed24fa Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Wed, 11 Dec 2024 10:43:35 +0000 Subject: [PATCH 008/334] [automated] Fix code linting --- modules.json | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/modules.json b/modules.json index cf418e3..2c7e85c 100644 --- a/modules.json +++ b/modules.json @@ -8,9 +8,7 @@ "multiqc": { "branch": "master", "git_sha": "cf17ca47590cc578dfb47db1c2a44ef86f89976d", - "installed_by": [ - "modules" - ] + "installed_by": ["modules"] } } }, @@ -19,23 +17,17 @@ "utils_nextflow_pipeline": { "branch": "master", "git_sha": "3aa0aec1d52d492fe241919f0c6100ebf0074082", - "installed_by": [ - "subworkflows" - ] + "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", "git_sha": "1b6b9a3338d011367137808b49b923515080e3ba", - "installed_by": [ - "subworkflows" - ] + "installed_by": ["subworkflows"] }, "utils_nfschema_plugin": { "branch": "master", "git_sha": "bbd5a41f4535a8defafe6080e00ea74c45f4f96c", - "installed_by": [ - "subworkflows" - ] + "installed_by": ["subworkflows"] } } } From cff421b83b4c285e198a5fb8778b64e126bec420 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Thu, 12 Dec 2024 11:22:47 +0000 Subject: [PATCH 009/334] Template update for nf-core/tools version 3.1.0 --- .github/CONTRIBUTING.md | 12 +- .github/workflows/awsfulltest.yml | 21 +- .github/workflows/branch.yml | 18 +- .github/workflows/ci.yml | 2 +- .github/workflows/download_pipeline.yml | 8 +- .github/workflows/fix-linting.yml | 4 +- .github/workflows/linting.yml | 10 +- .github/workflows/linting_comment.yml | 2 +- .github/workflows/release-announcements.yml | 2 +- .../workflows/template_version_comment.yml | 2 +- .gitpod.yml | 11 +- .nf-core.yml | 7 +- .vscode/settings.json | 3 + conf/base.config | 2 +- conf/modules.config | 1 + docs/usage.md | 32 +- modules.json | 8 +- modules/nf-core/fastqc/main.nf | 2 +- modules/nf-core/fastqc/meta.yml | 1 + nextflow.config | 45 ++- nextflow_schema.json | 6 + ro-crate-metadata.json | 311 ++++++++++++++++++ .../utils_nfcore_datasync_pipeline/main.nf | 7 +- .../nf-core/utils_nextflow_pipeline/main.nf | 2 + .../tests/main.workflow.nf.test | 10 +- .../nf-core/utils_nfcore_pipeline/main.nf | 89 ++--- .../tests/main.function.nf.test | 46 ++- .../tests/main.function.nf.test.snap | 30 -- .../utils_nfschema_plugin/tests/main.nf.test | 4 +- workflows/datasync.nf | 2 +- 30 files changed, 481 insertions(+), 219 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 ro-crate-metadata.json diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 3825d0f..04e0dfc 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# nf-core/datasync: Contributing Guidelines +# `nf-core/datasync`: Contributing Guidelines Hi there! Many thanks for taking an interest in improving nf-core/datasync. @@ -55,9 +55,9 @@ These tests are run both with the latest available version of `Nextflow` and als :warning: Only in the unlikely and regretful event of a release happening with a bug. -- On your own fork, make a new branch `patch` based on `upstream/master`. +- On your own fork, make a new branch `patch` based on `upstream/main` or `upstream/master`. - Fix the bug, and bump version (X.Y.Z+1). -- A PR should be made on `master` from patch to directly this particular bug. +- Open a pull-request from `patch` to `main`/`master` with the changes. ## Getting help @@ -65,13 +65,13 @@ For further information/help, please consult the [nf-core/datasync documentation ## Pipeline contribution conventions -To make the nf-core/datasync code and processing logic more understandable for new contributors and to ensure quality, we semi-standardise the way the code and other contributions are written. +To make the `nf-core/datasync` code and processing logic more understandable for new contributors and to ensure quality, we semi-standardise the way the code and other contributions are written. ### Adding a new step If you wish to contribute a new step, please use the following coding standards: -1. Define the corresponding input channel into your new process from the expected previous process channel +1. Define the corresponding input channel into your new process from the expected previous process channel. 2. Write the process block (see below). 3. Define the output channel if needed (see below). 4. Add any new parameters to `nextflow.config` with a default (see below). @@ -84,7 +84,7 @@ If you wish to contribute a new step, please use the following coding standards: ### Default values -Parameters should be initialised / defined with default values in `nextflow.config` under the `params` scope. +Parameters should be initialised / defined with default values within the `params` scope in `nextflow.config`. Once there, use `nf-core pipelines schema build` to add to `nextflow_schema.json`. diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index d01f992..1fb97f5 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -1,11 +1,12 @@ name: nf-core AWS full size tests -# This workflow is triggered on PRs opened against the master branch. +# This workflow is triggered on PRs opened against the main/master branch. # It can be additionally triggered manually with GitHub actions workflow dispatch button. # It runs the -profile 'test_full' on AWS batch on: pull_request: branches: + - main - master workflow_dispatch: pull_request_review: @@ -18,18 +19,30 @@ jobs: if: github.repository == 'nf-core/datasync' && github.event.review.state == 'approved' && github.event.pull_request.base.ref == 'master' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: - - uses: octokit/request-action@v2.x + - name: Get PR reviews + uses: octokit/request-action@v2.x + if: github.event_name != 'workflow_dispatch' id: check_approvals + continue-on-error: true with: - route: GET /repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews + route: GET /repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews?per_page=100 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - id: test_variables + + - name: Check for approvals + if: ${{ failure() && github.event_name != 'workflow_dispatch' }} + run: | + echo "No review approvals found. At least 2 approvals are required to run this action automatically." + exit 1 + + - name: Check for enough approvals (>=2) + id: test_variables if: github.event_name != 'workflow_dispatch' run: | JSON_RESPONSE='${{ steps.check_approvals.outputs.data }}' CURRENT_APPROVALS_COUNT=$(echo $JSON_RESPONSE | jq -c '[.[] | select(.state | contains("APPROVED")) ] | length') test $CURRENT_APPROVALS_COUNT -ge 2 || exit 1 # At least 2 approvals are required + - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 # TODO nf-core: You can customise AWS full pipeline tests as required diff --git a/.github/workflows/branch.yml b/.github/workflows/branch.yml index 8efcff7..72e58e1 100644 --- a/.github/workflows/branch.yml +++ b/.github/workflows/branch.yml @@ -1,15 +1,17 @@ name: nf-core branch protection -# This workflow is triggered on PRs to master branch on the repository -# It fails when someone tries to make a PR against the nf-core `master` branch instead of `dev` +# This workflow is triggered on PRs to `main`/`master` branch on the repository +# It fails when someone tries to make a PR against the nf-core `main`/`master` branch instead of `dev` on: pull_request_target: - branches: [master] + branches: + - main + - master jobs: test: runs-on: ubuntu-latest steps: - # PRs to the nf-core repo master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches + # PRs to the nf-core repo main/master branch are only ok if coming from the nf-core repo `dev` or any `patch` branches - name: Check PRs if: github.repository == 'nf-core/datasync' run: | @@ -22,7 +24,7 @@ jobs: uses: mshick/add-pr-comment@b8f338c590a895d50bcbfa6c5859251edc8952fc # v2 with: message: | - ## This PR is against the `master` branch :x: + ## This PR is against the `${{github.event.pull_request.base.ref}}` branch :x: * Do not close this PR * Click _Edit_ and change the `base` to `dev` @@ -32,9 +34,9 @@ jobs: Hi @${{ github.event.pull_request.user.login }}, - It looks like this pull-request is has been made against the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) `master` branch. - The `master` branch on nf-core repositories should always contain code from the latest release. - Because of this, PRs to `master` are only allowed if they come from the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) `dev` branch. + It looks like this pull-request is has been made against the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) ${{github.event.pull_request.base.ref}} branch. + The ${{github.event.pull_request.base.ref}} branch on nf-core repositories should always contain code from the latest release. + Because of this, PRs to ${{github.event.pull_request.base.ref}} are only allowed if they come from the [${{github.event.pull_request.head.repo.full_name }}](https://github.com/${{github.event.pull_request.head.repo.full_name }}) `dev` branch. You do not need to close this PR, you can change the target branch to `dev` by clicking the _"Edit"_ button at the top of this page. Note that even after this, the test will continue to show as failing until you push a new commit. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a85f12c..137b8f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: profile: "singularity" steps: - name: Check out pipeline code - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Set up Nextflow uses: nf-core/setup-nextflow@v2 diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 713dc3e..2576cc0 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -2,7 +2,7 @@ name: Test successful pipeline download with 'nf-core pipelines download' # Run the workflow when: # - dispatched manually -# - when a PR is opened or reopened to master branch +# - when a PR is opened or reopened to main/master branch # - the head branch of the pull request is updated, i.e. if fixes for a release are pushed last minute to dev. on: workflow_dispatch: @@ -17,9 +17,11 @@ on: - edited - synchronize branches: + - main - master pull_request_target: branches: + - main - master env: @@ -35,7 +37,7 @@ jobs: - name: Disk space cleanup uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 + - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 with: python-version: "3.12" architecture: "x64" @@ -69,7 +71,7 @@ jobs: --outdir ./${{ env.REPOTITLE_LOWERCASE }} \ --compress "none" \ --container-system 'singularity' \ - --container-library "quay.io" -l "docker.io" -l "community.wave.seqera.io" \ + --container-library "quay.io" -l "docker.io" -l "community.wave.seqera.io/library/" \ --container-cache-utilisation 'amend' \ --download-configuration 'yes' diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix-linting.yml index e7e5b56..1f3206f 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix-linting.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: token: ${{ secrets.nf_core_bot_auth_token }} @@ -32,7 +32,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} # Install and run pre-commit - - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 + - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 with: python-version: "3.12" diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index a502573..dbd52d5 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -14,10 +14,10 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Set up Python 3.12 - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 with: python-version: "3.12" @@ -31,12 +31,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Install Nextflow uses: nf-core/setup-nextflow@v2 - - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 + - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 with: python-version: "3.12" architecture: "x64" @@ -74,7 +74,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 42e519b..0bed96d 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@bf251b5aa9c2f7eeb574a96ee720e24f801b7c11 # v6 + uses: dawidd6/action-download-artifact@80620a5d27ce0ae443b965134db88467fc607b43 # v7 with: workflow: linting.yml workflow_conclusion: completed diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index c6ba35d..450b1d5 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5 + - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 with: python-version: "3.10" - name: Install dependencies diff --git a/.github/workflows/template_version_comment.yml b/.github/workflows/template_version_comment.yml index e8aafe4..537529b 100644 --- a/.github/workflows/template_version_comment.yml +++ b/.github/workflows/template_version_comment.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: ref: ${{ github.event.pull_request.head.sha }} diff --git a/.gitpod.yml b/.gitpod.yml index 4611863..83599f6 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -6,12 +6,5 @@ tasks: nextflow self-update vscode: - extensions: # based on nf-core.nf-core-extensionpack - #- esbenp.prettier-vscode # Markdown/CommonMark linting and style checking for Visual Studio Code - - EditorConfig.EditorConfig # override user/workspace settings with settings found in .editorconfig files - - Gruntfuggly.todo-tree # Display TODO and FIXME in a tree view in the activity bar - - mechatroner.rainbow-csv # Highlight columns in csv files in different colors - - nextflow.nextflow # Nextflow syntax highlighting - - oderwat.indent-rainbow # Highlight indentation level - - streetsidesoftware.code-spell-checker # Spelling checker for source code - - charliermarsh.ruff # Code linter Ruff + extensions: + - nf-core.nf-core-extensionpack # https://github.com/nf-core/vscode-extensionpack diff --git a/.nf-core.yml b/.nf-core.yml index ca377ca..9fad3e1 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,7 +1,4 @@ -bump_version: null -lint: null -nf_core_version: 3.0.2 -org_path: null +nf_core_version: 3.1.0 repository_type: pipeline template: author: Alexander Peltzer @@ -12,6 +9,4 @@ template: name: datasync org: nf-core outdir: . - skip_features: null version: 1.0dev -update: null diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a33b527 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "markdown.styles": ["public/vscode_markdown.css"] +} diff --git a/conf/base.config b/conf/base.config index 6b945e8..3f8e13e 100644 --- a/conf/base.config +++ b/conf/base.config @@ -20,7 +20,7 @@ process { maxErrors = '-1' // Process-specific resource requirements - // NOTE - Please try and re-use the labels below as much as possible. + // NOTE - Please try and reuse the labels below as much as possible. // These labels are used and recognised by default in DSL2 files hosted on nf-core/modules. // If possible, it would be nice to keep the same label naming convention when // adding in your local modules too. diff --git a/conf/modules.config b/conf/modules.config index d266a38..d203d2b 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -21,6 +21,7 @@ process { withName: FASTQC { ext.args = '--quiet' } + withName: 'MULTIQC' { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ diff --git a/docs/usage.md b/docs/usage.md index 37bfe04..e575084 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -75,9 +75,8 @@ If you wish to repeatedly use the same parameters for multiple runs, rather than Pipeline settings can be provided in a `yaml` or `json` file via `-params-file `. -:::warning -Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). -::: +> [!WARNING] +> Do not use `-c ` to specify parameters as this will result in errors. Custom config files specified with `-c` must only be used for [tuning process resource specifications](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources), other infrastructural tweaks (such as output directories), or module arguments (args). The above pipeline run specified with a params file in yaml format: @@ -106,23 +105,21 @@ nextflow pull nf-core/datasync ### Reproducibility -It is a good idea to specify a pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. +It is a good idea to specify the pipeline version when running the pipeline on your data. This ensures that a specific version of the pipeline code and software are used when you run your pipeline. If you keep using the same tag, you'll be running the same version of the pipeline, even if there have been changes to the code since. First, go to the [nf-core/datasync releases page](https://github.com/nf-core/datasync/releases) and find the latest pipeline version - numeric only (eg. `1.3.1`). Then specify this when running the pipeline with `-r` (one hyphen) - eg. `-r 1.3.1`. Of course, you can switch to another version by changing the number after the `-r` flag. This version number will be logged in reports when you run the pipeline, so that you'll know what you used when you look back in the future. For example, at the bottom of the MultiQC reports. -To further assist in reproducbility, you can use share and re-use [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. +To further assist in reproducibility, you can use share and reuse [parameter files](#running-the-pipeline) to repeat pipeline runs with the same settings without having to write out a command with every single parameter. -:::tip -If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. -::: +> [!TIP] +> If you wish to share such profile (such as upload as supplementary material for academic publications), make sure to NOT include cluster specific paths to files, nor institutional specific profiles. ## Core Nextflow arguments -:::note -These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen). -::: +> [!NOTE] +> These options are part of Nextflow and use a _single_ hyphen (pipeline parameters use a double-hyphen) ### `-profile` @@ -130,16 +127,15 @@ 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. -:::info -We highly recommend the use of Docker or Singularity containers for full pipeline reproducibility, however when this is not possible, Conda is also supported. -::: +> [!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. -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 see if your system is available in these configs please see the [nf-core/configs documentation](https://github.com/nf-core/configs#documentation). +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 suported, please see the [nf-core/configs documentation](https://github.com/nf-core/configs#documentation). Note that multiple profiles can be loaded, for example: `-profile test,docker` - the order of arguments is important! They are loaded in sequence, so later profiles can overwrite earlier profiles. -If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer enviroment. +If `-profile` is not specified, the pipeline will run locally and expect all software to be installed and available on the `PATH`. This is _not_ recommended, since it can lead to different results on different machines dependent on the computer environment. - `test` - A profile with a complete configuration for automated testing @@ -175,13 +171,13 @@ Specify the path to a specific config file (this is a core Nextflow command). Se ### Resource requests -Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the steps in the pipeline, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher requests (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. +Whilst the default requirements set within the pipeline will hopefully work for most people and with most input data, you may find that you want to customise the compute resources that the pipeline requests. Each step in the pipeline has a default set of requirements for number of CPUs, memory and time. For most of the pipeline steps, if the job exits with any of the error codes specified [here](https://github.com/nf-core/rnaseq/blob/4c27ef5610c87db00c3c5a3eed10b1d161abf575/conf/base.config#L18) it will automatically be resubmitted with higher resources request (2 x original, then 3 x original). If it still fails after the third attempt then the pipeline execution is stopped. To change the resource requests, please see the [max resources](https://nf-co.re/docs/usage/configuration#max-resources) and [tuning workflow resources](https://nf-co.re/docs/usage/configuration#tuning-workflow-resources) section of the nf-core website. ### Custom Containers -In some cases you may wish to change which container or conda environment a step of the pipeline uses for a particular tool. By default nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However in some cases the pipeline specified version maybe out of date. +In some cases, you may wish to change the container or conda environment used by a pipeline steps for a particular tool. By default, nf-core pipelines use containers and software from the [biocontainers](https://biocontainers.pro/) or [bioconda](https://bioconda.github.io/) projects. However, in some cases the pipeline specified version maybe out of date. To use a different container from the default container or conda environment specified in a pipeline, please see the [updating tool versions](https://nf-co.re/docs/usage/configuration#updating-tool-versions) section of the nf-core website. diff --git a/modules.json b/modules.json index 3341e8c..9eb34fb 100644 --- a/modules.json +++ b/modules.json @@ -7,7 +7,7 @@ "nf-core": { "fastqc": { "branch": "master", - "git_sha": "666652151335353eef2fcd58880bcef5bc2928e1", + "git_sha": "dc94b6ee04a05ddb9f7ae050712ff30a13149164", "installed_by": ["modules"] }, "multiqc": { @@ -21,17 +21,17 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "3aa0aec1d52d492fe241919f0c6100ebf0074082", + "git_sha": "c2b22d85f30a706a3073387f30380704fcae013b", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "1b6b9a3338d011367137808b49b923515080e3ba", + "git_sha": "51ae5406a030d4da1e49e4dab49756844fdd6c7a", "installed_by": ["subworkflows"] }, "utils_nfschema_plugin": { "branch": "master", - "git_sha": "bbd5a41f4535a8defafe6080e00ea74c45f4f96c", + "git_sha": "2fd2cd6d0e7b273747f32e465fdc6bcc3ae0814e", "installed_by": ["subworkflows"] } } diff --git a/modules/nf-core/fastqc/main.nf b/modules/nf-core/fastqc/main.nf index d8989f4..752c3a1 100644 --- a/modules/nf-core/fastqc/main.nf +++ b/modules/nf-core/fastqc/main.nf @@ -24,7 +24,7 @@ process FASTQC { // Make list of old name and new name pairs to use for renaming in the bash while loop def old_new_pairs = reads instanceof Path || reads.size() == 1 ? [[ reads, "${prefix}.${reads.extension}" ]] : reads.withIndex().collect { entry, index -> [ entry, "${prefix}_${index + 1}.${entry.extension}" ] } def rename_to = old_new_pairs*.join(' ').join(' ') - def renamed_files = old_new_pairs.collect{ old_name, new_name -> new_name }.join(' ') + def renamed_files = old_new_pairs.collect{ _old_name, new_name -> new_name }.join(' ') // The total amount of allocated RAM by FastQC is equal to the number of threads defined (--threads) time the amount of RAM defined (--memory) // https://github.com/s-andrews/FastQC/blob/1faeea0412093224d7f6a07f777fad60a5650795/fastqc#L211-L222 diff --git a/modules/nf-core/fastqc/meta.yml b/modules/nf-core/fastqc/meta.yml index 4827da7..2b2e62b 100644 --- a/modules/nf-core/fastqc/meta.yml +++ b/modules/nf-core/fastqc/meta.yml @@ -11,6 +11,7 @@ tools: FastQC gives general quality metrics about your reads. It provides information about the quality score distribution across your reads, the per base sequence content (%A/C/G/T). + You get information about adapter contamination and other overrepresented sequences. homepage: https://www.bioinformatics.babraham.ac.uk/projects/fastqc/ diff --git a/nextflow.config b/nextflow.config index bca2a3d..5cd47e9 100644 --- a/nextflow.config +++ b/nextflow.config @@ -38,8 +38,7 @@ params { show_hidden = false version = false pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' - - // Config options + trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss')// Config options config_profile_name = null config_profile_description = null @@ -153,6 +152,13 @@ profiles { executor.name = 'local' executor.cpus = 4 executor.memory = 8.GB + process { + resourceLimits = [ + memory: 8.GB, + cpus : 4, + time : 1.h + ] + } } test { includeConfig 'conf/test.config' } test_full { includeConfig 'conf/test_full.config' } @@ -201,30 +207,41 @@ set -C # No clobber - prevent output redirection from overwriting files. // Disable process selector warnings by default. Use debug profile to enable warnings. nextflow.enable.configProcessNamesValidation = false -def trace_timestamp = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') timeline { enabled = true - file = "${params.outdir}/pipeline_info/execution_timeline_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/execution_timeline_${params.trace_report_suffix}.html" } report { enabled = true - file = "${params.outdir}/pipeline_info/execution_report_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/execution_report_${params.trace_report_suffix}.html" } trace { enabled = true - file = "${params.outdir}/pipeline_info/execution_trace_${trace_timestamp}.txt" + file = "${params.outdir}/pipeline_info/execution_trace_${params.trace_report_suffix}.txt" } dag { enabled = true - file = "${params.outdir}/pipeline_info/pipeline_dag_${trace_timestamp}.html" + file = "${params.outdir}/pipeline_info/pipeline_dag_${params.trace_report_suffix}.html" } manifest { name = 'nf-core/datasync' - author = """Alexander Peltzer""" + author = """Alexander Peltzer""" // The author field is deprecated from Nextflow version 24.10.0, use contributors instead + contributors = [ + // TODO nf-core: Update the field with the details of the contributors to your pipeline. New with Nextflow version 24.10.0 + [ + name: 'Alexander Peltzer', + affiliation: '', + email: '', + github: '', + contribution: [], // List of contribution types ('author', 'maintainer' or 'contributor') + orcid: '' + ], + ] homePage = 'https://github.com/nf-core/datasync' description = """A simple sysops pipeline that can be used to synchronize, integrity check and permanently archive data.""" mainScript = 'main.nf' + defaultBranch = 'master' nextflowVersion = '!>=24.04.2' version = '1.0dev' doi = '' @@ -237,9 +254,10 @@ plugins { validation { defaultIgnoreParams = ["genomes"] + monochromeLogs = params.monochrome_logs help { enabled = true - command = "nextflow run $manifest.name -profile --input samplesheet.csv --outdir " + command = "nextflow run nf-core/datasync -profile --input samplesheet.csv --outdir " fullParameter = "help_full" showHiddenParameter = "show_hidden" beforeText = """ @@ -249,15 +267,15 @@ validation { \033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m \033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m \033[0;32m`._,._,\'\033[0m -\033[0;35m ${manifest.name} ${manifest.version}\033[0m +\033[0;35m nf-core/datasync ${manifest.version}\033[0m -\033[2m----------------------------------------------------\033[0m- """ - afterText = """${manifest.doi ? "* The pipeline\n" : ""}${manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${manifest.doi ? "\n" : ""} + afterText = """${manifest.doi ? "\n* The pipeline\n" : ""}${manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${manifest.doi ? "\n" : ""} * The nf-core framework https://doi.org/10.1038/s41587-020-0439-x * Software dependencies - https://github.com/${manifest.name}/blob/master/CITATIONS.md + https://github.com/nf-core/datasync/blob/master/CITATIONS.md """ } summary { @@ -265,6 +283,3 @@ validation { afterText = validation.help.afterText } } - -// Load modules.config for DSL2 module specific options -includeConfig 'conf/modules.config' diff --git a/nextflow_schema.json b/nextflow_schema.json index f9cb916..d9e3dd8 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -218,6 +218,12 @@ "description": "Base URL or local path to location of pipeline test dataset files", "default": "https://raw.githubusercontent.com/nf-core/test-datasets/", "hidden": true + }, + "trace_report_suffix": { + "type": "string", + "fa_icon": "far calendar", + "description": "Suffix to add to the trace report filename. Default is the date and time in the format yyyy-MM-dd_HH-mm-ss.", + "hidden": true } } } diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json new file mode 100644 index 0000000..4b09e1c --- /dev/null +++ b/ro-crate-metadata.json @@ -0,0 +1,311 @@ +{ + "@context": [ + "https://w3id.org/ro/crate/1.1/context", + { + "GithubService": "https://w3id.org/ro/terms/test#GithubService", + "JenkinsService": "https://w3id.org/ro/terms/test#JenkinsService", + "PlanemoEngine": "https://w3id.org/ro/terms/test#PlanemoEngine", + "TestDefinition": "https://w3id.org/ro/terms/test#TestDefinition", + "TestInstance": "https://w3id.org/ro/terms/test#TestInstance", + "TestService": "https://w3id.org/ro/terms/test#TestService", + "TestSuite": "https://w3id.org/ro/terms/test#TestSuite", + "TravisService": "https://w3id.org/ro/terms/test#TravisService", + "definition": "https://w3id.org/ro/terms/test#definition", + "engineVersion": "https://w3id.org/ro/terms/test#engineVersion", + "instance": "https://w3id.org/ro/terms/test#instance", + "resource": "https://w3id.org/ro/terms/test#resource", + "runsOn": "https://w3id.org/ro/terms/test#runsOn" + } + ], + "@graph": [ + { + "@id": "./", + "@type": "Dataset", + "creativeWorkStatus": "InProgress", + "datePublished": "2024-12-12T11:22:33+00:00", + "description": "

    \n \n \n \"nf-core/datasync\"\n \n

    \n\n[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![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/datasync)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23datasync-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/datasync)[![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/datasync** is a bioinformatics pipeline that ...\n\n\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))\n2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\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\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/datasync \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\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/datasync/usage) and the [parameter documentation](https://nf-co.re/datasync/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/datasync/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/datasync/output).\n\n## Credits\n\nnf-core/datasync was originally written by Alexander Peltzer.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\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 `#datasync` channel](https://nfcore.slack.com/channels/datasync) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\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", + "hasPart": [ + { + "@id": "main.nf" + }, + { + "@id": "assets/" + }, + { + "@id": "conf/" + }, + { + "@id": "docs/" + }, + { + "@id": "docs/images/" + }, + { + "@id": "modules/" + }, + { + "@id": "modules/nf-core/" + }, + { + "@id": "workflows/" + }, + { + "@id": "subworkflows/" + }, + { + "@id": "nextflow.config" + }, + { + "@id": "README.md" + }, + { + "@id": "nextflow_schema.json" + }, + { + "@id": "CHANGELOG.md" + }, + { + "@id": "LICENSE" + }, + { + "@id": "CODE_OF_CONDUCT.md" + }, + { + "@id": "CITATIONS.md" + }, + { + "@id": "modules.json" + }, + { + "@id": "docs/usage.md" + }, + { + "@id": "docs/output.md" + }, + { + "@id": ".nf-core.yml" + }, + { + "@id": ".pre-commit-config.yaml" + }, + { + "@id": ".prettierignore" + } + ], + "isBasedOn": "https://github.com/nf-core/datasync", + "license": "MIT", + "mainEntity": { + "@id": "main.nf" + }, + "mentions": [ + { + "@id": "#9f490429-3d14-493a-b124-be2775fcbd2f" + } + ], + "name": "nf-core/datasync" + }, + { + "@id": "ro-crate-metadata.json", + "@type": "CreativeWork", + "about": { + "@id": "./" + }, + "conformsTo": [ + { + "@id": "https://w3id.org/ro/crate/1.1" + }, + { + "@id": "https://w3id.org/workflowhub/workflow-ro-crate/1.0" + } + ] + }, + { + "@id": "main.nf", + "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "creator": [ + { + "@id": "https://orcid.org/0000-0002-6503-2180" + } + ], + "dateCreated": "", + "dateModified": "2024-12-12T11:22:33Z", + "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", + "keywords": ["nf-core", "nextflow"], + "license": ["MIT"], + "maintainer": [ + { + "@id": "https://orcid.org/0000-0002-6503-2180" + } + ], + "name": ["nf-core/datasync"], + "programmingLanguage": { + "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" + }, + "sdPublisher": { + "@id": "https://nf-co.re/" + }, + "url": ["https://github.com/nf-core/datasync", "https://nf-co.re/datasync/dev/"], + "version": ["1.0dev"] + }, + { + "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow", + "@type": "ComputerLanguage", + "identifier": { + "@id": "https://www.nextflow.io/" + }, + "name": "Nextflow", + "url": { + "@id": "https://www.nextflow.io/" + }, + "version": "!>=24.04.2" + }, + { + "@id": "#9f490429-3d14-493a-b124-be2775fcbd2f", + "@type": "TestSuite", + "instance": [ + { + "@id": "#de2f5e14-73b2-45aa-9f4c-e1a1c17e3843" + } + ], + "mainEntity": { + "@id": "main.nf" + }, + "name": "Test suite for nf-core/datasync" + }, + { + "@id": "#de2f5e14-73b2-45aa-9f4c-e1a1c17e3843", + "@type": "TestInstance", + "name": "GitHub Actions workflow for testing nf-core/datasync", + "resource": "repos/nf-core/datasync/actions/workflows/ci.yml", + "runsOn": { + "@id": "https://w3id.org/ro/terms/test#GithubService" + }, + "url": "https://api.github.com" + }, + { + "@id": "https://w3id.org/ro/terms/test#GithubService", + "@type": "TestService", + "name": "Github Actions", + "url": { + "@id": "https://github.com" + } + }, + { + "@id": "assets/", + "@type": "Dataset", + "description": "Additional files" + }, + { + "@id": "conf/", + "@type": "Dataset", + "description": "Configuration files" + }, + { + "@id": "docs/", + "@type": "Dataset", + "description": "Markdown files for documenting the pipeline" + }, + { + "@id": "docs/images/", + "@type": "Dataset", + "description": "Images for the documentation files" + }, + { + "@id": "modules/", + "@type": "Dataset", + "description": "Modules used by the pipeline" + }, + { + "@id": "modules/nf-core/", + "@type": "Dataset", + "description": "nf-core modules" + }, + { + "@id": "workflows/", + "@type": "Dataset", + "description": "Main pipeline workflows to be executed in main.nf" + }, + { + "@id": "subworkflows/", + "@type": "Dataset", + "description": "Smaller subworkflows" + }, + { + "@id": "nextflow.config", + "@type": "File", + "description": "Main Nextflow configuration file" + }, + { + "@id": "README.md", + "@type": "File", + "description": "Basic pipeline usage information" + }, + { + "@id": "nextflow_schema.json", + "@type": "File", + "description": "JSON schema for pipeline parameter specification" + }, + { + "@id": "CHANGELOG.md", + "@type": "File", + "description": "Information on changes made to the pipeline" + }, + { + "@id": "LICENSE", + "@type": "File", + "description": "The license - should be MIT" + }, + { + "@id": "CODE_OF_CONDUCT.md", + "@type": "File", + "description": "The nf-core code of conduct" + }, + { + "@id": "CITATIONS.md", + "@type": "File", + "description": "Citations needed when using the pipeline" + }, + { + "@id": "modules.json", + "@type": "File", + "description": "Version information for modules from nf-core/modules" + }, + { + "@id": "docs/usage.md", + "@type": "File", + "description": "Usage documentation" + }, + { + "@id": "docs/output.md", + "@type": "File", + "description": "Output documentation" + }, + { + "@id": ".nf-core.yml", + "@type": "File", + "description": "nf-core configuration file, configuring template features and linting rules" + }, + { + "@id": ".pre-commit-config.yaml", + "@type": "File", + "description": "Configuration file for pre-commit hooks" + }, + { + "@id": ".prettierignore", + "@type": "File", + "description": "Ignore file for prettier" + }, + { + "@id": "https://nf-co.re/", + "@type": "Organization", + "name": "nf-core", + "url": "https://nf-co.re/" + }, + { + "@id": "https://orcid.org/0000-0002-6503-2180", + "@type": "Person", + "email": "alexander.peltzer@boehringer-ingelheim.com", + "name": "Alexander Peltzer" + } + ] +} diff --git a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf index e9c4b16..311fba1 100644 --- a/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_datasync_pipeline/main.nf @@ -116,7 +116,8 @@ workflow PIPELINE_COMPLETION { main: summary_params = paramsSummaryMap(workflow, parameters_schema: "nextflow_schema.json") - + def multiqc_reports = multiqc_report.toList() + // // Completion email and summary // @@ -129,7 +130,7 @@ workflow PIPELINE_COMPLETION { plaintext_email, outdir, monochrome_logs, - multiqc_report.toList() + multiqc_reports.getVal(), ) } @@ -225,7 +226,7 @@ def toolBibliographyText() { } def methodsDescriptionText(mqc_methods_yaml) { - // Convert to a named map so can be used as with familar NXF ${workflow} variable syntax in the MultiQC YML file + // Convert to a named map so can be used as with familiar NXF ${workflow} variable syntax in the MultiQC YML file def meta = [:] meta.workflow = workflow.toMap() meta["manifest_map"] = workflow.manifest.toMap() diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf index 0fcbf7b..d6e593e 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nextflow_pipeline/main.nf @@ -92,10 +92,12 @@ def checkCondaChannels() { channels = config.channels } catch (NullPointerException e) { + log.debug(e) log.warn("Could not verify conda channel configuration.") return null } catch (IOException e) { + log.debug(e) log.warn("Could not verify conda channel configuration.") return null } diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.workflow.nf.test b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.workflow.nf.test index ca964ce..02dbf09 100644 --- a/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.workflow.nf.test +++ b/subworkflows/nf-core/utils_nextflow_pipeline/tests/main.workflow.nf.test @@ -52,10 +52,12 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert workflow.stdout.contains("nextflow_workflow v9.9.9") } - ) + expect { + with(workflow) { + assert success + assert "nextflow_workflow v9.9.9" in stdout + } + } } } diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index 5cb7baf..bfd2587 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -56,21 +56,6 @@ def checkProfileProvided(nextflow_cli_args) { } } -// -// Citation string for pipeline -// -def workflowCitation() { - def temp_doi_ref = "" - def manifest_doi = workflow.manifest.doi.tokenize(",") - // Handling multiple DOIs - // Removing `https://doi.org/` to handle pipelines using DOIs vs DOI resolvers - // Removing ` ` since the manifest.doi is a string and not a proper list - manifest_doi.each { doi_ref -> - temp_doi_ref += " https://doi.org/${doi_ref.replace('https://doi.org/', '').replace(' ', '')}\n" - } - return "If you use ${workflow.manifest.name} for your analysis please cite:\n\n" + "* The pipeline\n" + temp_doi_ref + "\n" + "* The nf-core framework\n" + " https://doi.org/10.1038/s41587-020-0439-x\n\n" + "* Software dependencies\n" + " https://github.com/${workflow.manifest.name}/blob/master/CITATIONS.md" -} - // // Generate workflow version string // @@ -150,33 +135,6 @@ def paramsSummaryMultiqc(summary_params) { return yaml_file_text } -// -// nf-core logo -// -def nfCoreLogo(monochrome_logs=true) { - def colors = logColours(monochrome_logs) as Map - String.format( - """\n - ${dashedLine(monochrome_logs)} - ${colors.green},--.${colors.black}/${colors.green},-.${colors.reset} - ${colors.blue} ___ __ __ __ ___ ${colors.green}/,-._.--~\'${colors.reset} - ${colors.blue} |\\ | |__ __ / ` / \\ |__) |__ ${colors.yellow}} {${colors.reset} - ${colors.blue} | \\| | \\__, \\__/ | \\ |___ ${colors.green}\\`-._,-`-,${colors.reset} - ${colors.green}`._,._,\'${colors.reset} - ${colors.purple} ${workflow.manifest.name} ${getWorkflowVersion()}${colors.reset} - ${dashedLine(monochrome_logs)} - """.stripIndent() - ) -} - -// -// Return dashed line -// -def dashedLine(monochrome_logs=true) { - def colors = logColours(monochrome_logs) as Map - return "-${colors.dim}----------------------------------------------------${colors.reset}-" -} - // // ANSII colours used for terminal logging // @@ -245,28 +203,24 @@ def logColours(monochrome_logs=true) { return colorcodes } -// -// Attach the multiqc report to email -// -def attachMultiqcReport(multiqc_report) { - def mqc_report = null - try { - if (workflow.success) { - mqc_report = multiqc_report.getVal() - if (mqc_report.getClass() == ArrayList && mqc_report.size() >= 1) { - if (mqc_report.size() > 1) { - log.warn("[${workflow.manifest.name}] Found multiple reports from process 'MULTIQC', will use only one") - } - mqc_report = mqc_report[0] - } +// Return a single report from an object that may be a Path or List +// +def getSingleReport(multiqc_reports) { + if (multiqc_reports instanceof Path) { + return multiqc_reports + } else if (multiqc_reports instanceof List) { + if (multiqc_reports.size() == 0) { + log.warn("[${workflow.manifest.name}] No reports found from process 'MULTIQC'") + return null + } else if (multiqc_reports.size() == 1) { + return multiqc_reports.first() + } else { + log.warn("[${workflow.manifest.name}] Found multiple reports from process 'MULTIQC', will use only one") + return multiqc_reports.first() } + } else { + return null } - catch (Exception all) { - if (multiqc_report) { - log.warn("[${workflow.manifest.name}] Could not attach MultiQC report to summary email") - } - } - return mqc_report } // @@ -320,7 +274,7 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi email_fields['summary'] = summary << misc_fields // On success try attach the multiqc report - def mqc_report = attachMultiqcReport(multiqc_report) + def mqc_report = getSingleReport(multiqc_report) // Check if we are only sending emails on failure def email_address = email @@ -340,7 +294,7 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi def email_html = html_template.toString() // Render the sendmail template - def max_multiqc_email_size = (params.containsKey('max_multiqc_email_size') ? params.max_multiqc_email_size : 0) as nextflow.util.MemoryUnit + def max_multiqc_email_size = (params.containsKey('max_multiqc_email_size') ? params.max_multiqc_email_size : 0) as MemoryUnit def smail_fields = [email: email_address, subject: subject, email_txt: email_txt, email_html: email_html, projectDir: "${workflow.projectDir}", mqcFile: mqc_report, mqcMaxSize: max_multiqc_email_size.toBytes()] def sf = new File("${workflow.projectDir}/assets/sendmail_template.txt") def sendmail_template = engine.createTemplate(sf).make(smail_fields) @@ -351,14 +305,17 @@ def completionEmail(summary_params, email, email_on_fail, plaintext_email, outdi if (email_address) { try { if (plaintext_email) { -new org.codehaus.groovy.GroovyException('Send plaintext e-mail, not HTML') } + new org.codehaus.groovy.GroovyException('Send plaintext e-mail, not HTML') + } // Try to send HTML e-mail using sendmail def sendmail_tf = new File(workflow.launchDir.toString(), ".sendmail_tmp.html") sendmail_tf.withWriter { w -> w << sendmail_html } ['sendmail', '-t'].execute() << sendmail_html log.info("-${colors.purple}[${workflow.manifest.name}]${colors.green} Sent summary e-mail to ${email_address} (sendmail)-") } - catch (Exception all) { + catch (Exception msg) { + log.debug(msg.toString()) + log.debug("Trying with mail instead of sendmail") // Catch failures and try with plaintext def mail_cmd = ['mail', '-s', subject, '--content-type=text/html', email_address] mail_cmd.execute() << email_html diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test index 1dc317f..f117040 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test @@ -41,26 +41,14 @@ nextflow_function { } } - test("Test Function workflowCitation") { - - function "workflowCitation" - - then { - assertAll( - { assert function.success }, - { assert snapshot(function.result).match() } - ) - } - } - - test("Test Function nfCoreLogo") { + test("Test Function without logColours") { - function "nfCoreLogo" + function "logColours" when { function { """ - input[0] = false + input[0] = true """ } } @@ -73,9 +61,8 @@ nextflow_function { } } - test("Test Function dashedLine") { - - function "dashedLine" + test("Test Function with logColours") { + function "logColours" when { function { @@ -93,14 +80,13 @@ nextflow_function { } } - test("Test Function without logColours") { - - function "logColours" + test("Test Function getSingleReport with a single file") { + function "getSingleReport" when { function { """ - input[0] = true + input[0] = file(params.modules_testdata_base_path + '/generic/tsv/test.tsv', checkIfExists: true) """ } } @@ -108,18 +94,22 @@ nextflow_function { then { assertAll( { assert function.success }, - { assert snapshot(function.result).match() } + { assert function.result.contains("test.tsv") } ) } } - test("Test Function with logColours") { - function "logColours" + test("Test Function getSingleReport with multiple files") { + function "getSingleReport" when { function { """ - input[0] = false + input[0] = [ + file(params.modules_testdata_base_path + '/generic/tsv/test.tsv', checkIfExists: true), + file(params.modules_testdata_base_path + '/generic/tsv/network.tsv', checkIfExists: true), + file(params.modules_testdata_base_path + '/generic/tsv/expression.tsv', checkIfExists: true) + ] """ } } @@ -127,7 +117,9 @@ nextflow_function { then { assertAll( { assert function.success }, - { assert snapshot(function.result).match() } + { assert function.result.contains("test.tsv") }, + { assert !function.result.contains("network.tsv") }, + { assert !function.result.contains("expression.tsv") } ) } } diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap index 1037232..02c6701 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap +++ b/subworkflows/nf-core/utils_nfcore_pipeline/tests/main.function.nf.test.snap @@ -17,26 +17,6 @@ }, "timestamp": "2024-02-28T12:02:59.729647" }, - "Test Function nfCoreLogo": { - "content": [ - "\n\n-\u001b[2m----------------------------------------------------\u001b[0m-\n \u001b[0;32m,--.\u001b[0;30m/\u001b[0;32m,-.\u001b[0m\n\u001b[0;34m ___ __ __ __ ___ \u001b[0;32m/,-._.--~'\u001b[0m\n\u001b[0;34m |\\ | |__ __ / ` / \\ |__) |__ \u001b[0;33m} {\u001b[0m\n\u001b[0;34m | \\| | \\__, \\__/ | \\ |___ \u001b[0;32m\\`-._,-`-,\u001b[0m\n \u001b[0;32m`._,._,'\u001b[0m\n\u001b[0;35m nextflow_workflow v9.9.9\u001b[0m\n-\u001b[2m----------------------------------------------------\u001b[0m-\n" - ], - "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" - }, - "timestamp": "2024-02-28T12:03:10.562934" - }, - "Test Function workflowCitation": { - "content": [ - "If you use nextflow_workflow for your analysis please cite:\n\n* The pipeline\n https://doi.org/10.5281/zenodo.5070524\n\n* The nf-core framework\n https://doi.org/10.1038/s41587-020-0439-x\n\n* Software dependencies\n https://github.com/nextflow_workflow/blob/master/CITATIONS.md" - ], - "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" - }, - "timestamp": "2024-02-28T12:03:07.019761" - }, "Test Function without logColours": { "content": [ { @@ -95,16 +75,6 @@ }, "timestamp": "2024-02-28T12:03:17.969323" }, - "Test Function dashedLine": { - "content": [ - "-\u001b[2m----------------------------------------------------\u001b[0m-" - ], - "meta": { - "nf-test": "0.8.4", - "nextflow": "23.10.1" - }, - "timestamp": "2024-02-28T12:03:14.366181" - }, "Test Function with logColours": { "content": [ { diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test index 842dc43..8fb3016 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test @@ -42,7 +42,7 @@ nextflow_workflow { params { test_data = '' - outdir = 1 + outdir = null } workflow { @@ -94,7 +94,7 @@ nextflow_workflow { params { test_data = '' - outdir = 1 + outdir = null } workflow { diff --git a/workflows/datasync.nf b/workflows/datasync.nf index 43f6b82..6905242 100644 --- a/workflows/datasync.nf +++ b/workflows/datasync.nf @@ -39,7 +39,7 @@ workflow DATASYNC { softwareVersionsToYAML(ch_versions) .collectFile( storeDir: "${params.outdir}/pipeline_info", - name: 'nf_core_' + 'pipeline_software_' + 'mqc_' + 'versions.yml', + name: 'nf_core_' + 'datasync_software_' + 'mqc_' + 'versions.yml', sort: true, newLine: true ).set { ch_collated_versions } From 357e4c567507fe13376320b263da54096e66a956 Mon Sep 17 00:00:00 2001 From: nf-core-bot Date: Fri, 20 Dec 2024 13:07:06 +0000 Subject: [PATCH 010/334] Template update for nf-core/tools version 3.1.1 --- .editorconfig | 4 ++ .github/ISSUE_TEMPLATE/bug_report.yml | 1 - .github/workflows/download_pipeline.yml | 41 ++++++++++------- .nf-core.yml | 2 +- .prettierignore | 1 + CITATIONS.md | 4 +- LICENSE | 2 +- README.md | 15 ++----- docs/output.md | 11 ++--- docs/usage.md | 2 +- nextflow.config | 3 ++ ro-crate-metadata.json | 44 +++++++++++++------ .../utils_nfcore_datasync_pipeline/main.nf | 2 +- 13 files changed, 75 insertions(+), 57 deletions(-) diff --git a/.editorconfig b/.editorconfig index 72dda28..6d9b74c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -31,3 +31,7 @@ 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/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e7b641c..fb324ab 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -9,7 +9,6 @@ body: - [nf-core website: troubleshooting](https://nf-co.re/usage/troubleshooting) - [nf-core/datasync pipeline documentation](https://nf-co.re/datasync/usage) - - type: textarea id: description attributes: diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 2576cc0..13b51e2 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -28,8 +28,12 @@ env: NXF_ANSI_LOG: false jobs: - download: + configure: runs-on: ubuntu-latest + outputs: + REPO_LOWERCASE: ${{ steps.get_repo_properties.outputs.REPO_LOWERCASE }} + REPOTITLE_LOWERCASE: ${{ steps.get_repo_properties.outputs.REPOTITLE_LOWERCASE }} + REPO_BRANCH: ${{ steps.get_repo_properties.outputs.REPO_BRANCH }} steps: - name: Install Nextflow uses: nf-core/setup-nextflow@v2 @@ -53,22 +57,27 @@ jobs: pip install git+https://github.com/nf-core/tools.git@dev - name: Get the repository name and current branch set as environment variable + id: get_repo_properties run: | - echo "REPO_LOWERCASE=${GITHUB_REPOSITORY,,}" >> ${GITHUB_ENV} - echo "REPOTITLE_LOWERCASE=$(basename ${GITHUB_REPOSITORY,,})" >> ${GITHUB_ENV} - echo "REPO_BRANCH=${{ github.event.inputs.testbranch || 'dev' }}" >> ${GITHUB_ENV} + echo "REPO_LOWERCASE=${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT" + echo "REPOTITLE_LOWERCASE=$(basename ${GITHUB_REPOSITORY,,})" >> "$GITHUB_OUTPUT" + echo "REPO_BRANCH=${{ github.event.inputs.testbranch || 'dev' }}" >> "$GITHUB_OUTPUT" - name: Make a cache directory for the container images run: | mkdir -p ./singularity_container_images + download: + runs-on: ubuntu-latest + needs: configure + steps: - name: Download the pipeline env: NXF_SINGULARITY_CACHEDIR: ./singularity_container_images run: | - nf-core pipelines download ${{ env.REPO_LOWERCASE }} \ - --revision ${{ env.REPO_BRANCH }} \ - --outdir ./${{ env.REPOTITLE_LOWERCASE }} \ + nf-core pipelines download ${{ needs.configure.outputs.REPO_LOWERCASE }} \ + --revision ${{ needs.configure.outputs.REPO_BRANCH }} \ + --outdir ./${{ needs.configure.outputs.REPOTITLE_LOWERCASE }} \ --compress "none" \ --container-system 'singularity' \ --container-library "quay.io" -l "docker.io" -l "community.wave.seqera.io/library/" \ @@ -76,14 +85,14 @@ jobs: --download-configuration 'yes' - name: Inspect download - run: tree ./${{ env.REPOTITLE_LOWERCASE }} + run: tree ./${{ needs.configure.outputs.REPOTITLE_LOWERCASE }} - name: Count the downloaded number of container images id: count_initial run: | image_count=$(ls -1 ./singularity_container_images | wc -l | xargs) echo "Initial container image count: $image_count" - echo "IMAGE_COUNT_INITIAL=$image_count" >> ${GITHUB_ENV} + echo "IMAGE_COUNT_INITIAL=$image_count" >> "$GITHUB_OUTPUT" - name: Run the downloaded pipeline (stub) id: stub_run_pipeline @@ -91,27 +100,27 @@ jobs: env: NXF_SINGULARITY_CACHEDIR: ./singularity_container_images NXF_SINGULARITY_HOME_MOUNT: true - run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -stub -profile test,singularity --outdir ./results + run: nextflow run ./${{needs.configure.outputs.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ needs.configure.outputs.REPO_BRANCH }}) -stub -profile test,singularity --outdir ./results - name: Run the downloaded pipeline (stub run not supported) id: run_pipeline - if: ${{ job.steps.stub_run_pipeline.status == failure() }} + if: ${{ steps.stub_run_pipeline.outcome == 'failure' }} env: NXF_SINGULARITY_CACHEDIR: ./singularity_container_images NXF_SINGULARITY_HOME_MOUNT: true - run: nextflow run ./${{ env.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ env.REPO_BRANCH }}) -profile test,singularity --outdir ./results + run: nextflow run ./${{ needs.configure.outputs.REPOTITLE_LOWERCASE }}/$( sed 's/\W/_/g' <<< ${{ needs.configure.outputs.REPO_BRANCH }}) -profile test,singularity --outdir ./results - name: Count the downloaded number of container images id: count_afterwards run: | image_count=$(ls -1 ./singularity_container_images | wc -l | xargs) echo "Post-pipeline run container image count: $image_count" - echo "IMAGE_COUNT_AFTER=$image_count" >> ${GITHUB_ENV} + echo "IMAGE_COUNT_AFTER=$image_count" >> "$GITHUB_OUTPUT" - name: Compare container image counts run: | - if [ "${{ env.IMAGE_COUNT_INITIAL }}" -ne "${{ env.IMAGE_COUNT_AFTER }}" ]; then - initial_count=${{ env.IMAGE_COUNT_INITIAL }} - final_count=${{ env.IMAGE_COUNT_AFTER }} + 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 }} + final_count=${{ steps.count_afterwards.outputs.IMAGE_COUNT_AFTER }} difference=$((final_count - initial_count)) echo "$difference additional container images were \n downloaded at runtime . The pipeline has no support for offline runs!" tree ./singularity_container_images diff --git a/.nf-core.yml b/.nf-core.yml index 9fad3e1..0a65c21 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,4 +1,4 @@ -nf_core_version: 3.1.0 +nf_core_version: 3.1.1 repository_type: pipeline template: author: Alexander Peltzer diff --git a/.prettierignore b/.prettierignore index 437d763..edd29f0 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,3 +10,4 @@ testing/ testing* *.pyc bin/ +ro-crate-metadata.json diff --git a/CITATIONS.md b/CITATIONS.md index 3032c6f..29e6bd4 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -12,9 +12,7 @@ - [FastQC](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/) -> Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online]. - -- [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) +> Andrews, S. (2010). FastQC: A Quality Control Tool for High Throughput Sequence Data [Online].- [MultiQC](https://pubmed.ncbi.nlm.nih.gov/27312411/) > Ewels P, Magnusson M, Lundin S, Käller M. MultiQC: summarize analysis results for multiple tools and samples in a single report. Bioinformatics. 2016 Oct 1;32(19):3047-8. doi: 10.1093/bioinformatics/btw354. Epub 2016 Jun 16. PubMed PMID: 27312411; PubMed Central PMCID: PMC5039924. diff --git a/LICENSE b/LICENSE index ef4eaa2..c86c931 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) Alexander Peltzer +Copyright (c) The nf-core/datasync team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ae71bb4..ffba325 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,7 @@ nf-core/datasync - - -[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml) +[![GitHub Actions CI Status](https://github.com/nf-core/datasync/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/ci.yml) [![GitHub Actions Linting Status](https://github.com/nf-core/datasync/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/datasync/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/datasync/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) @@ -29,15 +27,12 @@ - - -1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/)) -2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) +1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/)) ## Usage > [!NOTE] -> 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. +> 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. - - - + An extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file. diff --git a/docs/output.md b/docs/output.md index 1b7eb8b..e7beb92 100644 --- a/docs/output.md +++ b/docs/output.md @@ -12,8 +12,7 @@ The directories listed below will be created in the results directory after the The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes data using the following steps: -- [FastQC](#fastqc) - Raw read QC -- [MultiQC](#multiqc) - Aggregate report describing results and QC from the whole pipeline +- [FastQC](#fastqc) - Raw read QC- [MultiQC](#multiqc) - Aggregate report describing results and QC from the whole pipeline - [Pipeline information](#pipeline-information) - Report metrics generated during the workflow execution ### FastQC @@ -27,9 +26,7 @@ The pipeline is built using [Nextflow](https://www.nextflow.io/) and processes d