From 531e90e7878bf56032f3b612e296962269eaf7bf Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 24 Mar 2026 14:35:44 +0100 Subject: [PATCH 01/46] Make several tests structure-based instead of hash-based --- .../celltypes/celltypist/tests/main.nf.test | 8 +- .../celltypist/tests/main.nf.test.snap | 102 ++------ .../liana/rankaggregate/tests/main.nf.test | 3 +- .../rankaggregate/tests/main.nf.test.snap | 35 +-- modules/local/scanpy/bbknn/tests/main.nf.test | 5 +- .../scanpy/bbknn/tests/main.nf.test.snap | 31 +-- .../local/scanpy/combat/tests/main.nf.test | 5 +- .../scanpy/combat/tests/main.nf.test.snap | 41 +--- modules/local/scanpy/pca/main.nf | 2 - modules/local/scanpy/pca/templates/pca.py | 7 - modules/local/scanpy/pca/tests/main.nf.test | 7 +- .../local/scanpy/pca/tests/main.nf.test.snap | 78 +------ .../scanpy/rankgenesgroups/tests/main.nf.test | 8 +- .../rankgenesgroups/tests/main.nf.test.snap | 131 +---------- .../tests/main.nf.test | 16 +- .../tests/main.nf.test.snap | 218 +++--------------- .../local/integrate/tests/main.nf.test | 7 +- .../local/integrate/tests/main.nf.test.snap | 53 +---- 18 files changed, 123 insertions(+), 634 deletions(-) diff --git a/modules/local/celltypes/celltypist/tests/main.nf.test b/modules/local/celltypes/celltypist/tests/main.nf.test index 4c22a760..ad5f2675 100644 --- a/modules/local/celltypes/celltypist/tests/main.nf.test +++ b/modules/local/celltypes/celltypist/tests/main.nf.test @@ -27,9 +27,11 @@ nextflow_process { } then { + def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert "celltypist:Adult_COVID19_PBMC" in anndata(h5ad).obs.colnames } ) } @@ -55,9 +57,11 @@ nextflow_process { } then { + def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert "celltypist:Adult_COVID19_PBMC" in anndata(h5ad).obs.colnames } ) } diff --git a/modules/local/celltypes/celltypist/tests/main.nf.test.snap b/modules/local/celltypes/celltypist/tests/main.nf.test.snap index e1c674fd..dfa00a19 100644 --- a/modules/local/celltypes/celltypist/tests/main.nf.test.snap +++ b/modules/local/celltypes/celltypist/tests/main.nf.test.snap @@ -1,52 +1,15 @@ { "Should run with a symbol column other than index": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_celltypist.h5ad:md5,ef49126cbbaec817d468f2b196a7cc63" - ] - ], - "1": [ - [ - { - "id": "test" - }, - "test_celltypist.pkl:md5,b75851d6e4a34bd2e820234bf466cb8f" - ] - ], - "2": [ - "versions.yml:md5,d30822b1ba7cc7a7dc35c749b2353b57" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_celltypist.h5ad:md5,ef49126cbbaec817d468f2b196a7cc63" - ] - ], - "obs": [ - [ - { - "id": "test" - }, - "test_celltypist.pkl:md5,b75851d6e4a34bd2e820234bf466cb8f" - ] - ], - "versions": [ - "versions.yml:md5,d30822b1ba7cc7a7dc35c749b2353b57" - ] - } + [ + "versions.yml:md5,d30822b1ba7cc7a7dc35c749b2353b57" + ] ], + "timestamp": "2026-03-24T14:04:37.944003887", "meta": { - "nf-test": "0.9.2", + "nf-test": "0.9.4", "nextflow": "25.10.2" - }, - "timestamp": "2026-01-25T17:07:47.293607016" + } }, "Should run without failures - stub": { "content": [ @@ -91,59 +54,22 @@ ] } ], + "timestamp": "2025-06-01T22:03:47.365626813", "meta": { "nf-test": "0.9.0", "nextflow": "25.04.2" - }, - "timestamp": "2025-06-01T22:03:47.365626813" + } }, "Should run without failures": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_celltypist.h5ad:md5,ef49126cbbaec817d468f2b196a7cc63" - ] - ], - "1": [ - [ - { - "id": "test" - }, - "test_celltypist.pkl:md5,b75851d6e4a34bd2e820234bf466cb8f" - ] - ], - "2": [ - "versions.yml:md5,d30822b1ba7cc7a7dc35c749b2353b57" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_celltypist.h5ad:md5,ef49126cbbaec817d468f2b196a7cc63" - ] - ], - "obs": [ - [ - { - "id": "test" - }, - "test_celltypist.pkl:md5,b75851d6e4a34bd2e820234bf466cb8f" - ] - ], - "versions": [ - "versions.yml:md5,d30822b1ba7cc7a7dc35c749b2353b57" - ] - } + [ + "versions.yml:md5,d30822b1ba7cc7a7dc35c749b2353b57" + ] ], + "timestamp": "2026-03-24T14:01:47.279173042", "meta": { - "nf-test": "0.9.2", + "nf-test": "0.9.4", "nextflow": "25.10.2" - }, - "timestamp": "2026-01-25T17:07:21.807969437" + } } } \ No newline at end of file diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test b/modules/local/liana/rankaggregate/tests/main.nf.test index 06ce8f2c..086497f6 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test +++ b/modules/local/liana/rankaggregate/tests/main.nf.test @@ -29,7 +29,8 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert process.out.uns.size() > 0 } ) } diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test.snap b/modules/local/liana/rankaggregate/tests/main.nf.test.snap index 21fb0e19..68ad5bcf 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test.snap +++ b/modules/local/liana/rankaggregate/tests/main.nf.test.snap @@ -40,38 +40,11 @@ }, "Should run without failures": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_liana.h5ad:md5,c227d198aa472576b58ffe61ff37027b" - ] - ], - "1": [ - "test_liana.pkl:md5,058214ae3910f43472b791830a606047" - ], - "2": [ - "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_liana.h5ad:md5,c227d198aa472576b58ffe61ff37027b" - ] - ], - "uns": [ - "test_liana.pkl:md5,058214ae3910f43472b791830a606047" - ], - "versions": [ - "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" - ] - } + [ + "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" + ] ], - "timestamp": "2026-03-22T09:53:42.436168666", + "timestamp": "2026-03-24T14:03:54.706663316", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/bbknn/tests/main.nf.test b/modules/local/scanpy/bbknn/tests/main.nf.test index 6a942c7b..8c8f392b 100644 --- a/modules/local/scanpy/bbknn/tests/main.nf.test +++ b/modules/local/scanpy/bbknn/tests/main.nf.test @@ -28,9 +28,12 @@ nextflow_process { } then { + def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert "X_pca" in anndata(h5ad).obsm }, + { assert "connectivities" in anndata(h5ad).obsp } ) } diff --git a/modules/local/scanpy/bbknn/tests/main.nf.test.snap b/modules/local/scanpy/bbknn/tests/main.nf.test.snap index ef3abb17..569b3cb8 100644 --- a/modules/local/scanpy/bbknn/tests/main.nf.test.snap +++ b/modules/local/scanpy/bbknn/tests/main.nf.test.snap @@ -34,35 +34,14 @@ }, "Should run without failures": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.h5ad:md5,d83039db76dd28a01f459cfe7a1e1b6c" - ] - ], - "1": [ - "versions.yml:md5,0e8d49948d318a0226fecc9b8d3372bb" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test.h5ad:md5,d83039db76dd28a01f459cfe7a1e1b6c" - ] - ], - "versions": [ - "versions.yml:md5,0e8d49948d318a0226fecc9b8d3372bb" - ] - } + [ + "versions.yml:md5,0e8d49948d318a0226fecc9b8d3372bb" + ] ], - "timestamp": "2026-03-18T00:12:12.879701725", + "timestamp": "2026-03-24T14:03:12.708585961", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/scanpy/combat/tests/main.nf.test b/modules/local/scanpy/combat/tests/main.nf.test index be81d268..285cbf12 100644 --- a/modules/local/scanpy/combat/tests/main.nf.test +++ b/modules/local/scanpy/combat/tests/main.nf.test @@ -41,9 +41,12 @@ nextflow_process { } then { + def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert "X_emb" in anndata(h5ad).obsm }, + { assert "X_pca" in anndata(h5ad).obsm } ) } diff --git a/modules/local/scanpy/combat/tests/main.nf.test.snap b/modules/local/scanpy/combat/tests/main.nf.test.snap index c75c04ea..3fb13a1c 100644 --- a/modules/local/scanpy/combat/tests/main.nf.test.snap +++ b/modules/local/scanpy/combat/tests/main.nf.test.snap @@ -46,44 +46,11 @@ }, "Should run without failures": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test.h5ad:md5,c03a96f7779dc1c979d1dd920d4217b6" - ] - ], - "1": [ - "X_test.pkl:md5,8997a5b3f6b3e7cbfc21f8c1e4dff221" - ], - "2": [ - "test.npy:md5,5f2ff24403d91d7ed811542e97092393" - ], - "3": [ - "versions.yml:md5,9e3850fe91d236b81ba7557c47344e64" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test.h5ad:md5,c03a96f7779dc1c979d1dd920d4217b6" - ] - ], - "layers": [ - "test.npy:md5,5f2ff24403d91d7ed811542e97092393" - ], - "obsm": [ - "X_test.pkl:md5,8997a5b3f6b3e7cbfc21f8c1e4dff221" - ], - "versions": [ - "versions.yml:md5,9e3850fe91d236b81ba7557c47344e64" - ] - } + [ + "versions.yml:md5,9e3850fe91d236b81ba7557c47344e64" + ] ], - "timestamp": "2026-03-22T14:16:42.06841452", + "timestamp": "2026-03-24T14:03:10.04909002", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/pca/main.nf b/modules/local/scanpy/pca/main.nf index a56f1f9f..cafe81ed 100644 --- a/modules/local/scanpy/pca/main.nf +++ b/modules/local/scanpy/pca/main.nf @@ -14,7 +14,6 @@ process SCANPY_PCA { output: tuple val(meta), path("${prefix}.h5ad"), emit: h5ad path "X_${prefix}.pkl", emit: obsm - path "variance_ratio_${prefix}.yml", emit: variance_ratio path "versions.yml", emit: versions when: @@ -36,7 +35,6 @@ process SCANPY_PCA { touch ${prefix}.h5ad touch X_${prefix}.pkl - touch variance_ratio_${prefix}.yml cat <<-END_VERSIONS > versions.yml "${task.process}": diff --git a/modules/local/scanpy/pca/templates/pca.py b/modules/local/scanpy/pca/templates/pca.py index 17eb44f8..fec2ddde 100644 --- a/modules/local/scanpy/pca/templates/pca.py +++ b/modules/local/scanpy/pca/templates/pca.py @@ -7,9 +7,6 @@ os.environ["NUMBA_CACHE_DIR"] = "./tmp/numba" os.environ["MPLCONFIGDIR"] = "./tmp/matplotlib" -os.environ["OMP_NUM_THREADS"] = "1" -os.environ["OPENBLAS_NUM_THREADS"] = "1" -os.environ["MKL_NUM_THREADS"] = "1" import scanpy as sc import numpy as np @@ -41,10 +38,6 @@ df = pd.DataFrame(adata.obsm[key_added], index=adata.obs_names) df.to_pickle(f"X_{prefix}.pkl") -variance_ratio = adata.uns[key_added]["variance_ratio"].tolist() -with open(f"variance_ratio_{prefix}.yml", "w") as f: - yaml.dump({"variance_ratio": variance_ratio}, f) - # Versions versions = { "${task.process}": { diff --git a/modules/local/scanpy/pca/tests/main.nf.test b/modules/local/scanpy/pca/tests/main.nf.test index ef89c406..09055b4f 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test +++ b/modules/local/scanpy/pca/tests/main.nf.test @@ -30,12 +30,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { - assert snapshot( - path(process.out.variance_ratio[0]).yaml, - path(process.out.versions[0]).yaml - ).match() - }, + { assert snapshot(process.out.versions).match() }, { assert "X_pca" in anndata(process.out.h5ad[0][1]).obsm } ) } diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index 411fc037..05c5a818 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,10 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "variance_ratio_test_pca.yml:md5,d41d8cd98f00b204e9800998ecf8427e" - ], - "3": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ], "h5ad": [ [ @@ -30,15 +27,12 @@ "obsm": [ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], - "variance_ratio": [ - "variance_ratio_test_pca.yml:md5,d41d8cd98f00b204e9800998ecf8427e" - ], "versions": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ] } ], - "timestamp": "2026-03-18T23:28:51.301024619", + "timestamp": "2026-03-24T14:04:33.296174524", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -46,69 +40,11 @@ }, "Should run without failures": { "content": [ - { - "variance_ratio": [ - 0.724, - 0.028, - 0.02, - 0.014, - 0.008, - 0.006, - 0.004, - 0.004, - 0.003, - 0.003, - 0.003, - 0.002, - 0.002, - 0.002, - 0.002, - 0.002, - 0.002, - 0.002, - 0.002, - 0.002, - 0.002, - 0.002, - 0.002, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001, - 0.001 - ] - }, - { - "SCANPY_PCA": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - } - } + [ + "versions.yml:md5,1645b3233d21217bd7e2f01acd4a5892" + ] ], - "timestamp": "2026-03-18T23:35:10.339944767", + "timestamp": "2026-03-24T14:01:58.554176502", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test index f765ef4b..9f16ba94 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test @@ -32,7 +32,8 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert process.out.uns.size() > 0 } ) } @@ -94,7 +95,8 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert process.out.uns.size() > 0 } ) } @@ -125,7 +127,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() } ) } diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap index 682adf91..8781132e 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap @@ -52,40 +52,11 @@ }, "Should run with label subsetting": { "content": [ - { - "0": [ - - ], - "1": [ - - ], - "2": [ - - ], - "3": [ - - ], - "4": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ], - "h5ad": [ - - ], - "multiqc_files": [ - - ], - "plots": [ - - ], - "uns": [ - - ], - "versions": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ] - } + [ + "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" + ] ], - "timestamp": "2026-03-21T08:54:06.875259502", + "timestamp": "2026-03-24T14:07:28.405239364", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -93,50 +64,11 @@ }, "Should run without failures": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_characteristic_genes.h5ad:md5,9841d511b9ad3719520f69e6eebdb9ca" - ] - ], - "1": [ - "test_characteristic_genes.pkl:md5,a5375824a244e135c97349a6880d8e28" - ], - "2": [ - "test_characteristic_genes.png:md5,144d711a80fd70ace88db67cccd2f0bc" - ], - "3": [ - "test_characteristic_genes_mqc.json:md5,73c74aafa606395d0a010b51bfe20895" - ], - "4": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_characteristic_genes.h5ad:md5,9841d511b9ad3719520f69e6eebdb9ca" - ] - ], - "multiqc_files": [ - "test_characteristic_genes_mqc.json:md5,73c74aafa606395d0a010b51bfe20895" - ], - "plots": [ - "test_characteristic_genes.png:md5,144d711a80fd70ace88db67cccd2f0bc" - ], - "uns": [ - "test_characteristic_genes.pkl:md5,a5375824a244e135c97349a6880d8e28" - ], - "versions": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ] - } + [ + "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" + ] ], - "timestamp": "2026-03-22T09:53:53.651592336", + "timestamp": "2026-03-24T14:02:06.261606302", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -144,50 +76,11 @@ }, "Should run with condition subsetting": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_characteristic_genes.h5ad:md5,557ccc34f354c9c0b8b74dedd4550688" - ] - ], - "1": [ - "test_characteristic_genes.pkl:md5,eeebba0ce02541b826cc0b605ef30e3c" - ], - "2": [ - "test_characteristic_genes.png:md5,c49d632c6d6100f7931db5491844fdda" - ], - "3": [ - "test_characteristic_genes_mqc.json:md5,dd8d8a557bda69eb0b0e0d04ad0fc47f" - ], - "4": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_characteristic_genes.h5ad:md5,557ccc34f354c9c0b8b74dedd4550688" - ] - ], - "multiqc_files": [ - "test_characteristic_genes_mqc.json:md5,dd8d8a557bda69eb0b0e0d04ad0fc47f" - ], - "plots": [ - "test_characteristic_genes.png:md5,c49d632c6d6100f7931db5491844fdda" - ], - "uns": [ - "test_characteristic_genes.pkl:md5,eeebba0ce02541b826cc0b605ef30e3c" - ], - "versions": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ] - } + [ + "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" + ] ], - "timestamp": "2026-03-22T10:08:54.64745021", + "timestamp": "2026-03-24T14:05:35.093554074", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/differential_expression/tests/main.nf.test b/subworkflows/local/differential_expression/tests/main.nf.test index 290955ee..34036c4d 100644 --- a/subworkflows/local/differential_expression/tests/main.nf.test +++ b/subworkflows/local/differential_expression/tests/main.nf.test @@ -24,8 +24,12 @@ nextflow_workflow { } then { - assert workflow.success - assert snapshot(workflow.out).match() + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out.versions).match() }, + { assert workflow.out.uns.size() > 0 }, + { assert workflow.out.multiqc_files.size() > 0 } + ) } } @@ -47,8 +51,12 @@ nextflow_workflow { } then { - assert workflow.success - assert snapshot(workflow.out).match() + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out.versions).match() }, + { assert workflow.out.uns.size() > 0 }, + { assert workflow.out.multiqc_files.size() > 0 } + ) } } diff --git a/subworkflows/local/differential_expression/tests/main.nf.test.snap b/subworkflows/local/differential_expression/tests/main.nf.test.snap index c2cda462..38990e5f 100644 --- a/subworkflows/local/differential_expression/tests/main.nf.test.snap +++ b/subworkflows/local/differential_expression/tests/main.nf.test.snap @@ -1,118 +1,26 @@ { "Should run differential expression with leiden clustering": { "content": [ - { - "0": [ - "condition:leiden:0_characteristic_genes.pkl:md5,d6be6f9447ed67f6bb5d5df1acf22b86", - "condition:leiden:10_characteristic_genes.pkl:md5,7fd29daa10b8008e16f5c9639a402587", - "condition:leiden:11_characteristic_genes.pkl:md5,9e96aaf44b8d0f0c26a5bda59f63b096", - "condition:leiden:1_characteristic_genes.pkl:md5,f2d38b8ddd01bfd820945fc25fb15f06", - "condition:leiden:2_characteristic_genes.pkl:md5,184a05f08b741d4a0b6e0ee17a9609ec", - "condition:leiden:3_characteristic_genes.pkl:md5,b1bcd5c5d3332c121b01d24cb46a2334", - "condition:leiden:4_characteristic_genes.pkl:md5,15bc73779b616c2276eeedc94bd448b6", - "condition:leiden:5_characteristic_genes.pkl:md5,f314433d06e822b6bcdcccfe1635d32c", - "condition:leiden:6_characteristic_genes.pkl:md5,96e0edc86bf4df08008ff1af3cc10522", - "condition:leiden:7_characteristic_genes.pkl:md5,91ae9da4509aaddb59fb79505f6d37af", - "condition:leiden:8_characteristic_genes.pkl:md5,fae74f6935930804cd95b1e62b393f44", - "condition:leiden:9_characteristic_genes.pkl:md5,635e5ca72000437e64a458a4fc89dc4b", - "leiden:condition:Disease_characteristic_genes.pkl:md5,029b3b97860e8ba00b2b7701c0ef4836", - "leiden:condition:Healthy_characteristic_genes.pkl:md5,f638b9a63be41a80c24367c329ad9c92", - "leiden:condition:Treated_characteristic_genes.pkl:md5,5761aff9c5fff490dee108a0127a8af4", - "leiden_characteristic_genes.pkl:md5,e387d9c66878055c92c3d4de44cec54a" - ], - "1": [ - "condition:leiden:0_characteristic_genes_mqc.json:md5,0d9173af58f05a6a017b7bf62a8ab6a8", - "condition:leiden:10_characteristic_genes_mqc.json:md5,1c42e764ba8a629df84a9f6a7b7cb889", - "condition:leiden:11_characteristic_genes_mqc.json:md5,0778f0f0cd0bd3edf2317a7b557ce952", - "condition:leiden:1_characteristic_genes_mqc.json:md5,a3b5df45edbd4dcc5fb3cf73864f4e76", - "condition:leiden:2_characteristic_genes_mqc.json:md5,1656d5018a65811325f95449b34f302b", - "condition:leiden:3_characteristic_genes_mqc.json:md5,1ce90ec438f14d33bebd26db002544cb", - "condition:leiden:4_characteristic_genes_mqc.json:md5,375733d6a0a018ad6ef0776d5039fb64", - "condition:leiden:5_characteristic_genes_mqc.json:md5,17df859608e296b50492d4fbcaff66f2", - "condition:leiden:6_characteristic_genes_mqc.json:md5,21ec62fdde2bb968127d4f8b5acabaa7", - "condition:leiden:7_characteristic_genes_mqc.json:md5,d1fa8613daecf0aafb769d14c9be39d7", - "condition:leiden:8_characteristic_genes_mqc.json:md5,2602bc68c47188fda2742ad9f222cf4e", - "condition:leiden:9_characteristic_genes_mqc.json:md5,c968bea56d8763520f0d68de394ccb79", - "leiden:condition:Disease_characteristic_genes_mqc.json:md5,46ee7c6e656b2419d618650d7c67d0b0", - "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,cc6e0fe227a84f1036f893945604dcc2", - "leiden:condition:Treated_characteristic_genes_mqc.json:md5,a7a78be0d9f0655ae8a5cae77daf0a74", - "leiden_characteristic_genes_mqc.json:md5,875d02a88fd8f4f0c0462f4da112d1ed" - ], - "2": [ - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" - ], - "multiqc_files": [ - "condition:leiden:0_characteristic_genes_mqc.json:md5,0d9173af58f05a6a017b7bf62a8ab6a8", - "condition:leiden:10_characteristic_genes_mqc.json:md5,1c42e764ba8a629df84a9f6a7b7cb889", - "condition:leiden:11_characteristic_genes_mqc.json:md5,0778f0f0cd0bd3edf2317a7b557ce952", - "condition:leiden:1_characteristic_genes_mqc.json:md5,a3b5df45edbd4dcc5fb3cf73864f4e76", - "condition:leiden:2_characteristic_genes_mqc.json:md5,1656d5018a65811325f95449b34f302b", - "condition:leiden:3_characteristic_genes_mqc.json:md5,1ce90ec438f14d33bebd26db002544cb", - "condition:leiden:4_characteristic_genes_mqc.json:md5,375733d6a0a018ad6ef0776d5039fb64", - "condition:leiden:5_characteristic_genes_mqc.json:md5,17df859608e296b50492d4fbcaff66f2", - "condition:leiden:6_characteristic_genes_mqc.json:md5,21ec62fdde2bb968127d4f8b5acabaa7", - "condition:leiden:7_characteristic_genes_mqc.json:md5,d1fa8613daecf0aafb769d14c9be39d7", - "condition:leiden:8_characteristic_genes_mqc.json:md5,2602bc68c47188fda2742ad9f222cf4e", - "condition:leiden:9_characteristic_genes_mqc.json:md5,c968bea56d8763520f0d68de394ccb79", - "leiden:condition:Disease_characteristic_genes_mqc.json:md5,46ee7c6e656b2419d618650d7c67d0b0", - "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,cc6e0fe227a84f1036f893945604dcc2", - "leiden:condition:Treated_characteristic_genes_mqc.json:md5,a7a78be0d9f0655ae8a5cae77daf0a74", - "leiden_characteristic_genes_mqc.json:md5,875d02a88fd8f4f0c0462f4da112d1ed" - ], - "uns": [ - "condition:leiden:0_characteristic_genes.pkl:md5,d6be6f9447ed67f6bb5d5df1acf22b86", - "condition:leiden:10_characteristic_genes.pkl:md5,7fd29daa10b8008e16f5c9639a402587", - "condition:leiden:11_characteristic_genes.pkl:md5,9e96aaf44b8d0f0c26a5bda59f63b096", - "condition:leiden:1_characteristic_genes.pkl:md5,f2d38b8ddd01bfd820945fc25fb15f06", - "condition:leiden:2_characteristic_genes.pkl:md5,184a05f08b741d4a0b6e0ee17a9609ec", - "condition:leiden:3_characteristic_genes.pkl:md5,b1bcd5c5d3332c121b01d24cb46a2334", - "condition:leiden:4_characteristic_genes.pkl:md5,15bc73779b616c2276eeedc94bd448b6", - "condition:leiden:5_characteristic_genes.pkl:md5,f314433d06e822b6bcdcccfe1635d32c", - "condition:leiden:6_characteristic_genes.pkl:md5,96e0edc86bf4df08008ff1af3cc10522", - "condition:leiden:7_characteristic_genes.pkl:md5,91ae9da4509aaddb59fb79505f6d37af", - "condition:leiden:8_characteristic_genes.pkl:md5,fae74f6935930804cd95b1e62b393f44", - "condition:leiden:9_characteristic_genes.pkl:md5,635e5ca72000437e64a458a4fc89dc4b", - "leiden:condition:Disease_characteristic_genes.pkl:md5,029b3b97860e8ba00b2b7701c0ef4836", - "leiden:condition:Healthy_characteristic_genes.pkl:md5,f638b9a63be41a80c24367c329ad9c92", - "leiden:condition:Treated_characteristic_genes.pkl:md5,5761aff9c5fff490dee108a0127a8af4", - "leiden_characteristic_genes.pkl:md5,e387d9c66878055c92c3d4de44cec54a" - ], - "versions": [ - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" - ] - } + [ + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" + ] ], - "timestamp": "2026-03-22T10:30:59.698386674", + "timestamp": "2026-03-24T14:01:59.841477057", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -120,82 +28,20 @@ }, "Should run differential expression with label column": { "content": [ - { - "0": [ - "condition:label:B_cell_characteristic_genes.pkl:md5,2f99d61c2954906ec104799264fed6d0", - "condition:label:Cd4_t_characteristic_genes.pkl:md5,a38d1c237a97f99759d821f73bba5719", - "condition:label:Cd8_t_characteristic_genes.pkl:md5,776d565572bb6a1eddfd5567a69c0dc6", - "condition:label:Monocyte_characteristic_genes.pkl:md5,0e709c29bc3a61ba316048e2c8d61da8", - "condition:label:Nk_cell_characteristic_genes.pkl:md5,e91f318cec5509beb1641bf17e272523", - "condition:label:T_cell_characteristic_genes.pkl:md5,fca6d6c9ccd508cdcb5c718a2a4c25dd", - "label:condition:Disease_characteristic_genes.pkl:md5,dda81972668c2b9a164bb925930a9489", - "label:condition:Healthy_characteristic_genes.pkl:md5,f8b17a3fc7c93037a74b83f5d2a30622", - "label:condition:Treated_characteristic_genes.pkl:md5,b477570c5ae47b5239891344904d946d", - "label_characteristic_genes.pkl:md5,859c3b54b1b39be82f92048a60dab7c4" - ], - "1": [ - "condition:label:B_cell_characteristic_genes_mqc.json:md5,820db31f71bd14483b91ecf5e7656de4", - "condition:label:Cd4_t_characteristic_genes_mqc.json:md5,2af14cf72e88e19a5d9ce15dd7025727", - "condition:label:Cd8_t_characteristic_genes_mqc.json:md5,52203e4f1b841cb16e2b8ed719de1492", - "condition:label:Monocyte_characteristic_genes_mqc.json:md5,a88fa9d3780b4184d291d924a4830b9e", - "condition:label:Nk_cell_characteristic_genes_mqc.json:md5,51feda33f6932ea1429ff87f153e2aa0", - "condition:label:T_cell_characteristic_genes_mqc.json:md5,99f02e1eca31c65a84b9dbf57d05bd7a", - "label:condition:Disease_characteristic_genes_mqc.json:md5,5474c0aa0b23b308e0bbfa09cf67dc7d", - "label:condition:Healthy_characteristic_genes_mqc.json:md5,4e73669edf2a51df4e85f9e308e69b69", - "label:condition:Treated_characteristic_genes_mqc.json:md5,845060dadf420e9c9ee032989690c9e7", - "label_characteristic_genes_mqc.json:md5,dfa0f0eb363917eb443b7dbbde95a20f" - ], - "2": [ - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" - ], - "multiqc_files": [ - "condition:label:B_cell_characteristic_genes_mqc.json:md5,820db31f71bd14483b91ecf5e7656de4", - "condition:label:Cd4_t_characteristic_genes_mqc.json:md5,2af14cf72e88e19a5d9ce15dd7025727", - "condition:label:Cd8_t_characteristic_genes_mqc.json:md5,52203e4f1b841cb16e2b8ed719de1492", - "condition:label:Monocyte_characteristic_genes_mqc.json:md5,a88fa9d3780b4184d291d924a4830b9e", - "condition:label:Nk_cell_characteristic_genes_mqc.json:md5,51feda33f6932ea1429ff87f153e2aa0", - "condition:label:T_cell_characteristic_genes_mqc.json:md5,99f02e1eca31c65a84b9dbf57d05bd7a", - "label:condition:Disease_characteristic_genes_mqc.json:md5,5474c0aa0b23b308e0bbfa09cf67dc7d", - "label:condition:Healthy_characteristic_genes_mqc.json:md5,4e73669edf2a51df4e85f9e308e69b69", - "label:condition:Treated_characteristic_genes_mqc.json:md5,845060dadf420e9c9ee032989690c9e7", - "label_characteristic_genes_mqc.json:md5,dfa0f0eb363917eb443b7dbbde95a20f" - ], - "uns": [ - "condition:label:B_cell_characteristic_genes.pkl:md5,2f99d61c2954906ec104799264fed6d0", - "condition:label:Cd4_t_characteristic_genes.pkl:md5,a38d1c237a97f99759d821f73bba5719", - "condition:label:Cd8_t_characteristic_genes.pkl:md5,776d565572bb6a1eddfd5567a69c0dc6", - "condition:label:Monocyte_characteristic_genes.pkl:md5,0e709c29bc3a61ba316048e2c8d61da8", - "condition:label:Nk_cell_characteristic_genes.pkl:md5,e91f318cec5509beb1641bf17e272523", - "condition:label:T_cell_characteristic_genes.pkl:md5,fca6d6c9ccd508cdcb5c718a2a4c25dd", - "label:condition:Disease_characteristic_genes.pkl:md5,dda81972668c2b9a164bb925930a9489", - "label:condition:Healthy_characteristic_genes.pkl:md5,f8b17a3fc7c93037a74b83f5d2a30622", - "label:condition:Treated_characteristic_genes.pkl:md5,b477570c5ae47b5239891344904d946d", - "label_characteristic_genes.pkl:md5,859c3b54b1b39be82f92048a60dab7c4" - ], - "versions": [ - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" - ] - } + [ + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", + "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" + ] ], - "timestamp": "2026-03-17T22:20:42.142007254", + "timestamp": "2026-03-24T14:05:22.799299909", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/integrate/tests/main.nf.test b/subworkflows/local/integrate/tests/main.nf.test index 8cc58b83..1cd7063a 100644 --- a/subworkflows/local/integrate/tests/main.nf.test +++ b/subworkflows/local/integrate/tests/main.nf.test @@ -136,8 +136,11 @@ nextflow_workflow { } then { - assert workflow.success - assert snapshot(workflow.out).match() + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out.versions).match() }, + { assert "connectivities" in anndata(workflow.out.integrations[0][1]).obsp } + ) } } diff --git a/subworkflows/local/integrate/tests/main.nf.test.snap b/subworkflows/local/integrate/tests/main.nf.test.snap index 3060642c..b04b39bd 100644 --- a/subworkflows/local/integrate/tests/main.nf.test.snap +++ b/subworkflows/local/integrate/tests/main.nf.test.snap @@ -245,54 +245,13 @@ }, "Should run without failures - bbknn": { "content": [ - { - "0": [ - [ - { - "id": "bbknn" - }, - "bbknn.h5ad:md5,ed856f9046e0bc4e313697ca4aabcf04" - ] - ], - "1": [ - - ], - "2": [ - - ], - "3": [ - - ], - "4": [ - "versions.yml:md5,20020d8c9cf585aaa75dd5a14aa5d3ae", - "versions.yml:md5,ccf730637c4c61a84ac4a002bf9832e0", - "versions.yml:md5,d28b65c4c18c54e1abc34040b584b823" - ], - "integrations": [ - [ - { - "id": "bbknn" - }, - "bbknn.h5ad:md5,ed856f9046e0bc4e313697ca4aabcf04" - ] - ], - "obs": [ - - ], - "obsm": [ - - ], - "var": [ - - ], - "versions": [ - "versions.yml:md5,20020d8c9cf585aaa75dd5a14aa5d3ae", - "versions.yml:md5,ccf730637c4c61a84ac4a002bf9832e0", - "versions.yml:md5,d28b65c4c18c54e1abc34040b584b823" - ] - } + [ + "versions.yml:md5,20020d8c9cf585aaa75dd5a14aa5d3ae", + "versions.yml:md5,ccf730637c4c61a84ac4a002bf9832e0", + "versions.yml:md5,d28b65c4c18c54e1abc34040b584b823" + ] ], - "timestamp": "2026-03-17T22:22:18.579980166", + "timestamp": "2026-03-24T14:11:21.672408157", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" From 8c4135c74ffb2cd0c15c0b942599b611bcd5964b Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 24 Mar 2026 16:37:39 +0100 Subject: [PATCH 02/46] Remove doubletdetection from pipeline-level tests --- tests/default.nf.test.snap | 7 ++----- tests/main_pipeline_build.nf.test | 2 +- tests/main_pipeline_build.nf.test.snap | 13 ++++++------- tests/main_pipeline_extend.nf.test | 2 +- tests/main_pipeline_extend.nf.test.snap | 16 ++++++---------- tests/main_pipeline_qc.nf.test | 2 +- tests/main_pipeline_qc.nf.test.snap | 15 +++++++-------- tests/main_pipeline_reference_mapping.nf.test | 2 +- .../main_pipeline_reference_mapping.nf.test.snap | 13 ++++++------- 9 files changed, 31 insertions(+), 41 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index e9e5123f..bf510510 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -261,11 +261,8 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/sizes.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -286,10 +283,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-22T18:03:44.32474555", + "timestamp": "2026-03-24T15:35:27.123807122", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_build.nf.test b/tests/main_pipeline_build.nf.test index 203b8cf9..270d9d6d 100644 --- a/tests/main_pipeline_build.nf.test +++ b/tests/main_pipeline_build.nf.test @@ -10,7 +10,7 @@ nextflow_pipeline { params { input = 'https://github.com/nf-core/test-datasets/raw/refs/heads/scdownstream/samplesheet.csv' integration_methods = 'scvi,harmony,bbknn,combat,seurat' - doublet_detection = 'scrublet,doubletdetection,scds' + doublet_detection = 'scrublet,scds' celltypist_model = 'Adult_COVID19_PBMC' integration_hvgs = 500 outdir = "$outputDir" diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index e6bbf4b5..238b4f04 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -59,11 +59,6 @@ "pandas": "2.3.3", "python": "3.13.12" }, - "DOUBLETDETECTION": { - "anndata": "0.11.4", - "doubletdetection": "4.3.0.post1", - "python": "3.13.3" - }, "DOUBLET_REMOVAL": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -155,6 +150,10 @@ "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + }, "SCVITOOLS_SCVI": { "scvi": "1.3.3" }, @@ -300,10 +299,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-22T21:31:34.14074829", + "timestamp": "2026-03-24T15:42:23.456824765", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_extend.nf.test b/tests/main_pipeline_extend.nf.test index a2a64a04..3abf9f56 100644 --- a/tests/main_pipeline_extend.nf.test +++ b/tests/main_pipeline_extend.nf.test @@ -10,7 +10,7 @@ nextflow_pipeline { params { input = 'https://github.com/nf-core/test-datasets/raw/refs/heads/scdownstream/samplesheet_single.csv' integration_methods = 'scvi' - doublet_detection = 'scrublet,doubletdetection,scds' + doublet_detection = 'scrublet,scds' celltypist_model = 'Adult_COVID19_PBMC' integration_hvgs = 500 outdir = "$outputDir" diff --git a/tests/main_pipeline_extend.nf.test.snap b/tests/main_pipeline_extend.nf.test.snap index 4ccff40d..b7b8bb0d 100644 --- a/tests/main_pipeline_extend.nf.test.snap +++ b/tests/main_pipeline_extend.nf.test.snap @@ -56,11 +56,6 @@ "pandas": "2.3.3", "python": "3.13.12" }, - "DOUBLETDETECTION": { - "anndata": "0.11.4", - "doubletdetection": "4.3.0.post1", - "python": "3.13.3" - }, "DOUBLET_REMOVAL": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -130,6 +125,10 @@ "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + }, "SCVITOOLS_SCVI": { "scvi": "1.3.3" }, @@ -194,11 +193,8 @@ "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/sizes.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -215,10 +211,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-22T18:03:53.563393217", + "timestamp": "2026-03-24T15:35:23.085276096", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_qc.nf.test b/tests/main_pipeline_qc.nf.test index d915ebf1..4a296ac7 100644 --- a/tests/main_pipeline_qc.nf.test +++ b/tests/main_pipeline_qc.nf.test @@ -9,7 +9,7 @@ nextflow_pipeline { when { params { input = 'https://github.com/nf-core/test-datasets/raw/refs/heads/scdownstream/samplesheet.csv' - doublet_detection = 'scrublet,doubletdetection,scds' + doublet_detection = 'scrublet,scds' celltypist_model = 'Adult_COVID19_PBMC' qc_only = true outdir = "$outputDir" diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index f62b78e3..bd44bb63 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -1,7 +1,7 @@ { "Should process data from scratch": { "content": [ - 60, + 57, { "ADATA_READRDS": { "anndata": "0.11.1", @@ -45,11 +45,6 @@ "pandas": "2.3.3", "python": "3.13.12" }, - "DOUBLETDETECTION": { - "anndata": "0.11.4", - "doubletdetection": "4.3.0.post1", - "python": "3.13.3" - }, "DOUBLET_REMOVAL": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -97,6 +92,10 @@ "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + }, "UPSET_GENES": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -176,10 +175,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-22T18:02:21.271429508", + "timestamp": "2026-03-24T15:19:23.048545534", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_reference_mapping.nf.test b/tests/main_pipeline_reference_mapping.nf.test index 9b8b1b90..24517836 100644 --- a/tests/main_pipeline_reference_mapping.nf.test +++ b/tests/main_pipeline_reference_mapping.nf.test @@ -10,7 +10,7 @@ nextflow_pipeline { params { input = 'https://github.com/nf-core/test-datasets/raw/refs/heads/scdownstream/samplesheet_single.csv' integration_methods = 'scvi' - doublet_detection = 'scrublet,doubletdetection,scds' + doublet_detection = 'scrublet,scds' celltypist_model = 'Adult_COVID19_PBMC' integration_hvgs = 500 outdir = "$outputDir" diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 4cbbf825..1f67a65a 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -52,11 +52,6 @@ "pandas": "2.3.3", "python": "3.13.12" }, - "DOUBLETDETECTION": { - "anndata": "0.11.4", - "doubletdetection": "4.3.0.post1", - "python": "3.13.3" - }, "DOUBLET_REMOVAL": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -130,6 +125,10 @@ "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + }, "SCVITOOLS_SCVI": { "scvi": "1.3.3" }, @@ -215,10 +214,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-22T18:01:37.608502342", + "timestamp": "2026-03-24T15:34:01.68810189", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file From 79ac2d10003f9ff7444eb6655a2f2eb34ed7a3bd Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 24 Mar 2026 19:36:12 +0100 Subject: [PATCH 03/46] Update test snapshots --- modules/local/scanpy/pca/tests/main.nf.test.snap | 6 +++--- tests/main_pipeline_qc.nf.test.snap | 8 +------- tests/main_pipeline_reference_mapping.nf.test.snap | 8 +------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index 05c5a818..3d6a9777 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,7 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" ], "h5ad": [ [ @@ -28,11 +28,11 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" ] } ], - "timestamp": "2026-03-24T14:04:33.296174524", + "timestamp": "2026-03-24T18:04:19.704797397", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index bd44bb63..fb43c2ac 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -150,12 +150,6 @@ "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", - "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", @@ -175,7 +169,7 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T15:19:23.048545534", + "timestamp": "2026-03-24T18:39:32.940515591", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 1f67a65a..48450606 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -192,12 +192,6 @@ "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", "multiqc/multiqc_plots", - "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/pdf/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -214,7 +208,7 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T15:34:01.68810189", + "timestamp": "2026-03-24T18:43:18.421083649", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" From 3ba8985177738f2f1a769616fa24f0d36b5521f8 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 24 Mar 2026 19:36:29 +0100 Subject: [PATCH 04/46] Update CI nf-test version --- .github/workflows/nf-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml index 0c547d58..7645993d 100644 --- a/.github/workflows/nf-test.yml +++ b/.github/workflows/nf-test.yml @@ -29,7 +29,7 @@ concurrency: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NFT_VER: "0.9.3" + NFT_VER: "0.9.5" NFT_WORKDIR: "~" NXF_ANSI_LOG: false NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity From d0c5e97b478e5c7ae72749b408015650e17392e2 Mon Sep 17 00:00:00 2001 From: Erik Fasterius Date: Mon, 23 Mar 2026 12:22:35 +0100 Subject: [PATCH 05/46] Disable OpenMP CPU topology detection Disable OpenMP CPU topology detection for MacOS compatibility --- modules/local/adata/entropy/templates/entropy.py | 3 +++ modules/local/adata/extend/templates/extend.py | 4 ++++ modules/local/adata/merge/templates/merge.py | 3 +++ .../adata/mergeembeddings/templates/merge_embeddings.py | 4 ++++ modules/local/adata/prepcellxgene/templates/prepcellxgene.py | 2 ++ modules/local/adata/readcsv/templates/readcsv.py | 4 ++++ modules/local/adata/setindex/templates/setindex.py | 4 ++++ modules/local/adata/splitcol/templates/split_column.py | 4 ++++ .../adata/splitembeddings/templates/split_embeddings.py | 5 ++++- modules/local/adata/unify/templates/unify.py | 2 ++ modules/local/adata/upsetgenes/templates/upsetplot.py | 3 +++ modules/local/custom/collectsizes/templates/collectsizes.py | 4 ++++ .../doublet_removal/templates/doublet_removal.py | 3 +++ modules/local/scanpy/cellcycle/templates/cellcycle.py | 3 +++ modules/local/scanpy/combat/templates/combat.py | 3 +++ modules/local/scanpy/filter/templates/filter.py | 3 +++ modules/local/scanpy/harmony/templates/harmony.py | 3 +++ modules/local/scanpy/hvgs/templates/hvgs.py | 3 +++ modules/local/scanpy/leiden/templates/leiden.py | 3 +++ modules/local/scanpy/neighbors/templates/neighbors.py | 3 +++ modules/local/scanpy/paga/templates/paga.py | 3 +++ modules/local/scanpy/pca/templates/pca.py | 3 +++ modules/local/scanpy/plotqc/templates/plotqc.py | 2 ++ .../scanpy/rankgenesgroups/templates/rank_genes_groups.py | 5 ++++- modules/local/scanpy/readh5/templates/readh5.py | 3 +++ modules/local/scanpy/sample/templates/sample.py | 3 +++ modules/local/scanpy/umap/templates/umap.py | 3 +++ modules/local/scvitools/scanvi/templates/scanvi.py | 2 ++ modules/nf-core/scvitools/scar/templates/scar.py | 4 ++++ 29 files changed, 92 insertions(+), 2 deletions(-) diff --git a/modules/local/adata/entropy/templates/entropy.py b/modules/local/adata/entropy/templates/entropy.py index 59b4c8c6..4c7080f4 100644 --- a/modules/local/adata/entropy/templates/entropy.py +++ b/modules/local/adata/entropy/templates/entropy.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import json import base64 diff --git a/modules/local/adata/extend/templates/extend.py b/modules/local/adata/extend/templates/extend.py index bf555ffd..7d75b12b 100644 --- a/modules/local/adata/extend/templates/extend.py +++ b/modules/local/adata/extend/templates/extend.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility +import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import pickle import importlib.metadata diff --git a/modules/local/adata/merge/templates/merge.py b/modules/local/adata/merge/templates/merge.py index 153f0c15..b230f5f5 100644 --- a/modules/local/adata/merge/templates/merge.py +++ b/modules/local/adata/merge/templates/merge.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform from collections import defaultdict diff --git a/modules/local/adata/mergeembeddings/templates/merge_embeddings.py b/modules/local/adata/mergeembeddings/templates/merge_embeddings.py index c88ed493..45c0a99d 100644 --- a/modules/local/adata/mergeembeddings/templates/merge_embeddings.py +++ b/modules/local/adata/mergeembeddings/templates/merge_embeddings.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility +import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import numpy as np diff --git a/modules/local/adata/prepcellxgene/templates/prepcellxgene.py b/modules/local/adata/prepcellxgene/templates/prepcellxgene.py index 7344abe1..18721780 100644 --- a/modules/local/adata/prepcellxgene/templates/prepcellxgene.py +++ b/modules/local/adata/prepcellxgene/templates/prepcellxgene.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" os.environ["NUMBA_CACHE_DIR"] = "./tmp/numba" diff --git a/modules/local/adata/readcsv/templates/readcsv.py b/modules/local/adata/readcsv/templates/readcsv.py index 3f535a43..45e4445d 100644 --- a/modules/local/adata/readcsv/templates/readcsv.py +++ b/modules/local/adata/readcsv/templates/readcsv.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility +import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import importlib.metadata import anndata as ad diff --git a/modules/local/adata/setindex/templates/setindex.py b/modules/local/adata/setindex/templates/setindex.py index f07a00d0..70c38d41 100644 --- a/modules/local/adata/setindex/templates/setindex.py +++ b/modules/local/adata/setindex/templates/setindex.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility +import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import importlib.metadata import anndata as ad diff --git a/modules/local/adata/splitcol/templates/split_column.py b/modules/local/adata/splitcol/templates/split_column.py index 17ec8359..668c7f0a 100644 --- a/modules/local/adata/splitcol/templates/split_column.py +++ b/modules/local/adata/splitcol/templates/split_column.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility +import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import importlib.metadata diff --git a/modules/local/adata/splitembeddings/templates/split_embeddings.py b/modules/local/adata/splitembeddings/templates/split_embeddings.py index d0f227ac..aecef5b4 100644 --- a/modules/local/adata/splitembeddings/templates/split_embeddings.py +++ b/modules/local/adata/splitembeddings/templates/split_embeddings.py @@ -1,8 +1,11 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility +import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform -import pandas as pd import anndata as ad import yaml diff --git a/modules/local/adata/unify/templates/unify.py b/modules/local/adata/unify/templates/unify.py index dbd11a31..0e8126c3 100644 --- a/modules/local/adata/unify/templates/unify.py +++ b/modules/local/adata/unify/templates/unify.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" os.environ["NUMBA_CACHE_DIR"] = "./tmp/numba" diff --git a/modules/local/adata/upsetgenes/templates/upsetplot.py b/modules/local/adata/upsetgenes/templates/upsetplot.py index 625573a5..1f87cebc 100644 --- a/modules/local/adata/upsetgenes/templates/upsetplot.py +++ b/modules/local/adata/upsetgenes/templates/upsetplot.py @@ -1,6 +1,9 @@ #!/opt/conda/bin/python +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import base64 import json diff --git a/modules/local/custom/collectsizes/templates/collectsizes.py b/modules/local/custom/collectsizes/templates/collectsizes.py index f1a0c38b..be2d7c6e 100644 --- a/modules/local/custom/collectsizes/templates/collectsizes.py +++ b/modules/local/custom/collectsizes/templates/collectsizes.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility +import os +os.environ["KMP_AFFINITY"] = "disabled" + import json import platform diff --git a/modules/local/doublet_detection/doublet_removal/templates/doublet_removal.py b/modules/local/doublet_detection/doublet_removal/templates/doublet_removal.py index 552ca08e..7bd8c4df 100644 --- a/modules/local/doublet_detection/doublet_removal/templates/doublet_removal.py +++ b/modules/local/doublet_detection/doublet_removal/templates/doublet_removal.py @@ -1,6 +1,9 @@ #!/opt/conda/bin/python +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import base64 import json diff --git a/modules/local/scanpy/cellcycle/templates/cellcycle.py b/modules/local/scanpy/cellcycle/templates/cellcycle.py index 6ab74a34..7e696817 100644 --- a/modules/local/scanpy/cellcycle/templates/cellcycle.py +++ b/modules/local/scanpy/cellcycle/templates/cellcycle.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform os.environ["MPLCONFIGDIR"] = "./tmp/mpl" diff --git a/modules/local/scanpy/combat/templates/combat.py b/modules/local/scanpy/combat/templates/combat.py index 79e56331..48236926 100644 --- a/modules/local/scanpy/combat/templates/combat.py +++ b/modules/local/scanpy/combat/templates/combat.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform os.environ["MPLCONFIGDIR"] = "./tmp/mpl" diff --git a/modules/local/scanpy/filter/templates/filter.py b/modules/local/scanpy/filter/templates/filter.py index 12f81f6a..83ef45cf 100644 --- a/modules/local/scanpy/filter/templates/filter.py +++ b/modules/local/scanpy/filter/templates/filter.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform os.environ["MPLCONFIGDIR"] = "./tmp/mpl" diff --git a/modules/local/scanpy/harmony/templates/harmony.py b/modules/local/scanpy/harmony/templates/harmony.py index 5b44032e..33b2577b 100644 --- a/modules/local/scanpy/harmony/templates/harmony.py +++ b/modules/local/scanpy/harmony/templates/harmony.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import yaml import argparse diff --git a/modules/local/scanpy/hvgs/templates/hvgs.py b/modules/local/scanpy/hvgs/templates/hvgs.py index d5940605..70e43873 100644 --- a/modules/local/scanpy/hvgs/templates/hvgs.py +++ b/modules/local/scanpy/hvgs/templates/hvgs.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform from threadpoolctl import threadpool_limits diff --git a/modules/local/scanpy/leiden/templates/leiden.py b/modules/local/scanpy/leiden/templates/leiden.py index d285d7e3..5ec1154e 100644 --- a/modules/local/scanpy/leiden/templates/leiden.py +++ b/modules/local/scanpy/leiden/templates/leiden.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import json import base64 diff --git a/modules/local/scanpy/neighbors/templates/neighbors.py b/modules/local/scanpy/neighbors/templates/neighbors.py index e1b9988e..cbf35660 100644 --- a/modules/local/scanpy/neighbors/templates/neighbors.py +++ b/modules/local/scanpy/neighbors/templates/neighbors.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import argparse import shlex diff --git a/modules/local/scanpy/paga/templates/paga.py b/modules/local/scanpy/paga/templates/paga.py index e9475b95..d7ea8cde 100644 --- a/modules/local/scanpy/paga/templates/paga.py +++ b/modules/local/scanpy/paga/templates/paga.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import json import base64 diff --git a/modules/local/scanpy/pca/templates/pca.py b/modules/local/scanpy/pca/templates/pca.py index fec2ddde..2b75b455 100644 --- a/modules/local/scanpy/pca/templates/pca.py +++ b/modules/local/scanpy/pca/templates/pca.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import argparse import shlex diff --git a/modules/local/scanpy/plotqc/templates/plotqc.py b/modules/local/scanpy/plotqc/templates/plotqc.py index 397b43ec..454d48d6 100644 --- a/modules/local/scanpy/plotqc/templates/plotqc.py +++ b/modules/local/scanpy/plotqc/templates/plotqc.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" os.environ["NUMBA_CACHE_DIR"] = "./tmp/numba" os.environ["MPLCONFIGDIR"] = "./tmp/matplotlib" diff --git a/modules/local/scanpy/rankgenesgroups/templates/rank_genes_groups.py b/modules/local/scanpy/rankgenesgroups/templates/rank_genes_groups.py index 8b98ccfc..0223adc3 100644 --- a/modules/local/scanpy/rankgenesgroups/templates/rank_genes_groups.py +++ b/modules/local/scanpy/rankgenesgroups/templates/rank_genes_groups.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import json import platform import base64 @@ -136,7 +139,7 @@ elif len(valid_groups) == 1: print(f"Skipping rank_genes_groups computation: only one group has >= 2 samples (group: {valid_groups[0]}).") else: - print(f"Skipping rank_genes_groups computation: less than 2 valid groups remaining after filtering.") + print("Skipping rank_genes_groups computation: less than 2 valid groups remaining after filtering.") # Versions diff --git a/modules/local/scanpy/readh5/templates/readh5.py b/modules/local/scanpy/readh5/templates/readh5.py index bfb92334..d02c6806 100644 --- a/modules/local/scanpy/readh5/templates/readh5.py +++ b/modules/local/scanpy/readh5/templates/readh5.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform os.environ["MPLCONFIGDIR"] = "./tmp/mpl" diff --git a/modules/local/scanpy/sample/templates/sample.py b/modules/local/scanpy/sample/templates/sample.py index 45a6a311..dadb1059 100644 --- a/modules/local/scanpy/sample/templates/sample.py +++ b/modules/local/scanpy/sample/templates/sample.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform os.environ["MPLCONFIGDIR"] = "./tmp/mpl" diff --git a/modules/local/scanpy/umap/templates/umap.py b/modules/local/scanpy/umap/templates/umap.py index ee3d6024..1a410a5f 100644 --- a/modules/local/scanpy/umap/templates/umap.py +++ b/modules/local/scanpy/umap/templates/umap.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" + import platform import argparse import shlex diff --git a/modules/local/scvitools/scanvi/templates/scanvi.py b/modules/local/scvitools/scanvi/templates/scanvi.py index 80a285e8..08364085 100644 --- a/modules/local/scvitools/scanvi/templates/scanvi.py +++ b/modules/local/scvitools/scanvi/templates/scanvi.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" diff --git a/modules/nf-core/scvitools/scar/templates/scar.py b/modules/nf-core/scvitools/scar/templates/scar.py index 3418ce56..0ad95cc8 100644 --- a/modules/nf-core/scvitools/scar/templates/scar.py +++ b/modules/nf-core/scvitools/scar/templates/scar.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility +import os +os.environ["KMP_AFFINITY"] = "disabled" + import anndata as ad import scvi import yaml From e93537c3bf5fd8f97263734d56885819d078530b Mon Sep 17 00:00:00 2001 From: Erik Fasterius Date: Mon, 23 Mar 2026 14:17:06 +0100 Subject: [PATCH 06/46] Add `MPLCONFIGDIR` to `PREPCELLXGENE` module --- modules/local/adata/prepcellxgene/templates/prepcellxgene.py | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/local/adata/prepcellxgene/templates/prepcellxgene.py b/modules/local/adata/prepcellxgene/templates/prepcellxgene.py index 18721780..86634e64 100644 --- a/modules/local/adata/prepcellxgene/templates/prepcellxgene.py +++ b/modules/local/adata/prepcellxgene/templates/prepcellxgene.py @@ -4,6 +4,7 @@ import os os.environ["KMP_AFFINITY"] = "disabled" +os.environ["MPLCONFIGDIR"] = "./tmp" os.environ["NUMBA_CACHE_DIR"] = "./tmp/numba" import platform From 2d40395ed63ec06d5928cf32247df72a98495160 Mon Sep 17 00:00:00 2001 From: Erik Fasterius Date: Tue, 24 Mar 2026 21:33:59 +0100 Subject: [PATCH 07/46] Add missing CPU topology detection disables --- modules/local/scvitools/scvi/templates/scvi.py | 2 ++ modules/nf-core/scvitools/solo/templates/solo.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/modules/local/scvitools/scvi/templates/scvi.py b/modules/local/scvitools/scvi/templates/scvi.py index 646c3c2f..827767ae 100644 --- a/modules/local/scvitools/scvi/templates/scvi.py +++ b/modules/local/scvitools/scvi/templates/scvi.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" diff --git a/modules/nf-core/scvitools/solo/templates/solo.py b/modules/nf-core/scvitools/solo/templates/solo.py index 810869b5..b1da9388 100644 --- a/modules/nf-core/scvitools/solo/templates/solo.py +++ b/modules/nf-core/scvitools/solo/templates/solo.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 +# Disable OpenMP CPU topology detection for MacOS compatibility import os +os.environ["KMP_AFFINITY"] = "disabled" os.environ["MPLCONFIGDIR"] = "./tmp" From 278b7e606fcdf4bc8e181125db2fb83d9fb8fea2 Mon Sep 17 00:00:00 2001 From: Erik Fasterius Date: Tue, 24 Mar 2026 21:34:35 +0100 Subject: [PATCH 08/46] Update snapshots --- .../local/scanpy/hvgs/tests/main.nf.test.snap | 24 +- .../local/scanpy/umap/tests/main.nf.test.snap | 10 +- .../doublet_detection/tests/main.nf.test.snap | 4 +- .../local/per_group/tests/main.nf.test.snap | 102 ++-- tests/default.nf.test.snap | 10 +- tests/main_pipeline_build.nf.test.snap | 266 +-------- tests/main_pipeline_extend.nf.test.snap | 10 +- tests/main_pipeline_qc.nf.test.snap | 6 +- ...in_pipeline_reference_mapping.nf.test.snap | 6 +- tests/main_pipeline_sub.nf.test.snap | 557 +----------------- 10 files changed, 93 insertions(+), 902 deletions(-) diff --git a/modules/local/scanpy/hvgs/tests/main.nf.test.snap b/modules/local/scanpy/hvgs/tests/main.nf.test.snap index 75249c58..763a104e 100644 --- a/modules/local/scanpy/hvgs/tests/main.nf.test.snap +++ b/modules/local/scanpy/hvgs/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "test" }, - "test_hvg.h5ad:md5,f1cfc42d33cf47fb46652e2f12d06da1" + "test_hvg.h5ad:md5,b87529ef7c8990e93daf8b2e4781a845" ] ], "1": [ @@ -21,7 +21,7 @@ { "id": "test" }, - "test_hvg.h5ad:md5,f1cfc42d33cf47fb46652e2f12d06da1" + "test_hvg.h5ad:md5,b87529ef7c8990e93daf8b2e4781a845" ] ], "var": [ @@ -32,9 +32,9 @@ ] } ], - "timestamp": "2026-03-16T15:33:26.657516082", + "timestamp": "2026-03-24T19:12:07.14241", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } }, @@ -46,7 +46,7 @@ { "id": "test" }, - "test_hvg.h5ad:md5,a8c70cd2c88e801de037f181e6830997" + "test_hvg.h5ad:md5,c8bba9250a396c5f851539f069b286f5" ] ], "1": [ @@ -60,7 +60,7 @@ { "id": "test" }, - "test_hvg.h5ad:md5,a8c70cd2c88e801de037f181e6830997" + "test_hvg.h5ad:md5,c8bba9250a396c5f851539f069b286f5" ] ], "var": [ @@ -71,9 +71,9 @@ ] } ], - "timestamp": "2026-03-16T15:33:11.035461884", + "timestamp": "2026-03-24T19:11:54.87932", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } }, @@ -124,7 +124,7 @@ { "id": "test" }, - "test_hvg.h5ad:md5,4d3f42a1201d720b01d15133df67727d" + "test_hvg.h5ad:md5,8dbc3d35e675694bb3ec5c741260865d" ] ], "1": [ @@ -138,7 +138,7 @@ { "id": "test" }, - "test_hvg.h5ad:md5,4d3f42a1201d720b01d15133df67727d" + "test_hvg.h5ad:md5,8dbc3d35e675694bb3ec5c741260865d" ] ], "var": [ @@ -149,9 +149,9 @@ ] } ], - "timestamp": "2026-03-16T15:33:45.021373498", + "timestamp": "2026-03-24T19:12:19.009392", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } } diff --git a/modules/local/scanpy/umap/tests/main.nf.test.snap b/modules/local/scanpy/umap/tests/main.nf.test.snap index 9ff32e83..2d51e749 100644 --- a/modules/local/scanpy/umap/tests/main.nf.test.snap +++ b/modules/local/scanpy/umap/tests/main.nf.test.snap @@ -48,8 +48,8 @@ "content": [ { "variance_ratio": [ - 0.81, - 0.19 + 0.812, + 0.188 ] }, { @@ -60,10 +60,10 @@ } } ], - "timestamp": "2026-03-22T11:03:25.274578244", + "timestamp": "2026-03-24T19:16:21.013943", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/subworkflows/local/doublet_detection/tests/main.nf.test.snap b/subworkflows/local/doublet_detection/tests/main.nf.test.snap index 0930bd3b..38974f8e 100644 --- a/subworkflows/local/doublet_detection/tests/main.nf.test.snap +++ b/subworkflows/local/doublet_detection/tests/main.nf.test.snap @@ -6,9 +6,9 @@ "versions.yml:md5,413d1a693de9ab89500219638de87ee2" ] ], - "timestamp": "2026-03-16T16:26:16.794928707", + "timestamp": "2026-03-24T20:24:53.973965", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } }, diff --git a/subworkflows/local/per_group/tests/main.nf.test.snap b/subworkflows/local/per_group/tests/main.nf.test.snap index 5c47fe4a..606bff27 100644 --- a/subworkflows/local/per_group/tests/main.nf.test.snap +++ b/subworkflows/local/per_group/tests/main.nf.test.snap @@ -32,41 +32,41 @@ "content": [ { "0": [ - "condition:leiden:0_characteristic_genes.pkl:md5,d6be6f9447ed67f6bb5d5df1acf22b86", - "condition:leiden:10_characteristic_genes.pkl:md5,7fd29daa10b8008e16f5c9639a402587", - "condition:leiden:11_characteristic_genes.pkl:md5,9e96aaf44b8d0f0c26a5bda59f63b096", - "condition:leiden:1_characteristic_genes.pkl:md5,f2d38b8ddd01bfd820945fc25fb15f06", - "condition:leiden:2_characteristic_genes.pkl:md5,184a05f08b741d4a0b6e0ee17a9609ec", - "condition:leiden:3_characteristic_genes.pkl:md5,b1bcd5c5d3332c121b01d24cb46a2334", - "condition:leiden:4_characteristic_genes.pkl:md5,15bc73779b616c2276eeedc94bd448b6", - "condition:leiden:5_characteristic_genes.pkl:md5,f314433d06e822b6bcdcccfe1635d32c", - "condition:leiden:6_characteristic_genes.pkl:md5,96e0edc86bf4df08008ff1af3cc10522", - "condition:leiden:7_characteristic_genes.pkl:md5,91ae9da4509aaddb59fb79505f6d37af", - "condition:leiden:8_characteristic_genes.pkl:md5,fae74f6935930804cd95b1e62b393f44", - "condition:leiden:9_characteristic_genes.pkl:md5,635e5ca72000437e64a458a4fc89dc4b", - "leiden:condition:Disease_characteristic_genes.pkl:md5,029b3b97860e8ba00b2b7701c0ef4836", - "leiden:condition:Healthy_characteristic_genes.pkl:md5,f638b9a63be41a80c24367c329ad9c92", - "leiden:condition:Treated_characteristic_genes.pkl:md5,5761aff9c5fff490dee108a0127a8af4", - "leiden_characteristic_genes.pkl:md5,e387d9c66878055c92c3d4de44cec54a", - "test_liana.pkl:md5,45ccfc4e57fcb1687a4fe33535900110", + "condition:leiden:0_characteristic_genes.pkl:md5,6f2554cd4ad38c9bc79432a39fa0b409", + "condition:leiden:10_characteristic_genes.pkl:md5,b5cddf4993cd232ce31bb203ae95e095", + "condition:leiden:11_characteristic_genes.pkl:md5,245c0b4c0f35fdddae82a4abaf5206a4", + "condition:leiden:1_characteristic_genes.pkl:md5,869fcb61764f6d9e5e0b40ce10d8ba53", + "condition:leiden:2_characteristic_genes.pkl:md5,3f60956bb8fbc03d3c78662eba09d636", + "condition:leiden:3_characteristic_genes.pkl:md5,12e4e59b30050f1e8c5923e75966a4f9", + "condition:leiden:4_characteristic_genes.pkl:md5,9cecb081fd439849da75f437225401a9", + "condition:leiden:5_characteristic_genes.pkl:md5,5a1b5772f54d13c212e1629294682710", + "condition:leiden:6_characteristic_genes.pkl:md5,a77f8e628ef51c30bbe8502c2971738a", + "condition:leiden:7_characteristic_genes.pkl:md5,f43da75d0b5ca1adfb4461b1154cbbf4", + "condition:leiden:8_characteristic_genes.pkl:md5,1cf4e2aa43cd7990916c6d7fc21ff8b0", + "condition:leiden:9_characteristic_genes.pkl:md5,566473d7b82102221f3ff9028c8d8c63", + "leiden:condition:Disease_characteristic_genes.pkl:md5,26d956e25d644b767927a3c49cd01cf1", + "leiden:condition:Healthy_characteristic_genes.pkl:md5,d0fb86ba914f56dccf30be7268e62d8a", + "leiden:condition:Treated_characteristic_genes.pkl:md5,c91689a8a2fa03f7e832143818264984", + "leiden_characteristic_genes.pkl:md5,70d99a12704d8de11935e9c22ca75c5c", + "test_liana.pkl:md5,31f0ac157a5f1763a5304dd68974757a", "test_paga.pkl:md5,fbd4ae54e51678480c8c4712a9aad0c8" ], "1": [ "condition:leiden:0_characteristic_genes_mqc.json:md5,0d9173af58f05a6a017b7bf62a8ab6a8", "condition:leiden:10_characteristic_genes_mqc.json:md5,1c42e764ba8a629df84a9f6a7b7cb889", - "condition:leiden:11_characteristic_genes_mqc.json:md5,0778f0f0cd0bd3edf2317a7b557ce952", + "condition:leiden:11_characteristic_genes_mqc.json:md5,2c731f81eabd55cea7c6204127e52cca", "condition:leiden:1_characteristic_genes_mqc.json:md5,a3b5df45edbd4dcc5fb3cf73864f4e76", "condition:leiden:2_characteristic_genes_mqc.json:md5,1656d5018a65811325f95449b34f302b", "condition:leiden:3_characteristic_genes_mqc.json:md5,1ce90ec438f14d33bebd26db002544cb", "condition:leiden:4_characteristic_genes_mqc.json:md5,375733d6a0a018ad6ef0776d5039fb64", - "condition:leiden:5_characteristic_genes_mqc.json:md5,17df859608e296b50492d4fbcaff66f2", - "condition:leiden:6_characteristic_genes_mqc.json:md5,21ec62fdde2bb968127d4f8b5acabaa7", + "condition:leiden:5_characteristic_genes_mqc.json:md5,f4c37ef44bc9634d035a3180208c28b1", + "condition:leiden:6_characteristic_genes_mqc.json:md5,29bae0880d7eacb6da9c1ef45d22f9c4", "condition:leiden:7_characteristic_genes_mqc.json:md5,d1fa8613daecf0aafb769d14c9be39d7", "condition:leiden:8_characteristic_genes_mqc.json:md5,2602bc68c47188fda2742ad9f222cf4e", - "condition:leiden:9_characteristic_genes_mqc.json:md5,c968bea56d8763520f0d68de394ccb79", - "leiden:condition:Disease_characteristic_genes_mqc.json:md5,46ee7c6e656b2419d618650d7c67d0b0", - "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,cc6e0fe227a84f1036f893945604dcc2", - "leiden:condition:Treated_characteristic_genes_mqc.json:md5,a7a78be0d9f0655ae8a5cae77daf0a74", + "condition:leiden:9_characteristic_genes_mqc.json:md5,25f88011184cd35edbae303c67fd30d5", + "leiden:condition:Disease_characteristic_genes_mqc.json:md5,54b6743a8852defebc9b9a06d9e230d8", + "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,84f2a400ce922382be222d803b90a1e1", + "leiden:condition:Treated_characteristic_genes_mqc.json:md5,69ce2c401ed338c4288a47e4aeb0359c", "leiden_characteristic_genes_mqc.json:md5,875d02a88fd8f4f0c0462f4da112d1ed", "test_paga_mqc.json:md5,71c52f6ea9306b6763abd0496e55fe98" ], @@ -93,40 +93,40 @@ "multiqc_files": [ "condition:leiden:0_characteristic_genes_mqc.json:md5,0d9173af58f05a6a017b7bf62a8ab6a8", "condition:leiden:10_characteristic_genes_mqc.json:md5,1c42e764ba8a629df84a9f6a7b7cb889", - "condition:leiden:11_characteristic_genes_mqc.json:md5,0778f0f0cd0bd3edf2317a7b557ce952", + "condition:leiden:11_characteristic_genes_mqc.json:md5,2c731f81eabd55cea7c6204127e52cca", "condition:leiden:1_characteristic_genes_mqc.json:md5,a3b5df45edbd4dcc5fb3cf73864f4e76", "condition:leiden:2_characteristic_genes_mqc.json:md5,1656d5018a65811325f95449b34f302b", "condition:leiden:3_characteristic_genes_mqc.json:md5,1ce90ec438f14d33bebd26db002544cb", "condition:leiden:4_characteristic_genes_mqc.json:md5,375733d6a0a018ad6ef0776d5039fb64", - "condition:leiden:5_characteristic_genes_mqc.json:md5,17df859608e296b50492d4fbcaff66f2", - "condition:leiden:6_characteristic_genes_mqc.json:md5,21ec62fdde2bb968127d4f8b5acabaa7", + "condition:leiden:5_characteristic_genes_mqc.json:md5,f4c37ef44bc9634d035a3180208c28b1", + "condition:leiden:6_characteristic_genes_mqc.json:md5,29bae0880d7eacb6da9c1ef45d22f9c4", "condition:leiden:7_characteristic_genes_mqc.json:md5,d1fa8613daecf0aafb769d14c9be39d7", "condition:leiden:8_characteristic_genes_mqc.json:md5,2602bc68c47188fda2742ad9f222cf4e", - "condition:leiden:9_characteristic_genes_mqc.json:md5,c968bea56d8763520f0d68de394ccb79", - "leiden:condition:Disease_characteristic_genes_mqc.json:md5,46ee7c6e656b2419d618650d7c67d0b0", - "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,cc6e0fe227a84f1036f893945604dcc2", - "leiden:condition:Treated_characteristic_genes_mqc.json:md5,a7a78be0d9f0655ae8a5cae77daf0a74", + "condition:leiden:9_characteristic_genes_mqc.json:md5,25f88011184cd35edbae303c67fd30d5", + "leiden:condition:Disease_characteristic_genes_mqc.json:md5,54b6743a8852defebc9b9a06d9e230d8", + "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,84f2a400ce922382be222d803b90a1e1", + "leiden:condition:Treated_characteristic_genes_mqc.json:md5,69ce2c401ed338c4288a47e4aeb0359c", "leiden_characteristic_genes_mqc.json:md5,875d02a88fd8f4f0c0462f4da112d1ed", "test_paga_mqc.json:md5,71c52f6ea9306b6763abd0496e55fe98" ], "uns": [ - "condition:leiden:0_characteristic_genes.pkl:md5,d6be6f9447ed67f6bb5d5df1acf22b86", - "condition:leiden:10_characteristic_genes.pkl:md5,7fd29daa10b8008e16f5c9639a402587", - "condition:leiden:11_characteristic_genes.pkl:md5,9e96aaf44b8d0f0c26a5bda59f63b096", - "condition:leiden:1_characteristic_genes.pkl:md5,f2d38b8ddd01bfd820945fc25fb15f06", - "condition:leiden:2_characteristic_genes.pkl:md5,184a05f08b741d4a0b6e0ee17a9609ec", - "condition:leiden:3_characteristic_genes.pkl:md5,b1bcd5c5d3332c121b01d24cb46a2334", - "condition:leiden:4_characteristic_genes.pkl:md5,15bc73779b616c2276eeedc94bd448b6", - "condition:leiden:5_characteristic_genes.pkl:md5,f314433d06e822b6bcdcccfe1635d32c", - "condition:leiden:6_characteristic_genes.pkl:md5,96e0edc86bf4df08008ff1af3cc10522", - "condition:leiden:7_characteristic_genes.pkl:md5,91ae9da4509aaddb59fb79505f6d37af", - "condition:leiden:8_characteristic_genes.pkl:md5,fae74f6935930804cd95b1e62b393f44", - "condition:leiden:9_characteristic_genes.pkl:md5,635e5ca72000437e64a458a4fc89dc4b", - "leiden:condition:Disease_characteristic_genes.pkl:md5,029b3b97860e8ba00b2b7701c0ef4836", - "leiden:condition:Healthy_characteristic_genes.pkl:md5,f638b9a63be41a80c24367c329ad9c92", - "leiden:condition:Treated_characteristic_genes.pkl:md5,5761aff9c5fff490dee108a0127a8af4", - "leiden_characteristic_genes.pkl:md5,e387d9c66878055c92c3d4de44cec54a", - "test_liana.pkl:md5,45ccfc4e57fcb1687a4fe33535900110", + "condition:leiden:0_characteristic_genes.pkl:md5,6f2554cd4ad38c9bc79432a39fa0b409", + "condition:leiden:10_characteristic_genes.pkl:md5,b5cddf4993cd232ce31bb203ae95e095", + "condition:leiden:11_characteristic_genes.pkl:md5,245c0b4c0f35fdddae82a4abaf5206a4", + "condition:leiden:1_characteristic_genes.pkl:md5,869fcb61764f6d9e5e0b40ce10d8ba53", + "condition:leiden:2_characteristic_genes.pkl:md5,3f60956bb8fbc03d3c78662eba09d636", + "condition:leiden:3_characteristic_genes.pkl:md5,12e4e59b30050f1e8c5923e75966a4f9", + "condition:leiden:4_characteristic_genes.pkl:md5,9cecb081fd439849da75f437225401a9", + "condition:leiden:5_characteristic_genes.pkl:md5,5a1b5772f54d13c212e1629294682710", + "condition:leiden:6_characteristic_genes.pkl:md5,a77f8e628ef51c30bbe8502c2971738a", + "condition:leiden:7_characteristic_genes.pkl:md5,f43da75d0b5ca1adfb4461b1154cbbf4", + "condition:leiden:8_characteristic_genes.pkl:md5,1cf4e2aa43cd7990916c6d7fc21ff8b0", + "condition:leiden:9_characteristic_genes.pkl:md5,566473d7b82102221f3ff9028c8d8c63", + "leiden:condition:Disease_characteristic_genes.pkl:md5,26d956e25d644b767927a3c49cd01cf1", + "leiden:condition:Healthy_characteristic_genes.pkl:md5,d0fb86ba914f56dccf30be7268e62d8a", + "leiden:condition:Treated_characteristic_genes.pkl:md5,c91689a8a2fa03f7e832143818264984", + "leiden_characteristic_genes.pkl:md5,70d99a12704d8de11935e9c22ca75c5c", + "test_liana.pkl:md5,31f0ac157a5f1763a5304dd68974757a", "test_paga.pkl:md5,fbd4ae54e51678480c8c4712a9aad0c8" ], "versions": [ @@ -151,10 +151,10 @@ ] } ], - "timestamp": "2026-03-22T16:23:46.565771167", + "timestamp": "2026-03-24T19:51:41.129349", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index bf510510..8b57796f 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -259,10 +259,6 @@ "multiqc/multiqc_data/multiqc_sizes.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_plots", - "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -283,10 +279,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T15:35:27.123807122", + "timestamp": "2026-03-24T21:34:53.411968", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index 238b4f04..8a627281 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -2,18 +2,6 @@ "Should process data from scratch": { "content": [ { - "ADATA_EXTEND": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "ADATA_MERGE": { - "anndata": "0.12.10", - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, "ADATA_READRDS": { "anndata": "0.11.1", "anndata2ri": "1.3.2", @@ -21,20 +9,6 @@ "pandas": "2.2.3", "seurat": "5.1.0" }, - "ADATA_TORDS": { - "anndataR": "1.0.2" - }, - "ADATA_UNIFY": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "python": "3.13.12", - "scipy": "1.17.1" - }, - "CELDA_DECONTX": { - "r": "4.5.3", - "anndataR": "1.0.2", - "celda": "1.26.0" - }, "CELLDEX_FETCHREFERENCE": { "R": "R version 4.4.1 (2024-06-14)", "celldex": "1.16.0", @@ -42,267 +16,39 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, - "CELLTYPES_CELLTYPIST": { - "python": "3.12.8", - "pandas": "2.2.3", - "scanpy": "1.10.4", - "celltypist": "1.6.3" - }, - "CELLTYPES_SINGLER": { - "R": "R version 4.5.3 (2026-03-11)", - "SingleR": "2.12.0", - "celldex": "1.20.0", - "anndataR": "1.0.2", - "ggplot2": "4.0.2" - }, - "COLLECT_SIZES": { - "pandas": "2.3.3", - "python": "3.13.12" - }, - "DOUBLET_REMOVAL": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "pandas": "2.3.3", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, - "ENTROPY": { - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "FINALIZE_QC_ANNDATAS": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "GET_DEDOUBLETED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "GET_THRESHOLDED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "LEIDEN": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "NEIGHBORS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "QC_FILTERED": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, "QC_RAW": { "matplotlib": "3.10.8", "python": "3.13.12", "scanpy": "1.12" }, - "SCANPY_BBKNN": { - "bbknn": "1.6.0", - "pandas": "2.3.3", - "python": "3.12.12", - "scanpy": "1.11.5" - }, - "SCANPY_CELLCYCLE": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_COMBAT": { - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_FILTER": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_HARMONY": { - "harmonypy": "0.2.0", - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_HVGS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_PAGA": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_RANKGENESGROUPS": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_SCRUBLET": { - "python": "3.12.11", - "scanpy": "1.11.2" - }, - "SCVITOOLS_SCVI": { - "scvi": "1.3.3" - }, - "SEURAT_INTEGRATION": { - "R": "4.5.3", - "Seurat": "5.4.0", - "anndataR": "1.0.2" - }, - "UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "UPSET_GENES": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - }, - "liana": "1.6.1", - "python": "3.12.12", - "scanpy": "1.11.5" + } }, [ - "celltypes", - "celltypes/singler", - "celltypes/singler/SRR28679756_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679756_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679756_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679756_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679756_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_predictions.csv", - "celltypes/singler/SRR28679757_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679757_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679757_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679757_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679757_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_predictions.csv", - "celltypes/singler/SRR28679758_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679758_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679758_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679758_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679758_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_predictions.csv", - "cluster_dimred", - "cluster_dimred/bbknn", - "cluster_dimred/bbknn/entropy", - "cluster_dimred/bbknn/entropy/bbknn-global-0.5_entropy.png", - "cluster_dimred/bbknn/entropy/bbknn-global-1.0_entropy.png", - "cluster_dimred/bbknn/leiden", - "cluster_dimred/bbknn/leiden/bbknn-global-0.5_leiden.png", - "cluster_dimred/bbknn/leiden/bbknn-global-1.0_leiden.png", - "cluster_dimred/bbknn/umap", - "cluster_dimred/combat", - "cluster_dimred/combat/entropy", - "cluster_dimred/combat/entropy/combat-global-0.5_entropy.png", - "cluster_dimred/combat/entropy/combat-global-1.0_entropy.png", - "cluster_dimred/combat/leiden", - "cluster_dimred/combat/leiden/combat-global-0.5_leiden.png", - "cluster_dimred/combat/leiden/combat-global-1.0_leiden.png", - "cluster_dimred/combat/umap", - "cluster_dimred/harmony", - "cluster_dimred/harmony/entropy", - "cluster_dimred/harmony/entropy/harmony-global-0.5_entropy.png", - "cluster_dimred/harmony/entropy/harmony-global-1.0_entropy.png", - "cluster_dimred/harmony/leiden", - "cluster_dimred/harmony/leiden/harmony-global-0.5_leiden.png", - "cluster_dimred/harmony/leiden/harmony-global-1.0_leiden.png", - "cluster_dimred/harmony/umap", - "cluster_dimred/scvi", - "cluster_dimred/scvi/entropy", - "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", - "cluster_dimred/scvi/leiden", - "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", - "cluster_dimred/scvi/umap", - "cluster_dimred/seurat", - "cluster_dimred/seurat/entropy", - "cluster_dimred/seurat/entropy/seurat-global-0.5_entropy.png", - "cluster_dimred/seurat/entropy/seurat-global-1.0_entropy.png", - "cluster_dimred/seurat/leiden", - "cluster_dimred/seurat/leiden/seurat-global-0.5_leiden.png", - "cluster_dimred/seurat/leiden/seurat-global-1.0_leiden.png", - "cluster_dimred/seurat/umap", - "combine", - "combine/integrate", - "combine/integrate/scvi", - "combine/integrate/scvi/scvi_model", - "combine/integrate/scvi/scvi_model/model.pt", - "combine/merge", - "combine/merge/upset_genes.png", - "finalized", - "finalized/merged.h5ad", - "finalized/merged.rds", - "finalized/merged_metadata.csv", - "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_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", - "multiqc/multiqc_report.html", - "per_group", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "quality_control", - "quality_control/qc_filtered", - "quality_control/qc_filtered/SRR28679756_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_filtered/SRR28679757_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_filtered/SRR28679758_preprocessed_total_counts_vs_n_genes_by_counts.png", "quality_control/qc_raw", "quality_control/qc_raw/SRR28679756_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw/SRR28679757_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw/SRR28679758_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/sizes", - "quality_control/sizes/sizes.tsv" + "quality_control/qc_raw/SRR28679757_raw_total_counts_vs_n_genes_by_counts.png" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-24T15:42:23.456824765", + "timestamp": "2026-03-24T20:51:24.530168", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_extend.nf.test.snap b/tests/main_pipeline_extend.nf.test.snap index b7b8bb0d..606a79c5 100644 --- a/tests/main_pipeline_extend.nf.test.snap +++ b/tests/main_pipeline_extend.nf.test.snap @@ -191,10 +191,6 @@ "multiqc/multiqc_data/multiqc_sizes.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_plots", - "multiqc/multiqc_plots/pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -211,10 +207,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T15:35:23.085276096", + "timestamp": "2026-03-24T21:16:45.188348", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index fb43c2ac..7b80c99f 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -171,8 +171,8 @@ ], "timestamp": "2026-03-24T18:39:32.940515591", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } -} \ No newline at end of file +} diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 48450606..652c195f 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -210,8 +210,8 @@ ], "timestamp": "2026-03-24T18:43:18.421083649", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } -} \ No newline at end of file +} diff --git a/tests/main_pipeline_sub.nf.test.snap b/tests/main_pipeline_sub.nf.test.snap index d97db967..3be6adf1 100644 --- a/tests/main_pipeline_sub.nf.test.snap +++ b/tests/main_pipeline_sub.nf.test.snap @@ -1,38 +1,12 @@ { "Should be able to perform subclustering": { "content": [ - 291, + 9, { - "ADATA_EXTEND": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, "ADATA_SPLITEMBEDDINGS": { "anndata": "0.12.10", "python": "3.13.12" }, - "ADATA_TORDS": { - "anndataR": "1.0.2" - }, - "ENTROPY": { - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "LEIDEN": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "NEIGHBORS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_PAGA": { - "python": "3.13.12", - "scanpy": "1.12" - }, "SCANPY_RANKGENESGROUPS": { "pandas": "2.3.3", "python": "3.13.12", @@ -42,546 +16,25 @@ "anndata": "0.12.10", "python": "3.13.12" }, - "UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - }, - "liana": "1.6.1", - "python": "3.12.12", - "scanpy": "1.11.5" + } }, [ "adata", "adata/combat.h5ad", "adata/harmony.h5ad", "adata/scvi.h5ad", - "cluster_dimred", - "cluster_dimred/combat", - "cluster_dimred/combat/entropy", - "cluster_dimred/combat/entropy/combat-SRR28679756-0.5_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679756-1.0_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679757-0.5_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679757-1.0_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679758-0.5_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679758-1.0_entropy.png", - "cluster_dimred/combat/leiden", - "cluster_dimred/combat/leiden/combat-SRR28679756-0.5_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679756-1.0_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679757-0.5_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679757-1.0_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679758-0.5_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679758-1.0_leiden.png", - "cluster_dimred/combat/umap", - "cluster_dimred/harmony", - "cluster_dimred/harmony/entropy", - "cluster_dimred/harmony/entropy/harmony-SRR28679756-0.5_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679756-1.0_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679757-0.5_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679757-1.0_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679758-0.5_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679758-1.0_entropy.png", - "cluster_dimred/harmony/leiden", - "cluster_dimred/harmony/leiden/harmony-SRR28679756-0.5_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679756-1.0_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679757-0.5_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679757-1.0_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679758-0.5_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679758-1.0_leiden.png", - "cluster_dimred/harmony/umap", - "cluster_dimred/scvi", - "cluster_dimred/scvi/entropy", - "cluster_dimred/scvi/entropy/scvi-SRR28679756-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679756-1.0_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679757-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679757-1.0_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679758-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679758-1.0_entropy.png", - "cluster_dimred/scvi/leiden", - "cluster_dimred/scvi/leiden/scvi-SRR28679756-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679756-1.0_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679757-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679757-1.0_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679758-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679758-1.0_leiden.png", - "cluster_dimred/scvi/umap", - "finalized", - "finalized/base.h5ad", - "finalized/base.rds", - "finalized/base_metadata.csv", - "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", "per_group", - "per_group/combat-SRR28679756", - "per_group/combat-SRR28679756-0.5", - "per_group/combat-SRR28679756-0.5/paga", - "per_group/combat-SRR28679756-0.5/paga/combat-SRR28679756-0.5_paga.png", - "per_group/combat-SRR28679756-0.5_leiden", - "per_group/combat-SRR28679756-0.5_leiden/characteristic_genes", - "per_group/combat-SRR28679756-0.5_leiden/characteristic_genes/combat-SRR28679756-0.5_leiden_characteristic_genes.png", - "per_group/combat-SRR28679756-1.0", - "per_group/combat-SRR28679756-1.0/paga", - "per_group/combat-SRR28679756-1.0/paga/combat-SRR28679756-1.0_paga.png", - "per_group/combat-SRR28679756-1.0_leiden", - "per_group/combat-SRR28679756-1.0_leiden/characteristic_genes", - "per_group/combat-SRR28679756-1.0_leiden/characteristic_genes/combat-SRR28679756-1.0_leiden_characteristic_genes.png", - "per_group/combat-SRR28679756/paga", - "per_group/combat-SRR28679757", - "per_group/combat-SRR28679757-0.5", - "per_group/combat-SRR28679757-0.5/paga", - "per_group/combat-SRR28679757-0.5/paga/combat-SRR28679757-0.5_paga.png", - "per_group/combat-SRR28679757-0.5_leiden", - "per_group/combat-SRR28679757-0.5_leiden/characteristic_genes", - "per_group/combat-SRR28679757-0.5_leiden/characteristic_genes/combat-SRR28679757-0.5_leiden_characteristic_genes.png", - "per_group/combat-SRR28679757-1.0", - "per_group/combat-SRR28679757-1.0/paga", - "per_group/combat-SRR28679757-1.0/paga/combat-SRR28679757-1.0_paga.png", - "per_group/combat-SRR28679757-1.0_leiden", - "per_group/combat-SRR28679757-1.0_leiden/characteristic_genes", - "per_group/combat-SRR28679757-1.0_leiden/characteristic_genes/combat-SRR28679757-1.0_leiden_characteristic_genes.png", - "per_group/combat-SRR28679757/paga", - "per_group/combat-SRR28679758", - "per_group/combat-SRR28679758-0.5", - "per_group/combat-SRR28679758-0.5/paga", - "per_group/combat-SRR28679758-0.5/paga/combat-SRR28679758-0.5_paga.png", - "per_group/combat-SRR28679758-0.5_leiden", - "per_group/combat-SRR28679758-0.5_leiden/characteristic_genes", - "per_group/combat-SRR28679758-0.5_leiden/characteristic_genes/combat-SRR28679758-0.5_leiden_characteristic_genes.png", - "per_group/combat-SRR28679758-1.0", - "per_group/combat-SRR28679758-1.0/paga", - "per_group/combat-SRR28679758-1.0/paga/combat-SRR28679758-1.0_paga.png", - "per_group/combat-SRR28679758-1.0_leiden", - "per_group/combat-SRR28679758-1.0_leiden/characteristic_genes", - "per_group/combat-SRR28679758-1.0_leiden/characteristic_genes/combat-SRR28679758-1.0_leiden_characteristic_genes.png", - "per_group/combat-SRR28679758/paga", - "per_group/condition:combat-SRR28679756-0.5_leiden:0", - "per_group/condition:combat-SRR28679756-0.5_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:1", - "per_group/condition:combat-SRR28679756-0.5_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:2", - "per_group/condition:combat-SRR28679756-0.5_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:3", - "per_group/condition:combat-SRR28679756-0.5_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:4", - "per_group/condition:combat-SRR28679756-0.5_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:5", - "per_group/condition:combat-SRR28679756-0.5_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:6", - "per_group/condition:combat-SRR28679756-0.5_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:7", - "per_group/condition:combat-SRR28679756-0.5_leiden:7/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:8", - "per_group/condition:combat-SRR28679756-0.5_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:9", - "per_group/condition:combat-SRR28679756-0.5_leiden:9/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:0", - "per_group/condition:combat-SRR28679756-1.0_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:1", - "per_group/condition:combat-SRR28679756-1.0_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:10", - "per_group/condition:combat-SRR28679756-1.0_leiden:10/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:11", - "per_group/condition:combat-SRR28679756-1.0_leiden:11/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:12", - "per_group/condition:combat-SRR28679756-1.0_leiden:12/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:13", - "per_group/condition:combat-SRR28679756-1.0_leiden:13/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:14", - "per_group/condition:combat-SRR28679756-1.0_leiden:14/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:15", - "per_group/condition:combat-SRR28679756-1.0_leiden:15/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:2", - "per_group/condition:combat-SRR28679756-1.0_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:3", - "per_group/condition:combat-SRR28679756-1.0_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:4", - "per_group/condition:combat-SRR28679756-1.0_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:5", - "per_group/condition:combat-SRR28679756-1.0_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:6", - "per_group/condition:combat-SRR28679756-1.0_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:7", - "per_group/condition:combat-SRR28679756-1.0_leiden:7/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:8", - "per_group/condition:combat-SRR28679756-1.0_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:9", - "per_group/condition:combat-SRR28679756-1.0_leiden:9/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:0", - "per_group/condition:combat-SRR28679757-0.5_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:1", - "per_group/condition:combat-SRR28679757-0.5_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:2", - "per_group/condition:combat-SRR28679757-0.5_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:3", - "per_group/condition:combat-SRR28679757-0.5_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:4", - "per_group/condition:combat-SRR28679757-0.5_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:5", - "per_group/condition:combat-SRR28679757-0.5_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:6", - "per_group/condition:combat-SRR28679757-0.5_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:0", - "per_group/condition:combat-SRR28679757-1.0_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:1", - "per_group/condition:combat-SRR28679757-1.0_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:10", - "per_group/condition:combat-SRR28679757-1.0_leiden:10/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:11", - "per_group/condition:combat-SRR28679757-1.0_leiden:11/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:12", - "per_group/condition:combat-SRR28679757-1.0_leiden:12/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:2", - "per_group/condition:combat-SRR28679757-1.0_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:3", - "per_group/condition:combat-SRR28679757-1.0_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:4", - "per_group/condition:combat-SRR28679757-1.0_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:5", - "per_group/condition:combat-SRR28679757-1.0_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:6", - "per_group/condition:combat-SRR28679757-1.0_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:7", - "per_group/condition:combat-SRR28679757-1.0_leiden:7/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:8", - "per_group/condition:combat-SRR28679757-1.0_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:9", - "per_group/condition:combat-SRR28679757-1.0_leiden:9/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:0", - "per_group/condition:combat-SRR28679758-0.5_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:1", - "per_group/condition:combat-SRR28679758-0.5_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:2", - "per_group/condition:combat-SRR28679758-0.5_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:3", - "per_group/condition:combat-SRR28679758-0.5_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:4", - "per_group/condition:combat-SRR28679758-0.5_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:5", - "per_group/condition:combat-SRR28679758-0.5_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:6", - "per_group/condition:combat-SRR28679758-0.5_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:0", - "per_group/condition:combat-SRR28679758-1.0_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:1", - "per_group/condition:combat-SRR28679758-1.0_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:10", - "per_group/condition:combat-SRR28679758-1.0_leiden:10/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:11", - "per_group/condition:combat-SRR28679758-1.0_leiden:11/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:12", - "per_group/condition:combat-SRR28679758-1.0_leiden:12/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:13", - "per_group/condition:combat-SRR28679758-1.0_leiden:13/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:2", - "per_group/condition:combat-SRR28679758-1.0_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:3", - "per_group/condition:combat-SRR28679758-1.0_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:4", - "per_group/condition:combat-SRR28679758-1.0_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:5", - "per_group/condition:combat-SRR28679758-1.0_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:6", - "per_group/condition:combat-SRR28679758-1.0_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:7", - "per_group/condition:combat-SRR28679758-1.0_leiden:7/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:8", - "per_group/condition:combat-SRR28679758-1.0_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:9", - "per_group/condition:combat-SRR28679758-1.0_leiden:9/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:0", - "per_group/condition:harmony-SRR28679756-0.5_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:1", - "per_group/condition:harmony-SRR28679756-0.5_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:2", - "per_group/condition:harmony-SRR28679756-0.5_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:3", - "per_group/condition:harmony-SRR28679756-0.5_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:4", - "per_group/condition:harmony-SRR28679756-0.5_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:0", - "per_group/condition:harmony-SRR28679756-1.0_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:1", - "per_group/condition:harmony-SRR28679756-1.0_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:2", - "per_group/condition:harmony-SRR28679756-1.0_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:3", - "per_group/condition:harmony-SRR28679756-1.0_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:4", - "per_group/condition:harmony-SRR28679756-1.0_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:5", - "per_group/condition:harmony-SRR28679756-1.0_leiden:5/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:6", - "per_group/condition:harmony-SRR28679756-1.0_leiden:6/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:7", - "per_group/condition:harmony-SRR28679756-1.0_leiden:7/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:8", - "per_group/condition:harmony-SRR28679756-1.0_leiden:8/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:0", - "per_group/condition:harmony-SRR28679757-0.5_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:1", - "per_group/condition:harmony-SRR28679757-0.5_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:2", - "per_group/condition:harmony-SRR28679757-0.5_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:3", - "per_group/condition:harmony-SRR28679757-0.5_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:4", - "per_group/condition:harmony-SRR28679757-0.5_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:0", - "per_group/condition:harmony-SRR28679757-1.0_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:1", - "per_group/condition:harmony-SRR28679757-1.0_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:2", - "per_group/condition:harmony-SRR28679757-1.0_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:3", - "per_group/condition:harmony-SRR28679757-1.0_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:4", - "per_group/condition:harmony-SRR28679757-1.0_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:5", - "per_group/condition:harmony-SRR28679757-1.0_leiden:5/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:6", - "per_group/condition:harmony-SRR28679757-1.0_leiden:6/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:7", - "per_group/condition:harmony-SRR28679757-1.0_leiden:7/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:8", - "per_group/condition:harmony-SRR28679757-1.0_leiden:8/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:9", - "per_group/condition:harmony-SRR28679757-1.0_leiden:9/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:0", - "per_group/condition:harmony-SRR28679758-0.5_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:1", - "per_group/condition:harmony-SRR28679758-0.5_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:2", - "per_group/condition:harmony-SRR28679758-0.5_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:3", - "per_group/condition:harmony-SRR28679758-0.5_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:4", - "per_group/condition:harmony-SRR28679758-0.5_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:0", - "per_group/condition:harmony-SRR28679758-1.0_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:1", - "per_group/condition:harmony-SRR28679758-1.0_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:2", - "per_group/condition:harmony-SRR28679758-1.0_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:3", - "per_group/condition:harmony-SRR28679758-1.0_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:4", - "per_group/condition:harmony-SRR28679758-1.0_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:5", - "per_group/condition:harmony-SRR28679758-1.0_leiden:5/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:6", - "per_group/condition:harmony-SRR28679758-1.0_leiden:6/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:7", - "per_group/condition:harmony-SRR28679758-1.0_leiden:7/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:8", - "per_group/condition:harmony-SRR28679758-1.0_leiden:8/characteristic_genes", "per_group/condition:sample:SRR28679756", "per_group/condition:sample:SRR28679756/characteristic_genes", "per_group/condition:sample:SRR28679757", "per_group/condition:sample:SRR28679757/characteristic_genes", "per_group/condition:sample:SRR28679758", "per_group/condition:sample:SRR28679758/characteristic_genes", - "per_group/condition:scvi-SRR28679756-0.5_leiden:0", - "per_group/condition:scvi-SRR28679756-0.5_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679756-0.5_leiden:1", - "per_group/condition:scvi-SRR28679756-0.5_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679756-0.5_leiden:2", - "per_group/condition:scvi-SRR28679756-0.5_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:0", - "per_group/condition:scvi-SRR28679756-1.0_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:1", - "per_group/condition:scvi-SRR28679756-1.0_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:10", - "per_group/condition:scvi-SRR28679756-1.0_leiden:10/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:11", - "per_group/condition:scvi-SRR28679756-1.0_leiden:11/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:12", - "per_group/condition:scvi-SRR28679756-1.0_leiden:12/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:2", - "per_group/condition:scvi-SRR28679756-1.0_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:3", - "per_group/condition:scvi-SRR28679756-1.0_leiden:3/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:4", - "per_group/condition:scvi-SRR28679756-1.0_leiden:4/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:5", - "per_group/condition:scvi-SRR28679756-1.0_leiden:5/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:6", - "per_group/condition:scvi-SRR28679756-1.0_leiden:6/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:7", - "per_group/condition:scvi-SRR28679756-1.0_leiden:7/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:8", - "per_group/condition:scvi-SRR28679756-1.0_leiden:8/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:9", - "per_group/condition:scvi-SRR28679756-1.0_leiden:9/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:0", - "per_group/condition:scvi-SRR28679757-0.5_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:1", - "per_group/condition:scvi-SRR28679757-0.5_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:2", - "per_group/condition:scvi-SRR28679757-0.5_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:3", - "per_group/condition:scvi-SRR28679757-0.5_leiden:3/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:4", - "per_group/condition:scvi-SRR28679757-0.5_leiden:4/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:5", - "per_group/condition:scvi-SRR28679757-0.5_leiden:5/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:0", - "per_group/condition:scvi-SRR28679757-1.0_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:1", - "per_group/condition:scvi-SRR28679757-1.0_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:10", - "per_group/condition:scvi-SRR28679757-1.0_leiden:10/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:11", - "per_group/condition:scvi-SRR28679757-1.0_leiden:11/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:12", - "per_group/condition:scvi-SRR28679757-1.0_leiden:12/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:2", - "per_group/condition:scvi-SRR28679757-1.0_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:3", - "per_group/condition:scvi-SRR28679757-1.0_leiden:3/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:4", - "per_group/condition:scvi-SRR28679757-1.0_leiden:4/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:5", - "per_group/condition:scvi-SRR28679757-1.0_leiden:5/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:6", - "per_group/condition:scvi-SRR28679757-1.0_leiden:6/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:7", - "per_group/condition:scvi-SRR28679757-1.0_leiden:7/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:8", - "per_group/condition:scvi-SRR28679757-1.0_leiden:8/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:9", - "per_group/condition:scvi-SRR28679757-1.0_leiden:9/characteristic_genes", - "per_group/condition:scvi-SRR28679758-0.5_leiden:0", - "per_group/condition:scvi-SRR28679758-0.5_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679758-0.5_leiden:1", - "per_group/condition:scvi-SRR28679758-0.5_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679758-0.5_leiden:2", - "per_group/condition:scvi-SRR28679758-0.5_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:0", - "per_group/condition:scvi-SRR28679758-1.0_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:1", - "per_group/condition:scvi-SRR28679758-1.0_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:10", - "per_group/condition:scvi-SRR28679758-1.0_leiden:10/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:11", - "per_group/condition:scvi-SRR28679758-1.0_leiden:11/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:12", - "per_group/condition:scvi-SRR28679758-1.0_leiden:12/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:13", - "per_group/condition:scvi-SRR28679758-1.0_leiden:13/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:2", - "per_group/condition:scvi-SRR28679758-1.0_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:3", - "per_group/condition:scvi-SRR28679758-1.0_leiden:3/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:4", - "per_group/condition:scvi-SRR28679758-1.0_leiden:4/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:5", - "per_group/condition:scvi-SRR28679758-1.0_leiden:5/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:6", - "per_group/condition:scvi-SRR28679758-1.0_leiden:6/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:7", - "per_group/condition:scvi-SRR28679758-1.0_leiden:7/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:8", - "per_group/condition:scvi-SRR28679758-1.0_leiden:8/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:9", - "per_group/condition:scvi-SRR28679758-1.0_leiden:9/characteristic_genes", - "per_group/harmony-SRR28679756", - "per_group/harmony-SRR28679756-0.5", - "per_group/harmony-SRR28679756-0.5/paga", - "per_group/harmony-SRR28679756-0.5/paga/harmony-SRR28679756-0.5_paga.png", - "per_group/harmony-SRR28679756-0.5_leiden", - "per_group/harmony-SRR28679756-0.5_leiden/characteristic_genes", - "per_group/harmony-SRR28679756-0.5_leiden/characteristic_genes/harmony-SRR28679756-0.5_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679756-1.0", - "per_group/harmony-SRR28679756-1.0/paga", - "per_group/harmony-SRR28679756-1.0/paga/harmony-SRR28679756-1.0_paga.png", - "per_group/harmony-SRR28679756-1.0_leiden", - "per_group/harmony-SRR28679756-1.0_leiden/characteristic_genes", - "per_group/harmony-SRR28679756-1.0_leiden/characteristic_genes/harmony-SRR28679756-1.0_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679756/paga", - "per_group/harmony-SRR28679757", - "per_group/harmony-SRR28679757-0.5", - "per_group/harmony-SRR28679757-0.5/paga", - "per_group/harmony-SRR28679757-0.5/paga/harmony-SRR28679757-0.5_paga.png", - "per_group/harmony-SRR28679757-0.5_leiden", - "per_group/harmony-SRR28679757-0.5_leiden/characteristic_genes", - "per_group/harmony-SRR28679757-0.5_leiden/characteristic_genes/harmony-SRR28679757-0.5_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679757-1.0", - "per_group/harmony-SRR28679757-1.0/paga", - "per_group/harmony-SRR28679757-1.0/paga/harmony-SRR28679757-1.0_paga.png", - "per_group/harmony-SRR28679757-1.0_leiden", - "per_group/harmony-SRR28679757-1.0_leiden/characteristic_genes", - "per_group/harmony-SRR28679757-1.0_leiden/characteristic_genes/harmony-SRR28679757-1.0_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679757/paga", - "per_group/harmony-SRR28679758", - "per_group/harmony-SRR28679758-0.5", - "per_group/harmony-SRR28679758-0.5/paga", - "per_group/harmony-SRR28679758-0.5/paga/harmony-SRR28679758-0.5_paga.png", - "per_group/harmony-SRR28679758-0.5_leiden", - "per_group/harmony-SRR28679758-0.5_leiden/characteristic_genes", - "per_group/harmony-SRR28679758-0.5_leiden/characteristic_genes/harmony-SRR28679758-0.5_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679758-1.0", - "per_group/harmony-SRR28679758-1.0/paga", - "per_group/harmony-SRR28679758-1.0/paga/harmony-SRR28679758-1.0_paga.png", - "per_group/harmony-SRR28679758-1.0_leiden", - "per_group/harmony-SRR28679758-1.0_leiden/characteristic_genes", - "per_group/harmony-SRR28679758-1.0_leiden/characteristic_genes/harmony-SRR28679758-1.0_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679758/paga", "per_group/sample", "per_group/sample/characteristic_genes", "per_group/sample/characteristic_genes/sample_characteristic_genes.png", - "per_group/scvi-SRR28679756", - "per_group/scvi-SRR28679756-0.5", - "per_group/scvi-SRR28679756-0.5/paga", - "per_group/scvi-SRR28679756-0.5/paga/scvi-SRR28679756-0.5_paga.png", - "per_group/scvi-SRR28679756-0.5_leiden", - "per_group/scvi-SRR28679756-0.5_leiden/characteristic_genes", - "per_group/scvi-SRR28679756-0.5_leiden/characteristic_genes/scvi-SRR28679756-0.5_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679756-1.0", - "per_group/scvi-SRR28679756-1.0/paga", - "per_group/scvi-SRR28679756-1.0/paga/scvi-SRR28679756-1.0_paga.png", - "per_group/scvi-SRR28679756-1.0_leiden", - "per_group/scvi-SRR28679756-1.0_leiden/characteristic_genes", - "per_group/scvi-SRR28679756-1.0_leiden/characteristic_genes/scvi-SRR28679756-1.0_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679756/paga", - "per_group/scvi-SRR28679757", - "per_group/scvi-SRR28679757-0.5", - "per_group/scvi-SRR28679757-0.5/paga", - "per_group/scvi-SRR28679757-0.5/paga/scvi-SRR28679757-0.5_paga.png", - "per_group/scvi-SRR28679757-0.5_leiden", - "per_group/scvi-SRR28679757-0.5_leiden/characteristic_genes", - "per_group/scvi-SRR28679757-0.5_leiden/characteristic_genes/scvi-SRR28679757-0.5_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679757-1.0", - "per_group/scvi-SRR28679757-1.0/paga", - "per_group/scvi-SRR28679757-1.0/paga/scvi-SRR28679757-1.0_paga.png", - "per_group/scvi-SRR28679757-1.0_leiden", - "per_group/scvi-SRR28679757-1.0_leiden/characteristic_genes", - "per_group/scvi-SRR28679757-1.0_leiden/characteristic_genes/scvi-SRR28679757-1.0_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679757/paga", - "per_group/scvi-SRR28679758", - "per_group/scvi-SRR28679758-0.5", - "per_group/scvi-SRR28679758-0.5/paga", - "per_group/scvi-SRR28679758-0.5/paga/scvi-SRR28679758-0.5_paga.png", - "per_group/scvi-SRR28679758-0.5_leiden", - "per_group/scvi-SRR28679758-0.5_leiden/characteristic_genes", - "per_group/scvi-SRR28679758-0.5_leiden/characteristic_genes/scvi-SRR28679758-0.5_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679758-1.0", - "per_group/scvi-SRR28679758-1.0/paga", - "per_group/scvi-SRR28679758-1.0/paga/scvi-SRR28679758-1.0_paga.png", - "per_group/scvi-SRR28679758-1.0_leiden", - "per_group/scvi-SRR28679758-1.0_leiden/characteristic_genes", - "per_group/scvi-SRR28679758-1.0_leiden/characteristic_genes/scvi-SRR28679758-1.0_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679758/paga", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "splitcol", @@ -590,12 +43,12 @@ "splitcol/SRR28679758.h5ad" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-22T17:54:46.906369255", + "timestamp": "2026-03-24T20:38:21.169674", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } } From 32210e4ae6763e8dba24f313dcafc889521eb2eb Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 24 Mar 2026 22:35:46 +0100 Subject: [PATCH 09/46] Simplify umap tests --- modules/local/scanpy/umap/main.nf | 2 -- modules/local/scanpy/umap/templates/umap.py | 8 ------ modules/local/scanpy/umap/tests/main.nf.test | 7 +---- .../local/scanpy/umap/tests/main.nf.test.snap | 28 ++++--------------- 4 files changed, 7 insertions(+), 38 deletions(-) diff --git a/modules/local/scanpy/umap/main.nf b/modules/local/scanpy/umap/main.nf index 77d786ad..e5430d23 100644 --- a/modules/local/scanpy/umap/main.nf +++ b/modules/local/scanpy/umap/main.nf @@ -13,7 +13,6 @@ process SCANPY_UMAP { output: tuple val(meta), path("${prefix}.h5ad"), emit: h5ad path "X_${prefix}.pkl", emit: obsm - path "variance_ratio_${prefix}.yml", emit: variance_ratio path "versions.yml", emit: versions when: @@ -29,7 +28,6 @@ process SCANPY_UMAP { """ touch "${prefix}.h5ad" touch "X_${prefix}.pkl" - touch "variance_ratio_${prefix}.yml" touch "versions.yml" """ } diff --git a/modules/local/scanpy/umap/templates/umap.py b/modules/local/scanpy/umap/templates/umap.py index 1a410a5f..c187612b 100644 --- a/modules/local/scanpy/umap/templates/umap.py +++ b/modules/local/scanpy/umap/templates/umap.py @@ -32,14 +32,6 @@ if params.decimals is not None: adata.obsm["X_umap"] = np.round(adata.obsm["X_umap"].astype(np.float64), params.decimals) -var_per_dim = np.var(adata.obsm["X_umap"].astype(np.float64), axis=0) -variance_ratio = (var_per_dim / var_per_dim.sum()).tolist() -if params.decimals is not None: - variance_ratio = np.round(variance_ratio, params.decimals).tolist() - -with open(f"variance_ratio_{prefix}.yml", "w") as f: - yaml.dump({"variance_ratio": variance_ratio}, f) - adata.write_h5ad(f"{prefix}.h5ad") df = pd.DataFrame(adata.obsm["X_umap"], index=adata.obs_names) df.to_pickle(f"X_{prefix}.pkl") diff --git a/modules/local/scanpy/umap/tests/main.nf.test b/modules/local/scanpy/umap/tests/main.nf.test index 1b6edbc4..2ab2e2f1 100644 --- a/modules/local/scanpy/umap/tests/main.nf.test +++ b/modules/local/scanpy/umap/tests/main.nf.test @@ -29,12 +29,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { - assert snapshot( - path(process.out.variance_ratio[0]).yaml, - path(process.out.versions[0]).yaml - ).match() - }, + { assert snapshot(process.out.versions).match() }, { assert "X_umap" in anndata(process.out.h5ad[0][1]).obsm } ) } diff --git a/modules/local/scanpy/umap/tests/main.nf.test.snap b/modules/local/scanpy/umap/tests/main.nf.test.snap index 2d51e749..7af04343 100644 --- a/modules/local/scanpy/umap/tests/main.nf.test.snap +++ b/modules/local/scanpy/umap/tests/main.nf.test.snap @@ -14,9 +14,6 @@ "X_test.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "variance_ratio_test.yml:md5,d41d8cd98f00b204e9800998ecf8427e" - ], - "3": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ], "h5ad": [ @@ -30,9 +27,6 @@ "obsm": [ "X_test.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], - "variance_ratio": [ - "variance_ratio_test.yml:md5,d41d8cd98f00b204e9800998ecf8427e" - ], "versions": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ] @@ -46,24 +40,14 @@ }, "Should run without failures": { "content": [ - { - "variance_ratio": [ - 0.812, - 0.188 - ] - }, - { - "SCANPY_UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - } - } + [ + "versions.yml:md5,f7e77a6f6fe060c4158eb2a86e7c0754" + ] ], - "timestamp": "2026-03-24T19:16:21.013943", + "timestamp": "2026-03-24T22:36:15.214017742", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file From 25eab93615ef19b01ded3c7d3fa09b5ac66ed23b Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 24 Mar 2026 22:40:28 +0100 Subject: [PATCH 10/46] Update HVG tests --- modules/local/scanpy/hvgs/tests/main.nf.test | 12 +- .../local/scanpy/hvgs/tests/main.nf.test.snap | 117 +++--------------- 2 files changed, 27 insertions(+), 102 deletions(-) diff --git a/modules/local/scanpy/hvgs/tests/main.nf.test b/modules/local/scanpy/hvgs/tests/main.nf.test index 834e0cc6..f02d6277 100644 --- a/modules/local/scanpy/hvgs/tests/main.nf.test +++ b/modules/local/scanpy/hvgs/tests/main.nf.test @@ -27,9 +27,11 @@ nextflow_process { } then { + def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert "highly_variable" in anndata(h5ad).var.colnames } ) } @@ -55,9 +57,11 @@ nextflow_process { } then { + def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert "highly_variable" in anndata(h5ad).var.colnames } ) } @@ -84,9 +88,11 @@ nextflow_process { } then { + def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(process.out.versions).match() }, + { assert "highly_variable" in anndata(h5ad).var.colnames } ) } diff --git a/modules/local/scanpy/hvgs/tests/main.nf.test.snap b/modules/local/scanpy/hvgs/tests/main.nf.test.snap index 763a104e..b786fafc 100644 --- a/modules/local/scanpy/hvgs/tests/main.nf.test.snap +++ b/modules/local/scanpy/hvgs/tests/main.nf.test.snap @@ -1,80 +1,26 @@ { "Should run with a specified number of HVGs": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_hvg.h5ad:md5,b87529ef7c8990e93daf8b2e4781a845" - ] - ], - "1": [ - "test_hvg.pkl:md5,6e7304cb50e936bf78b69ad70b29495e" - ], - "2": [ - "versions.yml:md5,082c751136be043b260385c9829a571d" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_hvg.h5ad:md5,b87529ef7c8990e93daf8b2e4781a845" - ] - ], - "var": [ - "test_hvg.pkl:md5,6e7304cb50e936bf78b69ad70b29495e" - ], - "versions": [ - "versions.yml:md5,082c751136be043b260385c9829a571d" - ] - } + [ + "versions.yml:md5,082c751136be043b260385c9829a571d" + ] ], - "timestamp": "2026-03-24T19:12:07.14241", + "timestamp": "2026-03-24T22:39:20.219700483", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without a specified number of HVGs": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_hvg.h5ad:md5,c8bba9250a396c5f851539f069b286f5" - ] - ], - "1": [ - "test_hvg.pkl:md5,82f4f37286430dbfbe76a531a53b867d" - ], - "2": [ - "versions.yml:md5,082c751136be043b260385c9829a571d" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_hvg.h5ad:md5,c8bba9250a396c5f851539f069b286f5" - ] - ], - "var": [ - "test_hvg.pkl:md5,82f4f37286430dbfbe76a531a53b867d" - ], - "versions": [ - "versions.yml:md5,082c751136be043b260385c9829a571d" - ] - } + [ + "versions.yml:md5,082c751136be043b260385c9829a571d" + ] ], - "timestamp": "2026-03-24T19:11:54.87932", + "timestamp": "2026-03-24T22:38:55.263409625", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures - stub": { @@ -118,41 +64,14 @@ }, "Should run with a list of genes excluded from integration": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_hvg.h5ad:md5,8dbc3d35e675694bb3ec5c741260865d" - ] - ], - "1": [ - "test_hvg.pkl:md5,e7432bf749f3ff633369d0b3199a24c4" - ], - "2": [ - "versions.yml:md5,082c751136be043b260385c9829a571d" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_hvg.h5ad:md5,8dbc3d35e675694bb3ec5c741260865d" - ] - ], - "var": [ - "test_hvg.pkl:md5,e7432bf749f3ff633369d0b3199a24c4" - ], - "versions": [ - "versions.yml:md5,082c751136be043b260385c9829a571d" - ] - } + [ + "versions.yml:md5,082c751136be043b260385c9829a571d" + ] ], - "timestamp": "2026-03-24T19:12:19.009392", + "timestamp": "2026-03-24T22:39:44.588148179", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file From ec3648de3e489aef5d4d538b2d0c88f5a35d283d Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 24 Mar 2026 22:42:50 +0100 Subject: [PATCH 11/46] Update SCDS tests --- .../doublet_detection/scds/tests/main.nf.test | 12 ++++------ .../scds/tests/main.nf.test.snap | 24 ++++++------------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/modules/local/doublet_detection/scds/tests/main.nf.test b/modules/local/doublet_detection/scds/tests/main.nf.test index b1ddb738..50f9f24d 100644 --- a/modules/local/doublet_detection/scds/tests/main.nf.test +++ b/modules/local/doublet_detection/scds/tests/main.nf.test @@ -25,16 +25,12 @@ nextflow_process { } then { + def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot( - process.out.versions, - process.out.predictions, - // Hashing does not work due to this issue: - // https://github.com/scverse/anndataR/issues/272 - file(process.out.h5ad.get(0).get(1)).exists(), - file(process.out.h5ad.get(0).get(1)).size() - ).match() } + { assert snapshot(process.out.versions).match() }, + { assert anndata(h5ad).obs.rownames.size() > 0 }, + { assert process.out.predictions.size() > 0 } ) } diff --git a/modules/local/doublet_detection/scds/tests/main.nf.test.snap b/modules/local/doublet_detection/scds/tests/main.nf.test.snap index e2305bbb..0b282a5f 100644 --- a/modules/local/doublet_detection/scds/tests/main.nf.test.snap +++ b/modules/local/doublet_detection/scds/tests/main.nf.test.snap @@ -42,32 +42,22 @@ ] } ], + "timestamp": "2025-05-30T16:52:57.673676107", "meta": { "nf-test": "0.9.0", "nextflow": "25.04.2" - }, - "timestamp": "2025-05-30T16:52:57.673676107" + } }, "Should run without failures": { "content": [ [ "versions.yml:md5,c8683fe6c044ab53b908d2fd7c38f8f7" - ], - [ - [ - { - "id": "test" - }, - "test_scds.csv:md5,6bedc66c5fc2517cea4808a72c29e17f" - ] - ], - true, - 7541879 + ] ], + "timestamp": "2026-03-24T22:41:47.177647207", "meta": { - "nf-test": "0.9.0", - "nextflow": "25.04.2" - }, - "timestamp": "2025-05-30T16:52:47.324747683" + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } } } \ No newline at end of file From 6af93add1d3681e9b872464bc44b86079389bbf1 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 24 Mar 2026 22:54:12 +0100 Subject: [PATCH 12/46] Simplify per-group tests --- .../local/per_group/tests/main.nf.test | 16 +- .../local/per_group/tests/main.nf.test.snap | 171 +++--------------- 2 files changed, 39 insertions(+), 148 deletions(-) diff --git a/subworkflows/local/per_group/tests/main.nf.test b/subworkflows/local/per_group/tests/main.nf.test index 30783857..0bec9091 100644 --- a/subworkflows/local/per_group/tests/main.nf.test +++ b/subworkflows/local/per_group/tests/main.nf.test @@ -29,8 +29,12 @@ nextflow_workflow { } then { - assert workflow.success - assert snapshot(workflow.out).match() + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out.versions).match() }, + { assert workflow.out.uns.size() > 0 }, + { assert workflow.out.multiqc_files.size() > 0 } + ) } } @@ -58,8 +62,12 @@ nextflow_workflow { } then { - assert workflow.success - assert snapshot(workflow.out).match() + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out.versions).match() }, + { assert workflow.out.uns.size() > 0 }, + { assert workflow.out.multiqc_files.size() > 0 } + ) } } diff --git a/subworkflows/local/per_group/tests/main.nf.test.snap b/subworkflows/local/per_group/tests/main.nf.test.snap index 606bff27..c73bfa76 100644 --- a/subworkflows/local/per_group/tests/main.nf.test.snap +++ b/subworkflows/local/per_group/tests/main.nf.test.snap @@ -1,28 +1,11 @@ { "Should run without failures - PAGA only": { "content": [ - { - "0": [ - "test_paga.pkl:md5,fbd4ae54e51678480c8c4712a9aad0c8" - ], - "1": [ - "test_paga_mqc.json:md5,71c52f6ea9306b6763abd0496e55fe98" - ], - "2": [ - "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" - ], - "multiqc_files": [ - "test_paga_mqc.json:md5,71c52f6ea9306b6763abd0496e55fe98" - ], - "uns": [ - "test_paga.pkl:md5,fbd4ae54e51678480c8c4712a9aad0c8" - ], - "versions": [ - "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" - ] - } + [ + "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" + ] ], - "timestamp": "2026-03-22T16:22:14.976995704", + "timestamp": "2026-03-24T22:47:31.100084258", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -30,131 +13,31 @@ }, "Should run without failures - full run": { "content": [ - { - "0": [ - "condition:leiden:0_characteristic_genes.pkl:md5,6f2554cd4ad38c9bc79432a39fa0b409", - "condition:leiden:10_characteristic_genes.pkl:md5,b5cddf4993cd232ce31bb203ae95e095", - "condition:leiden:11_characteristic_genes.pkl:md5,245c0b4c0f35fdddae82a4abaf5206a4", - "condition:leiden:1_characteristic_genes.pkl:md5,869fcb61764f6d9e5e0b40ce10d8ba53", - "condition:leiden:2_characteristic_genes.pkl:md5,3f60956bb8fbc03d3c78662eba09d636", - "condition:leiden:3_characteristic_genes.pkl:md5,12e4e59b30050f1e8c5923e75966a4f9", - "condition:leiden:4_characteristic_genes.pkl:md5,9cecb081fd439849da75f437225401a9", - "condition:leiden:5_characteristic_genes.pkl:md5,5a1b5772f54d13c212e1629294682710", - "condition:leiden:6_characteristic_genes.pkl:md5,a77f8e628ef51c30bbe8502c2971738a", - "condition:leiden:7_characteristic_genes.pkl:md5,f43da75d0b5ca1adfb4461b1154cbbf4", - "condition:leiden:8_characteristic_genes.pkl:md5,1cf4e2aa43cd7990916c6d7fc21ff8b0", - "condition:leiden:9_characteristic_genes.pkl:md5,566473d7b82102221f3ff9028c8d8c63", - "leiden:condition:Disease_characteristic_genes.pkl:md5,26d956e25d644b767927a3c49cd01cf1", - "leiden:condition:Healthy_characteristic_genes.pkl:md5,d0fb86ba914f56dccf30be7268e62d8a", - "leiden:condition:Treated_characteristic_genes.pkl:md5,c91689a8a2fa03f7e832143818264984", - "leiden_characteristic_genes.pkl:md5,70d99a12704d8de11935e9c22ca75c5c", - "test_liana.pkl:md5,31f0ac157a5f1763a5304dd68974757a", - "test_paga.pkl:md5,fbd4ae54e51678480c8c4712a9aad0c8" - ], - "1": [ - "condition:leiden:0_characteristic_genes_mqc.json:md5,0d9173af58f05a6a017b7bf62a8ab6a8", - "condition:leiden:10_characteristic_genes_mqc.json:md5,1c42e764ba8a629df84a9f6a7b7cb889", - "condition:leiden:11_characteristic_genes_mqc.json:md5,2c731f81eabd55cea7c6204127e52cca", - "condition:leiden:1_characteristic_genes_mqc.json:md5,a3b5df45edbd4dcc5fb3cf73864f4e76", - "condition:leiden:2_characteristic_genes_mqc.json:md5,1656d5018a65811325f95449b34f302b", - "condition:leiden:3_characteristic_genes_mqc.json:md5,1ce90ec438f14d33bebd26db002544cb", - "condition:leiden:4_characteristic_genes_mqc.json:md5,375733d6a0a018ad6ef0776d5039fb64", - "condition:leiden:5_characteristic_genes_mqc.json:md5,f4c37ef44bc9634d035a3180208c28b1", - "condition:leiden:6_characteristic_genes_mqc.json:md5,29bae0880d7eacb6da9c1ef45d22f9c4", - "condition:leiden:7_characteristic_genes_mqc.json:md5,d1fa8613daecf0aafb769d14c9be39d7", - "condition:leiden:8_characteristic_genes_mqc.json:md5,2602bc68c47188fda2742ad9f222cf4e", - "condition:leiden:9_characteristic_genes_mqc.json:md5,25f88011184cd35edbae303c67fd30d5", - "leiden:condition:Disease_characteristic_genes_mqc.json:md5,54b6743a8852defebc9b9a06d9e230d8", - "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,84f2a400ce922382be222d803b90a1e1", - "leiden:condition:Treated_characteristic_genes_mqc.json:md5,69ce2c401ed338c4288a47e4aeb0359c", - "leiden_characteristic_genes_mqc.json:md5,875d02a88fd8f4f0c0462f4da112d1ed", - "test_paga_mqc.json:md5,71c52f6ea9306b6763abd0496e55fe98" - ], - "2": [ - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd", - "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" - ], - "multiqc_files": [ - "condition:leiden:0_characteristic_genes_mqc.json:md5,0d9173af58f05a6a017b7bf62a8ab6a8", - "condition:leiden:10_characteristic_genes_mqc.json:md5,1c42e764ba8a629df84a9f6a7b7cb889", - "condition:leiden:11_characteristic_genes_mqc.json:md5,2c731f81eabd55cea7c6204127e52cca", - "condition:leiden:1_characteristic_genes_mqc.json:md5,a3b5df45edbd4dcc5fb3cf73864f4e76", - "condition:leiden:2_characteristic_genes_mqc.json:md5,1656d5018a65811325f95449b34f302b", - "condition:leiden:3_characteristic_genes_mqc.json:md5,1ce90ec438f14d33bebd26db002544cb", - "condition:leiden:4_characteristic_genes_mqc.json:md5,375733d6a0a018ad6ef0776d5039fb64", - "condition:leiden:5_characteristic_genes_mqc.json:md5,f4c37ef44bc9634d035a3180208c28b1", - "condition:leiden:6_characteristic_genes_mqc.json:md5,29bae0880d7eacb6da9c1ef45d22f9c4", - "condition:leiden:7_characteristic_genes_mqc.json:md5,d1fa8613daecf0aafb769d14c9be39d7", - "condition:leiden:8_characteristic_genes_mqc.json:md5,2602bc68c47188fda2742ad9f222cf4e", - "condition:leiden:9_characteristic_genes_mqc.json:md5,25f88011184cd35edbae303c67fd30d5", - "leiden:condition:Disease_characteristic_genes_mqc.json:md5,54b6743a8852defebc9b9a06d9e230d8", - "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,84f2a400ce922382be222d803b90a1e1", - "leiden:condition:Treated_characteristic_genes_mqc.json:md5,69ce2c401ed338c4288a47e4aeb0359c", - "leiden_characteristic_genes_mqc.json:md5,875d02a88fd8f4f0c0462f4da112d1ed", - "test_paga_mqc.json:md5,71c52f6ea9306b6763abd0496e55fe98" - ], - "uns": [ - "condition:leiden:0_characteristic_genes.pkl:md5,6f2554cd4ad38c9bc79432a39fa0b409", - "condition:leiden:10_characteristic_genes.pkl:md5,b5cddf4993cd232ce31bb203ae95e095", - "condition:leiden:11_characteristic_genes.pkl:md5,245c0b4c0f35fdddae82a4abaf5206a4", - "condition:leiden:1_characteristic_genes.pkl:md5,869fcb61764f6d9e5e0b40ce10d8ba53", - "condition:leiden:2_characteristic_genes.pkl:md5,3f60956bb8fbc03d3c78662eba09d636", - "condition:leiden:3_characteristic_genes.pkl:md5,12e4e59b30050f1e8c5923e75966a4f9", - "condition:leiden:4_characteristic_genes.pkl:md5,9cecb081fd439849da75f437225401a9", - "condition:leiden:5_characteristic_genes.pkl:md5,5a1b5772f54d13c212e1629294682710", - "condition:leiden:6_characteristic_genes.pkl:md5,a77f8e628ef51c30bbe8502c2971738a", - "condition:leiden:7_characteristic_genes.pkl:md5,f43da75d0b5ca1adfb4461b1154cbbf4", - "condition:leiden:8_characteristic_genes.pkl:md5,1cf4e2aa43cd7990916c6d7fc21ff8b0", - "condition:leiden:9_characteristic_genes.pkl:md5,566473d7b82102221f3ff9028c8d8c63", - "leiden:condition:Disease_characteristic_genes.pkl:md5,26d956e25d644b767927a3c49cd01cf1", - "leiden:condition:Healthy_characteristic_genes.pkl:md5,d0fb86ba914f56dccf30be7268e62d8a", - "leiden:condition:Treated_characteristic_genes.pkl:md5,c91689a8a2fa03f7e832143818264984", - "leiden_characteristic_genes.pkl:md5,70d99a12704d8de11935e9c22ca75c5c", - "test_liana.pkl:md5,31f0ac157a5f1763a5304dd68974757a", - "test_paga.pkl:md5,fbd4ae54e51678480c8c4712a9aad0c8" - ], - "versions": [ - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd", - "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" - ] - } + [ + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", + "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd", + "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" + ] ], - "timestamp": "2026-03-24T19:51:41.129349", + "timestamp": "2026-03-24T22:49:03.481722599", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file From ded90e274c2c16899e968425813189e6f2098060 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Wed, 25 Mar 2026 16:19:45 +0100 Subject: [PATCH 13/46] Update testing strategy --- .cursor/rules/nf-test-assertions.mdc | 92 +++++++++++++++++++ .../local/celda/decontx/tests/main.nf.test | 14 +-- .../celda/decontx/tests/main.nf.test.snap | 75 ++++++++++----- .../celltypes/celltypist/tests/main.nf.test | 6 +- .../celltypist/tests/main.nf.test.snap | 34 +++++-- .../doublet_detection/scds/tests/main.nf.test | 4 +- .../scds/tests/main.nf.test.snap | 22 ++++- .../liana/rankaggregate/tests/main.nf.test | 3 +- .../rankaggregate/tests/main.nf.test.snap | 17 ++-- modules/local/scanpy/bbknn/tests/main.nf.test | 5 +- .../scanpy/bbknn/tests/main.nf.test.snap | 20 ++-- .../local/scanpy/combat/tests/main.nf.test | 2 +- .../scanpy/combat/tests/main.nf.test.snap | 20 ++-- modules/local/scanpy/hvgs/tests/main.nf.test | 9 +- .../local/scanpy/hvgs/tests/main.nf.test.snap | 42 ++++++--- modules/local/scanpy/pca/tests/main.nf.test | 5 +- .../local/scanpy/pca/tests/main.nf.test.snap | 15 ++- .../scanpy/rankgenesgroups/tests/main.nf.test | 8 +- .../rankgenesgroups/tests/main.nf.test.snap | 49 +++++++--- modules/local/scanpy/umap/tests/main.nf.test | 2 +- .../local/scanpy/umap/tests/main.nf.test.snap | 15 ++- .../seurat/integration/tests/main.nf.test | 2 +- .../integration/tests/main.nf.test.snap | 17 ++-- nf-test.config | 2 +- .../ambient_correction/tests/main.nf.test | 26 +++--- .../tests/main.nf.test.snap | 73 ++++++++------- .../celltype_assignment/tests/main.nf.test | 9 +- .../tests/main.nf.test.snap | 10 +- .../tests/main.nf.test | 8 +- .../tests/main.nf.test.snap | 12 ++- .../local/integrate/tests/main.nf.test | 28 +++--- .../local/integrate/tests/main.nf.test.snap | 39 ++++---- .../local/per_group/tests/main.nf.test | 8 +- .../local/per_group/tests/main.nf.test.snap | 12 ++- 34 files changed, 459 insertions(+), 246 deletions(-) create mode 100644 .cursor/rules/nf-test-assertions.mdc diff --git a/.cursor/rules/nf-test-assertions.mdc b/.cursor/rules/nf-test-assertions.mdc new file mode 100644 index 00000000..28974d98 --- /dev/null +++ b/.cursor/rules/nf-test-assertions.mdc @@ -0,0 +1,92 @@ +--- +description: nf-test assertion patterns for scdownstream — how to write platform-independent, targeted tests +globs: "**/*.nf.test" +alwaysApply: false +--- + +# nf-test Assertion Patterns + +## Core principle + +Never snapshot platform-sensitive data (h5ad file hashes, floating-point arrays). Instead, assert structural properties and snapshot only stable values. + +## Assertion hierarchy + +### 1. Stub tests — full snapshot + +Stub tests always use `snapshot(process.out).match()` since all outputs are empty touch files with deterministic MD5s: + +```groovy +test("Should run without failures - stub") { + options '-stub' + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } +} +``` + +### 2. Non-stub tests — single combined snapshot + +For every non-stub test, use a **single** `snapshot(...).match()` call containing: +1. **`path(process.out.versions[0]).yaml`** — reads the actual `versions.yml` content (tool names + versions) as a structured object, more human-readable than MD5 +2. **`anndata(h5ad).yaml`** — captures the complete AnnData structure (n_obs, n_vars, obs/var column names, all field keys) + +Then add direct boolean assertions for the key fields that the test is specifically validating. + +```groovy +then { + def h5ad = process.out.h5ad[0][1] + assertAll( + { assert process.success }, + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, + { assert "X_pca" in anndata(h5ad).obsm } // what this test specifically validates + ) +} +``` + +For **subworkflows** with multiple `versions.yml` files, snapshot the whole versions channel via MD5 (no single file to read): + +```groovy +{ assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } +``` + +### 3. Tests without h5ad output + +When a test has no h5ad output (e.g. only `uns`, `multiqc_files`, `obs`), snapshot versions + stable counts: + +```groovy +{ assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size(), process.out.multiqc_files.size()).match() } +``` + +### 4. One snapshot call per test + +Each test can only have **one** `snapshot(...).match()` call — nf-test keys snapshots by test name. Multiple calls cause duplicate ID errors. Always combine into one: + +```groovy +// ❌ BAD — duplicate snapshot IDs +{ assert snapshot(process.out.versions).match() } +{ assert snapshot(anndata(h5ad).yaml).match() } + +// ✅ GOOD +{ assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } +``` + +### 5. Boolean presence checks + +Fields that either exist or don't are expressed as direct assertions, not snapshots. These document the functional purpose of the test: + +```groovy +{ assert "X_pca" in anndata(h5ad).obsm } +{ assert "connectivities" in anndata(h5ad).obsp } +{ assert "ambient_corrected_decontx" in anndata(h5ad).layers } +``` + +These are **in addition to** the combined snapshot, not instead of it. + +## API references + +- **nft-anndata**: [github.com/nictru/nft-anndata](https://github.com/nictru/nft-anndata) +- **nf-test path API** (yaml, json, md5, linesGzip): [nf-test.com/docs/assertions/files](https://www.nf-test.com/docs/assertions/files/) diff --git a/modules/local/celda/decontx/tests/main.nf.test b/modules/local/celda/decontx/tests/main.nf.test index acceff33..00c9d57f 100644 --- a/modules/local/celda/decontx/tests/main.nf.test +++ b/modules/local/celda/decontx/tests/main.nf.test @@ -32,8 +32,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert anndata(h5ad).obs.rownames.size() > 0 } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } ) } @@ -64,8 +63,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert anndata(h5ad).obs.rownames.size() > 0 } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } ) } @@ -96,8 +94,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert anndata(h5ad).obs.rownames.size() > 0 } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } ) } @@ -160,8 +157,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert anndata(h5ad).obs.rownames.size() > 0 } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } ) } @@ -192,7 +188,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, { assert "ambient_corrected_decontx" in anndata(h5ad).layers } ) } diff --git a/modules/local/celda/decontx/tests/main.nf.test.snap b/modules/local/celda/decontx/tests/main.nf.test.snap index b44c22ec..b1ef2763 100644 --- a/modules/local/celda/decontx/tests/main.nf.test.snap +++ b/modules/local/celda/decontx/tests/main.nf.test.snap @@ -1,23 +1,33 @@ { "Should run without failures without batch column": { "content": [ - [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ] + { + "CELDA_DECONTX": { + "r": "4.5.3", + "anndataR": "1.0.2", + "celda": "1.26.0" + } + }, + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T22:48:36.887205847", + "timestamp": "2026-03-25T16:03:20.607863222", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures without raw - single batch": { "content": [ - [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ] + { + "CELDA_DECONTX": { + "r": "4.5.3", + "anndataR": "1.0.2", + "celda": "1.26.0" + } + }, + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T22:55:17.598632412", + "timestamp": "2026-03-25T16:04:16.789960757", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -25,11 +35,16 @@ }, "Should run without failures with raw": { "content": [ - [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ] + { + "CELDA_DECONTX": { + "r": "4.5.3", + "anndataR": "1.0.2", + "celda": "1.26.0" + } + }, + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T22:58:14.087588206", + "timestamp": "2026-03-25T16:07:08.797021713", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -37,11 +52,16 @@ }, "Should write to a custom output layer": { "content": [ - [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ] + { + "CELDA_DECONTX": { + "r": "4.5.3", + "anndataR": "1.0.2", + "celda": "1.26.0" + } + }, + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - ambient_corrected_decontx\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T22:59:07.21446379", + "timestamp": "2026-03-25T16:08:11.366375453", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -74,19 +94,24 @@ ] } ], - "timestamp": "2026-03-15T21:35:01.416848398", + "timestamp": "2026-03-25T16:08:49.849468757", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures without raw - multi-batch": { "content": [ - [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ] + { + "CELDA_DECONTX": { + "r": "4.5.3", + "anndataR": "1.0.2", + "celda": "1.26.0" + } + }, + "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T22:57:05.67552094", + "timestamp": "2026-03-25T16:05:55.215308418", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -119,10 +144,10 @@ ] } ], - "timestamp": "2026-03-15T21:28:55.554328929", + "timestamp": "2026-03-25T16:06:07.366572356", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/celltypes/celltypist/tests/main.nf.test b/modules/local/celltypes/celltypist/tests/main.nf.test index ad5f2675..104f7d98 100644 --- a/modules/local/celltypes/celltypist/tests/main.nf.test +++ b/modules/local/celltypes/celltypist/tests/main.nf.test @@ -30,8 +30,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert "celltypist:Adult_COVID19_PBMC" in anndata(h5ad).obs.colnames } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).obs.colnames).match() } ) } @@ -60,8 +59,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert "celltypist:Adult_COVID19_PBMC" in anndata(h5ad).obs.colnames } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).obs.colnames).match() } ) } diff --git a/modules/local/celltypes/celltypist/tests/main.nf.test.snap b/modules/local/celltypes/celltypist/tests/main.nf.test.snap index dfa00a19..0ecca1b5 100644 --- a/modules/local/celltypes/celltypist/tests/main.nf.test.snap +++ b/modules/local/celltypes/celltypist/tests/main.nf.test.snap @@ -1,11 +1,21 @@ { "Should run with a symbol column other than index": { "content": [ + { + "CELLTYPES_CELLTYPIST": { + "python": "3.12.8", + "pandas": "2.2.3", + "scanpy": "1.10.4", + "celltypist": "1.6.3" + } + }, [ - "versions.yml:md5,d30822b1ba7cc7a7dc35c749b2353b57" + "celltypist:Adult_COVID19_PBMC", + "celltypist:Adult_COVID19_PBMC:conf", + "sample" ] ], - "timestamp": "2026-03-24T14:04:37.944003887", + "timestamp": "2026-03-25T15:44:41.940273199", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -54,19 +64,29 @@ ] } ], - "timestamp": "2025-06-01T22:03:47.365626813", + "timestamp": "2026-03-25T15:45:36.6350805", "meta": { - "nf-test": "0.9.0", - "nextflow": "25.04.2" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures": { "content": [ + { + "CELLTYPES_CELLTYPIST": { + "python": "3.12.8", + "pandas": "2.2.3", + "scanpy": "1.10.4", + "celltypist": "1.6.3" + } + }, [ - "versions.yml:md5,d30822b1ba7cc7a7dc35c749b2353b57" + "celltypist:Adult_COVID19_PBMC", + "celltypist:Adult_COVID19_PBMC:conf", + "sample" ] ], - "timestamp": "2026-03-24T14:01:47.279173042", + "timestamp": "2026-03-25T15:44:12.70140271", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/doublet_detection/scds/tests/main.nf.test b/modules/local/doublet_detection/scds/tests/main.nf.test index 50f9f24d..f23ab827 100644 --- a/modules/local/doublet_detection/scds/tests/main.nf.test +++ b/modules/local/doublet_detection/scds/tests/main.nf.test @@ -28,9 +28,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert anndata(h5ad).obs.rownames.size() > 0 }, - { assert process.out.predictions.size() > 0 } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).obs.colnames).match() } ) } diff --git a/modules/local/doublet_detection/scds/tests/main.nf.test.snap b/modules/local/doublet_detection/scds/tests/main.nf.test.snap index 0b282a5f..6fceac91 100644 --- a/modules/local/doublet_detection/scds/tests/main.nf.test.snap +++ b/modules/local/doublet_detection/scds/tests/main.nf.test.snap @@ -42,19 +42,31 @@ ] } ], - "timestamp": "2025-05-30T16:52:57.673676107", + "timestamp": "2026-03-25T15:44:42.961362081", "meta": { - "nf-test": "0.9.0", - "nextflow": "25.04.2" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures": { "content": [ + { + "SCDS": { + "R": "4.3.3", + "scds": "1.18.0" + } + }, [ - "versions.yml:md5,c8683fe6c044ab53b908d2fd7c38f8f7" + "bcds_call", + "bcds_score", + "cxds_call", + "cxds_score", + "hybrid_call", + "hybrid_score", + "sample" ] ], - "timestamp": "2026-03-24T22:41:47.177647207", + "timestamp": "2026-03-25T15:44:28.452040006", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test b/modules/local/liana/rankaggregate/tests/main.nf.test index 086497f6..3fb99fba 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test +++ b/modules/local/liana/rankaggregate/tests/main.nf.test @@ -29,8 +29,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert process.out.uns.size() > 0 } + { assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size()).match() } ) } diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test.snap b/modules/local/liana/rankaggregate/tests/main.nf.test.snap index 68ad5bcf..e15a6054 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test.snap +++ b/modules/local/liana/rankaggregate/tests/main.nf.test.snap @@ -32,19 +32,22 @@ ] } ], - "timestamp": "2026-01-10T22:29:55.568090889", + "timestamp": "2026-03-25T15:47:27.037482832", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures": { "content": [ - [ - "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" - ] + { + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" + }, + 1 ], - "timestamp": "2026-03-24T14:03:54.706663316", + "timestamp": "2026-03-25T15:46:58.7462693", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/bbknn/tests/main.nf.test b/modules/local/scanpy/bbknn/tests/main.nf.test index 8c8f392b..d6d5af69 100644 --- a/modules/local/scanpy/bbknn/tests/main.nf.test +++ b/modules/local/scanpy/bbknn/tests/main.nf.test @@ -31,9 +31,10 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, { assert "X_pca" in anndata(h5ad).obsm }, - { assert "connectivities" in anndata(h5ad).obsp } + { assert "connectivities" in anndata(h5ad).obsp }, + { assert "distances" in anndata(h5ad).obsp } ) } diff --git a/modules/local/scanpy/bbknn/tests/main.nf.test.snap b/modules/local/scanpy/bbknn/tests/main.nf.test.snap index 569b3cb8..67dfa61e 100644 --- a/modules/local/scanpy/bbknn/tests/main.nf.test.snap +++ b/modules/local/scanpy/bbknn/tests/main.nf.test.snap @@ -26,19 +26,25 @@ ] } ], - "timestamp": "2025-06-03T07:44:27.274185863", + "timestamp": "2026-03-25T15:44:42.434469309", "meta": { - "nf-test": "0.9.0", - "nextflow": "25.04.2" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures": { "content": [ - [ - "versions.yml:md5,0e8d49948d318a0226fecc9b8d3372bb" - ] + { + "SCANPY_BBKNN": { + "bbknn": "1.6.0", + "pandas": "2.3.3", + "python": "3.12.12", + "scanpy": "1.11.5" + } + }, + "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - PCs\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - neighbors\n - pca\n" ], - "timestamp": "2026-03-24T14:03:12.708585961", + "timestamp": "2026-03-25T15:44:30.059984814", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/combat/tests/main.nf.test b/modules/local/scanpy/combat/tests/main.nf.test index 285cbf12..f89918b7 100644 --- a/modules/local/scanpy/combat/tests/main.nf.test +++ b/modules/local/scanpy/combat/tests/main.nf.test @@ -44,7 +44,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, { assert "X_emb" in anndata(h5ad).obsm }, { assert "X_pca" in anndata(h5ad).obsm } ) diff --git a/modules/local/scanpy/combat/tests/main.nf.test.snap b/modules/local/scanpy/combat/tests/main.nf.test.snap index 3fb13a1c..014679c3 100644 --- a/modules/local/scanpy/combat/tests/main.nf.test.snap +++ b/modules/local/scanpy/combat/tests/main.nf.test.snap @@ -38,19 +38,25 @@ ] } ], - "timestamp": "2025-06-03T07:48:07.847500785", + "timestamp": "2026-03-25T15:44:57.270966951", "meta": { - "nf-test": "0.9.0", - "nextflow": "25.04.2" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures": { "content": [ - [ - "versions.yml:md5,9e3850fe91d236b81ba7557c47344e64" - ] + { + "SCANPY_COMBAT": { + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 38234\nn_vars: 100\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\n - X_emb\n - X_pca\nvarm:\n - PCs\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n - pca\n" ], - "timestamp": "2026-03-24T14:03:10.04909002", + "timestamp": "2026-03-25T15:44:41.450577055", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/hvgs/tests/main.nf.test b/modules/local/scanpy/hvgs/tests/main.nf.test index f02d6277..f0e6038c 100644 --- a/modules/local/scanpy/hvgs/tests/main.nf.test +++ b/modules/local/scanpy/hvgs/tests/main.nf.test @@ -30,8 +30,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert "highly_variable" in anndata(h5ad).var.colnames } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } ) } @@ -60,8 +59,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert "highly_variable" in anndata(h5ad).var.colnames } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } ) } @@ -91,8 +89,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert "highly_variable" in anndata(h5ad).var.colnames } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } ) } diff --git a/modules/local/scanpy/hvgs/tests/main.nf.test.snap b/modules/local/scanpy/hvgs/tests/main.nf.test.snap index b786fafc..f0028d60 100644 --- a/modules/local/scanpy/hvgs/tests/main.nf.test.snap +++ b/modules/local/scanpy/hvgs/tests/main.nf.test.snap @@ -1,11 +1,15 @@ { "Should run with a specified number of HVGs": { "content": [ - [ - "versions.yml:md5,082c751136be043b260385c9829a571d" - ] + { + "SCANPY_HVGS": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 38234\nn_vars: 100\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" ], - "timestamp": "2026-03-24T22:39:20.219700483", + "timestamp": "2026-03-25T15:44:54.05696891", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -13,11 +17,15 @@ }, "Should run without a specified number of HVGs": { "content": [ - [ - "versions.yml:md5,082c751136be043b260385c9829a571d" - ] + { + "SCANPY_HVGS": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 38234\nn_vars: 251\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" ], - "timestamp": "2026-03-24T22:38:55.263409625", + "timestamp": "2026-03-25T15:44:22.933975481", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -56,19 +64,23 @@ ] } ], - "timestamp": "2025-06-03T07:49:56.630416945", + "timestamp": "2026-03-25T15:46:02.052667216", "meta": { - "nf-test": "0.9.0", - "nextflow": "25.04.2" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run with a list of genes excluded from integration": { "content": [ - [ - "versions.yml:md5,082c751136be043b260385c9829a571d" - ] + { + "SCANPY_HVGS": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 38234\nn_vars: 100\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" ], - "timestamp": "2026-03-24T22:39:44.588148179", + "timestamp": "2026-03-25T15:45:40.075913692", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/pca/tests/main.nf.test b/modules/local/scanpy/pca/tests/main.nf.test index 09055b4f..bf7682d0 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test +++ b/modules/local/scanpy/pca/tests/main.nf.test @@ -30,8 +30,9 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert "X_pca" in anndata(process.out.h5ad[0][1]).obsm } + { assert snapshot(path(process.out.versions[0]).yaml, anndata(process.out.h5ad[0][1]).yaml).match() }, + { assert "X_pca" in anndata(process.out.h5ad[0][1]).obsm }, + { assert "X_pca" in anndata(process.out.h5ad[0][1]).uns } ) } diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index 3d6a9777..d2a18897 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -32,7 +32,7 @@ ] } ], - "timestamp": "2026-03-24T18:04:19.704797397", + "timestamp": "2026-03-25T15:44:51.46301442", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -40,11 +40,16 @@ }, "Should run without failures": { "content": [ - [ - "versions.yml:md5,1645b3233d21217bd7e2f01acd4a5892" - ] + { + "SCANPY_PCA": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\nvarp:\nuns:\n - X_pca\n" ], - "timestamp": "2026-03-24T14:01:58.554176502", + "timestamp": "2026-03-25T15:44:23.378021891", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test index 9f16ba94..e72ef015 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test @@ -32,8 +32,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert process.out.uns.size() > 0 } + { assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size(), process.out.plots.size(), process.out.multiqc_files.size()).match() } ) } @@ -95,8 +94,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { assert process.out.uns.size() > 0 } + { assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size(), process.out.plots.size(), process.out.multiqc_files.size()).match() } ) } @@ -127,7 +125,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size(), process.out.plots.size(), process.out.multiqc_files.size()).match() } ) } diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap index 8781132e..0aaf00c7 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap @@ -44,19 +44,26 @@ ] } ], - "timestamp": "2026-01-18T21:23:45.231170376", + "timestamp": "2026-03-25T15:46:33.576251638", "meta": { - "nf-test": "0.9.2", + "nf-test": "0.9.4", "nextflow": "25.10.2" } }, "Should run with label subsetting": { "content": [ - [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ] + { + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + 0, + 0, + 0 ], - "timestamp": "2026-03-24T14:07:28.405239364", + "timestamp": "2026-03-25T15:48:20.422064292", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -64,11 +71,18 @@ }, "Should run without failures": { "content": [ - [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ] + { + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + 1, + 1, + 1 ], - "timestamp": "2026-03-24T14:02:06.261606302", + "timestamp": "2026-03-25T15:46:09.386660869", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -76,11 +90,18 @@ }, "Should run with condition subsetting": { "content": [ - [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ] + { + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + 1, + 1, + 1 ], - "timestamp": "2026-03-24T14:05:35.093554074", + "timestamp": "2026-03-25T15:47:33.511565517", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/umap/tests/main.nf.test b/modules/local/scanpy/umap/tests/main.nf.test index 2ab2e2f1..4b97519b 100644 --- a/modules/local/scanpy/umap/tests/main.nf.test +++ b/modules/local/scanpy/umap/tests/main.nf.test @@ -29,7 +29,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, + { assert snapshot(path(process.out.versions[0]).yaml, anndata(process.out.h5ad[0][1]).yaml).match() }, { assert "X_umap" in anndata(process.out.h5ad[0][1]).obsm } ) } diff --git a/modules/local/scanpy/umap/tests/main.nf.test.snap b/modules/local/scanpy/umap/tests/main.nf.test.snap index 7af04343..ebb9aeb9 100644 --- a/modules/local/scanpy/umap/tests/main.nf.test.snap +++ b/modules/local/scanpy/umap/tests/main.nf.test.snap @@ -32,7 +32,7 @@ ] } ], - "timestamp": "2026-03-22T11:03:38.032169255", + "timestamp": "2026-03-25T15:45:02.008562399", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -40,11 +40,16 @@ }, "Should run without failures": { "content": [ - [ - "versions.yml:md5,f7e77a6f6fe060c4158eb2a86e7c0754" - ] + { + "SCANPY_UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\n - X_umap\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - neighbors\n - umap\n" ], - "timestamp": "2026-03-24T22:36:15.214017742", + "timestamp": "2026-03-25T15:44:47.312318602", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/seurat/integration/tests/main.nf.test b/modules/local/seurat/integration/tests/main.nf.test index 78937e3c..522d4087 100644 --- a/modules/local/seurat/integration/tests/main.nf.test +++ b/modules/local/seurat/integration/tests/main.nf.test @@ -57,7 +57,7 @@ nextflow_process { def h5ad = process.out.h5ad[0][1] assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match() }, + { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, { assert "X_emb" in anndata(h5ad).obsm } ) } diff --git a/modules/local/seurat/integration/tests/main.nf.test.snap b/modules/local/seurat/integration/tests/main.nf.test.snap index 48b7847f..1ea588f1 100644 --- a/modules/local/seurat/integration/tests/main.nf.test.snap +++ b/modules/local/seurat/integration/tests/main.nf.test.snap @@ -26,19 +26,24 @@ ] } ], - "timestamp": "2026-01-25T17:20:38.340547924", + "timestamp": "2026-03-25T15:46:56.458125743", "meta": { - "nf-test": "0.9.2", + "nf-test": "0.9.4", "nextflow": "25.10.2" } }, "Should run without failures": { "content": [ - [ - "versions.yml:md5,c160ec9ef4b681e3c034bd0e0d165987" - ] + { + "SEURAT_INTEGRATION": { + "R": "4.5.3", + "Seurat": "5.4.0", + "anndataR": "1.0.2" + } + }, + "n_obs: 27350\nn_vars: 100\nobs:\n index: _index\n columns:\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - mean_counts\n - means\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - total_counts\nlayers:\nobsm:\n - X_emb\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" ], - "timestamp": "2026-03-23T23:41:50.78672933", + "timestamp": "2026-03-25T15:46:39.138426369", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/nf-test.config b/nf-test.config index 9680c4b6..4c9eeb54 100644 --- a/nf-test.config +++ b/nf-test.config @@ -20,7 +20,7 @@ config { // load the necessary plugins plugins { load "nft-utils@0.0.3" - load "nft-anndata@0.3.5" + load "nft-anndata@0.4.0" load "nft-csv@0.1.0" } } diff --git a/subworkflows/local/ambient_correction/tests/main.nf.test b/subworkflows/local/ambient_correction/tests/main.nf.test index 977a38f8..53b8ab05 100644 --- a/subworkflows/local/ambient_correction/tests/main.nf.test +++ b/subworkflows/local/ambient_correction/tests/main.nf.test @@ -30,7 +30,7 @@ nextflow_workflow { then { assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() } + { assert snapshot(workflow.out.versions, workflow.out.h5ad.size()).match() } ) } @@ -85,7 +85,7 @@ nextflow_workflow { then { assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() } + { assert snapshot(workflow.out.versions, workflow.out.h5ad.size()).match() } ) } @@ -115,7 +115,7 @@ nextflow_workflow { def h5ad = workflow.out.h5ad[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, { assert "ambient_corrected_decontx" in anndata(h5ad).layers } ) } @@ -146,7 +146,7 @@ nextflow_workflow { def h5ad = workflow.out.h5ad[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, { assert "ambient_corrected_decontx" in anndata(h5ad).layers } ) } @@ -177,7 +177,7 @@ nextflow_workflow { def h5ad = workflow.out.h5ad[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, { assert "ambient_corrected_soupx" in anndata(h5ad).layers } ) } @@ -209,7 +209,7 @@ nextflow_workflow { def h5ad = workflow.out.h5ad[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, { assert "ambient_corrected_scar" in anndata(h5ad).layers } ) } @@ -240,7 +240,7 @@ nextflow_workflow { def h5ad = workflow.out.h5ad[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, { assert "ambient_corrected_cellbender" in anndata(h5ad).layers } ) } @@ -271,8 +271,7 @@ nextflow_workflow { def h5ad = workflow.out.h5ad[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, - { assert anndata(h5ad).obs.rownames.size() > 0 } + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } ) } @@ -302,8 +301,7 @@ nextflow_workflow { def h5ad = workflow.out.h5ad[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, - { assert anndata(h5ad).obs.rownames.size() > 0 } + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } ) } @@ -334,8 +332,7 @@ nextflow_workflow { def h5ad = workflow.out.h5ad[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, - { assert anndata(h5ad).obs.rownames.size() > 0 } + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } ) } @@ -365,8 +362,7 @@ nextflow_workflow { def h5ad = workflow.out.h5ad[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, - { assert anndata(h5ad).obs.rownames.size() > 0 } + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } ) } diff --git a/subworkflows/local/ambient_correction/tests/main.nf.test.snap b/subworkflows/local/ambient_correction/tests/main.nf.test.snap index 16a305cb..f1b3b7e0 100644 --- a/subworkflows/local/ambient_correction/tests/main.nf.test.snap +++ b/subworkflows/local/ambient_correction/tests/main.nf.test.snap @@ -3,9 +3,10 @@ "content": [ [ - ] + ], + 1 ], - "timestamp": "2026-03-23T22:53:42.301253063", + "timestamp": "2026-03-25T15:46:16.218237575", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -15,34 +16,37 @@ "content": [ [ "versions.yml:md5,f9ea95abb10a7769d50d14fcaa5734ee" - ] + ], + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T23:01:44.949156977", + "timestamp": "2026-03-25T15:55:43.229893039", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" } }, - "Should run with 'cellbender' ambient correction to 'X'": { + "Should run with 'decontx' ambient correction and no batch column": { "content": [ [ - "versions.yml:md5,1d70371b0f0ca5e50f7ba70335f8946f", - "versions.yml:md5,e6e98e83cbc9a2924c66e901445bbc4f" - ] + "versions.yml:md5,f9ea95abb10a7769d50d14fcaa5734ee" + ], + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_decontx\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T23:06:59.552055248", + "timestamp": "2026-03-25T15:49:17.935387052", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" } }, - "Should run with 'decontx' ambient correction and no batch column": { + "Should run with 'cellbender' ambient correction to 'X'": { "content": [ [ - "versions.yml:md5,f9ea95abb10a7769d50d14fcaa5734ee" - ] + "versions.yml:md5,1d70371b0f0ca5e50f7ba70335f8946f", + "versions.yml:md5,e6e98e83cbc9a2924c66e901445bbc4f" + ], + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T22:55:48.212429509", + "timestamp": "2026-03-25T16:00:43.278473562", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -52,9 +56,10 @@ "content": [ [ "versions.yml:md5,f9ea95abb10a7769d50d14fcaa5734ee" - ] + ], + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_decontx\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T22:54:53.07199224", + "timestamp": "2026-03-25T15:48:15.985988809", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -64,33 +69,36 @@ "content": [ [ "versions.yml:md5,0266faf0b40a7b86ec9f2b1948f8c7aa" - ] + ], + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T23:02:27.711519463", + "timestamp": "2026-03-25T15:56:25.809642699", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" } }, - "Should run with 'scar' ambient correction": { + "Should not do anything if ambient correction is disabled in meta": { "content": [ [ - "versions.yml:md5,2717cb5f250a65aec0a76a456f7028ba" - ] + + ], + 1 ], - "timestamp": "2026-03-23T22:57:58.607959901", + "timestamp": "2026-03-25T15:46:46.64367644", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" } }, - "Should not do anything if ambient correction is disabled in meta": { + "Should run with 'scar' ambient correction": { "content": [ [ - - ] + "versions.yml:md5,2717cb5f250a65aec0a76a456f7028ba" + ], + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - _scvi_batch\n - _scvi_labels\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_scar\nobsm:\nvarm:\n - ambient_profile\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T22:54:01.532131592", + "timestamp": "2026-03-25T15:51:33.678378475", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -101,9 +109,10 @@ [ "versions.yml:md5,1d70371b0f0ca5e50f7ba70335f8946f", "versions.yml:md5,e6e98e83cbc9a2924c66e901445bbc4f" - ] + ], + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_cellbender\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T23:00:54.238589778", + "timestamp": "2026-03-25T15:54:46.503094206", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -113,9 +122,10 @@ "content": [ [ "versions.yml:md5,0266faf0b40a7b86ec9f2b1948f8c7aa" - ] + ], + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_soupx\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T22:56:39.961201724", + "timestamp": "2026-03-25T15:50:04.360822128", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -125,9 +135,10 @@ "content": [ [ "versions.yml:md5,2717cb5f250a65aec0a76a456f7028ba" - ] + ], + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - _scvi_batch\n - _scvi_labels\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\n - ambient_profile\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-23T23:03:37.590823873", + "timestamp": "2026-03-25T15:57:30.785675292", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/celltype_assignment/tests/main.nf.test b/subworkflows/local/celltype_assignment/tests/main.nf.test index faa362f5..8e29d55e 100644 --- a/subworkflows/local/celltype_assignment/tests/main.nf.test +++ b/subworkflows/local/celltype_assignment/tests/main.nf.test @@ -29,11 +29,10 @@ nextflow_workflow { } then { - assert workflow.success - assert snapshot( - workflow.out.versions, - workflow.out.obs.size() - ).match() + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out.versions, workflow.out.obs.size()).match() } + ) } } diff --git a/subworkflows/local/celltype_assignment/tests/main.nf.test.snap b/subworkflows/local/celltype_assignment/tests/main.nf.test.snap index c38ded62..1766ea61 100644 --- a/subworkflows/local/celltype_assignment/tests/main.nf.test.snap +++ b/subworkflows/local/celltype_assignment/tests/main.nf.test.snap @@ -9,10 +9,10 @@ ], 2 ], - "timestamp": "2026-03-17T21:51:53.626655883", + "timestamp": "2026-03-25T15:50:21.38171952", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - stub": { @@ -60,10 +60,10 @@ ] } ], - "timestamp": "2025-07-17T10:31:35.176849323", + "timestamp": "2026-03-25T15:50:38.187327089", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/subworkflows/local/differential_expression/tests/main.nf.test b/subworkflows/local/differential_expression/tests/main.nf.test index 34036c4d..f94b4ff0 100644 --- a/subworkflows/local/differential_expression/tests/main.nf.test +++ b/subworkflows/local/differential_expression/tests/main.nf.test @@ -26,9 +26,7 @@ nextflow_workflow { then { assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, - { assert workflow.out.uns.size() > 0 }, - { assert workflow.out.multiqc_files.size() > 0 } + { assert snapshot(workflow.out.versions, workflow.out.uns.size(), workflow.out.multiqc_files.size()).match() } ) } @@ -53,9 +51,7 @@ nextflow_workflow { then { assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, - { assert workflow.out.uns.size() > 0 }, - { assert workflow.out.multiqc_files.size() > 0 } + { assert snapshot(workflow.out.versions, workflow.out.uns.size(), workflow.out.multiqc_files.size()).match() } ) } diff --git a/subworkflows/local/differential_expression/tests/main.nf.test.snap b/subworkflows/local/differential_expression/tests/main.nf.test.snap index 38990e5f..95ceb00a 100644 --- a/subworkflows/local/differential_expression/tests/main.nf.test.snap +++ b/subworkflows/local/differential_expression/tests/main.nf.test.snap @@ -18,9 +18,11 @@ "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" - ] + ], + 16, + 16 ], - "timestamp": "2026-03-24T14:01:59.841477057", + "timestamp": "2026-03-25T15:46:36.932593016", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -39,9 +41,11 @@ "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" - ] + ], + 10, + 10 ], - "timestamp": "2026-03-24T14:05:22.799299909", + "timestamp": "2026-03-25T15:48:05.790450423", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/integrate/tests/main.nf.test b/subworkflows/local/integrate/tests/main.nf.test index 1cd7063a..8512108d 100644 --- a/subworkflows/local/integrate/tests/main.nf.test +++ b/subworkflows/local/integrate/tests/main.nf.test @@ -67,11 +67,12 @@ nextflow_workflow { } then { - assert workflow.success - assert snapshot( - workflow.out.versions - ).match() - assert "X_emb" in anndata(workflow.out.integrations[0][1]).obsm + def h5ad = workflow.out.integrations[0][1] + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, + { assert "X_emb" in anndata(h5ad).obsm } + ) } } @@ -136,10 +137,12 @@ nextflow_workflow { } then { + def h5ad = workflow.out.integrations[0][1] assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, - { assert "connectivities" in anndata(workflow.out.integrations[0][1]).obsp } + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, + { assert "connectivities" in anndata(h5ad).obsp }, + { assert "distances" in anndata(h5ad).obsp } ) } @@ -205,11 +208,12 @@ nextflow_workflow { } then { - assert workflow.success - assert snapshot( - workflow.out.versions - ).match() - assert "X_emb" in anndata(workflow.out.integrations[0][1]).obsm + def h5ad = workflow.out.integrations[0][1] + assertAll( + { assert workflow.success }, + { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, + { assert "X_emb" in anndata(h5ad).obsm } + ) } } diff --git a/subworkflows/local/integrate/tests/main.nf.test.snap b/subworkflows/local/integrate/tests/main.nf.test.snap index b04b39bd..9c7afde4 100644 --- a/subworkflows/local/integrate/tests/main.nf.test.snap +++ b/subworkflows/local/integrate/tests/main.nf.test.snap @@ -48,10 +48,10 @@ ] } ], - "timestamp": "2026-01-16T22:34:13.677132566", + "timestamp": "2026-03-25T15:45:28.18158151", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures - bbknn - stub": { @@ -103,10 +103,10 @@ ] } ], - "timestamp": "2026-01-16T22:35:18.22501323", + "timestamp": "2026-03-25T15:47:40.215608271", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures - combat": { @@ -115,9 +115,10 @@ "versions.yml:md5,20020d8c9cf585aaa75dd5a14aa5d3ae", "versions.yml:md5,a6c1e0a77e0d31423a9d77edba85127d", "versions.yml:md5,d28b65c4c18c54e1abc34040b584b823" - ] + ], + "n_obs: 12940\nn_vars: 2077\nobs:\n index: _index\n columns:\n - batch\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - mean_counts\n - means\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\n - X_emb\n - X_pca\nvarm:\n - PCs\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n - pca\n" ], - "timestamp": "2026-03-22T14:55:07.151113899", + "timestamp": "2026-03-25T15:50:43.745384682", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -168,10 +169,10 @@ ] } ], - "timestamp": "2026-01-16T22:37:23.996766665", + "timestamp": "2026-03-25T15:50:57.251962289", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures - combat - stub": { @@ -223,10 +224,10 @@ ] } ], - "timestamp": "2026-01-16T22:36:29.062441577", + "timestamp": "2026-03-25T15:49:26.334091777", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures - harmony": { @@ -235,9 +236,10 @@ "versions.yml:md5,20020d8c9cf585aaa75dd5a14aa5d3ae", "versions.yml:md5,d28b65c4c18c54e1abc34040b584b823", "versions.yml:md5,f838f281f13db0dd578a991df1d8b57c" - ] + ], + "n_obs: 12940\nn_vars: 2077\nobs:\n index: _index\n columns:\n - batch\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - mean_counts\n - means\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\n - X_emb\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" ], - "timestamp": "2026-03-22T13:40:54.235838286", + "timestamp": "2026-03-25T15:47:16.180497374", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -249,9 +251,10 @@ "versions.yml:md5,20020d8c9cf585aaa75dd5a14aa5d3ae", "versions.yml:md5,ccf730637c4c61a84ac4a002bf9832e0", "versions.yml:md5,d28b65c4c18c54e1abc34040b584b823" - ] + ], + "n_obs: 12940\nn_vars: 2077\nobs:\n index: _index\n columns:\n - batch\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - mean_counts\n - means\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\n - X_pca\nvarm:\n - PCs\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - hvg\n - log1p\n - neighbors\n - pca\n" ], - "timestamp": "2026-03-24T14:11:21.672408157", + "timestamp": "2026-03-25T15:49:08.65878862", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/per_group/tests/main.nf.test b/subworkflows/local/per_group/tests/main.nf.test index 0bec9091..581fb2cc 100644 --- a/subworkflows/local/per_group/tests/main.nf.test +++ b/subworkflows/local/per_group/tests/main.nf.test @@ -31,9 +31,7 @@ nextflow_workflow { then { assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, - { assert workflow.out.uns.size() > 0 }, - { assert workflow.out.multiqc_files.size() > 0 } + { assert snapshot(workflow.out.versions, workflow.out.uns.size(), workflow.out.multiqc_files.size()).match() } ) } @@ -64,9 +62,7 @@ nextflow_workflow { then { assertAll( { assert workflow.success }, - { assert snapshot(workflow.out.versions).match() }, - { assert workflow.out.uns.size() > 0 }, - { assert workflow.out.multiqc_files.size() > 0 } + { assert snapshot(workflow.out.versions, workflow.out.uns.size(), workflow.out.multiqc_files.size()).match() } ) } diff --git a/subworkflows/local/per_group/tests/main.nf.test.snap b/subworkflows/local/per_group/tests/main.nf.test.snap index c73bfa76..38d30e33 100644 --- a/subworkflows/local/per_group/tests/main.nf.test.snap +++ b/subworkflows/local/per_group/tests/main.nf.test.snap @@ -3,9 +3,11 @@ "content": [ [ "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" - ] + ], + 1, + 1 ], - "timestamp": "2026-03-24T22:47:31.100084258", + "timestamp": "2026-03-25T16:10:11.679192446", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -32,9 +34,11 @@ "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd", "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" - ] + ], + 18, + 17 ], - "timestamp": "2026-03-24T22:49:03.481722599", + "timestamp": "2026-03-25T16:12:47.770237258", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" From fd036629f72eabf59de630cfcc834175b88656bf Mon Sep 17 00:00:00 2001 From: Erik Fasterius Date: Thu, 26 Mar 2026 14:15:30 +0100 Subject: [PATCH 14/46] Update snapshots --- .../local/scanpy/pca/tests/main.nf.test.snap | 10 +- tests/default.nf.test.snap | 2 +- tests/main_pipeline_build.nf.test.snap | 255 +++++++- tests/main_pipeline_qc.nf.test.snap | 5 +- ...in_pipeline_reference_mapping.nf.test.snap | 5 +- tests/main_pipeline_sub.nf.test.snap | 551 +++++++++++++++++- 6 files changed, 808 insertions(+), 20 deletions(-) diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index d2a18897..0ac9343b 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,7 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ], "h5ad": [ [ @@ -28,14 +28,14 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ] } ], - "timestamp": "2026-03-25T15:44:51.46301442", + "timestamp": "2026-03-26T08:18:17.901045", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } }, "Should run without failures": { diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 8b57796f..cd8e83ad 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -279,7 +279,7 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T21:34:53.411968", + "timestamp": "2026-03-26T10:09:39.311745", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index 8a627281..e017f735 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -2,6 +2,18 @@ "Should process data from scratch": { "content": [ { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, "ADATA_READRDS": { "anndata": "0.11.1", "anndata2ri": "1.3.2", @@ -9,6 +21,20 @@ "pandas": "2.2.3", "seurat": "5.1.0" }, + "ADATA_TORDS": { + "anndataR": "1.0.2" + }, + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + }, + "CELDA_DECONTX": { + "r": "4.5.3", + "anndataR": "1.0.2", + "celda": "1.26.0" + }, "CELLDEX_FETCHREFERENCE": { "R": "R version 4.4.1 (2024-06-14)", "celldex": "1.16.0", @@ -16,36 +42,257 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, + "CELLTYPES_CELLTYPIST": { + "python": "3.12.8", + "pandas": "2.2.3", + "scanpy": "1.10.4", + "celltypist": "1.6.3" + }, + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + }, + "COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + }, + "DOUBLET_REMOVAL": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "pandas": "2.3.3", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, + "ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "FINALIZE_QC_ANNDATAS": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "GET_DEDOUBLETED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "GET_THRESHOLDED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "QC_FILTERED": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, "QC_RAW": { "matplotlib": "3.10.8", "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_BBKNN": { + "bbknn": "1.6.0", + "pandas": "2.3.3", + "python": "3.12.12", + "scanpy": "1.11.5" + }, + "SCANPY_CELLCYCLE": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_COMBAT": { + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_HARMONY": { + "harmonypy": "0.2.0", + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_HVGS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + }, + "SCVITOOLS_SCVI": { + "scvi": "1.3.3" + }, + "SEURAT_INTEGRATION": { + "R": "4.5.3", + "Seurat": "5.4.0", + "anndataR": "1.0.2" + }, + "UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "UPSET_GENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - } + }, + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" }, [ + "celltypes", + "celltypes/singler", + "celltypes/singler/SRR28679756_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679756_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679756_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679756_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679756_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_predictions.csv", + "celltypes/singler/SRR28679757_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679757_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679757_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679757_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679757_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_predictions.csv", + "celltypes/singler/SRR28679758_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679758_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679758_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679758_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679758_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_predictions.csv", + "cluster_dimred", + "cluster_dimred/bbknn", + "cluster_dimred/bbknn/entropy", + "cluster_dimred/bbknn/entropy/bbknn-global-0.5_entropy.png", + "cluster_dimred/bbknn/entropy/bbknn-global-1.0_entropy.png", + "cluster_dimred/bbknn/leiden", + "cluster_dimred/bbknn/leiden/bbknn-global-0.5_leiden.png", + "cluster_dimred/bbknn/leiden/bbknn-global-1.0_leiden.png", + "cluster_dimred/bbknn/umap", + "cluster_dimred/combat", + "cluster_dimred/combat/entropy", + "cluster_dimred/combat/entropy/combat-global-0.5_entropy.png", + "cluster_dimred/combat/entropy/combat-global-1.0_entropy.png", + "cluster_dimred/combat/leiden", + "cluster_dimred/combat/leiden/combat-global-0.5_leiden.png", + "cluster_dimred/combat/leiden/combat-global-1.0_leiden.png", + "cluster_dimred/combat/umap", + "cluster_dimred/harmony", + "cluster_dimred/harmony/entropy", + "cluster_dimred/harmony/entropy/harmony-global-0.5_entropy.png", + "cluster_dimred/harmony/entropy/harmony-global-1.0_entropy.png", + "cluster_dimred/harmony/leiden", + "cluster_dimred/harmony/leiden/harmony-global-0.5_leiden.png", + "cluster_dimred/harmony/leiden/harmony-global-1.0_leiden.png", + "cluster_dimred/harmony/umap", + "cluster_dimred/scvi", + "cluster_dimred/scvi/entropy", + "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", + "cluster_dimred/scvi/leiden", + "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", + "cluster_dimred/scvi/umap", + "cluster_dimred/seurat", + "cluster_dimred/seurat/entropy", + "cluster_dimred/seurat/entropy/seurat-global-0.5_entropy.png", + "cluster_dimred/seurat/entropy/seurat-global-1.0_entropy.png", + "cluster_dimred/seurat/leiden", + "cluster_dimred/seurat/leiden/seurat-global-0.5_leiden.png", + "cluster_dimred/seurat/leiden/seurat-global-1.0_leiden.png", + "cluster_dimred/seurat/umap", + "combine", + "combine/integrate", + "combine/integrate/scvi", + "combine/integrate/scvi/scvi_model", + "combine/integrate/scvi/scvi_model/model.pt", + "combine/merge", + "combine/merge/upset_genes.png", + "finalized", + "finalized/merged.h5ad", + "finalized/merged.rds", + "finalized/merged_metadata.csv", + "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_sizes.txt", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_report.html", + "per_group", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "quality_control", + "quality_control/qc_filtered", + "quality_control/qc_filtered/SRR28679756_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_filtered/SRR28679757_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_filtered/SRR28679758_preprocessed_total_counts_vs_n_genes_by_counts.png", "quality_control/qc_raw", "quality_control/qc_raw/SRR28679756_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw/SRR28679757_raw_total_counts_vs_n_genes_by_counts.png" + "quality_control/qc_raw/SRR28679757_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_raw/SRR28679758_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/sizes", + "quality_control/sizes/sizes.tsv" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T20:51:24.530168", + "timestamp": "2026-03-26T10:28:17.194294", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index 7b80c99f..038dcc7f 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -149,7 +149,6 @@ "multiqc/multiqc_data/multiqc_sizes.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_plots", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", @@ -169,10 +168,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T18:39:32.940515591", + "timestamp": "2026-03-26T09:29:39.661493", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" } } -} +} \ No newline at end of file diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 652c195f..7798a6e1 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -191,7 +191,6 @@ "multiqc/multiqc_data/multiqc_sizes.txt", "multiqc/multiqc_data/multiqc_software_versions.txt", "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_plots", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -208,10 +207,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T18:43:18.421083649", + "timestamp": "2026-03-26T09:36:00.222856", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" } } -} +} \ No newline at end of file diff --git a/tests/main_pipeline_sub.nf.test.snap b/tests/main_pipeline_sub.nf.test.snap index 3be6adf1..81a98518 100644 --- a/tests/main_pipeline_sub.nf.test.snap +++ b/tests/main_pipeline_sub.nf.test.snap @@ -1,12 +1,38 @@ { "Should be able to perform subclustering": { "content": [ - 9, + 289, { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, "ADATA_SPLITEMBEDDINGS": { "anndata": "0.12.10", "python": "3.13.12" }, + "ADATA_TORDS": { + "anndataR": "1.0.2" + }, + "ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + }, "SCANPY_RANKGENESGROUPS": { "pandas": "2.3.3", "python": "3.13.12", @@ -16,25 +42,542 @@ "anndata": "0.12.10", "python": "3.13.12" }, + "UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - } + }, + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" }, [ "adata", "adata/combat.h5ad", "adata/harmony.h5ad", "adata/scvi.h5ad", + "cluster_dimred", + "cluster_dimred/combat", + "cluster_dimred/combat/entropy", + "cluster_dimred/combat/entropy/combat-SRR28679756-0.5_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679756-1.0_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679757-0.5_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679757-1.0_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679758-0.5_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679758-1.0_entropy.png", + "cluster_dimred/combat/leiden", + "cluster_dimred/combat/leiden/combat-SRR28679756-0.5_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679756-1.0_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679757-0.5_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679757-1.0_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679758-0.5_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679758-1.0_leiden.png", + "cluster_dimred/combat/umap", + "cluster_dimred/harmony", + "cluster_dimred/harmony/entropy", + "cluster_dimred/harmony/entropy/harmony-SRR28679756-0.5_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679756-1.0_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679757-0.5_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679757-1.0_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679758-0.5_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679758-1.0_entropy.png", + "cluster_dimred/harmony/leiden", + "cluster_dimred/harmony/leiden/harmony-SRR28679756-0.5_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679756-1.0_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679757-0.5_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679757-1.0_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679758-0.5_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679758-1.0_leiden.png", + "cluster_dimred/harmony/umap", + "cluster_dimred/scvi", + "cluster_dimred/scvi/entropy", + "cluster_dimred/scvi/entropy/scvi-SRR28679756-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679756-1.0_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679757-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679757-1.0_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679758-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679758-1.0_entropy.png", + "cluster_dimred/scvi/leiden", + "cluster_dimred/scvi/leiden/scvi-SRR28679756-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679756-1.0_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679757-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679757-1.0_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679758-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679758-1.0_leiden.png", + "cluster_dimred/scvi/umap", + "finalized", + "finalized/base.h5ad", + "finalized/base.rds", + "finalized/base_metadata.csv", + "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", "per_group", + "per_group/combat-SRR28679756", + "per_group/combat-SRR28679756-0.5", + "per_group/combat-SRR28679756-0.5/paga", + "per_group/combat-SRR28679756-0.5/paga/combat-SRR28679756-0.5_paga.png", + "per_group/combat-SRR28679756-0.5_leiden", + "per_group/combat-SRR28679756-0.5_leiden/characteristic_genes", + "per_group/combat-SRR28679756-0.5_leiden/characteristic_genes/combat-SRR28679756-0.5_leiden_characteristic_genes.png", + "per_group/combat-SRR28679756-1.0", + "per_group/combat-SRR28679756-1.0/paga", + "per_group/combat-SRR28679756-1.0/paga/combat-SRR28679756-1.0_paga.png", + "per_group/combat-SRR28679756-1.0_leiden", + "per_group/combat-SRR28679756-1.0_leiden/characteristic_genes", + "per_group/combat-SRR28679756-1.0_leiden/characteristic_genes/combat-SRR28679756-1.0_leiden_characteristic_genes.png", + "per_group/combat-SRR28679756/paga", + "per_group/combat-SRR28679757", + "per_group/combat-SRR28679757-0.5", + "per_group/combat-SRR28679757-0.5/paga", + "per_group/combat-SRR28679757-0.5/paga/combat-SRR28679757-0.5_paga.png", + "per_group/combat-SRR28679757-0.5_leiden", + "per_group/combat-SRR28679757-0.5_leiden/characteristic_genes", + "per_group/combat-SRR28679757-0.5_leiden/characteristic_genes/combat-SRR28679757-0.5_leiden_characteristic_genes.png", + "per_group/combat-SRR28679757-1.0", + "per_group/combat-SRR28679757-1.0/paga", + "per_group/combat-SRR28679757-1.0/paga/combat-SRR28679757-1.0_paga.png", + "per_group/combat-SRR28679757-1.0_leiden", + "per_group/combat-SRR28679757-1.0_leiden/characteristic_genes", + "per_group/combat-SRR28679757-1.0_leiden/characteristic_genes/combat-SRR28679757-1.0_leiden_characteristic_genes.png", + "per_group/combat-SRR28679757/paga", + "per_group/combat-SRR28679758", + "per_group/combat-SRR28679758-0.5", + "per_group/combat-SRR28679758-0.5/paga", + "per_group/combat-SRR28679758-0.5/paga/combat-SRR28679758-0.5_paga.png", + "per_group/combat-SRR28679758-0.5_leiden", + "per_group/combat-SRR28679758-0.5_leiden/characteristic_genes", + "per_group/combat-SRR28679758-0.5_leiden/characteristic_genes/combat-SRR28679758-0.5_leiden_characteristic_genes.png", + "per_group/combat-SRR28679758-1.0", + "per_group/combat-SRR28679758-1.0/paga", + "per_group/combat-SRR28679758-1.0/paga/combat-SRR28679758-1.0_paga.png", + "per_group/combat-SRR28679758-1.0_leiden", + "per_group/combat-SRR28679758-1.0_leiden/characteristic_genes", + "per_group/combat-SRR28679758-1.0_leiden/characteristic_genes/combat-SRR28679758-1.0_leiden_characteristic_genes.png", + "per_group/combat-SRR28679758/paga", + "per_group/condition:combat-SRR28679756-0.5_leiden:0", + "per_group/condition:combat-SRR28679756-0.5_leiden:0/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:1", + "per_group/condition:combat-SRR28679756-0.5_leiden:1/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:2", + "per_group/condition:combat-SRR28679756-0.5_leiden:2/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:3", + "per_group/condition:combat-SRR28679756-0.5_leiden:3/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:4", + "per_group/condition:combat-SRR28679756-0.5_leiden:4/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:5", + "per_group/condition:combat-SRR28679756-0.5_leiden:5/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:6", + "per_group/condition:combat-SRR28679756-0.5_leiden:6/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:7", + "per_group/condition:combat-SRR28679756-0.5_leiden:7/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:8", + "per_group/condition:combat-SRR28679756-0.5_leiden:8/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:0", + "per_group/condition:combat-SRR28679756-1.0_leiden:0/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:1", + "per_group/condition:combat-SRR28679756-1.0_leiden:1/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:10", + "per_group/condition:combat-SRR28679756-1.0_leiden:10/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:11", + "per_group/condition:combat-SRR28679756-1.0_leiden:11/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:12", + "per_group/condition:combat-SRR28679756-1.0_leiden:12/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:13", + "per_group/condition:combat-SRR28679756-1.0_leiden:13/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:14", + "per_group/condition:combat-SRR28679756-1.0_leiden:14/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:2", + "per_group/condition:combat-SRR28679756-1.0_leiden:2/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:3", + "per_group/condition:combat-SRR28679756-1.0_leiden:3/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:4", + "per_group/condition:combat-SRR28679756-1.0_leiden:4/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:5", + "per_group/condition:combat-SRR28679756-1.0_leiden:5/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:6", + "per_group/condition:combat-SRR28679756-1.0_leiden:6/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:7", + "per_group/condition:combat-SRR28679756-1.0_leiden:7/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:8", + "per_group/condition:combat-SRR28679756-1.0_leiden:8/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:9", + "per_group/condition:combat-SRR28679756-1.0_leiden:9/characteristic_genes", + "per_group/condition:combat-SRR28679757-0.5_leiden:0", + "per_group/condition:combat-SRR28679757-0.5_leiden:0/characteristic_genes", + "per_group/condition:combat-SRR28679757-0.5_leiden:1", + "per_group/condition:combat-SRR28679757-0.5_leiden:1/characteristic_genes", + "per_group/condition:combat-SRR28679757-0.5_leiden:2", + "per_group/condition:combat-SRR28679757-0.5_leiden:2/characteristic_genes", + "per_group/condition:combat-SRR28679757-0.5_leiden:3", + "per_group/condition:combat-SRR28679757-0.5_leiden:3/characteristic_genes", + "per_group/condition:combat-SRR28679757-0.5_leiden:4", + "per_group/condition:combat-SRR28679757-0.5_leiden:4/characteristic_genes", + "per_group/condition:combat-SRR28679757-0.5_leiden:5", + "per_group/condition:combat-SRR28679757-0.5_leiden:5/characteristic_genes", + "per_group/condition:combat-SRR28679757-0.5_leiden:6", + "per_group/condition:combat-SRR28679757-0.5_leiden:6/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:0", + "per_group/condition:combat-SRR28679757-1.0_leiden:0/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:1", + "per_group/condition:combat-SRR28679757-1.0_leiden:1/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:10", + "per_group/condition:combat-SRR28679757-1.0_leiden:10/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:11", + "per_group/condition:combat-SRR28679757-1.0_leiden:11/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:12", + "per_group/condition:combat-SRR28679757-1.0_leiden:12/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:2", + "per_group/condition:combat-SRR28679757-1.0_leiden:2/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:3", + "per_group/condition:combat-SRR28679757-1.0_leiden:3/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:4", + "per_group/condition:combat-SRR28679757-1.0_leiden:4/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:5", + "per_group/condition:combat-SRR28679757-1.0_leiden:5/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:6", + "per_group/condition:combat-SRR28679757-1.0_leiden:6/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:7", + "per_group/condition:combat-SRR28679757-1.0_leiden:7/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:8", + "per_group/condition:combat-SRR28679757-1.0_leiden:8/characteristic_genes", + "per_group/condition:combat-SRR28679757-1.0_leiden:9", + "per_group/condition:combat-SRR28679757-1.0_leiden:9/characteristic_genes", + "per_group/condition:combat-SRR28679758-0.5_leiden:0", + "per_group/condition:combat-SRR28679758-0.5_leiden:0/characteristic_genes", + "per_group/condition:combat-SRR28679758-0.5_leiden:1", + "per_group/condition:combat-SRR28679758-0.5_leiden:1/characteristic_genes", + "per_group/condition:combat-SRR28679758-0.5_leiden:2", + "per_group/condition:combat-SRR28679758-0.5_leiden:2/characteristic_genes", + "per_group/condition:combat-SRR28679758-0.5_leiden:3", + "per_group/condition:combat-SRR28679758-0.5_leiden:3/characteristic_genes", + "per_group/condition:combat-SRR28679758-0.5_leiden:4", + "per_group/condition:combat-SRR28679758-0.5_leiden:4/characteristic_genes", + "per_group/condition:combat-SRR28679758-0.5_leiden:5", + "per_group/condition:combat-SRR28679758-0.5_leiden:5/characteristic_genes", + "per_group/condition:combat-SRR28679758-0.5_leiden:6", + "per_group/condition:combat-SRR28679758-0.5_leiden:6/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:0", + "per_group/condition:combat-SRR28679758-1.0_leiden:0/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:1", + "per_group/condition:combat-SRR28679758-1.0_leiden:1/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:10", + "per_group/condition:combat-SRR28679758-1.0_leiden:10/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:11", + "per_group/condition:combat-SRR28679758-1.0_leiden:11/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:12", + "per_group/condition:combat-SRR28679758-1.0_leiden:12/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:13", + "per_group/condition:combat-SRR28679758-1.0_leiden:13/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:2", + "per_group/condition:combat-SRR28679758-1.0_leiden:2/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:3", + "per_group/condition:combat-SRR28679758-1.0_leiden:3/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:4", + "per_group/condition:combat-SRR28679758-1.0_leiden:4/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:5", + "per_group/condition:combat-SRR28679758-1.0_leiden:5/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:6", + "per_group/condition:combat-SRR28679758-1.0_leiden:6/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:7", + "per_group/condition:combat-SRR28679758-1.0_leiden:7/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:8", + "per_group/condition:combat-SRR28679758-1.0_leiden:8/characteristic_genes", + "per_group/condition:combat-SRR28679758-1.0_leiden:9", + "per_group/condition:combat-SRR28679758-1.0_leiden:9/characteristic_genes", + "per_group/condition:harmony-SRR28679756-0.5_leiden:0", + "per_group/condition:harmony-SRR28679756-0.5_leiden:0/characteristic_genes", + "per_group/condition:harmony-SRR28679756-0.5_leiden:1", + "per_group/condition:harmony-SRR28679756-0.5_leiden:1/characteristic_genes", + "per_group/condition:harmony-SRR28679756-0.5_leiden:2", + "per_group/condition:harmony-SRR28679756-0.5_leiden:2/characteristic_genes", + "per_group/condition:harmony-SRR28679756-0.5_leiden:3", + "per_group/condition:harmony-SRR28679756-0.5_leiden:3/characteristic_genes", + "per_group/condition:harmony-SRR28679756-0.5_leiden:4", + "per_group/condition:harmony-SRR28679756-0.5_leiden:4/characteristic_genes", + "per_group/condition:harmony-SRR28679756-1.0_leiden:0", + "per_group/condition:harmony-SRR28679756-1.0_leiden:0/characteristic_genes", + "per_group/condition:harmony-SRR28679756-1.0_leiden:1", + "per_group/condition:harmony-SRR28679756-1.0_leiden:1/characteristic_genes", + "per_group/condition:harmony-SRR28679756-1.0_leiden:2", + "per_group/condition:harmony-SRR28679756-1.0_leiden:2/characteristic_genes", + "per_group/condition:harmony-SRR28679756-1.0_leiden:3", + "per_group/condition:harmony-SRR28679756-1.0_leiden:3/characteristic_genes", + "per_group/condition:harmony-SRR28679756-1.0_leiden:4", + "per_group/condition:harmony-SRR28679756-1.0_leiden:4/characteristic_genes", + "per_group/condition:harmony-SRR28679756-1.0_leiden:5", + "per_group/condition:harmony-SRR28679756-1.0_leiden:5/characteristic_genes", + "per_group/condition:harmony-SRR28679756-1.0_leiden:6", + "per_group/condition:harmony-SRR28679756-1.0_leiden:6/characteristic_genes", + "per_group/condition:harmony-SRR28679756-1.0_leiden:7", + "per_group/condition:harmony-SRR28679756-1.0_leiden:7/characteristic_genes", + "per_group/condition:harmony-SRR28679756-1.0_leiden:8", + "per_group/condition:harmony-SRR28679756-1.0_leiden:8/characteristic_genes", + "per_group/condition:harmony-SRR28679757-0.5_leiden:0", + "per_group/condition:harmony-SRR28679757-0.5_leiden:0/characteristic_genes", + "per_group/condition:harmony-SRR28679757-0.5_leiden:1", + "per_group/condition:harmony-SRR28679757-0.5_leiden:1/characteristic_genes", + "per_group/condition:harmony-SRR28679757-0.5_leiden:2", + "per_group/condition:harmony-SRR28679757-0.5_leiden:2/characteristic_genes", + "per_group/condition:harmony-SRR28679757-0.5_leiden:3", + "per_group/condition:harmony-SRR28679757-0.5_leiden:3/characteristic_genes", + "per_group/condition:harmony-SRR28679757-0.5_leiden:4", + "per_group/condition:harmony-SRR28679757-0.5_leiden:4/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:0", + "per_group/condition:harmony-SRR28679757-1.0_leiden:0/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:1", + "per_group/condition:harmony-SRR28679757-1.0_leiden:1/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:2", + "per_group/condition:harmony-SRR28679757-1.0_leiden:2/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:3", + "per_group/condition:harmony-SRR28679757-1.0_leiden:3/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:4", + "per_group/condition:harmony-SRR28679757-1.0_leiden:4/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:5", + "per_group/condition:harmony-SRR28679757-1.0_leiden:5/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:6", + "per_group/condition:harmony-SRR28679757-1.0_leiden:6/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:7", + "per_group/condition:harmony-SRR28679757-1.0_leiden:7/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:8", + "per_group/condition:harmony-SRR28679757-1.0_leiden:8/characteristic_genes", + "per_group/condition:harmony-SRR28679757-1.0_leiden:9", + "per_group/condition:harmony-SRR28679757-1.0_leiden:9/characteristic_genes", + "per_group/condition:harmony-SRR28679758-0.5_leiden:0", + "per_group/condition:harmony-SRR28679758-0.5_leiden:0/characteristic_genes", + "per_group/condition:harmony-SRR28679758-0.5_leiden:1", + "per_group/condition:harmony-SRR28679758-0.5_leiden:1/characteristic_genes", + "per_group/condition:harmony-SRR28679758-0.5_leiden:2", + "per_group/condition:harmony-SRR28679758-0.5_leiden:2/characteristic_genes", + "per_group/condition:harmony-SRR28679758-0.5_leiden:3", + "per_group/condition:harmony-SRR28679758-0.5_leiden:3/characteristic_genes", + "per_group/condition:harmony-SRR28679758-0.5_leiden:4", + "per_group/condition:harmony-SRR28679758-0.5_leiden:4/characteristic_genes", + "per_group/condition:harmony-SRR28679758-1.0_leiden:0", + "per_group/condition:harmony-SRR28679758-1.0_leiden:0/characteristic_genes", + "per_group/condition:harmony-SRR28679758-1.0_leiden:1", + "per_group/condition:harmony-SRR28679758-1.0_leiden:1/characteristic_genes", + "per_group/condition:harmony-SRR28679758-1.0_leiden:2", + "per_group/condition:harmony-SRR28679758-1.0_leiden:2/characteristic_genes", + "per_group/condition:harmony-SRR28679758-1.0_leiden:3", + "per_group/condition:harmony-SRR28679758-1.0_leiden:3/characteristic_genes", + "per_group/condition:harmony-SRR28679758-1.0_leiden:4", + "per_group/condition:harmony-SRR28679758-1.0_leiden:4/characteristic_genes", + "per_group/condition:harmony-SRR28679758-1.0_leiden:5", + "per_group/condition:harmony-SRR28679758-1.0_leiden:5/characteristic_genes", + "per_group/condition:harmony-SRR28679758-1.0_leiden:6", + "per_group/condition:harmony-SRR28679758-1.0_leiden:6/characteristic_genes", + "per_group/condition:harmony-SRR28679758-1.0_leiden:7", + "per_group/condition:harmony-SRR28679758-1.0_leiden:7/characteristic_genes", + "per_group/condition:harmony-SRR28679758-1.0_leiden:8", + "per_group/condition:harmony-SRR28679758-1.0_leiden:8/characteristic_genes", "per_group/condition:sample:SRR28679756", "per_group/condition:sample:SRR28679756/characteristic_genes", "per_group/condition:sample:SRR28679757", "per_group/condition:sample:SRR28679757/characteristic_genes", "per_group/condition:sample:SRR28679758", "per_group/condition:sample:SRR28679758/characteristic_genes", + "per_group/condition:scvi-SRR28679756-0.5_leiden:0", + "per_group/condition:scvi-SRR28679756-0.5_leiden:0/characteristic_genes", + "per_group/condition:scvi-SRR28679756-0.5_leiden:1", + "per_group/condition:scvi-SRR28679756-0.5_leiden:1/characteristic_genes", + "per_group/condition:scvi-SRR28679756-0.5_leiden:2", + "per_group/condition:scvi-SRR28679756-0.5_leiden:2/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:0", + "per_group/condition:scvi-SRR28679756-1.0_leiden:0/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:1", + "per_group/condition:scvi-SRR28679756-1.0_leiden:1/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:10", + "per_group/condition:scvi-SRR28679756-1.0_leiden:10/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:11", + "per_group/condition:scvi-SRR28679756-1.0_leiden:11/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:12", + "per_group/condition:scvi-SRR28679756-1.0_leiden:12/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:2", + "per_group/condition:scvi-SRR28679756-1.0_leiden:2/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:3", + "per_group/condition:scvi-SRR28679756-1.0_leiden:3/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:4", + "per_group/condition:scvi-SRR28679756-1.0_leiden:4/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:5", + "per_group/condition:scvi-SRR28679756-1.0_leiden:5/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:6", + "per_group/condition:scvi-SRR28679756-1.0_leiden:6/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:7", + "per_group/condition:scvi-SRR28679756-1.0_leiden:7/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:8", + "per_group/condition:scvi-SRR28679756-1.0_leiden:8/characteristic_genes", + "per_group/condition:scvi-SRR28679756-1.0_leiden:9", + "per_group/condition:scvi-SRR28679756-1.0_leiden:9/characteristic_genes", + "per_group/condition:scvi-SRR28679757-0.5_leiden:0", + "per_group/condition:scvi-SRR28679757-0.5_leiden:0/characteristic_genes", + "per_group/condition:scvi-SRR28679757-0.5_leiden:1", + "per_group/condition:scvi-SRR28679757-0.5_leiden:1/characteristic_genes", + "per_group/condition:scvi-SRR28679757-0.5_leiden:2", + "per_group/condition:scvi-SRR28679757-0.5_leiden:2/characteristic_genes", + "per_group/condition:scvi-SRR28679757-0.5_leiden:3", + "per_group/condition:scvi-SRR28679757-0.5_leiden:3/characteristic_genes", + "per_group/condition:scvi-SRR28679757-0.5_leiden:4", + "per_group/condition:scvi-SRR28679757-0.5_leiden:4/characteristic_genes", + "per_group/condition:scvi-SRR28679757-0.5_leiden:5", + "per_group/condition:scvi-SRR28679757-0.5_leiden:5/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:0", + "per_group/condition:scvi-SRR28679757-1.0_leiden:0/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:1", + "per_group/condition:scvi-SRR28679757-1.0_leiden:1/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:10", + "per_group/condition:scvi-SRR28679757-1.0_leiden:10/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:11", + "per_group/condition:scvi-SRR28679757-1.0_leiden:11/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:12", + "per_group/condition:scvi-SRR28679757-1.0_leiden:12/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:2", + "per_group/condition:scvi-SRR28679757-1.0_leiden:2/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:3", + "per_group/condition:scvi-SRR28679757-1.0_leiden:3/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:4", + "per_group/condition:scvi-SRR28679757-1.0_leiden:4/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:5", + "per_group/condition:scvi-SRR28679757-1.0_leiden:5/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:6", + "per_group/condition:scvi-SRR28679757-1.0_leiden:6/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:7", + "per_group/condition:scvi-SRR28679757-1.0_leiden:7/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:8", + "per_group/condition:scvi-SRR28679757-1.0_leiden:8/characteristic_genes", + "per_group/condition:scvi-SRR28679757-1.0_leiden:9", + "per_group/condition:scvi-SRR28679757-1.0_leiden:9/characteristic_genes", + "per_group/condition:scvi-SRR28679758-0.5_leiden:0", + "per_group/condition:scvi-SRR28679758-0.5_leiden:0/characteristic_genes", + "per_group/condition:scvi-SRR28679758-0.5_leiden:1", + "per_group/condition:scvi-SRR28679758-0.5_leiden:1/characteristic_genes", + "per_group/condition:scvi-SRR28679758-0.5_leiden:2", + "per_group/condition:scvi-SRR28679758-0.5_leiden:2/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:0", + "per_group/condition:scvi-SRR28679758-1.0_leiden:0/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:1", + "per_group/condition:scvi-SRR28679758-1.0_leiden:1/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:10", + "per_group/condition:scvi-SRR28679758-1.0_leiden:10/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:11", + "per_group/condition:scvi-SRR28679758-1.0_leiden:11/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:12", + "per_group/condition:scvi-SRR28679758-1.0_leiden:12/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:13", + "per_group/condition:scvi-SRR28679758-1.0_leiden:13/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:2", + "per_group/condition:scvi-SRR28679758-1.0_leiden:2/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:3", + "per_group/condition:scvi-SRR28679758-1.0_leiden:3/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:4", + "per_group/condition:scvi-SRR28679758-1.0_leiden:4/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:5", + "per_group/condition:scvi-SRR28679758-1.0_leiden:5/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:6", + "per_group/condition:scvi-SRR28679758-1.0_leiden:6/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:7", + "per_group/condition:scvi-SRR28679758-1.0_leiden:7/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:8", + "per_group/condition:scvi-SRR28679758-1.0_leiden:8/characteristic_genes", + "per_group/condition:scvi-SRR28679758-1.0_leiden:9", + "per_group/condition:scvi-SRR28679758-1.0_leiden:9/characteristic_genes", + "per_group/harmony-SRR28679756", + "per_group/harmony-SRR28679756-0.5", + "per_group/harmony-SRR28679756-0.5/paga", + "per_group/harmony-SRR28679756-0.5/paga/harmony-SRR28679756-0.5_paga.png", + "per_group/harmony-SRR28679756-0.5_leiden", + "per_group/harmony-SRR28679756-0.5_leiden/characteristic_genes", + "per_group/harmony-SRR28679756-0.5_leiden/characteristic_genes/harmony-SRR28679756-0.5_leiden_characteristic_genes.png", + "per_group/harmony-SRR28679756-1.0", + "per_group/harmony-SRR28679756-1.0/paga", + "per_group/harmony-SRR28679756-1.0/paga/harmony-SRR28679756-1.0_paga.png", + "per_group/harmony-SRR28679756-1.0_leiden", + "per_group/harmony-SRR28679756-1.0_leiden/characteristic_genes", + "per_group/harmony-SRR28679756-1.0_leiden/characteristic_genes/harmony-SRR28679756-1.0_leiden_characteristic_genes.png", + "per_group/harmony-SRR28679756/paga", + "per_group/harmony-SRR28679757", + "per_group/harmony-SRR28679757-0.5", + "per_group/harmony-SRR28679757-0.5/paga", + "per_group/harmony-SRR28679757-0.5/paga/harmony-SRR28679757-0.5_paga.png", + "per_group/harmony-SRR28679757-0.5_leiden", + "per_group/harmony-SRR28679757-0.5_leiden/characteristic_genes", + "per_group/harmony-SRR28679757-0.5_leiden/characteristic_genes/harmony-SRR28679757-0.5_leiden_characteristic_genes.png", + "per_group/harmony-SRR28679757-1.0", + "per_group/harmony-SRR28679757-1.0/paga", + "per_group/harmony-SRR28679757-1.0/paga/harmony-SRR28679757-1.0_paga.png", + "per_group/harmony-SRR28679757-1.0_leiden", + "per_group/harmony-SRR28679757-1.0_leiden/characteristic_genes", + "per_group/harmony-SRR28679757-1.0_leiden/characteristic_genes/harmony-SRR28679757-1.0_leiden_characteristic_genes.png", + "per_group/harmony-SRR28679757/paga", + "per_group/harmony-SRR28679758", + "per_group/harmony-SRR28679758-0.5", + "per_group/harmony-SRR28679758-0.5/paga", + "per_group/harmony-SRR28679758-0.5/paga/harmony-SRR28679758-0.5_paga.png", + "per_group/harmony-SRR28679758-0.5_leiden", + "per_group/harmony-SRR28679758-0.5_leiden/characteristic_genes", + "per_group/harmony-SRR28679758-0.5_leiden/characteristic_genes/harmony-SRR28679758-0.5_leiden_characteristic_genes.png", + "per_group/harmony-SRR28679758-1.0", + "per_group/harmony-SRR28679758-1.0/paga", + "per_group/harmony-SRR28679758-1.0/paga/harmony-SRR28679758-1.0_paga.png", + "per_group/harmony-SRR28679758-1.0_leiden", + "per_group/harmony-SRR28679758-1.0_leiden/characteristic_genes", + "per_group/harmony-SRR28679758-1.0_leiden/characteristic_genes/harmony-SRR28679758-1.0_leiden_characteristic_genes.png", + "per_group/harmony-SRR28679758/paga", "per_group/sample", "per_group/sample/characteristic_genes", "per_group/sample/characteristic_genes/sample_characteristic_genes.png", + "per_group/scvi-SRR28679756", + "per_group/scvi-SRR28679756-0.5", + "per_group/scvi-SRR28679756-0.5/paga", + "per_group/scvi-SRR28679756-0.5/paga/scvi-SRR28679756-0.5_paga.png", + "per_group/scvi-SRR28679756-0.5_leiden", + "per_group/scvi-SRR28679756-0.5_leiden/characteristic_genes", + "per_group/scvi-SRR28679756-0.5_leiden/characteristic_genes/scvi-SRR28679756-0.5_leiden_characteristic_genes.png", + "per_group/scvi-SRR28679756-1.0", + "per_group/scvi-SRR28679756-1.0/paga", + "per_group/scvi-SRR28679756-1.0/paga/scvi-SRR28679756-1.0_paga.png", + "per_group/scvi-SRR28679756-1.0_leiden", + "per_group/scvi-SRR28679756-1.0_leiden/characteristic_genes", + "per_group/scvi-SRR28679756-1.0_leiden/characteristic_genes/scvi-SRR28679756-1.0_leiden_characteristic_genes.png", + "per_group/scvi-SRR28679756/paga", + "per_group/scvi-SRR28679757", + "per_group/scvi-SRR28679757-0.5", + "per_group/scvi-SRR28679757-0.5/paga", + "per_group/scvi-SRR28679757-0.5/paga/scvi-SRR28679757-0.5_paga.png", + "per_group/scvi-SRR28679757-0.5_leiden", + "per_group/scvi-SRR28679757-0.5_leiden/characteristic_genes", + "per_group/scvi-SRR28679757-0.5_leiden/characteristic_genes/scvi-SRR28679757-0.5_leiden_characteristic_genes.png", + "per_group/scvi-SRR28679757-1.0", + "per_group/scvi-SRR28679757-1.0/paga", + "per_group/scvi-SRR28679757-1.0/paga/scvi-SRR28679757-1.0_paga.png", + "per_group/scvi-SRR28679757-1.0_leiden", + "per_group/scvi-SRR28679757-1.0_leiden/characteristic_genes", + "per_group/scvi-SRR28679757-1.0_leiden/characteristic_genes/scvi-SRR28679757-1.0_leiden_characteristic_genes.png", + "per_group/scvi-SRR28679757/paga", + "per_group/scvi-SRR28679758", + "per_group/scvi-SRR28679758-0.5", + "per_group/scvi-SRR28679758-0.5/paga", + "per_group/scvi-SRR28679758-0.5/paga/scvi-SRR28679758-0.5_paga.png", + "per_group/scvi-SRR28679758-0.5_leiden", + "per_group/scvi-SRR28679758-0.5_leiden/characteristic_genes", + "per_group/scvi-SRR28679758-0.5_leiden/characteristic_genes/scvi-SRR28679758-0.5_leiden_characteristic_genes.png", + "per_group/scvi-SRR28679758-1.0", + "per_group/scvi-SRR28679758-1.0/paga", + "per_group/scvi-SRR28679758-1.0/paga/scvi-SRR28679758-1.0_paga.png", + "per_group/scvi-SRR28679758-1.0_leiden", + "per_group/scvi-SRR28679758-1.0_leiden/characteristic_genes", + "per_group/scvi-SRR28679758-1.0_leiden/characteristic_genes/scvi-SRR28679758-1.0_leiden_characteristic_genes.png", + "per_group/scvi-SRR28679758/paga", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "splitcol", @@ -43,10 +586,10 @@ "splitcol/SRR28679758.h5ad" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T20:38:21.169674", + "timestamp": "2026-03-26T09:48:21.621218", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" From dc7e2b15f46189f933355f4cc4f84b321b65e7f3 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sat, 28 Mar 2026 17:57:52 +0100 Subject: [PATCH 15/46] Improve module tests --- .cursor/rules/nf-test-assertions.mdc | 183 +++++-- docs/reproducibility.md | 151 ++++++ .../local/adata/entropy/tests/main.nf.test | 14 +- modules/local/adata/extend/tests/main.nf.test | 82 ++- .../adata/mergeembeddings/tests/main.nf.test | 58 +- modules/local/adata/mygene/tests/main.nf.test | 14 +- .../adata/prepcellxgene/tests/main.nf.test | 14 +- .../local/adata/readcsv/tests/main.nf.test | 14 +- .../local/adata/readrds/tests/main.nf.test | 28 +- .../local/adata/setindex/tests/main.nf.test | 21 +- .../adata/splitembeddings/tests/main.nf.test | 14 +- modules/local/adata/tords/tests/main.nf.test | 14 +- modules/local/adata/unify/tests/main.nf.test | 499 +++++++----------- .../local/adata/upsetgenes/tests/main.nf.test | 14 +- .../local/celda/decontx/tests/main.nf.test | 85 +-- .../celda/decontx/tests/main.nf.test.snap | 104 +++- .../celltypes/celltypist/tests/main.nf.test | 41 +- .../custom/collectsizes/tests/main.nf.test | 14 +- .../doublet_detection/scds/tests/main.nf.test | 22 +- .../hugounifier/apply/tests/main.nf.test | 23 +- .../local/hugounifier/get/tests/main.nf.test | 34 +- .../liana/rankaggregate/tests/main.nf.test | 19 +- .../rankaggregate/tests/main.nf.test.snap | 34 +- modules/local/scanpy/bbknn/tests/main.nf.test | 26 +- .../local/scanpy/cellcycle/tests/main.nf.test | 14 +- .../local/scanpy/combat/tests/main.nf.test | 24 +- .../local/scanpy/filter/tests/main.nf.test | 59 ++- .../local/scanpy/harmony/tests/main.nf.test | 24 +- .../scanpy/harmony/tests/main.nf.test.snap | 5 +- modules/local/scanpy/hvgs/tests/main.nf.test | 43 +- .../local/scanpy/leiden/tests/main.nf.test | 22 +- .../local/scanpy/neighbors/tests/main.nf.test | 29 +- .../scanpy/neighbors/tests/main.nf.test.snap | 20 +- modules/local/scanpy/paga/tests/main.nf.test | 20 +- .../local/scanpy/paga/tests/main.nf.test.snap | 11 +- modules/local/scanpy/pca/tests/main.nf.test | 23 +- .../local/scanpy/plotqc/tests/main.nf.test | 14 +- .../scanpy/rankgenesgroups/tests/main.nf.test | 39 +- .../rankgenesgroups/tests/main.nf.test.snap | 103 +++- .../local/scanpy/readh5/tests/main.nf.test | 14 +- .../local/scanpy/sample/tests/main.nf.test | 21 +- modules/local/scanpy/umap/tests/main.nf.test | 22 +- .../scimilarity/annotate/tests/main.nf.test | 7 +- .../scimilarity/embed/tests/main.nf.test | 7 +- .../scimilarity/pseudobulk/tests/main.nf.test | 39 +- .../pseudobulk/tests/main.nf.test.snap | 24 +- .../local/scvitools/scanvi/tests/main.nf.test | 20 +- .../scvitools/scanvi/tests/main.nf.test.snap | 11 +- .../local/scvitools/scvi/tests/main.nf.test | 20 +- .../scvitools/scvi/tests/main.nf.test.snap | 13 +- .../seurat/integration/tests/main.nf.test | 22 +- modules/local/soupx/tests/main.nf.test | 53 +- modules/local/soupx/tests/main.nf.test.snap | 57 +- 53 files changed, 1412 insertions(+), 890 deletions(-) create mode 100644 docs/reproducibility.md diff --git a/.cursor/rules/nf-test-assertions.mdc b/.cursor/rules/nf-test-assertions.mdc index 28974d98..bfba7968 100644 --- a/.cursor/rules/nf-test-assertions.mdc +++ b/.cursor/rules/nf-test-assertions.mdc @@ -10,81 +10,190 @@ alwaysApply: false Never snapshot platform-sensitive data (h5ad file hashes, floating-point arrays). Instead, assert structural properties and snapshot only stable values. -## Assertion hierarchy +## Assertion order — sequential, no `assertAll` -### 1. Stub tests — full snapshot +All `then {}` blocks use **plain sequential `assert` statements** in this fixed order: -Stub tests always use `snapshot(process.out).match()` since all outputs are empty touch files with deterministic MD5s: +1. `def adata = anndata(...)` — parsed once, reused below (only when h5ad is used 2+ times) +2. `assert process.success` / `assert workflow.success` — bare, runs first so failures show the real error +3. **Field checks** — specific, readable assertions that fire before the snapshot (e.g. `assert "X_pca" in adata.obsm`) +4. `assert snapshot(...).match()` — comprehensive regression net, runs last + +**Why this order**: if the snapshot passes, the field checks would always pass too. But if a field is missing, the specific field assertion fires first with a clear message ("false" on `"X_pca" in adata.obsm`), instead of a verbose YAML diff. + +**Never use `assertAll`** — it groups all failures into one report which makes CI output harder to read when a process fails. + +## Stub tests + +Stub tests always use the simple pattern: ```groovy test("Should run without failures - stub") { options '-stub' then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } ``` -### 2. Non-stub tests — single combined snapshot +## Non-stub tests — full example + +```groovy +then { + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert "X_pca" in adata.obsm // field checks BEFORE snapshot + assert "X_pca" in adata.uns + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() // snapshot LAST — comprehensive regression +} +``` -For every non-stub test, use a **single** `snapshot(...).match()` call containing: -1. **`path(process.out.versions[0]).yaml`** — reads the actual `versions.yml` content (tool names + versions) as a structured object, more human-readable than MD5 -2. **`anndata(h5ad).yaml`** — captures the complete AnnData structure (n_obs, n_vars, obs/var column names, all field keys) +## `def adata` variable -Then add direct boolean assertions for the key fields that the test is specifically validating. +When `anndata(path)` would appear more than once in the same `then {}` block, always extract it: ```groovy -then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, - { assert "X_pca" in anndata(h5ad).obsm } // what this test specifically validates - ) +def adata = anndata(process.out.h5ad[0][1]) +// then use adata.obsm, adata.yaml, with(adata) { ... } +``` + +For subworkflow tests, the path comes from `workflow.out`: + +```groovy +def adata = anndata(workflow.out.h5ad[0][1]) +// or workflow.out.integrations[0][1] etc. +``` + +## `with(adata)` for grouped checks + +When asserting multiple properties of the same AnnData object, use `with(adata)`: + +```groovy +def adata = anndata(process.out.h5ad[0][1]) +assert process.success +with(adata) { + assert "batch" in obs.colnames + assert "label" in obs.colnames + assert !("counts" in layers) } +assert snapshot(process.out, path(process.out.versions[0]).yaml, adata.yaml).match() ``` -For **subworkflows** with multiple `versions.yml` files, snapshot the whole versions channel via MD5 (no single file to read): +## What to include in `snapshot()` + +### Module tests + +| Situation | What to snapshot | +|-----------|-----------------| +| Deterministic output (pure data transform) | `process.out, path(process.out.versions[0]).yaml, adata.yaml` | +| Non-deterministic output (ML, randomness) | `path(process.out.versions[0]).yaml, adata.yaml` (drop `process.out`) | +| No h5ad output | `process.out, path(process.out.versions[0]).yaml` | + +### Subworkflow tests + +For subworkflows with multiple `versions.yml` files, snapshot the whole versions channel: ```groovy -{ assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } +assert snapshot(workflow.out.versions, adata.yaml).match() ``` -### 3. Tests without h5ad output +Or for deterministic subworkflows: -When a test has no h5ad output (e.g. only `uns`, `multiqc_files`, `obs`), snapshot versions + stable counts: +```groovy +assert snapshot(workflow.out, workflow.out.versions, adata.yaml).match() +``` + +## Deterministic vs non-deterministic modules + +**Deterministic** (always include `process.out` in snapshot): +`adata/entropy`, `adata/extend`, `adata/merge`, `adata/mergeembeddings`, `adata/mygene`, `adata/prepcellxgene`, `adata/readcsv`, `adata/readrds`, `adata/setindex`, `adata/splitcol`, `adata/splitembeddings`, `adata/tords`, `adata/unify`, `adata/upsetgenes`, `celda/decontx`, `celltypes/celltypist`, `celltypes/singler`, `custom/collectsizes`, `doublet_detection/doublet_removal`, `doublet_detection/scds`, `hugounifier/apply`, `hugounifier/get`, `liana/rankaggregate`, `scanpy/bbknn`, `scanpy/cellcycle`, `scanpy/combat`, `scanpy/filter`, `scanpy/harmony`, `scanpy/hvgs`, `scanpy/leiden`, `scanpy/neighbors`, `scanpy/paga`, `scanpy/plotqc`, `scanpy/rankgenesgroups`, `scanpy/readh5`, `scanpy/sample`, `scanpy/umap`, `soupx` + +**Non-deterministic** (omit `process.out` from snapshot, use structural/size checks): +`scanpy/pca` (floating-point variance), `scvitools/scvi`, `scvitools/scanvi`, `seurat/integration`, `scimilarity/embed`, `scimilarity/annotate`, `scimilarity/pseudobulk` + +## Common mistake — do NOT drop `process.out` from deterministic modules + +For deterministic modules, the original tests used exact MD5 hashes. That means `process.out` **must** remain in the snapshot. Only omit it for ML/randomness-based modules. ```groovy -{ assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size(), process.out.multiqc_files.size()).match() } +// ❌ WRONG — drops the full output snapshot for a deterministic module +assert snapshot(path(process.out.versions[0]).yaml, adata.yaml).match() + +// ✅ CORRECT for deterministic modules +assert snapshot(process.out, path(process.out.versions[0]).yaml, adata.yaml).match() ``` -### 4. One snapshot call per test +## Versions channel + +- **Module tests**: `path(process.out.versions[0]).yaml` — reads the single `versions.yml` as YAML +- **Subworkflow tests**: `workflow.out.versions` — snapshot the whole versions channel (multiple files, use MD5) + +The versions channel should never include `meta`. In module tests, `process.out.versions[0]` is a plain path (no tuple). -Each test can only have **one** `snapshot(...).match()` call — nf-test keys snapshots by test name. Multiple calls cause duplicate ID errors. Always combine into one: +## Spread multi-argument snapshots over multiple lines ```groovy -// ❌ BAD — duplicate snapshot IDs -{ assert snapshot(process.out.versions).match() } -{ assert snapshot(anndata(h5ad).yaml).match() } +// ✅ readable +assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml +).match() + +// ❌ hard to read +assert snapshot(process.out, path(process.out.versions[0]).yaml, adata.yaml).match() +``` + +## One snapshot call per test + +Each test can only have **one** `snapshot(...).match()` call — nf-test keys snapshots by test name. Always combine into one call. -// ✅ GOOD -{ assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } +## Explicit field checks — always assert created fields + +Every test should explicitly assert the key outputs/fields that the module creates: +- `assert "X_pca" in adata.obsm` for new embeddings +- `assert "leiden" in adata.obs.colnames` for new obs columns +- `assert "rank_genes_groups" in adata.uns` for uns keys +- `assert "ambient_corrected" in adata.layers` for new layers + +## Known nft-anndata limitation: `uns` is top-level keys only + +`adata.uns` (and `uns` inside a `with(adata)` block) is a `Set` — it exposes only the **top-level key names**, not the nested values. This means: + +```groovy +assert "paga" in adata.uns // ✅ works — checks key presence +assert "connectivities" in adata.uns["paga"] // ❌ fails — cannot navigate into nested uns ``` -### 5. Boolean presence checks +Sub-key structure of nested `uns` entries (e.g. `uns["paga"]["connectivities"]`) is only verifiable via `adata.yaml` in the snapshot. + +## Known nft-anndata limitation: passthrough h5ad files -Fields that either exist or don't are expressed as direct assertions, not snapshots. These document the functional purpose of the test: +`nft-anndata 0.4.0` tries to open `.h5ad` files when they appear as **staged** files in snapshot serialisation. It does **NOT** open files that were never staged into the Nextflow work directory (e.g., direct references to `/nf-core/test-datasets/...`). + +**What triggers HDF5 read** (fails on unstaged files): +- `workflow.out.h5ad.toList()` inside a snapshot +- Explicit `anndata(path).yaml` where path is a passthrough/unstaged file + +**What does NOT trigger HDF5 read** (safe for passthrough): +- `snapshot(workflow.out)` — passthrough paths are serialised as raw strings +- `workflow.out.h5ad.size()` — only counts elements + +For **load_h5ad** (which passes through files from test datasets), use: ```groovy -{ assert "X_pca" in anndata(h5ad).obsm } -{ assert "connectivities" in anndata(h5ad).obsp } -{ assert "ambient_corrected_decontx" in anndata(h5ad).layers } +then { + assert workflow.success + assert snapshot(workflow.out).match() +} ``` -These are **in addition to** the combined snapshot, not instead of it. +Do NOT use `anndata(workflow.out.h5ad[0][1]).yaml` for passthrough files. ## API references diff --git a/docs/reproducibility.md b/docs/reproducibility.md new file mode 100644 index 00000000..6b2d25b6 --- /dev/null +++ b/docs/reproducibility.md @@ -0,0 +1,151 @@ +# Module Reproducibility + +Classification of all local modules and subworkflows by output reproducibility. + +## Legend + +| Level | Meaning | +| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Fully deterministic** | Same input always produces bit-identical output across all platforms and library versions. | +| **Seeded / quasi-deterministic** | A fixed random seed is set, but floating-point results (PCA coordinates, embeddings) can differ slightly across hardware, LAPACK/BLAS backends, or library versions. File hashes may differ between platforms even when logic is correct. | +| **Non-deterministic** | Output varies between runs or platforms even with identical inputs — either due to unseeded stochasticity, iterative ML training, or live external API/download calls. | + +The **Dev branch implied** column is derived mechanically from whether the `dev` branch tests use `snapshot(process.out)` / `snapshot(workflow.out)` (which captures file MD5 hashes). A module that snapshots `process.out` was treated as deterministic on dev; one that omits it was not. Differences between the two columns indicate cases where the current branch and dev disagreed. + +--- + +## Modules + +### `adata/` + +| Module | Description | Reproducibility | Dev branch implied | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `adata/entropy` | Computes per-group normalised Shannon entropy of a categorical obs column and optionally plots it. | Fully deterministic | Deterministic | +| `adata/extend` | Extends an AnnData object with additional obs/var/obsm/obsp/uns/layers data from pickle or CSV files. | Fully deterministic | Deterministic | +| `adata/merge` | Concatenates multiple AnnData objects into inner (gene intersection) and outer (union) merged datasets. | Fully deterministic | Deterministic | +| `adata/mergeembeddings` | Merges embeddings from a newly integrated AnnData back into the combined base+integrated AnnData by cell-index alignment. | Fully deterministic | Deterministic | +| `adata/mygene` | Translates gene identifiers (Ensembl/Entrez/symbol) to HGNC symbols via the MyGene.info REST API. | **Non-deterministic** — live external API call; results depend on database state at query time. | ⚠️ Deterministic — dev snapshots `process.out` despite the live API | +| `adata/prepcellxgene` | Prepares an AnnData object for CellxGene by renaming embedding keys and converting counts to log-normalised float32. | Fully deterministic | Deterministic | +| `adata/readcsv` | Reads a CSV file and writes it as an AnnData H5AD. | Fully deterministic | Deterministic | +| `adata/readrds` | Converts an RDS file (Seurat or SingleCellExperiment) to AnnData H5AD via anndata2ri/rpy2. | Fully deterministic | Deterministic | +| `adata/setindex` | Sets a specified obs or var column as the new AnnData index. | Fully deterministic | Deterministic | +| `adata/splitcol` | Splits an AnnData object into one H5AD file per unique value of a specified obs column. | Fully deterministic | Deterministic | +| `adata/splitembeddings` | Splits multiple named embeddings from a single AnnData into separate H5AD files each containing `X_emb`. | Fully deterministic | Deterministic | +| `adata/tords` | Converts an AnnData H5AD to an RDS SingleCellExperiment object using anndataR. | Fully deterministic | Deterministic | +| `adata/unify` | Normalises gene symbols, resolves duplicates, unifies batch/label/condition columns, and prefixes barcodes with sample ID. | Fully deterministic | Deterministic | +| `adata/upsetgenes` | Plots an UpSet diagram of gene set overlaps across multiple AnnData objects and outputs a MultiQC JSON image. | Fully deterministic | Deterministic | + +### `celda/` + +| Module | Description | Reproducibility | Dev branch implied | +| --------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------- | +| `celda/decontx` | Removes ambient RNA contamination using the decontX variational EM algorithm (celda R package). | **Non-deterministic** — decontX uses stochastic initialisation with no fixed seed. | Non-deterministic ✓ | + +### `celldex/` + +| Module | Description | Reproducibility | Dev branch implied | +| ------------------------ | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------- | +| `celldex/fetchreference` | Downloads a named celldex reference dataset and saves it as a tar-compressed HDF5 SummarizedExperiment. | **Non-deterministic** — live download from ExperimentHub; database version varies over time. | Non-deterministic ✓ | + +### `celltypes/` + +| Module | Description | Reproducibility | Dev branch implied | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------- | +| `celltypes/celltypist` | Annotates cell types using one or more CellTypist logistic regression models after normalising and log-transforming counts. | Fully deterministic — uses a fixed, pre-trained model with no stochastic inference at prediction time. | Deterministic ✓ | +| `celltypes/singler` | Assigns cell types using the SingleR correlation-based method against one or more celldex reference datasets. | Fully deterministic — correlation/label-transfer method with no randomness. | ⚠️ Non-deterministic — dev omits `process.out` | + +### `custom/` + +| Module | Description | Reproducibility | Dev branch implied | +| --------------------- | ------------------------------------------------------------------------------------------- | ------------------- | ------------------ | +| `custom/collectsizes` | Pivots a TSV of per-sample cell counts at different QC stages into a MultiQC summary table. | Fully deterministic | Deterministic ✓ | + +### `doublet_detection/` + +| Module | Description | Reproducibility | Dev branch implied | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------- | +| `doublet_detection/doublet_removal` | Removes doublet cells from an AnnData object based on a threshold applied to aggregated doublet-caller predictions. | Fully deterministic | Deterministic ✓ | +| `doublet_detection/scds` | Scores and calls doublets using bcds + cxds + hybrid (scds R package) with `set.seed(0)`. | Seeded / quasi-deterministic — seed is fixed, but internal boosting results may vary slightly across R/package versions. | ⚠️ Non-deterministic — dev omits `process.out` | + +### `hugounifier/` + +| Module | Description | Reproducibility | Dev branch implied | +| ------------------- | --------------------------------------------------------------------------------------------- | ------------------- | ---------------------------------------------- | +| `hugounifier/get` | Computes a cross-dataset gene symbol renaming change table using the `hugo-unifier` CLI tool. | Fully deterministic | ⚠️ Non-deterministic — dev omits `process.out` | +| `hugounifier/apply` | Applies a gene symbol renaming change table to a single AnnData H5AD file. | Fully deterministic | ⚠️ Non-deterministic — dev omits `process.out` | + +### `liana/` + +| Module | Description | Reproducibility | Dev branch implied | +| --------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------ | +| `liana/rankaggregate` | Runs LIANA rank-aggregate ligand–receptor interaction analysis on a clustered AnnData object. | Fully deterministic — rank aggregation of multiple fixed scoring methods with no stochastic component. | Deterministic ✓ | + +### `scanpy/` + +| Module | Description | Reproducibility | Dev branch implied | +| ------------------------ | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | +| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | Deterministic ✓ | +| `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | Deterministic ✓ | +| `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | Deterministic ✓ | +| `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | Deterministic ✓ | +| `scanpy/harmony` | Runs Harmony batch integration after log-normalisation and PCA, storing the corrected embedding as `X_emb`. | **Non-deterministic** — Harmony is an iterative optimisation with no fixed seed; upstream PCA is also unseeded. | Non-deterministic ✓ | +| `scanpy/hvgs` | Selects highly variable genes and subsets the AnnData to those genes. | Fully deterministic | Deterministic ✓ | +| `scanpy/leiden` | Performs Leiden community-detection clustering at a specified resolution. | **Non-deterministic** — Leiden uses random restarts with no fixed seed. | Non-deterministic ✓ | +| `scanpy/neighbors` | Computes a k-nearest-neighbour graph on a specified embedding. | Fully deterministic given a fixed input embedding. | ⚠️ Stub-only test on dev | +| `scanpy/paga` | Computes PAGA coarse-grained cluster connectivity and saves a graph and plot. | Fully deterministic — PAGA is a deterministic graph-summarisation step given fixed Leiden labels. | Deterministic ✓ | +| `scanpy/pca` | Runs PCA with `random_state=0` and stores the result under a specified key. | Seeded / quasi-deterministic — seed is fixed, but float coordinates can differ across LAPACK/MKL backends. | ⚠️ Non-deterministic — dev omits `process.out` | +| `scanpy/plotqc` | Calculates QC metrics and produces a counts-vs-genes scatter plot for MultiQC. | Fully deterministic | Deterministic ✓ | +| `scanpy/rankgenesgroups` | Runs differential gene expression (rank genes groups) across clusters using a configurable statistical method. | Fully deterministic for `wilcoxon` and `t-test` (defaults); depends on chosen method parameter. | Deterministic ✓ | +| `scanpy/readh5` | Reads a 10x Genomics HDF5 (`.h5`) file and writes it as an AnnData H5AD. | Fully deterministic | Deterministic ✓ | +| `scanpy/sample` | Down-samples cells to a fixed count or fraction using `rng=0`. | Seeded / quasi-deterministic — seed is fixed, but sampled cell set may vary across NumPy versions. | Deterministic ✓ | +| `scanpy/umap` | Computes a UMAP embedding from a pre-built neighbour graph using `random_state=0`. | Seeded / quasi-deterministic — seed is fixed, but float coordinates vary across umap-learn/numba versions. | ⚠️ Non-deterministic — dev omits `process.out` | + +### `scimilarity/` + +| Module | Description | Reproducibility | Dev branch implied | +| ------------------------ | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | +| `scimilarity/annotate` | Annotates cells with cell type labels using SCimilarity's kNN lookup into the pretrained reference embedding. | Fully deterministic — pure kNN lookup against a fixed reference with no stochastic inference. ⚠️ No non-stub test exists: the SCimilarity model file (~30 GB) exceeds practical test data limits. | Stub-only on both | +| `scimilarity/embed` | Embeds cells into SCimilarity's pretrained metric-learning latent space. | Fully deterministic — inference-only forward pass through a fixed pretrained network (no dropout at inference). ⚠️ No non-stub test exists: the SCimilarity model file (~30 GB) exceeds practical test data limits. | Stub-only on both | +| `scimilarity/pseudobulk` | Aggregates single-cell counts into pseudobulk profiles grouped by specified metadata columns. | Fully deterministic | Deterministic ✓ | + +### `scvitools/` + +| Module | Description | Reproducibility | Dev branch implied | +| ------------------ | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `scvitools/scanvi` | Trains a scANVI semi-supervised VAE for batch integration and label transfer with `seed=0` and deterministic CUDA ops. | Seeded / quasi-deterministic — seed and `torch.use_deterministic_algorithms(True)` are set, but variational training and early stopping can still differ across GPU drivers and torch/scvi versions. Tests deliberately omit `process.out`. | Non-deterministic ✓ | +| `scvitools/scvi` | Trains a scVI VAE for batch integration with `seed=0` and deterministic CUDA ops. | Seeded / quasi-deterministic — same caveats as scANVI above. Tests deliberately omit `process.out`. | Non-deterministic ✓ | + +### `seurat/` + +| Module | Description | Reproducibility | Dev branch implied | +| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------- | +| `seurat/integration` | Performs Seurat v5 CCA-based batch integration after SCTransform and PCA with `set.seed(0)`, storing the corrected embedding as `X_emb`. | Seeded / quasi-deterministic — seed is fixed, but CCA/SCTransform involve floating-point iterative optimisation that can vary across Seurat/LAPACK versions. | ⚠️ Non-deterministic — dev omits `process.out` | + +### `soupx/` + +| Module | Description | Reproducibility | Dev branch implied | +| ------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------ | +| `soupx` | Estimates and removes ambient RNA contamination using SoupX, preceded by Seurat clustering to define cluster-level contamination. | Fully deterministic — the Seurat clustering step uses a fixed seed; the original tests used `snapshot(process.out)`. | Deterministic ✓ | + +--- + +## Subworkflows + +| Subworkflow | Description | Reproducibility | Dev branch implied | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `ambient_correction` | Dispatches ambient RNA correction to decontX, SoupX, or none based on a parameter. | **Non-deterministic** for decontX (no seed); fully deterministic for SoupX and the `none` passthrough. | Non-deterministic ✓ | +| `celltype_assignment` | Orchestrates cell type annotation by running SingleR and/or CellTypist. | Fully deterministic — both methods are deterministic at inference time. | ⚠️ Non-deterministic — dev omits `workflow.out` | +| `cluster` | Full clustering pipeline: neighbours → UMAP → Leiden at multiple resolutions → Shannon entropy. | Seeded / quasi-deterministic for UMAP; **non-deterministic** due to unseeded Leiden. | Non-deterministic ✓ | +| `combine` | Merges all samples and runs all configured integration methods. | Inherits from constituent modules — ranges from fully deterministic (no integration) to seeded/quasi-deterministic (scVI, Harmony, Seurat). | ⚠️ Deterministic — dev snapshots `workflow.out` regardless of integration method | +| `differential_expression` | Runs rank-genes-groups DE analysis across all combinations of clustering labels, conditions, and cell-type subsets. | Fully deterministic for the default wilcoxon/t-test methods. | Deterministic ✓ | +| `doublet_detection` | Runs one or more doublet-detection methods (scds, solo, scrublet, doubletdetection) and removes called doublets. | **Non-deterministic** — solo, scrublet, and doubletdetection have stochastic components; scds is seeded. | Non-deterministic ✓ | +| `finalize` | Assembles the final AnnData by extending it with all collected obs/obsm/uns/layers outputs. | Fully deterministic | Deterministic ✓ | +| `integrate` | Applies HVG selection then one or more integration methods (scVI, scANVI, Harmony, BBKNN, ComBat, Seurat, SCimilarity). | Seeded / quasi-deterministic for scVI/scANVI/ComBat/Seurat/BBKNN; **non-deterministic** for Harmony. | ⚠️ Deterministic — dev snapshots `workflow.out` for all integration methods including Harmony | +| `load_h5ad` | Loads input files in H5AD, 10x H5, RDS, or CSV format and converts all to AnnData H5AD. | Fully deterministic | Deterministic ✓ | +| `per_group` | Runs PAGA, LIANA rank-aggregate, and rank-genes DE per cluster. | Fully deterministic | Deterministic ✓ | +| `pseudobulking` | Aggregates single-cell data into pseudobulk profiles grouped by specified metadata columns. | Fully deterministic | Deterministic ✓ | +| `quality_control` | Full per-sample QC pipeline: empty droplet filtering, ambient correction, gene unification, cell/gene filtering, optional downsampling, doublet detection, and optional cell cycle scoring. | Seeded / quasi-deterministic to **non-deterministic** depending on configured ambient and doublet-detection methods. | ⚠️ Deterministic — dev snapshots `workflow.out` regardless of method configuration | +| `scimilarity` | Embeds cells into the SCimilarity pretrained latent space and annotates with cell type labels. | Fully deterministic — fixed pretrained model, inference-only. | Stub-only on both | +| `singler` | Downloads (or uses pre-provided) celldex reference datasets and runs SingleR annotation. | Fully deterministic for annotation; **non-deterministic** if downloading references at runtime via ExperimentHub. | Deterministic ✓ | +| `unify` | Standardises gene symbols (optionally via MyGene.info and HUGO-unifier) and normalises metadata columns (batch, label, condition). | **Non-deterministic** when `symbol_col == "none"` (triggers MyGene.info API call); fully deterministic otherwise. | Deterministic — dev snapshots `workflow.out` including the MyGene.info path | +| `unify_genes` | Applies HUGO-unifier to compute and apply a cross-dataset gene symbol renaming table. | Fully deterministic | ⚠️ Non-deterministic — dev omits `workflow.out` | diff --git a/modules/local/adata/entropy/tests/main.nf.test b/modules/local/adata/entropy/tests/main.nf.test index 8444d174..83d6e242 100644 --- a/modules/local/adata/entropy/tests/main.nf.test +++ b/modules/local/adata/entropy/tests/main.nf.test @@ -28,10 +28,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -58,10 +57,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/extend/tests/main.nf.test b/modules/local/adata/extend/tests/main.nf.test index 83a2cb77..45c90110 100644 --- a/modules/local/adata/extend/tests/main.nf.test +++ b/modules/local/adata/extend/tests/main.nf.test @@ -31,16 +31,12 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "scvi-global-1.0_leiden" in obs.colnames - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "scvi-global-1.0_leiden" in obs.colnames + } + assert snapshot(process.out).match() } } @@ -69,16 +65,12 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "X_scvi" in obsm - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "X_scvi" in obsm + } + assert snapshot(process.out).match() } } @@ -113,19 +105,15 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "scvi-global-1.0_leiden" in obs.colnames - assert "scvi-global-1.0:entropy" in obs.colnames - assert "X_scvi" in obsm - assert "X_scvi-global_umap" in obsm - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "scvi-global-1.0_leiden" in obs.colnames + assert "scvi-global-1.0:entropy" in obs.colnames + assert "X_scvi" in obsm + assert "X_scvi-global_umap" in obsm + } + assert snapshot(process.out).match() } } @@ -154,16 +142,12 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "scvi-global-1.0_paga" in uns - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "scvi-global-1.0_paga" in uns + } + assert snapshot(process.out).match() } } @@ -192,10 +176,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } @@ -226,10 +208,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/mergeembeddings/tests/main.nf.test b/modules/local/adata/mergeembeddings/tests/main.nf.test index 0146473f..501b83ee 100644 --- a/modules/local/adata/mergeembeddings/tests/main.nf.test +++ b/modules/local/adata/mergeembeddings/tests/main.nf.test @@ -26,22 +26,16 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "X_emb" in obsm - // Should have cells from both base (50) and integrated (30) - assert obs.rownames.size() == 80 - } - }, - // obsm pickle should be created - { assert file(process.out.obsm[0]).name == "X_scvi.pkl" }, - // obs pickle should NOT be created for non-scanvi - { assert process.out.obs.size() == 0 } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "X_emb" in obsm + // Should have cells from both base (50) and integrated (30) + assert obs.rownames.size() == 80 + } + assert file(process.out.obsm[0]).name == "X_scvi.pkl" + assert process.out.obs.size() == 0 + assert snapshot(process.out).match() } } @@ -65,22 +59,16 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "X_emb" in obsm - assert "label:scANVI" in obs.colnames - assert obs.rownames.size() == 80 - } - }, - // obsm pickle should be created - { assert file(process.out.obsm[0]).name == "X_scanvi.pkl" }, - // obs pickle SHOULD be created for scanvi - { assert file(process.out.obs[0]).name == "scanvi.pkl" } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "X_emb" in obsm + assert "label:scANVI" in obs.colnames + assert obs.rownames.size() == 80 + } + assert file(process.out.obsm[0]).name == "X_scanvi.pkl" + assert file(process.out.obs[0]).name == "scanvi.pkl" + assert snapshot(process.out).match() } } @@ -106,10 +94,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/mygene/tests/main.nf.test b/modules/local/adata/mygene/tests/main.nf.test index 18c5839a..e6e99f7a 100644 --- a/modules/local/adata/mygene/tests/main.nf.test +++ b/modules/local/adata/mygene/tests/main.nf.test @@ -25,10 +25,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -53,10 +52,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/prepcellxgene/tests/main.nf.test b/modules/local/adata/prepcellxgene/tests/main.nf.test index ed8689b5..680dd004 100644 --- a/modules/local/adata/prepcellxgene/tests/main.nf.test +++ b/modules/local/adata/prepcellxgene/tests/main.nf.test @@ -25,10 +25,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -53,10 +52,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/readcsv/tests/main.nf.test b/modules/local/adata/readcsv/tests/main.nf.test index f6f808fd..321e296d 100644 --- a/modules/local/adata/readcsv/tests/main.nf.test +++ b/modules/local/adata/readcsv/tests/main.nf.test @@ -25,10 +25,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -53,10 +52,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/readrds/tests/main.nf.test b/modules/local/adata/readrds/tests/main.nf.test index e286456e..ec7239f7 100644 --- a/modules/local/adata/readrds/tests/main.nf.test +++ b/modules/local/adata/readrds/tests/main.nf.test @@ -25,10 +25,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -53,10 +52,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -79,10 +77,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -107,10 +104,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/setindex/tests/main.nf.test b/modules/local/adata/setindex/tests/main.nf.test index 50062bf2..81967669 100644 --- a/modules/local/adata/setindex/tests/main.nf.test +++ b/modules/local/adata/setindex/tests/main.nf.test @@ -27,10 +27,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -55,10 +54,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -85,10 +83,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/splitembeddings/tests/main.nf.test b/modules/local/adata/splitembeddings/tests/main.nf.test index 7eb6f617..92e0b868 100644 --- a/modules/local/adata/splitembeddings/tests/main.nf.test +++ b/modules/local/adata/splitembeddings/tests/main.nf.test @@ -26,10 +26,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -55,10 +54,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/tords/tests/main.nf.test b/modules/local/adata/tords/tests/main.nf.test index aa4bac0b..66f20a1f 100644 --- a/modules/local/adata/tords/tests/main.nf.test +++ b/modules/local/adata/tords/tests/main.nf.test @@ -26,10 +26,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -55,10 +54,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/unify/tests/main.nf.test b/modules/local/adata/unify/tests/main.nf.test index b2fc48fa..d4ee9d36 100644 --- a/modules/local/adata/unify/tests/main.nf.test +++ b/modules/local/adata/unify/tests/main.nf.test @@ -36,20 +36,16 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "batch" in obs.colnames - assert "label" in obs.colnames - assert "sample" in obs.colnames - assert !("counts" in layers) - assert layers.size() == 0 - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "batch" in obs.colnames + assert "label" in obs.colnames + assert "sample" in obs.colnames + assert !("counts" in layers) + assert layers.size() == 0 + } + assert snapshot(process.out).match() } } @@ -78,19 +74,15 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "batch" in obs.colnames - assert "label" in obs.colnames - assert "sample" in obs.colnames - assert layers.size() == 0 - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "batch" in obs.colnames + assert "label" in obs.colnames + assert "sample" in obs.colnames + assert layers.size() == 0 + } + assert snapshot(process.out).match() } } @@ -123,10 +115,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } @@ -155,16 +145,12 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "original_index" in var.colnames - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "original_index" in var.colnames + } + assert snapshot(process.out).match() } } @@ -197,11 +183,10 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert adata.var.rownames.toUnique().size() == adata.var.rownames.size() + assert snapshot(process.out).match() } } @@ -230,11 +215,10 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert adata.var.rownames.toUnique().size() == adata.var.rownames.size() + assert snapshot(process.out).match() } } @@ -263,11 +247,10 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert adata.var.rownames.toUnique().size() == adata.var.rownames.size() + assert snapshot(process.out).match() } } @@ -296,11 +279,11 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + // make_unique adds numeric suffixes — var names are unique but not aggregated + assert adata.var.rownames.toUnique().size() == adata.var.rownames.size() + assert snapshot(process.out).match() } } @@ -333,17 +316,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - // After isoform aggregation, numeric suffixes should be removed - assert var.rownames.every { !it.matches(/.*\\.\\d+$/) } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + // After isoform aggregation, numeric suffixes should be removed + assert var.rownames.every { !it.matches(/.*\\.\\d+$/) } + } + assert snapshot(process.out).match() } } @@ -376,18 +355,14 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "batch" in obs.colnames - assert !("batch_id" in obs.colnames) - assert obs.get("batch").unique().every { it.contains("_test") } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "batch" in obs.colnames + assert !("batch_id" in obs.colnames) + assert obs.get("batch").unique().every { it.contains("_test") } + } + assert snapshot(process.out).match() } } @@ -416,17 +391,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "batch" in obs.colnames - assert obs.get("batch").unique().every { it.contains("_test") } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "batch" in obs.colnames + assert obs.get("batch").unique().every { it.contains("_test") } + } + assert snapshot(process.out).match() } } @@ -455,17 +426,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "batch" in obs.colnames - assert obs.get("batch").unique().every { it == "test_test" } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "batch" in obs.colnames + assert obs.get("batch").unique().every { it == "test_test" } + } + assert snapshot(process.out).match() } } @@ -528,18 +495,14 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "label" in obs.colnames - assert !("cell_type" in obs.colnames) - assert obs.get("label").unique().size() > 0 - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "label" in obs.colnames + assert !("cell_type" in obs.colnames) + assert obs.get("label").unique().size() > 0 + } + assert snapshot(process.out).match() } } @@ -568,17 +531,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "label" in obs.colnames - assert obs.get("label").unique().size() > 0 - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "label" in obs.colnames + assert obs.get("label").unique().size() > 0 + } + assert snapshot(process.out).match() } } @@ -607,17 +566,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "label" in obs.colnames - assert obs.get("label").unique().every { it == "Unknown" } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "label" in obs.colnames + assert obs.get("label").unique().every { it == "Unknown" } + } + assert snapshot(process.out).match() } } @@ -646,17 +601,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "label" in obs.colnames - assert "Unknown" in obs.get("label").unique() - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "label" in obs.colnames + assert "Unknown" in obs.get("label").unique() + } + assert snapshot(process.out).match() } } @@ -685,17 +636,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "label" in obs.colnames - assert "Unknown" in obs.get("label").unique() - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "label" in obs.colnames + assert "Unknown" in obs.get("label").unique() + } + assert snapshot(process.out).match() } } @@ -724,18 +671,14 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "label" in obs.colnames - // Labels should be normalized (no spaces, dashes, special chars) - assert obs.get("label").unique().every { !it.contains(" ") && !it.contains("-") && !it.contains("+") } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "label" in obs.colnames + // Labels should be normalized (no spaces, dashes, special chars) + assert obs.get("label").unique().every { !it.contains(" ") && !it.contains("-") && !it.contains("+") } + } + assert snapshot(process.out).match() } } @@ -798,18 +741,14 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "condition" in obs.colnames - assert !("disease_state" in obs.colnames) - assert obs.get("condition").unique().size() > 0 - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "condition" in obs.colnames + assert !("disease_state" in obs.colnames) + assert obs.get("condition").unique().size() > 0 + } + assert snapshot(process.out).match() } } @@ -838,17 +777,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "condition" in obs.colnames - assert obs.get("condition").unique().size() > 0 - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "condition" in obs.colnames + assert obs.get("condition").unique().size() > 0 + } + assert snapshot(process.out).match() } } @@ -877,17 +812,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "condition" in obs.colnames - assert obs.get("condition").unique().every { it == "Unknown" } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "condition" in obs.colnames + assert obs.get("condition").unique().every { it == "Unknown" } + } + assert snapshot(process.out).match() } } @@ -950,10 +881,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } @@ -982,10 +911,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } @@ -1018,17 +945,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - // All cell names should be prefixed - assert obs.rownames.every { it.startsWith("test_") } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + // All cell names should be prefixed + assert obs.rownames.every { it.startsWith("test_") } + } + assert snapshot(process.out).match() } } @@ -1057,18 +980,14 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "sample" in obs.colnames - assert "sample_original" in obs.colnames - assert obs.get("sample").unique().every { it == "test" } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "sample" in obs.colnames + assert "sample_original" in obs.colnames + assert obs.get("sample").unique().every { it == "test" } + } + assert snapshot(process.out).match() } } @@ -1097,17 +1016,13 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "sample" in obs.colnames - assert obs.get("sample").unique().every { it == "test" } - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "sample" in obs.colnames + assert obs.get("sample").unique().every { it == "test" } + } + assert snapshot(process.out).match() } } @@ -1140,19 +1055,15 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert obsm.size() == 0 - assert varm.size() == 0 - assert uns.size() == 0 - assert layers.size() == 0 - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert obsm.size() == 0 + assert varm.size() == 0 + assert uns.size() == 0 + assert layers.size() == 0 + } + assert snapshot(process.out).match() } } @@ -1185,22 +1096,18 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "batch" in obs.colnames - assert "label" in obs.colnames - assert "sample" in obs.colnames - assert obsm.size() == 0 - assert varm.size() == 0 - assert uns.size() == 0 - assert layers.size() == 0 - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "batch" in obs.colnames + assert "label" in obs.colnames + assert "sample" in obs.colnames + assert obsm.size() == 0 + assert varm.size() == 0 + assert uns.size() == 0 + assert layers.size() == 0 + } + assert snapshot(process.out).match() } } @@ -1229,22 +1136,18 @@ nextflow_process { } then { - def filename = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() }, - { - with(anndata(filename)) { - assert "batch" in obs.colnames - assert "label" in obs.colnames - assert "sample" in obs.colnames - assert obsm.size() == 0 - assert varm.size() == 0 - assert uns.size() == 0 - assert layers.size() == 0 - } - } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "batch" in obs.colnames + assert "label" in obs.colnames + assert "sample" in obs.colnames + assert obsm.size() == 0 + assert varm.size() == 0 + assert uns.size() == 0 + assert layers.size() == 0 + } + assert snapshot(process.out).match() } } @@ -1279,10 +1182,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/adata/upsetgenes/tests/main.nf.test b/modules/local/adata/upsetgenes/tests/main.nf.test index a53f8d69..4b7fa2e0 100644 --- a/modules/local/adata/upsetgenes/tests/main.nf.test +++ b/modules/local/adata/upsetgenes/tests/main.nf.test @@ -29,10 +29,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -61,10 +60,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/celda/decontx/tests/main.nf.test b/modules/local/celda/decontx/tests/main.nf.test index 00c9d57f..cee1d07f 100644 --- a/modules/local/celda/decontx/tests/main.nf.test +++ b/modules/local/celda/decontx/tests/main.nf.test @@ -29,11 +29,15 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + // output written to X, so no named decontx layer + assert !("ambient_corrected_decontx" in adata.layers) + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -60,11 +64,15 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + // output written to X, so no named decontx layer + assert !("ambient_corrected_decontx" in adata.layers) + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -91,11 +99,15 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + // output written to X, so no named decontx layer + assert !("ambient_corrected_decontx" in adata.layers) + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -124,10 +136,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -154,11 +165,15 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + // output written to X, so no named decontx layer + assert !("ambient_corrected_decontx" in adata.layers) + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -185,12 +200,15 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, - { assert "ambient_corrected_decontx" in anndata(h5ad).layers } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + + assert "ambient_corrected_decontx" in adata.layers + + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -219,10 +237,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/celda/decontx/tests/main.nf.test.snap b/modules/local/celda/decontx/tests/main.nf.test.snap index b1ef2763..df653129 100644 --- a/modules/local/celda/decontx/tests/main.nf.test.snap +++ b/modules/local/celda/decontx/tests/main.nf.test.snap @@ -1,6 +1,30 @@ { "Should run without failures without batch column": { "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_decontx.h5ad:md5,1eb88b5ef4b605b4f62030c2a607e28a" + ] + ], + "1": [ + "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" + ], + "h5ad": [ + [ + { + "id": "test" + }, + "test_decontx.h5ad:md5,1eb88b5ef4b605b4f62030c2a607e28a" + ] + ], + "versions": [ + "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" + ] + }, { "CELDA_DECONTX": { "r": "4.5.3", @@ -10,7 +34,7 @@ }, "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-25T16:03:20.607863222", + "timestamp": "2026-03-28T16:50:38.098489322", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -18,6 +42,30 @@ }, "Should run without failures without raw - single batch": { "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_decontx.h5ad:md5,1eb88b5ef4b605b4f62030c2a607e28a" + ] + ], + "1": [ + "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" + ], + "h5ad": [ + [ + { + "id": "test" + }, + "test_decontx.h5ad:md5,1eb88b5ef4b605b4f62030c2a607e28a" + ] + ], + "versions": [ + "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" + ] + }, { "CELDA_DECONTX": { "r": "4.5.3", @@ -27,7 +75,7 @@ }, "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-25T16:04:16.789960757", + "timestamp": "2026-03-28T16:51:40.101871935", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -35,6 +83,30 @@ }, "Should run without failures with raw": { "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_decontx.h5ad:md5,5b66bb96352049340b9214c45e8706cd" + ] + ], + "1": [ + "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" + ], + "h5ad": [ + [ + { + "id": "test" + }, + "test_decontx.h5ad:md5,5b66bb96352049340b9214c45e8706cd" + ] + ], + "versions": [ + "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" + ] + }, { "CELDA_DECONTX": { "r": "4.5.3", @@ -44,7 +116,7 @@ }, "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-25T16:07:08.797021713", + "timestamp": "2026-03-28T16:54:46.7175794", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -102,6 +174,30 @@ }, "Should run without failures without raw - multi-batch": { "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_decontx.h5ad:md5,cf9801305448dfc1ecbae9ab102d09f3" + ] + ], + "1": [ + "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" + ], + "h5ad": [ + [ + { + "id": "test" + }, + "test_decontx.h5ad:md5,cf9801305448dfc1ecbae9ab102d09f3" + ] + ], + "versions": [ + "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" + ] + }, { "CELDA_DECONTX": { "r": "4.5.3", @@ -111,7 +207,7 @@ }, "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-25T16:05:55.215308418", + "timestamp": "2026-03-28T16:46:02.200693929", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/celltypes/celltypist/tests/main.nf.test b/modules/local/celltypes/celltypist/tests/main.nf.test index 104f7d98..81477ffa 100644 --- a/modules/local/celltypes/celltypist/tests/main.nf.test +++ b/modules/local/celltypes/celltypist/tests/main.nf.test @@ -27,11 +27,16 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).obs.colnames).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "celltypist:Adult_COVID19_PBMC" in obs.colnames + assert "celltypist:Adult_COVID19_PBMC:conf" in obs.colnames + } + assert snapshot( + path(process.out.versions[0]).yaml, + adata.obs.colnames + ).match() } } @@ -56,11 +61,16 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).obs.colnames).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "celltypist:Adult_COVID19_PBMC" in obs.colnames + assert "celltypist:Adult_COVID19_PBMC:conf" in obs.colnames + } + assert snapshot( + path(process.out.versions[0]).yaml, + adata.obs.colnames + ).match() } } @@ -85,9 +95,7 @@ nextflow_process { } then { - assertAll( - { assert process.failed } - ) + assert process.failed } } @@ -113,10 +121,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/custom/collectsizes/tests/main.nf.test b/modules/local/custom/collectsizes/tests/main.nf.test index d1519bc2..ee24cd74 100644 --- a/modules/local/custom/collectsizes/tests/main.nf.test +++ b/modules/local/custom/collectsizes/tests/main.nf.test @@ -23,10 +23,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -49,10 +48,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/doublet_detection/scds/tests/main.nf.test b/modules/local/doublet_detection/scds/tests/main.nf.test index f23ab827..513bf125 100644 --- a/modules/local/doublet_detection/scds/tests/main.nf.test +++ b/modules/local/doublet_detection/scds/tests/main.nf.test @@ -25,11 +25,16 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).obs.colnames).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "hybrid_call" in obs.colnames + assert "hybrid_score" in obs.colnames + } + assert snapshot( + path(process.out.versions[0]).yaml, + adata.obs.colnames + ).match() } } @@ -54,10 +59,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/hugounifier/apply/tests/main.nf.test b/modules/local/hugounifier/apply/tests/main.nf.test index 1cb039bb..0785a00d 100644 --- a/modules/local/hugounifier/apply/tests/main.nf.test +++ b/modules/local/hugounifier/apply/tests/main.nf.test @@ -45,15 +45,15 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { - with(anndata(process.out.h5ad[0][1])) { - assert var.rownames.size() > 0 - assert obs.rownames.size() > 0 - } + assert process.success + + with(anndata(process.out.h5ad[0][1])) { + + assert var.rownames.size() > 0 + + assert obs.rownames.size() > 0 + } - ) } } @@ -79,10 +79,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/hugounifier/get/tests/main.nf.test b/modules/local/hugounifier/get/tests/main.nf.test index d111058f..d8d4deec 100644 --- a/modules/local/hugounifier/get/tests/main.nf.test +++ b/modules/local/hugounifier/get/tests/main.nf.test @@ -29,20 +29,21 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert process.out.changes[0][1].size() == 2 }, - { - with(path(process.out.changes[0][1][0]).csv) { - assert columnNames == ["action", "symbol", "new", "reason"] - } - }, - { - with(path(process.out.changes[0][1][1]).csv) { - assert columnNames == ["action", "symbol", "new", "reason"] - } + assert process.success + + assert process.out.changes[0][1].size() == 2 + + with(path(process.out.changes[0][1][0]).csv) { + + assert columnNames == ["action", "symbol", "new", "reason"] + + } + + with(path(process.out.changes[0][1][1]).csv) { + + assert columnNames == ["action", "symbol", "new", "reason"] + } - ) } } @@ -71,10 +72,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test b/modules/local/liana/rankaggregate/tests/main.nf.test index 3fb99fba..d1121a1c 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test +++ b/modules/local/liana/rankaggregate/tests/main.nf.test @@ -27,10 +27,14 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size()).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert "liana_res" in adata.uns + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -55,10 +59,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test.snap b/modules/local/liana/rankaggregate/tests/main.nf.test.snap index e15a6054..9c36fc6e 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test.snap +++ b/modules/local/liana/rankaggregate/tests/main.nf.test.snap @@ -40,14 +40,44 @@ }, "Should run without failures": { "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_liana.h5ad:md5,c227d198aa472576b58ffe61ff37027b" + ] + ], + "1": [ + "test_liana.pkl:md5,058214ae3910f43472b791830a606047" + ], + "2": [ + "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" + ], + "h5ad": [ + [ + { + "id": "test" + }, + "test_liana.h5ad:md5,c227d198aa472576b58ffe61ff37027b" + ] + ], + "uns": [ + "test_liana.pkl:md5,058214ae3910f43472b791830a606047" + ], + "versions": [ + "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" + ] + }, { "liana": "1.6.1", "python": "3.12.12", "scanpy": "1.11.5" }, - 1 + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - liana_res\n - log1p\n - neighbors\n" ], - "timestamp": "2026-03-25T15:46:58.7462693", + "timestamp": "2026-03-28T17:34:38.380015311", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/bbknn/tests/main.nf.test b/modules/local/scanpy/bbknn/tests/main.nf.test index d6d5af69..7fb1827a 100644 --- a/modules/local/scanpy/bbknn/tests/main.nf.test +++ b/modules/local/scanpy/bbknn/tests/main.nf.test @@ -28,14 +28,17 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, - { assert "X_pca" in anndata(h5ad).obsm }, - { assert "connectivities" in anndata(h5ad).obsp }, - { assert "distances" in anndata(h5ad).obsp } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "X_pca" in obsm + assert "connectivities" in obsp + assert "distances" in obsp + } + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -61,10 +64,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/cellcycle/tests/main.nf.test b/modules/local/scanpy/cellcycle/tests/main.nf.test index b86ad0c8..b9b7baff 100644 --- a/modules/local/scanpy/cellcycle/tests/main.nf.test +++ b/modules/local/scanpy/cellcycle/tests/main.nf.test @@ -28,10 +28,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -59,10 +58,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/combat/tests/main.nf.test b/modules/local/scanpy/combat/tests/main.nf.test index f89918b7..cf68a3a5 100644 --- a/modules/local/scanpy/combat/tests/main.nf.test +++ b/modules/local/scanpy/combat/tests/main.nf.test @@ -41,13 +41,16 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, - { assert "X_emb" in anndata(h5ad).obsm }, - { assert "X_pca" in anndata(h5ad).obsm } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "X_emb" in obsm + assert "X_pca" in obsm + } + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -69,10 +72,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/filter/tests/main.nf.test b/modules/local/scanpy/filter/tests/main.nf.test index dc21ef14..69025afb 100644 --- a/modules/local/scanpy/filter/tests/main.nf.test +++ b/modules/local/scanpy/filter/tests/main.nf.test @@ -32,10 +32,17 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "mt" in var.colnames + assert "pct_counts_mt" in obs.colnames + } + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -66,10 +73,17 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "mt" in var.colnames + assert "pct_counts_mt" in obs.colnames + } + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -99,10 +113,9 @@ nextflow_process { } then { - assertAll( - { assert process.failed }, - { assert snapshot(process.out).match() } - ) + assert process.failed + + assert snapshot(process.out).match() } } @@ -133,10 +146,17 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "mt" in var.colnames + assert "pct_counts_mt" in obs.colnames + } + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -168,10 +188,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/harmony/tests/main.nf.test b/modules/local/scanpy/harmony/tests/main.nf.test index ae6568f7..78e8bfe2 100644 --- a/modules/local/scanpy/harmony/tests/main.nf.test +++ b/modules/local/scanpy/harmony/tests/main.nf.test @@ -29,16 +29,14 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { - assert snapshot( - path(process.out.variance_ratio[0]).yaml, - path(process.out.versions[0]).yaml - ).match() - }, - { assert "X_emb" in anndata(process.out.h5ad[0][1]).obsm } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert "X_emb" in adata.obsm + assert snapshot( + path(process.out.variance_ratio[0]).yaml, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -65,10 +63,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/harmony/tests/main.nf.test.snap b/modules/local/scanpy/harmony/tests/main.nf.test.snap index d4282c8a..6b01e291 100644 --- a/modules/local/scanpy/harmony/tests/main.nf.test.snap +++ b/modules/local/scanpy/harmony/tests/main.nf.test.snap @@ -107,9 +107,10 @@ "python": "3.13.12", "scanpy": "1.12" } - } + }, + "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_emb\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-22T13:18:13.205002754", + "timestamp": "2026-03-28T16:50:30.59991269", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/hvgs/tests/main.nf.test b/modules/local/scanpy/hvgs/tests/main.nf.test index f0e6038c..661c0efe 100644 --- a/modules/local/scanpy/hvgs/tests/main.nf.test +++ b/modules/local/scanpy/hvgs/tests/main.nf.test @@ -27,11 +27,13 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert "highly_variable" in adata.var.colnames + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -56,11 +58,13 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert "highly_variable" in adata.var.colnames + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -86,11 +90,13 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert "highly_variable" in adata.var.colnames + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -117,10 +123,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/leiden/tests/main.nf.test b/modules/local/scanpy/leiden/tests/main.nf.test index 48072498..b3e93666 100644 --- a/modules/local/scanpy/leiden/tests/main.nf.test +++ b/modules/local/scanpy/leiden/tests/main.nf.test @@ -30,16 +30,17 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { - def obs = anndata(process.out.h5ad[0][1]).obs + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { assert "leiden" in obs.colnames def n_clusters = obs.get("leiden").n_unique() - assert n_clusters >= 5 && n_clusters <= 30 : "Expected 5–30 Leiden clusters, got ${n_clusters}" + assert n_clusters >= 5 && n_clusters <= 30 : "Expected 5-30 Leiden clusters, got ${n_clusters}" } - ) + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -67,10 +68,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/neighbors/tests/main.nf.test b/modules/local/scanpy/neighbors/tests/main.nf.test index dfc16839..2aaaaccf 100644 --- a/modules/local/scanpy/neighbors/tests/main.nf.test +++ b/modules/local/scanpy/neighbors/tests/main.nf.test @@ -28,18 +28,23 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out.versions).match() }, - { - def ad = anndata(process.out.h5ad[0][1]) - assert "connectivities" in ad.obsp - assert "distances" in ad.obsp - assert "neighbors" in ad.uns + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "connectivities" in obsp + assert "distances" in obsp + assert "neighbors" in uns } - ) + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } + } + + test("Should run without failures - stub") { + options '-stub' when { @@ -59,10 +64,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/neighbors/tests/main.nf.test.snap b/modules/local/scanpy/neighbors/tests/main.nf.test.snap index 6ac4b68a..4aca825d 100644 --- a/modules/local/scanpy/neighbors/tests/main.nf.test.snap +++ b/modules/local/scanpy/neighbors/tests/main.nf.test.snap @@ -1,5 +1,5 @@ { - "Should run without failures": { + "Should run without failures - stub": { "content": [ { "0": [ @@ -26,7 +26,23 @@ ] } ], - "timestamp": "2026-03-22T16:18:04.455217395", + "timestamp": "2026-03-28T16:08:57.025739289", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } + }, + "Should run without failures": { + "content": [ + { + "SCANPY_NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - neighbors\n" + ], + "timestamp": "2026-03-28T16:08:43.931518403", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/paga/tests/main.nf.test b/modules/local/scanpy/paga/tests/main.nf.test index 13d8fa09..3c9f91da 100644 --- a/modules/local/scanpy/paga/tests/main.nf.test +++ b/modules/local/scanpy/paga/tests/main.nf.test @@ -27,10 +27,16 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "paga" in uns + } + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -55,10 +61,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/paga/tests/main.nf.test.snap b/modules/local/scanpy/paga/tests/main.nf.test.snap index 4b920861..1a591bf1 100644 --- a/modules/local/scanpy/paga/tests/main.nf.test.snap +++ b/modules/local/scanpy/paga/tests/main.nf.test.snap @@ -105,9 +105,16 @@ "versions": [ "versions.yml:md5,a87c0e3b4494aaca112a02c554da3084" ] - } + }, + { + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - leiden_sizes\n - neighbors\n - paga\n" ], - "timestamp": "2026-03-22T09:51:51.950233221", + "timestamp": "2026-03-28T16:35:55.348547031", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/pca/tests/main.nf.test b/modules/local/scanpy/pca/tests/main.nf.test index bf7682d0..5f1eec26 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test +++ b/modules/local/scanpy/pca/tests/main.nf.test @@ -28,12 +28,16 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(process.out.h5ad[0][1]).yaml).match() }, - { assert "X_pca" in anndata(process.out.h5ad[0][1]).obsm }, - { assert "X_pca" in anndata(process.out.h5ad[0][1]).uns } - ) + def adata = anndata(process.out.h5ad[0][1]) + + assert process.success + assert "X_pca" in adata.obsm + assert "X_pca" in adata.uns + + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -59,10 +63,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/plotqc/tests/main.nf.test b/modules/local/scanpy/plotqc/tests/main.nf.test index 8af12fc9..e803619e 100644 --- a/modules/local/scanpy/plotqc/tests/main.nf.test +++ b/modules/local/scanpy/plotqc/tests/main.nf.test @@ -25,10 +25,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -53,10 +52,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test index e72ef015..be8084ed 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test @@ -30,10 +30,14 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size(), process.out.plots.size(), process.out.multiqc_files.size()).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert "rank_genes_groups" in adata.uns + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -61,10 +65,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } @@ -92,10 +94,14 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size(), process.out.plots.size(), process.out.multiqc_files.size()).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert "rank_genes_groups" in adata.uns + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -123,10 +129,11 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, process.out.uns.size(), process.out.plots.size(), process.out.multiqc_files.size()).match() } - ) + assert process.success + assert process.out.h5ad.size() == 0 + assert snapshot( + path(process.out.versions[0]).yaml + ).match() } } diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap index 0aaf00c7..99389b75 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap @@ -58,12 +58,9 @@ "python": "3.13.12", "scanpy": "1.12" } - }, - 0, - 0, - 0 + } ], - "timestamp": "2026-03-25T15:48:20.422064292", + "timestamp": "2026-03-28T17:42:45.977438907", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -71,6 +68,48 @@ }, "Should run without failures": { "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_characteristic_genes.h5ad:md5,9841d511b9ad3719520f69e6eebdb9ca" + ] + ], + "1": [ + "test_characteristic_genes.pkl:md5,a5375824a244e135c97349a6880d8e28" + ], + "2": [ + "test_characteristic_genes.png:md5,144d711a80fd70ace88db67cccd2f0bc" + ], + "3": [ + "test_characteristic_genes_mqc.json:md5,73c74aafa606395d0a010b51bfe20895" + ], + "4": [ + "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" + ], + "h5ad": [ + [ + { + "id": "test" + }, + "test_characteristic_genes.h5ad:md5,9841d511b9ad3719520f69e6eebdb9ca" + ] + ], + "multiqc_files": [ + "test_characteristic_genes_mqc.json:md5,73c74aafa606395d0a010b51bfe20895" + ], + "plots": [ + "test_characteristic_genes.png:md5,144d711a80fd70ace88db67cccd2f0bc" + ], + "uns": [ + "test_characteristic_genes.pkl:md5,a5375824a244e135c97349a6880d8e28" + ], + "versions": [ + "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" + ] + }, { "SCANPY_RANKGENESGROUPS": { "pandas": "2.3.3", @@ -78,11 +117,9 @@ "scanpy": "1.12" } }, - 1, - 1, - 1 + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - log1p\n - neighbors\n - rank_genes_groups\n" ], - "timestamp": "2026-03-25T15:46:09.386660869", + "timestamp": "2026-03-28T17:38:32.692483999", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -90,6 +127,48 @@ }, "Should run with condition subsetting": { "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_characteristic_genes.h5ad:md5,557ccc34f354c9c0b8b74dedd4550688" + ] + ], + "1": [ + "test_characteristic_genes.pkl:md5,eeebba0ce02541b826cc0b605ef30e3c" + ], + "2": [ + "test_characteristic_genes.png:md5,c49d632c6d6100f7931db5491844fdda" + ], + "3": [ + "test_characteristic_genes_mqc.json:md5,dd8d8a557bda69eb0b0e0d04ad0fc47f" + ], + "4": [ + "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" + ], + "h5ad": [ + [ + { + "id": "test" + }, + "test_characteristic_genes.h5ad:md5,557ccc34f354c9c0b8b74dedd4550688" + ] + ], + "multiqc_files": [ + "test_characteristic_genes_mqc.json:md5,dd8d8a557bda69eb0b0e0d04ad0fc47f" + ], + "plots": [ + "test_characteristic_genes.png:md5,c49d632c6d6100f7931db5491844fdda" + ], + "uns": [ + "test_characteristic_genes.pkl:md5,eeebba0ce02541b826cc0b605ef30e3c" + ], + "versions": [ + "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" + ] + }, { "SCANPY_RANKGENESGROUPS": { "pandas": "2.3.3", @@ -97,11 +176,9 @@ "scanpy": "1.12" } }, - 1, - 1, - 1 + "n_obs: 4386\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - leiden\n - sample\n - sample_original\nvar:\n index: _index\n columns:\n - symbols\nlayers:\nobsm:\n - X_pca\nvarm:\n - PCs\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - leiden\n - log1p\n - neighbors\n - pca\n - rank_genes_groups\n" ], - "timestamp": "2026-03-25T15:47:33.511565517", + "timestamp": "2026-03-28T17:39:26.160880497", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/readh5/tests/main.nf.test b/modules/local/scanpy/readh5/tests/main.nf.test index a844a3e3..64cc59ce 100644 --- a/modules/local/scanpy/readh5/tests/main.nf.test +++ b/modules/local/scanpy/readh5/tests/main.nf.test @@ -25,10 +25,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -53,10 +52,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/sample/tests/main.nf.test b/modules/local/scanpy/sample/tests/main.nf.test index 8a4d2d7e..0411e29e 100644 --- a/modules/local/scanpy/sample/tests/main.nf.test +++ b/modules/local/scanpy/sample/tests/main.nf.test @@ -52,10 +52,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -80,10 +79,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } @@ -110,10 +108,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scanpy/umap/tests/main.nf.test b/modules/local/scanpy/umap/tests/main.nf.test index 4b97519b..29676795 100644 --- a/modules/local/scanpy/umap/tests/main.nf.test +++ b/modules/local/scanpy/umap/tests/main.nf.test @@ -27,11 +27,16 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(process.out.h5ad[0][1]).yaml).match() }, - { assert "X_umap" in anndata(process.out.h5ad[0][1]).obsm } - ) + def adata = anndata(process.out.h5ad[0][1]) + + assert process.success + + assert "X_umap" in adata.obsm + + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -56,10 +61,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scimilarity/annotate/tests/main.nf.test b/modules/local/scimilarity/annotate/tests/main.nf.test index 82e0139e..fa0572b7 100644 --- a/modules/local/scimilarity/annotate/tests/main.nf.test +++ b/modules/local/scimilarity/annotate/tests/main.nf.test @@ -36,10 +36,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scimilarity/embed/tests/main.nf.test b/modules/local/scimilarity/embed/tests/main.nf.test index 87c9e70a..a727de54 100644 --- a/modules/local/scimilarity/embed/tests/main.nf.test +++ b/modules/local/scimilarity/embed/tests/main.nf.test @@ -36,10 +36,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/scimilarity/pseudobulk/tests/main.nf.test b/modules/local/scimilarity/pseudobulk/tests/main.nf.test index 8819223e..c36bcada 100644 --- a/modules/local/scimilarity/pseudobulk/tests/main.nf.test +++ b/modules/local/scimilarity/pseudobulk/tests/main.nf.test @@ -30,10 +30,18 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + // one pseudobulk row per unique sample + assert "sample" in obs.colnames + assert n_obs > 0 + } + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -61,10 +69,19 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + // one pseudobulk row per unique sample × leiden combination + assert "sample" in obs.colnames + assert "leiden" in obs.colnames + assert n_obs > 0 + } + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -93,10 +110,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/scimilarity/pseudobulk/tests/main.nf.test.snap b/modules/local/scimilarity/pseudobulk/tests/main.nf.test.snap index f3186b5b..c0848637 100644 --- a/modules/local/scimilarity/pseudobulk/tests/main.nf.test.snap +++ b/modules/local/scimilarity/pseudobulk/tests/main.nf.test.snap @@ -24,9 +24,17 @@ "versions": [ "versions.yml:md5,85681d93adbb062a90bb197b31eea879" ] - } + }, + { + "SCIMILARITY_PSEUDOBULK": { + "anndata": "0.12.10", + "python": "3.12.13", + "scimilarity": "0.4.1" + } + }, + "n_obs: 3\nn_vars: 9887\nobs:\n index: _index\n columns:\n - cells\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - count_nonzero\n - sum\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-20T23:28:46.83306667", + "timestamp": "2026-03-28T17:48:52.497299288", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -57,9 +65,17 @@ "versions": [ "versions.yml:md5,85681d93adbb062a90bb197b31eea879" ] - } + }, + { + "SCIMILARITY_PSEUDOBULK": { + "anndata": "0.12.10", + "python": "3.12.13", + "scimilarity": "0.4.1" + } + }, + "n_obs: 43\nn_vars: 9887\nobs:\n index: _index\n columns:\n - cells\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - count_nonzero\n - sum\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-21T08:56:36.22861983", + "timestamp": "2026-03-28T17:49:47.066833253", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scvitools/scanvi/tests/main.nf.test b/modules/local/scvitools/scanvi/tests/main.nf.test index 94266d43..fd9eb261 100644 --- a/modules/local/scvitools/scanvi/tests/main.nf.test +++ b/modules/local/scvitools/scanvi/tests/main.nf.test @@ -45,9 +45,12 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot( + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "X_emb" in obsm + } + assert snapshot( // Hashes are not stable due to floating point inaccuracies file(process.out.h5ad[0][1]).size(), file(process.out.h5ad[0][1]).name, @@ -55,10 +58,9 @@ nextflow_process { file(process.out.model[0][1]).name, file(process.out.obsm[0]).size(), file(process.out.obsm[0]).name, - process.out.versions + path(process.out.versions[0]).yaml, + adata.yaml ).match() - }, - ) } } @@ -85,10 +87,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/scvitools/scanvi/tests/main.nf.test.snap b/modules/local/scvitools/scanvi/tests/main.nf.test.snap index a7156a3a..a9cc6fcb 100644 --- a/modules/local/scvitools/scanvi/tests/main.nf.test.snap +++ b/modules/local/scvitools/scanvi/tests/main.nf.test.snap @@ -68,11 +68,14 @@ "model.pt", 6118418, "X_test_scanvi.pkl", - [ - "versions.yml:md5,3d5ccecd49a7565e7f6c86996381d8d4" - ] + { + "SCVITOOLS_SCANVI": { + "scvi": "1.3.3" + } + }, + "n_obs: 38234\nn_vars: 100\nobs:\n index: _index\n columns:\n - _scvi_batch\n - _scvi_labels\n - label:scANVI\n - leiden\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\n - X_emb\n - X_pca\nvarm:\n - PCs\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - hvg\n - leiden\n - log1p\n - neighbors\n - pca\n" ], - "timestamp": "2026-03-22T10:00:38.083128488", + "timestamp": "2026-03-28T16:19:18.135819708", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scvitools/scvi/tests/main.nf.test b/modules/local/scvitools/scvi/tests/main.nf.test index f5acff81..e0a8e733 100644 --- a/modules/local/scvitools/scvi/tests/main.nf.test +++ b/modules/local/scvitools/scvi/tests/main.nf.test @@ -29,17 +29,19 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot( + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + with(adata) { + assert "X_emb" in obsm + } + assert snapshot( // Hashes are not stable due to floating point inaccuracies file(process.out.h5ad.get(0).get(1)).size(), file(process.out.model.get(0).get(1)).size(), file(process.out.obsm.get(0)).size(), - process.out.versions + path(process.out.versions[0]).yaml, + adata.yaml ).match() - }, - ) } } @@ -68,10 +70,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/scvitools/scvi/tests/main.nf.test.snap b/modules/local/scvitools/scvi/tests/main.nf.test.snap index c50ddffa..2dfc6a76 100644 --- a/modules/local/scvitools/scvi/tests/main.nf.test.snap +++ b/modules/local/scvitools/scvi/tests/main.nf.test.snap @@ -59,14 +59,17 @@ 18403662, 26244445, 6118418, - [ - "versions.yml:md5,8c1ab0d537dc26cb0c55b4fa49f7dafb" - ] + { + "SCVITOOLS_SCVI": { + "scvi": "1.3.3" + } + }, + "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - _scvi_batch\n - _scvi_labels\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_emb\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-16T20:35:30.494274963", + "timestamp": "2026-03-28T16:17:00.032046985", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/seurat/integration/tests/main.nf.test b/modules/local/seurat/integration/tests/main.nf.test index 522d4087..32af7969 100644 --- a/modules/local/seurat/integration/tests/main.nf.test +++ b/modules/local/seurat/integration/tests/main.nf.test @@ -54,12 +54,15 @@ nextflow_process { } then { - def h5ad = process.out.h5ad[0][1] - assertAll( - { assert process.success }, - { assert snapshot(path(process.out.versions[0]).yaml, anndata(h5ad).yaml).match() }, - { assert "X_emb" in anndata(h5ad).obsm } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + + assert "X_emb" in adata.obsm + + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -81,10 +84,9 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + + assert snapshot(process.out).match() } } diff --git a/modules/local/soupx/tests/main.nf.test b/modules/local/soupx/tests/main.nf.test index bd78b103..2502d275 100644 --- a/modules/local/soupx/tests/main.nf.test +++ b/modules/local/soupx/tests/main.nf.test @@ -29,10 +29,49 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + // output written to X, so no named soupx layer + assert !("ambient_corrected_soupx" in adata.layers) + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() + } + + } + + test("Should write to a custom output layer") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/scrnaseq/h5ad/SRR28679759_filtered_matrix.h5ad', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/scrnaseq/h5ad/SRR28679759_raw_matrix.h5ad', checkIfExists: true) + ] + ) + input[1] = 0.8 + input[2] = "X" + input[3] = "ambient_corrected_soupx" + """ + } + } + + then { + def adata = anndata(process.out.h5ad[0][1]) + assert process.success + assert "ambient_corrected_soupx" in adata.layers + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -61,10 +100,8 @@ nextflow_process { } then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) + assert process.success + assert snapshot(process.out).match() } } diff --git a/modules/local/soupx/tests/main.nf.test.snap b/modules/local/soupx/tests/main.nf.test.snap index 882cb3de..37f83890 100644 --- a/modules/local/soupx/tests/main.nf.test.snap +++ b/modules/local/soupx/tests/main.nf.test.snap @@ -57,12 +57,63 @@ "versions": [ "versions.yml:md5,eebdf63518e672c2ceb40e1bd9c9fbdf" ] - } + }, + { + "SOUPX": { + "r": "4.5.3", + "anndataR": "1.0.2", + "SoupX": "1.6.2", + "Seurat": "5.4.0" + } + }, + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + ], + "timestamp": "2026-03-28T17:53:34.957086995", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } + }, + "Should write to a custom output layer": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_soupX.h5ad:md5,0a5f1e7591e5598537771755d312f35f" + ] + ], + "1": [ + "versions.yml:md5,eebdf63518e672c2ceb40e1bd9c9fbdf" + ], + "h5ad": [ + [ + { + "id": "test" + }, + "test_soupX.h5ad:md5,0a5f1e7591e5598537771755d312f35f" + ] + ], + "versions": [ + "versions.yml:md5,eebdf63518e672c2ceb40e1bd9c9fbdf" + ] + }, + { + "SOUPX": { + "r": "4.5.3", + "anndataR": "1.0.2", + "SoupX": "1.6.2", + "Seurat": "5.4.0" + } + }, + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_soupx\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-17T09:51:41.65597708", + "timestamp": "2026-03-28T17:54:16.513364716", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file From f32147f1c11da981c70b7fc0c13ab4594e09826b Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sat, 28 Mar 2026 19:50:47 +0100 Subject: [PATCH 16/46] Improve subworkflow tests --- .../celltypes/singler/tests/main.nf.test | 47 +- .../celltypes/singler/tests/main.nf.test.snap | 64 ++- .../ambient_correction/tests/main.nf.test | 147 ++++--- .../celltype_assignment/tests/main.nf.test | 10 +- subworkflows/local/cluster/tests/main.nf.test | 54 +-- .../tests/main.nf.test | 22 +- .../tests/main.nf.test.snap | 220 ++++++++-- .../doublet_detection/tests/main.nf.test | 29 +- .../doublet_detection/tests/main.nf.test.snap | 26 +- subworkflows/local/finalize/main.nf | 3 +- .../local/finalize/tests/main.nf.test | 26 +- .../local/finalize/tests/main.nf.test.snap | 156 +++++-- .../local/integrate/tests/main.nf.test | 44 +- .../local/per_group/tests/main.nf.test | 86 +++- .../local/per_group/tests/main.nf.test.snap | 318 ++++++++++++-- .../local/pseudobulking/tests/main.nf.test | 10 +- .../pseudobulking/tests/main.nf.test.snap | 5 +- .../local/quality_control/tests/main.nf.test | 37 +- .../quality_control/tests/main.nf.test.snap | 415 ++++++++++++------ subworkflows/local/singler/tests/main.nf.test | 15 +- .../local/singler/tests/main.nf.test.snap | 56 +-- subworkflows/local/unify/tests/main.nf.test | 75 ++-- .../local/unify/tests/main.nf.test.snap | 74 +++- .../local/unify_genes/tests/main.nf.test | 51 ++- .../local/unify_genes/tests/main.nf.test.snap | 89 +++- 25 files changed, 1555 insertions(+), 524 deletions(-) diff --git a/modules/local/celltypes/singler/tests/main.nf.test b/modules/local/celltypes/singler/tests/main.nf.test index 4523a664..654452da 100644 --- a/modules/local/celltypes/singler/tests/main.nf.test +++ b/modules/local/celltypes/singler/tests/main.nf.test @@ -40,12 +40,20 @@ nextflow_process { } then { + def predictions = path(process.out.obs[0][1]).csv assert process.success + with(predictions) { + assert rowCount > 0 + assert columnNames.any { it.endsWith("labels_test") } + assert columnNames.any { it.endsWith("pruned.labels_test") } + } + assert process.out.distribution.size() == 1 + assert process.out.heatmap.size() == 1 assert snapshot( process.out.obs, file(process.out.distribution[0][1]).name, file(process.out.heatmap[0][1]).name, - process.out.versions + path(process.out.versions[0]).yaml ).match() } @@ -79,12 +87,20 @@ nextflow_process { } then { + def predictions = path(process.out.obs[0][1]).csv assert process.success + with(predictions) { + assert rowCount > 0 + assert columnNames.any { it.endsWith("labels_hpca") } + assert columnNames.any { it.endsWith("pruned.labels_hpca") } + } + assert process.out.distribution.size() == 1 + assert process.out.heatmap.size() == 1 assert snapshot( process.out.obs, file(process.out.distribution[0][1]).name, file(process.out.heatmap[0][1]).name, - process.out.versions + path(process.out.versions[0]).yaml ).match() } @@ -118,12 +134,20 @@ nextflow_process { } then { + def predictions = path(process.out.obs[0][1]).csv assert process.success + with(predictions) { + assert rowCount > 0 + assert columnNames.any { it.endsWith("labels_hpca") } + assert columnNames.any { it.endsWith("pruned.labels_hpca") } + } + assert process.out.distribution.size() == 1 + assert process.out.heatmap.size() == 1 assert snapshot( process.out.obs, file(process.out.distribution[0][1]).name, file(process.out.heatmap[0][1]).name, - process.out.versions + path(process.out.versions[0]).yaml ).match() } @@ -191,13 +215,22 @@ nextflow_process { } then { + def predictions = path(process.out.obs[0][1]).csv assert process.success + with(predictions) { + assert rowCount > 0 + // one set of label columns per reference + assert columnNames.any { it.endsWith("labels_hpca") } + assert columnNames.any { it.endsWith("pruned.labels_hpca") } + assert columnNames.any { it.endsWith("labels_monaco_immune") } + assert columnNames.any { it.endsWith("pruned.labels_monaco_immune") } + } + // one distribution and heatmap pdf per reference + assert process.out.distribution[0][1].size() == 2 + assert process.out.heatmap[0][1].size() == 2 assert snapshot( process.out.obs, - // Cannot capture names because there are multiple files - // file(process.out.distribution[0][1]).name, - // file(process.out.heatmap[0][1]).name, - process.out.versions + path(process.out.versions[0]).yaml ).match() } diff --git a/modules/local/celltypes/singler/tests/main.nf.test.snap b/modules/local/celltypes/singler/tests/main.nf.test.snap index d5fe7716..40e225a1 100644 --- a/modules/local/celltypes/singler/tests/main.nf.test.snap +++ b/modules/local/celltypes/singler/tests/main.nf.test.snap @@ -11,14 +11,20 @@ ], "test_singler_hpca_distribution.pdf", "test_singler_hpca_heatmap.pdf", - [ - "versions.yml:md5,70b80d9d31fab709351b4448a54a0528" - ] + { + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + } + } ], - "timestamp": "2026-03-16T12:37:54.417981638", + "timestamp": "2026-03-28T18:59:53.764238934", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run after celldex reference is fetched": { @@ -33,14 +39,20 @@ ], "test_singler_test_distribution.pdf", "test_singler_test_heatmap.pdf", - [ - "versions.yml:md5,70b80d9d31fab709351b4448a54a0528" - ] + { + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + } + } ], - "timestamp": "2026-03-16T11:40:03.222322422", + "timestamp": "2026-03-28T18:54:39.185673723", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run with a single reference": { @@ -55,14 +67,20 @@ ], "test_singler_hpca_distribution.pdf", "test_singler_hpca_heatmap.pdf", - [ - "versions.yml:md5,70b80d9d31fab709351b4448a54a0528" - ] + { + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + } + } ], - "timestamp": "2026-03-16T12:35:27.022696083", + "timestamp": "2026-03-28T18:57:17.216120097", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run with a single reference - stub": { @@ -140,14 +158,20 @@ "test_singler_predictions.csv:md5,11a52bcaca3f7e8ad88a9fe7d26b49c5" ] ], - [ - "versions.yml:md5,70b80d9d31fab709351b4448a54a0528" - ] + { + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + } + } ], - "timestamp": "2026-03-16T12:40:51.446458814", + "timestamp": "2026-03-28T19:03:07.666721816", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/subworkflows/local/ambient_correction/tests/main.nf.test b/subworkflows/local/ambient_correction/tests/main.nf.test index 53b8ab05..3a3df23d 100644 --- a/subworkflows/local/ambient_correction/tests/main.nf.test +++ b/subworkflows/local/ambient_correction/tests/main.nf.test @@ -28,10 +28,12 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, workflow.out.h5ad.size()).match() } - ) + assert workflow.success + assert workflow.out.h5ad.size() == 1 + assert snapshot( + workflow.out.versions, + workflow.out.h5ad.size() + ).match() } } @@ -83,10 +85,12 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, workflow.out.h5ad.size()).match() } - ) + assert workflow.success + assert workflow.out.h5ad.size() == 1 + assert snapshot( + workflow.out.versions, + workflow.out.h5ad.size() + ).match() } } @@ -112,12 +116,15 @@ nextflow_workflow { } then { - def h5ad = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, - { assert "ambient_corrected_decontx" in anndata(h5ad).layers } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + + assert "ambient_corrected_decontx" in adata.layers + + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -143,12 +150,15 @@ nextflow_workflow { } then { - def h5ad = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, - { assert "ambient_corrected_decontx" in anndata(h5ad).layers } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + + assert "ambient_corrected_decontx" in adata.layers + + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -174,12 +184,15 @@ nextflow_workflow { } then { - def h5ad = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, - { assert "ambient_corrected_soupx" in anndata(h5ad).layers } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + + assert "ambient_corrected_soupx" in adata.layers + + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -206,12 +219,15 @@ nextflow_workflow { } then { - def h5ad = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, - { assert "ambient_corrected_scar" in anndata(h5ad).layers } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + + assert "ambient_corrected_scar" in adata.layers + + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -237,12 +253,15 @@ nextflow_workflow { } then { - def h5ad = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, - { assert "ambient_corrected_cellbender" in anndata(h5ad).layers } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + + assert "ambient_corrected_cellbender" in adata.layers + + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -268,11 +287,14 @@ nextflow_workflow { } then { - def h5ad = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + // output written to X, so no named decontx layer + assert !("ambient_corrected_decontx" in adata.layers) + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -298,11 +320,14 @@ nextflow_workflow { } then { - def h5ad = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + // output written to X, so no named soupx layer + assert !("ambient_corrected_soupx" in adata.layers) + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -329,11 +354,14 @@ nextflow_workflow { } then { - def h5ad = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + // output written to X, so no named scar layer + assert !("ambient_corrected_scar" in adata.layers) + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -359,11 +387,14 @@ nextflow_workflow { } then { - def h5ad = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + // output written to X, so no named cellbender layer + assert !("ambient_corrected_cellbender" in adata.layers) + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } diff --git a/subworkflows/local/celltype_assignment/tests/main.nf.test b/subworkflows/local/celltype_assignment/tests/main.nf.test index 8e29d55e..50a0bb48 100644 --- a/subworkflows/local/celltype_assignment/tests/main.nf.test +++ b/subworkflows/local/celltype_assignment/tests/main.nf.test @@ -29,10 +29,12 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, workflow.out.obs.size()).match() } - ) + assert workflow.success + assert workflow.out.obs.size() >= 1 + assert snapshot( + workflow.out.versions, + workflow.out.obs.size() + ).match() } } diff --git a/subworkflows/local/cluster/tests/main.nf.test b/subworkflows/local/cluster/tests/main.nf.test index 62a8fd4e..ed090f72 100644 --- a/subworkflows/local/cluster/tests/main.nf.test +++ b/subworkflows/local/cluster/tests/main.nf.test @@ -64,20 +64,20 @@ nextflow_workflow { then { assert workflow.success - assert snapshot(workflow.out.versions).match() workflow.out.h5ad_neighbors.each { meta, h5ad -> - def ad = anndata(h5ad) - assert ad.obsm.any { it.endsWith("_umap") } - assert "connectivities" in ad.obsp - assert "distances" in ad.obsp + def adata = anndata(h5ad) + with(adata) { + assert obsm.any { it.endsWith("_umap") } + assert "connectivities" in obsp + assert "distances" in obsp + } } workflow.out.h5ad_clustering.each { meta, h5ad -> - def obs = anndata(h5ad).obs + def adata = anndata(h5ad) def key = meta.id + "_leiden" - assert key in obs.colnames : "Expected ${key} in obs, found: ${obs.colnames}" - def n = obs.get(key).n_unique() - assert n >= 2 && n <= 50 : "Expected 2–50 clusters for ${key}, got ${n}" + assert key in adata.obs.colnames } + assert snapshot(workflow.out.versions).match() } } @@ -139,20 +139,20 @@ nextflow_workflow { then { assert workflow.success - assert snapshot(workflow.out.versions).match() workflow.out.h5ad_neighbors.each { meta, h5ad -> - def ad = anndata(h5ad) - assert ad.obsm.any { it.endsWith("_umap") } - assert "connectivities" in ad.obsp - assert "distances" in ad.obsp + def adata = anndata(h5ad) + with(adata) { + assert obsm.any { it.endsWith("_umap") } + assert "connectivities" in obsp + assert "distances" in obsp + } } workflow.out.h5ad_clustering.each { meta, h5ad -> - def obs = anndata(h5ad).obs + def adata = anndata(h5ad) def key = meta.id + "_leiden" - assert key in obs.colnames : "Expected ${key} in obs, found: ${obs.colnames}" - def n = obs.get(key).n_unique() - assert n >= 2 && n <= 50 : "Expected 2–50 clusters for ${key}, got ${n}" + assert key in adata.obs.colnames } + assert snapshot(workflow.out.versions).match() } } @@ -214,20 +214,20 @@ nextflow_workflow { then { assert workflow.success - assert snapshot(workflow.out.versions).match() workflow.out.h5ad_neighbors.each { meta, h5ad -> - def ad = anndata(h5ad) - assert ad.obsm.any { it.endsWith("_umap") } - assert "connectivities" in ad.obsp - assert "distances" in ad.obsp + def adata = anndata(h5ad) + with(adata) { + assert obsm.any { it.endsWith("_umap") } + assert "connectivities" in obsp + assert "distances" in obsp + } } workflow.out.h5ad_clustering.each { meta, h5ad -> - def obs = anndata(h5ad).obs + def adata = anndata(h5ad) def key = meta.id + "_leiden" - assert key in obs.colnames - def n = obs.get(key).n_unique() - assert n >= 2 && n <= 50 : "Expected 2–50 clusters for ${key}, got ${n}" + assert key in adata.obs.colnames } + assert snapshot(workflow.out.versions).match() } } diff --git a/subworkflows/local/differential_expression/tests/main.nf.test b/subworkflows/local/differential_expression/tests/main.nf.test index f94b4ff0..4ca191e9 100644 --- a/subworkflows/local/differential_expression/tests/main.nf.test +++ b/subworkflows/local/differential_expression/tests/main.nf.test @@ -24,10 +24,13 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, workflow.out.uns.size(), workflow.out.multiqc_files.size()).match() } - ) + assert workflow.success + assert workflow.out.uns.size() >= 1 + assert workflow.out.multiqc_files.size() >= 1 + assert workflow.out.uns.any { file(it).name.endsWith("_characteristic_genes.pkl") } + assert snapshot( + workflow.out.versions.collect { path(it).yaml } + ).match() } } @@ -49,10 +52,13 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, workflow.out.uns.size(), workflow.out.multiqc_files.size()).match() } - ) + assert workflow.success + assert workflow.out.uns.size() >= 1 + assert workflow.out.multiqc_files.size() >= 1 + assert workflow.out.uns.any { file(it).name.endsWith("_characteristic_genes.pkl") } + assert snapshot( + workflow.out.versions.collect { path(it).yaml } + ).match() } } diff --git a/subworkflows/local/differential_expression/tests/main.nf.test.snap b/subworkflows/local/differential_expression/tests/main.nf.test.snap index 95ceb00a..dd314882 100644 --- a/subworkflows/local/differential_expression/tests/main.nf.test.snap +++ b/subworkflows/local/differential_expression/tests/main.nf.test.snap @@ -2,27 +2,121 @@ "Should run differential expression with leiden clustering": { "content": [ [ - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" - ], - 16, - 16 + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + } + ] ], - "timestamp": "2026-03-25T15:46:36.932593016", + "timestamp": "2026-03-28T19:42:40.224566991", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -31,21 +125,79 @@ "Should run differential expression with label column": { "content": [ [ - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934", - "versions.yml:md5,c4e56a7a79e312d6f945d4913899b934" - ], - 10, - 10 + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + } + ] ], - "timestamp": "2026-03-25T15:48:05.790450423", + "timestamp": "2026-03-28T19:43:40.510185657", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/doublet_detection/tests/main.nf.test b/subworkflows/local/doublet_detection/tests/main.nf.test index 26fb4f2b..fc745f68 100644 --- a/subworkflows/local/doublet_detection/tests/main.nf.test +++ b/subworkflows/local/doublet_detection/tests/main.nf.test @@ -28,10 +28,8 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert workflow.trace.tasks().size() == 0 } - ) + assert workflow.success + assert workflow.trace.tasks().size() == 0 } } @@ -58,14 +56,15 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert anndata(workflow.out.h5ad[0][1]).n_obs > 5960 }, - { assert anndata(workflow.out.h5ad[0][1]).n_obs < 5985 }, - { assert snapshot( - workflow.out.versions, - ).match() } - ) + def adata = anndata(workflow.out.h5ad[0][1]) + + assert workflow.success + assert adata.n_obs > 5960 + assert adata.n_obs < 5985 + assert snapshot( + workflow.out.versions.collect { path(it).yaml }, + adata.yaml + ).match() } } @@ -93,10 +92,8 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out).match() } - ) + assert workflow.success + assert snapshot(workflow.out).match() } } diff --git a/subworkflows/local/doublet_detection/tests/main.nf.test.snap b/subworkflows/local/doublet_detection/tests/main.nf.test.snap index 38974f8e..e1e7e74f 100644 --- a/subworkflows/local/doublet_detection/tests/main.nf.test.snap +++ b/subworkflows/local/doublet_detection/tests/main.nf.test.snap @@ -2,14 +2,28 @@ "Should run with all methods except doubletdetection": { "content": [ [ - "versions.yml:md5,09080fed8361c8fcf41d5527c339deed", - "versions.yml:md5,413d1a693de9ab89500219638de87ee2" - ] + { + "DOUBLET_DETECTION:DOUBLET_REMOVAL": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "pandas": "2.3.3", + "python": "3.13.12", + "upsetplot": "0.9.0" + } + }, + { + "DOUBLET_DETECTION:SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + } + } + ], + "n_obs: 5968\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-24T20:24:53.973965", + "timestamp": "2026-03-28T19:43:37.850974576", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures - stub": { diff --git a/subworkflows/local/finalize/main.nf b/subworkflows/local/finalize/main.nf index 4771260d..8aa2a5bf 100644 --- a/subworkflows/local/finalize/main.nf +++ b/subworkflows/local/finalize/main.nf @@ -40,5 +40,6 @@ workflow FINALIZE { } emit: - versions = ch_versions // channel: [ versions.yml ] + h5ad = ADATA_EXTEND.out.h5ad // channel: [ meta, h5ad ] + versions = ch_versions // channel: [ versions.yml ] } diff --git a/subworkflows/local/finalize/tests/main.nf.test b/subworkflows/local/finalize/tests/main.nf.test index b6fea76a..3e96f1fc 100644 --- a/subworkflows/local/finalize/tests/main.nf.test +++ b/subworkflows/local/finalize/tests/main.nf.test @@ -63,8 +63,18 @@ nextflow_workflow { } then { + def adata = anndata(workflow.out.h5ad[0][1]) assert workflow.success - assert snapshot(workflow.out).match() + with(adata) { + assert "scvi-global-1.0_leiden" in obs.colnames + assert "X_scvi" in obsm + assert "scvi-global-1.0_paga" in uns + } + assert snapshot( + workflow.out.h5ad, + workflow.out.versions.collect { path(it).yaml }, + adata.yaml + ).match() } } @@ -125,8 +135,13 @@ nextflow_workflow { } then { + def adata = anndata(workflow.out.h5ad[0][1]) assert workflow.success - assert snapshot(workflow.out).match() + assert snapshot( + workflow.out.h5ad, + workflow.out.versions.collect { path(it).yaml }, + adata.yaml + ).match() } } @@ -193,8 +208,13 @@ nextflow_workflow { } then { + def adata = anndata(workflow.out.h5ad[0][1]) assert workflow.success - assert snapshot(workflow.out).match() + assert snapshot( + workflow.out.h5ad, + workflow.out.versions.collect { path(it).yaml }, + adata.yaml + ).match() } } diff --git a/subworkflows/local/finalize/tests/main.nf.test.snap b/subworkflows/local/finalize/tests/main.nf.test.snap index 31d1939a..56337559 100644 --- a/subworkflows/local/finalize/tests/main.nf.test.snap +++ b/subworkflows/local/finalize/tests/main.nf.test.snap @@ -1,18 +1,32 @@ { "Should run without failures - with fragments": { "content": [ - { - "0": [ - "versions.yml:md5,cbeebeb2116035eeb1a2c11972c74d79", - "versions.yml:md5,fe9c91eed91a74cf24e85fd6f7c3932c" - ], - "versions": [ - "versions.yml:md5,cbeebeb2116035eeb1a2c11972c74d79", - "versions.yml:md5,fe9c91eed91a74cf24e85fd6f7c3932c" + [ + [ + { + "id": "test" + }, + "test.h5ad:md5,88250dce39d3ebc42b13639bb9a9bc81" ] - } + ], + [ + { + "FINALIZE:ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + } + }, + { + "FINALIZE:ADATA_TORDS": { + "anndataR": "1.0.2" + } + } + ], + "n_obs: 23373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - celltypist:Adult_Human_Skin\n - celltypist:Adult_Human_Skin:conf\n - label\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - sample_original\n - scvi-global-1.0_leiden\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_scvi\nvarm:\nobsp:\nvarp:\nuns:\n - scvi-global-1.0_paga\n" ], - "timestamp": "2026-03-17T22:18:57.499343763", + "timestamp": "2026-03-28T18:21:52.014648621", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -20,20 +34,40 @@ }, "Should run without failures - with prep_cellxgene": { "content": [ - { - "0": [ - "versions.yml:md5,1e7c2d22af9afd605d7fdc65a5ece3b7", - "versions.yml:md5,cbeebeb2116035eeb1a2c11972c74d79", - "versions.yml:md5,fe9c91eed91a74cf24e85fd6f7c3932c" - ], - "versions": [ - "versions.yml:md5,1e7c2d22af9afd605d7fdc65a5ece3b7", - "versions.yml:md5,cbeebeb2116035eeb1a2c11972c74d79", - "versions.yml:md5,fe9c91eed91a74cf24e85fd6f7c3932c" + [ + [ + { + "id": "test" + }, + "test.h5ad:md5,f1586170686d73b8143e95aad0f331ce" ] - } + ], + [ + { + "FINALIZE:ADATA_PREPCELLXGENE": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "FINALIZE:ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + } + }, + { + "FINALIZE:ADATA_TORDS": { + "anndataR": "1.0.2" + } + } + ], + "n_obs: 23373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - celltypist:Adult_Human_Skin\n - celltypist:Adult_Human_Skin:conf\n - label\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - sample_original\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-17T22:20:50.85306115", + "timestamp": "2026-03-28T18:23:22.810706464", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -43,54 +77,100 @@ "content": [ { "0": [ + [ + { + "id": "test" + }, + "test.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ], + "h5ad": [ + [ + { + "id": "test" + }, + "test.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], "versions": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ] } ], - "timestamp": "2026-01-16T22:46:55.506826803", + "timestamp": "2026-03-28T18:21:21.411777638", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures - no fragments - stub": { "content": [ { "0": [ + [ + { + "id": "test" + }, + "test.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ], + "h5ad": [ + [ + { + "id": "test" + }, + "test.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], "versions": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ] } ], - "timestamp": "2026-01-16T22:47:50.084502894", + "timestamp": "2026-03-28T18:22:08.331764694", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures - no fragments": { "content": [ - { - "0": [ - "versions.yml:md5,cbeebeb2116035eeb1a2c11972c74d79", - "versions.yml:md5,fe9c91eed91a74cf24e85fd6f7c3932c" - ], - "versions": [ - "versions.yml:md5,cbeebeb2116035eeb1a2c11972c74d79", - "versions.yml:md5,fe9c91eed91a74cf24e85fd6f7c3932c" + [ + [ + { + "id": "test" + }, + "test.h5ad:md5,f1586170686d73b8143e95aad0f331ce" ] - } + ], + [ + { + "FINALIZE:ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + } + }, + { + "FINALIZE:ADATA_TORDS": { + "anndataR": "1.0.2" + } + } + ], + "n_obs: 23373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - celltypist:Adult_Human_Skin\n - celltypist:Adult_Human_Skin:conf\n - label\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - sample_original\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-17T22:19:50.750328034", + "timestamp": "2026-03-28T18:22:37.732852134", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/integrate/tests/main.nf.test b/subworkflows/local/integrate/tests/main.nf.test index 8512108d..537e9bbf 100644 --- a/subworkflows/local/integrate/tests/main.nf.test +++ b/subworkflows/local/integrate/tests/main.nf.test @@ -67,12 +67,13 @@ nextflow_workflow { } then { - def h5ad = workflow.out.integrations[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, - { assert "X_emb" in anndata(h5ad).obsm } - ) + def adata = anndata(workflow.out.integrations[0][1]) + assert workflow.success + assert "X_emb" in adata.obsm + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -137,13 +138,17 @@ nextflow_workflow { } then { - def h5ad = workflow.out.integrations[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, - { assert "connectivities" in anndata(h5ad).obsp }, - { assert "distances" in anndata(h5ad).obsp } - ) + def adata = anndata(workflow.out.integrations[0][1]) + assert workflow.success + with(adata) { + assert "X_pca" in obsm + assert "connectivities" in obsp + assert "distances" in obsp + } + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } @@ -208,12 +213,13 @@ nextflow_workflow { } then { - def h5ad = workflow.out.integrations[0][1] - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, anndata(h5ad).yaml).match() }, - { assert "X_emb" in anndata(h5ad).obsm } - ) + def adata = anndata(workflow.out.integrations[0][1]) + assert workflow.success + assert "X_emb" in adata.obsm + assert snapshot( + workflow.out.versions, + adata.yaml + ).match() } } diff --git a/subworkflows/local/per_group/tests/main.nf.test b/subworkflows/local/per_group/tests/main.nf.test index 581fb2cc..0e07b0e9 100644 --- a/subworkflows/local/per_group/tests/main.nf.test +++ b/subworkflows/local/per_group/tests/main.nf.test @@ -7,6 +7,36 @@ nextflow_workflow { tag "subworkflows" tag "subworkflows_local" + test("Should run without failures - PAGA only - stub") { + + options '-stub' + + when { + params { + outdir = "$outputDir" + skip_liana = true + skip_rankgenesgroups = true + } + workflow { + """ + input[0] = channel.of([ + [id: 'test', obs_key: 'leiden', condition_col: 'condition'], + file(params.pipelines_testdata_base_path + '/pbmc/with_label_and_condition_pca.h5ad', checkIfExists: true) + ]) + input[1] = channel.empty() + input[2] = true + input[3] = true + """ + } + } + + then { + assert workflow.success + assert snapshot(workflow.out).match() + } + + } + test("Should run without failures - PAGA only") { when { @@ -29,10 +59,45 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, workflow.out.uns.size(), workflow.out.multiqc_files.size()).match() } - ) + assert workflow.success + // PAGA produces exactly one uns pkl + assert workflow.out.uns.size() == 1 + assert workflow.out.uns.any { file(it).name == "test_paga.pkl" } + assert workflow.out.multiqc_files.size() == 1 + assert snapshot( + workflow.out.versions.collect { path(it).yaml } + ).match() + } + + } + + test("Should run without failures - full run - stub") { + + options '-stub' + + when { + params { + outdir = "$outputDir" + skip_liana = false + skip_rankgenesgroups = false + } + workflow { + """ + def h5ad = channel.of([ + [id: 'test', obs_key: 'leiden', condition_col: 'condition'], + file(params.pipelines_testdata_base_path + '/pbmc/with_label_and_condition_pca.h5ad', checkIfExists: true) + ]) + input[0] = h5ad + input[1] = h5ad + input[2] = false + input[3] = false + """ + } + } + + then { + assert workflow.success + assert snapshot(workflow.out).match() } } @@ -60,10 +125,15 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { assert snapshot(workflow.out.versions, workflow.out.uns.size(), workflow.out.multiqc_files.size()).match() } - ) + assert workflow.success + // PAGA + LIANA + RANKGENESGROUPS all produce uns pkls + assert workflow.out.uns.size() >= 1 + assert workflow.out.uns.any { file(it).name == "test_paga.pkl" } + assert workflow.out.uns.any { file(it).name == "test_liana.pkl" } + assert workflow.out.multiqc_files.size() >= 1 + assert snapshot( + workflow.out.versions.collect { path(it).yaml } + ).match() } } diff --git a/subworkflows/local/per_group/tests/main.nf.test.snap b/subworkflows/local/per_group/tests/main.nf.test.snap index 38d30e33..370f7df9 100644 --- a/subworkflows/local/per_group/tests/main.nf.test.snap +++ b/subworkflows/local/per_group/tests/main.nf.test.snap @@ -2,12 +2,44 @@ "Should run without failures - PAGA only": { "content": [ [ - "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" - ], - 1, - 1 + { + "PER_GROUP:SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + } + } + ] ], - "timestamp": "2026-03-25T16:10:11.679192446", + "timestamp": "2026-03-28T18:31:51.294256583", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } + }, + "Should run without failures - PAGA only - stub": { + "content": [ + { + "0": [ + "test_paga.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "1": [ + "test_paga_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "2": [ + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "multiqc_files": [ + "test_paga_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "uns": [ + "test_paga.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "versions": [ + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + } + ], + "timestamp": "2026-03-28T18:27:44.794170345", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -16,29 +48,261 @@ "Should run without failures - full run": { "content": [ [ - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,1a9c1aa04f881610ab37fe0d8c9c9cb1", - "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd", - "versions.yml:md5,7d65ff4a31af5f58251f2f57320c8c94" - ], - 18, - 17 + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "PER_GROUP:DIFFERENTIAL_EXPRESSION:SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" + }, + { + "PER_GROUP:SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + } + } + ] + ], + "timestamp": "2026-03-28T18:29:59.302941687", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } + }, + "Should run without failures - full run - stub": { + "content": [ + { + "0": [ + "condition:leiden:0_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:10_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:11_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:1_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:2_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:3_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:4_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:5_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:6_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:7_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:8_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:9_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Disease_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Healthy_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Treated_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_liana.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_paga.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "1": [ + "condition:leiden:0_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:10_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:11_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:1_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:2_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:3_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:4_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:5_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:6_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:7_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:8_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:9_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Disease_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Treated_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_paga_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "2": [ + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "multiqc_files": [ + "condition:leiden:0_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:10_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:11_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:1_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:2_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:3_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:4_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:5_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:6_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:7_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:8_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:9_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Disease_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Healthy_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Treated_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden_characteristic_genes_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_paga_mqc.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "uns": [ + "condition:leiden:0_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:10_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:11_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:1_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:2_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:3_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:4_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:5_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:6_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:7_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:8_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "condition:leiden:9_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Disease_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Healthy_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden:condition:Treated_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "leiden_characteristic_genes.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_liana.pkl:md5,d41d8cd98f00b204e9800998ecf8427e", + "test_paga.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "versions": [ + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + } ], - "timestamp": "2026-03-25T16:12:47.770237258", + "timestamp": "2026-03-28T18:28:27.393037698", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/pseudobulking/tests/main.nf.test b/subworkflows/local/pseudobulking/tests/main.nf.test index 37c2a3a9..c5ae36cc 100644 --- a/subworkflows/local/pseudobulking/tests/main.nf.test +++ b/subworkflows/local/pseudobulking/tests/main.nf.test @@ -28,8 +28,16 @@ nextflow_workflow { } then { + def adata = anndata(workflow.out.h5ad_pseudobulk[0][1]) assert workflow.success - assert snapshot(workflow.out).match() + with(adata) { + assert "sample" in obs.colnames + assert n_obs > 0 + } + assert snapshot( + workflow.out, + adata.yaml + ).match() } } diff --git a/subworkflows/local/pseudobulking/tests/main.nf.test.snap b/subworkflows/local/pseudobulking/tests/main.nf.test.snap index eee8a9c3..14cb70f8 100644 --- a/subworkflows/local/pseudobulking/tests/main.nf.test.snap +++ b/subworkflows/local/pseudobulking/tests/main.nf.test.snap @@ -57,9 +57,10 @@ "versions": [ "versions.yml:md5,7629f78da2c667f7f5975f67b4cc521c" ] - } + }, + "n_obs: 3\nn_vars: 9887\nobs:\n index: _index\n columns:\n - cells\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - count_nonzero\n - sum\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-22T16:29:32.242181196", + "timestamp": "2026-03-28T18:09:14.725182453", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/quality_control/tests/main.nf.test b/subworkflows/local/quality_control/tests/main.nf.test index 6c58839f..126f77b2 100644 --- a/subworkflows/local/quality_control/tests/main.nf.test +++ b/subworkflows/local/quality_control/tests/main.nf.test @@ -41,7 +41,12 @@ nextflow_workflow { then { assert workflow.success - assert snapshot(workflow.out).match() + // sample is fully filtered out by SCANPY_FILTER quality thresholds + assert workflow.out.h5ad.size() == 0 + assert snapshot( + workflow.out.multiqc_files, + workflow.out.versions.collect { path(it).yaml } + ).match() } } @@ -81,7 +86,12 @@ nextflow_workflow { then { assert workflow.success - assert snapshot(workflow.out).match() + // sample is fully filtered out by SCANPY_FILTER quality thresholds + assert workflow.out.h5ad.size() == 0 + assert snapshot( + workflow.out.multiqc_files, + workflow.out.versions.collect { path(it).yaml } + ).match() } } @@ -119,12 +129,22 @@ nextflow_workflow { } then { + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + with(adata) { + assert "pct_counts_mt" in obs.colnames + assert "batch" in obs.colnames + assert "label" in obs.colnames + assert "condition" in obs.colnames + assert "sample" in obs.colnames + } assert snapshot( workflow.out.multiqc_files, - workflow.out.versions, - anndata(workflow.out.h5ad[0][1]).n_obs, - anndata(workflow.out.h5ad[0][1]).n_vars + workflow.out.versions.collect { path(it).yaml }, + adata.n_obs, + adata.n_vars, + adata.yaml ).match() } @@ -205,7 +225,12 @@ nextflow_workflow { then { assert workflow.success - assert snapshot(workflow.out).match() + // sample is fully filtered out by SCANPY_FILTER quality thresholds + assert workflow.out.h5ad.size() == 0 + assert snapshot( + workflow.out.multiqc_files, + workflow.out.versions.collect { path(it).yaml } + ).match() } } diff --git a/subworkflows/local/quality_control/tests/main.nf.test.snap b/subworkflows/local/quality_control/tests/main.nf.test.snap index 0a5af692..ae1b3188 100644 --- a/subworkflows/local/quality_control/tests/main.nf.test.snap +++ b/subworkflows/local/quality_control/tests/main.nf.test.snap @@ -1,50 +1,67 @@ { "Should run without ambient RNA removal and doublet detection": { "content": [ - { - "0": [ - - ], - "1": [ - - ], - "2": [ - "sizes_mqc.json:md5,756ad6aae0f322aadfac95c2b38fcef2", - "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" - ], - "3": [ - "versions.yml:md5,09337464bba597568401c441bedb9b61", - "versions.yml:md5,53938cd26fe63616cc4524da4b6062c5", - "versions.yml:md5,5ce128aab0a55bc373e4a4f1c945a603", - "versions.yml:md5,88b8f8687e69ee5ccecf75b7e6845176", - "versions.yml:md5,c4bcd7799f794fb7a2ab6b9a32d346f9", - "versions.yml:md5,d5b598692c585148c4d3027bc296f6fd", - "versions.yml:md5,e10aa3cdeade2300701438cb1bc47b29", - "versions.yml:md5,e98df7a38d5622b937cdabcf7dd7a7d4" - ], - "h5ad": [ - - ], - "multiqc_files": [ - "sizes_mqc.json:md5,756ad6aae0f322aadfac95c2b38fcef2", - "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" - ], - "obs": [ - - ], - "versions": [ - "versions.yml:md5,09337464bba597568401c441bedb9b61", - "versions.yml:md5,53938cd26fe63616cc4524da4b6062c5", - "versions.yml:md5,5ce128aab0a55bc373e4a4f1c945a603", - "versions.yml:md5,88b8f8687e69ee5ccecf75b7e6845176", - "versions.yml:md5,c4bcd7799f794fb7a2ab6b9a32d346f9", - "versions.yml:md5,d5b598692c585148c4d3027bc296f6fd", - "versions.yml:md5,e10aa3cdeade2300701438cb1bc47b29", - "versions.yml:md5,e98df7a38d5622b937cdabcf7dd7a7d4" - ] - } + [ + "sizes_mqc.json:md5,756ad6aae0f322aadfac95c2b38fcef2", + "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" + ], + [ + { + "QUALITY_CONTROL:SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "QUALITY_CONTROL:GET_UNFILTERED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:QC_RAW": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "QUALITY_CONTROL:GET_FILTERED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:GET_THRESHOLDED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:UNIFY:ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "QUALITY_CONTROL:UNIFY:UPSET_GENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + } + }, + { + "QUALITY_CONTROL:COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + } + } + ] ], - "timestamp": "2026-03-22T17:47:36.928267661", + "timestamp": "2026-03-28T19:42:23.484650804", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -52,50 +69,67 @@ }, "Should run without ambient RNA removal and doublet detection, but with custom mito genes": { "content": [ - { - "0": [ - - ], - "1": [ - - ], - "2": [ - "sizes_mqc.json:md5,756ad6aae0f322aadfac95c2b38fcef2", - "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" - ], - "3": [ - "versions.yml:md5,09337464bba597568401c441bedb9b61", - "versions.yml:md5,53938cd26fe63616cc4524da4b6062c5", - "versions.yml:md5,5ce128aab0a55bc373e4a4f1c945a603", - "versions.yml:md5,88b8f8687e69ee5ccecf75b7e6845176", - "versions.yml:md5,c4bcd7799f794fb7a2ab6b9a32d346f9", - "versions.yml:md5,d5b598692c585148c4d3027bc296f6fd", - "versions.yml:md5,e10aa3cdeade2300701438cb1bc47b29", - "versions.yml:md5,e98df7a38d5622b937cdabcf7dd7a7d4" - ], - "h5ad": [ - - ], - "multiqc_files": [ - "sizes_mqc.json:md5,756ad6aae0f322aadfac95c2b38fcef2", - "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" - ], - "obs": [ - - ], - "versions": [ - "versions.yml:md5,09337464bba597568401c441bedb9b61", - "versions.yml:md5,53938cd26fe63616cc4524da4b6062c5", - "versions.yml:md5,5ce128aab0a55bc373e4a4f1c945a603", - "versions.yml:md5,88b8f8687e69ee5ccecf75b7e6845176", - "versions.yml:md5,c4bcd7799f794fb7a2ab6b9a32d346f9", - "versions.yml:md5,d5b598692c585148c4d3027bc296f6fd", - "versions.yml:md5,e10aa3cdeade2300701438cb1bc47b29", - "versions.yml:md5,e98df7a38d5622b937cdabcf7dd7a7d4" - ] - } + [ + "sizes_mqc.json:md5,756ad6aae0f322aadfac95c2b38fcef2", + "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" + ], + [ + { + "QUALITY_CONTROL:SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "QUALITY_CONTROL:GET_UNFILTERED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:QC_RAW": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "QUALITY_CONTROL:GET_FILTERED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:GET_THRESHOLDED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:UNIFY:ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "QUALITY_CONTROL:UNIFY:UPSET_GENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + } + }, + { + "QUALITY_CONTROL:COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + } + } + ] ], - "timestamp": "2026-03-22T17:49:49.029435332", + "timestamp": "2026-03-28T19:43:09.6069317", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -198,24 +232,100 @@ "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" ], [ - "versions.yml:md5,09337464bba597568401c441bedb9b61", - "versions.yml:md5,2a595c6f30f1d3a0217f04cc2ffdf4de", - "versions.yml:md5,36d44f6713879308f604b5387983c640", - "versions.yml:md5,3c7417bff601859a86cdcb86fa6bfcb3", - "versions.yml:md5,53938cd26fe63616cc4524da4b6062c5", - "versions.yml:md5,5ce128aab0a55bc373e4a4f1c945a603", - "versions.yml:md5,88b8f8687e69ee5ccecf75b7e6845176", - "versions.yml:md5,8a904ed120b0307240c5a2ebe6dc34f8", - "versions.yml:md5,8cbafef2498da69040e524cc42260989", - "versions.yml:md5,c4bcd7799f794fb7a2ab6b9a32d346f9", - "versions.yml:md5,d5b598692c585148c4d3027bc296f6fd", - "versions.yml:md5,e10aa3cdeade2300701438cb1bc47b29", - "versions.yml:md5,e98df7a38d5622b937cdabcf7dd7a7d4" + { + "QUALITY_CONTROL:SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "QUALITY_CONTROL:AMBIENT_CORRECTION:CELDA_DECONTX": { + "r": "4.5.3", + "anndataR": "1.0.2", + "celda": "1.26.0" + } + }, + { + "QUALITY_CONTROL:DOUBLET_DETECTION:DOUBLET_REMOVAL": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "pandas": "2.3.3", + "python": "3.13.12", + "upsetplot": "0.9.0" + } + }, + { + "QUALITY_CONTROL:GET_DEDOUBLETED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:GET_UNFILTERED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:QC_RAW": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "QUALITY_CONTROL:GET_FILTERED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:DOUBLET_DETECTION:SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + } + }, + { + "QUALITY_CONTROL:QC_FILTERED": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "QUALITY_CONTROL:GET_THRESHOLDED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:UNIFY:ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "QUALITY_CONTROL:UNIFY:UPSET_GENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + } + }, + { + "QUALITY_CONTROL:COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + } + } ], 12939, - 9887 + 9887, + "n_obs: 12939\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - sample_original\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - mean_counts\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-22T17:57:09.098006399", + "timestamp": "2026-03-28T19:46:31.986728169", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -223,50 +333,67 @@ }, "Should run with cell cycle scoring": { "content": [ - { - "0": [ - - ], - "1": [ - - ], - "2": [ - "sizes_mqc.json:md5,756ad6aae0f322aadfac95c2b38fcef2", - "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" - ], - "3": [ - "versions.yml:md5,09337464bba597568401c441bedb9b61", - "versions.yml:md5,53938cd26fe63616cc4524da4b6062c5", - "versions.yml:md5,5ce128aab0a55bc373e4a4f1c945a603", - "versions.yml:md5,88b8f8687e69ee5ccecf75b7e6845176", - "versions.yml:md5,c4bcd7799f794fb7a2ab6b9a32d346f9", - "versions.yml:md5,d5b598692c585148c4d3027bc296f6fd", - "versions.yml:md5,e10aa3cdeade2300701438cb1bc47b29", - "versions.yml:md5,e98df7a38d5622b937cdabcf7dd7a7d4" - ], - "h5ad": [ - - ], - "multiqc_files": [ - "sizes_mqc.json:md5,756ad6aae0f322aadfac95c2b38fcef2", - "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" - ], - "obs": [ - - ], - "versions": [ - "versions.yml:md5,09337464bba597568401c441bedb9b61", - "versions.yml:md5,53938cd26fe63616cc4524da4b6062c5", - "versions.yml:md5,5ce128aab0a55bc373e4a4f1c945a603", - "versions.yml:md5,88b8f8687e69ee5ccecf75b7e6845176", - "versions.yml:md5,c4bcd7799f794fb7a2ab6b9a32d346f9", - "versions.yml:md5,d5b598692c585148c4d3027bc296f6fd", - "versions.yml:md5,e10aa3cdeade2300701438cb1bc47b29", - "versions.yml:md5,e98df7a38d5622b937cdabcf7dd7a7d4" - ] - } + [ + "sizes_mqc.json:md5,756ad6aae0f322aadfac95c2b38fcef2", + "test_raw_mqc.json:md5,1892d1a9408417050623e6bc2c2480a3" + ], + [ + { + "QUALITY_CONTROL:SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "QUALITY_CONTROL:GET_UNFILTERED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:QC_RAW": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "QUALITY_CONTROL:GET_FILTERED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:GET_THRESHOLDED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + } + }, + { + "QUALITY_CONTROL:UNIFY:ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "QUALITY_CONTROL:UNIFY:UPSET_GENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + } + }, + { + "QUALITY_CONTROL:COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + } + } + ] ], - "timestamp": "2026-03-22T17:58:51.427722446", + "timestamp": "2026-03-28T19:47:47.258742454", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/singler/tests/main.nf.test b/subworkflows/local/singler/tests/main.nf.test index 83dbfa07..e8ab2c5d 100644 --- a/subworkflows/local/singler/tests/main.nf.test +++ b/subworkflows/local/singler/tests/main.nf.test @@ -32,8 +32,21 @@ nextflow_workflow { } then { + def predictions = path(workflow.out.obs[0][1]).csv assert workflow.success - assert snapshot(workflow.out).match() + assert workflow.out.obs.size() == 1 + with(predictions) { + assert rowCount > 0 + // one label column per reference, keyed by the reference meta.id + assert columnNames.any { it.endsWith("labels_hpca_direct") } + assert columnNames.any { it.endsWith("pruned.labels_hpca_direct") } + assert columnNames.any { it.endsWith("labels_immune_celldex") } + assert columnNames.any { it.endsWith("pruned.labels_immune_celldex") } + } + assert snapshot( + workflow.out.obs, + workflow.out.versions.collect { path(it).yaml } + ).match() } } diff --git a/subworkflows/local/singler/tests/main.nf.test.snap b/subworkflows/local/singler/tests/main.nf.test.snap index 04ef113e..c723ca46 100644 --- a/subworkflows/local/singler/tests/main.nf.test.snap +++ b/subworkflows/local/singler/tests/main.nf.test.snap @@ -36,37 +36,39 @@ }, "Should run without failures": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_singler_predictions.csv:md5,dae3881eb387e231fccb6c4302d93077" - ] - ], - "1": [ - "versions.yml:md5,9055f318b5890f047abf54b761b99cd1", - "versions.yml:md5,af2576b779b477b66790d98fa63566a6" - ], - "obs": [ - [ - { - "id": "test" - }, - "test_singler_predictions.csv:md5,dae3881eb387e231fccb6c4302d93077" - ] - ], - "versions": [ - "versions.yml:md5,9055f318b5890f047abf54b761b99cd1", - "versions.yml:md5,af2576b779b477b66790d98fa63566a6" + [ + [ + { + "id": "test" + }, + "test_singler_predictions.csv:md5,dae3881eb387e231fccb6c4302d93077" ] - } + ], + [ + { + "SINGLER:CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + } + }, + { + "SINGLER:CELLDEX_FETCHREFERENCE": { + "R": "R version 4.4.1 (2024-06-14)", + "celldex": "1.16.0", + "yaml": "2.3.10", + "SingleCellExperiment": "1.28.0", + "HDF5Array": "1.34.0" + } + } + ] ], - "timestamp": "2026-03-17T21:50:58.100916466", + "timestamp": "2026-03-28T19:19:04.019970429", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/subworkflows/local/unify/tests/main.nf.test b/subworkflows/local/unify/tests/main.nf.test index 2bc6e5d1..e75b292a 100644 --- a/subworkflows/local/unify/tests/main.nf.test +++ b/subworkflows/local/unify/tests/main.nf.test @@ -57,8 +57,20 @@ nextflow_workflow { } then { + def adata = anndata(workflow.out.h5ad[0][1]) assert workflow.success - assert snapshot(workflow.out).match() + with(adata) { + assert "batch" in obs.colnames + assert "label" in obs.colnames + assert "condition" in obs.colnames + assert "sample" in obs.colnames + assert var.rownames.size() > 0 + assert obs.rownames.size() > 0 + } + assert snapshot( + workflow.out, + adata.yaml + ).match() } } @@ -113,35 +125,20 @@ nextflow_workflow { } then { + def adata = anndata(workflow.out.h5ad[0][1]) assert workflow.success - assert snapshot(workflow.out).match() - } - - } - - test("Should run without failures - symbol_col index, unify_gene_symbols false, snapshot stability") { - - when { - params { - outdir = "$outputDir" - unify_gene_symbols = false - } - workflow { - """ - input[0] = channel.of([ - [id: 'test', symbol_col: 'index', batch_col: 'batch', label_col: ''], - file(params.pipelines_testdata_base_path + '/anndata-variations/symbols_as_index.h5ad', checkIfExists: true) - ]) - input[1] = false - input[2] = 'sum' - input[3] = false - """ + with(adata) { + assert "batch" in obs.colnames + assert "label" in obs.colnames + assert "condition" in obs.colnames + assert "sample" in obs.colnames + assert var.rownames.size() > 0 + assert obs.rownames.size() > 0 } - } - - then { - assert workflow.success - assert snapshot(workflow.out).match() + assert snapshot( + workflow.out, + adata.yaml + ).match() } } @@ -196,16 +193,20 @@ nextflow_workflow { } then { - def filename = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { - with(anndata(filename)) { - assert var.rownames.size() > 0 - assert obs.rownames.size() > 0 - } + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + with(adata) { + assert "batch" in obs.colnames + assert "label" in obs.colnames + assert "condition" in obs.colnames + assert "sample" in obs.colnames + assert var.rownames.size() > 0 + assert obs.rownames.size() > 0 } - ) + assert snapshot( + workflow.out, + adata.yaml + ).match() } } diff --git a/subworkflows/local/unify/tests/main.nf.test.snap b/subworkflows/local/unify/tests/main.nf.test.snap index f04158d1..3b95401a 100644 --- a/subworkflows/local/unify/tests/main.nf.test.snap +++ b/subworkflows/local/unify/tests/main.nf.test.snap @@ -99,12 +99,13 @@ "versions.yml:md5,56975dcf8aab71705ad7f822233409b8", "versions.yml:md5,f4baeb211a033b2534fb83ba7ec2cd86" ] - } + }, + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - sample\n - sample_original\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-16T16:27:36.451603253", + "timestamp": "2026-03-28T19:24:17.42519548", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - symbol_col index, unify_gene_symbols false, snapshot stability": { @@ -160,6 +161,66 @@ "nextflow": "25.10.4" } }, + "Should run without failures - symbol_col index, unify_gene_symbols true": { + "content": [ + { + "0": [ + [ + { + "id": "test", + "symbol_col": "index", + "batch_col": "batch", + "label_col": "label", + "condition_col": "condition", + "unknown_label": "unknown", + "counts_layer": "X" + }, + "test_unified.h5ad:md5,95eaecd7513a2cec94ff17aa626d11cd" + ] + ], + "1": [ + + ], + "2": [ + "versions.yml:md5,36bf3fb866d0085291382bf6713f7698", + "versions.yml:md5,4e6f35e1d0c91cec3120567db9f0bdfe", + "versions.yml:md5,56867b1608bf70187c185b4fecb3eab7", + "versions.yml:md5,56975dcf8aab71705ad7f822233409b8", + "versions.yml:md5,f4baeb211a033b2534fb83ba7ec2cd86" + ], + "h5ad": [ + [ + { + "id": "test", + "symbol_col": "index", + "batch_col": "batch", + "label_col": "label", + "condition_col": "condition", + "unknown_label": "unknown", + "counts_layer": "X" + }, + "test_unified.h5ad:md5,95eaecd7513a2cec94ff17aa626d11cd" + ] + ], + "multiqc_files": [ + + ], + "versions": [ + "versions.yml:md5,36bf3fb866d0085291382bf6713f7698", + "versions.yml:md5,4e6f35e1d0c91cec3120567db9f0bdfe", + "versions.yml:md5,56867b1608bf70187c185b4fecb3eab7", + "versions.yml:md5,56975dcf8aab71705ad7f822233409b8", + "versions.yml:md5,f4baeb211a033b2534fb83ba7ec2cd86" + ] + }, + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - sample\n - sample_original\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + ], + "timestamp": "2026-03-28T18:05:26.745577508", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } + }, "Should run without failures - symbol_col index, unify_gene_symbols false - stub": { "content": [ { @@ -321,12 +382,13 @@ "versions.yml:md5,d206caf8bf0d007a1c248652300a3834", "versions.yml:md5,f4baeb211a033b2534fb83ba7ec2cd86" ] - } + }, + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - sample\nvar:\n index: _index\n columns:\n - original_index\n - symbols\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-16T16:28:45.097590752", + "timestamp": "2026-03-28T19:25:29.064608355", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/subworkflows/local/unify_genes/tests/main.nf.test b/subworkflows/local/unify_genes/tests/main.nf.test index f2371333..5f9e6cb1 100644 --- a/subworkflows/local/unify_genes/tests/main.nf.test +++ b/subworkflows/local/unify_genes/tests/main.nf.test @@ -49,16 +49,18 @@ nextflow_workflow { } then { - def filename = workflow.out.h5ad[0][1] - assertAll( - { assert workflow.success }, - { - with(anndata(filename)) { - assert var.rownames.size() > 0 - assert obs.rownames.size() > 0 - } + def adata = anndata(workflow.out.h5ad[0][1]) + assert workflow.success + with(adata) { + // hugo-unifier adds a unified HGNC symbol column to var + assert "symbols" in var.colnames + assert var.rownames.size() > 0 + assert obs.rownames.size() > 0 } - ) + assert snapshot( + workflow.out, + adata.yaml + ).match() } } @@ -105,21 +107,24 @@ nextflow_workflow { } then { - assertAll( - { assert workflow.success }, - { - with(anndata(workflow.out.h5ad[0][1])) { - assert var.rownames.size() > 0 - assert obs.rownames.size() > 0 - } - }, - { - with(anndata(workflow.out.h5ad[1][1])) { - assert var.rownames.size() > 0 - assert obs.rownames.size() > 0 - } + def adata1 = anndata(workflow.out.h5ad[0][1]) + def adata2 = anndata(workflow.out.h5ad[1][1]) + assert workflow.success + with(adata1) { + assert "symbols" in var.colnames + assert var.rownames.size() > 0 + assert obs.rownames.size() > 0 + } + with(adata2) { + assert "symbols" in var.colnames + assert var.rownames.size() > 0 + assert obs.rownames.size() > 0 } - ) + assert snapshot( + workflow.out, + adata1.yaml, + adata2.yaml + ).match() } } diff --git a/subworkflows/local/unify_genes/tests/main.nf.test.snap b/subworkflows/local/unify_genes/tests/main.nf.test.snap index 627adb9e..f2653cbb 100644 --- a/subworkflows/local/unify_genes/tests/main.nf.test.snap +++ b/subworkflows/local/unify_genes/tests/main.nf.test.snap @@ -1,4 +1,40 @@ { + "Should run without failures - single sample": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" + ] + ], + "1": [ + "versions.yml:md5,a25a9f067f9ece70fa40d51efbcdbdee", + "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" + ], + "h5ad": [ + [ + { + "id": "test" + }, + "test_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" + ] + ], + "versions": [ + "versions.yml:md5,a25a9f067f9ece70fa40d51efbcdbdee", + "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" + ] + }, + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + ], + "timestamp": "2026-03-28T18:02:45.786444117", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } + }, "Should run without failures - multiple samples - stub": { "content": [ { @@ -82,5 +118,56 @@ "nf-test": "0.9.2", "nextflow": "25.04.6" } + }, + "Should run without failures - multiple samples": { + "content": [ + { + "0": [ + [ + { + "id": "test1" + }, + "test1_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" + ], + [ + { + "id": "test2" + }, + "test2_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" + ] + ], + "1": [ + "versions.yml:md5,a25a9f067f9ece70fa40d51efbcdbdee", + "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e", + "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" + ], + "h5ad": [ + [ + { + "id": "test1" + }, + "test1_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" + ], + [ + { + "id": "test2" + }, + "test2_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" + ] + ], + "versions": [ + "versions.yml:md5,a25a9f067f9ece70fa40d51efbcdbdee", + "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e", + "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" + ] + }, + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n", + "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + ], + "timestamp": "2026-03-28T18:03:47.506803742", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } } -} +} \ No newline at end of file From da0d51a9508ecc9f483f303014978e4c55355a0a Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sat, 28 Mar 2026 21:28:58 +0100 Subject: [PATCH 17/46] Remove variance_ratio implementations --- .../local/scanpy/combat/templates/combat.py | 1 - modules/local/scanpy/harmony/main.nf | 2 - .../local/scanpy/harmony/templates/harmony.py | 8 --- .../local/scanpy/harmony/tests/main.nf.test | 1 - .../scanpy/harmony/tests/main.nf.test.snap | 62 +------------------ modules/local/scanpy/pca/templates/pca.py | 3 - .../local/scvitools/scanvi/tests/main.nf.test | 3 - .../scvitools/scanvi/tests/main.nf.test.snap | 3 - .../local/scvitools/scvi/tests/main.nf.test | 3 - .../scvitools/scvi/tests/main.nf.test.snap | 3 - .../local/integrate/tests/main.nf.test.snap | 10 +-- 11 files changed, 3 insertions(+), 96 deletions(-) diff --git a/modules/local/scanpy/combat/templates/combat.py b/modules/local/scanpy/combat/templates/combat.py index 48236926..cb7f8ded 100644 --- a/modules/local/scanpy/combat/templates/combat.py +++ b/modules/local/scanpy/combat/templates/combat.py @@ -41,7 +41,6 @@ adata.obsm["X_pca"] = np.round(adata.obsm["X_pca"].astype(np.float64), args.decimals) adata.varm["PCs"] = np.round(adata.varm["PCs"].astype(np.float64), args.decimals) adata.uns["pca"]["variance"] = np.round(adata.uns["pca"]["variance"].astype(np.float64), args.decimals) - adata.uns["pca"]["variance_ratio"] = np.round(adata.uns["pca"]["variance_ratio"].astype(np.float64), args.decimals) adata.obsm["X_emb"] = adata.obsm["X_pca"] diff --git a/modules/local/scanpy/harmony/main.nf b/modules/local/scanpy/harmony/main.nf index cc47b500..d438c359 100644 --- a/modules/local/scanpy/harmony/main.nf +++ b/modules/local/scanpy/harmony/main.nf @@ -15,7 +15,6 @@ process SCANPY_HARMONY { output: tuple val(meta), path("${prefix}.h5ad"), emit: h5ad path "X_${prefix}.pkl", emit: obsm - path "variance_ratio_${prefix}.yml", emit: variance_ratio path "versions.yml", emit: versions script: @@ -31,7 +30,6 @@ process SCANPY_HARMONY { """ touch ${prefix}.h5ad touch X_${prefix}.pkl - touch variance_ratio_${prefix}.yml touch versions.yml """ } diff --git a/modules/local/scanpy/harmony/templates/harmony.py b/modules/local/scanpy/harmony/templates/harmony.py index 33b2577b..adaa81dd 100644 --- a/modules/local/scanpy/harmony/templates/harmony.py +++ b/modules/local/scanpy/harmony/templates/harmony.py @@ -60,14 +60,6 @@ adata_processing.obsm["X_emb"] = adata_processing.obsm["X_emb"].round(params.decimals) adata.obsm["X_emb"] = adata_processing.obsm["X_emb"] -var_per_dim = np.var(adata.obsm["X_emb"].astype(np.float64), axis=0) -variance_ratio = (var_per_dim / var_per_dim.sum()).tolist() -if params.decimals is not None: - variance_ratio = np.round(variance_ratio, params.decimals).tolist() - -with open(f"variance_ratio_{prefix}.yml", "w") as f: - yaml.dump({"variance_ratio": variance_ratio}, f) - adata.write_h5ad(f"{prefix}.h5ad") df = pd.DataFrame(adata.obsm["X_emb"], index=adata.obs_names) diff --git a/modules/local/scanpy/harmony/tests/main.nf.test b/modules/local/scanpy/harmony/tests/main.nf.test index 78e8bfe2..ffc73a3b 100644 --- a/modules/local/scanpy/harmony/tests/main.nf.test +++ b/modules/local/scanpy/harmony/tests/main.nf.test @@ -33,7 +33,6 @@ nextflow_process { assert process.success assert "X_emb" in adata.obsm assert snapshot( - path(process.out.variance_ratio[0]).yaml, path(process.out.versions[0]).yaml, adata.yaml ).match() diff --git a/modules/local/scanpy/harmony/tests/main.nf.test.snap b/modules/local/scanpy/harmony/tests/main.nf.test.snap index 6b01e291..c907b62b 100644 --- a/modules/local/scanpy/harmony/tests/main.nf.test.snap +++ b/modules/local/scanpy/harmony/tests/main.nf.test.snap @@ -14,9 +14,6 @@ "X_test.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "variance_ratio_test.yml:md5,d41d8cd98f00b204e9800998ecf8427e" - ], - "3": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ], "h5ad": [ @@ -30,9 +27,6 @@ "obsm": [ "X_test.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], - "variance_ratio": [ - "variance_ratio_test.yml:md5,d41d8cd98f00b204e9800998ecf8427e" - ], "versions": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ] @@ -46,60 +40,6 @@ }, "Should run without failures": { "content": [ - { - "variance_ratio": [ - 0.2, - 0.05, - 0.05, - 0.04, - 0.04, - 0.03, - 0.03, - 0.02, - 0.02, - 0.02, - 0.02, - 0.02, - 0.02, - 0.02, - 0.02, - 0.02, - 0.02, - 0.02, - 0.02, - 0.02, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01, - 0.01 - ] - }, { "SCANPY_HARMONY": { "harmonypy": "0.2.0", @@ -116,4 +56,4 @@ "nextflow": "25.10.2" } } -} \ No newline at end of file +} diff --git a/modules/local/scanpy/pca/templates/pca.py b/modules/local/scanpy/pca/templates/pca.py index 2b75b455..3cfe4fea 100644 --- a/modules/local/scanpy/pca/templates/pca.py +++ b/modules/local/scanpy/pca/templates/pca.py @@ -33,9 +33,6 @@ if params.decimals is not None: adata.obsm[key_added] = np.round(adata.obsm[key_added].astype(np.float64), params.decimals) - adata.uns[key_added]["variance_ratio"] = np.round( - adata.uns[key_added]["variance_ratio"].astype(np.float64), params.decimals - ) adata.write_h5ad(f"{prefix}.h5ad") df = pd.DataFrame(adata.obsm[key_added], index=adata.obs_names) diff --git a/modules/local/scvitools/scanvi/tests/main.nf.test b/modules/local/scvitools/scanvi/tests/main.nf.test index fd9eb261..d26593ca 100644 --- a/modules/local/scvitools/scanvi/tests/main.nf.test +++ b/modules/local/scvitools/scanvi/tests/main.nf.test @@ -52,11 +52,8 @@ nextflow_process { } assert snapshot( // Hashes are not stable due to floating point inaccuracies - file(process.out.h5ad[0][1]).size(), file(process.out.h5ad[0][1]).name, - file(process.out.model[0][1]).size(), file(process.out.model[0][1]).name, - file(process.out.obsm[0]).size(), file(process.out.obsm[0]).name, path(process.out.versions[0]).yaml, adata.yaml diff --git a/modules/local/scvitools/scanvi/tests/main.nf.test.snap b/modules/local/scvitools/scanvi/tests/main.nf.test.snap index a9cc6fcb..58ead009 100644 --- a/modules/local/scvitools/scanvi/tests/main.nf.test.snap +++ b/modules/local/scvitools/scanvi/tests/main.nf.test.snap @@ -62,11 +62,8 @@ }, "Should run without failures": { "content": [ - 28863010, "test_scanvi.h5ad", - 1380887, "model.pt", - 6118418, "X_test_scanvi.pkl", { "SCVITOOLS_SCANVI": { diff --git a/modules/local/scvitools/scvi/tests/main.nf.test b/modules/local/scvitools/scvi/tests/main.nf.test index e0a8e733..fb61a949 100644 --- a/modules/local/scvitools/scvi/tests/main.nf.test +++ b/modules/local/scvitools/scvi/tests/main.nf.test @@ -36,9 +36,6 @@ nextflow_process { } assert snapshot( // Hashes are not stable due to floating point inaccuracies - file(process.out.h5ad.get(0).get(1)).size(), - file(process.out.model.get(0).get(1)).size(), - file(process.out.obsm.get(0)).size(), path(process.out.versions[0]).yaml, adata.yaml ).match() diff --git a/modules/local/scvitools/scvi/tests/main.nf.test.snap b/modules/local/scvitools/scvi/tests/main.nf.test.snap index 2dfc6a76..0613f0e8 100644 --- a/modules/local/scvitools/scvi/tests/main.nf.test.snap +++ b/modules/local/scvitools/scvi/tests/main.nf.test.snap @@ -56,9 +56,6 @@ }, "Should run without failures": { "content": [ - 18403662, - 26244445, - 6118418, { "SCVITOOLS_SCVI": { "scvi": "1.3.3" diff --git a/subworkflows/local/integrate/tests/main.nf.test.snap b/subworkflows/local/integrate/tests/main.nf.test.snap index 9c7afde4..b6308ba5 100644 --- a/subworkflows/local/integrate/tests/main.nf.test.snap +++ b/subworkflows/local/integrate/tests/main.nf.test.snap @@ -14,12 +14,9 @@ ], "2": [ - - ], - "3": [ "X_harmony.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], - "4": [ + "3": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" @@ -139,12 +136,9 @@ ], "2": [ - - ], - "3": [ "X_harmony.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], - "4": [ + "3": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ], "integrations": [ From c448905d83003e3cae2b47aaec01031bfd2048c4 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sat, 28 Mar 2026 21:36:13 +0100 Subject: [PATCH 18/46] Update soupx/decontx tests --- docs/reproducibility.md | 6 +- .../local/celda/decontx/tests/main.nf.test | 4 - .../celda/decontx/tests/main.nf.test.snap | 98 +------------------ modules/local/soupx/tests/main.nf.test | 2 - modules/local/soupx/tests/main.nf.test.snap | 50 +--------- 5 files changed, 5 insertions(+), 155 deletions(-) diff --git a/docs/reproducibility.md b/docs/reproducibility.md index 6b2d25b6..c6a5d8ae 100644 --- a/docs/reproducibility.md +++ b/docs/reproducibility.md @@ -123,9 +123,9 @@ The **Dev branch implied** column is derived mechanically from whether the `dev` ### `soupx/` -| Module | Description | Reproducibility | Dev branch implied | -| ------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------ | -| `soupx` | Estimates and removes ambient RNA contamination using SoupX, preceded by Seurat clustering to define cluster-level contamination. | Fully deterministic — the Seurat clustering step uses a fixed seed; the original tests used `snapshot(process.out)`. | Deterministic ✓ | +| Module | Description | Reproducibility | Dev branch implied | +| ------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| `soupx` | Estimates and removes ambient RNA contamination using SoupX, preceded by Seurat clustering to define cluster-level contamination. | **Non-deterministic** — Seurat clustering is seeded but graph-based steps (Louvain/Leiden) vary across library versions; soup fraction estimates can differ across platforms. | Non-deterministic ✓ | --- diff --git a/modules/local/celda/decontx/tests/main.nf.test b/modules/local/celda/decontx/tests/main.nf.test index cee1d07f..03dcfaba 100644 --- a/modules/local/celda/decontx/tests/main.nf.test +++ b/modules/local/celda/decontx/tests/main.nf.test @@ -34,7 +34,6 @@ nextflow_process { // output written to X, so no named decontx layer assert !("ambient_corrected_decontx" in adata.layers) assert snapshot( - process.out, path(process.out.versions[0]).yaml, adata.yaml ).match() @@ -69,7 +68,6 @@ nextflow_process { // output written to X, so no named decontx layer assert !("ambient_corrected_decontx" in adata.layers) assert snapshot( - process.out, path(process.out.versions[0]).yaml, adata.yaml ).match() @@ -104,7 +102,6 @@ nextflow_process { // output written to X, so no named decontx layer assert !("ambient_corrected_decontx" in adata.layers) assert snapshot( - process.out, path(process.out.versions[0]).yaml, adata.yaml ).match() @@ -170,7 +167,6 @@ nextflow_process { // output written to X, so no named decontx layer assert !("ambient_corrected_decontx" in adata.layers) assert snapshot( - process.out, path(process.out.versions[0]).yaml, adata.yaml ).match() diff --git a/modules/local/celda/decontx/tests/main.nf.test.snap b/modules/local/celda/decontx/tests/main.nf.test.snap index df653129..2e2f04b7 100644 --- a/modules/local/celda/decontx/tests/main.nf.test.snap +++ b/modules/local/celda/decontx/tests/main.nf.test.snap @@ -1,30 +1,6 @@ { "Should run without failures without batch column": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_decontx.h5ad:md5,1eb88b5ef4b605b4f62030c2a607e28a" - ] - ], - "1": [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_decontx.h5ad:md5,1eb88b5ef4b605b4f62030c2a607e28a" - ] - ], - "versions": [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ] - }, { "CELDA_DECONTX": { "r": "4.5.3", @@ -42,30 +18,6 @@ }, "Should run without failures without raw - single batch": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_decontx.h5ad:md5,1eb88b5ef4b605b4f62030c2a607e28a" - ] - ], - "1": [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_decontx.h5ad:md5,1eb88b5ef4b605b4f62030c2a607e28a" - ] - ], - "versions": [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ] - }, { "CELDA_DECONTX": { "r": "4.5.3", @@ -83,30 +35,6 @@ }, "Should run without failures with raw": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_decontx.h5ad:md5,5b66bb96352049340b9214c45e8706cd" - ] - ], - "1": [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_decontx.h5ad:md5,5b66bb96352049340b9214c45e8706cd" - ] - ], - "versions": [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ] - }, { "CELDA_DECONTX": { "r": "4.5.3", @@ -174,30 +102,6 @@ }, "Should run without failures without raw - multi-batch": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_decontx.h5ad:md5,cf9801305448dfc1ecbae9ab102d09f3" - ] - ], - "1": [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_decontx.h5ad:md5,cf9801305448dfc1ecbae9ab102d09f3" - ] - ], - "versions": [ - "versions.yml:md5,7aee6256bf034aaa7fef6492db7bcb88" - ] - }, { "CELDA_DECONTX": { "r": "4.5.3", @@ -246,4 +150,4 @@ "nextflow": "25.10.2" } } -} \ No newline at end of file +} diff --git a/modules/local/soupx/tests/main.nf.test b/modules/local/soupx/tests/main.nf.test index 2502d275..4cca951b 100644 --- a/modules/local/soupx/tests/main.nf.test +++ b/modules/local/soupx/tests/main.nf.test @@ -34,7 +34,6 @@ nextflow_process { // output written to X, so no named soupx layer assert !("ambient_corrected_soupx" in adata.layers) assert snapshot( - process.out, path(process.out.versions[0]).yaml, adata.yaml ).match() @@ -68,7 +67,6 @@ nextflow_process { assert process.success assert "ambient_corrected_soupx" in adata.layers assert snapshot( - process.out, path(process.out.versions[0]).yaml, adata.yaml ).match() diff --git a/modules/local/soupx/tests/main.nf.test.snap b/modules/local/soupx/tests/main.nf.test.snap index 37f83890..17551e84 100644 --- a/modules/local/soupx/tests/main.nf.test.snap +++ b/modules/local/soupx/tests/main.nf.test.snap @@ -34,30 +34,6 @@ }, "Should run without failures": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_soupX.h5ad:md5,936b48aa0f6b63215b0d2db2492bbdb7" - ] - ], - "1": [ - "versions.yml:md5,eebdf63518e672c2ceb40e1bd9c9fbdf" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_soupX.h5ad:md5,936b48aa0f6b63215b0d2db2492bbdb7" - ] - ], - "versions": [ - "versions.yml:md5,eebdf63518e672c2ceb40e1bd9c9fbdf" - ] - }, { "SOUPX": { "r": "4.5.3", @@ -76,30 +52,6 @@ }, "Should write to a custom output layer": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_soupX.h5ad:md5,0a5f1e7591e5598537771755d312f35f" - ] - ], - "1": [ - "versions.yml:md5,eebdf63518e672c2ceb40e1bd9c9fbdf" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_soupX.h5ad:md5,0a5f1e7591e5598537771755d312f35f" - ] - ], - "versions": [ - "versions.yml:md5,eebdf63518e672c2ceb40e1bd9c9fbdf" - ] - }, { "SOUPX": { "r": "4.5.3", @@ -116,4 +68,4 @@ "nextflow": "25.10.2" } } -} \ No newline at end of file +} From bfd1d328c237ab03f7cdce03885eb39806e20ae1 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sat, 28 Mar 2026 22:20:16 +0100 Subject: [PATCH 19/46] Update stale snapshots for scanpy/filter, scanpy/leiden, scanpy/pca Snapshots regenerated with nftu after test assertions were expanded to include path(versions).yaml and adata.yaml alongside process.out, and after a scanpy version bump changed the versions.yml content. --- .../scanpy/filter/tests/main.nf.test.snap | 39 ++++++++++++++----- .../scanpy/leiden/tests/main.nf.test.snap | 12 ++++-- .../local/scanpy/pca/tests/main.nf.test.snap | 10 ++--- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/modules/local/scanpy/filter/tests/main.nf.test.snap b/modules/local/scanpy/filter/tests/main.nf.test.snap index ae4e19e9..e88811ec 100644 --- a/modules/local/scanpy/filter/tests/main.nf.test.snap +++ b/modules/local/scanpy/filter/tests/main.nf.test.snap @@ -47,12 +47,19 @@ "versions": [ "versions.yml:md5,b522587d103606ffd4959a6297fb9476" ] - } + }, + { + "SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 5719\nn_vars: 992\nobs:\n index: _index\n columns:\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - mean_counts\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-16T15:33:26.743121974", + "timestamp": "2026-03-28T22:09:49.666922142", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - stub": { @@ -113,12 +120,19 @@ "versions": [ "versions.yml:md5,b522587d103606ffd4959a6297fb9476" ] - } + }, + { + "SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 5719\nn_vars: 992\nobs:\n index: _index\n columns:\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - mean_counts\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-16T15:33:11.353190554", + "timestamp": "2026-03-28T22:09:25.003400702", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - with custom mito genes": { @@ -146,12 +160,19 @@ "versions": [ "versions.yml:md5,b522587d103606ffd4959a6297fb9476" ] - } + }, + { + "SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 5719\nn_vars: 992\nobs:\n index: _index\n columns:\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - mean_counts\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" ], - "timestamp": "2026-03-16T15:34:02.974430103", + "timestamp": "2026-03-28T22:10:39.378358618", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/scanpy/leiden/tests/main.nf.test.snap b/modules/local/scanpy/leiden/tests/main.nf.test.snap index 65b74eef..4404f13a 100644 --- a/modules/local/scanpy/leiden/tests/main.nf.test.snap +++ b/modules/local/scanpy/leiden/tests/main.nf.test.snap @@ -52,11 +52,15 @@ }, "Should run without failures": { "content": [ - [ - "versions.yml:md5,094091f84634347067c71751fa7c6b27" - ] + { + "SCANPY_LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - neighbors\n" ], - "timestamp": "2026-03-22T15:00:00.781565748", + "timestamp": "2026-03-28T22:11:18.707514777", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index 0ac9343b..1690e2ca 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,7 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" ], "h5ad": [ [ @@ -28,14 +28,14 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" ] } ], - "timestamp": "2026-03-26T08:18:17.901045", + "timestamp": "2026-03-28T22:12:17.200260088", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures": { From 1362a8ea1170a38a0ac22068cb9ae1333d7e5030 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sat, 28 Mar 2026 22:27:28 +0100 Subject: [PATCH 20/46] Add rule for preventing direct snapshot editing --- .cursor/rules/nf-test-snapshots.mdc | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .cursor/rules/nf-test-snapshots.mdc diff --git a/.cursor/rules/nf-test-snapshots.mdc b/.cursor/rules/nf-test-snapshots.mdc new file mode 100644 index 00000000..9332b64e --- /dev/null +++ b/.cursor/rules/nf-test-snapshots.mdc @@ -0,0 +1,35 @@ +--- +description: Never directly edit nf-test snapshot files; always use nftu to regenerate them +globs: "**/*.nf.test.snap" +alwaysApply: false +--- + +# nf-test Snapshot Files + +**Never manually edit `.nf.test.snap` files.** + +Directly editing snapshots cannot guarantee that the written content matches what the pipeline would actually produce. Always regenerate them using the `--update-snapshot` flag of `nf-test`: + +```bash +nf-test test --update-snapshot +``` + +The exact invocation depends on the environment (profiles, container engine, etc.). Check local aliases or project documentation for the recommended command on the current machine. + +## Example + +```bash +# ✅ GOOD — regenerate snapshots from actual test output +nf-test test --update-snapshot modules/local/scanpy/filter/tests/main.nf.test + +# ❌ BAD — manually editing the snap file +# vim modules/local/scanpy/filter/tests/main.nf.test.snap +``` + +You can pass multiple test files in one invocation: + +```bash +nf-test test --update-snapshot \ + modules/local/scanpy/filter/tests/main.nf.test \ + modules/local/scanpy/leiden/tests/main.nf.test +``` From 913f1aa4a026ccd3637d7f6387a89d1b92f4c0b1 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sat, 28 Mar 2026 23:09:58 +0100 Subject: [PATCH 21/46] Fix integrate stub snapshots after variance_ratio removal Two harmony stub test snapshots had stale channel indices from the variance_ratio output removal and were missed in the previous fix. Regenerated with nftu. --- .../local/integrate/tests/main.nf.test.snap | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/subworkflows/local/integrate/tests/main.nf.test.snap b/subworkflows/local/integrate/tests/main.nf.test.snap index b6308ba5..f8582565 100644 --- a/subworkflows/local/integrate/tests/main.nf.test.snap +++ b/subworkflows/local/integrate/tests/main.nf.test.snap @@ -14,9 +14,12 @@ ], "2": [ - "X_harmony.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" + ], "3": [ + "X_harmony.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "4": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" @@ -45,7 +48,7 @@ ] } ], - "timestamp": "2026-03-25T15:45:28.18158151", + "timestamp": "2026-03-28T23:05:37.694952307", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -136,9 +139,12 @@ ], "2": [ - "X_harmony.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" + ], "3": [ + "X_harmony.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" + ], + "4": [ "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ], "integrations": [ @@ -163,7 +169,7 @@ ] } ], - "timestamp": "2026-03-25T15:50:57.251962289", + "timestamp": "2026-03-28T23:09:49.392744851", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" From 55937e748516f8d16dd6266deb52b22800d31fa8 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sat, 28 Mar 2026 23:48:07 +0100 Subject: [PATCH 22/46] Rewrite reproducibility.md with accurate test strategy column Replace the stale Dev branch implied column with a Test strategy (this branch) column describing what each test actually asserts. Correct soupx and ambient_correction reproducibility classifications. --- docs/reproducibility.md | 190 +++++++++++++++++++++------------------- 1 file changed, 99 insertions(+), 91 deletions(-) diff --git a/docs/reproducibility.md b/docs/reproducibility.md index c6a5d8ae..fcbe3717 100644 --- a/docs/reproducibility.md +++ b/docs/reproducibility.md @@ -10,7 +10,15 @@ Classification of all local modules and subworkflows by output reproducibility. | **Seeded / quasi-deterministic** | A fixed random seed is set, but floating-point results (PCA coordinates, embeddings) can differ slightly across hardware, LAPACK/BLAS backends, or library versions. File hashes may differ between platforms even when logic is correct. | | **Non-deterministic** | Output varies between runs or platforms even with identical inputs — either due to unseeded stochasticity, iterative ML training, or live external API/download calls. | -The **Dev branch implied** column is derived mechanically from whether the `dev` branch tests use `snapshot(process.out)` / `snapshot(workflow.out)` (which captures file MD5 hashes). A module that snapshots `process.out` was treated as deterministic on dev; one that omits it was not. Differences between the two columns indicate cases where the current branch and dev disagreed. +The **Test strategy (this branch)** column describes what the tests on this branch actually assert: + +| Strategy | What is checked | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------- | +| `hash` | Full `snapshot(process.out)` — bit-identical file MD5 hashes. Only safe for deterministic modules. | +| `structural` | `adata.yaml` schema (obs/var column names, layer/obsm keys) and `versions.yml` content — no matrix values or file hashes. | +| `column names` | Only the names of obs columns are asserted, not their values. | +| `range assertion` | A numeric output (e.g. cluster count) is checked to fall within an expected range. | +| `stub only` | No non-stub test exists; only empty stub outputs are verified. | --- @@ -18,134 +26,134 @@ The **Dev branch implied** column is derived mechanically from whether the `dev` ### `adata/` -| Module | Description | Reproducibility | Dev branch implied | -| ----------------------- | -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | -| `adata/entropy` | Computes per-group normalised Shannon entropy of a categorical obs column and optionally plots it. | Fully deterministic | Deterministic | -| `adata/extend` | Extends an AnnData object with additional obs/var/obsm/obsp/uns/layers data from pickle or CSV files. | Fully deterministic | Deterministic | -| `adata/merge` | Concatenates multiple AnnData objects into inner (gene intersection) and outer (union) merged datasets. | Fully deterministic | Deterministic | -| `adata/mergeembeddings` | Merges embeddings from a newly integrated AnnData back into the combined base+integrated AnnData by cell-index alignment. | Fully deterministic | Deterministic | -| `adata/mygene` | Translates gene identifiers (Ensembl/Entrez/symbol) to HGNC symbols via the MyGene.info REST API. | **Non-deterministic** — live external API call; results depend on database state at query time. | ⚠️ Deterministic — dev snapshots `process.out` despite the live API | -| `adata/prepcellxgene` | Prepares an AnnData object for CellxGene by renaming embedding keys and converting counts to log-normalised float32. | Fully deterministic | Deterministic | -| `adata/readcsv` | Reads a CSV file and writes it as an AnnData H5AD. | Fully deterministic | Deterministic | -| `adata/readrds` | Converts an RDS file (Seurat or SingleCellExperiment) to AnnData H5AD via anndata2ri/rpy2. | Fully deterministic | Deterministic | -| `adata/setindex` | Sets a specified obs or var column as the new AnnData index. | Fully deterministic | Deterministic | -| `adata/splitcol` | Splits an AnnData object into one H5AD file per unique value of a specified obs column. | Fully deterministic | Deterministic | -| `adata/splitembeddings` | Splits multiple named embeddings from a single AnnData into separate H5AD files each containing `X_emb`. | Fully deterministic | Deterministic | -| `adata/tords` | Converts an AnnData H5AD to an RDS SingleCellExperiment object using anndataR. | Fully deterministic | Deterministic | -| `adata/unify` | Normalises gene symbols, resolves duplicates, unifies batch/label/condition columns, and prefixes barcodes with sample ID. | Fully deterministic | Deterministic | -| `adata/upsetgenes` | Plots an UpSet diagram of gene set overlaps across multiple AnnData objects and outputs a MultiQC JSON image. | Fully deterministic | Deterministic | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------ | +| `adata/entropy` | Computes per-group normalised Shannon entropy of a categorical obs column and optionally plots it. | Fully deterministic | hash | +| `adata/extend` | Extends an AnnData object with additional obs/var/obsm/obsp/uns/layers data from pickle or CSV files. | Fully deterministic | hash | +| `adata/merge` | Concatenates multiple AnnData objects into inner (gene intersection) and outer (union) merged datasets. | Fully deterministic | hash | +| `adata/mergeembeddings` | Merges embeddings from a newly integrated AnnData back into the combined base+integrated AnnData by cell-index alignment. | Fully deterministic | hash | +| `adata/mygene` | Translates gene identifiers (Ensembl/Entrez/symbol) to HGNC symbols via the MyGene.info REST API. | **Non-deterministic** — live external API call; results depend on database state at query time. | ⚠️ hash — snapshots `process.out` despite the live API | +| `adata/prepcellxgene` | Prepares an AnnData object for CellxGene by renaming embedding keys and converting counts to log-normalised float32. | Fully deterministic | hash | +| `adata/readcsv` | Reads a CSV file and writes it as an AnnData H5AD. | Fully deterministic | hash | +| `adata/readrds` | Converts an RDS file (Seurat or SingleCellExperiment) to AnnData H5AD via anndata2ri/rpy2. | Fully deterministic | hash | +| `adata/setindex` | Sets a specified obs or var column as the new AnnData index. | Fully deterministic | hash | +| `adata/splitcol` | Splits an AnnData object into one H5AD file per unique value of a specified obs column. | Fully deterministic | hash | +| `adata/splitembeddings` | Splits multiple named embeddings from a single AnnData into separate H5AD files each containing `X_emb`. | Fully deterministic | hash | +| `adata/tords` | Converts an AnnData H5AD to an RDS SingleCellExperiment object using anndataR. | Fully deterministic | hash | +| `adata/unify` | Normalises gene symbols, resolves duplicates, unifies batch/label/condition columns, and prefixes barcodes with sample ID. | Fully deterministic | hash | +| `adata/upsetgenes` | Plots an UpSet diagram of gene set overlaps across multiple AnnData objects and outputs a MultiQC JSON image. | Fully deterministic | hash | ### `celda/` -| Module | Description | Reproducibility | Dev branch implied | -| --------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------- | -| `celda/decontx` | Removes ambient RNA contamination using the decontX variational EM algorithm (celda R package). | **Non-deterministic** — decontX uses stochastic initialisation with no fixed seed. | Non-deterministic ✓ | +| Module | Description | Reproducibility | Test strategy (this branch) | +| --------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------ | +| `celda/decontx` | Removes ambient RNA contamination using the decontX variational EM algorithm (celda R package). | **Non-deterministic** — decontX uses stochastic initialisation with no fixed seed. | structural — h5ad hash omitted; versions + schema only | ### `celldex/` -| Module | Description | Reproducibility | Dev branch implied | -| ------------------------ | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------- | -| `celldex/fetchreference` | Downloads a named celldex reference dataset and saves it as a tar-compressed HDF5 SummarizedExperiment. | **Non-deterministic** — live download from ExperimentHub; database version varies over time. | Non-deterministic ✓ | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------------------------ | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------- | +| `celldex/fetchreference` | Downloads a named celldex reference dataset and saves it as a tar-compressed HDF5 SummarizedExperiment. | **Non-deterministic** — live download from ExperimentHub; database version varies over time. | structural | ### `celltypes/` -| Module | Description | Reproducibility | Dev branch implied | -| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------- | -| `celltypes/celltypist` | Annotates cell types using one or more CellTypist logistic regression models after normalising and log-transforming counts. | Fully deterministic — uses a fixed, pre-trained model with no stochastic inference at prediction time. | Deterministic ✓ | -| `celltypes/singler` | Assigns cell types using the SingleR correlation-based method against one or more celldex reference datasets. | Fully deterministic — correlation/label-transfer method with no randomness. | ⚠️ Non-deterministic — dev omits `process.out` | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------- | +| `celltypes/celltypist` | Annotates cell types using one or more CellTypist logistic regression models after normalising and log-transforming counts. | Fully deterministic — uses a fixed, pre-trained model with no stochastic inference at prediction time. | column names only | +| `celltypes/singler` | Assigns cell types using the SingleR correlation-based method against one or more celldex reference datasets. | Fully deterministic — correlation/label-transfer method with no randomness. | obs CSV + file names | ### `custom/` -| Module | Description | Reproducibility | Dev branch implied | -| --------------------- | ------------------------------------------------------------------------------------------- | ------------------- | ------------------ | -| `custom/collectsizes` | Pivots a TSV of per-sample cell counts at different QC stages into a MultiQC summary table. | Fully deterministic | Deterministic ✓ | +| Module | Description | Reproducibility | Test strategy (this branch) | +| --------------------- | ------------------------------------------------------------------------------------------- | ------------------- | --------------------------- | +| `custom/collectsizes` | Pivots a TSV of per-sample cell counts at different QC stages into a MultiQC summary table. | Fully deterministic | hash | ### `doublet_detection/` -| Module | Description | Reproducibility | Dev branch implied | -| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------- | -| `doublet_detection/doublet_removal` | Removes doublet cells from an AnnData object based on a threshold applied to aggregated doublet-caller predictions. | Fully deterministic | Deterministic ✓ | -| `doublet_detection/scds` | Scores and calls doublets using bcds + cxds + hybrid (scds R package) with `set.seed(0)`. | Seeded / quasi-deterministic — seed is fixed, but internal boosting results may vary slightly across R/package versions. | ⚠️ Non-deterministic — dev omits `process.out` | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------------- | +| `doublet_detection/doublet_removal` | Removes doublet cells from an AnnData object based on a threshold applied to aggregated doublet-caller predictions. | Fully deterministic | hash | +| `doublet_detection/scds` | Scores and calls doublets using bcds + cxds + hybrid (scds R package) with `set.seed(0)`. | Seeded / quasi-deterministic — seed is fixed, but internal boosting results may vary slightly across R/package versions. | column names only | ### `hugounifier/` -| Module | Description | Reproducibility | Dev branch implied | -| ------------------- | --------------------------------------------------------------------------------------------- | ------------------- | ---------------------------------------------- | -| `hugounifier/get` | Computes a cross-dataset gene symbol renaming change table using the `hugo-unifier` CLI tool. | Fully deterministic | ⚠️ Non-deterministic — dev omits `process.out` | -| `hugounifier/apply` | Applies a gene symbol renaming change table to a single AnnData H5AD file. | Fully deterministic | ⚠️ Non-deterministic — dev omits `process.out` | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------------------- | --------------------------------------------------------------------------------------------- | ------------------- | --------------------------- | +| `hugounifier/get` | Computes a cross-dataset gene symbol renaming change table using the `hugo-unifier` CLI tool. | Fully deterministic | hash | +| `hugounifier/apply` | Applies a gene symbol renaming change table to a single AnnData H5AD file. | Fully deterministic | hash | ### `liana/` -| Module | Description | Reproducibility | Dev branch implied | -| --------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------ | -| `liana/rankaggregate` | Runs LIANA rank-aggregate ligand–receptor interaction analysis on a clustered AnnData object. | Fully deterministic — rank aggregation of multiple fixed scoring methods with no stochastic component. | Deterministic ✓ | +| Module | Description | Reproducibility | Test strategy (this branch) | +| --------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------- | +| `liana/rankaggregate` | Runs LIANA rank-aggregate ligand–receptor interaction analysis on a clustered AnnData object. | Fully deterministic — rank aggregation of multiple fixed scoring methods with no stochastic component. | hash | ### `scanpy/` -| Module | Description | Reproducibility | Dev branch implied | -| ------------------------ | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | -| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | Deterministic ✓ | -| `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | Deterministic ✓ | -| `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | Deterministic ✓ | -| `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | Deterministic ✓ | -| `scanpy/harmony` | Runs Harmony batch integration after log-normalisation and PCA, storing the corrected embedding as `X_emb`. | **Non-deterministic** — Harmony is an iterative optimisation with no fixed seed; upstream PCA is also unseeded. | Non-deterministic ✓ | -| `scanpy/hvgs` | Selects highly variable genes and subsets the AnnData to those genes. | Fully deterministic | Deterministic ✓ | -| `scanpy/leiden` | Performs Leiden community-detection clustering at a specified resolution. | **Non-deterministic** — Leiden uses random restarts with no fixed seed. | Non-deterministic ✓ | -| `scanpy/neighbors` | Computes a k-nearest-neighbour graph on a specified embedding. | Fully deterministic given a fixed input embedding. | ⚠️ Stub-only test on dev | -| `scanpy/paga` | Computes PAGA coarse-grained cluster connectivity and saves a graph and plot. | Fully deterministic — PAGA is a deterministic graph-summarisation step given fixed Leiden labels. | Deterministic ✓ | -| `scanpy/pca` | Runs PCA with `random_state=0` and stores the result under a specified key. | Seeded / quasi-deterministic — seed is fixed, but float coordinates can differ across LAPACK/MKL backends. | ⚠️ Non-deterministic — dev omits `process.out` | -| `scanpy/plotqc` | Calculates QC metrics and produces a counts-vs-genes scatter plot for MultiQC. | Fully deterministic | Deterministic ✓ | -| `scanpy/rankgenesgroups` | Runs differential gene expression (rank genes groups) across clusters using a configurable statistical method. | Fully deterministic for `wilcoxon` and `t-test` (defaults); depends on chosen method parameter. | Deterministic ✓ | -| `scanpy/readh5` | Reads a 10x Genomics HDF5 (`.h5`) file and writes it as an AnnData H5AD. | Fully deterministic | Deterministic ✓ | -| `scanpy/sample` | Down-samples cells to a fixed count or fraction using `rng=0`. | Seeded / quasi-deterministic — seed is fixed, but sampled cell set may vary across NumPy versions. | Deterministic ✓ | -| `scanpy/umap` | Computes a UMAP embedding from a pre-built neighbour graph using `random_state=0`. | Seeded / quasi-deterministic — seed is fixed, but float coordinates vary across umap-learn/numba versions. | ⚠️ Non-deterministic — dev omits `process.out` | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------------------------ | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | +| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | hash | +| `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | hash | +| `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | structural — versions + schema only | +| `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | hash + structural | +| `scanpy/harmony` | Runs Harmony batch integration after log-normalisation and PCA, storing the corrected embedding as `X_emb`. | **Non-deterministic** — Harmony is an iterative optimisation with no fixed seed; upstream PCA is also unseeded. | structural — versions + schema only; `variance_ratio` output removed | +| `scanpy/hvgs` | Selects highly variable genes and subsets the AnnData to those genes. | Fully deterministic | hash | +| `scanpy/leiden` | Performs Leiden community-detection clustering at a specified resolution. | **Non-deterministic** — Leiden uses random restarts with no fixed seed. | structural — range assertion on cluster count + versions + schema | +| `scanpy/neighbors` | Computes a k-nearest-neighbour graph on a specified embedding. | Fully deterministic given a fixed input embedding. | structural — versions + schema only | +| `scanpy/paga` | Computes PAGA coarse-grained cluster connectivity and saves a graph and plot. | Fully deterministic — PAGA is a deterministic graph-summarisation step given fixed Leiden labels. | hash | +| `scanpy/pca` | Runs PCA with `random_state=0` and stores the result under a specified key. | Seeded / quasi-deterministic — seed is fixed, but float coordinates can differ across LAPACK/MKL backends. | structural — versions + schema only | +| `scanpy/plotqc` | Calculates QC metrics and produces a counts-vs-genes scatter plot for MultiQC. | Fully deterministic | hash | +| `scanpy/rankgenesgroups` | Runs differential gene expression (rank genes groups) across clusters using a configurable statistical method. | Fully deterministic for `wilcoxon` and `t-test` (defaults); depends on chosen method parameter. | hash | +| `scanpy/readh5` | Reads a 10x Genomics HDF5 (`.h5`) file and writes it as an AnnData H5AD. | Fully deterministic | hash | +| `scanpy/sample` | Down-samples cells to a fixed count or fraction using `rng=0`. | Seeded / quasi-deterministic — seed is fixed, but sampled cell set may vary across NumPy versions. | hash | +| `scanpy/umap` | Computes a UMAP embedding from a pre-built neighbour graph using `random_state=0`. | Seeded / quasi-deterministic — seed is fixed, but float coordinates vary across umap-learn/numba versions. | structural — versions + schema only | ### `scimilarity/` -| Module | Description | Reproducibility | Dev branch implied | -| ------------------------ | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -| `scimilarity/annotate` | Annotates cells with cell type labels using SCimilarity's kNN lookup into the pretrained reference embedding. | Fully deterministic — pure kNN lookup against a fixed reference with no stochastic inference. ⚠️ No non-stub test exists: the SCimilarity model file (~30 GB) exceeds practical test data limits. | Stub-only on both | -| `scimilarity/embed` | Embeds cells into SCimilarity's pretrained metric-learning latent space. | Fully deterministic — inference-only forward pass through a fixed pretrained network (no dropout at inference). ⚠️ No non-stub test exists: the SCimilarity model file (~30 GB) exceeds practical test data limits. | Stub-only on both | -| `scimilarity/pseudobulk` | Aggregates single-cell counts into pseudobulk profiles grouped by specified metadata columns. | Fully deterministic | Deterministic ✓ | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------------------------ | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| `scimilarity/annotate` | Annotates cells with cell type labels using SCimilarity's kNN lookup into the pretrained reference embedding. | Fully deterministic — pure kNN lookup against a fixed reference with no stochastic inference. ⚠️ No non-stub test exists: the SCimilarity model file (~30 GB) exceeds practical test data limits. | stub only | +| `scimilarity/embed` | Embeds cells into SCimilarity's pretrained metric-learning latent space. | Fully deterministic — inference-only forward pass through a fixed pretrained network (no dropout at inference). ⚠️ No non-stub test exists: the SCimilarity model file (~30 GB) exceeds practical test data limits. | stub only | +| `scimilarity/pseudobulk` | Aggregates single-cell counts into pseudobulk profiles grouped by specified metadata columns. | Fully deterministic | hash | ### `scvitools/` -| Module | Description | Reproducibility | Dev branch implied | -| ------------------ | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | -| `scvitools/scanvi` | Trains a scANVI semi-supervised VAE for batch integration and label transfer with `seed=0` and deterministic CUDA ops. | Seeded / quasi-deterministic — seed and `torch.use_deterministic_algorithms(True)` are set, but variational training and early stopping can still differ across GPU drivers and torch/scvi versions. Tests deliberately omit `process.out`. | Non-deterministic ✓ | -| `scvitools/scvi` | Trains a scVI VAE for batch integration with `seed=0` and deterministic CUDA ops. | Seeded / quasi-deterministic — same caveats as scANVI above. Tests deliberately omit `process.out`. | Non-deterministic ✓ | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------------------ | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | +| `scvitools/scanvi` | Trains a scANVI semi-supervised VAE for batch integration and label transfer with `seed=0` and deterministic CUDA ops. | Seeded / quasi-deterministic — seed and `torch.use_deterministic_algorithms(True)` are set, but variational training and early stopping can still differ across GPU drivers and torch/scvi versions. | structural — file names + versions + schema | +| `scvitools/scvi` | Trains a scVI VAE for batch integration with `seed=0` and deterministic CUDA ops. | Seeded / quasi-deterministic — same caveats as scANVI above. | structural — versions + schema only | ### `seurat/` -| Module | Description | Reproducibility | Dev branch implied | -| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------- | -| `seurat/integration` | Performs Seurat v5 CCA-based batch integration after SCTransform and PCA with `set.seed(0)`, storing the corrected embedding as `X_emb`. | Seeded / quasi-deterministic — seed is fixed, but CCA/SCTransform involve floating-point iterative optimisation that can vary across Seurat/LAPACK versions. | ⚠️ Non-deterministic — dev omits `process.out` | +| Module | Description | Reproducibility | Test strategy (this branch) | +| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------- | +| `seurat/integration` | Performs Seurat v5 CCA-based batch integration after SCTransform and PCA with `set.seed(0)`, storing the corrected embedding as `X_emb`. | Seeded / quasi-deterministic — seed is fixed, but CCA/SCTransform involve floating-point iterative optimisation that can vary across Seurat/LAPACK versions. | structural — versions + schema only | ### `soupx/` -| Module | Description | Reproducibility | Dev branch implied | -| ------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | -| `soupx` | Estimates and removes ambient RNA contamination using SoupX, preceded by Seurat clustering to define cluster-level contamination. | **Non-deterministic** — Seurat clustering is seeded but graph-based steps (Louvain/Leiden) vary across library versions; soup fraction estimates can differ across platforms. | Non-deterministic ✓ | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | +| `soupx` | Estimates and removes ambient RNA contamination using SoupX, preceded by Seurat clustering to define cluster-level contamination. | **Non-deterministic** — Seurat clustering is seeded but graph-based steps (Louvain/Leiden) vary across library versions; soup fraction estimates can differ across platforms. | structural — h5ad hash omitted; versions + schema only | --- ## Subworkflows -| Subworkflow | Description | Reproducibility | Dev branch implied | -| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -| `ambient_correction` | Dispatches ambient RNA correction to decontX, SoupX, or none based on a parameter. | **Non-deterministic** for decontX (no seed); fully deterministic for SoupX and the `none` passthrough. | Non-deterministic ✓ | -| `celltype_assignment` | Orchestrates cell type annotation by running SingleR and/or CellTypist. | Fully deterministic — both methods are deterministic at inference time. | ⚠️ Non-deterministic — dev omits `workflow.out` | -| `cluster` | Full clustering pipeline: neighbours → UMAP → Leiden at multiple resolutions → Shannon entropy. | Seeded / quasi-deterministic for UMAP; **non-deterministic** due to unseeded Leiden. | Non-deterministic ✓ | -| `combine` | Merges all samples and runs all configured integration methods. | Inherits from constituent modules — ranges from fully deterministic (no integration) to seeded/quasi-deterministic (scVI, Harmony, Seurat). | ⚠️ Deterministic — dev snapshots `workflow.out` regardless of integration method | -| `differential_expression` | Runs rank-genes-groups DE analysis across all combinations of clustering labels, conditions, and cell-type subsets. | Fully deterministic for the default wilcoxon/t-test methods. | Deterministic ✓ | -| `doublet_detection` | Runs one or more doublet-detection methods (scds, solo, scrublet, doubletdetection) and removes called doublets. | **Non-deterministic** — solo, scrublet, and doubletdetection have stochastic components; scds is seeded. | Non-deterministic ✓ | -| `finalize` | Assembles the final AnnData by extending it with all collected obs/obsm/uns/layers outputs. | Fully deterministic | Deterministic ✓ | -| `integrate` | Applies HVG selection then one or more integration methods (scVI, scANVI, Harmony, BBKNN, ComBat, Seurat, SCimilarity). | Seeded / quasi-deterministic for scVI/scANVI/ComBat/Seurat/BBKNN; **non-deterministic** for Harmony. | ⚠️ Deterministic — dev snapshots `workflow.out` for all integration methods including Harmony | -| `load_h5ad` | Loads input files in H5AD, 10x H5, RDS, or CSV format and converts all to AnnData H5AD. | Fully deterministic | Deterministic ✓ | -| `per_group` | Runs PAGA, LIANA rank-aggregate, and rank-genes DE per cluster. | Fully deterministic | Deterministic ✓ | -| `pseudobulking` | Aggregates single-cell data into pseudobulk profiles grouped by specified metadata columns. | Fully deterministic | Deterministic ✓ | -| `quality_control` | Full per-sample QC pipeline: empty droplet filtering, ambient correction, gene unification, cell/gene filtering, optional downsampling, doublet detection, and optional cell cycle scoring. | Seeded / quasi-deterministic to **non-deterministic** depending on configured ambient and doublet-detection methods. | ⚠️ Deterministic — dev snapshots `workflow.out` regardless of method configuration | -| `scimilarity` | Embeds cells into the SCimilarity pretrained latent space and annotates with cell type labels. | Fully deterministic — fixed pretrained model, inference-only. | Stub-only on both | -| `singler` | Downloads (or uses pre-provided) celldex reference datasets and runs SingleR annotation. | Fully deterministic for annotation; **non-deterministic** if downloading references at runtime via ExperimentHub. | Deterministic ✓ | -| `unify` | Standardises gene symbols (optionally via MyGene.info and HUGO-unifier) and normalises metadata columns (batch, label, condition). | **Non-deterministic** when `symbol_col == "none"` (triggers MyGene.info API call); fully deterministic otherwise. | Deterministic — dev snapshots `workflow.out` including the MyGene.info path | -| `unify_genes` | Applies HUGO-unifier to compute and apply a cross-dataset gene symbol renaming table. | Fully deterministic | ⚠️ Non-deterministic — dev omits `workflow.out` | +| Subworkflow | Description | Reproducibility | Test strategy (this branch) | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | +| `ambient_correction` | Dispatches ambient RNA correction to decontX, SoupX, or none based on a parameter. | **Non-deterministic** for decontX (no seed) and SoupX (seeded clustering but variable results); fully deterministic for the `none` passthrough. | structural — versions + schema only | +| `celltype_assignment` | Orchestrates cell type annotation by running SingleR and/or CellTypist. | Fully deterministic — both methods are deterministic at inference time. | obs size only | +| `cluster` | Full clustering pipeline: neighbours → UMAP → Leiden at multiple resolutions → Shannon entropy. | Seeded / quasi-deterministic for UMAP; **non-deterministic** due to unseeded Leiden. | structural — versions only | +| `combine` | Merges all samples and runs all configured integration methods. | Inherits from constituent modules — ranges from fully deterministic (no integration) to seeded/quasi-deterministic (scVI, Harmony, Seurat). | structural — versions only | +| `differential_expression` | Runs rank-genes-groups DE analysis across all combinations of clustering labels, conditions, and cell-type subsets. | Fully deterministic for the default wilcoxon/t-test methods. | hash | +| `doublet_detection` | Runs one or more doublet-detection methods (scds, solo, scrublet, doubletdetection) and removes called doublets. | **Non-deterministic** — solo, scrublet, and doubletdetection have stochastic components; scds is seeded. | structural + range assertion on cell count | +| `finalize` | Assembles the final AnnData by extending it with all collected obs/obsm/uns/layers outputs. | Fully deterministic | hash | +| `integrate` | Applies HVG selection then one or more integration methods (scVI, scANVI, Harmony, BBKNN, ComBat, Seurat, SCimilarity). | Seeded / quasi-deterministic for scVI/scANVI/ComBat/Seurat/BBKNN; **non-deterministic** for Harmony. | structural — versions + schema only | +| `load_h5ad` | Loads input files in H5AD, 10x H5, RDS, or CSV format and converts all to AnnData H5AD. | Fully deterministic | hash | +| `per_group` | Runs PAGA, LIANA rank-aggregate, and rank-genes DE per cluster. | Fully deterministic | structural — versions only | +| `pseudobulking` | Aggregates single-cell data into pseudobulk profiles grouped by specified metadata columns. | Fully deterministic | hash | +| `quality_control` | Full per-sample QC pipeline: empty droplet filtering, ambient correction, gene unification, cell/gene filtering, optional downsampling, doublet detection, and optional cell cycle scoring. | Seeded / quasi-deterministic to **non-deterministic** depending on configured ambient and doublet-detection methods. | structural — versions + multiqc files | +| `scimilarity` | Embeds cells into the SCimilarity pretrained latent space and annotates with cell type labels. | Fully deterministic — fixed pretrained model, inference-only. | stub only | +| `singler` | Downloads (or uses pre-provided) celldex reference datasets and runs SingleR annotation. | Fully deterministic for annotation; **non-deterministic** if downloading references at runtime via ExperimentHub. | hash | +| `unify` | Standardises gene symbols (optionally via MyGene.info and HUGO-unifier) and normalises metadata columns (batch, label, condition). | **Non-deterministic** when `symbol_col == "none"` (triggers MyGene.info API call); fully deterministic otherwise. | hash | +| `unify_genes` | Applies HUGO-unifier to compute and apply a cross-dataset gene symbol renaming table. | Fully deterministic | structural — versions only | From ec9d2f528036fc55ec122f55338e8a874b77dde7 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 10:34:55 +0200 Subject: [PATCH 23/46] Update pipeline-level snapshots --- tests/default.nf.test.snap | 11 +++++++++-- tests/main_pipeline_build.nf.test.snap | 11 +++++++++-- tests/main_pipeline_extend.nf.test.snap | 11 +++++++++-- tests/main_pipeline_qc.nf.test.snap | 11 +++++++++-- tests/main_pipeline_reference_mapping.nf.test.snap | 11 +++++++++-- tests/main_pipeline_sub.nf.test.snap | 10 +++++++--- 6 files changed, 52 insertions(+), 13 deletions(-) diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index cd8e83ad..f1cac52f 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -259,6 +259,13 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -279,9 +286,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-26T10:09:39.311745", + "timestamp": "2026-03-29T10:26:55.684056857", "meta": { - "nf-test": "0.9.5", + "nf-test": "0.9.4", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index e017f735..eca749f1 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -272,6 +272,13 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -292,9 +299,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-26T10:28:17.194294", + "timestamp": "2026-03-29T10:29:54.888502684", "meta": { - "nf-test": "0.9.5", + "nf-test": "0.9.4", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_extend.nf.test.snap b/tests/main_pipeline_extend.nf.test.snap index 606a79c5..13150e7b 100644 --- a/tests/main_pipeline_extend.nf.test.snap +++ b/tests/main_pipeline_extend.nf.test.snap @@ -191,6 +191,13 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -207,9 +214,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-24T21:16:45.188348", + "timestamp": "2026-03-29T10:24:43.828273462", "meta": { - "nf-test": "0.9.5", + "nf-test": "0.9.4", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index 038dcc7f..2db90c24 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -149,6 +149,13 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", @@ -168,9 +175,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-26T09:29:39.661493", + "timestamp": "2026-03-29T10:21:58.506298996", "meta": { - "nf-test": "0.9.5", + "nf-test": "0.9.4", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 7798a6e1..6c9b6727 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -191,6 +191,13 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -207,9 +214,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-26T09:36:00.222856", + "timestamp": "2026-03-29T10:22:27.294854553", "meta": { - "nf-test": "0.9.5", + "nf-test": "0.9.4", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_sub.nf.test.snap b/tests/main_pipeline_sub.nf.test.snap index 81a98518..6bf33463 100644 --- a/tests/main_pipeline_sub.nf.test.snap +++ b/tests/main_pipeline_sub.nf.test.snap @@ -1,7 +1,7 @@ { "Should be able to perform subclustering": { "content": [ - 289, + 291, { "ADATA_EXTEND": { "anndata": "0.12.10", @@ -183,6 +183,8 @@ "per_group/condition:combat-SRR28679756-0.5_leiden:7/characteristic_genes", "per_group/condition:combat-SRR28679756-0.5_leiden:8", "per_group/condition:combat-SRR28679756-0.5_leiden:8/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:9", + "per_group/condition:combat-SRR28679756-0.5_leiden:9/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:0", "per_group/condition:combat-SRR28679756-1.0_leiden:0/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:1", @@ -197,6 +199,8 @@ "per_group/condition:combat-SRR28679756-1.0_leiden:13/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:14", "per_group/condition:combat-SRR28679756-1.0_leiden:14/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:15", + "per_group/condition:combat-SRR28679756-1.0_leiden:15/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:2", "per_group/condition:combat-SRR28679756-1.0_leiden:2/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:3", @@ -589,9 +593,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-26T09:48:21.621218", + "timestamp": "2026-03-29T10:17:32.99372406", "meta": { - "nf-test": "0.9.5", + "nf-test": "0.9.4", "nextflow": "25.10.4" } } From 2d202831b321195985cb136909968c66d5274afc Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 11:36:53 +0200 Subject: [PATCH 24/46] Improve snapshot anndata yaml formatting --- .../celda/decontx/tests/main.nf.test.snap | 188 +++++++++- .../rankaggregate/tests/main.nf.test.snap | 43 ++- .../scanpy/bbknn/tests/main.nf.test.snap | 39 +- .../scanpy/combat/tests/main.nf.test.snap | 43 ++- .../scanpy/filter/tests/main.nf.test.snap | 150 +++++++- .../scanpy/harmony/tests/main.nf.test.snap | 39 +- .../local/scanpy/hvgs/tests/main.nf.test.snap | 123 ++++++- .../scanpy/leiden/tests/main.nf.test.snap | 41 ++- .../scanpy/neighbors/tests/main.nf.test.snap | 41 ++- .../local/scanpy/paga/tests/main.nf.test.snap | 43 ++- .../local/scanpy/pca/tests/main.nf.test.snap | 37 +- .../rankgenesgroups/tests/main.nf.test.snap | 90 ++++- .../local/scanpy/umap/tests/main.nf.test.snap | 43 ++- .../pseudobulk/tests/main.nf.test.snap | 79 +++- .../scvitools/scanvi/tests/main.nf.test.snap | 50 ++- .../scvitools/scvi/tests/main.nf.test.snap | 39 +- .../integration/tests/main.nf.test.snap | 54 ++- modules/local/soupx/tests/main.nf.test.snap | 76 +++- nf-test.config | 2 +- .../tests/main.nf.test.snap | 337 +++++++++++++++++- .../doublet_detection/tests/main.nf.test.snap | 37 +- .../local/finalize/tests/main.nf.test.snap | 145 +++++++- .../local/integrate/tests/main.nf.test.snap | 170 ++++++++- .../pseudobulking/tests/main.nf.test.snap | 39 +- .../quality_control/tests/main.nf.test.snap | 54 ++- .../local/unify/tests/main.nf.test.snap | 123 ++++++- .../local/unify_genes/tests/main.nf.test.snap | 109 +++++- 27 files changed, 2125 insertions(+), 109 deletions(-) diff --git a/modules/local/celda/decontx/tests/main.nf.test.snap b/modules/local/celda/decontx/tests/main.nf.test.snap index 2e2f04b7..6dac3570 100644 --- a/modules/local/celda/decontx/tests/main.nf.test.snap +++ b/modules/local/celda/decontx/tests/main.nf.test.snap @@ -8,9 +8,42 @@ "celda": "1.26.0" } }, - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T16:50:38.098489322", + "timestamp": "2026-03-29T11:18:08.048436803", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -25,9 +58,42 @@ "celda": "1.26.0" } }, - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T16:51:40.101871935", + "timestamp": "2026-03-29T11:21:17.900019258", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -42,9 +108,42 @@ "celda": "1.26.0" } }, - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T16:54:46.7175794", + "timestamp": "2026-03-29T11:24:51.060377162", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -59,9 +158,43 @@ "celda": "1.26.0" } }, - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - ambient_corrected_decontx\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "ambient_corrected_decontx", + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T16:08:11.366375453", + "timestamp": "2026-03-29T11:25:48.190196709", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -109,9 +242,42 @@ "celda": "1.26.0" } }, - "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 38234, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T16:46:02.200693929", + "timestamp": "2026-03-29T11:23:38.441578672", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -150,4 +316,4 @@ "nextflow": "25.10.2" } } -} +} \ No newline at end of file diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test.snap b/modules/local/liana/rankaggregate/tests/main.nf.test.snap index 9c36fc6e..47f65e87 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test.snap +++ b/modules/local/liana/rankaggregate/tests/main.nf.test.snap @@ -75,9 +75,48 @@ "python": "3.12.12", "scanpy": "1.11.5" }, - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - liana_res\n - log1p\n - neighbors\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "leiden", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "X_pca" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "X_pca", + "leiden", + "liana_res", + "log1p", + "neighbors" + ] + } ], - "timestamp": "2026-03-28T17:34:38.380015311", + "timestamp": "2026-03-29T11:18:40.019088419", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/bbknn/tests/main.nf.test.snap b/modules/local/scanpy/bbknn/tests/main.nf.test.snap index 67dfa61e..f6f4bfac 100644 --- a/modules/local/scanpy/bbknn/tests/main.nf.test.snap +++ b/modules/local/scanpy/bbknn/tests/main.nf.test.snap @@ -42,9 +42,44 @@ "scanpy": "1.11.5" } }, - "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - PCs\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - neighbors\n - pca\n" + { + "n_obs": 38234, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "PCs" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "neighbors", + "pca" + ] + } ], - "timestamp": "2026-03-25T15:44:30.059984814", + "timestamp": "2026-03-29T11:17:44.928430046", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/combat/tests/main.nf.test.snap b/modules/local/scanpy/combat/tests/main.nf.test.snap index 014679c3..d06f446c 100644 --- a/modules/local/scanpy/combat/tests/main.nf.test.snap +++ b/modules/local/scanpy/combat/tests/main.nf.test.snap @@ -54,9 +54,48 @@ "scanpy": "1.12" } }, - "n_obs: 38234\nn_vars: 100\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\n - X_emb\n - X_pca\nvarm:\n - PCs\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n - pca\n" + { + "n_obs": 38234, + "n_vars": 100, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "dispersions", + "dispersions_norm", + "highly_variable", + "means" + ] + }, + "layers": [ + + ], + "obsm": [ + "X_emb", + "X_pca" + ], + "varm": [ + "PCs" + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "hvg", + "log1p", + "pca" + ] + } ], - "timestamp": "2026-03-25T15:44:41.450577055", + "timestamp": "2026-03-29T11:17:34.118271552", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/filter/tests/main.nf.test.snap b/modules/local/scanpy/filter/tests/main.nf.test.snap index e88811ec..5ba7fb15 100644 --- a/modules/local/scanpy/filter/tests/main.nf.test.snap +++ b/modules/local/scanpy/filter/tests/main.nf.test.snap @@ -54,9 +54,55 @@ "scanpy": "1.12" } }, - "n_obs: 5719\nn_vars: 992\nobs:\n index: _index\n columns:\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - mean_counts\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 5719, + "n_vars": 992, + "obs": { + "index": "_index", + "columns": [ + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "mean_counts", + "mt", + "n_cells", + "n_cells_by_counts", + "n_counts", + "pct_dropout_by_counts", + "symbols", + "total_counts" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T22:09:49.666922142", + "timestamp": "2026-03-29T11:18:14.694442933", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -127,9 +173,55 @@ "scanpy": "1.12" } }, - "n_obs: 5719\nn_vars: 992\nobs:\n index: _index\n columns:\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - mean_counts\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 5719, + "n_vars": 992, + "obs": { + "index": "_index", + "columns": [ + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "mean_counts", + "mt", + "n_cells", + "n_cells_by_counts", + "n_counts", + "pct_dropout_by_counts", + "symbols", + "total_counts" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T22:09:25.003400702", + "timestamp": "2026-03-29T11:17:17.630245843", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -167,9 +259,55 @@ "scanpy": "1.12" } }, - "n_obs: 5719\nn_vars: 992\nobs:\n index: _index\n columns:\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - mean_counts\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 5719, + "n_vars": 992, + "obs": { + "index": "_index", + "columns": [ + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "mean_counts", + "mt", + "n_cells", + "n_cells_by_counts", + "n_counts", + "pct_dropout_by_counts", + "symbols", + "total_counts" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T22:10:39.378358618", + "timestamp": "2026-03-29T11:20:39.503874531", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/harmony/tests/main.nf.test.snap b/modules/local/scanpy/harmony/tests/main.nf.test.snap index c907b62b..5a847531 100644 --- a/modules/local/scanpy/harmony/tests/main.nf.test.snap +++ b/modules/local/scanpy/harmony/tests/main.nf.test.snap @@ -48,12 +48,45 @@ "scanpy": "1.12" } }, - "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_emb\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 38234, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_emb" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T16:50:30.59991269", + "timestamp": "2026-03-29T11:17:47.094134151", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" } } -} +} \ No newline at end of file diff --git a/modules/local/scanpy/hvgs/tests/main.nf.test.snap b/modules/local/scanpy/hvgs/tests/main.nf.test.snap index f0028d60..e9865ea7 100644 --- a/modules/local/scanpy/hvgs/tests/main.nf.test.snap +++ b/modules/local/scanpy/hvgs/tests/main.nf.test.snap @@ -7,9 +7,46 @@ "scanpy": "1.12" } }, - "n_obs: 38234\nn_vars: 100\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" + { + "n_obs": 38234, + "n_vars": 100, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "dispersions", + "dispersions_norm", + "highly_variable", + "means" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "hvg", + "log1p" + ] + } ], - "timestamp": "2026-03-25T15:44:54.05696891", + "timestamp": "2026-03-29T11:18:05.314404083", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -23,9 +60,46 @@ "scanpy": "1.12" } }, - "n_obs: 38234\nn_vars: 251\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" + { + "n_obs": 38234, + "n_vars": 251, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "dispersions", + "dispersions_norm", + "highly_variable", + "means" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "hvg", + "log1p" + ] + } ], - "timestamp": "2026-03-25T15:44:22.933975481", + "timestamp": "2026-03-29T11:17:05.806436168", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -78,9 +152,46 @@ "scanpy": "1.12" } }, - "n_obs: 38234\nn_vars: 100\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" + { + "n_obs": 38234, + "n_vars": 100, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "dispersions", + "dispersions_norm", + "highly_variable", + "means" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "hvg", + "log1p" + ] + } ], - "timestamp": "2026-03-25T15:45:40.075913692", + "timestamp": "2026-03-29T11:19:17.695541068", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/leiden/tests/main.nf.test.snap b/modules/local/scanpy/leiden/tests/main.nf.test.snap index 4404f13a..cdb54f1d 100644 --- a/modules/local/scanpy/leiden/tests/main.nf.test.snap +++ b/modules/local/scanpy/leiden/tests/main.nf.test.snap @@ -58,9 +58,46 @@ "scanpy": "1.12" } }, - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - neighbors\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "leiden", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "X_pca" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "X_pca", + "leiden", + "neighbors" + ] + } ], - "timestamp": "2026-03-28T22:11:18.707514777", + "timestamp": "2026-03-29T11:17:20.376586064", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/neighbors/tests/main.nf.test.snap b/modules/local/scanpy/neighbors/tests/main.nf.test.snap index 4aca825d..f87886a3 100644 --- a/modules/local/scanpy/neighbors/tests/main.nf.test.snap +++ b/modules/local/scanpy/neighbors/tests/main.nf.test.snap @@ -40,9 +40,46 @@ "scanpy": "1.12" } }, - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - neighbors\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "leiden", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "X_pca" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "X_pca", + "leiden", + "neighbors" + ] + } ], - "timestamp": "2026-03-28T16:08:43.931518403", + "timestamp": "2026-03-29T11:17:42.474824863", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/paga/tests/main.nf.test.snap b/modules/local/scanpy/paga/tests/main.nf.test.snap index 1a591bf1..4c40f84d 100644 --- a/modules/local/scanpy/paga/tests/main.nf.test.snap +++ b/modules/local/scanpy/paga/tests/main.nf.test.snap @@ -112,9 +112,48 @@ "scanpy": "1.12" } }, - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - leiden_sizes\n - neighbors\n - paga\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "leiden", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "X_pca" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "X_pca", + "leiden", + "leiden_sizes", + "neighbors", + "paga" + ] + } ], - "timestamp": "2026-03-28T16:35:55.348547031", + "timestamp": "2026-03-29T11:17:22.514762435", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index 1690e2ca..65d4e536 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -47,9 +47,42 @@ "scanpy": "1.12" } }, - "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\nvarp:\nuns:\n - X_pca\n" + { + "n_obs": 38234, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "X_pca" + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "X_pca" + ] + } ], - "timestamp": "2026-03-25T15:44:23.378021891", + "timestamp": "2026-03-29T11:17:21.253081099", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap index 99389b75..9262a494 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap @@ -117,9 +117,48 @@ "scanpy": "1.12" } }, - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - log1p\n - neighbors\n - rank_genes_groups\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "leiden", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "X_pca" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "X_pca", + "leiden", + "log1p", + "neighbors", + "rank_genes_groups" + ] + } ], - "timestamp": "2026-03-28T17:38:32.692483999", + "timestamp": "2026-03-29T11:17:32.94515289", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -176,9 +215,52 @@ "scanpy": "1.12" } }, - "n_obs: 4386\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - leiden\n - sample\n - sample_original\nvar:\n index: _index\n columns:\n - symbols\nlayers:\nobsm:\n - X_pca\nvarm:\n - PCs\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - leiden\n - log1p\n - neighbors\n - pca\n - rank_genes_groups\n" + { + "n_obs": 4386, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "leiden", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "PCs" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "leiden", + "log1p", + "neighbors", + "pca", + "rank_genes_groups" + ] + } ], - "timestamp": "2026-03-28T17:39:26.160880497", + "timestamp": "2026-03-29T11:19:18.847060178", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scanpy/umap/tests/main.nf.test.snap b/modules/local/scanpy/umap/tests/main.nf.test.snap index ebb9aeb9..c1eb3782 100644 --- a/modules/local/scanpy/umap/tests/main.nf.test.snap +++ b/modules/local/scanpy/umap/tests/main.nf.test.snap @@ -47,9 +47,48 @@ "scanpy": "1.12" } }, - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_pca\n - X_umap\nvarm:\n - X_pca\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - X_pca\n - leiden\n - neighbors\n - umap\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "leiden", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca", + "X_umap" + ], + "varm": [ + "X_pca" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "X_pca", + "leiden", + "neighbors", + "umap" + ] + } ], - "timestamp": "2026-03-25T15:44:47.312318602", + "timestamp": "2026-03-29T11:17:48.823449269", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scimilarity/pseudobulk/tests/main.nf.test.snap b/modules/local/scimilarity/pseudobulk/tests/main.nf.test.snap index c0848637..b8f9da4d 100644 --- a/modules/local/scimilarity/pseudobulk/tests/main.nf.test.snap +++ b/modules/local/scimilarity/pseudobulk/tests/main.nf.test.snap @@ -32,9 +32,44 @@ "scimilarity": "0.4.1" } }, - "n_obs: 3\nn_vars: 9887\nobs:\n index: _index\n columns:\n - cells\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - count_nonzero\n - sum\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 3, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "cells", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + "count_nonzero", + "sum" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T17:48:52.497299288", + "timestamp": "2026-03-29T11:18:26.581328121", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -73,9 +108,45 @@ "scimilarity": "0.4.1" } }, - "n_obs: 43\nn_vars: 9887\nobs:\n index: _index\n columns:\n - cells\n - leiden\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - count_nonzero\n - sum\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 43, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "cells", + "leiden", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + "count_nonzero", + "sum" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T17:49:47.066833253", + "timestamp": "2026-03-29T11:20:35.310554907", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scvitools/scanvi/tests/main.nf.test.snap b/modules/local/scvitools/scanvi/tests/main.nf.test.snap index 58ead009..f1aaf8bc 100644 --- a/modules/local/scvitools/scanvi/tests/main.nf.test.snap +++ b/modules/local/scvitools/scanvi/tests/main.nf.test.snap @@ -70,9 +70,55 @@ "scvi": "1.3.3" } }, - "n_obs: 38234\nn_vars: 100\nobs:\n index: _index\n columns:\n - _scvi_batch\n - _scvi_labels\n - label:scANVI\n - leiden\n - sample\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - means\nlayers:\nobsm:\n - X_emb\n - X_pca\nvarm:\n - PCs\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - hvg\n - leiden\n - log1p\n - neighbors\n - pca\n" + { + "n_obs": 38234, + "n_vars": 100, + "obs": { + "index": "_index", + "columns": [ + "_scvi_batch", + "_scvi_labels", + "label:scANVI", + "leiden", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "dispersions", + "dispersions_norm", + "highly_variable", + "means" + ] + }, + "layers": [ + + ], + "obsm": [ + "X_emb", + "X_pca" + ], + "varm": [ + "PCs" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "hvg", + "leiden", + "log1p", + "neighbors", + "pca" + ] + } ], - "timestamp": "2026-03-28T16:19:18.135819708", + "timestamp": "2026-03-29T11:22:21.217764975", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/scvitools/scvi/tests/main.nf.test.snap b/modules/local/scvitools/scvi/tests/main.nf.test.snap index 0613f0e8..96d72d6c 100644 --- a/modules/local/scvitools/scvi/tests/main.nf.test.snap +++ b/modules/local/scvitools/scvi/tests/main.nf.test.snap @@ -61,9 +61,44 @@ "scvi": "1.3.3" } }, - "n_obs: 38234\nn_vars: 9887\nobs:\n index: _index\n columns:\n - _scvi_batch\n - _scvi_labels\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_emb\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 38234, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "_scvi_batch", + "_scvi_labels", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_emb" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T16:17:00.032046985", + "timestamp": "2026-03-29T11:23:09.044443613", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/seurat/integration/tests/main.nf.test.snap b/modules/local/seurat/integration/tests/main.nf.test.snap index 1ea588f1..fc44d34f 100644 --- a/modules/local/seurat/integration/tests/main.nf.test.snap +++ b/modules/local/seurat/integration/tests/main.nf.test.snap @@ -41,9 +41,59 @@ "anndataR": "1.0.2" } }, - "n_obs: 27350\nn_vars: 100\nobs:\n index: _index\n columns:\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - mean_counts\n - means\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - total_counts\nlayers:\nobsm:\n - X_emb\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" + { + "n_obs": 27350, + "n_vars": 100, + "obs": { + "index": "_index", + "columns": [ + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "dispersions", + "dispersions_norm", + "highly_variable", + "mean_counts", + "means", + "mt", + "n_cells", + "n_cells_by_counts", + "n_counts", + "pct_dropout_by_counts", + "total_counts" + ] + }, + "layers": [ + + ], + "obsm": [ + "X_emb" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "hvg", + "log1p" + ] + } ], - "timestamp": "2026-03-25T15:46:39.138426369", + "timestamp": "2026-03-29T11:22:37.77182437", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/soupx/tests/main.nf.test.snap b/modules/local/soupx/tests/main.nf.test.snap index 17551e84..952b77bb 100644 --- a/modules/local/soupx/tests/main.nf.test.snap +++ b/modules/local/soupx/tests/main.nf.test.snap @@ -42,9 +42,42 @@ "Seurat": "5.4.0" } }, - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T17:53:34.957086995", + "timestamp": "2026-03-29T11:17:40.208088329", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -60,12 +93,45 @@ "Seurat": "5.4.0" } }, - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_soupx\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + "ambient_corrected_soupx" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T17:54:16.513364716", + "timestamp": "2026-03-29T11:21:01.296297672", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" } } -} +} \ No newline at end of file diff --git a/nf-test.config b/nf-test.config index 4c9eeb54..78ff087b 100644 --- a/nf-test.config +++ b/nf-test.config @@ -20,7 +20,7 @@ config { // load the necessary plugins plugins { load "nft-utils@0.0.3" - load "nft-anndata@0.4.0" + loadFromFile "testing/plugins/nft-anndata-0.4.1.jar" load "nft-csv@0.1.0" } } diff --git a/subworkflows/local/ambient_correction/tests/main.nf.test.snap b/subworkflows/local/ambient_correction/tests/main.nf.test.snap index f1b3b7e0..2d051d45 100644 --- a/subworkflows/local/ambient_correction/tests/main.nf.test.snap +++ b/subworkflows/local/ambient_correction/tests/main.nf.test.snap @@ -17,9 +17,42 @@ [ "versions.yml:md5,f9ea95abb10a7769d50d14fcaa5734ee" ], - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T15:55:43.229893039", + "timestamp": "2026-03-29T11:28:03.511988284", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -30,9 +63,42 @@ [ "versions.yml:md5,f9ea95abb10a7769d50d14fcaa5734ee" ], - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_decontx\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + "ambient_corrected_decontx" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T15:49:17.935387052", + "timestamp": "2026-03-29T11:21:35.00820843", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -44,9 +110,42 @@ "versions.yml:md5,1d70371b0f0ca5e50f7ba70335f8946f", "versions.yml:md5,e6e98e83cbc9a2924c66e901445bbc4f" ], - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T16:00:43.278473562", + "timestamp": "2026-03-29T11:32:46.973630904", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -57,9 +156,42 @@ [ "versions.yml:md5,f9ea95abb10a7769d50d14fcaa5734ee" ], - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_decontx\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + "ambient_corrected_decontx" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T15:48:15.985988809", + "timestamp": "2026-03-29T11:18:56.290966056", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -70,9 +202,42 @@ [ "versions.yml:md5,0266faf0b40a7b86ec9f2b1948f8c7aa" ], - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T15:56:25.809642699", + "timestamp": "2026-03-29T11:28:48.515147711", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -96,9 +261,44 @@ [ "versions.yml:md5,2717cb5f250a65aec0a76a456f7028ba" ], - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - _scvi_batch\n - _scvi_labels\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_scar\nobsm:\nvarm:\n - ambient_profile\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "_scvi_batch", + "_scvi_labels", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + "ambient_corrected_scar" + ], + "obsm": [ + + ], + "varm": [ + "ambient_profile" + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T15:51:33.678378475", + "timestamp": "2026-03-29T11:24:02.851605031", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -110,9 +310,42 @@ "versions.yml:md5,1d70371b0f0ca5e50f7ba70335f8946f", "versions.yml:md5,e6e98e83cbc9a2924c66e901445bbc4f" ], - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_cellbender\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + "ambient_corrected_cellbender" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T15:54:46.503094206", + "timestamp": "2026-03-29T11:27:11.134006387", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -123,9 +356,42 @@ [ "versions.yml:md5,0266faf0b40a7b86ec9f2b1948f8c7aa" ], - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - ambient_corrected_soupx\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + "ambient_corrected_soupx" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T15:50:04.360822128", + "timestamp": "2026-03-29T11:22:41.092799679", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -136,9 +402,44 @@ [ "versions.yml:md5,2717cb5f250a65aec0a76a456f7028ba" ], - "n_obs: 7373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - _scvi_batch\n - _scvi_labels\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\n - ambient_profile\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "_scvi_batch", + "_scvi_labels", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + "ambient_profile" + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-25T15:57:30.785675292", + "timestamp": "2026-03-29T11:29:53.928496596", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/doublet_detection/tests/main.nf.test.snap b/subworkflows/local/doublet_detection/tests/main.nf.test.snap index e1e7e74f..d7339e7b 100644 --- a/subworkflows/local/doublet_detection/tests/main.nf.test.snap +++ b/subworkflows/local/doublet_detection/tests/main.nf.test.snap @@ -18,9 +18,42 @@ } } ], - "n_obs: 5968\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 5968, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T19:43:37.850974576", + "timestamp": "2026-03-29T11:19:54.674217844", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/finalize/tests/main.nf.test.snap b/subworkflows/local/finalize/tests/main.nf.test.snap index 56337559..56c53a1e 100644 --- a/subworkflows/local/finalize/tests/main.nf.test.snap +++ b/subworkflows/local/finalize/tests/main.nf.test.snap @@ -24,9 +24,54 @@ } } ], - "n_obs: 23373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - celltypist:Adult_Human_Skin\n - celltypist:Adult_Human_Skin:conf\n - label\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - sample_original\n - scvi-global-1.0_leiden\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\nlayers:\nobsm:\n - X_scvi\nvarm:\nobsp:\nvarp:\nuns:\n - scvi-global-1.0_paga\n" + { + "n_obs": 23373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "scvi-global-1.0_leiden", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_scvi" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "scvi-global-1.0_paga" + ] + } ], - "timestamp": "2026-03-28T18:21:52.014648621", + "timestamp": "2026-03-29T11:12:29.040402189", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -65,9 +110,53 @@ } } ], - "n_obs: 23373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - celltypist:Adult_Human_Skin\n - celltypist:Adult_Human_Skin:conf\n - label\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - sample_original\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 23373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T18:23:22.810706464", + "timestamp": "2026-03-29T11:13:56.762622049", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -168,9 +257,53 @@ } } ], - "n_obs: 23373\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - celltypist:Adult_Human_Skin\n - celltypist:Adult_Human_Skin:conf\n - label\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - sample_original\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 23373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T18:22:37.732852134", + "timestamp": "2026-03-29T11:13:12.249331199", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/integrate/tests/main.nf.test.snap b/subworkflows/local/integrate/tests/main.nf.test.snap index f8582565..be6b7709 100644 --- a/subworkflows/local/integrate/tests/main.nf.test.snap +++ b/subworkflows/local/integrate/tests/main.nf.test.snap @@ -116,9 +116,62 @@ "versions.yml:md5,a6c1e0a77e0d31423a9d77edba85127d", "versions.yml:md5,d28b65c4c18c54e1abc34040b584b823" ], - "n_obs: 12940\nn_vars: 2077\nobs:\n index: _index\n columns:\n - batch\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - mean_counts\n - means\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\n - X_emb\n - X_pca\nvarm:\n - PCs\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n - pca\n" + { + "n_obs": 12940, + "n_vars": 2077, + "obs": { + "index": "_index", + "columns": [ + "batch", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "dispersions", + "dispersions_norm", + "highly_variable", + "mean_counts", + "means", + "mt", + "n_cells", + "n_cells_by_counts", + "n_counts", + "pct_dropout_by_counts", + "symbols", + "total_counts" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + "X_emb", + "X_pca" + ], + "varm": [ + "PCs" + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "hvg", + "log1p", + "pca" + ] + } ], - "timestamp": "2026-03-25T15:50:43.745384682", + "timestamp": "2026-03-29T11:24:13.787124189", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -237,9 +290,60 @@ "versions.yml:md5,d28b65c4c18c54e1abc34040b584b823", "versions.yml:md5,f838f281f13db0dd578a991df1d8b57c" ], - "n_obs: 12940\nn_vars: 2077\nobs:\n index: _index\n columns:\n - batch\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - mean_counts\n - means\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\n - X_emb\nvarm:\nobsp:\nvarp:\nuns:\n - hvg\n - log1p\n" + { + "n_obs": 12940, + "n_vars": 2077, + "obs": { + "index": "_index", + "columns": [ + "batch", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "dispersions", + "dispersions_norm", + "highly_variable", + "mean_counts", + "means", + "mt", + "n_cells", + "n_cells_by_counts", + "n_counts", + "pct_dropout_by_counts", + "symbols", + "total_counts" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + "X_emb" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "hvg", + "log1p" + ] + } ], - "timestamp": "2026-03-25T15:47:16.180497374", + "timestamp": "2026-03-29T11:19:08.193313955", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -252,9 +356,63 @@ "versions.yml:md5,ccf730637c4c61a84ac4a002bf9832e0", "versions.yml:md5,d28b65c4c18c54e1abc34040b584b823" ], - "n_obs: 12940\nn_vars: 2077\nobs:\n index: _index\n columns:\n - batch\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - dispersions\n - dispersions_norm\n - highly_variable\n - mean_counts\n - means\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\n - counts\nobsm:\n - X_pca\nvarm:\n - PCs\nobsp:\n - connectivities\n - distances\nvarp:\nuns:\n - hvg\n - log1p\n - neighbors\n - pca\n" + { + "n_obs": 12940, + "n_vars": 2077, + "obs": { + "index": "_index", + "columns": [ + "batch", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "dispersions", + "dispersions_norm", + "highly_variable", + "mean_counts", + "means", + "mt", + "n_cells", + "n_cells_by_counts", + "n_counts", + "pct_dropout_by_counts", + "symbols", + "total_counts" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "PCs" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "hvg", + "log1p", + "neighbors", + "pca" + ] + } ], - "timestamp": "2026-03-25T15:49:08.65878862", + "timestamp": "2026-03-29T11:22:31.479708062", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/pseudobulking/tests/main.nf.test.snap b/subworkflows/local/pseudobulking/tests/main.nf.test.snap index 14cb70f8..1c04a6ac 100644 --- a/subworkflows/local/pseudobulking/tests/main.nf.test.snap +++ b/subworkflows/local/pseudobulking/tests/main.nf.test.snap @@ -58,9 +58,44 @@ "versions.yml:md5,7629f78da2c667f7f5975f67b4cc521c" ] }, - "n_obs: 3\nn_vars: 9887\nobs:\n index: _index\n columns:\n - cells\n - sample\nvar:\n index: _index\n columns:\nlayers:\n - count_nonzero\n - sum\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 3, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "cells", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + "count_nonzero", + "sum" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T18:09:14.725182453", + "timestamp": "2026-03-29T11:18:26.343309887", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/quality_control/tests/main.nf.test.snap b/subworkflows/local/quality_control/tests/main.nf.test.snap index ae1b3188..1d61e4c6 100644 --- a/subworkflows/local/quality_control/tests/main.nf.test.snap +++ b/subworkflows/local/quality_control/tests/main.nf.test.snap @@ -323,9 +323,59 @@ ], 12939, 9887, - "n_obs: 12939\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - n_counts\n - n_genes\n - n_genes_by_counts\n - pct_counts_mt\n - sample\n - sample_original\n - total_counts\n - total_counts_mt\nvar:\n index: _index\n columns:\n - mean_counts\n - mt\n - n_cells\n - n_cells_by_counts\n - n_counts\n - pct_dropout_by_counts\n - symbols\n - total_counts\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12939, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "mean_counts", + "mt", + "n_cells", + "n_cells_by_counts", + "n_counts", + "pct_dropout_by_counts", + "symbols", + "total_counts" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T19:46:31.986728169", + "timestamp": "2026-03-29T11:24:39.776574078", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/unify/tests/main.nf.test.snap b/subworkflows/local/unify/tests/main.nf.test.snap index 3b95401a..89a428e5 100644 --- a/subworkflows/local/unify/tests/main.nf.test.snap +++ b/subworkflows/local/unify/tests/main.nf.test.snap @@ -100,9 +100,46 @@ "versions.yml:md5,f4baeb211a033b2534fb83ba7ec2cd86" ] }, - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - sample\n - sample_original\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T19:24:17.42519548", + "timestamp": "2026-03-29T11:17:31.315941656", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -213,9 +250,46 @@ "versions.yml:md5,f4baeb211a033b2534fb83ba7ec2cd86" ] }, - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - sample\n - sample_original\nvar:\n index: _index\n columns:\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T18:05:26.745577508", + "timestamp": "2026-03-29T11:22:29.327390466", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -383,9 +457,46 @@ "versions.yml:md5,f4baeb211a033b2534fb83ba7ec2cd86" ] }, - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - batch\n - condition\n - label\n - sample\nvar:\n index: _index\n columns:\n - original_index\n - symbols\nlayers:\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "original_index", + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T19:25:29.064608355", + "timestamp": "2026-03-29T11:19:53.355480172", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/unify_genes/tests/main.nf.test.snap b/subworkflows/local/unify_genes/tests/main.nf.test.snap index f2653cbb..d79ced95 100644 --- a/subworkflows/local/unify_genes/tests/main.nf.test.snap +++ b/subworkflows/local/unify_genes/tests/main.nf.test.snap @@ -27,9 +27,42 @@ "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" ] }, - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T18:02:45.786444117", + "timestamp": "2026-03-29T11:17:56.776337553", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -161,10 +194,76 @@ "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" ] }, - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n", - "n_obs: 12940\nn_vars: 9887\nobs:\n index: _index\n columns:\n - sample\nvar:\n index: _index\n columns:\n - symbols\nlayers:\n - counts\nobsm:\nvarm:\nobsp:\nvarp:\nuns:\n" + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } ], - "timestamp": "2026-03-28T18:03:47.506803742", + "timestamp": "2026-03-29T11:20:09.647383365", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" From 0182e9ee05c8f42ab0a5103e124d56df70ca8a4b Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 11:49:31 +0200 Subject: [PATCH 25/46] Switch to nft-anndata 0.4.1 from registry --- nf-test.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nf-test.config b/nf-test.config index 78ff087b..2eaa14f0 100644 --- a/nf-test.config +++ b/nf-test.config @@ -20,7 +20,7 @@ config { // load the necessary plugins plugins { load "nft-utils@0.0.3" - loadFromFile "testing/plugins/nft-anndata-0.4.1.jar" + load "nft-anndata@0.4.1" load "nft-csv@0.1.0" } } From 3cf6370daafc4c07ae61e1445a1568551b77aaad Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 13:21:54 +0200 Subject: [PATCH 26/46] Update some more module and sw tests --- .../local/adata/entropy/tests/main.nf.test | 8 +- .../adata/entropy/tests/main.nf.test.snap | 48 +++- modules/local/adata/merge/main.nf | 2 +- modules/local/adata/merge/tests/main.nf.test | 22 +- .../local/adata/merge/tests/main.nf.test.snap | 252 +++++++++++++++++- modules/local/adata/mygene/tests/main.nf.test | 8 +- .../adata/mygene/tests/main.nf.test.snap | 53 +++- .../adata/prepcellxgene/tests/main.nf.test | 8 +- .../prepcellxgene/tests/main.nf.test.snap | 98 ++++++- .../local/adata/setindex/tests/main.nf.test | 16 +- .../adata/setindex/tests/main.nf.test.snap | 88 +++++- .../local/adata/splitcol/tests/main.nf.test | 7 +- .../adata/splitcol/tests/main.nf.test.snap | 116 +++++++- .../adata/splitembeddings/tests/main.nf.test | 1 - .../doublet_removal/tests/main.nf.test | 7 +- .../doublet_removal/tests/main.nf.test.snap | 47 +++- .../local/scanpy/cellcycle/tests/main.nf.test | 8 +- .../scanpy/cellcycle/tests/main.nf.test.snap | 47 +++- .../local/scanpy/sample/tests/main.nf.test | 16 +- .../scanpy/sample/tests/main.nf.test.snap | 88 +++++- subworkflows/local/combine/tests/main.nf.test | 4 +- .../local/combine/tests/main.nf.test.snap | 140 +++++++--- 22 files changed, 1000 insertions(+), 84 deletions(-) diff --git a/modules/local/adata/entropy/tests/main.nf.test b/modules/local/adata/entropy/tests/main.nf.test index 83d6e242..a6f708f1 100644 --- a/modules/local/adata/entropy/tests/main.nf.test +++ b/modules/local/adata/entropy/tests/main.nf.test @@ -28,9 +28,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/adata/entropy/tests/main.nf.test.snap b/modules/local/adata/entropy/tests/main.nf.test.snap index 8ba842dd..4edb7149 100644 --- a/modules/local/adata/entropy/tests/main.nf.test.snap +++ b/modules/local/adata/entropy/tests/main.nf.test.snap @@ -93,9 +93,55 @@ "versions": [ "versions.yml:md5,06c3be8b97dfd251b6aef3221b56d5fc" ] + }, + { + "ADATA_ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 38234, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "leiden", + "sample", + "test:entropy" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_pca" + ], + "varm": [ + "PCs" + ], + "obsp": [ + "connectivities", + "distances" + ], + "varp": [ + + ], + "uns": [ + "leiden", + "neighbors", + "pca" + ] } ], - "timestamp": "2026-03-22T09:52:42.901052235", + "timestamp": "2026-03-29T12:57:45.425691493", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/modules/local/adata/merge/main.nf b/modules/local/adata/merge/main.nf index b5ada8d2..7d24b262 100644 --- a/modules/local/adata/merge/main.nf +++ b/modules/local/adata/merge/main.nf @@ -9,7 +9,7 @@ process ADATA_MERGE { 'community.wave.seqera.io/library/harmonypy_anndata_leidenalg_numpy_pruned:43066d5f86f18261' }" input: - tuple val(meta), path(h5ads) + tuple val(meta), path(h5ads, stageAs: 'input/sample_?.h5ad') tuple val(meta2), path(base) output: diff --git a/modules/local/adata/merge/tests/main.nf.test b/modules/local/adata/merge/tests/main.nf.test index e9570946..6cce785d 100644 --- a/modules/local/adata/merge/tests/main.nf.test +++ b/modules/local/adata/merge/tests/main.nf.test @@ -48,8 +48,17 @@ nextflow_process { } then { + def adata_outer = anndata(process.out.outer[0][1]) + def adata_inner = anndata(process.out.inner[0][1]) + def adata_integrate = anndata(process.out.integrate[0][1]) assert process.success - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata_outer.yaml, + adata_inner.yaml, + adata_integrate.yaml + ).match() } } @@ -96,8 +105,17 @@ nextflow_process { } then { + def adata_outer = anndata(process.out.outer[0][1]) + def adata_inner = anndata(process.out.inner[0][1]) + def adata_integrate = anndata(process.out.integrate[0][1]) assert process.success - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata_outer.yaml, + adata_inner.yaml, + adata_integrate.yaml + ).match() } } diff --git a/modules/local/adata/merge/tests/main.nf.test.snap b/modules/local/adata/merge/tests/main.nf.test.snap index a00ab4b1..76f21681 100644 --- a/modules/local/adata/merge/tests/main.nf.test.snap +++ b/modules/local/adata/merge/tests/main.nf.test.snap @@ -62,12 +62,134 @@ "versions": [ "versions.yml:md5,f90dc837c47fb9c2207d021f2201c357" ] + }, + { + "ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 20313, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + }, + { + "n_obs": 20313, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + }, + { + "n_obs": 20313, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:43:43.452579031", + "timestamp": "2026-03-29T12:57:53.789595572", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run with base": { @@ -133,12 +255,134 @@ "versions": [ "versions.yml:md5,f90dc837c47fb9c2207d021f2201c357" ] + }, + { + "ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 20313, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + }, + { + "n_obs": 20313, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:44:08.746876922", + "timestamp": "2026-03-29T12:58:39.973626992", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without base - stub": { diff --git a/modules/local/adata/mygene/tests/main.nf.test b/modules/local/adata/mygene/tests/main.nf.test index e6e99f7a..75cf7191 100644 --- a/modules/local/adata/mygene/tests/main.nf.test +++ b/modules/local/adata/mygene/tests/main.nf.test @@ -25,9 +25,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/adata/mygene/tests/main.nf.test.snap b/modules/local/adata/mygene/tests/main.nf.test.snap index b49b8fdb..9845b96d 100644 --- a/modules/local/adata/mygene/tests/main.nf.test.snap +++ b/modules/local/adata/mygene/tests/main.nf.test.snap @@ -26,11 +26,11 @@ ] } ], + "timestamp": "2025-06-01T20:33:41.374900824", "meta": { "nf-test": "0.9.0", "nextflow": "25.04.2" - }, - "timestamp": "2025-06-01T20:33:41.374900824" + } }, "Should run without failures": { "content": [ @@ -57,12 +57,53 @@ "versions": [ "versions.yml:md5,8b217b33308585e6caf9da8cf1c23e2e" ] + }, + { + "ADATA_MYGENE": { + "anndata": "0.12.7", + "mygene": "3.2.2", + "python": "3.13.11" + } + }, + { + "n_obs": 7373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], + "timestamp": "2026-03-29T12:58:00.211862297", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" - }, - "timestamp": "2025-12-30T17:40:13.292339816" + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } } } \ No newline at end of file diff --git a/modules/local/adata/prepcellxgene/tests/main.nf.test b/modules/local/adata/prepcellxgene/tests/main.nf.test index 680dd004..2e92aa8a 100644 --- a/modules/local/adata/prepcellxgene/tests/main.nf.test +++ b/modules/local/adata/prepcellxgene/tests/main.nf.test @@ -25,9 +25,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/adata/prepcellxgene/tests/main.nf.test.snap b/modules/local/adata/prepcellxgene/tests/main.nf.test.snap index 3a5dd1bc..58b78d2a 100644 --- a/modules/local/adata/prepcellxgene/tests/main.nf.test.snap +++ b/modules/local/adata/prepcellxgene/tests/main.nf.test.snap @@ -57,12 +57,106 @@ "versions": [ "versions.yml:md5,374fc58d78d5ecc45ac7cd4b1c5a4012" ] + }, + { + "ADATA_PREPCELLXGENE": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 23364, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "bbknn-global-0.5:entropy", + "bbknn-global-0.5_leiden", + "bbknn-global-1.0:entropy", + "bbknn-global-1.0_leiden", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "combat-global-0.5:entropy", + "combat-global-0.5_leiden", + "combat-global-1.0:entropy", + "combat-global-1.0_leiden", + "condition", + "harmony-global-0.5:entropy", + "harmony-global-0.5_leiden", + "harmony-global-1.0:entropy", + "harmony-global-1.0_leiden", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "scvi-global-0.5:entropy", + "scvi-global-0.5_leiden", + "scvi-global-1.0:entropy", + "scvi-global-1.0_leiden", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "intersection" + ] + }, + "layers": [ + + ], + "obsm": [ + "X_bbknn-global_umap", + "X_combat-global_umap", + "X_harmony-global_umap", + "X_scvi-global_umap", + "combat", + "harmony", + "scvi" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "bbknn-global-0.5_characteristic_genes", + "bbknn-global-0.5_paga", + "bbknn-global-1.0_characteristic_genes", + "bbknn-global-1.0_paga", + "combat-global-0.5_characteristic_genes", + "combat-global-0.5_liana", + "combat-global-0.5_paga", + "combat-global-1.0_characteristic_genes", + "combat-global-1.0_liana", + "combat-global-1.0_paga", + "harmony-global-0.5_characteristic_genes", + "harmony-global-0.5_paga", + "harmony-global-1.0_characteristic_genes", + "harmony-global-1.0_paga", + "log1p", + "scvi-global-0.5_characteristic_genes", + "scvi-global-0.5_paga", + "scvi-global-1.0_characteristic_genes", + "scvi-global-1.0_paga" + ] } ], - "timestamp": "2026-03-16T15:35:08.942215746", + "timestamp": "2026-03-29T12:57:46.020211425", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/adata/setindex/tests/main.nf.test b/modules/local/adata/setindex/tests/main.nf.test index 81967669..9a540ba9 100644 --- a/modules/local/adata/setindex/tests/main.nf.test +++ b/modules/local/adata/setindex/tests/main.nf.test @@ -27,9 +27,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -54,9 +58,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/adata/setindex/tests/main.nf.test.snap b/modules/local/adata/setindex/tests/main.nf.test.snap index 8fba2435..a482f423 100644 --- a/modules/local/adata/setindex/tests/main.nf.test.snap +++ b/modules/local/adata/setindex/tests/main.nf.test.snap @@ -24,12 +24,52 @@ "versions": [ "versions.yml:md5,3849ee644c0cc7554e8328607967f0f0" ] + }, + { + "ADATA_SETINDEX": { + "anndata": "0.12.10", + "python": "3.13.12" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:13:51.064093335", + "timestamp": "2026-03-29T12:58:00.87153549", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - obs": { @@ -57,12 +97,52 @@ "versions": [ "versions.yml:md5,3849ee644c0cc7554e8328607967f0f0" ] + }, + { + "ADATA_SETINDEX": { + "anndata": "0.12.10", + "python": "3.13.12" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:13:30.688344891", + "timestamp": "2026-03-29T12:57:38.294706928", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - stub": { diff --git a/modules/local/adata/splitcol/tests/main.nf.test b/modules/local/adata/splitcol/tests/main.nf.test index 8d4cc980..36c24d5c 100644 --- a/modules/local/adata/splitcol/tests/main.nf.test +++ b/modules/local/adata/splitcol/tests/main.nf.test @@ -22,8 +22,13 @@ nextflow_process { } then { + def adatas = process.out.h5ad[0][1].collect { anndata(it) } assert process.success - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adatas.collect { it.yaml } + ).match() } } diff --git a/modules/local/adata/splitcol/tests/main.nf.test.snap b/modules/local/adata/splitcol/tests/main.nf.test.snap index 4d9df59a..d679958a 100644 --- a/modules/local/adata/splitcol/tests/main.nf.test.snap +++ b/modules/local/adata/splitcol/tests/main.nf.test.snap @@ -71,12 +71,122 @@ "versions": [ "versions.yml:md5,a74338e0a89adfeb07bdad07af3877f7" ] - } + }, + { + "ADATA_SPLITCOL": { + "anndata": "0.12.10", + "python": "3.13.12" + } + }, + [ + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + }, + { + "n_obs": 12640, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + }, + { + "n_obs": 12654, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } + ] ], - "timestamp": "2026-03-16T15:13:30.797750659", + "timestamp": "2026-03-29T12:57:38.085403361", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/adata/splitembeddings/tests/main.nf.test b/modules/local/adata/splitembeddings/tests/main.nf.test index 92e0b868..c45f8175 100644 --- a/modules/local/adata/splitembeddings/tests/main.nf.test +++ b/modules/local/adata/splitembeddings/tests/main.nf.test @@ -27,7 +27,6 @@ nextflow_process { then { assert process.success - assert snapshot(process.out).match() } diff --git a/modules/local/doublet_detection/doublet_removal/tests/main.nf.test b/modules/local/doublet_detection/doublet_removal/tests/main.nf.test index ea1715e8..69e1531e 100644 --- a/modules/local/doublet_detection/doublet_removal/tests/main.nf.test +++ b/modules/local/doublet_detection/doublet_removal/tests/main.nf.test @@ -32,8 +32,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/doublet_detection/doublet_removal/tests/main.nf.test.snap b/modules/local/doublet_detection/doublet_removal/tests/main.nf.test.snap index 9c5f2a39..5a9cb2e9 100644 --- a/modules/local/doublet_detection/doublet_removal/tests/main.nf.test.snap +++ b/modules/local/doublet_detection/doublet_removal/tests/main.nf.test.snap @@ -69,12 +69,55 @@ "versions": [ "versions.yml:md5,893433c90a0287b3000a0ccf2e680fec" ] + }, + { + "DOUBLET_REMOVAL": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "pandas": "2.3.3", + "python": "3.13.12", + "upsetplot": "0.9.0" + } + }, + { + "n_obs": 5901, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:15:35.811807967", + "timestamp": "2026-03-29T12:57:40.009249885", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/scanpy/cellcycle/tests/main.nf.test b/modules/local/scanpy/cellcycle/tests/main.nf.test index b9b7baff..cb964fd6 100644 --- a/modules/local/scanpy/cellcycle/tests/main.nf.test +++ b/modules/local/scanpy/cellcycle/tests/main.nf.test @@ -28,9 +28,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/scanpy/cellcycle/tests/main.nf.test.snap b/modules/local/scanpy/cellcycle/tests/main.nf.test.snap index 0b0c4bd9..3020e38f 100644 --- a/modules/local/scanpy/cellcycle/tests/main.nf.test.snap +++ b/modules/local/scanpy/cellcycle/tests/main.nf.test.snap @@ -40,12 +40,55 @@ "versions": [ "versions.yml:md5,835e61377485d04a9622f14de885ffe8" ] + }, + { + "SCANPY_CELLCYCLE": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "G2M_score", + "S_score", + "phase", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:15:03.013574886", + "timestamp": "2026-03-29T12:57:44.699366263", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - stub": { diff --git a/modules/local/scanpy/sample/tests/main.nf.test b/modules/local/scanpy/sample/tests/main.nf.test index 0411e29e..9482cfa3 100644 --- a/modules/local/scanpy/sample/tests/main.nf.test +++ b/modules/local/scanpy/sample/tests/main.nf.test @@ -52,9 +52,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -79,9 +83,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/scanpy/sample/tests/main.nf.test.snap b/modules/local/scanpy/sample/tests/main.nf.test.snap index f1e27692..317c8920 100644 --- a/modules/local/scanpy/sample/tests/main.nf.test.snap +++ b/modules/local/scanpy/sample/tests/main.nf.test.snap @@ -24,12 +24,52 @@ "versions": [ "versions.yml:md5,e107029fe0131716a546cc6a1d026522" ] + }, + { + "SCANPY_SAMPLE": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "n_obs": 100, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:15:01.327418477", + "timestamp": "2026-03-29T12:58:39.048199574", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run with fractional subsampling": { @@ -57,12 +97,52 @@ "versions": [ "versions.yml:md5,e107029fe0131716a546cc6a1d026522" ] + }, + { + "SCANPY_SAMPLE": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "n_obs": 6470, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:14:41.127806542", + "timestamp": "2026-03-29T12:58:12.748303278", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - stub": { diff --git a/subworkflows/local/combine/tests/main.nf.test b/subworkflows/local/combine/tests/main.nf.test index 3a134ed1..87bcbad3 100644 --- a/subworkflows/local/combine/tests/main.nf.test +++ b/subworkflows/local/combine/tests/main.nf.test @@ -21,7 +21,7 @@ nextflow_workflow { [[id: 'test1'], file(params.pipelines_testdata_base_path + '/anndata-variations/batch_correct_name.h5ad', checkIfExists: true)], [[id: 'test2'], file(params.pipelines_testdata_base_path + '/anndata-variations/batch_correct_name.h5ad', checkIfExists: true)] ) - input[1] = channel.empty() + input[1] = channel.value([[], []]) input[2] = false input[3] = 0 input[4] = 'scvi' @@ -54,7 +54,7 @@ nextflow_workflow { [[id: 'test1'], file(params.pipelines_testdata_base_path + '/anndata-variations/batch_correct_name.h5ad', checkIfExists: true)], [[id: 'test2'], file(params.pipelines_testdata_base_path + '/anndata-variations/batch_correct_name.h5ad', checkIfExists: true)] ) - input[1] = channel.empty() + input[1] = channel.value([[], []]) input[2] = false input[3] = 0 input[4] = 'scvi' diff --git a/subworkflows/local/combine/tests/main.nf.test.snap b/subworkflows/local/combine/tests/main.nf.test.snap index bc108952..4ef22e14 100644 --- a/subworkflows/local/combine/tests/main.nf.test.snap +++ b/subworkflows/local/combine/tests/main.nf.test.snap @@ -3,106 +3,182 @@ "content": [ { "0": [ - + [ + { + "id": "merged" + }, + "merged_outer.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] ], "1": [ - + [ + { + "id": "merged" + }, + "merged_inner.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] ], "2": [ - + [ + { + "id": "scvi", + "integration": "scvi" + }, + "scvi.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] ], "3": [ - + "gene_intersection.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "4": [ ], "5": [ - + "X_scvi.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "6": [ - + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ], "h5ad": [ - + [ + { + "id": "merged" + }, + "merged_outer.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] ], "h5ad_inner": [ - + [ + { + "id": "merged" + }, + "merged_inner.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] ], "integrations": [ - + [ + { + "id": "scvi", + "integration": "scvi" + }, + "scvi.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" + ] ], "obs": [ ], "obsm": [ - + "X_scvi.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "var": [ - + "gene_intersection.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ] } ], + "timestamp": "2026-03-29T13:17:18.066551589", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" - }, - "timestamp": "2026-01-16T22:32:56.838829264" + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } }, "Should run without failures - without base": { "content": [ { "0": [ - + [ + { + "id": "merged" + }, + "merged_outer.h5ad:md5,4c254e264541c969b4984867b21377d7" + ] ], "1": [ - + [ + { + "id": "merged" + }, + "merged_inner.h5ad:md5,4c254e264541c969b4984867b21377d7" + ] ], "2": [ - + [ + { + "id": "scvi", + "integration": "scvi" + }, + "scvi.h5ad:md5,98926b9a9feba2c6c9d3db14bccbb0e3" + ] ], "3": [ - + "gene_intersection.pkl:md5,ac5a8f750a472fa0fd9d393c8e8593fc" ], "4": [ ], "5": [ - + "X_scvi.pkl:md5,4e060be031c055cfa8812e5d0b138527" ], "6": [ - + "versions.yml:md5,0bfc384d091cd0b62c696af886df2c74", + "versions.yml:md5,195b81aece6ef2297facddfe7982f3ae", + "versions.yml:md5,ab044221564d1fdd7b4fca018253b58a", + "versions.yml:md5,e0ddd235448fc155982490a373f9d6fb" ], "h5ad": [ - + [ + { + "id": "merged" + }, + "merged_outer.h5ad:md5,4c254e264541c969b4984867b21377d7" + ] ], "h5ad_inner": [ - + [ + { + "id": "merged" + }, + "merged_inner.h5ad:md5,4c254e264541c969b4984867b21377d7" + ] ], "integrations": [ - + [ + { + "id": "scvi", + "integration": "scvi" + }, + "scvi.h5ad:md5,98926b9a9feba2c6c9d3db14bccbb0e3" + ] ], "obs": [ ], "obsm": [ - + "X_scvi.pkl:md5,4e060be031c055cfa8812e5d0b138527" ], "var": [ - + "gene_intersection.pkl:md5,ac5a8f750a472fa0fd9d393c8e8593fc" ], "versions": [ - + "versions.yml:md5,0bfc384d091cd0b62c696af886df2c74", + "versions.yml:md5,195b81aece6ef2297facddfe7982f3ae", + "versions.yml:md5,ab044221564d1fdd7b4fca018253b58a", + "versions.yml:md5,e0ddd235448fc155982490a373f9d6fb" ] } ], + "timestamp": "2026-03-29T13:18:55.833490331", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" - }, - "timestamp": "2026-01-16T22:33:05.898148109" + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } } } \ No newline at end of file From 8488d0dfebad650bd213df9c5eb697b804730529 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 13:38:41 +0200 Subject: [PATCH 27/46] Update combine tests --- .cursor/rules/nf-test-assertions.mdc | 29 ++-- subworkflows/local/combine/tests/main.nf.test | 10 +- .../local/combine/tests/main.nf.test.snap | 142 +++++++++--------- .../tests/main.nf.test.snap | 4 +- .../local/per_group/tests/main.nf.test.snap | 8 +- 5 files changed, 104 insertions(+), 89 deletions(-) diff --git a/.cursor/rules/nf-test-assertions.mdc b/.cursor/rules/nf-test-assertions.mdc index bfba7968..330170ba 100644 --- a/.cursor/rules/nf-test-assertions.mdc +++ b/.cursor/rules/nf-test-assertions.mdc @@ -96,29 +96,38 @@ assert snapshot(process.out, path(process.out.versions[0]).yaml, adata.yaml).mat ### Subworkflow tests -For subworkflows with multiple `versions.yml` files, snapshot the whole versions channel: +For subworkflows with multiple `versions.yml` files, collect them as parsed YAML for readability: ```groovy -assert snapshot(workflow.out.versions, adata.yaml).match() +assert snapshot( + workflow.out.versions.collect { path(it).yaml }, + adata.yaml +).match() ``` Or for deterministic subworkflows: ```groovy -assert snapshot(workflow.out, workflow.out.versions, adata.yaml).match() +assert snapshot( + workflow.out, + workflow.out.versions.collect { path(it).yaml }, + adata.yaml +).match() ``` ## Deterministic vs non-deterministic modules -**Deterministic** (always include `process.out` in snapshot): -`adata/entropy`, `adata/extend`, `adata/merge`, `adata/mergeembeddings`, `adata/mygene`, `adata/prepcellxgene`, `adata/readcsv`, `adata/readrds`, `adata/setindex`, `adata/splitcol`, `adata/splitembeddings`, `adata/tords`, `adata/unify`, `adata/upsetgenes`, `celda/decontx`, `celltypes/celltypist`, `celltypes/singler`, `custom/collectsizes`, `doublet_detection/doublet_removal`, `doublet_detection/scds`, `hugounifier/apply`, `hugounifier/get`, `liana/rankaggregate`, `scanpy/bbknn`, `scanpy/cellcycle`, `scanpy/combat`, `scanpy/filter`, `scanpy/harmony`, `scanpy/hvgs`, `scanpy/leiden`, `scanpy/neighbors`, `scanpy/paga`, `scanpy/plotqc`, `scanpy/rankgenesgroups`, `scanpy/readh5`, `scanpy/sample`, `scanpy/umap`, `soupx` +See [`docs/reproducibility.md`](../docs/reproducibility.md) for the full classification of every module and subworkflow. The relevant column for tests is **"Test strategy (this branch)"**: -**Non-deterministic** (omit `process.out` from snapshot, use structural/size checks): -`scanpy/pca` (floating-point variance), `scvitools/scvi`, `scvitools/scanvi`, `seurat/integration`, `scimilarity/embed`, `scimilarity/annotate`, `scimilarity/pseudobulk` +| Strategy | Snapshot pattern | +|----------|-----------------| +| `hash` | `process.out, path(process.out.versions[0]).yaml, adata.yaml` | +| `structural` | drop `process.out`; keep `path(process.out.versions[0]).yaml, adata.yaml` | +| `stub only` | no non-stub test; stub uses `snapshot(process.out).match()` | -## Common mistake — do NOT drop `process.out` from deterministic modules +## Common mistake — do NOT drop `process.out` from `hash`-strategy modules -For deterministic modules, the original tests used exact MD5 hashes. That means `process.out` **must** remain in the snapshot. Only omit it for ML/randomness-based modules. +For modules classified as `hash` in `docs/reproducibility.md`, the original tests used exact MD5 hashes. That means `process.out` **must** remain in the snapshot. Only omit it for `structural`-strategy modules. ```groovy // ❌ WRONG — drops the full output snapshot for a deterministic module @@ -131,7 +140,7 @@ assert snapshot(process.out, path(process.out.versions[0]).yaml, adata.yaml).mat ## Versions channel - **Module tests**: `path(process.out.versions[0]).yaml` — reads the single `versions.yml` as YAML -- **Subworkflow tests**: `workflow.out.versions` — snapshot the whole versions channel (multiple files, use MD5) +- **Subworkflow tests**: `workflow.out.versions.collect { path(it).yaml }` — parses each file for human-readable version names The versions channel should never include `meta`. In module tests, `process.out.versions[0]` is a plain path (no tuple). diff --git a/subworkflows/local/combine/tests/main.nf.test b/subworkflows/local/combine/tests/main.nf.test index 87bcbad3..b04791d5 100644 --- a/subworkflows/local/combine/tests/main.nf.test +++ b/subworkflows/local/combine/tests/main.nf.test @@ -69,8 +69,16 @@ nextflow_workflow { } then { + def adata = anndata(workflow.out.h5ad[0][1]) assert workflow.success - assert snapshot(workflow.out).match() + assert "batch" in adata.obs.colnames + assert snapshot( + workflow.out.h5ad, + workflow.out.h5ad_inner, + workflow.out.var, + workflow.out.versions.collect { path(it).yaml }, + adata.yaml + ).match() } } diff --git a/subworkflows/local/combine/tests/main.nf.test.snap b/subworkflows/local/combine/tests/main.nf.test.snap index 4ef22e14..99120b72 100644 --- a/subworkflows/local/combine/tests/main.nf.test.snap +++ b/subworkflows/local/combine/tests/main.nf.test.snap @@ -84,7 +84,7 @@ ] } ], - "timestamp": "2026-03-29T13:17:18.066551589", + "timestamp": "2026-03-29T13:32:53.623653313", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -92,90 +92,88 @@ }, "Should run without failures - without base": { "content": [ + [ + [ + { + "id": "merged" + }, + "merged_outer.h5ad:md5,4c254e264541c969b4984867b21377d7" + ] + ], + [ + [ + { + "id": "merged" + }, + "merged_inner.h5ad:md5,4c254e264541c969b4984867b21377d7" + ] + ], + [ + "gene_intersection.pkl:md5,ac5a8f750a472fa0fd9d393c8e8593fc" + ], + [ + { + "COMBINE:INTEGRATE:SCVITOOLS_SCVI": { + "scvi": "1.3.3" + } + }, + { + "COMBINE:INTEGRATE:SCANPY_HVGS": { + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "COMBINE:ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + } + }, + { + "COMBINE:INTEGRATE:SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + } + } + ], { - "0": [ - [ - { - "id": "merged" - }, - "merged_outer.h5ad:md5,4c254e264541c969b4984867b21377d7" + "n_obs": 25880, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch" ] - ], - "1": [ - [ - { - "id": "merged" - }, - "merged_inner.h5ad:md5,4c254e264541c969b4984867b21377d7" + }, + "var": { + "index": "_index", + "columns": [ + ] + }, + "layers": [ + "counts" ], - "2": [ - [ - { - "id": "scvi", - "integration": "scvi" - }, - "scvi.h5ad:md5,98926b9a9feba2c6c9d3db14bccbb0e3" - ] - ], - "3": [ - "gene_intersection.pkl:md5,ac5a8f750a472fa0fd9d393c8e8593fc" - ], - "4": [ + "obsm": [ ], - "5": [ - "X_scvi.pkl:md5,4e060be031c055cfa8812e5d0b138527" - ], - "6": [ - "versions.yml:md5,0bfc384d091cd0b62c696af886df2c74", - "versions.yml:md5,195b81aece6ef2297facddfe7982f3ae", - "versions.yml:md5,ab044221564d1fdd7b4fca018253b58a", - "versions.yml:md5,e0ddd235448fc155982490a373f9d6fb" - ], - "h5ad": [ - [ - { - "id": "merged" - }, - "merged_outer.h5ad:md5,4c254e264541c969b4984867b21377d7" - ] - ], - "h5ad_inner": [ - [ - { - "id": "merged" - }, - "merged_inner.h5ad:md5,4c254e264541c969b4984867b21377d7" - ] - ], - "integrations": [ - [ - { - "id": "scvi", - "integration": "scvi" - }, - "scvi.h5ad:md5,98926b9a9feba2c6c9d3db14bccbb0e3" - ] - ], - "obs": [ + "varm": [ ], - "obsm": [ - "X_scvi.pkl:md5,4e060be031c055cfa8812e5d0b138527" + "obsp": [ + ], - "var": [ - "gene_intersection.pkl:md5,ac5a8f750a472fa0fd9d393c8e8593fc" + "varp": [ + ], - "versions": [ - "versions.yml:md5,0bfc384d091cd0b62c696af886df2c74", - "versions.yml:md5,195b81aece6ef2297facddfe7982f3ae", - "versions.yml:md5,ab044221564d1fdd7b4fca018253b58a", - "versions.yml:md5,e0ddd235448fc155982490a373f9d6fb" + "uns": [ + ] } ], - "timestamp": "2026-03-29T13:18:55.833490331", + "timestamp": "2026-03-29T13:34:40.022498245", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/differential_expression/tests/main.nf.test.snap b/subworkflows/local/differential_expression/tests/main.nf.test.snap index dd314882..11574c49 100644 --- a/subworkflows/local/differential_expression/tests/main.nf.test.snap +++ b/subworkflows/local/differential_expression/tests/main.nf.test.snap @@ -116,7 +116,7 @@ } ] ], - "timestamp": "2026-03-28T19:42:40.224566991", + "timestamp": "2026-03-29T13:30:15.199583154", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -197,7 +197,7 @@ } ] ], - "timestamp": "2026-03-28T19:43:40.510185657", + "timestamp": "2026-03-29T13:31:13.926825588", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/per_group/tests/main.nf.test.snap b/subworkflows/local/per_group/tests/main.nf.test.snap index 370f7df9..a1891678 100644 --- a/subworkflows/local/per_group/tests/main.nf.test.snap +++ b/subworkflows/local/per_group/tests/main.nf.test.snap @@ -10,7 +10,7 @@ } ] ], - "timestamp": "2026-03-28T18:31:51.294256583", + "timestamp": "2026-03-29T13:29:55.686223135", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -39,7 +39,7 @@ ] } ], - "timestamp": "2026-03-28T18:27:44.794170345", + "timestamp": "2026-03-29T13:27:01.860499372", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -173,7 +173,7 @@ } ] ], - "timestamp": "2026-03-28T18:29:59.302941687", + "timestamp": "2026-03-29T13:32:00.149772102", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -302,7 +302,7 @@ ] } ], - "timestamp": "2026-03-28T18:28:27.393037698", + "timestamp": "2026-03-29T13:30:19.935000889", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" From 4f483a021d39e6ffe0893db8db4f40bd7523f817 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 13:51:16 +0200 Subject: [PATCH 28/46] Update some more module tests --- .../local/adata/readcsv/tests/main.nf.test | 9 +- .../adata/readcsv/tests/main.nf.test.snap | 45 ++++++- .../local/adata/readrds/tests/main.nf.test | 16 ++- .../adata/readrds/tests/main.nf.test.snap | 117 ++++++++++++++++-- .../local/scanpy/readh5/tests/main.nf.test | 8 +- .../scanpy/readh5/tests/main.nf.test.snap | 47 ++++++- 6 files changed, 217 insertions(+), 25 deletions(-) diff --git a/modules/local/adata/readcsv/tests/main.nf.test b/modules/local/adata/readcsv/tests/main.nf.test index 321e296d..6e329327 100644 --- a/modules/local/adata/readcsv/tests/main.nf.test +++ b/modules/local/adata/readcsv/tests/main.nf.test @@ -25,9 +25,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -53,7 +57,6 @@ nextflow_process { then { assert process.success - assert snapshot(process.out).match() } diff --git a/modules/local/adata/readcsv/tests/main.nf.test.snap b/modules/local/adata/readcsv/tests/main.nf.test.snap index 1649095a..084a952b 100644 --- a/modules/local/adata/readcsv/tests/main.nf.test.snap +++ b/modules/local/adata/readcsv/tests/main.nf.test.snap @@ -57,12 +57,53 @@ "versions": [ "versions.yml:md5,04012b0101dd2263a1ebe8a9870dcf2c" ] + }, + { + "ADATA_READCSV": { + "anndata": "0.12.10", + "pandas": "2.3.3", + "python": "3.13.12" + } + }, + { + "n_obs": 100, + "n_vars": 100, + "obs": { + "index": "_index", + "columns": [ + + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:13:30.494289545", + "timestamp": "2026-03-29T13:50:20.11008928", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/adata/readrds/tests/main.nf.test b/modules/local/adata/readrds/tests/main.nf.test index ec7239f7..6e579c3e 100644 --- a/modules/local/adata/readrds/tests/main.nf.test +++ b/modules/local/adata/readrds/tests/main.nf.test @@ -25,9 +25,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -77,9 +81,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/adata/readrds/tests/main.nf.test.snap b/modules/local/adata/readrds/tests/main.nf.test.snap index 17139824..329e5554 100644 --- a/modules/local/adata/readrds/tests/main.nf.test.snap +++ b/modules/local/adata/readrds/tests/main.nf.test.snap @@ -24,13 +24,59 @@ "versions": [ "versions.yml:md5,97a57daf2be7236a765bbf214c58c444" ] + }, + { + "ADATA_READRDS": { + "anndata": "0.11.1", + "anndata2ri": "1.3.2", + "rpy2": "3.5.11", + "pandas": "2.2.3", + "seurat": "5.1.0" + } + }, + { + "n_obs": 12634, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "feature_types", + "gene_ids", + "gene_symbol", + "gene_versions" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], + "timestamp": "2026-03-29T13:46:53.842611485", "meta": { - "nf-test": "0.9.0", - "nextflow": "25.04.2" - }, - "timestamp": "2025-06-02T14:05:30.580002034" + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } }, "Should read SCE file - stub": { "content": [ @@ -59,11 +105,11 @@ ] } ], + "timestamp": "2025-06-02T14:05:41.785903395", "meta": { "nf-test": "0.9.0", "nextflow": "25.04.2" - }, - "timestamp": "2025-06-02T14:05:41.785903395" + } }, "Should read seurat file": { "content": [ @@ -90,13 +136,60 @@ "versions": [ "versions.yml:md5,97a57daf2be7236a765bbf214c58c444" ] + }, + { + "ADATA_READRDS": { + "anndata": "0.11.1", + "anndata2ri": "1.3.2", + "rpy2": "3.5.11", + "pandas": "2.2.3", + "seurat": "5.1.0" + } + }, + { + "n_obs": 12650, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "ident", + "nCount_RNA", + "nFeature_RNA", + "orig.ident", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], + "timestamp": "2026-03-29T13:46:07.673656598", "meta": { - "nf-test": "0.9.0", - "nextflow": "25.04.2" - }, - "timestamp": "2025-06-02T14:04:47.09491976" + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } }, "Should read seurat file - stub": { "content": [ @@ -125,10 +218,10 @@ ] } ], + "timestamp": "2025-06-02T14:04:58.058486624", "meta": { "nf-test": "0.9.0", "nextflow": "25.04.2" - }, - "timestamp": "2025-06-02T14:04:58.058486624" + } } } \ No newline at end of file diff --git a/modules/local/scanpy/readh5/tests/main.nf.test b/modules/local/scanpy/readh5/tests/main.nf.test index 64cc59ce..6d0bff9b 100644 --- a/modules/local/scanpy/readh5/tests/main.nf.test +++ b/modules/local/scanpy/readh5/tests/main.nf.test @@ -25,9 +25,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/scanpy/readh5/tests/main.nf.test.snap b/modules/local/scanpy/readh5/tests/main.nf.test.snap index d1dfa942..86ce6ac0 100644 --- a/modules/local/scanpy/readh5/tests/main.nf.test.snap +++ b/modules/local/scanpy/readh5/tests/main.nf.test.snap @@ -57,12 +57,55 @@ "versions": [ "versions.yml:md5,cb1290acd28dadec5487c92ca6866c1d" ] + }, + { + "SCANPY_READH5": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + } + }, + { + "n_obs": 1107, + "n_vars": 507, + "obs": { + "index": "_index", + "columns": [ + + ] + }, + "var": { + "index": "_index", + "columns": [ + "feature_types", + "gene_ids", + "genome" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:14:15.685803076", + "timestamp": "2026-03-29T13:45:54.372715018", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file From 2879704dcea456035498d54e0f52f347e90c9f0f Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 13:56:32 +0200 Subject: [PATCH 29/46] Update adata/merge test snapshots --- .../local/adata/merge/tests/main.nf.test.snap | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/local/adata/merge/tests/main.nf.test.snap b/modules/local/adata/merge/tests/main.nf.test.snap index 76f21681..fe55d298 100644 --- a/modules/local/adata/merge/tests/main.nf.test.snap +++ b/modules/local/adata/merge/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "combined" }, - "combined_outer.h5ad:md5,d03dc674beb17ce07839ea78791fec77" + "combined_outer.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" ] ], "1": [ @@ -15,7 +15,7 @@ { "id": "combined" }, - "combined_inner.h5ad:md5,d03dc674beb17ce07839ea78791fec77" + "combined_inner.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" ] ], "2": [ @@ -23,7 +23,7 @@ { "id": "combined" }, - "combined_integrate.h5ad:md5,d03dc674beb17ce07839ea78791fec77" + "combined_integrate.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" ] ], "3": [ @@ -37,7 +37,7 @@ { "id": "combined" }, - "combined_inner.h5ad:md5,d03dc674beb17ce07839ea78791fec77" + "combined_inner.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" ] ], "integrate": [ @@ -45,7 +45,7 @@ { "id": "combined" }, - "combined_integrate.h5ad:md5,d03dc674beb17ce07839ea78791fec77" + "combined_integrate.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" ] ], "intersect_genes": [ @@ -56,7 +56,7 @@ { "id": "combined" }, - "combined_outer.h5ad:md5,d03dc674beb17ce07839ea78791fec77" + "combined_outer.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" ] ], "versions": [ @@ -186,10 +186,10 @@ ] } ], - "timestamp": "2026-03-29T12:57:53.789595572", + "timestamp": "2026-03-29T13:52:58.903537417", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nextflow": "25.10.4" } }, "Should run with base": { From fb58df50e17c2ff7cc564a5104837ea947378bfe Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 14:15:08 +0200 Subject: [PATCH 30/46] Change scanpy/hvgs classification in reproducibility doc --- docs/reproducibility.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/reproducibility.md b/docs/reproducibility.md index fcbe3717..3a2b42a3 100644 --- a/docs/reproducibility.md +++ b/docs/reproducibility.md @@ -90,23 +90,23 @@ The **Test strategy (this branch)** column describes what the tests on this bran ### `scanpy/` -| Module | Description | Reproducibility | Test strategy (this branch) | -| ------------------------ | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | hash | -| `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | hash | -| `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | structural — versions + schema only | -| `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | hash + structural | -| `scanpy/harmony` | Runs Harmony batch integration after log-normalisation and PCA, storing the corrected embedding as `X_emb`. | **Non-deterministic** — Harmony is an iterative optimisation with no fixed seed; upstream PCA is also unseeded. | structural — versions + schema only; `variance_ratio` output removed | -| `scanpy/hvgs` | Selects highly variable genes and subsets the AnnData to those genes. | Fully deterministic | hash | -| `scanpy/leiden` | Performs Leiden community-detection clustering at a specified resolution. | **Non-deterministic** — Leiden uses random restarts with no fixed seed. | structural — range assertion on cluster count + versions + schema | -| `scanpy/neighbors` | Computes a k-nearest-neighbour graph on a specified embedding. | Fully deterministic given a fixed input embedding. | structural — versions + schema only | -| `scanpy/paga` | Computes PAGA coarse-grained cluster connectivity and saves a graph and plot. | Fully deterministic — PAGA is a deterministic graph-summarisation step given fixed Leiden labels. | hash | -| `scanpy/pca` | Runs PCA with `random_state=0` and stores the result under a specified key. | Seeded / quasi-deterministic — seed is fixed, but float coordinates can differ across LAPACK/MKL backends. | structural — versions + schema only | -| `scanpy/plotqc` | Calculates QC metrics and produces a counts-vs-genes scatter plot for MultiQC. | Fully deterministic | hash | -| `scanpy/rankgenesgroups` | Runs differential gene expression (rank genes groups) across clusters using a configurable statistical method. | Fully deterministic for `wilcoxon` and `t-test` (defaults); depends on chosen method parameter. | hash | -| `scanpy/readh5` | Reads a 10x Genomics HDF5 (`.h5`) file and writes it as an AnnData H5AD. | Fully deterministic | hash | -| `scanpy/sample` | Down-samples cells to a fixed count or fraction using `rng=0`. | Seeded / quasi-deterministic — seed is fixed, but sampled cell set may vary across NumPy versions. | hash | -| `scanpy/umap` | Computes a UMAP embedding from a pre-built neighbour graph using `random_state=0`. | Seeded / quasi-deterministic — seed is fixed, but float coordinates vary across umap-learn/numba versions. | structural — versions + schema only | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | +| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | hash | +| `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | hash | +| `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | structural — versions + schema only | +| `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | hash + structural | +| `scanpy/harmony` | Runs Harmony batch integration after log-normalisation and PCA, storing the corrected embedding as `X_emb`. | **Non-deterministic** — Harmony is an iterative optimisation with no fixed seed; upstream PCA is also unseeded. | structural — versions + schema only; `variance_ratio` output removed | +| `scanpy/hvgs` | Selects highly variable genes and subsets the AnnData to those genes. | Seeded / quasi-deterministic — HVG variance statistics rely on NumPy/SciPy floating-point operations that can produce slightly different results across library versions. | structural — versions + schema only | +| `scanpy/leiden` | Performs Leiden community-detection clustering at a specified resolution. | **Non-deterministic** — Leiden uses random restarts with no fixed seed. | structural — range assertion on cluster count + versions + schema | +| `scanpy/neighbors` | Computes a k-nearest-neighbour graph on a specified embedding. | Fully deterministic given a fixed input embedding. | structural — versions + schema only | +| `scanpy/paga` | Computes PAGA coarse-grained cluster connectivity and saves a graph and plot. | Fully deterministic — PAGA is a deterministic graph-summarisation step given fixed Leiden labels. | hash | +| `scanpy/pca` | Runs PCA with `random_state=0` and stores the result under a specified key. | Seeded / quasi-deterministic — seed is fixed, but float coordinates can differ across LAPACK/MKL backends. | structural — versions + schema only | +| `scanpy/plotqc` | Calculates QC metrics and produces a counts-vs-genes scatter plot for MultiQC. | Fully deterministic | hash | +| `scanpy/rankgenesgroups` | Runs differential gene expression (rank genes groups) across clusters using a configurable statistical method. | Fully deterministic for `wilcoxon` and `t-test` (defaults); depends on chosen method parameter. | hash | +| `scanpy/readh5` | Reads a 10x Genomics HDF5 (`.h5`) file and writes it as an AnnData H5AD. | Fully deterministic | hash | +| `scanpy/sample` | Down-samples cells to a fixed count or fraction using `rng=0`. | Seeded / quasi-deterministic — seed is fixed, but sampled cell set may vary across NumPy versions. | hash | +| `scanpy/umap` | Computes a UMAP embedding from a pre-built neighbour graph using `random_state=0`. | Seeded / quasi-deterministic — seed is fixed, but float coordinates vary across umap-learn/numba versions. | structural — versions + schema only | ### `scimilarity/` From 491fce6200868b9717c308ee86f8c0a451e0fc1d Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 14:41:27 +0200 Subject: [PATCH 31/46] Update some more tests --- docs/reproducibility.md | 16 +- modules/local/adata/extend/tests/main.nf.test | 31 +- .../adata/extend/tests/main.nf.test.snap | 289 +++++++++++++++++- .../hugounifier/apply/tests/main.nf.test | 11 +- .../hugounifier/apply/tests/main.nf.test.snap | 50 ++- .../local/hugounifier/get/tests/main.nf.test | 10 +- .../hugounifier/get/tests/main.nf.test.snap | 16 +- subworkflows/local/combine/tests/main.nf.test | 3 - .../local/combine/tests/main.nf.test.snap | 21 +- .../local/pseudobulking/tests/main.nf.test | 1 + .../pseudobulking/tests/main.nf.test.snap | 11 +- .../local/unify_genes/tests/main.nf.test | 5 +- .../local/unify_genes/tests/main.nf.test.snap | 101 ++---- 13 files changed, 432 insertions(+), 133 deletions(-) diff --git a/docs/reproducibility.md b/docs/reproducibility.md index 3a2b42a3..9bbe58a3 100644 --- a/docs/reproducibility.md +++ b/docs/reproducibility.md @@ -77,10 +77,10 @@ The **Test strategy (this branch)** column describes what the tests on this bran ### `hugounifier/` -| Module | Description | Reproducibility | Test strategy (this branch) | -| ------------------- | --------------------------------------------------------------------------------------------- | ------------------- | --------------------------- | -| `hugounifier/get` | Computes a cross-dataset gene symbol renaming change table using the `hugo-unifier` CLI tool. | Fully deterministic | hash | -| `hugounifier/apply` | Applies a gene symbol renaming change table to a single AnnData H5AD file. | Fully deterministic | hash | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | +| `hugounifier/get` | Computes a cross-dataset gene symbol renaming change table using the `hugo-unifier` CLI tool. | **Non-deterministic** — uses the HUGO Gene Nomenclature Committee REST API; results depend on database state at query time. | structural — CSV column names + versions only | +| `hugounifier/apply` | Applies a gene symbol renaming change table to a single AnnData H5AD file. | Fully deterministic once the change table is fixed; but see `hugounifier/get` above. | structural — versions + schema only | ### `liana/` @@ -92,7 +92,7 @@ The **Test strategy (this branch)** column describes what the tests on this bran | Module | Description | Reproducibility | Test strategy (this branch) | | ------------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | hash | +| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | structural — versions + schema only | | `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | hash | | `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | structural — versions + schema only | | `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | hash + structural | @@ -144,8 +144,8 @@ The **Test strategy (this branch)** column describes what the tests on this bran | `ambient_correction` | Dispatches ambient RNA correction to decontX, SoupX, or none based on a parameter. | **Non-deterministic** for decontX (no seed) and SoupX (seeded clustering but variable results); fully deterministic for the `none` passthrough. | structural — versions + schema only | | `celltype_assignment` | Orchestrates cell type annotation by running SingleR and/or CellTypist. | Fully deterministic — both methods are deterministic at inference time. | obs size only | | `cluster` | Full clustering pipeline: neighbours → UMAP → Leiden at multiple resolutions → Shannon entropy. | Seeded / quasi-deterministic for UMAP; **non-deterministic** due to unseeded Leiden. | structural — versions only | -| `combine` | Merges all samples and runs all configured integration methods. | Inherits from constituent modules — ranges from fully deterministic (no integration) to seeded/quasi-deterministic (scVI, Harmony, Seurat). | structural — versions only | -| `differential_expression` | Runs rank-genes-groups DE analysis across all combinations of clustering labels, conditions, and cell-type subsets. | Fully deterministic for the default wilcoxon/t-test methods. | hash | +| `combine` | Merges all samples and runs all configured integration methods. | Inherits from constituent modules — ranges from fully deterministic (no integration) to seeded/quasi-deterministic (scVI, Harmony, Seurat). | structural — versions + schema only | +| `differential_expression` | Runs rank-genes-groups DE analysis across all combinations of clustering labels, conditions, and cell-type subsets. | Fully deterministic for the default wilcoxon/t-test methods. | structural — versions only | | `doublet_detection` | Runs one or more doublet-detection methods (scds, solo, scrublet, doubletdetection) and removes called doublets. | **Non-deterministic** — solo, scrublet, and doubletdetection have stochastic components; scds is seeded. | structural + range assertion on cell count | | `finalize` | Assembles the final AnnData by extending it with all collected obs/obsm/uns/layers outputs. | Fully deterministic | hash | | `integrate` | Applies HVG selection then one or more integration methods (scVI, scANVI, Harmony, BBKNN, ComBat, Seurat, SCimilarity). | Seeded / quasi-deterministic for scVI/scANVI/ComBat/Seurat/BBKNN; **non-deterministic** for Harmony. | structural — versions + schema only | @@ -156,4 +156,4 @@ The **Test strategy (this branch)** column describes what the tests on this bran | `scimilarity` | Embeds cells into the SCimilarity pretrained latent space and annotates with cell type labels. | Fully deterministic — fixed pretrained model, inference-only. | stub only | | `singler` | Downloads (or uses pre-provided) celldex reference datasets and runs SingleR annotation. | Fully deterministic for annotation; **non-deterministic** if downloading references at runtime via ExperimentHub. | hash | | `unify` | Standardises gene symbols (optionally via MyGene.info and HUGO-unifier) and normalises metadata columns (batch, label, condition). | **Non-deterministic** when `symbol_col == "none"` (triggers MyGene.info API call); fully deterministic otherwise. | hash | -| `unify_genes` | Applies HUGO-unifier to compute and apply a cross-dataset gene symbol renaming table. | Fully deterministic | structural — versions only | +| `unify_genes` | Applies HUGO-unifier to compute and apply a cross-dataset gene symbol renaming table. | **Non-deterministic** — `hugounifier/get` uses a live HUGO API; results depend on database state at query time. | structural — versions + schema only | diff --git a/modules/local/adata/extend/tests/main.nf.test b/modules/local/adata/extend/tests/main.nf.test index 45c90110..2739c92e 100644 --- a/modules/local/adata/extend/tests/main.nf.test +++ b/modules/local/adata/extend/tests/main.nf.test @@ -36,7 +36,11 @@ nextflow_process { with(adata) { assert "scvi-global-1.0_leiden" in obs.colnames } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -70,7 +74,11 @@ nextflow_process { with(adata) { assert "X_scvi" in obsm } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -113,7 +121,11 @@ nextflow_process { assert "X_scvi" in obsm assert "X_scvi-global_umap" in obsm } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -147,7 +159,11 @@ nextflow_process { with(adata) { assert "scvi-global-1.0_paga" in uns } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -176,8 +192,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/adata/extend/tests/main.nf.test.snap b/modules/local/adata/extend/tests/main.nf.test.snap index 1f2670f4..cb27194c 100644 --- a/modules/local/adata/extend/tests/main.nf.test.snap +++ b/modules/local/adata/extend/tests/main.nf.test.snap @@ -40,12 +40,68 @@ "versions": [ "versions.yml:md5,b2a073150918c118c3858cf4e82145f7" ] + }, + { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + } + }, + { + "n_obs": 23373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "scvi-global-1.0:entropy", + "scvi-global-1.0_leiden", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_scvi", + "X_scvi-global_umap" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:14:17.984419949", + "timestamp": "2026-03-29T14:30:06.774357979", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should extend with obsm data": { @@ -89,12 +145,65 @@ "versions": [ "versions.yml:md5,b2a073150918c118c3858cf4e82145f7" ] + }, + { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + } + }, + { + "n_obs": 23373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_scvi" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:13:53.551305616", + "timestamp": "2026-03-29T14:29:47.492628938", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should extend with uns data": { @@ -138,12 +247,65 @@ "versions": [ "versions.yml:md5,b2a073150918c118c3858cf4e82145f7" ] + }, + { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + } + }, + { + "n_obs": 23373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "scvi-global-1.0_paga" + ] } ], - "timestamp": "2026-03-16T15:14:39.805580912", + "timestamp": "2026-03-29T14:30:26.284065573", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should extend with obs data": { @@ -187,12 +349,66 @@ "versions": [ "versions.yml:md5,b2a073150918c118c3858cf4e82145f7" ] + }, + { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + } + }, + { + "n_obs": 23373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "scvi-global-1.0_leiden", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:13:30.793377663", + "timestamp": "2026-03-29T14:29:26.551795343", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - stub": { @@ -285,12 +501,65 @@ "versions": [ "versions.yml:md5,b2a073150918c118c3858cf4e82145f7" ] + }, + { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + } + }, + { + "n_obs": 23373, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:14:59.60059937", + "timestamp": "2026-03-29T14:30:51.255096363", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/hugounifier/apply/tests/main.nf.test b/modules/local/hugounifier/apply/tests/main.nf.test index 0785a00d..edc22b63 100644 --- a/modules/local/hugounifier/apply/tests/main.nf.test +++ b/modules/local/hugounifier/apply/tests/main.nf.test @@ -45,15 +45,16 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - - with(anndata(process.out.h5ad[0][1])) { - + with(adata) { assert var.rownames.size() > 0 - assert obs.rownames.size() > 0 - } + assert snapshot( + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/hugounifier/apply/tests/main.nf.test.snap b/modules/local/hugounifier/apply/tests/main.nf.test.snap index b3a1e4bd..dd565734 100644 --- a/modules/local/hugounifier/apply/tests/main.nf.test.snap +++ b/modules/local/hugounifier/apply/tests/main.nf.test.snap @@ -31,5 +31,53 @@ "nf-test": "0.9.2", "nextflow": "25.04.6" } + }, + "Should run without failures": { + "content": [ + { + "HUGOUNIFIER_APPLY": { + "hugo-unifier": "0.3.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + "counts" + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] + } + ], + "timestamp": "2026-03-29T14:29:56.746430632", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } } -} +} \ No newline at end of file diff --git a/modules/local/hugounifier/get/tests/main.nf.test b/modules/local/hugounifier/get/tests/main.nf.test index d8d4deec..f822a6b2 100644 --- a/modules/local/hugounifier/get/tests/main.nf.test +++ b/modules/local/hugounifier/get/tests/main.nf.test @@ -30,20 +30,16 @@ nextflow_process { then { assert process.success - assert process.out.changes[0][1].size() == 2 - with(path(process.out.changes[0][1][0]).csv) { - assert columnNames == ["action", "symbol", "new", "reason"] - } - with(path(process.out.changes[0][1][1]).csv) { - assert columnNames == ["action", "symbol", "new", "reason"] - } + assert snapshot( + path(process.out.versions[0]).yaml + ).match() } } diff --git a/modules/local/hugounifier/get/tests/main.nf.test.snap b/modules/local/hugounifier/get/tests/main.nf.test.snap index f9b67f8e..fabeb6a5 100644 --- a/modules/local/hugounifier/get/tests/main.nf.test.snap +++ b/modules/local/hugounifier/get/tests/main.nf.test.snap @@ -37,5 +37,19 @@ "nf-test": "0.9.2", "nextflow": "25.04.6" } + }, + "Should run without failures": { + "content": [ + { + "HUGOUNIFIER_GET": { + "hugo-unifier": "0.3.1" + } + } + ], + "timestamp": "2026-03-29T14:29:45.757744", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } } -} +} \ No newline at end of file diff --git a/subworkflows/local/combine/tests/main.nf.test b/subworkflows/local/combine/tests/main.nf.test index b04791d5..fcaa7275 100644 --- a/subworkflows/local/combine/tests/main.nf.test +++ b/subworkflows/local/combine/tests/main.nf.test @@ -73,9 +73,6 @@ nextflow_workflow { assert workflow.success assert "batch" in adata.obs.colnames assert snapshot( - workflow.out.h5ad, - workflow.out.h5ad_inner, - workflow.out.var, workflow.out.versions.collect { path(it).yaml }, adata.yaml ).match() diff --git a/subworkflows/local/combine/tests/main.nf.test.snap b/subworkflows/local/combine/tests/main.nf.test.snap index 99120b72..1a2b6ceb 100644 --- a/subworkflows/local/combine/tests/main.nf.test.snap +++ b/subworkflows/local/combine/tests/main.nf.test.snap @@ -92,25 +92,6 @@ }, "Should run without failures - without base": { "content": [ - [ - [ - { - "id": "merged" - }, - "merged_outer.h5ad:md5,4c254e264541c969b4984867b21377d7" - ] - ], - [ - [ - { - "id": "merged" - }, - "merged_inner.h5ad:md5,4c254e264541c969b4984867b21377d7" - ] - ], - [ - "gene_intersection.pkl:md5,ac5a8f750a472fa0fd9d393c8e8593fc" - ], [ { "COMBINE:INTEGRATE:SCVITOOLS_SCVI": { @@ -173,7 +154,7 @@ ] } ], - "timestamp": "2026-03-29T13:34:40.022498245", + "timestamp": "2026-03-29T14:31:17.652923187", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/pseudobulking/tests/main.nf.test b/subworkflows/local/pseudobulking/tests/main.nf.test index c5ae36cc..399e6df2 100644 --- a/subworkflows/local/pseudobulking/tests/main.nf.test +++ b/subworkflows/local/pseudobulking/tests/main.nf.test @@ -36,6 +36,7 @@ nextflow_workflow { } assert snapshot( workflow.out, + workflow.out.versions.collect { path(it).yaml }, adata.yaml ).match() } diff --git a/subworkflows/local/pseudobulking/tests/main.nf.test.snap b/subworkflows/local/pseudobulking/tests/main.nf.test.snap index 1c04a6ac..680db832 100644 --- a/subworkflows/local/pseudobulking/tests/main.nf.test.snap +++ b/subworkflows/local/pseudobulking/tests/main.nf.test.snap @@ -58,6 +58,15 @@ "versions.yml:md5,7629f78da2c667f7f5975f67b4cc521c" ] }, + [ + { + "PSEUDOBULKING:PSEUDOBULK": { + "anndata": "0.12.10", + "python": "3.12.13", + "scimilarity": "0.4.1" + } + } + ], { "n_obs": 3, "n_vars": 9887, @@ -95,7 +104,7 @@ ] } ], - "timestamp": "2026-03-29T11:18:26.343309887", + "timestamp": "2026-03-29T14:30:24.242646237", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/unify_genes/tests/main.nf.test b/subworkflows/local/unify_genes/tests/main.nf.test index 5f9e6cb1..ab576964 100644 --- a/subworkflows/local/unify_genes/tests/main.nf.test +++ b/subworkflows/local/unify_genes/tests/main.nf.test @@ -52,13 +52,12 @@ nextflow_workflow { def adata = anndata(workflow.out.h5ad[0][1]) assert workflow.success with(adata) { - // hugo-unifier adds a unified HGNC symbol column to var assert "symbols" in var.colnames assert var.rownames.size() > 0 assert obs.rownames.size() > 0 } assert snapshot( - workflow.out, + workflow.out.versions.collect { path(it).yaml }, adata.yaml ).match() } @@ -121,7 +120,7 @@ nextflow_workflow { assert obs.rownames.size() > 0 } assert snapshot( - workflow.out, + workflow.out.versions.collect { path(it).yaml }, adata1.yaml, adata2.yaml ).match() diff --git a/subworkflows/local/unify_genes/tests/main.nf.test.snap b/subworkflows/local/unify_genes/tests/main.nf.test.snap index d79ced95..719f2cfd 100644 --- a/subworkflows/local/unify_genes/tests/main.nf.test.snap +++ b/subworkflows/local/unify_genes/tests/main.nf.test.snap @@ -1,32 +1,18 @@ { "Should run without failures - single sample": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" - ] - ], - "1": [ - "versions.yml:md5,a25a9f067f9ece70fa40d51efbcdbdee", - "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" - ] - ], - "versions": [ - "versions.yml:md5,a25a9f067f9ece70fa40d51efbcdbdee", - "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" - ] - }, + [ + { + "UNIFY_GENES:HUGOUNIFIER_GET": { + "hugo-unifier": "0.3.1" + } + }, + { + "UNIFY_GENES:HUGOUNIFIER_APPLY": { + "hugo-unifier": "0.3.1" + } + } + ], { "n_obs": 12940, "n_vars": 9887, @@ -62,7 +48,7 @@ ] } ], - "timestamp": "2026-03-29T11:17:56.776337553", + "timestamp": "2026-03-29T14:30:07.824538049", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -146,7 +132,7 @@ ] } ], - "timestamp": "2026-01-17T08:56:25.329555915", + "timestamp": "2026-01-17T08:56:25.329515915", "meta": { "nf-test": "0.9.2", "nextflow": "25.04.6" @@ -154,46 +140,23 @@ }, "Should run without failures - multiple samples": { "content": [ - { - "0": [ - [ - { - "id": "test1" - }, - "test1_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" - ], - [ - { - "id": "test2" - }, - "test2_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" - ] - ], - "1": [ - "versions.yml:md5,a25a9f067f9ece70fa40d51efbcdbdee", - "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e", - "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" - ], - "h5ad": [ - [ - { - "id": "test1" - }, - "test1_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" - ], - [ - { - "id": "test2" - }, - "test2_hugounifier.h5ad:md5,bcf466d3603608aea2e9b497fd95fba9" - ] - ], - "versions": [ - "versions.yml:md5,a25a9f067f9ece70fa40d51efbcdbdee", - "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e", - "versions.yml:md5,ff9e30a2b6a2a38e584c66fc01f53b5e" - ] - }, + [ + { + "UNIFY_GENES:HUGOUNIFIER_GET": { + "hugo-unifier": "0.3.1" + } + }, + { + "UNIFY_GENES:HUGOUNIFIER_APPLY": { + "hugo-unifier": "0.3.1" + } + }, + { + "UNIFY_GENES:HUGOUNIFIER_APPLY": { + "hugo-unifier": "0.3.1" + } + } + ], { "n_obs": 12940, "n_vars": 9887, @@ -263,7 +226,7 @@ ] } ], - "timestamp": "2026-03-29T11:20:09.647383365", + "timestamp": "2026-03-29T14:31:03.525495969", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" From b051578e1da559f360ff364dfcec9a5ccfb2d587 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 15:17:20 +0200 Subject: [PATCH 32/46] Update more tests --- .../adata/mergeembeddings/tests/main.nf.test | 13 +- .../mergeembeddings/tests/main.nf.test.snap | 88 +- .../adata/splitembeddings/tests/main.nf.test | 8 +- .../splitembeddings/tests/main.nf.test.snap | 89 +- modules/local/adata/tords/tests/main.nf.test | 6 +- .../local/adata/tords/tests/main.nf.test.snap | 9 +- modules/local/adata/unify/tests/main.nf.test | 177 +- .../local/adata/unify/tests/main.nf.test.snap | 1453 ++++++++++++++++- .../local/adata/upsetgenes/tests/main.nf.test | 6 +- .../adata/upsetgenes/tests/main.nf.test.snap | 12 +- .../custom/collectsizes/tests/main.nf.test | 6 +- .../collectsizes/tests/main.nf.test.snap | 10 +- .../local/scanpy/plotqc/tests/main.nf.test | 6 +- .../scanpy/plotqc/tests/main.nf.test.snap | 11 +- subworkflows/local/combine/main.nf | 2 +- 15 files changed, 1782 insertions(+), 114 deletions(-) diff --git a/modules/local/adata/mergeembeddings/tests/main.nf.test b/modules/local/adata/mergeembeddings/tests/main.nf.test index 501b83ee..a114e553 100644 --- a/modules/local/adata/mergeembeddings/tests/main.nf.test +++ b/modules/local/adata/mergeembeddings/tests/main.nf.test @@ -30,12 +30,15 @@ nextflow_process { assert process.success with(adata) { assert "X_emb" in obsm - // Should have cells from both base (50) and integrated (30) assert obs.rownames.size() == 80 } assert file(process.out.obsm[0]).name == "X_scvi.pkl" assert process.out.obs.size() == 0 - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -68,7 +71,11 @@ nextflow_process { } assert file(process.out.obsm[0]).name == "X_scanvi.pkl" assert file(process.out.obs[0]).name == "scanvi.pkl" - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/adata/mergeembeddings/tests/main.nf.test.snap b/modules/local/adata/mergeembeddings/tests/main.nf.test.snap index a34b8b1a..f23f720f 100644 --- a/modules/local/adata/mergeembeddings/tests/main.nf.test.snap +++ b/modules/local/adata/mergeembeddings/tests/main.nf.test.snap @@ -36,12 +36,52 @@ "versions": [ "versions.yml:md5,3d07e17bd07e6c00aca3a44b734c7932" ] + }, + { + "ADATA_MERGEEMBEDDINGS": { + "anndata": "0.12.10", + "python": "3.13.12" + } + }, + { + "n_obs": 80, + "n_vars": 100, + "obs": { + "index": "_index", + "columns": [ + "label:scANVI" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_emb" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:44:44.292571618", + "timestamp": "2026-03-29T14:52:29.252580895", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - stub": { @@ -126,12 +166,52 @@ "versions": [ "versions.yml:md5,3d07e17bd07e6c00aca3a44b734c7932" ] + }, + { + "ADATA_MERGEEMBEDDINGS": { + "anndata": "0.12.10", + "python": "3.13.12" + } + }, + { + "n_obs": 80, + "n_vars": 100, + "obs": { + "index": "_index", + "columns": [ + + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + "X_emb" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:44:33.161545572", + "timestamp": "2026-03-29T14:52:09.297927484", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/adata/splitembeddings/tests/main.nf.test b/modules/local/adata/splitembeddings/tests/main.nf.test index c45f8175..2113b0e3 100644 --- a/modules/local/adata/splitembeddings/tests/main.nf.test +++ b/modules/local/adata/splitembeddings/tests/main.nf.test @@ -26,8 +26,14 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - assert snapshot(process.out).match() + assert "X_emb" in adata.obsm + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/adata/splitembeddings/tests/main.nf.test.snap b/modules/local/adata/splitembeddings/tests/main.nf.test.snap index 93aca767..911f0c48 100644 --- a/modules/local/adata/splitembeddings/tests/main.nf.test.snap +++ b/modules/local/adata/splitembeddings/tests/main.nf.test.snap @@ -57,12 +57,97 @@ "versions": [ "versions.yml:md5,c19d8adf68e8f111100a334d06042be0" ] + }, + { + "ADATA_SPLITEMBEDDINGS": { + "anndata": "0.12.10", + "python": "3.13.12" + } + }, + { + "n_obs": 23364, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "bbknn-global-0.5:entropy", + "bbknn-global-0.5_leiden", + "bbknn-global-1.0:entropy", + "bbknn-global-1.0_leiden", + "celltypist:Adult_Human_Skin", + "celltypist:Adult_Human_Skin:conf", + "combat-global-0.5:entropy", + "combat-global-0.5_leiden", + "combat-global-1.0:entropy", + "combat-global-1.0_leiden", + "condition", + "harmony-global-0.5:entropy", + "harmony-global-0.5_leiden", + "harmony-global-1.0:entropy", + "harmony-global-1.0_leiden", + "label", + "n_counts", + "n_genes", + "n_genes_by_counts", + "pct_counts_mt", + "sample", + "sample_original", + "scvi-global-0.5:entropy", + "scvi-global-0.5_leiden", + "scvi-global-1.0:entropy", + "scvi-global-1.0_leiden", + "total_counts", + "total_counts_mt" + ] + }, + "var": { + "index": "_index", + "columns": [ + "intersection" + ] + }, + "layers": [ + + ], + "obsm": [ + "X_emb" + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + "bbknn-global-0.5_characteristic_genes", + "bbknn-global-0.5_paga", + "bbknn-global-1.0_characteristic_genes", + "bbknn-global-1.0_paga", + "combat-global-0.5_characteristic_genes", + "combat-global-0.5_liana", + "combat-global-0.5_paga", + "combat-global-1.0_characteristic_genes", + "combat-global-1.0_liana", + "combat-global-1.0_paga", + "harmony-global-0.5_characteristic_genes", + "harmony-global-0.5_paga", + "harmony-global-1.0_characteristic_genes", + "harmony-global-1.0_paga", + "scvi-global-0.5_characteristic_genes", + "scvi-global-0.5_paga", + "scvi-global-1.0_characteristic_genes", + "scvi-global-1.0_paga" + ] } ], - "timestamp": "2026-03-16T15:13:31.208997494", + "timestamp": "2026-03-29T14:55:42.179483745", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/adata/tords/tests/main.nf.test b/modules/local/adata/tords/tests/main.nf.test index 66f20a1f..df3ddc6a 100644 --- a/modules/local/adata/tords/tests/main.nf.test +++ b/modules/local/adata/tords/tests/main.nf.test @@ -27,8 +27,10 @@ nextflow_process { then { assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml + ).match() } } diff --git a/modules/local/adata/tords/tests/main.nf.test.snap b/modules/local/adata/tords/tests/main.nf.test.snap index 8954c160..9c896bd5 100644 --- a/modules/local/adata/tords/tests/main.nf.test.snap +++ b/modules/local/adata/tords/tests/main.nf.test.snap @@ -57,12 +57,17 @@ "versions": [ "versions.yml:md5,bf93dcd42995e7fa34eac37384568f9d" ] + }, + { + "ADATA_TORDS": { + "anndataR": "1.0.2" + } } ], - "timestamp": "2026-03-14T21:05:44.197188707", + "timestamp": "2026-03-29T14:52:16.412480466", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/adata/unify/tests/main.nf.test b/modules/local/adata/unify/tests/main.nf.test index d4ee9d36..dc636c8a 100644 --- a/modules/local/adata/unify/tests/main.nf.test +++ b/modules/local/adata/unify/tests/main.nf.test @@ -45,7 +45,11 @@ nextflow_process { assert !("counts" in layers) assert layers.size() == 0 } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -82,7 +86,11 @@ nextflow_process { assert "sample" in obs.colnames assert layers.size() == 0 } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -115,8 +123,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -150,7 +163,11 @@ nextflow_process { with(adata) { assert "original_index" in var.colnames } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -186,7 +203,11 @@ nextflow_process { def adata = anndata(process.out.h5ad[0][1]) assert process.success assert adata.var.rownames.toUnique().size() == adata.var.rownames.size() - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -218,7 +239,11 @@ nextflow_process { def adata = anndata(process.out.h5ad[0][1]) assert process.success assert adata.var.rownames.toUnique().size() == adata.var.rownames.size() - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -250,7 +275,11 @@ nextflow_process { def adata = anndata(process.out.h5ad[0][1]) assert process.success assert adata.var.rownames.toUnique().size() == adata.var.rownames.size() - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -283,7 +312,11 @@ nextflow_process { assert process.success // make_unique adds numeric suffixes — var names are unique but not aggregated assert adata.var.rownames.toUnique().size() == adata.var.rownames.size() - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -322,7 +355,11 @@ nextflow_process { // After isoform aggregation, numeric suffixes should be removed assert var.rownames.every { !it.matches(/.*\\.\\d+$/) } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -362,7 +399,11 @@ nextflow_process { assert !("batch_id" in obs.colnames) assert obs.get("batch").unique().every { it.contains("_test") } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -397,7 +438,11 @@ nextflow_process { assert "batch" in obs.colnames assert obs.get("batch").unique().every { it.contains("_test") } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -432,7 +477,11 @@ nextflow_process { assert "batch" in obs.colnames assert obs.get("batch").unique().every { it == "test_test" } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -502,7 +551,11 @@ nextflow_process { assert !("cell_type" in obs.colnames) assert obs.get("label").unique().size() > 0 } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -537,7 +590,11 @@ nextflow_process { assert "label" in obs.colnames assert obs.get("label").unique().size() > 0 } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -572,7 +629,11 @@ nextflow_process { assert "label" in obs.colnames assert obs.get("label").unique().every { it == "Unknown" } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -607,7 +668,11 @@ nextflow_process { assert "label" in obs.colnames assert "Unknown" in obs.get("label").unique() } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -642,7 +707,11 @@ nextflow_process { assert "label" in obs.colnames assert "Unknown" in obs.get("label").unique() } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -678,7 +747,11 @@ nextflow_process { // Labels should be normalized (no spaces, dashes, special chars) assert obs.get("label").unique().every { !it.contains(" ") && !it.contains("-") && !it.contains("+") } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -748,7 +821,11 @@ nextflow_process { assert !("disease_state" in obs.colnames) assert obs.get("condition").unique().size() > 0 } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -783,7 +860,11 @@ nextflow_process { assert "condition" in obs.colnames assert obs.get("condition").unique().size() > 0 } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -818,7 +899,11 @@ nextflow_process { assert "condition" in obs.colnames assert obs.get("condition").unique().every { it == "Unknown" } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -881,8 +966,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -911,8 +1001,13 @@ nextflow_process { } then { + def adata = anndata(process.out.h5ad[0][1]) assert process.success - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -951,7 +1046,11 @@ nextflow_process { // All cell names should be prefixed assert obs.rownames.every { it.startsWith("test_") } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -987,7 +1086,11 @@ nextflow_process { assert "sample_original" in obs.colnames assert obs.get("sample").unique().every { it == "test" } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -1022,7 +1125,11 @@ nextflow_process { assert "sample" in obs.colnames assert obs.get("sample").unique().every { it == "test" } } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -1063,7 +1170,11 @@ nextflow_process { assert uns.size() == 0 assert layers.size() == 0 } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -1107,7 +1218,11 @@ nextflow_process { assert uns.size() == 0 assert layers.size() == 0 } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } @@ -1147,7 +1262,11 @@ nextflow_process { assert uns.size() == 0 assert layers.size() == 0 } - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml, + adata.yaml + ).match() } } diff --git a/modules/local/adata/unify/tests/main.nf.test.snap b/modules/local/adata/unify/tests/main.nf.test.snap index ae86783a..73121bfb 100644 --- a/modules/local/adata/unify/tests/main.nf.test.snap +++ b/modules/local/adata/unify/tests/main.nf.test.snap @@ -24,12 +24,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:17:15.684411771", + "timestamp": "2026-03-29T14:56:53.251161983", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle sample column with different value": { @@ -57,12 +103,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:19:52.912657028", + "timestamp": "2026-03-29T15:01:01.165008808", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle symbols in column": { @@ -90,12 +182,59 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "original_index", + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:14:30.460619874", + "timestamp": "2026-03-29T14:53:06.26109274", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle label column with different name": { @@ -123,12 +262,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:17:04.588955265", + "timestamp": "2026-03-29T14:56:34.900590714", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should create condition column when missing": { @@ -156,12 +341,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:18:48.352425666", + "timestamp": "2026-03-29T14:59:24.088148335", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle label column with unknown values": { @@ -189,12 +420,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:17:38.16180871", + "timestamp": "2026-03-29T14:57:31.870669065", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle duplicates with sum aggregation": { @@ -222,12 +499,59 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "original_index", + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:14:59.92375867", + "timestamp": "2026-03-29T14:53:32.347938099", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should create batch column when missing": { @@ -255,12 +579,57 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:16:42.291640291", + "timestamp": "2026-03-29T14:55:55.84386358", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run without failures - stub": { @@ -321,12 +690,59 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9937, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "original_index", + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:15:57.903315865", + "timestamp": "2026-03-29T14:54:38.882767578", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle condition column with different name": { @@ -354,12 +770,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:18:22.557718057", + "timestamp": "2026-03-29T14:58:45.748755829", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle duplicates with mean aggregation": { @@ -387,12 +849,59 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "original_index", + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:15:28.4354681", + "timestamp": "2026-03-29T14:53:56.526120053", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should aggregate isoforms": { @@ -420,12 +929,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:16:08.914108958", + "timestamp": "2026-03-29T14:54:57.071278012", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle condition column already named condition": { @@ -453,12 +1008,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:18:35.814191761", + "timestamp": "2026-03-29T14:59:04.275089995", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should normalize label column with special characters": { @@ -486,12 +1087,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:18:01.193993289", + "timestamp": "2026-03-29T14:58:09.361409579", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should create label column when missing": { @@ -519,12 +1166,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:17:26.892769495", + "timestamp": "2026-03-29T14:57:12.4063596", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle CSR sparse matrix": { @@ -552,12 +1245,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:19:12.458275697", + "timestamp": "2026-03-29T15:00:01.784544718", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle CSC sparse matrix": { @@ -585,12 +1324,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:19:26.441833105", + "timestamp": "2026-03-29T15:00:21.051026466", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle batch column with different name": { @@ -618,12 +1403,57 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:16:19.536570356", + "timestamp": "2026-03-29T14:55:16.158601868", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle label column with NaN values": { @@ -651,12 +1481,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:17:49.960531221", + "timestamp": "2026-03-29T14:57:50.573060947", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should remove obsm, varm, uns, and layers": { @@ -684,12 +1560,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:20:17.793802423", + "timestamp": "2026-03-29T15:01:41.445930077", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle duplicates with max aggregation": { @@ -717,12 +1639,59 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "original_index", + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:15:47.399791749", + "timestamp": "2026-03-29T14:54:20.647392444", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should create sample column when missing": { @@ -750,12 +1719,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:20:04.777517593", + "timestamp": "2026-03-29T15:01:21.148229802", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle batch column already named batch": { @@ -783,12 +1798,57 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:16:31.488655855", + "timestamp": "2026-03-29T14:55:35.420110559", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle complex structure": { @@ -816,12 +1876,60 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "gene_id", + "original_index", + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:20:42.731739831", + "timestamp": "2026-03-29T15:02:22.64116359", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle counts in layer": { @@ -849,12 +1957,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:13:51.662484416", + "timestamp": "2026-03-29T14:52:30.401577773", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle counts in X matrix": { @@ -882,12 +2036,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:13:30.614823898", + "timestamp": "2026-03-29T14:52:10.928524596", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle symbols as index": { @@ -915,12 +2115,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:14:12.108232932", + "timestamp": "2026-03-29T14:52:48.132443363", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle minimal structure": { @@ -948,12 +2194,57 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:20:30.122685513", + "timestamp": "2026-03-29T15:02:01.13903733", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should handle duplicate cell names": { @@ -981,12 +2272,58 @@ "versions": [ "versions.yml:md5,3584046bdacc455c1d7d03d51ded03cb" ] + }, + { + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + } + }, + { + "n_obs": 12940, + "n_vars": 9887, + "obs": { + "index": "_index", + "columns": [ + "batch", + "condition", + "label", + "sample", + "sample_original" + ] + }, + "var": { + "index": "_index", + "columns": [ + "symbols" + ] + }, + "layers": [ + + ], + "obsm": [ + + ], + "varm": [ + + ], + "obsp": [ + + ], + "varp": [ + + ], + "uns": [ + + ] } ], - "timestamp": "2026-03-16T15:19:39.263298116", + "timestamp": "2026-03-29T15:00:41.681029229", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/adata/upsetgenes/tests/main.nf.test b/modules/local/adata/upsetgenes/tests/main.nf.test index 4b7fa2e0..a104c389 100644 --- a/modules/local/adata/upsetgenes/tests/main.nf.test +++ b/modules/local/adata/upsetgenes/tests/main.nf.test @@ -30,8 +30,10 @@ nextflow_process { then { assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml + ).match() } } diff --git a/modules/local/adata/upsetgenes/tests/main.nf.test.snap b/modules/local/adata/upsetgenes/tests/main.nf.test.snap index 64402386..1e2ad56c 100644 --- a/modules/local/adata/upsetgenes/tests/main.nf.test.snap +++ b/modules/local/adata/upsetgenes/tests/main.nf.test.snap @@ -69,12 +69,20 @@ "versions": [ "versions.yml:md5,e45c6196557674c1f638289fd20f6cf3" ] + }, + { + "ADATA_UPSETGENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + } } ], - "timestamp": "2026-03-16T15:15:06.26124523", + "timestamp": "2026-03-29T14:52:10.760796153", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/custom/collectsizes/tests/main.nf.test b/modules/local/custom/collectsizes/tests/main.nf.test index ee24cd74..bbc63ad2 100644 --- a/modules/local/custom/collectsizes/tests/main.nf.test +++ b/modules/local/custom/collectsizes/tests/main.nf.test @@ -24,8 +24,10 @@ nextflow_process { then { assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml + ).match() } } diff --git a/modules/local/custom/collectsizes/tests/main.nf.test.snap b/modules/local/custom/collectsizes/tests/main.nf.test.snap index 792e40a7..56e8df9f 100644 --- a/modules/local/custom/collectsizes/tests/main.nf.test.snap +++ b/modules/local/custom/collectsizes/tests/main.nf.test.snap @@ -69,12 +69,18 @@ "versions": [ "versions.yml:md5,9d20a6e34fd08f441c0efb937cf52806" ] + }, + { + "CUSTOM_COLLECTSIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + } } ], - "timestamp": "2026-03-16T19:04:34.30658104", + "timestamp": "2026-03-29T14:52:06.15939485", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/scanpy/plotqc/tests/main.nf.test b/modules/local/scanpy/plotqc/tests/main.nf.test index e803619e..adf61bcd 100644 --- a/modules/local/scanpy/plotqc/tests/main.nf.test +++ b/modules/local/scanpy/plotqc/tests/main.nf.test @@ -26,8 +26,10 @@ nextflow_process { then { assert process.success - - assert snapshot(process.out).match() + assert snapshot( + process.out, + path(process.out.versions[0]).yaml + ).match() } } diff --git a/modules/local/scanpy/plotqc/tests/main.nf.test.snap b/modules/local/scanpy/plotqc/tests/main.nf.test.snap index 1de12f12..f92c7b0f 100644 --- a/modules/local/scanpy/plotqc/tests/main.nf.test.snap +++ b/modules/local/scanpy/plotqc/tests/main.nf.test.snap @@ -69,12 +69,19 @@ "versions": [ "versions.yml:md5,0bf6e1aafa1eb89d15132965ac3c5d15" ] + }, + { + "SCANPY_PLOTQC": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + } } ], - "timestamp": "2026-03-16T15:14:17.873430808", + "timestamp": "2026-03-29T14:52:14.317465255", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/subworkflows/local/combine/main.nf b/subworkflows/local/combine/main.nf index a0e22835..ca16cbde 100644 --- a/subworkflows/local/combine/main.nf +++ b/subworkflows/local/combine/main.nf @@ -27,7 +27,7 @@ workflow COMBINE { ADATA_MERGE( ch_h5ad .map { _meta, h5ad -> [[id: "merged"], h5ad] } - .groupTuple(), + .groupTuple(sort: true), ch_base, ) ch_var = ch_var.mix(ADATA_MERGE.out.intersect_genes) From 6f0481e3f06a96d0d1758d58a404f87c4abfe0bc Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 15:17:36 +0200 Subject: [PATCH 33/46] Fix adata/merge determinism issue --- modules/local/adata/merge/tests/main.nf.test | 4 ++-- modules/local/adata/merge/tests/main.nf.test.snap | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/adata/merge/tests/main.nf.test b/modules/local/adata/merge/tests/main.nf.test index 6cce785d..86e4ab5b 100644 --- a/modules/local/adata/merge/tests/main.nf.test +++ b/modules/local/adata/merge/tests/main.nf.test @@ -41,7 +41,7 @@ nextflow_process { } process { """ - input[0] = ADATA_UNIFY.out.h5ad.map{ _meta, h5ad -> [[id: 'combined'], h5ad] }.groupTuple() + input[0] = ADATA_UNIFY.out.h5ad.map{ _meta, h5ad -> [[id: 'combined'], h5ad] }.groupTuple(sort: true) input[1] = [[], []] """ } @@ -73,7 +73,7 @@ nextflow_process { } process { """ - input[0] = ADATA_UNIFY.out.h5ad.map{ _meta, h5ad -> [[id: 'combined'], h5ad] }.groupTuple() + input[0] = ADATA_UNIFY.out.h5ad.map{ _meta, h5ad -> [[id: 'combined'], h5ad] }.groupTuple(sort: true) input[1] = [[], []] """ } diff --git a/modules/local/adata/merge/tests/main.nf.test.snap b/modules/local/adata/merge/tests/main.nf.test.snap index fe55d298..d9288fb1 100644 --- a/modules/local/adata/merge/tests/main.nf.test.snap +++ b/modules/local/adata/merge/tests/main.nf.test.snap @@ -186,10 +186,10 @@ ] } ], - "timestamp": "2026-03-29T13:52:58.903537417", + "timestamp": "2026-03-29T15:15:03.443383668", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.4" + "nextflow": "25.10.2" } }, "Should run with base": { From 1f7e98a6a84d8d1e382eb19f70fe97fc59ad5bb4 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Sun, 29 Mar 2026 15:50:16 +0200 Subject: [PATCH 34/46] Another attempt of fixing adata/merge --- modules/local/adata/merge/tests/main.nf.test | 4 ++-- modules/local/adata/merge/tests/main.nf.test.snap | 14 +++++++------- subworkflows/local/combine/main.nf | 3 ++- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/modules/local/adata/merge/tests/main.nf.test b/modules/local/adata/merge/tests/main.nf.test index 86e4ab5b..b4f033f0 100644 --- a/modules/local/adata/merge/tests/main.nf.test +++ b/modules/local/adata/merge/tests/main.nf.test @@ -41,7 +41,7 @@ nextflow_process { } process { """ - input[0] = ADATA_UNIFY.out.h5ad.map{ _meta, h5ad -> [[id: 'combined'], h5ad] }.groupTuple(sort: true) + input[0] = ADATA_UNIFY.out.h5ad.map{ _meta, h5ad -> [[id: 'combined'], h5ad] }.groupTuple().map{ meta, h5ads -> [meta, h5ads.sort{ a, b -> a.name <=> b.name }] } input[1] = [[], []] """ } @@ -73,7 +73,7 @@ nextflow_process { } process { """ - input[0] = ADATA_UNIFY.out.h5ad.map{ _meta, h5ad -> [[id: 'combined'], h5ad] }.groupTuple(sort: true) + input[0] = ADATA_UNIFY.out.h5ad.map{ _meta, h5ad -> [[id: 'combined'], h5ad] }.groupTuple().map{ meta, h5ads -> [meta, h5ads.sort{ it.name }] } input[1] = [[], []] """ } diff --git a/modules/local/adata/merge/tests/main.nf.test.snap b/modules/local/adata/merge/tests/main.nf.test.snap index d9288fb1..9c03c681 100644 --- a/modules/local/adata/merge/tests/main.nf.test.snap +++ b/modules/local/adata/merge/tests/main.nf.test.snap @@ -7,7 +7,7 @@ { "id": "combined" }, - "combined_outer.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" + "combined_outer.h5ad:md5,d03dc674beb17ce07839ea78791fec77" ] ], "1": [ @@ -15,7 +15,7 @@ { "id": "combined" }, - "combined_inner.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" + "combined_inner.h5ad:md5,d03dc674beb17ce07839ea78791fec77" ] ], "2": [ @@ -23,7 +23,7 @@ { "id": "combined" }, - "combined_integrate.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" + "combined_integrate.h5ad:md5,d03dc674beb17ce07839ea78791fec77" ] ], "3": [ @@ -37,7 +37,7 @@ { "id": "combined" }, - "combined_inner.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" + "combined_inner.h5ad:md5,d03dc674beb17ce07839ea78791fec77" ] ], "integrate": [ @@ -45,7 +45,7 @@ { "id": "combined" }, - "combined_integrate.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" + "combined_integrate.h5ad:md5,d03dc674beb17ce07839ea78791fec77" ] ], "intersect_genes": [ @@ -56,7 +56,7 @@ { "id": "combined" }, - "combined_outer.h5ad:md5,4b877999213cc0272cbfe601f371c2e1" + "combined_outer.h5ad:md5,d03dc674beb17ce07839ea78791fec77" ] ], "versions": [ @@ -186,7 +186,7 @@ ] } ], - "timestamp": "2026-03-29T15:15:03.443383668", + "timestamp": "2026-03-29T15:46:45.952212141", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/combine/main.nf b/subworkflows/local/combine/main.nf index ca16cbde..bd46eb85 100644 --- a/subworkflows/local/combine/main.nf +++ b/subworkflows/local/combine/main.nf @@ -27,7 +27,8 @@ workflow COMBINE { ADATA_MERGE( ch_h5ad .map { _meta, h5ad -> [[id: "merged"], h5ad] } - .groupTuple(sort: true), + .groupTuple() + .map { meta, h5ads -> [meta, h5ads.sort { a, b -> a.name <=> b.name }] }, ch_base, ) ch_var = ch_var.mix(ADATA_MERGE.out.intersect_genes) From 30f16891bb411636a79c7631068ac550b5980ef6 Mon Sep 17 00:00:00 2001 From: Erik Fasterius Date: Sun, 29 Mar 2026 19:00:17 +0200 Subject: [PATCH 35/46] Update snapshots --- .../rankaggregate/tests/main.nf.test.snap | 14 +- .../local/scanpy/pca/tests/main.nf.test.snap | 10 +- .../rankgenesgroups/tests/main.nf.test.snap | 10 +- tests/default.nf.test.snap | 11 +- tests/main_pipeline_build.nf.test.snap | 11 +- tests/main_pipeline_extend.nf.test.snap | 147 +----------------- tests/main_pipeline_qc.nf.test.snap | 11 +- ...in_pipeline_reference_mapping.nf.test.snap | 102 +----------- tests/main_pipeline_sub.nf.test.snap | 10 +- 9 files changed, 35 insertions(+), 291 deletions(-) diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test.snap b/modules/local/liana/rankaggregate/tests/main.nf.test.snap index 47f65e87..605146c3 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test.snap +++ b/modules/local/liana/rankaggregate/tests/main.nf.test.snap @@ -46,11 +46,11 @@ { "id": "test" }, - "test_liana.h5ad:md5,c227d198aa472576b58ffe61ff37027b" + "test_liana.h5ad:md5,2091717718c2506ae92fa43a3132ed1c" ] ], "1": [ - "test_liana.pkl:md5,058214ae3910f43472b791830a606047" + "test_liana.pkl:md5,f161ee10f742898fe3f8a42a22b440f9" ], "2": [ "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" @@ -60,11 +60,11 @@ { "id": "test" }, - "test_liana.h5ad:md5,c227d198aa472576b58ffe61ff37027b" + "test_liana.h5ad:md5,2091717718c2506ae92fa43a3132ed1c" ] ], "uns": [ - "test_liana.pkl:md5,058214ae3910f43472b791830a606047" + "test_liana.pkl:md5,f161ee10f742898fe3f8a42a22b440f9" ], "versions": [ "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" @@ -116,10 +116,10 @@ ] } ], - "timestamp": "2026-03-29T11:18:40.019088419", + "timestamp": "2026-03-29T17:40:53.9124", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index 65d4e536..58ffb4b9 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,7 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ], "h5ad": [ [ @@ -28,14 +28,14 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ] } ], - "timestamp": "2026-03-28T22:12:17.200260088", + "timestamp": "2026-03-29T17:42:52.521545", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } }, "Should run without failures": { diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap index 9262a494..ba1f4f7a 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap @@ -172,7 +172,7 @@ { "id": "test" }, - "test_characteristic_genes.h5ad:md5,557ccc34f354c9c0b8b74dedd4550688" + "test_characteristic_genes.h5ad:md5,d8ad5714c35d2bda2f6ddefb99ec6a81" ] ], "1": [ @@ -192,7 +192,7 @@ { "id": "test" }, - "test_characteristic_genes.h5ad:md5,557ccc34f354c9c0b8b74dedd4550688" + "test_characteristic_genes.h5ad:md5,d8ad5714c35d2bda2f6ddefb99ec6a81" ] ], "multiqc_files": [ @@ -260,10 +260,10 @@ ] } ], - "timestamp": "2026-03-29T11:19:18.847060178", + "timestamp": "2026-03-29T17:51:08.826799", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index f1cac52f..14145abe 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -259,13 +259,6 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -286,9 +279,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T10:26:55.684056857", + "timestamp": "2026-03-29T18:46:54.039339", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index eca749f1..489ef856 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -272,13 +272,6 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -299,9 +292,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T10:29:54.888502684", + "timestamp": "2026-03-29T18:49:17.189049", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_extend.nf.test.snap b/tests/main_pipeline_extend.nf.test.snap index 13150e7b..61ab933d 100644 --- a/tests/main_pipeline_extend.nf.test.snap +++ b/tests/main_pipeline_extend.nf.test.snap @@ -2,25 +2,6 @@ "Should perform scvi reference extension": { "content": [ { - "ADATA_EXTEND": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "ADATA_MERGE": { - "anndata": "0.12.10", - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "ADATA_MERGEEMBEDDINGS": { - "anndata": "0.12.10", - "python": "3.13.12" - }, - "ADATA_TORDS": { - "anndataR": "1.0.2" - }, "ADATA_UNIFY": { "anndata": "0.12.10", "numpy": "2.3.5", @@ -39,23 +20,6 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, - "CELLTYPES_CELLTYPIST": { - "python": "3.12.8", - "pandas": "2.2.3", - "scanpy": "1.10.4", - "celltypist": "1.6.3" - }, - "CELLTYPES_SINGLER": { - "R": "R version 4.5.3 (2026-03-11)", - "SingleR": "2.12.0", - "celldex": "1.20.0", - "anndataR": "1.0.2", - "ggplot2": "4.0.2" - }, - "COLLECT_SIZES": { - "pandas": "2.3.3", - "python": "3.13.12" - }, "DOUBLET_REMOVAL": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -63,21 +27,6 @@ "python": "3.13.12", "upsetplot": "0.9.0" }, - "ENTROPY": { - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "FINALIZE_QC_ANNDATAS": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "GET_DEDOUBLETED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" @@ -90,53 +39,19 @@ "python": "3.13.0", "anndata": "0.10.9" }, - "LEIDEN": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "NEIGHBORS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "QC_FILTERED": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, "QC_RAW": { "matplotlib": "3.10.8", "python": "3.13.12", "scanpy": "1.12" }, - "SCANPY_CELLCYCLE": { - "python": "3.13.12", - "scanpy": "1.12" - }, "SCANPY_FILTER": { "python": "3.13.12", "scanpy": "1.12" }, - "SCANPY_PAGA": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_RANKGENESGROUPS": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, "SCANPY_SCRUBLET": { "python": "3.12.11", "scanpy": "1.11.2" }, - "SCVITOOLS_SCVI": { - "scvi": "1.3.3" - }, - "UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, "UPSET_GENES": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -145,78 +60,26 @@ }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - }, - "liana": "1.6.1", - "python": "3.12.12", - "scanpy": "1.11.5" + } }, [ - "celltypes", - "celltypes/singler", - "celltypes/singler/SRR28679759_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679759_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679759_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679759_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679759_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_predictions.csv", - "cluster_dimred", - "cluster_dimred/scvi", - "cluster_dimred/scvi/entropy", - "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", - "cluster_dimred/scvi/leiden", - "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", - "cluster_dimred/scvi/umap", "combine", - "combine/integrate", - "combine/integrate/scvi", - "combine/integrate/scvi/scvi_model", - "combine/integrate/scvi/scvi_model/model.pt", "combine/merge", - "finalized", - "finalized/merged.h5ad", - "finalized/merged.rds", - "finalized/merged_metadata.csv", - "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_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", - "multiqc/multiqc_report.html", - "per_group", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "quality_control", "quality_control/qc_filtered", "quality_control/qc_filtered/SRR28679759_preprocessed_total_counts_vs_n_genes_by_counts.png", "quality_control/qc_raw", - "quality_control/qc_raw/SRR28679759_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/sizes", - "quality_control/sizes/sizes.tsv" + "quality_control/qc_raw/SRR28679759_raw_total_counts_vs_n_genes_by_counts.png" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-29T10:24:43.828273462", + "timestamp": "2026-03-29T17:32:04.88827", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index 2db90c24..ae865061 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -149,13 +149,6 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", @@ -175,9 +168,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T10:21:58.506298996", + "timestamp": "2026-03-29T18:13:02.828075", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 6c9b6727..0717be16 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -2,21 +2,6 @@ "Should perform scvi reference mapping": { "content": [ { - "ADATA_EXTEND": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "ADATA_MERGE": { - "anndata": "0.12.10", - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "ADATA_TORDS": { - "anndataR": "1.0.2" - }, "ADATA_UNIFY": { "anndata": "0.12.10", "numpy": "2.3.5", @@ -59,17 +44,6 @@ "python": "3.13.12", "upsetplot": "0.9.0" }, - "ENTROPY": { - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "FINALIZE_QC_ANNDATAS": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, "GET_DEDOUBLETED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" @@ -86,14 +60,6 @@ "python": "3.13.0", "anndata": "0.10.9" }, - "LEIDEN": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "NEIGHBORS": { - "python": "3.13.12", - "scanpy": "1.12" - }, "QC_FILTERED": { "matplotlib": "3.10.8", "python": "3.13.12", @@ -112,31 +78,10 @@ "python": "3.13.12", "scanpy": "1.12" }, - "SCANPY_HVGS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_PAGA": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_RANKGENESGROUPS": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, "SCANPY_SCRUBLET": { "python": "3.12.11", "scanpy": "1.11.2" }, - "SCVITOOLS_SCVI": { - "scvi": "1.3.3" - }, - "UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, "UPSET_GENES": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -145,10 +90,7 @@ }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - }, - "liana": "1.6.1", - "python": "3.12.12", - "scanpy": "1.11.5" + } }, [ "celltypes", @@ -162,44 +104,8 @@ "celltypes/singler/SRR28679759_singler_immune_direct_distribution.pdf", "celltypes/singler/SRR28679759_singler_immune_direct_heatmap.pdf", "celltypes/singler/SRR28679759_singler_predictions.csv", - "cluster_dimred", - "cluster_dimred/scvi", - "cluster_dimred/scvi/entropy", - "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", - "cluster_dimred/scvi/leiden", - "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", - "cluster_dimred/scvi/umap", "combine", - "combine/integrate", - "combine/integrate/scvi", - "combine/integrate/scvi/scvi_model", - "combine/integrate/scvi/scvi_model/model.pt", "combine/merge", - "finalized", - "finalized/merged.h5ad", - "finalized/merged.rds", - "finalized/merged_metadata.csv", - "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_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", - "multiqc/multiqc_report.html", - "per_group", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "quality_control", @@ -211,12 +117,12 @@ "quality_control/sizes/sizes.tsv" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-29T10:22:27.294854553", + "timestamp": "2026-03-29T17:34:25.000756", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } } diff --git a/tests/main_pipeline_sub.nf.test.snap b/tests/main_pipeline_sub.nf.test.snap index 6bf33463..45e88e8f 100644 --- a/tests/main_pipeline_sub.nf.test.snap +++ b/tests/main_pipeline_sub.nf.test.snap @@ -1,7 +1,7 @@ { "Should be able to perform subclustering": { "content": [ - 291, + 289, { "ADATA_EXTEND": { "anndata": "0.12.10", @@ -183,8 +183,6 @@ "per_group/condition:combat-SRR28679756-0.5_leiden:7/characteristic_genes", "per_group/condition:combat-SRR28679756-0.5_leiden:8", "per_group/condition:combat-SRR28679756-0.5_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:9", - "per_group/condition:combat-SRR28679756-0.5_leiden:9/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:0", "per_group/condition:combat-SRR28679756-1.0_leiden:0/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:1", @@ -199,8 +197,6 @@ "per_group/condition:combat-SRR28679756-1.0_leiden:13/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:14", "per_group/condition:combat-SRR28679756-1.0_leiden:14/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:15", - "per_group/condition:combat-SRR28679756-1.0_leiden:15/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:2", "per_group/condition:combat-SRR28679756-1.0_leiden:2/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:3", @@ -593,9 +589,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T10:17:32.99372406", + "timestamp": "2026-03-29T18:37:42.198507", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } } From dfc9be7dc5d11d90af915ad78c26ca03b22d2685 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Mon, 30 Mar 2026 07:54:26 +0200 Subject: [PATCH 36/46] Update scanpy/pca test snapshot --- modules/local/scanpy/pca/tests/main.nf.test.snap | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index 58ffb4b9..a4cf45df 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,7 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" ], "h5ad": [ [ @@ -28,13 +28,13 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" ] } ], - "timestamp": "2026-03-29T17:42:52.521545", + "timestamp": "2026-03-30T07:53:20.208532988", "meta": { - "nf-test": "0.9.5", + "nf-test": "0.9.4", "nextflow": "25.10.4" } }, From e22e0e2f75240717a801767092db13dcd84860f0 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Mon, 30 Mar 2026 08:10:14 +0200 Subject: [PATCH 37/46] Update upstream modules --- modules.json | 21 +- modules/nf-core/anndata/barcodes/main.nf | 2 +- modules/nf-core/anndata/barcodes/meta.yml | 17 +- .../anndata/barcodes/tests/main.nf.test | 8 +- .../anndata/barcodes/tests/main.nf.test.snap | 50 +- .../cellbender/merge/cellbender-merge.diff | 27 - modules/nf-core/cellbender/merge/main.nf | 10 +- modules/nf-core/cellbender/merge/meta.yml | 28 +- .../cellbender/merge/tests/main.nf.test | 2 + .../cellbender/merge/tests/main.nf.test.snap | 20 +- .../cellbender/removebackground/main.nf | 63 +- .../cellbender/removebackground/meta.yml | 54 +- .../removebackground/tests/gpu.nf.test | 2 +- .../removebackground/tests/gpu.nf.test.snap | 42 +- .../removebackground/tests/main.nf.test | 2 +- .../removebackground/tests/main.nf.test.snap | 42 +- .../linux_amd64-bd-c1f4a7982b743963_1.txt | 1552 +++++++++++++++++ .../linux_arm64-bd-40bf3b435e89dc22_1.txt | 1502 ++++++++++++++++ modules/nf-core/multiqc/main.nf | 27 +- modules/nf-core/multiqc/meta.yml | 168 +- modules/nf-core/multiqc/tests/main.nf.test | 191 +- .../nf-core/multiqc/tests/main.nf.test.snap | 407 ++++- modules/nf-core/multiqc/tests/nextflow.config | 1 + modules/nf-core/untar/main.nf | 11 +- modules/nf-core/untar/meta.yml | 28 +- modules/nf-core/untar/tests/main.nf.test | 20 +- modules/nf-core/untar/tests/main.nf.test.snap | 176 +- .../main.nf | 6 - .../tests/main.nf.test | 3 +- .../tests/main.nf.test.snap | 31 +- 30 files changed, 4001 insertions(+), 512 deletions(-) delete mode 100644 modules/nf-core/cellbender/merge/cellbender-merge.diff 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_arm64-bd-40bf3b435e89dc22_1.txt diff --git a/modules.json b/modules.json index d4074a41..39a8e374 100644 --- a/modules.json +++ b/modules.json @@ -7,7 +7,7 @@ "nf-core": { "anndata/barcodes": { "branch": "master", - "git_sha": "e753770db613ce014b3c4bc94f6cba443427b726", + "git_sha": "be8a8b740b7e58b8b992774f26307f3d7df9a250", "installed_by": ["h5ad_removebackground_barcodes_cellbender_anndata", "modules"] }, "anndata/getsize": { @@ -17,13 +17,12 @@ }, "cellbender/merge": { "branch": "master", - "git_sha": "e753770db613ce014b3c4bc94f6cba443427b726", - "installed_by": ["modules"], - "patch": "modules/nf-core/cellbender/merge/cellbender-merge.diff" + "git_sha": "380cb90926b8c28558cb11479da5ff45bc4f1c5d", + "installed_by": ["modules"] }, "cellbender/removebackground": { "branch": "master", - "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", + "git_sha": "b7d92b962382d64514f6c5ec6901078d90cc5a44", "installed_by": ["h5ad_removebackground_barcodes_cellbender_anndata", "modules"] }, "doubletdetection": { @@ -33,7 +32,7 @@ }, "multiqc": { "branch": "master", - "git_sha": "5bdb098216aaf5df9c3b6343e6204cd932503c16", + "git_sha": "79b36b51048048374b642289bfe9e591ef56fe05", "installed_by": ["modules"] }, "scanpy/scrublet": { @@ -44,18 +43,16 @@ "scvitools/scar": { "branch": "master", "git_sha": "e753770db613ce014b3c4bc94f6cba443427b726", - "installed_by": ["modules"], - "patch": "modules/nf-core/scvitools/scar/scvitools-scar.diff" + "installed_by": ["modules"] }, "scvitools/solo": { "branch": "master", "git_sha": "e753770db613ce014b3c4bc94f6cba443427b726", - "installed_by": ["modules"], - "patch": "modules/nf-core/scvitools/solo/scvitools-solo.diff" + "installed_by": ["modules"] }, "untar": { "branch": "master", - "git_sha": "00ee87ebb541af0008596400ce6d5f66d79d5408", + "git_sha": "447f7bc0fa41dfc2400c8cad4c0291880dc060cf", "installed_by": ["modules"] } } @@ -64,7 +61,7 @@ "nf-core": { "h5ad_removebackground_barcodes_cellbender_anndata": { "branch": "master", - "git_sha": "ed115522edb3c5ed73a891a5d00ee839d157c650", + "git_sha": "b7d92b962382d64514f6c5ec6901078d90cc5a44", "installed_by": ["subworkflows"] }, "utils_nextflow_pipeline": { diff --git a/modules/nf-core/anndata/barcodes/main.nf b/modules/nf-core/anndata/barcodes/main.nf index 35c7b48c..4893a8c9 100644 --- a/modules/nf-core/anndata/barcodes/main.nf +++ b/modules/nf-core/anndata/barcodes/main.nf @@ -12,7 +12,7 @@ process ANNDATA_BARCODES { output: tuple val(meta), path("*.h5ad"), emit: h5ad - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions_anndata, topic: versions when: task.ext.when == null || task.ext.when diff --git a/modules/nf-core/anndata/barcodes/meta.yml b/modules/nf-core/anndata/barcodes/meta.yml index d948e680..5ffc3ecd 100644 --- a/modules/nf-core/anndata/barcodes/meta.yml +++ b/modules/nf-core/anndata/barcodes/meta.yml @@ -1,6 +1,6 @@ name: anndata_barcodes -description: Module to subset AnnData object to cells with matching barcodes from - the csv file +description: Module to subset AnnData object to cells with matching barcodes + from the csv file keywords: - single-cell - barcodes @@ -14,7 +14,8 @@ tools: documentation: "https://anndata.readthedocs.io" tool_dev_url: "https://github.com/theislab/anndata" doi: "10.21105/joss.04371" - licence: ["BSD-3-clause"] + licence: + - "BSD-3-clause" identifier: biotools:anndata input: - - meta: @@ -50,13 +51,21 @@ output: pattern: "*.h5ad" ontologies: - edam: "http://edamontology.org/format_3590" # HDF5 - versions: + versions_anndata: - versions.yml: type: file description: File containing software versions pattern: "versions.yml" ontologies: - edam: "http://edamontology.org/format_3750" # YAML +topics: + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: "http://edamontology.org/format_3750" authors: - "@nictru" - "@chaochaowong" diff --git a/modules/nf-core/anndata/barcodes/tests/main.nf.test b/modules/nf-core/anndata/barcodes/tests/main.nf.test index 09dab520..2b68f8c4 100644 --- a/modules/nf-core/anndata/barcodes/tests/main.nf.test +++ b/modules/nf-core/anndata/barcodes/tests/main.nf.test @@ -15,7 +15,7 @@ nextflow_process { """ input[0] = channel.from([ [ - [ id:'test', single_end:false ], // meta map + [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/scrnaseq/h5ad/SRR28679759_filtered_matrix.h5ad', checkIfExists: true) ] @@ -27,7 +27,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } @@ -42,7 +42,7 @@ nextflow_process { """ input[0] = channel.from([ [ - [ id:'test', single_end:false ], // meta map + [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/scrnaseq/h5ad/SRR28679759_filtered_matrix.h5ad', checkIfExists: true) ] @@ -54,7 +54,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } diff --git a/modules/nf-core/anndata/barcodes/tests/main.nf.test.snap b/modules/nf-core/anndata/barcodes/tests/main.nf.test.snap index 070bed63..34c7ec56 100644 --- a/modules/nf-core/anndata/barcodes/tests/main.nf.test.snap +++ b/modules/nf-core/anndata/barcodes/tests/main.nf.test.snap @@ -2,71 +2,45 @@ "scdownstream - h5ad - csv - stub": { "content": [ { - "0": [ - [ - { - "id": "test", - "single_end": false - }, - "test.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - "versions.yml:md5,a67b616625325797d4ae6f996b2cfb1d" - ], "h5ad": [ [ { - "id": "test", - "single_end": false + "id": "test" }, "test.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ + "versions_anndata": [ "versions.yml:md5,a67b616625325797d4ae6f996b2cfb1d" ] } ], + "timestamp": "2026-03-15T19:12:06.598082087", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-11T13:32:57.324009122" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, "scdownstream - h5ad - csv": { "content": [ { - "0": [ - [ - { - "id": "test", - "single_end": false - }, - "test.h5ad:md5,d07d45f8d8d46411bf049f3ccff475f3" - ] - ], - "1": [ - "versions.yml:md5,c101fba36a629db79bf582b25fa301dd" - ], "h5ad": [ [ { - "id": "test", - "single_end": false + "id": "test" }, "test.h5ad:md5,d07d45f8d8d46411bf049f3ccff475f3" ] ], - "versions": [ + "versions_anndata": [ "versions.yml:md5,c101fba36a629db79bf582b25fa301dd" ] } ], + "timestamp": "2026-03-15T19:11:57.14168146", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-11T13:32:49.298191972" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } } } \ No newline at end of file diff --git a/modules/nf-core/cellbender/merge/cellbender-merge.diff b/modules/nf-core/cellbender/merge/cellbender-merge.diff deleted file mode 100644 index 89782904..00000000 --- a/modules/nf-core/cellbender/merge/cellbender-merge.diff +++ /dev/null @@ -1,27 +0,0 @@ -Changes in component 'nf-core/cellbender/merge' -'modules/nf-core/cellbender/merge/environment.yml' is unchanged -'modules/nf-core/cellbender/merge/meta.yml' is unchanged -Changes in 'cellbender/merge/main.nf': ---- modules/nf-core/cellbender/merge/main.nf -+++ modules/nf-core/cellbender/merge/main.nf -@@ -9,6 +9,7 @@ - - input: - tuple val(meta), path(filtered), path(unfiltered), path(cellbender_h5) -+ val(output_layer) - - output: - tuple val(meta), path("${prefix}.h5ad"), emit: h5ad -@@ -19,7 +20,6 @@ - - script: - prefix = task.ext.prefix ?: "${meta.id}" -- output_layer = task.ext.output_layer ?: "cellbender" - template 'merge.py' - - stub: - -'modules/nf-core/cellbender/merge/tests/main.nf.test.snap' is unchanged -'modules/nf-core/cellbender/merge/tests/main.nf.test' is unchanged -'modules/nf-core/cellbender/merge/templates/merge.py' is unchanged -************************************************************ diff --git a/modules/nf-core/cellbender/merge/main.nf b/modules/nf-core/cellbender/merge/main.nf index 27ea4c99..4b684552 100644 --- a/modules/nf-core/cellbender/merge/main.nf +++ b/modules/nf-core/cellbender/merge/main.nf @@ -9,17 +9,23 @@ process CELLBENDER_MERGE { input: tuple val(meta), path(filtered), path(unfiltered), path(cellbender_h5) - val(output_layer) + val(output_layer_name) output: tuple val(meta), path("${prefix}.h5ad"), emit: h5ad - path "versions.yml" , emit: versions + path "versions.yml" , emit: versions_cellbender, topic: versions when: task.ext.when == null || task.ext.when script: prefix = task.ext.prefix ?: "${meta.id}" + output_layer = output_layer_name ?: "cellbender" + + """ + echo ${output_layer} + """ + template 'merge.py' stub: diff --git a/modules/nf-core/cellbender/merge/meta.yml b/modules/nf-core/cellbender/merge/meta.yml index 4ad77d9e..3ca4f6a3 100644 --- a/modules/nf-core/cellbender/merge/meta.yml +++ b/modules/nf-core/cellbender/merge/meta.yml @@ -1,17 +1,19 @@ name: cellbender_merge -description: Module to use CellBender to remove ambient RNA from single-cell RNA-seq - data +description: Module to use CellBender to remove ambient RNA from single-cell + RNA-seq data keywords: - single-cell - scRNA-seq - ambient RNA removal tools: - cellbender: - description: CellBender is a software package for eliminating technical artifacts - from high-throughput single-cell RNA sequencing (scRNA-seq) data. + description: CellBender is a software package for eliminating technical + artifacts from high-throughput single-cell RNA sequencing (scRNA-seq) + data. documentation: https://cellbender.readthedocs.io/en/latest/ tool_dev_url: https://github.com/broadinstitute/CellBender - licence: ["BSD-3-Clause"] + licence: + - "BSD-3-Clause" identifier: biotools:CellBender input: - - meta: @@ -21,7 +23,8 @@ input: e.g. [ id:'test' ] - filtered: type: file - description: AnnData file containing filtered data (without empty droplets) + description: AnnData file containing filtered data (without empty + droplets) pattern: "*.h5ad" ontologies: [] - unfiltered: @@ -34,6 +37,9 @@ input: description: CellBender h5 file containing ambient RNA estimates pattern: "*.h5" ontologies: [] + - output_layer_name: + type: string + description: The name of the layer to store counts output: h5ad: - - meta: @@ -46,13 +52,21 @@ output: description: AnnData file containing decontaminated counts as `adata.X` pattern: "*.h5ad" ontologies: [] + versions_cellbender: + - versions.yml: + type: file + description: File containing software version + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 +topics: versions: - versions.yml: type: file description: File containing software version pattern: "versions.yml" ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - edam: http://edamontology.org/format_3750 authors: - "@nictru" maintainers: diff --git a/modules/nf-core/cellbender/merge/tests/main.nf.test b/modules/nf-core/cellbender/merge/tests/main.nf.test index f6de930b..f2b47d16 100644 --- a/modules/nf-core/cellbender/merge/tests/main.nf.test +++ b/modules/nf-core/cellbender/merge/tests/main.nf.test @@ -18,6 +18,7 @@ nextflow_process { file(params.modules_testdata_base_path + 'genomics/homo_sapiens/scrnaseq/h5ad/SRR28679759_raw_matrix.h5ad', checkIfExists: true), file("https://raw.githubusercontent.com/nf-core/test-datasets/scdownstream/intermediates/SRR28679759_cellbender.h5", checkIfExists: true) ] + input[1] = '' """ } } @@ -40,6 +41,7 @@ nextflow_process { file(params.modules_testdata_base_path + 'genomics/homo_sapiens/scrnaseq/h5ad/SRR28679759_raw_matrix.h5ad', checkIfExists: true), file("https://raw.githubusercontent.com/nf-core/test-datasets/scdownstream/intermediates/SRR28679759_cellbender.h5", checkIfExists: true) ] + input[1] = '' """ } } diff --git a/modules/nf-core/cellbender/merge/tests/main.nf.test.snap b/modules/nf-core/cellbender/merge/tests/main.nf.test.snap index 40fa0d00..8f9d1cd6 100644 --- a/modules/nf-core/cellbender/merge/tests/main.nf.test.snap +++ b/modules/nf-core/cellbender/merge/tests/main.nf.test.snap @@ -21,16 +21,16 @@ "test.h5ad:md5,d76d209cda94917cc4faf430d288480c" ] ], - "versions": [ + "versions_cellbender": [ "versions.yml:md5,52469695a4396996323548dcd4f659ec" ] } ], + "timestamp": "2026-03-13T12:59:16.360615406", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-24T10:36:28.084259232" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, "test_cellbender_merge - stub": { "content": [ @@ -54,15 +54,15 @@ "test.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ + "versions_cellbender": [ "versions.yml:md5,b5c0e4b30e6148c29e758b0600ac3c7b" ] } ], + "timestamp": "2026-03-13T12:59:28.800015588", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-24T10:40:42.308329653" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } } } \ No newline at end of file diff --git a/modules/nf-core/cellbender/removebackground/main.nf b/modules/nf-core/cellbender/removebackground/main.nf index e2d0b004..0cff86d6 100644 --- a/modules/nf-core/cellbender/removebackground/main.nf +++ b/modules/nf-core/cellbender/removebackground/main.nf @@ -22,46 +22,35 @@ process CELLBENDER_REMOVEBACKGROUND { tuple val(meta), path("${prefix}.pdf") , emit: pdf tuple val(meta), path("${prefix}.log") , emit: log tuple val(meta), path("ckpt.tar.gz") , emit: checkpoint - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('cellbender'), eval('cellbender --version'), emit: versions_cellbender, topic: versions when: - task.ext.when == null || task.ext.when - + task.ext.when == null || task.ext.when script: - prefix = task.ext.prefix ?: "${meta.id}" - args = task.ext.args ?: "" - use_gpu = task.ext.use_gpu ? "--cuda" : "" - """ - TMPDIR=. cellbender remove-background \ - ${args} \ - --cpu-threads ${task.cpus} \ - --estimator-multiple-cpu \ - ${use_gpu} \ - --input ${h5ad} \ - --output ${prefix}.h5 - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - cellbender: \$(cellbender --version) - END_VERSIONS - """ + prefix = task.ext.prefix ?: "${meta.id}" + args = task.ext.args ?: "" + use_gpu = task.ext.use_gpu ? "--cuda" : "" + """ + TMPDIR=. cellbender remove-background \ + ${args} \ + --cpu-threads ${task.cpus} \ + --estimator-multiple-cpu \ + ${use_gpu} \ + --input ${h5ad} \ + --output ${prefix}.h5 + """ stub: - prefix = task.ext.prefix ?: "${meta.id}" - """ - touch "${prefix}.h5" - touch "${prefix}_filtered.h5" - touch "${prefix}_posterior.h5" - touch "${prefix}_cell_barcodes.csv" - touch "${prefix}_metrics.csv" - touch "${prefix}_report.html" - touch "${prefix}.pdf" - touch "${prefix}.log" - echo "" | gzip > ckpt.tar.gz - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - cellbender: \$(cellbender --version) - END_VERSIONS - """ + prefix = task.ext.prefix ?: "${meta.id}" + """ + touch "${prefix}.h5" + touch "${prefix}_filtered.h5" + touch "${prefix}_posterior.h5" + touch "${prefix}_cell_barcodes.csv" + touch "${prefix}_metrics.csv" + touch "${prefix}_report.html" + touch "${prefix}.pdf" + touch "${prefix}.log" + echo "" | gzip > ckpt.tar.gz + """ } diff --git a/modules/nf-core/cellbender/removebackground/meta.yml b/modules/nf-core/cellbender/removebackground/meta.yml index a1f5d1e7..80348782 100644 --- a/modules/nf-core/cellbender/removebackground/meta.yml +++ b/modules/nf-core/cellbender/removebackground/meta.yml @@ -1,17 +1,19 @@ name: cellbender_removebackground -description: Module to use CellBender to estimate ambient RNA from single-cell RNA-seq - data +description: Module to use CellBender to estimate ambient RNA from single-cell + RNA-seq data keywords: - single-cell - scRNA-seq - ambient RNA removal tools: - cellbender: - description: CellBender is a software package for eliminating technical artifacts - from high-throughput single-cell RNA sequencing (scRNA-seq) data. + description: CellBender is a software package for eliminating technical + artifacts from high-throughput single-cell RNA sequencing (scRNA-seq) + data. documentation: https://cellbender.readthedocs.io/en/latest/ tool_dev_url: https://github.com/broadinstitute/CellBender - licence: ["BSD-3-Clause"] + licence: + - "BSD-3-Clause" identifier: biotools:CellBender input: - - meta: @@ -31,8 +33,8 @@ output: description: Groovy Map containing sample information - ${prefix}.h5: type: file - description: Full count matrix as an h5 file, with background RNA removed. - This file contains all the original droplet barcodes. + description: Full count matrix as an h5 file, with background RNA + removed. This file contains all the original droplet barcodes. pattern: "*.h5" ontologies: [] filtered_h5: @@ -67,7 +69,7 @@ output: but is included as a separate output for convenient use in certain downstream applications. pattern: "*.csv" ontologies: - - edam: http://edamontology.org/format_3752 # CSV + - edam: http://edamontology.org/format_3752 #CSV metrics: - - meta: type: map @@ -79,7 +81,7 @@ output: when using CellBender as part of a large-scale automated pipeline. pattern: "*.csv" ontologies: - - edam: http://edamontology.org/format_3752 # CSV + - edam: http://edamontology.org/format_3752 #CSV report: - - meta: type: map @@ -96,8 +98,8 @@ output: description: Groovy Map containing sample information - ${prefix}.pdf: type: file - description: PDF file that provides a standard graphical summary of the inference - procedure. + description: PDF file that provides a standard graphical summary of the + inference procedure. pattern: "*.pdf" ontologies: [] log: @@ -115,17 +117,31 @@ output: description: Groovy Map containing sample information - ckpt.tar.gz: type: file - description: Checkpoint file which contains the trained model and the full - posterior. + description: Checkpoint file which contains the trained model and the + full posterior. pattern: "*.ckpt" ontologies: [] + versions_cellbender: + - - ${task.process}: + type: string + description: The name of the process + - cellbender: + type: string + description: The name of the tool + - cellbender --version: + type: eval + description: The expression to obtain the version of the tool +topics: versions: - - versions.yml: - type: file - description: File containing software version - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The name of the process + - cellbender: + type: string + description: The name of the tool + - cellbender --version: + type: eval + description: The expression to obtain the version of the tool authors: - "@nictru" maintainers: diff --git a/modules/nf-core/cellbender/removebackground/tests/gpu.nf.test b/modules/nf-core/cellbender/removebackground/tests/gpu.nf.test index f9e158a9..398ce227 100644 --- a/modules/nf-core/cellbender/removebackground/tests/gpu.nf.test +++ b/modules/nf-core/cellbender/removebackground/tests/gpu.nf.test @@ -25,7 +25,7 @@ nextflow_process { assertAll( {assert process.success}, {assert snapshot( - process.out.versions, + process.out.findAll { key, val -> key.startsWith('versions') }, process.out.h5.collect{file(it[1]).name}, process.out.filtered_h5.collect{file(it[1]).name}, process.out.posterior_h5.collect{file(it[1]).name}, diff --git a/modules/nf-core/cellbender/removebackground/tests/gpu.nf.test.snap b/modules/nf-core/cellbender/removebackground/tests/gpu.nf.test.snap index b9990a90..081c6a90 100644 --- a/modules/nf-core/cellbender/removebackground/tests/gpu.nf.test.snap +++ b/modules/nf-core/cellbender/removebackground/tests/gpu.nf.test.snap @@ -1,9 +1,15 @@ { "test_cellbender_removebackground": { "content": [ - [ - "versions.yml:md5,53e48cca1f71828723220055334da62d" - ], + { + "versions_cellbender": [ + [ + "CELLBENDER_REMOVEBACKGROUND", + "cellbender", + "0.3.2" + ] + ] + }, [ "test.h5" ], @@ -29,11 +35,11 @@ "test.log" ] ], + "timestamp": "2026-03-13T15:28:36.521030974", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-24T11:25:08.924988231" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, "test_cellbender_removebackground - stub": { "content": [ @@ -111,7 +117,11 @@ ] ], "9": [ - "versions.yml:md5,53e48cca1f71828723220055334da62d" + [ + "CELLBENDER_REMOVEBACKGROUND", + "cellbender", + "0.3.2" + ] ], "barcodes": [ [ @@ -185,15 +195,19 @@ "test_report.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,53e48cca1f71828723220055334da62d" + "versions_cellbender": [ + [ + "CELLBENDER_REMOVEBACKGROUND", + "cellbender", + "0.3.2" + ] ] } ], + "timestamp": "2026-03-12T14:54:31.232109215", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-11T10:58:34.420027935" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } } } \ No newline at end of file diff --git a/modules/nf-core/cellbender/removebackground/tests/main.nf.test b/modules/nf-core/cellbender/removebackground/tests/main.nf.test index 9941c169..c1213509 100644 --- a/modules/nf-core/cellbender/removebackground/tests/main.nf.test +++ b/modules/nf-core/cellbender/removebackground/tests/main.nf.test @@ -24,7 +24,7 @@ nextflow_process { assertAll( {assert process.success}, {assert snapshot( - process.out.versions, + process.out.findAll { key, val -> key.startsWith('versions') }, process.out.h5.collect{file(it[1]).name}, process.out.filtered_h5.collect{file(it[1]).name}, process.out.posterior_h5.collect{file(it[1]).name}, diff --git a/modules/nf-core/cellbender/removebackground/tests/main.nf.test.snap b/modules/nf-core/cellbender/removebackground/tests/main.nf.test.snap index b9990a90..65d63698 100644 --- a/modules/nf-core/cellbender/removebackground/tests/main.nf.test.snap +++ b/modules/nf-core/cellbender/removebackground/tests/main.nf.test.snap @@ -1,9 +1,15 @@ { "test_cellbender_removebackground": { "content": [ - [ - "versions.yml:md5,53e48cca1f71828723220055334da62d" - ], + { + "versions_cellbender": [ + [ + "CELLBENDER_REMOVEBACKGROUND", + "cellbender", + "0.3.2" + ] + ] + }, [ "test.h5" ], @@ -29,11 +35,11 @@ "test.log" ] ], + "timestamp": "2026-03-13T15:30:56.645899744", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-24T11:25:08.924988231" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, "test_cellbender_removebackground - stub": { "content": [ @@ -111,7 +117,11 @@ ] ], "9": [ - "versions.yml:md5,53e48cca1f71828723220055334da62d" + [ + "CELLBENDER_REMOVEBACKGROUND", + "cellbender", + "0.3.2" + ] ], "barcodes": [ [ @@ -185,15 +195,19 @@ "test_report.html:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,53e48cca1f71828723220055334da62d" + "versions_cellbender": [ + [ + "CELLBENDER_REMOVEBACKGROUND", + "cellbender", + "0.3.2" + ] ] } ], + "timestamp": "2026-03-12T14:56:46.093356987", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-11T10:58:34.420027935" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } } } \ 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 00000000..76190304 --- /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_arm64-bd-40bf3b435e89dc22_1.txt b/modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt new file mode 100644 index 00000000..a58231a0 --- /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/main.nf b/modules/nf-core/multiqc/main.nf index 3b0e975b..5376aea1 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -1,25 +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://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/34/34e733a9ae16a27e80fe00f863ea1479c96416017f24a907996126283e7ecd4d/data' : - 'community.wave.seqera.io/library/multiqc:1.33--ee7739d47738383b' }" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/34/34e733a9ae16a27e80fe00f863ea1479c96416017f24a907996126283e7ecd4d/data' + : 'community.wave.seqera.io/library/multiqc:1.33--ee7739d47738383b'}" 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 "*.html" , emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - tuple val("${task.process}"), val('multiqc'), eval('multiqc --version | sed "s/.* //g"'), 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 @@ -27,8 +23,7 @@ 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}" : '' @@ -38,7 +33,6 @@ process MULTIQC { ${args} \\ ${config} \\ ${prefix} \\ - ${extra_config} \\ ${logo} \\ ${replace} \\ ${samples} \\ @@ -50,6 +44,7 @@ process MULTIQC { mkdir multiqc_data touch multiqc_data/.stub mkdir multiqc_plots + touch multiqc_plots/.stub touch multiqc_report.html """ } diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index f790cab0..57cf43ca 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,67 +12,81 @@ 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: - - "*.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: ".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: Plots created by MultiQC - pattern: "*_data" + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + ontologies: + - edam: http://edamontology.org/format_3750 + - 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 + - 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: + - - 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 @@ -95,25 +109,25 @@ maintainers: - "@jfy133" containers: conda: - linux_amd64: - lock_file: https://wave.seqera.io/v1alpha1/builds/bd-d58f60e4deb769bf_1/condalock - linux_arm64: - lock_file: https://wave.seqera.io/v1alpha1/builds/bd-193776baee4194db_1/condalock + linux/amd64: + lock_file: modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c1f4a7982b743963_1.txt + linux/arm64: + lock_file: modules/nf-core/multiqc/.conda-lock/linux_arm64-bd-40bf3b435e89dc22_1.txt docker: - linux_amd64: - build_id: bd-d58f60e4deb769bf_1 - name: community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf - scanId: sc-d76ac07493e940b4_6 - linux_arm64: - build_id: bd-193776baee4194db_1 - name: community.wave.seqera.io/library/multiqc:1.32--193776baee4194db - scanId: sc-86caded0bff8246e_3 + linux/amd64: + name: community.wave.seqera.io/library/multiqc:1.33--c1f4a7982b743963 + build_id: bd-c1f4a7982b743963_1 + scan_id: sc-b7b7f470b2a16699_1 + linux/arm64: + name: community.wave.seqera.io/library/multiqc:1.33--40bf3b435e89dc22 + build_id: bd-40bf3b435e89dc22_1 + scan_id: sc-0e2108a0e7368d2f_1 singularity: - linux_amd64: - build_id: bd-e649ffa094d1ef4a_1 - name: oras://community.wave.seqera.io/library/multiqc:1.32--e649ffa094d1ef4a - https: https://community.wave.seqera.io/v2/library/multiqc/blobs/sha256:8c6c120d559d7ee04c7442b61ad7cf5a9e8970be5feefb37d68eeaa60c1034eb - linux_arm64: - build_id: bd-aee0064f5570ef22_1 - name: oras://community.wave.seqera.io/library/multiqc:1.32--aee0064f5570ef22 - https: https://community.wave.seqera.io/v2/library/multiqc/blobs/sha256:f02c59ebf6e9a00aa954ee8188a4ecc5c743e18f40b9215a242f67606a00f9cf + linux/amd64: + name: oras://community.wave.seqera.io/library/multiqc:1.33--9b3473b1c4bb0493 + build_id: bd-9b3473b1c4bb0493_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c4/c4e6d9f669e1a99b53c7dc5cdd6b8e7fd6654032c755bb783cc9849e8203f4d1/data + linux/arm64: + name: oras://community.wave.seqera.io/library/multiqc:1.33--e1ef2065eb21b530 + build_id: bd-e1ef2065eb21b530_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/2a/2acce766e3efb280fa43acdbe85305ea6496ddadbcaa2d806ac4985dfe4686ce/data diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test index 06a6cda4..4cbdb95d 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -15,25 +15,41 @@ 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.findAll { key, val -> key.startsWith("versions")}).match() } - ) + 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") { @@ -42,24 +58,41 @@ 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] ==~ ".*/custom_prefix.html" }, - { assert process.out.data[0] ==~ ".*/custom_prefix_data" } - ) + 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]") { @@ -67,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.findAll { key, val -> key.startsWith("versions")}).match() } - ) + 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() } } @@ -94,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.findAll { key, val -> key.startsWith("versions")} ).match() } + { 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 d72d35b7..3bfc524f 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -1,7 +1,176 @@ { + "sarscov2 single-end [fastqc] [multiple configs]": { + "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.33" + ] + ] + } + ], + "timestamp": "2026-03-17T16:15:42.577775492", + "meta": { + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } + }, "sarscov2 single-end [fastqc]": { "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": "multiqc_report.html", "versions": [ [ "MULTIQC", @@ -11,38 +180,230 @@ ] } ], + "timestamp": "2026-03-17T16:21:17.072841555", "meta": { - "nf-test": "0.9.3", - "nextflow": "25.10.2" - }, - "timestamp": "2025-12-09T10:10:43.020315838" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, "sarscov2 single-end [fastqc] - stub": { "content": [ - [ - "multiqc_report.html", - "multiqc_data", - "multiqc_plots", - { - "versions": [ + { + "data": [ + [ + { + "id": "FASTQC" + }, + [ + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "plots": [ + [ + { + "id": "FASTQC" + }, [ - "MULTIQC", - "multiqc", - "1.33" + ".stub:md5,d41d8cd98f00b204e9800998ecf8427e" ] ] - } - ] + ], + "report": [ + [ + { + "id": "FASTQC" + }, + "multiqc_report.html:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ], + "timestamp": "2026-02-26T15:14:39.789193051", "meta": { - "nf-test": "0.9.3", - "nextflow": "25.10.2" - }, - "timestamp": "2025-12-09T10:11:14.131950776" + "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.33" + ] + ] + } + ], + "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", @@ -52,10 +413,10 @@ ] } ], + "timestamp": "2026-03-17T16:15:18.189023981", "meta": { - "nf-test": "0.9.3", - "nextflow": "25.10.2" - }, - "timestamp": "2025-12-09T10:11:07.15692209" + "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 c537a6a3..374dfef2 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/untar/main.nf b/modules/nf-core/untar/main.nf index e712ebe6..b9c324da 100644 --- a/modules/nf-core/untar/main.nf +++ b/modules/nf-core/untar/main.nf @@ -12,7 +12,7 @@ process UNTAR { output: tuple val(meta), path("${prefix}"), emit: untar - path "versions.yml", emit: versions + tuple val("${task.process}"), val('untar'), eval('tar --version 2>&1 | head -1 | sed "s/tar (GNU tar) //; s/ Copyright.*//"'), emit: versions_untar, topic: versions when: task.ext.when == null || task.ext.when @@ -43,10 +43,6 @@ process UNTAR { ${args2} fi - cat <<-END_VERSIONS > versions.yml - "${task.process}": - untar: \$(echo \$(tar --version 2>&1) | sed 's/^.*(GNU tar) //; s/ Copyright.*\$//') - END_VERSIONS """ stub: @@ -75,10 +71,5 @@ process UNTAR { fi done fi - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - untar: \$(echo \$(tar --version 2>&1) | sed 's/^.*(GNU tar) //; s/ Copyright.*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/untar/meta.yml b/modules/nf-core/untar/meta.yml index 1603e382..571d8078 100644 --- a/modules/nf-core/untar/meta.yml +++ b/modules/nf-core/untar/meta.yml @@ -38,13 +38,29 @@ output: Groovy Map containing sample information e.g. [ id:'test', single_end:false ] pattern: "*/" + versions_untar: + - - ${task.process}: + type: string + description: The name of the process + - untar: + type: string + description: The name of the tool + - tar --version 2>&1 | head -1 | sed "s/tar (GNU tar) //; s/ Copyright.*//": + 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 name of the process + - untar: + type: string + description: The name of the tool + - tar --version 2>&1 | head -1 | sed "s/tar (GNU tar) //; s/ Copyright.*//": + type: eval + description: The expression to obtain the version of the tool + authors: - "@joseespinosa" - "@drpatelh" diff --git a/modules/nf-core/untar/tests/main.nf.test b/modules/nf-core/untar/tests/main.nf.test index c957517a..fde8db16 100644 --- a/modules/nf-core/untar/tests/main.nf.test +++ b/modules/nf-core/untar/tests/main.nf.test @@ -20,7 +20,10 @@ nextflow_process { then { assertAll ( { assert process.success }, - { assert snapshot(process.out).match() }, + { assert snapshot( + process.out.untar, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() }, ) } } @@ -38,7 +41,10 @@ nextflow_process { then { assertAll ( { assert process.success }, - { assert snapshot(process.out).match() }, + { assert snapshot( + process.out.untar, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() }, ) } } @@ -58,7 +64,10 @@ nextflow_process { then { assertAll ( { assert process.success }, - { assert snapshot(process.out).match() }, + { assert snapshot( + process.out.untar, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() }, ) } } @@ -78,7 +87,10 @@ nextflow_process { then { assertAll ( { assert process.success }, - { assert snapshot(process.out).match() }, + { assert snapshot( + process.out.untar, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() }, ) } } diff --git a/modules/nf-core/untar/tests/main.nf.test.snap b/modules/nf-core/untar/tests/main.nf.test.snap index ceb91b79..51a414dd 100644 --- a/modules/nf-core/untar/tests/main.nf.test.snap +++ b/modules/nf-core/untar/tests/main.nf.test.snap @@ -1,158 +1,118 @@ { "test_untar_onlyfiles": { "content": [ - { - "0": [ + [ + [ + [ + + ], [ - [ - - ], - [ - "hello.txt:md5,e59ff97941044f85df5297e1c302d260" - ] + "hello.txt:md5,e59ff97941044f85df5297e1c302d260" ] - ], - "1": [ - "versions.yml:md5,6063247258c56fd271d076bb04dd7536" - ], - "untar": [ + ] + ], + { + "versions_untar": [ [ - [ - - ], - [ - "hello.txt:md5,e59ff97941044f85df5297e1c302d260" - ] + "UNTAR", + "untar", + "1.34" ] - ], - "versions": [ - "versions.yml:md5,6063247258c56fd271d076bb04dd7536" ] } ], "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.3" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2024-07-10T12:04:28.231047" + "timestamp": "2026-01-28T17:49:32.000491" }, "test_untar_onlyfiles - stub": { "content": [ - { - "0": [ + [ + [ + [ + + ], [ - [ - - ], - [ - "hello.txt:md5,d41d8cd98f00b204e9800998ecf8427e" - ] + "hello.txt:md5,d41d8cd98f00b204e9800998ecf8427e" ] - ], - "1": [ - "versions.yml:md5,6063247258c56fd271d076bb04dd7536" - ], - "untar": [ + ] + ], + { + "versions_untar": [ [ - [ - - ], - [ - "hello.txt:md5,d41d8cd98f00b204e9800998ecf8427e" - ] + "UNTAR", + "untar", + "1.34" ] - ], - "versions": [ - "versions.yml:md5,6063247258c56fd271d076bb04dd7536" ] } ], "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.3" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2024-07-10T12:04:45.773103" + "timestamp": "2026-01-28T17:49:58.812479" }, "test_untar - stub": { "content": [ - { - "0": [ + [ + [ + [ + + ], [ - [ - - ], - [ - "hash.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", - "opts.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", - "taxo.k2d:md5,d41d8cd98f00b204e9800998ecf8427e" - ] + "hash.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", + "opts.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", + "taxo.k2d:md5,d41d8cd98f00b204e9800998ecf8427e" ] - ], - "1": [ - "versions.yml:md5,6063247258c56fd271d076bb04dd7536" - ], - "untar": [ + ] + ], + { + "versions_untar": [ [ - [ - - ], - [ - "hash.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", - "opts.k2d:md5,d41d8cd98f00b204e9800998ecf8427e", - "taxo.k2d:md5,d41d8cd98f00b204e9800998ecf8427e" - ] + "UNTAR", + "untar", + "1.34" ] - ], - "versions": [ - "versions.yml:md5,6063247258c56fd271d076bb04dd7536" ] } ], "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.3" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2024-07-10T12:04:36.777441" + "timestamp": "2026-01-28T17:49:48.119456" }, "test_untar": { "content": [ - { - "0": [ + [ + [ + [ + + ], [ - [ - - ], - [ - "hash.k2d:md5,8b8598468f54a7087c203ad0190555d9", - "opts.k2d:md5,a033d00cf6759407010b21700938f543", - "taxo.k2d:md5,094d5891cdccf2f1468088855c214b2c" - ] + "hash.k2d:md5,8b8598468f54a7087c203ad0190555d9", + "opts.k2d:md5,a033d00cf6759407010b21700938f543", + "taxo.k2d:md5,094d5891cdccf2f1468088855c214b2c" ] - ], - "1": [ - "versions.yml:md5,6063247258c56fd271d076bb04dd7536" - ], - "untar": [ + ] + ], + { + "versions_untar": [ [ - [ - - ], - [ - "hash.k2d:md5,8b8598468f54a7087c203ad0190555d9", - "opts.k2d:md5,a033d00cf6759407010b21700938f543", - "taxo.k2d:md5,094d5891cdccf2f1468088855c214b2c" - ] + "UNTAR", + "untar", + "1.34" ] - ], - "versions": [ - "versions.yml:md5,6063247258c56fd271d076bb04dd7536" ] } ], "meta": { - "nf-test": "0.8.4", - "nextflow": "24.04.3" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2024-07-10T12:04:19.377674" + "timestamp": "2026-01-28T17:49:17.252494" } } \ No newline at end of file diff --git a/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/main.nf b/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/main.nf index c7a019f4..997d5d7d 100644 --- a/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/main.nf +++ b/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/main.nf @@ -10,16 +10,10 @@ workflow H5AD_REMOVEBACKGROUND_BARCODES_CELLBENDER_ANNDATA { ch_unfiltered // channel: [mandatory] meta, h5ad main: - ch_versions = channel.empty() - CELLBENDER_REMOVEBACKGROUND(ch_unfiltered) - ch_versions = ch_versions.mix(CELLBENDER_REMOVEBACKGROUND.out.versions) ANNDATA_BARCODES(ch_unfiltered.join(CELLBENDER_REMOVEBACKGROUND.out.barcodes)) - ch_versions = ch_versions.mix(ANNDATA_BARCODES.out.versions) emit: h5ad = ANNDATA_BARCODES.out.h5ad // channel: [ val(meta), path(h5ad) ] - - versions = ch_versions // channel: [ path(versions.yml) ] } diff --git a/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/tests/main.nf.test b/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/tests/main.nf.test index 066aa0ce..350ccf64 100644 --- a/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/tests/main.nf.test +++ b/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/tests/main.nf.test @@ -25,8 +25,7 @@ nextflow_workflow { then { assertAll( { assert workflow.success}, - { assert file(workflow.out.h5ad.get(0).get(1)).exists()}, - { assert snapshot(workflow.out.versions).match()} + { assert file(workflow.out.h5ad.get(0).get(1)).exists()} ) } } diff --git a/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/tests/main.nf.test.snap b/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/tests/main.nf.test.snap index 3069c17f..bc69c04d 100644 --- a/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/tests/main.nf.test.snap +++ b/subworkflows/nf-core/h5ad_removebackground_barcodes_cellbender_anndata/tests/main.nf.test.snap @@ -1,16 +1,15 @@ { "h5ad - h5ad_removebackground_barcodes_cellbender_anndata": { "content": [ - [ - "versions.yml:md5,3b268371ecd09ac624398c004f5e279d", - "versions.yml:md5,d18fac1840ecbc7e6ee830d26e83ac91" - ] + { + + } ], + "timestamp": "2026-03-13T16:10:00.940145898", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-11T13:36:03.576334046" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } }, "h5ad - h5ad_removebackground_barcodes_cellbender_anndata - stub": { "content": [ @@ -23,10 +22,6 @@ "test.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "1": [ - "versions.yml:md5,3b268371ecd09ac624398c004f5e279d", - "versions.yml:md5,44799738472a56b1d09e916215b2a006" - ], "h5ad": [ [ { @@ -34,17 +29,13 @@ }, "test.h5ad:md5,d41d8cd98f00b204e9800998ecf8427e" ] - ], - "versions": [ - "versions.yml:md5,3b268371ecd09ac624398c004f5e279d", - "versions.yml:md5,44799738472a56b1d09e916215b2a006" ] } ], + "timestamp": "2026-03-12T15:06:01.974773939", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.3" - }, - "timestamp": "2025-06-11T13:36:15.057527557" + "nf-test": "0.9.4", + "nextflow": "25.10.4" + } } } \ No newline at end of file From 38ab8d8632e5d32caff76c6dfb3af2840f602b99 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Mon, 30 Mar 2026 08:16:46 +0200 Subject: [PATCH 38/46] Adjust for updated modules --- subworkflows/local/ambient_correction/main.nf | 2 -- subworkflows/local/quality_control/main.nf | 1 - subworkflows/local/scimilarity/main.nf | 1 - workflows/scdownstream.nf | 12 +++++------- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/subworkflows/local/ambient_correction/main.nf b/subworkflows/local/ambient_correction/main.nf index ea191413..ef879b05 100644 --- a/subworkflows/local/ambient_correction/main.nf +++ b/subworkflows/local/ambient_correction/main.nf @@ -69,7 +69,6 @@ workflow AMBIENT_CORRECTION { CELLBENDER_REMOVEBACKGROUND ( ch_multi.input .map { meta, _filtered, unfiltered -> [meta, unfiltered] }) - ch_versions = ch_versions.mix(CELLBENDER_REMOVEBACKGROUND.out.versions) CELLBENDER_MERGE ( ch_multi.input @@ -86,7 +85,6 @@ workflow AMBIENT_CORRECTION { ch_multi.output_layer ) ch_h5ad = ch_h5ad.mix(CELLBENDER_MERGE.out.h5ad) - ch_versions = ch_versions.mix(CELLBENDER_MERGE.out.versions) } else if (method == 'soupx') { SOUPX ( diff --git a/subworkflows/local/quality_control/main.nf b/subworkflows/local/quality_control/main.nf index 2d7c812b..31812988 100644 --- a/subworkflows/local/quality_control/main.nf +++ b/subworkflows/local/quality_control/main.nf @@ -75,7 +75,6 @@ workflow QUALITY_CONTROL { [meta, unfiltered] } ) - ch_versions = ch_versions.mix(EMPTY_DROPLET_REMOVAL.out.versions) ch_complete = ch_complete.mix( ch_needs_filtering diff --git a/subworkflows/local/scimilarity/main.nf b/subworkflows/local/scimilarity/main.nf index 252dee99..25ed98ca 100644 --- a/subworkflows/local/scimilarity/main.nf +++ b/subworkflows/local/scimilarity/main.nf @@ -28,7 +28,6 @@ workflow SCIMILARITY { UNTAR ( ch_scimilarity_model ) - ch_versions = ch_versions.mix(UNTAR.out.versions) ch_scimilarity_model = UNTAR.out.untar } diff --git a/workflows/scdownstream.nf b/workflows/scdownstream.nf index 15f708e4..72d908e9 100644 --- a/workflows/scdownstream.nf +++ b/workflows/scdownstream.nf @@ -353,14 +353,12 @@ workflow SCDOWNSTREAM { ) MULTIQC ( - ch_multiqc_files.collect(), - ch_multiqc_config.toList(), - ch_multiqc_custom_config.toList(), - ch_multiqc_logo.toList(), - [], - [], + ch_multiqc_files.collect() + .combine(ch_multiqc_config.mix(ch_multiqc_custom_config).collect().ifEmpty([])) + .combine(ch_multiqc_logo.collect().ifEmpty([])) + .map { files, configs, logos -> [[id: 'multiqc'], files, configs, logos, [], []] }, ) - ch_multiqc_report = MULTIQC.out.report.toList() + ch_multiqc_report = MULTIQC.out.report.map { _meta, report -> report }.toList() emit: multiqc_report = ch_multiqc_report // channel: [ path(multiqc_report.html) ] From 7c2b51c952a61c72fac83a3a371cdf66ae66b3ca Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Mon, 30 Mar 2026 09:55:17 +0200 Subject: [PATCH 39/46] Align tests with module updates --- .../tests/main.nf.test.snap | 10 +- .../local/scimilarity/tests/main.nf.test.snap | 14 +- tests/default.nf.test.snap | 13 +- tests/main_pipeline_build.nf.test.snap | 13 +- tests/main_pipeline_extend.nf.test.snap | 149 +++++++++++++++++- tests/main_pipeline_qc.nf.test.snap | 13 +- ...in_pipeline_reference_mapping.nf.test.snap | 104 +++++++++++- tests/main_pipeline_sub.nf.test.snap | 12 +- workflows/scdownstream.nf | 20 +-- 9 files changed, 296 insertions(+), 52 deletions(-) diff --git a/subworkflows/local/ambient_correction/tests/main.nf.test.snap b/subworkflows/local/ambient_correction/tests/main.nf.test.snap index 2d051d45..9e8efbcc 100644 --- a/subworkflows/local/ambient_correction/tests/main.nf.test.snap +++ b/subworkflows/local/ambient_correction/tests/main.nf.test.snap @@ -107,8 +107,7 @@ "Should run with 'cellbender' ambient correction to 'X'": { "content": [ [ - "versions.yml:md5,1d70371b0f0ca5e50f7ba70335f8946f", - "versions.yml:md5,e6e98e83cbc9a2924c66e901445bbc4f" + ], { "n_obs": 7373, @@ -145,7 +144,7 @@ ] } ], - "timestamp": "2026-03-29T11:32:46.973630904", + "timestamp": "2026-03-30T08:50:28.315741473", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -307,8 +306,7 @@ "Should run with 'cellbender' ambient correction": { "content": [ [ - "versions.yml:md5,1d70371b0f0ca5e50f7ba70335f8946f", - "versions.yml:md5,e6e98e83cbc9a2924c66e901445bbc4f" + ], { "n_obs": 7373, @@ -345,7 +343,7 @@ ] } ], - "timestamp": "2026-03-29T11:27:11.134006387", + "timestamp": "2026-03-30T08:42:11.218749814", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" diff --git a/subworkflows/local/scimilarity/tests/main.nf.test.snap b/subworkflows/local/scimilarity/tests/main.nf.test.snap index 9a4e2cbd..afd1cab9 100644 --- a/subworkflows/local/scimilarity/tests/main.nf.test.snap +++ b/subworkflows/local/scimilarity/tests/main.nf.test.snap @@ -17,7 +17,6 @@ "X_test.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "3": [ - "versions.yml:md5,48890903e09c762a5003d3630680f8f1", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ], @@ -36,17 +35,16 @@ "X_test.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,48890903e09c762a5003d3630680f8f1", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e", "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ] } ], + "timestamp": "2026-03-30T08:23:19.253074422", "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" - }, - "timestamp": "2026-01-10T23:00:05.637283949" + "nf-test": "0.9.4", + "nextflow": "25.10.2" + } }, "Should run without failures - stub - uncompressed model": { "content": [ @@ -89,10 +87,10 @@ ] } ], + "timestamp": "2026-01-10T23:01:38.877123044", "meta": { "nf-test": "0.9.2", "nextflow": "25.04.6" - }, - "timestamp": "2026-01-10T23:01:38.877123044" + } } } \ No newline at end of file diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 14145abe..38da659d 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -259,6 +259,13 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -279,10 +286,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T18:46:54.039339", + "timestamp": "2026-03-30T09:25:33.88487868", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index 489ef856..e0b24d08 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -272,6 +272,13 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -292,10 +299,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T18:49:17.189049", + "timestamp": "2026-03-30T09:28:16.222812249", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_extend.nf.test.snap b/tests/main_pipeline_extend.nf.test.snap index 61ab933d..fbec78bc 100644 --- a/tests/main_pipeline_extend.nf.test.snap +++ b/tests/main_pipeline_extend.nf.test.snap @@ -2,6 +2,25 @@ "Should perform scvi reference extension": { "content": [ { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "ADATA_MERGEEMBEDDINGS": { + "anndata": "0.12.10", + "python": "3.13.12" + }, + "ADATA_TORDS": { + "anndataR": "1.0.2" + }, "ADATA_UNIFY": { "anndata": "0.12.10", "numpy": "2.3.5", @@ -20,6 +39,23 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, + "CELLTYPES_CELLTYPIST": { + "python": "3.12.8", + "pandas": "2.2.3", + "scanpy": "1.10.4", + "celltypist": "1.6.3" + }, + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + }, + "COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + }, "DOUBLET_REMOVAL": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -27,6 +63,21 @@ "python": "3.13.12", "upsetplot": "0.9.0" }, + "ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "FINALIZE_QC_ANNDATAS": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "GET_DEDOUBLETED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" @@ -39,19 +90,53 @@ "python": "3.13.0", "anndata": "0.10.9" }, + "LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "QC_FILTERED": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, "QC_RAW": { "matplotlib": "3.10.8", "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_CELLCYCLE": { + "python": "3.13.12", + "scanpy": "1.12" + }, "SCANPY_FILTER": { "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, "SCANPY_SCRUBLET": { "python": "3.12.11", "scanpy": "1.11.2" }, + "SCVITOOLS_SCVI": { + "scvi": "1.3.3" + }, + "UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, "UPSET_GENES": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -60,27 +145,79 @@ }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - } + }, + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" }, [ + "celltypes", + "celltypes/singler", + "celltypes/singler/SRR28679759_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679759_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679759_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679759_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679759_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_predictions.csv", + "cluster_dimred", + "cluster_dimred/scvi", + "cluster_dimred/scvi/entropy", + "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", + "cluster_dimred/scvi/leiden", + "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", + "cluster_dimred/scvi/umap", "combine", + "combine/integrate", + "combine/integrate/scvi", + "combine/integrate/scvi/scvi_model", + "combine/integrate/scvi/scvi_model/model.pt", "combine/merge", + "finalized", + "finalized/merged.h5ad", + "finalized/merged.rds", + "finalized/merged_metadata.csv", + "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_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", + "multiqc/multiqc_report.html", + "per_group", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "quality_control", "quality_control/qc_filtered", "quality_control/qc_filtered/SRR28679759_preprocessed_total_counts_vs_n_genes_by_counts.png", "quality_control/qc_raw", - "quality_control/qc_raw/SRR28679759_raw_total_counts_vs_n_genes_by_counts.png" + "quality_control/qc_raw/SRR28679759_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/sizes", + "quality_control/sizes/sizes.tsv" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T17:32:04.88827", + "timestamp": "2026-03-30T09:22:34.702307282", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index ae865061..64c1afec 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -149,6 +149,13 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", @@ -168,10 +175,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T18:13:02.828075", + "timestamp": "2026-03-30T09:00:07.268240826", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 0717be16..3ebe4816 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -2,6 +2,21 @@ "Should perform scvi reference mapping": { "content": [ { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "ADATA_TORDS": { + "anndataR": "1.0.2" + }, "ADATA_UNIFY": { "anndata": "0.12.10", "numpy": "2.3.5", @@ -44,6 +59,17 @@ "python": "3.13.12", "upsetplot": "0.9.0" }, + "ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "FINALIZE_QC_ANNDATAS": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, "GET_DEDOUBLETED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" @@ -60,6 +86,14 @@ "python": "3.13.0", "anndata": "0.10.9" }, + "LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + }, "QC_FILTERED": { "matplotlib": "3.10.8", "python": "3.13.12", @@ -78,10 +112,31 @@ "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_HVGS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, "SCANPY_SCRUBLET": { "python": "3.12.11", "scanpy": "1.11.2" }, + "SCVITOOLS_SCVI": { + "scvi": "1.3.3" + }, + "UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, "UPSET_GENES": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -90,7 +145,10 @@ }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - } + }, + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" }, [ "celltypes", @@ -104,8 +162,44 @@ "celltypes/singler/SRR28679759_singler_immune_direct_distribution.pdf", "celltypes/singler/SRR28679759_singler_immune_direct_heatmap.pdf", "celltypes/singler/SRR28679759_singler_predictions.csv", + "cluster_dimred", + "cluster_dimred/scvi", + "cluster_dimred/scvi/entropy", + "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", + "cluster_dimred/scvi/leiden", + "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", + "cluster_dimred/scvi/umap", "combine", + "combine/integrate", + "combine/integrate/scvi", + "combine/integrate/scvi/scvi_model", + "combine/integrate/scvi/scvi_model/model.pt", "combine/merge", + "finalized", + "finalized/merged.h5ad", + "finalized/merged.rds", + "finalized/merged_metadata.csv", + "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_sizes.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/sizes.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/sizes.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/sizes.svg", + "multiqc/multiqc_report.html", + "per_group", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "quality_control", @@ -117,13 +211,13 @@ "quality_control/sizes/sizes.tsv" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T17:34:25.000756", + "timestamp": "2026-03-30T09:01:17.509977693", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_sub.nf.test.snap b/tests/main_pipeline_sub.nf.test.snap index 45e88e8f..4f1a404d 100644 --- a/tests/main_pipeline_sub.nf.test.snap +++ b/tests/main_pipeline_sub.nf.test.snap @@ -1,7 +1,7 @@ { "Should be able to perform subclustering": { "content": [ - 289, + 291, { "ADATA_EXTEND": { "anndata": "0.12.10", @@ -183,6 +183,8 @@ "per_group/condition:combat-SRR28679756-0.5_leiden:7/characteristic_genes", "per_group/condition:combat-SRR28679756-0.5_leiden:8", "per_group/condition:combat-SRR28679756-0.5_leiden:8/characteristic_genes", + "per_group/condition:combat-SRR28679756-0.5_leiden:9", + "per_group/condition:combat-SRR28679756-0.5_leiden:9/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:0", "per_group/condition:combat-SRR28679756-1.0_leiden:0/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:1", @@ -197,6 +199,8 @@ "per_group/condition:combat-SRR28679756-1.0_leiden:13/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:14", "per_group/condition:combat-SRR28679756-1.0_leiden:14/characteristic_genes", + "per_group/condition:combat-SRR28679756-1.0_leiden:15", + "per_group/condition:combat-SRR28679756-1.0_leiden:15/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:2", "per_group/condition:combat-SRR28679756-1.0_leiden:2/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:3", @@ -589,10 +593,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-29T18:37:42.198507", + "timestamp": "2026-03-30T08:57:20.252506257", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/workflows/scdownstream.nf b/workflows/scdownstream.nf index 72d908e9..2fe98b5c 100644 --- a/workflows/scdownstream.nf +++ b/workflows/scdownstream.nf @@ -320,16 +320,9 @@ workflow SCDOWNSTREAM { // // MODULE: MultiQC // - ch_multiqc_config = channel.fromPath( - "${projectDir}/assets/multiqc_config.yml", - checkIfExists: true - ) - ch_multiqc_custom_config = multiqc_config - ? channel.fromPath(multiqc_config, checkIfExists: true) - : channel.empty() - ch_multiqc_logo = multiqc_logo - ? channel.fromPath(multiqc_logo, checkIfExists: true) - : channel.empty() + def mqc_config = file("${projectDir}/assets/multiqc_config.yml", checkIfExists: true) + def mqc_configs = multiqc_config ? [mqc_config, file(multiqc_config, checkIfExists: true)] : [mqc_config] + def mqc_logo = multiqc_logo ? file(multiqc_logo, checkIfExists: true) : [] summary_params = paramsSummaryMap( workflow, @@ -353,10 +346,9 @@ workflow SCDOWNSTREAM { ) MULTIQC ( - ch_multiqc_files.collect() - .combine(ch_multiqc_config.mix(ch_multiqc_custom_config).collect().ifEmpty([])) - .combine(ch_multiqc_logo.collect().ifEmpty([])) - .map { files, configs, logos -> [[id: 'multiqc'], files, configs, logos, [], []] }, + ch_multiqc_files + .collect() + .map { files -> [[id: 'multiqc'], files, mqc_configs, mqc_logo, [], []] } ) ch_multiqc_report = MULTIQC.out.report.map { _meta, report -> report }.toList() From 8ff74ddbb8e739d5074d832b142260f9cb44341f Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Mon, 30 Mar 2026 09:55:54 +0200 Subject: [PATCH 40/46] Make liana/rankaggregate and scanpy/rankgenesgroups tests structural --- docs/reproducibility.md | 42 ++++----- .../liana/rankaggregate/tests/main.nf.test | 1 - .../rankaggregate/tests/main.nf.test.snap | 36 +------- .../scanpy/rankgenesgroups/tests/main.nf.test | 2 - .../rankgenesgroups/tests/main.nf.test.snap | 92 +------------------ 5 files changed, 28 insertions(+), 145 deletions(-) diff --git a/docs/reproducibility.md b/docs/reproducibility.md index 9bbe58a3..6a38a320 100644 --- a/docs/reproducibility.md +++ b/docs/reproducibility.md @@ -84,29 +84,29 @@ The **Test strategy (this branch)** column describes what the tests on this bran ### `liana/` -| Module | Description | Reproducibility | Test strategy (this branch) | -| --------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------- | -| `liana/rankaggregate` | Runs LIANA rank-aggregate ligand–receptor interaction analysis on a clustered AnnData object. | Fully deterministic — rank aggregation of multiple fixed scoring methods with no stochastic component. | hash | +| Module | Description | Reproducibility | Test strategy (this branch) | +| --------------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | +| `liana/rankaggregate` | Runs LIANA rank-aggregate ligand–receptor interaction analysis on a clustered AnnData object. | **Seeded / quasi-deterministic** — scoring methods are deterministic but floating-point aggregation can vary across BLAS/NumPy backends. | structural — versions + schema only | ### `scanpy/` -| Module | Description | Reproducibility | Test strategy (this branch) | -| ------------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | structural — versions + schema only | -| `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | hash | -| `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | structural — versions + schema only | -| `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | hash + structural | -| `scanpy/harmony` | Runs Harmony batch integration after log-normalisation and PCA, storing the corrected embedding as `X_emb`. | **Non-deterministic** — Harmony is an iterative optimisation with no fixed seed; upstream PCA is also unseeded. | structural — versions + schema only; `variance_ratio` output removed | -| `scanpy/hvgs` | Selects highly variable genes and subsets the AnnData to those genes. | Seeded / quasi-deterministic — HVG variance statistics rely on NumPy/SciPy floating-point operations that can produce slightly different results across library versions. | structural — versions + schema only | -| `scanpy/leiden` | Performs Leiden community-detection clustering at a specified resolution. | **Non-deterministic** — Leiden uses random restarts with no fixed seed. | structural — range assertion on cluster count + versions + schema | -| `scanpy/neighbors` | Computes a k-nearest-neighbour graph on a specified embedding. | Fully deterministic given a fixed input embedding. | structural — versions + schema only | -| `scanpy/paga` | Computes PAGA coarse-grained cluster connectivity and saves a graph and plot. | Fully deterministic — PAGA is a deterministic graph-summarisation step given fixed Leiden labels. | hash | -| `scanpy/pca` | Runs PCA with `random_state=0` and stores the result under a specified key. | Seeded / quasi-deterministic — seed is fixed, but float coordinates can differ across LAPACK/MKL backends. | structural — versions + schema only | -| `scanpy/plotqc` | Calculates QC metrics and produces a counts-vs-genes scatter plot for MultiQC. | Fully deterministic | hash | -| `scanpy/rankgenesgroups` | Runs differential gene expression (rank genes groups) across clusters using a configurable statistical method. | Fully deterministic for `wilcoxon` and `t-test` (defaults); depends on chosen method parameter. | hash | -| `scanpy/readh5` | Reads a 10x Genomics HDF5 (`.h5`) file and writes it as an AnnData H5AD. | Fully deterministic | hash | -| `scanpy/sample` | Down-samples cells to a fixed count or fraction using `rng=0`. | Seeded / quasi-deterministic — seed is fixed, but sampled cell set may vary across NumPy versions. | hash | -| `scanpy/umap` | Computes a UMAP embedding from a pre-built neighbour graph using `random_state=0`. | Seeded / quasi-deterministic — seed is fixed, but float coordinates vary across umap-learn/numba versions. | structural — versions + schema only | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------------------------ | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | +| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | structural — versions + schema only | +| `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | hash | +| `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | structural — versions + schema only | +| `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | hash + structural | +| `scanpy/harmony` | Runs Harmony batch integration after log-normalisation and PCA, storing the corrected embedding as `X_emb`. | **Non-deterministic** — Harmony is an iterative optimisation with no fixed seed; upstream PCA is also unseeded. | structural — versions + schema only; `variance_ratio` output removed | +| `scanpy/hvgs` | Selects highly variable genes and subsets the AnnData to those genes. | Seeded / quasi-deterministic — HVG variance statistics rely on NumPy/SciPy floating-point operations that can produce slightly different results across library versions. | structural — versions + schema only | +| `scanpy/leiden` | Performs Leiden community-detection clustering at a specified resolution. | **Non-deterministic** — Leiden uses random restarts with no fixed seed. | structural — range assertion on cluster count + versions + schema | +| `scanpy/neighbors` | Computes a k-nearest-neighbour graph on a specified embedding. | Fully deterministic given a fixed input embedding. | structural — versions + schema only | +| `scanpy/paga` | Computes PAGA coarse-grained cluster connectivity and saves a graph and plot. | Fully deterministic — PAGA is a deterministic graph-summarisation step given fixed Leiden labels. | hash | +| `scanpy/pca` | Runs PCA with `random_state=0` and stores the result under a specified key. | Seeded / quasi-deterministic — seed is fixed, but float coordinates can differ across LAPACK/MKL backends. | structural — versions + schema only | +| `scanpy/plotqc` | Calculates QC metrics and produces a counts-vs-genes scatter plot for MultiQC. | Fully deterministic | hash | +| `scanpy/rankgenesgroups` | Runs differential gene expression (rank genes groups) across clusters using a configurable statistical method. | **Seeded / quasi-deterministic** — wilcoxon and t-test are deterministic in theory, but tied-rank handling and floating-point tie-breaking can differ across SciPy versions. | structural — versions + schema only | +| `scanpy/readh5` | Reads a 10x Genomics HDF5 (`.h5`) file and writes it as an AnnData H5AD. | Fully deterministic | hash | +| `scanpy/sample` | Down-samples cells to a fixed count or fraction using `rng=0`. | Seeded / quasi-deterministic — seed is fixed, but sampled cell set may vary across NumPy versions. | hash | +| `scanpy/umap` | Computes a UMAP embedding from a pre-built neighbour graph using `random_state=0`. | Seeded / quasi-deterministic — seed is fixed, but float coordinates vary across umap-learn/numba versions. | structural — versions + schema only | ### `scimilarity/` @@ -150,7 +150,7 @@ The **Test strategy (this branch)** column describes what the tests on this bran | `finalize` | Assembles the final AnnData by extending it with all collected obs/obsm/uns/layers outputs. | Fully deterministic | hash | | `integrate` | Applies HVG selection then one or more integration methods (scVI, scANVI, Harmony, BBKNN, ComBat, Seurat, SCimilarity). | Seeded / quasi-deterministic for scVI/scANVI/ComBat/Seurat/BBKNN; **non-deterministic** for Harmony. | structural — versions + schema only | | `load_h5ad` | Loads input files in H5AD, 10x H5, RDS, or CSV format and converts all to AnnData H5AD. | Fully deterministic | hash | -| `per_group` | Runs PAGA, LIANA rank-aggregate, and rank-genes DE per cluster. | Fully deterministic | structural — versions only | +| `per_group` | Runs PAGA, LIANA rank-aggregate, and rank-genes DE per cluster. | **Seeded / quasi-deterministic** — inherits from constituent `liana/rankaggregate` and `scanpy/rankgenesgroups` modules. | structural — versions only | | `pseudobulking` | Aggregates single-cell data into pseudobulk profiles grouped by specified metadata columns. | Fully deterministic | hash | | `quality_control` | Full per-sample QC pipeline: empty droplet filtering, ambient correction, gene unification, cell/gene filtering, optional downsampling, doublet detection, and optional cell cycle scoring. | Seeded / quasi-deterministic to **non-deterministic** depending on configured ambient and doublet-detection methods. | structural — versions + multiqc files | | `scimilarity` | Embeds cells into the SCimilarity pretrained latent space and annotates with cell type labels. | Fully deterministic — fixed pretrained model, inference-only. | stub only | diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test b/modules/local/liana/rankaggregate/tests/main.nf.test index d1121a1c..71f54e4b 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test +++ b/modules/local/liana/rankaggregate/tests/main.nf.test @@ -31,7 +31,6 @@ nextflow_process { assert process.success assert "liana_res" in adata.uns assert snapshot( - process.out, path(process.out.versions[0]).yaml, adata.yaml ).match() diff --git a/modules/local/liana/rankaggregate/tests/main.nf.test.snap b/modules/local/liana/rankaggregate/tests/main.nf.test.snap index 605146c3..c8e7b781 100644 --- a/modules/local/liana/rankaggregate/tests/main.nf.test.snap +++ b/modules/local/liana/rankaggregate/tests/main.nf.test.snap @@ -40,36 +40,6 @@ }, "Should run without failures": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_liana.h5ad:md5,2091717718c2506ae92fa43a3132ed1c" - ] - ], - "1": [ - "test_liana.pkl:md5,f161ee10f742898fe3f8a42a22b440f9" - ], - "2": [ - "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_liana.h5ad:md5,2091717718c2506ae92fa43a3132ed1c" - ] - ], - "uns": [ - "test_liana.pkl:md5,f161ee10f742898fe3f8a42a22b440f9" - ], - "versions": [ - "versions.yml:md5,44f181a9b2e8bebcda641e7400af14cd" - ] - }, { "liana": "1.6.1", "python": "3.12.12", @@ -116,10 +86,10 @@ ] } ], - "timestamp": "2026-03-29T17:40:53.9124", + "timestamp": "2026-03-30T09:51:34.987832204", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test index be8084ed..c79570c5 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test @@ -34,7 +34,6 @@ nextflow_process { assert process.success assert "rank_genes_groups" in adata.uns assert snapshot( - process.out, path(process.out.versions[0]).yaml, adata.yaml ).match() @@ -98,7 +97,6 @@ nextflow_process { assert process.success assert "rank_genes_groups" in adata.uns assert snapshot( - process.out, path(process.out.versions[0]).yaml, adata.yaml ).match() diff --git a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap index ba1f4f7a..17676beb 100644 --- a/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap +++ b/modules/local/scanpy/rankgenesgroups/tests/main.nf.test.snap @@ -68,48 +68,6 @@ }, "Should run without failures": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_characteristic_genes.h5ad:md5,9841d511b9ad3719520f69e6eebdb9ca" - ] - ], - "1": [ - "test_characteristic_genes.pkl:md5,a5375824a244e135c97349a6880d8e28" - ], - "2": [ - "test_characteristic_genes.png:md5,144d711a80fd70ace88db67cccd2f0bc" - ], - "3": [ - "test_characteristic_genes_mqc.json:md5,73c74aafa606395d0a010b51bfe20895" - ], - "4": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_characteristic_genes.h5ad:md5,9841d511b9ad3719520f69e6eebdb9ca" - ] - ], - "multiqc_files": [ - "test_characteristic_genes_mqc.json:md5,73c74aafa606395d0a010b51bfe20895" - ], - "plots": [ - "test_characteristic_genes.png:md5,144d711a80fd70ace88db67cccd2f0bc" - ], - "uns": [ - "test_characteristic_genes.pkl:md5,a5375824a244e135c97349a6880d8e28" - ], - "versions": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ] - }, { "SCANPY_RANKGENESGROUPS": { "pandas": "2.3.3", @@ -158,7 +116,7 @@ ] } ], - "timestamp": "2026-03-29T11:17:32.94515289", + "timestamp": "2026-03-30T09:51:04.151403312", "meta": { "nf-test": "0.9.4", "nextflow": "25.10.2" @@ -166,48 +124,6 @@ }, "Should run with condition subsetting": { "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_characteristic_genes.h5ad:md5,d8ad5714c35d2bda2f6ddefb99ec6a81" - ] - ], - "1": [ - "test_characteristic_genes.pkl:md5,eeebba0ce02541b826cc0b605ef30e3c" - ], - "2": [ - "test_characteristic_genes.png:md5,c49d632c6d6100f7931db5491844fdda" - ], - "3": [ - "test_characteristic_genes_mqc.json:md5,dd8d8a557bda69eb0b0e0d04ad0fc47f" - ], - "4": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ], - "h5ad": [ - [ - { - "id": "test" - }, - "test_characteristic_genes.h5ad:md5,d8ad5714c35d2bda2f6ddefb99ec6a81" - ] - ], - "multiqc_files": [ - "test_characteristic_genes_mqc.json:md5,dd8d8a557bda69eb0b0e0d04ad0fc47f" - ], - "plots": [ - "test_characteristic_genes.png:md5,c49d632c6d6100f7931db5491844fdda" - ], - "uns": [ - "test_characteristic_genes.pkl:md5,eeebba0ce02541b826cc0b605ef30e3c" - ], - "versions": [ - "versions.yml:md5,a279f17d763d69028f9d84346e55dec8" - ] - }, { "SCANPY_RANKGENESGROUPS": { "pandas": "2.3.3", @@ -260,10 +176,10 @@ ] } ], - "timestamp": "2026-03-29T17:51:08.826799", + "timestamp": "2026-03-30T09:52:00.65325378", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file From 72bb8b16f5e7ba5daf3a1a208428718d54e02721 Mon Sep 17 00:00:00 2001 From: Erik Fasterius Date: Mon, 30 Mar 2026 14:59:49 +0200 Subject: [PATCH 41/46] Update snapshots --- .../fetchreference/tests/main.nf.test.snap | 8 +-- .../local/scanpy/pca/tests/main.nf.test.snap | 8 +-- .../annotate/tests/main.nf.test.snap | 4 +- .../scimilarity/embed/tests/main.nf.test.snap | 4 +- .../local/unify/tests/main.nf.test.snap | 53 ------------------- tests/default.nf.test.snap | 13 ++--- tests/main_pipeline_build.nf.test.snap | 13 ++--- tests/main_pipeline_extend.nf.test.snap | 13 ++--- tests/main_pipeline_qc.nf.test.snap | 13 ++--- ...in_pipeline_reference_mapping.nf.test.snap | 13 ++--- tests/main_pipeline_sub.nf.test.snap | 12 ++--- 11 files changed, 31 insertions(+), 123 deletions(-) diff --git a/modules/local/celldex/fetchreference/tests/main.nf.test.snap b/modules/local/celldex/fetchreference/tests/main.nf.test.snap index cf32a325..876e1f02 100644 --- a/modules/local/celldex/fetchreference/tests/main.nf.test.snap +++ b/modules/local/celldex/fetchreference/tests/main.nf.test.snap @@ -26,11 +26,11 @@ ] } ], + "timestamp": "2025-07-12T19:01:49.530052242", "meta": { "nf-test": "0.9.2", "nextflow": "25.04.6" - }, - "timestamp": "2025-07-12T19:01:49.530052242" + } }, "Should run without failures": { "content": [ @@ -48,10 +48,10 @@ } } ], + "timestamp": "2025-07-12T19:01:38.261026661", "meta": { "nf-test": "0.9.2", "nextflow": "25.04.6" - }, - "timestamp": "2025-07-12T19:01:38.261026661" + } } } \ No newline at end of file diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index a4cf45df..e89f7585 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,7 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ], "h5ad": [ [ @@ -28,13 +28,13 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ] } ], - "timestamp": "2026-03-30T07:53:20.208532988", + "timestamp": "2026-03-30T10:39:25.66784", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } }, diff --git a/modules/local/scimilarity/annotate/tests/main.nf.test.snap b/modules/local/scimilarity/annotate/tests/main.nf.test.snap index 5b226f6e..e5bdb129 100644 --- a/modules/local/scimilarity/annotate/tests/main.nf.test.snap +++ b/modules/local/scimilarity/annotate/tests/main.nf.test.snap @@ -32,10 +32,10 @@ ] } ], + "timestamp": "2026-01-25T17:16:36.878264104", "meta": { "nf-test": "0.9.2", "nextflow": "25.10.2" - }, - "timestamp": "2026-01-25T17:16:36.878264104" + } } } \ No newline at end of file diff --git a/modules/local/scimilarity/embed/tests/main.nf.test.snap b/modules/local/scimilarity/embed/tests/main.nf.test.snap index e5a49987..f9166e20 100644 --- a/modules/local/scimilarity/embed/tests/main.nf.test.snap +++ b/modules/local/scimilarity/embed/tests/main.nf.test.snap @@ -32,10 +32,10 @@ ] } ], + "timestamp": "2026-01-25T17:04:22.682984013", "meta": { "nf-test": "0.9.2", "nextflow": "25.10.2" - }, - "timestamp": "2026-01-25T17:04:22.682984013" + } } } \ No newline at end of file diff --git a/subworkflows/local/unify/tests/main.nf.test.snap b/subworkflows/local/unify/tests/main.nf.test.snap index 89a428e5..c854d4cf 100644 --- a/subworkflows/local/unify/tests/main.nf.test.snap +++ b/subworkflows/local/unify/tests/main.nf.test.snap @@ -145,59 +145,6 @@ "nextflow": "25.10.2" } }, - "Should run without failures - symbol_col index, unify_gene_symbols false, snapshot stability": { - "content": [ - { - "0": [ - [ - { - "id": "test", - "symbol_col": "index", - "batch_col": "batch", - "label_col": "label", - "condition_col": "condition", - "unknown_label": "unknown", - "counts_layer": "X" - }, - "test_unified.h5ad:md5,634cda43f3cc2ce7ffeddcd8cb0a1e76" - ] - ], - "1": [ - - ], - "2": [ - "versions.yml:md5,56975dcf8aab71705ad7f822233409b8", - "versions.yml:md5,f4baeb211a033b2534fb83ba7ec2cd86" - ], - "h5ad": [ - [ - { - "id": "test", - "symbol_col": "index", - "batch_col": "batch", - "label_col": "label", - "condition_col": "condition", - "unknown_label": "unknown", - "counts_layer": "X" - }, - "test_unified.h5ad:md5,634cda43f3cc2ce7ffeddcd8cb0a1e76" - ] - ], - "multiqc_files": [ - - ], - "versions": [ - "versions.yml:md5,56975dcf8aab71705ad7f822233409b8", - "versions.yml:md5,f4baeb211a033b2534fb83ba7ec2cd86" - ] - } - ], - "timestamp": "2026-03-16T16:28:57.027859362", - "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.4" - } - }, "Should run without failures - symbol_col index, unify_gene_symbols true": { "content": [ { diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 38da659d..c028660a 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -259,13 +259,6 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -286,10 +279,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T09:25:33.88487868", + "timestamp": "2026-03-30T14:34:12.503084", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index e0b24d08..b0115e64 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -272,13 +272,6 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -299,10 +292,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T09:28:16.222812249", + "timestamp": "2026-03-30T12:14:36.010663", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_extend.nf.test.snap b/tests/main_pipeline_extend.nf.test.snap index fbec78bc..b1e31f97 100644 --- a/tests/main_pipeline_extend.nf.test.snap +++ b/tests/main_pipeline_extend.nf.test.snap @@ -191,13 +191,6 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -214,10 +207,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T09:22:34.702307282", + "timestamp": "2026-03-30T12:22:16.840216", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index 64c1afec..c5da7395 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -149,13 +149,6 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", @@ -175,10 +168,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T09:00:07.268240826", + "timestamp": "2026-03-30T12:30:59.441635", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 3ebe4816..19a07ec0 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -191,13 +191,6 @@ "multiqc/multiqc_data/multiqc_sizes.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/sizes.pdf", - "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/sizes.png", - "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/sizes.svg", "multiqc/multiqc_report.html", "per_group", "pipeline_info", @@ -214,10 +207,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T09:01:17.509977693", + "timestamp": "2026-03-30T13:13:32.829865", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_sub.nf.test.snap b/tests/main_pipeline_sub.nf.test.snap index 4f1a404d..f5ce8e29 100644 --- a/tests/main_pipeline_sub.nf.test.snap +++ b/tests/main_pipeline_sub.nf.test.snap @@ -1,7 +1,7 @@ { "Should be able to perform subclustering": { "content": [ - 291, + 289, { "ADATA_EXTEND": { "anndata": "0.12.10", @@ -183,8 +183,6 @@ "per_group/condition:combat-SRR28679756-0.5_leiden:7/characteristic_genes", "per_group/condition:combat-SRR28679756-0.5_leiden:8", "per_group/condition:combat-SRR28679756-0.5_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:9", - "per_group/condition:combat-SRR28679756-0.5_leiden:9/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:0", "per_group/condition:combat-SRR28679756-1.0_leiden:0/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:1", @@ -199,8 +197,6 @@ "per_group/condition:combat-SRR28679756-1.0_leiden:13/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:14", "per_group/condition:combat-SRR28679756-1.0_leiden:14/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:15", - "per_group/condition:combat-SRR28679756-1.0_leiden:15/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:2", "per_group/condition:combat-SRR28679756-1.0_leiden:2/characteristic_genes", "per_group/condition:combat-SRR28679756-1.0_leiden:3", @@ -593,10 +589,10 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T08:57:20.252506257", + "timestamp": "2026-03-30T12:49:27.557798", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } } } \ No newline at end of file From 28258230bb35fc808a3b4271617d1e2d5b94580f Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 31 Mar 2026 14:46:55 +0200 Subject: [PATCH 42/46] Update snapshots --- subworkflows/local/singler/main.nf | 6 +- tests/default.nf.test | 2 +- tests/default.nf.test.snap | 182 +----- tests/main_pipeline_build.nf.test | 2 +- tests/main_pipeline_build.nf.test.snap | 263 +------- tests/main_pipeline_extend.nf.test | 2 +- tests/main_pipeline_extend.nf.test.snap | 185 +----- tests/main_pipeline_qc.nf.test | 4 +- tests/main_pipeline_qc.nf.test.snap | 137 +---- tests/main_pipeline_reference_mapping.nf.test | 2 +- ...in_pipeline_reference_mapping.nf.test.snap | 185 +----- tests/main_pipeline_sub.nf.test | 4 +- tests/main_pipeline_sub.nf.test.snap | 582 +----------------- 13 files changed, 43 insertions(+), 1513 deletions(-) diff --git a/subworkflows/local/singler/main.nf b/subworkflows/local/singler/main.nf index f5109b7c..4200fa5a 100644 --- a/subworkflows/local/singler/main.nf +++ b/subworkflows/local/singler/main.nf @@ -17,13 +17,11 @@ workflow SINGLER { CELLDEX_FETCHREFERENCE ( ch_reference.names - .map { - meta, ref -> { + .map { meta, ref -> if (!meta.version) { error "If you specify a celldex reference, you also need to specify a version" } - return [meta, ref, meta.version] - } + [meta, ref, meta.version] } ) ch_versions = ch_versions.mix(CELLDEX_FETCHREFERENCE.out.versions) diff --git a/tests/default.nf.test b/tests/default.nf.test index a429dccb..87ba45be 100644 --- a/tests/default.nf.test +++ b/tests/default.nf.test @@ -14,7 +14,7 @@ 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}', 'per_group/**']) + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', 'per_group/**', 'multiqc/**']) // stable_path: All files in ${params.outdir}/ with stable content def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') assertAll( diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index c028660a..7d1d425b 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -2,18 +2,6 @@ "-profile test": { "content": [ { - "ADATA_EXTEND": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "ADATA_MERGE": { - "anndata": "0.12.10", - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, "ADATA_READRDS": { "anndata": "0.11.1", "anndata2ri": "1.3.2", @@ -21,9 +9,6 @@ "pandas": "2.2.3", "seurat": "5.1.0" }, - "ADATA_TORDS": { - "anndataR": "1.0.2" - }, "ADATA_UNIFY": { "anndata": "0.12.10", "numpy": "2.3.5", @@ -35,26 +20,12 @@ "anndataR": "1.0.2", "celda": "1.26.0" }, - "CELLDEX_FETCHREFERENCE": { - "R": "R version 4.4.1 (2024-06-14)", - "celldex": "1.16.0", - "yaml": "2.3.10", - "SingleCellExperiment": "1.28.0", - "HDF5Array": "1.34.0" - }, "CELLTYPES_CELLTYPIST": { "python": "3.12.8", "pandas": "2.2.3", "scanpy": "1.10.4", "celltypist": "1.6.3" }, - "CELLTYPES_SINGLER": { - "R": "R version 4.5.3 (2026-03-11)", - "SingleR": "2.12.0", - "celldex": "1.20.0", - "anndataR": "1.0.2", - "ggplot2": "4.0.2" - }, "COLLECT_SIZES": { "pandas": "2.3.3", "python": "3.13.12" @@ -66,17 +37,6 @@ "python": "3.13.12", "upsetplot": "0.9.0" }, - "ENTROPY": { - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "FINALIZE_QC_ANNDATAS": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, "GET_DEDOUBLETED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" @@ -93,14 +53,6 @@ "python": "3.13.0", "anndata": "0.10.9" }, - "LEIDEN": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "NEIGHBORS": { - "python": "3.13.12", - "scanpy": "1.12" - }, "QC_FILTERED": { "matplotlib": "3.10.8", "python": "3.13.12", @@ -111,57 +63,18 @@ "python": "3.13.12", "scanpy": "1.12" }, - "SCANPY_BBKNN": { - "bbknn": "1.6.0", - "pandas": "2.3.3", - "python": "3.12.12", - "scanpy": "1.11.5" - }, "SCANPY_CELLCYCLE": { "python": "3.13.12", "scanpy": "1.12" }, - "SCANPY_COMBAT": { - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, "SCANPY_FILTER": { "python": "3.13.12", "scanpy": "1.12" }, - "SCANPY_HARMONY": { - "harmonypy": "0.2.0", - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_HVGS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_PAGA": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_RANKGENESGROUPS": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, "SCANPY_SCRUBLET": { "python": "3.12.11", "scanpy": "1.11.2" }, - "SCVITOOLS_SCVI": { - "scvi": "1.3.3" - }, - "UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, "UPSET_GENES": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -170,97 +83,12 @@ }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - }, - "liana": "1.6.1", - "python": "3.12.12", - "scanpy": "1.11.5" + } }, [ - "celltypes", - "celltypes/singler", - "celltypes/singler/SRR28679756_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679756_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679756_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679756_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679756_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_predictions.csv", - "celltypes/singler/SRR28679757_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679757_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679757_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679757_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679757_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_predictions.csv", - "celltypes/singler/SRR28679758_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679758_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679758_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679758_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679758_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_predictions.csv", - "cluster_dimred", - "cluster_dimred/bbknn", - "cluster_dimred/bbknn/entropy", - "cluster_dimred/bbknn/entropy/bbknn-global-0.5_entropy.png", - "cluster_dimred/bbknn/entropy/bbknn-global-1.0_entropy.png", - "cluster_dimred/bbknn/leiden", - "cluster_dimred/bbknn/leiden/bbknn-global-0.5_leiden.png", - "cluster_dimred/bbknn/leiden/bbknn-global-1.0_leiden.png", - "cluster_dimred/bbknn/umap", - "cluster_dimred/combat", - "cluster_dimred/combat/entropy", - "cluster_dimred/combat/entropy/combat-global-0.5_entropy.png", - "cluster_dimred/combat/entropy/combat-global-1.0_entropy.png", - "cluster_dimred/combat/leiden", - "cluster_dimred/combat/leiden/combat-global-0.5_leiden.png", - "cluster_dimred/combat/leiden/combat-global-1.0_leiden.png", - "cluster_dimred/combat/umap", - "cluster_dimred/harmony", - "cluster_dimred/harmony/entropy", - "cluster_dimred/harmony/entropy/harmony-global-0.5_entropy.png", - "cluster_dimred/harmony/entropy/harmony-global-1.0_entropy.png", - "cluster_dimred/harmony/leiden", - "cluster_dimred/harmony/leiden/harmony-global-0.5_leiden.png", - "cluster_dimred/harmony/leiden/harmony-global-1.0_leiden.png", - "cluster_dimred/harmony/umap", - "cluster_dimred/scvi", - "cluster_dimred/scvi/entropy", - "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", - "cluster_dimred/scvi/leiden", - "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", - "cluster_dimred/scvi/umap", "combine", - "combine/integrate", - "combine/integrate/scvi", - "combine/integrate/scvi/scvi_model", - "combine/integrate/scvi/scvi_model/model.pt", "combine/merge", "combine/merge/upset_genes.png", - "finalized", - "finalized/merged.h5ad", - "finalized/merged.rds", - "finalized/merged_metadata.csv", - "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_sizes.txt", - "multiqc/multiqc_data/multiqc_software_versions.txt", - "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_report.html", - "per_group", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "quality_control", @@ -276,13 +104,13 @@ "quality_control/sizes/sizes.tsv" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-30T14:34:12.503084", + "timestamp": "2026-03-30T23:00:46.95358214", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_build.nf.test b/tests/main_pipeline_build.nf.test index 270d9d6d..631f11a3 100644 --- a/tests/main_pipeline_build.nf.test +++ b/tests/main_pipeline_build.nf.test @@ -19,7 +19,7 @@ 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}', 'per_group/**']) + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', 'per_group/**', 'multiqc/**']) // stable_path: All files in ${params.outdir}/ with stable content def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') assertAll( diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index b0115e64..930dbd52 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -2,18 +2,6 @@ "Should process data from scratch": { "content": [ { - "ADATA_EXTEND": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "ADATA_MERGE": { - "anndata": "0.12.10", - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, "ADATA_READRDS": { "anndata": "0.11.1", "anndata2ri": "1.3.2", @@ -21,15 +9,6 @@ "pandas": "2.2.3", "seurat": "5.1.0" }, - "ADATA_TORDS": { - "anndataR": "1.0.2" - }, - "ADATA_UNIFY": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "python": "3.13.12", - "scipy": "1.17.1" - }, "CELDA_DECONTX": { "r": "4.5.3", "anndataR": "1.0.2", @@ -42,260 +21,30 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, - "CELLTYPES_CELLTYPIST": { - "python": "3.12.8", - "pandas": "2.2.3", - "scanpy": "1.10.4", - "celltypist": "1.6.3" - }, - "CELLTYPES_SINGLER": { - "R": "R version 4.5.3 (2026-03-11)", - "SingleR": "2.12.0", - "celldex": "1.20.0", - "anndataR": "1.0.2", - "ggplot2": "4.0.2" - }, - "COLLECT_SIZES": { - "pandas": "2.3.3", - "python": "3.13.12" - }, - "DOUBLET_REMOVAL": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "pandas": "2.3.3", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, - "ENTROPY": { - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "FINALIZE_QC_ANNDATAS": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "GET_DEDOUBLETED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "GET_THRESHOLDED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "LEIDEN": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "NEIGHBORS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "QC_FILTERED": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, - "QC_RAW": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_BBKNN": { - "bbknn": "1.6.0", - "pandas": "2.3.3", - "python": "3.12.12", - "scanpy": "1.11.5" - }, - "SCANPY_CELLCYCLE": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_COMBAT": { - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_FILTER": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_HARMONY": { - "harmonypy": "0.2.0", - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_HVGS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_PAGA": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_RANKGENESGROUPS": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_SCRUBLET": { - "python": "3.12.11", - "scanpy": "1.11.2" - }, - "SCVITOOLS_SCVI": { - "scvi": "1.3.3" - }, - "SEURAT_INTEGRATION": { - "R": "4.5.3", - "Seurat": "5.4.0", - "anndataR": "1.0.2" - }, - "UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "UPSET_GENES": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - }, - "liana": "1.6.1", - "python": "3.12.12", - "scanpy": "1.11.5" + } }, [ - "celltypes", - "celltypes/singler", - "celltypes/singler/SRR28679756_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679756_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679756_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679756_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679756_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_predictions.csv", - "celltypes/singler/SRR28679757_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679757_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679757_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679757_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679757_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_predictions.csv", - "celltypes/singler/SRR28679758_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679758_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679758_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679758_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679758_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_predictions.csv", - "cluster_dimred", - "cluster_dimred/bbknn", - "cluster_dimred/bbknn/entropy", - "cluster_dimred/bbknn/entropy/bbknn-global-0.5_entropy.png", - "cluster_dimred/bbknn/entropy/bbknn-global-1.0_entropy.png", - "cluster_dimred/bbknn/leiden", - "cluster_dimred/bbknn/leiden/bbknn-global-0.5_leiden.png", - "cluster_dimred/bbknn/leiden/bbknn-global-1.0_leiden.png", - "cluster_dimred/bbknn/umap", - "cluster_dimred/combat", - "cluster_dimred/combat/entropy", - "cluster_dimred/combat/entropy/combat-global-0.5_entropy.png", - "cluster_dimred/combat/entropy/combat-global-1.0_entropy.png", - "cluster_dimred/combat/leiden", - "cluster_dimred/combat/leiden/combat-global-0.5_leiden.png", - "cluster_dimred/combat/leiden/combat-global-1.0_leiden.png", - "cluster_dimred/combat/umap", - "cluster_dimred/harmony", - "cluster_dimred/harmony/entropy", - "cluster_dimred/harmony/entropy/harmony-global-0.5_entropy.png", - "cluster_dimred/harmony/entropy/harmony-global-1.0_entropy.png", - "cluster_dimred/harmony/leiden", - "cluster_dimred/harmony/leiden/harmony-global-0.5_leiden.png", - "cluster_dimred/harmony/leiden/harmony-global-1.0_leiden.png", - "cluster_dimred/harmony/umap", - "cluster_dimred/scvi", - "cluster_dimred/scvi/entropy", - "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", - "cluster_dimred/scvi/leiden", - "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", - "cluster_dimred/scvi/umap", - "cluster_dimred/seurat", - "cluster_dimred/seurat/entropy", - "cluster_dimred/seurat/entropy/seurat-global-0.5_entropy.png", - "cluster_dimred/seurat/entropy/seurat-global-1.0_entropy.png", - "cluster_dimred/seurat/leiden", - "cluster_dimred/seurat/leiden/seurat-global-0.5_leiden.png", - "cluster_dimred/seurat/leiden/seurat-global-1.0_leiden.png", - "cluster_dimred/seurat/umap", - "combine", - "combine/integrate", - "combine/integrate/scvi", - "combine/integrate/scvi/scvi_model", - "combine/integrate/scvi/scvi_model/model.pt", - "combine/merge", - "combine/merge/upset_genes.png", - "finalized", - "finalized/merged.h5ad", - "finalized/merged.rds", - "finalized/merged_metadata.csv", - "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_sizes.txt", - "multiqc/multiqc_data/multiqc_software_versions.txt", - "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_report.html", - "per_group", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", - "quality_control", - "quality_control/qc_filtered", - "quality_control/qc_filtered/SRR28679756_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_filtered/SRR28679757_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_filtered/SRR28679758_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw", - "quality_control/qc_raw/SRR28679756_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw/SRR28679757_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw/SRR28679758_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/sizes", - "quality_control/sizes/sizes.tsv" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-30T12:14:36.010663", + "timestamp": "2026-03-30T21:34:24.960083679", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_extend.nf.test b/tests/main_pipeline_extend.nf.test index 3abf9f56..891e69cb 100644 --- a/tests/main_pipeline_extend.nf.test +++ b/tests/main_pipeline_extend.nf.test @@ -21,7 +21,7 @@ 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}', 'per_group/**']) + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', 'per_group/**', 'multiqc/**']) // stable_path: All files in ${params.outdir}/ with stable content def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') assertAll( diff --git a/tests/main_pipeline_extend.nf.test.snap b/tests/main_pipeline_extend.nf.test.snap index b1e31f97..9ddd93b8 100644 --- a/tests/main_pipeline_extend.nf.test.snap +++ b/tests/main_pipeline_extend.nf.test.snap @@ -2,31 +2,6 @@ "Should perform scvi reference extension": { "content": [ { - "ADATA_EXTEND": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "ADATA_MERGE": { - "anndata": "0.12.10", - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "ADATA_MERGEEMBEDDINGS": { - "anndata": "0.12.10", - "python": "3.13.12" - }, - "ADATA_TORDS": { - "anndataR": "1.0.2" - }, - "ADATA_UNIFY": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "python": "3.13.12", - "scipy": "1.17.1" - }, "CELDA_DECONTX": { "r": "4.5.3", "anndataR": "1.0.2", @@ -39,178 +14,30 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, - "CELLTYPES_CELLTYPIST": { - "python": "3.12.8", - "pandas": "2.2.3", - "scanpy": "1.10.4", - "celltypist": "1.6.3" - }, - "CELLTYPES_SINGLER": { - "R": "R version 4.5.3 (2026-03-11)", - "SingleR": "2.12.0", - "celldex": "1.20.0", - "anndataR": "1.0.2", - "ggplot2": "4.0.2" - }, - "COLLECT_SIZES": { - "pandas": "2.3.3", - "python": "3.13.12" - }, - "DOUBLET_REMOVAL": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "pandas": "2.3.3", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, - "ENTROPY": { - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "FINALIZE_QC_ANNDATAS": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "GET_DEDOUBLETED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "GET_THRESHOLDED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "LEIDEN": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "NEIGHBORS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "QC_FILTERED": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, - "QC_RAW": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_CELLCYCLE": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_FILTER": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_PAGA": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_RANKGENESGROUPS": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_SCRUBLET": { - "python": "3.12.11", - "scanpy": "1.11.2" - }, - "SCVITOOLS_SCVI": { - "scvi": "1.3.3" - }, - "UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "UPSET_GENES": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - }, - "liana": "1.6.1", - "python": "3.12.12", - "scanpy": "1.11.5" + } }, [ - "celltypes", - "celltypes/singler", - "celltypes/singler/SRR28679759_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679759_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679759_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679759_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679759_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_predictions.csv", - "cluster_dimred", - "cluster_dimred/scvi", - "cluster_dimred/scvi/entropy", - "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", - "cluster_dimred/scvi/leiden", - "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", - "cluster_dimred/scvi/umap", - "combine", - "combine/integrate", - "combine/integrate/scvi", - "combine/integrate/scvi/scvi_model", - "combine/integrate/scvi/scvi_model/model.pt", - "combine/merge", - "finalized", - "finalized/merged.h5ad", - "finalized/merged.rds", - "finalized/merged_metadata.csv", - "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_sizes.txt", - "multiqc/multiqc_data/multiqc_software_versions.txt", - "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_report.html", - "per_group", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", - "quality_control", - "quality_control/qc_filtered", - "quality_control/qc_filtered/SRR28679759_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw", - "quality_control/qc_raw/SRR28679759_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/sizes", - "quality_control/sizes/sizes.tsv" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-30T12:22:16.840216", + "timestamp": "2026-03-30T21:33:58.038700942", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_qc.nf.test b/tests/main_pipeline_qc.nf.test index 4a296ac7..73ca00e8 100644 --- a/tests/main_pipeline_qc.nf.test +++ b/tests/main_pipeline_qc.nf.test @@ -18,14 +18,14 @@ 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}']) + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', 'per_group/**', 'multiqc/**']) // 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(), + // workflow.trace.succeeded().size(), disabled, because tool versions may differ and affect exact task counts // 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_scdownstream_software_mqc_versions.yml"), // All stable path name, with a relative path diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index c5da7395..9f4487ed 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -1,7 +1,6 @@ { "Should process data from scratch": { "content": [ - 57, { "ADATA_READRDS": { "anndata": "0.11.1", @@ -10,12 +9,6 @@ "pandas": "2.2.3", "seurat": "5.1.0" }, - "ADATA_UNIFY": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "python": "3.13.12", - "scipy": "1.17.1" - }, "CELDA_DECONTX": { "r": "4.5.3", "anndataR": "1.0.2", @@ -28,150 +21,30 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, - "CELLTYPES_CELLTYPIST": { - "python": "3.12.8", - "pandas": "2.2.3", - "scanpy": "1.10.4", - "celltypist": "1.6.3" - }, - "CELLTYPES_SINGLER": { - "R": "R version 4.5.3 (2026-03-11)", - "SingleR": "2.12.0", - "celldex": "1.20.0", - "anndataR": "1.0.2", - "ggplot2": "4.0.2" - }, - "COLLECT_SIZES": { - "pandas": "2.3.3", - "python": "3.13.12" - }, - "DOUBLET_REMOVAL": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "pandas": "2.3.3", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, - "FINALIZE_QC_ANNDATAS": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "GET_DEDOUBLETED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "GET_THRESHOLDED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "QC_FILTERED": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, - "QC_RAW": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_CELLCYCLE": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_FILTER": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_SCRUBLET": { - "python": "3.12.11", - "scanpy": "1.11.2" - }, - "UPSET_GENES": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" } }, [ - "celltypes", - "celltypes/singler", - "celltypes/singler/SRR28679756_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679756_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679756_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679756_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679756_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679756_singler_predictions.csv", - "celltypes/singler/SRR28679757_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679757_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679757_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679757_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679757_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679757_singler_predictions.csv", - "celltypes/singler/SRR28679758_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679758_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679758_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679758_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679758_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679758_singler_predictions.csv", - "combine", - "combine/merge", - "combine/merge/upset_genes.png", - "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_sizes.txt", - "multiqc/multiqc_data/multiqc_software_versions.txt", - "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_report.html", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", - "quality_control", - "quality_control/qc_filtered", - "quality_control/qc_filtered/SRR28679756_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_filtered/SRR28679757_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_filtered/SRR28679758_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw", - "quality_control/qc_raw/SRR28679756_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw/SRR28679757_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw/SRR28679758_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/sizes", - "quality_control/sizes/sizes.tsv" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-30T12:30:59.441635", + "timestamp": "2026-03-30T21:34:25.526334913", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_reference_mapping.nf.test b/tests/main_pipeline_reference_mapping.nf.test index 24517836..e20eaed8 100644 --- a/tests/main_pipeline_reference_mapping.nf.test +++ b/tests/main_pipeline_reference_mapping.nf.test @@ -20,7 +20,7 @@ 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}', 'per_group/**']) + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', 'per_group/**', 'multiqc/**']) // stable_path: All files in ${params.outdir}/ with stable content def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') assertAll( diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 19a07ec0..5e251de0 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -2,27 +2,6 @@ "Should perform scvi reference mapping": { "content": [ { - "ADATA_EXTEND": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "ADATA_MERGE": { - "anndata": "0.12.10", - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "ADATA_TORDS": { - "anndataR": "1.0.2" - }, - "ADATA_UNIFY": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "python": "3.13.12", - "scipy": "1.17.1" - }, "CELDA_DECONTX": { "r": "4.5.3", "anndataR": "1.0.2", @@ -35,182 +14,30 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, - "CELLTYPES_CELLTYPIST": { - "python": "3.12.8", - "pandas": "2.2.3", - "scanpy": "1.10.4", - "celltypist": "1.6.3" - }, - "CELLTYPES_SINGLER": { - "R": "R version 4.5.3 (2026-03-11)", - "SingleR": "2.12.0", - "celldex": "1.20.0", - "anndataR": "1.0.2", - "ggplot2": "4.0.2" - }, - "COLLECT_SIZES": { - "pandas": "2.3.3", - "python": "3.13.12" - }, - "DOUBLET_REMOVAL": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "pandas": "2.3.3", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, - "ENTROPY": { - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "FINALIZE_QC_ANNDATAS": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "GET_DEDOUBLETED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "GET_THRESHOLDED_SIZE": { - "python": "3.13.0", - "anndata": "0.10.9" - }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, - "LEIDEN": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "NEIGHBORS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "QC_FILTERED": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, - "QC_RAW": { - "matplotlib": "3.10.8", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_CELLCYCLE": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_FILTER": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_HVGS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_PAGA": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_RANKGENESGROUPS": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_SCRUBLET": { - "python": "3.12.11", - "scanpy": "1.11.2" - }, - "SCVITOOLS_SCVI": { - "scvi": "1.3.3" - }, - "UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "UPSET_GENES": { - "anndata": "0.12.10", - "matplotlib": "3.10.8", - "python": "3.13.12", - "upsetplot": "0.9.0" - }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - }, - "liana": "1.6.1", - "python": "3.12.12", - "scanpy": "1.11.5" + } }, [ - "celltypes", - "celltypes/singler", - "celltypes/singler/SRR28679759_singler_hpca_celldex_distribution.pdf", - "celltypes/singler/SRR28679759_singler_hpca_celldex_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_hpca_direct_distribution.pdf", - "celltypes/singler/SRR28679759_singler_hpca_direct_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_immune_celldex_distribution.pdf", - "celltypes/singler/SRR28679759_singler_immune_celldex_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_immune_direct_distribution.pdf", - "celltypes/singler/SRR28679759_singler_immune_direct_heatmap.pdf", - "celltypes/singler/SRR28679759_singler_predictions.csv", - "cluster_dimred", - "cluster_dimred/scvi", - "cluster_dimred/scvi/entropy", - "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", - "cluster_dimred/scvi/leiden", - "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", - "cluster_dimred/scvi/umap", - "combine", - "combine/integrate", - "combine/integrate/scvi", - "combine/integrate/scvi/scvi_model", - "combine/integrate/scvi/scvi_model/model.pt", - "combine/merge", - "finalized", - "finalized/merged.h5ad", - "finalized/merged.rds", - "finalized/merged_metadata.csv", - "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_sizes.txt", - "multiqc/multiqc_data/multiqc_software_versions.txt", - "multiqc/multiqc_data/multiqc_sources.txt", - "multiqc/multiqc_report.html", - "per_group", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", - "quality_control", - "quality_control/qc_filtered", - "quality_control/qc_filtered/SRR28679759_preprocessed_total_counts_vs_n_genes_by_counts.png", - "quality_control/qc_raw", - "quality_control/qc_raw/SRR28679759_raw_total_counts_vs_n_genes_by_counts.png", - "quality_control/sizes", - "quality_control/sizes/sizes.tsv" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-30T13:13:32.829865", + "timestamp": "2026-03-30T23:00:46.211628435", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file diff --git a/tests/main_pipeline_sub.nf.test b/tests/main_pipeline_sub.nf.test index ed061091..740f29f9 100644 --- a/tests/main_pipeline_sub.nf.test +++ b/tests/main_pipeline_sub.nf.test @@ -20,14 +20,14 @@ 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}']) + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', 'per_group/**', 'multiqc/**']) // 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(), + // workflow.trace.succeeded().size(), disabled, because clustering is not stable and the DIFFERENTIAL_EXPRESSION subworkflow creates tasks based on the number of clusters // 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_scdownstream_software_mqc_versions.yml"), // All stable path name, with a relative path diff --git a/tests/main_pipeline_sub.nf.test.snap b/tests/main_pipeline_sub.nf.test.snap index f5ce8e29..1a8e0c8d 100644 --- a/tests/main_pipeline_sub.nf.test.snap +++ b/tests/main_pipeline_sub.nf.test.snap @@ -1,52 +1,7 @@ { "Should be able to perform subclustering": { "content": [ - 289, { - "ADATA_EXTEND": { - "anndata": "0.12.10", - "numpy": "2.3.5", - "pandas": "2.3.3", - "python": "3.13.12" - }, - "ADATA_SPLITEMBEDDINGS": { - "anndata": "0.12.10", - "python": "3.13.12" - }, - "ADATA_TORDS": { - "anndataR": "1.0.2" - }, - "ENTROPY": { - "python": "3.13.12", - "scanpy": "1.12", - "scipy": "1.17.1" - }, - "LEIDEN": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "NEIGHBORS": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_PAGA": { - "python": "3.13.12", - "scanpy": "1.12" - }, - "SCANPY_RANKGENESGROUPS": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, - "SPLITCOL": { - "anndata": "0.12.10", - "python": "3.13.12" - }, - "UMAP": { - "pandas": "2.3.3", - "python": "3.13.12", - "scanpy": "1.12" - }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" }, @@ -55,544 +10,17 @@ "scanpy": "1.11.5" }, [ - "adata", - "adata/combat.h5ad", - "adata/harmony.h5ad", - "adata/scvi.h5ad", - "cluster_dimred", - "cluster_dimred/combat", - "cluster_dimred/combat/entropy", - "cluster_dimred/combat/entropy/combat-SRR28679756-0.5_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679756-1.0_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679757-0.5_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679757-1.0_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679758-0.5_entropy.png", - "cluster_dimred/combat/entropy/combat-SRR28679758-1.0_entropy.png", - "cluster_dimred/combat/leiden", - "cluster_dimred/combat/leiden/combat-SRR28679756-0.5_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679756-1.0_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679757-0.5_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679757-1.0_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679758-0.5_leiden.png", - "cluster_dimred/combat/leiden/combat-SRR28679758-1.0_leiden.png", - "cluster_dimred/combat/umap", - "cluster_dimred/harmony", - "cluster_dimred/harmony/entropy", - "cluster_dimred/harmony/entropy/harmony-SRR28679756-0.5_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679756-1.0_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679757-0.5_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679757-1.0_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679758-0.5_entropy.png", - "cluster_dimred/harmony/entropy/harmony-SRR28679758-1.0_entropy.png", - "cluster_dimred/harmony/leiden", - "cluster_dimred/harmony/leiden/harmony-SRR28679756-0.5_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679756-1.0_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679757-0.5_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679757-1.0_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679758-0.5_leiden.png", - "cluster_dimred/harmony/leiden/harmony-SRR28679758-1.0_leiden.png", - "cluster_dimred/harmony/umap", - "cluster_dimred/scvi", - "cluster_dimred/scvi/entropy", - "cluster_dimred/scvi/entropy/scvi-SRR28679756-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679756-1.0_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679757-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679757-1.0_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679758-0.5_entropy.png", - "cluster_dimred/scvi/entropy/scvi-SRR28679758-1.0_entropy.png", - "cluster_dimred/scvi/leiden", - "cluster_dimred/scvi/leiden/scvi-SRR28679756-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679756-1.0_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679757-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679757-1.0_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679758-0.5_leiden.png", - "cluster_dimred/scvi/leiden/scvi-SRR28679758-1.0_leiden.png", - "cluster_dimred/scvi/umap", - "finalized", - "finalized/base.h5ad", - "finalized/base.rds", - "finalized/base_metadata.csv", - "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", - "per_group", - "per_group/combat-SRR28679756", - "per_group/combat-SRR28679756-0.5", - "per_group/combat-SRR28679756-0.5/paga", - "per_group/combat-SRR28679756-0.5/paga/combat-SRR28679756-0.5_paga.png", - "per_group/combat-SRR28679756-0.5_leiden", - "per_group/combat-SRR28679756-0.5_leiden/characteristic_genes", - "per_group/combat-SRR28679756-0.5_leiden/characteristic_genes/combat-SRR28679756-0.5_leiden_characteristic_genes.png", - "per_group/combat-SRR28679756-1.0", - "per_group/combat-SRR28679756-1.0/paga", - "per_group/combat-SRR28679756-1.0/paga/combat-SRR28679756-1.0_paga.png", - "per_group/combat-SRR28679756-1.0_leiden", - "per_group/combat-SRR28679756-1.0_leiden/characteristic_genes", - "per_group/combat-SRR28679756-1.0_leiden/characteristic_genes/combat-SRR28679756-1.0_leiden_characteristic_genes.png", - "per_group/combat-SRR28679756/paga", - "per_group/combat-SRR28679757", - "per_group/combat-SRR28679757-0.5", - "per_group/combat-SRR28679757-0.5/paga", - "per_group/combat-SRR28679757-0.5/paga/combat-SRR28679757-0.5_paga.png", - "per_group/combat-SRR28679757-0.5_leiden", - "per_group/combat-SRR28679757-0.5_leiden/characteristic_genes", - "per_group/combat-SRR28679757-0.5_leiden/characteristic_genes/combat-SRR28679757-0.5_leiden_characteristic_genes.png", - "per_group/combat-SRR28679757-1.0", - "per_group/combat-SRR28679757-1.0/paga", - "per_group/combat-SRR28679757-1.0/paga/combat-SRR28679757-1.0_paga.png", - "per_group/combat-SRR28679757-1.0_leiden", - "per_group/combat-SRR28679757-1.0_leiden/characteristic_genes", - "per_group/combat-SRR28679757-1.0_leiden/characteristic_genes/combat-SRR28679757-1.0_leiden_characteristic_genes.png", - "per_group/combat-SRR28679757/paga", - "per_group/combat-SRR28679758", - "per_group/combat-SRR28679758-0.5", - "per_group/combat-SRR28679758-0.5/paga", - "per_group/combat-SRR28679758-0.5/paga/combat-SRR28679758-0.5_paga.png", - "per_group/combat-SRR28679758-0.5_leiden", - "per_group/combat-SRR28679758-0.5_leiden/characteristic_genes", - "per_group/combat-SRR28679758-0.5_leiden/characteristic_genes/combat-SRR28679758-0.5_leiden_characteristic_genes.png", - "per_group/combat-SRR28679758-1.0", - "per_group/combat-SRR28679758-1.0/paga", - "per_group/combat-SRR28679758-1.0/paga/combat-SRR28679758-1.0_paga.png", - "per_group/combat-SRR28679758-1.0_leiden", - "per_group/combat-SRR28679758-1.0_leiden/characteristic_genes", - "per_group/combat-SRR28679758-1.0_leiden/characteristic_genes/combat-SRR28679758-1.0_leiden_characteristic_genes.png", - "per_group/combat-SRR28679758/paga", - "per_group/condition:combat-SRR28679756-0.5_leiden:0", - "per_group/condition:combat-SRR28679756-0.5_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:1", - "per_group/condition:combat-SRR28679756-0.5_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:2", - "per_group/condition:combat-SRR28679756-0.5_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:3", - "per_group/condition:combat-SRR28679756-0.5_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:4", - "per_group/condition:combat-SRR28679756-0.5_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:5", - "per_group/condition:combat-SRR28679756-0.5_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:6", - "per_group/condition:combat-SRR28679756-0.5_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:7", - "per_group/condition:combat-SRR28679756-0.5_leiden:7/characteristic_genes", - "per_group/condition:combat-SRR28679756-0.5_leiden:8", - "per_group/condition:combat-SRR28679756-0.5_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:0", - "per_group/condition:combat-SRR28679756-1.0_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:1", - "per_group/condition:combat-SRR28679756-1.0_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:10", - "per_group/condition:combat-SRR28679756-1.0_leiden:10/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:11", - "per_group/condition:combat-SRR28679756-1.0_leiden:11/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:12", - "per_group/condition:combat-SRR28679756-1.0_leiden:12/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:13", - "per_group/condition:combat-SRR28679756-1.0_leiden:13/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:14", - "per_group/condition:combat-SRR28679756-1.0_leiden:14/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:2", - "per_group/condition:combat-SRR28679756-1.0_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:3", - "per_group/condition:combat-SRR28679756-1.0_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:4", - "per_group/condition:combat-SRR28679756-1.0_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:5", - "per_group/condition:combat-SRR28679756-1.0_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:6", - "per_group/condition:combat-SRR28679756-1.0_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:7", - "per_group/condition:combat-SRR28679756-1.0_leiden:7/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:8", - "per_group/condition:combat-SRR28679756-1.0_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679756-1.0_leiden:9", - "per_group/condition:combat-SRR28679756-1.0_leiden:9/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:0", - "per_group/condition:combat-SRR28679757-0.5_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:1", - "per_group/condition:combat-SRR28679757-0.5_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:2", - "per_group/condition:combat-SRR28679757-0.5_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:3", - "per_group/condition:combat-SRR28679757-0.5_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:4", - "per_group/condition:combat-SRR28679757-0.5_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:5", - "per_group/condition:combat-SRR28679757-0.5_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679757-0.5_leiden:6", - "per_group/condition:combat-SRR28679757-0.5_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:0", - "per_group/condition:combat-SRR28679757-1.0_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:1", - "per_group/condition:combat-SRR28679757-1.0_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:10", - "per_group/condition:combat-SRR28679757-1.0_leiden:10/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:11", - "per_group/condition:combat-SRR28679757-1.0_leiden:11/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:12", - "per_group/condition:combat-SRR28679757-1.0_leiden:12/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:2", - "per_group/condition:combat-SRR28679757-1.0_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:3", - "per_group/condition:combat-SRR28679757-1.0_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:4", - "per_group/condition:combat-SRR28679757-1.0_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:5", - "per_group/condition:combat-SRR28679757-1.0_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:6", - "per_group/condition:combat-SRR28679757-1.0_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:7", - "per_group/condition:combat-SRR28679757-1.0_leiden:7/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:8", - "per_group/condition:combat-SRR28679757-1.0_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679757-1.0_leiden:9", - "per_group/condition:combat-SRR28679757-1.0_leiden:9/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:0", - "per_group/condition:combat-SRR28679758-0.5_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:1", - "per_group/condition:combat-SRR28679758-0.5_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:2", - "per_group/condition:combat-SRR28679758-0.5_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:3", - "per_group/condition:combat-SRR28679758-0.5_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:4", - "per_group/condition:combat-SRR28679758-0.5_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:5", - "per_group/condition:combat-SRR28679758-0.5_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679758-0.5_leiden:6", - "per_group/condition:combat-SRR28679758-0.5_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:0", - "per_group/condition:combat-SRR28679758-1.0_leiden:0/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:1", - "per_group/condition:combat-SRR28679758-1.0_leiden:1/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:10", - "per_group/condition:combat-SRR28679758-1.0_leiden:10/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:11", - "per_group/condition:combat-SRR28679758-1.0_leiden:11/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:12", - "per_group/condition:combat-SRR28679758-1.0_leiden:12/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:13", - "per_group/condition:combat-SRR28679758-1.0_leiden:13/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:2", - "per_group/condition:combat-SRR28679758-1.0_leiden:2/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:3", - "per_group/condition:combat-SRR28679758-1.0_leiden:3/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:4", - "per_group/condition:combat-SRR28679758-1.0_leiden:4/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:5", - "per_group/condition:combat-SRR28679758-1.0_leiden:5/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:6", - "per_group/condition:combat-SRR28679758-1.0_leiden:6/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:7", - "per_group/condition:combat-SRR28679758-1.0_leiden:7/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:8", - "per_group/condition:combat-SRR28679758-1.0_leiden:8/characteristic_genes", - "per_group/condition:combat-SRR28679758-1.0_leiden:9", - "per_group/condition:combat-SRR28679758-1.0_leiden:9/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:0", - "per_group/condition:harmony-SRR28679756-0.5_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:1", - "per_group/condition:harmony-SRR28679756-0.5_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:2", - "per_group/condition:harmony-SRR28679756-0.5_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:3", - "per_group/condition:harmony-SRR28679756-0.5_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679756-0.5_leiden:4", - "per_group/condition:harmony-SRR28679756-0.5_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:0", - "per_group/condition:harmony-SRR28679756-1.0_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:1", - "per_group/condition:harmony-SRR28679756-1.0_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:2", - "per_group/condition:harmony-SRR28679756-1.0_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:3", - "per_group/condition:harmony-SRR28679756-1.0_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:4", - "per_group/condition:harmony-SRR28679756-1.0_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:5", - "per_group/condition:harmony-SRR28679756-1.0_leiden:5/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:6", - "per_group/condition:harmony-SRR28679756-1.0_leiden:6/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:7", - "per_group/condition:harmony-SRR28679756-1.0_leiden:7/characteristic_genes", - "per_group/condition:harmony-SRR28679756-1.0_leiden:8", - "per_group/condition:harmony-SRR28679756-1.0_leiden:8/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:0", - "per_group/condition:harmony-SRR28679757-0.5_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:1", - "per_group/condition:harmony-SRR28679757-0.5_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:2", - "per_group/condition:harmony-SRR28679757-0.5_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:3", - "per_group/condition:harmony-SRR28679757-0.5_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679757-0.5_leiden:4", - "per_group/condition:harmony-SRR28679757-0.5_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:0", - "per_group/condition:harmony-SRR28679757-1.0_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:1", - "per_group/condition:harmony-SRR28679757-1.0_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:2", - "per_group/condition:harmony-SRR28679757-1.0_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:3", - "per_group/condition:harmony-SRR28679757-1.0_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:4", - "per_group/condition:harmony-SRR28679757-1.0_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:5", - "per_group/condition:harmony-SRR28679757-1.0_leiden:5/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:6", - "per_group/condition:harmony-SRR28679757-1.0_leiden:6/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:7", - "per_group/condition:harmony-SRR28679757-1.0_leiden:7/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:8", - "per_group/condition:harmony-SRR28679757-1.0_leiden:8/characteristic_genes", - "per_group/condition:harmony-SRR28679757-1.0_leiden:9", - "per_group/condition:harmony-SRR28679757-1.0_leiden:9/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:0", - "per_group/condition:harmony-SRR28679758-0.5_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:1", - "per_group/condition:harmony-SRR28679758-0.5_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:2", - "per_group/condition:harmony-SRR28679758-0.5_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:3", - "per_group/condition:harmony-SRR28679758-0.5_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679758-0.5_leiden:4", - "per_group/condition:harmony-SRR28679758-0.5_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:0", - "per_group/condition:harmony-SRR28679758-1.0_leiden:0/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:1", - "per_group/condition:harmony-SRR28679758-1.0_leiden:1/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:2", - "per_group/condition:harmony-SRR28679758-1.0_leiden:2/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:3", - "per_group/condition:harmony-SRR28679758-1.0_leiden:3/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:4", - "per_group/condition:harmony-SRR28679758-1.0_leiden:4/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:5", - "per_group/condition:harmony-SRR28679758-1.0_leiden:5/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:6", - "per_group/condition:harmony-SRR28679758-1.0_leiden:6/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:7", - "per_group/condition:harmony-SRR28679758-1.0_leiden:7/characteristic_genes", - "per_group/condition:harmony-SRR28679758-1.0_leiden:8", - "per_group/condition:harmony-SRR28679758-1.0_leiden:8/characteristic_genes", - "per_group/condition:sample:SRR28679756", - "per_group/condition:sample:SRR28679756/characteristic_genes", - "per_group/condition:sample:SRR28679757", - "per_group/condition:sample:SRR28679757/characteristic_genes", - "per_group/condition:sample:SRR28679758", - "per_group/condition:sample:SRR28679758/characteristic_genes", - "per_group/condition:scvi-SRR28679756-0.5_leiden:0", - "per_group/condition:scvi-SRR28679756-0.5_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679756-0.5_leiden:1", - "per_group/condition:scvi-SRR28679756-0.5_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679756-0.5_leiden:2", - "per_group/condition:scvi-SRR28679756-0.5_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:0", - "per_group/condition:scvi-SRR28679756-1.0_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:1", - "per_group/condition:scvi-SRR28679756-1.0_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:10", - "per_group/condition:scvi-SRR28679756-1.0_leiden:10/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:11", - "per_group/condition:scvi-SRR28679756-1.0_leiden:11/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:12", - "per_group/condition:scvi-SRR28679756-1.0_leiden:12/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:2", - "per_group/condition:scvi-SRR28679756-1.0_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:3", - "per_group/condition:scvi-SRR28679756-1.0_leiden:3/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:4", - "per_group/condition:scvi-SRR28679756-1.0_leiden:4/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:5", - "per_group/condition:scvi-SRR28679756-1.0_leiden:5/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:6", - "per_group/condition:scvi-SRR28679756-1.0_leiden:6/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:7", - "per_group/condition:scvi-SRR28679756-1.0_leiden:7/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:8", - "per_group/condition:scvi-SRR28679756-1.0_leiden:8/characteristic_genes", - "per_group/condition:scvi-SRR28679756-1.0_leiden:9", - "per_group/condition:scvi-SRR28679756-1.0_leiden:9/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:0", - "per_group/condition:scvi-SRR28679757-0.5_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:1", - "per_group/condition:scvi-SRR28679757-0.5_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:2", - "per_group/condition:scvi-SRR28679757-0.5_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:3", - "per_group/condition:scvi-SRR28679757-0.5_leiden:3/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:4", - "per_group/condition:scvi-SRR28679757-0.5_leiden:4/characteristic_genes", - "per_group/condition:scvi-SRR28679757-0.5_leiden:5", - "per_group/condition:scvi-SRR28679757-0.5_leiden:5/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:0", - "per_group/condition:scvi-SRR28679757-1.0_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:1", - "per_group/condition:scvi-SRR28679757-1.0_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:10", - "per_group/condition:scvi-SRR28679757-1.0_leiden:10/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:11", - "per_group/condition:scvi-SRR28679757-1.0_leiden:11/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:12", - "per_group/condition:scvi-SRR28679757-1.0_leiden:12/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:2", - "per_group/condition:scvi-SRR28679757-1.0_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:3", - "per_group/condition:scvi-SRR28679757-1.0_leiden:3/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:4", - "per_group/condition:scvi-SRR28679757-1.0_leiden:4/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:5", - "per_group/condition:scvi-SRR28679757-1.0_leiden:5/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:6", - "per_group/condition:scvi-SRR28679757-1.0_leiden:6/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:7", - "per_group/condition:scvi-SRR28679757-1.0_leiden:7/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:8", - "per_group/condition:scvi-SRR28679757-1.0_leiden:8/characteristic_genes", - "per_group/condition:scvi-SRR28679757-1.0_leiden:9", - "per_group/condition:scvi-SRR28679757-1.0_leiden:9/characteristic_genes", - "per_group/condition:scvi-SRR28679758-0.5_leiden:0", - "per_group/condition:scvi-SRR28679758-0.5_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679758-0.5_leiden:1", - "per_group/condition:scvi-SRR28679758-0.5_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679758-0.5_leiden:2", - "per_group/condition:scvi-SRR28679758-0.5_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:0", - "per_group/condition:scvi-SRR28679758-1.0_leiden:0/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:1", - "per_group/condition:scvi-SRR28679758-1.0_leiden:1/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:10", - "per_group/condition:scvi-SRR28679758-1.0_leiden:10/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:11", - "per_group/condition:scvi-SRR28679758-1.0_leiden:11/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:12", - "per_group/condition:scvi-SRR28679758-1.0_leiden:12/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:13", - "per_group/condition:scvi-SRR28679758-1.0_leiden:13/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:2", - "per_group/condition:scvi-SRR28679758-1.0_leiden:2/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:3", - "per_group/condition:scvi-SRR28679758-1.0_leiden:3/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:4", - "per_group/condition:scvi-SRR28679758-1.0_leiden:4/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:5", - "per_group/condition:scvi-SRR28679758-1.0_leiden:5/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:6", - "per_group/condition:scvi-SRR28679758-1.0_leiden:6/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:7", - "per_group/condition:scvi-SRR28679758-1.0_leiden:7/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:8", - "per_group/condition:scvi-SRR28679758-1.0_leiden:8/characteristic_genes", - "per_group/condition:scvi-SRR28679758-1.0_leiden:9", - "per_group/condition:scvi-SRR28679758-1.0_leiden:9/characteristic_genes", - "per_group/harmony-SRR28679756", - "per_group/harmony-SRR28679756-0.5", - "per_group/harmony-SRR28679756-0.5/paga", - "per_group/harmony-SRR28679756-0.5/paga/harmony-SRR28679756-0.5_paga.png", - "per_group/harmony-SRR28679756-0.5_leiden", - "per_group/harmony-SRR28679756-0.5_leiden/characteristic_genes", - "per_group/harmony-SRR28679756-0.5_leiden/characteristic_genes/harmony-SRR28679756-0.5_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679756-1.0", - "per_group/harmony-SRR28679756-1.0/paga", - "per_group/harmony-SRR28679756-1.0/paga/harmony-SRR28679756-1.0_paga.png", - "per_group/harmony-SRR28679756-1.0_leiden", - "per_group/harmony-SRR28679756-1.0_leiden/characteristic_genes", - "per_group/harmony-SRR28679756-1.0_leiden/characteristic_genes/harmony-SRR28679756-1.0_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679756/paga", - "per_group/harmony-SRR28679757", - "per_group/harmony-SRR28679757-0.5", - "per_group/harmony-SRR28679757-0.5/paga", - "per_group/harmony-SRR28679757-0.5/paga/harmony-SRR28679757-0.5_paga.png", - "per_group/harmony-SRR28679757-0.5_leiden", - "per_group/harmony-SRR28679757-0.5_leiden/characteristic_genes", - "per_group/harmony-SRR28679757-0.5_leiden/characteristic_genes/harmony-SRR28679757-0.5_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679757-1.0", - "per_group/harmony-SRR28679757-1.0/paga", - "per_group/harmony-SRR28679757-1.0/paga/harmony-SRR28679757-1.0_paga.png", - "per_group/harmony-SRR28679757-1.0_leiden", - "per_group/harmony-SRR28679757-1.0_leiden/characteristic_genes", - "per_group/harmony-SRR28679757-1.0_leiden/characteristic_genes/harmony-SRR28679757-1.0_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679757/paga", - "per_group/harmony-SRR28679758", - "per_group/harmony-SRR28679758-0.5", - "per_group/harmony-SRR28679758-0.5/paga", - "per_group/harmony-SRR28679758-0.5/paga/harmony-SRR28679758-0.5_paga.png", - "per_group/harmony-SRR28679758-0.5_leiden", - "per_group/harmony-SRR28679758-0.5_leiden/characteristic_genes", - "per_group/harmony-SRR28679758-0.5_leiden/characteristic_genes/harmony-SRR28679758-0.5_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679758-1.0", - "per_group/harmony-SRR28679758-1.0/paga", - "per_group/harmony-SRR28679758-1.0/paga/harmony-SRR28679758-1.0_paga.png", - "per_group/harmony-SRR28679758-1.0_leiden", - "per_group/harmony-SRR28679758-1.0_leiden/characteristic_genes", - "per_group/harmony-SRR28679758-1.0_leiden/characteristic_genes/harmony-SRR28679758-1.0_leiden_characteristic_genes.png", - "per_group/harmony-SRR28679758/paga", - "per_group/sample", - "per_group/sample/characteristic_genes", - "per_group/sample/characteristic_genes/sample_characteristic_genes.png", - "per_group/scvi-SRR28679756", - "per_group/scvi-SRR28679756-0.5", - "per_group/scvi-SRR28679756-0.5/paga", - "per_group/scvi-SRR28679756-0.5/paga/scvi-SRR28679756-0.5_paga.png", - "per_group/scvi-SRR28679756-0.5_leiden", - "per_group/scvi-SRR28679756-0.5_leiden/characteristic_genes", - "per_group/scvi-SRR28679756-0.5_leiden/characteristic_genes/scvi-SRR28679756-0.5_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679756-1.0", - "per_group/scvi-SRR28679756-1.0/paga", - "per_group/scvi-SRR28679756-1.0/paga/scvi-SRR28679756-1.0_paga.png", - "per_group/scvi-SRR28679756-1.0_leiden", - "per_group/scvi-SRR28679756-1.0_leiden/characteristic_genes", - "per_group/scvi-SRR28679756-1.0_leiden/characteristic_genes/scvi-SRR28679756-1.0_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679756/paga", - "per_group/scvi-SRR28679757", - "per_group/scvi-SRR28679757-0.5", - "per_group/scvi-SRR28679757-0.5/paga", - "per_group/scvi-SRR28679757-0.5/paga/scvi-SRR28679757-0.5_paga.png", - "per_group/scvi-SRR28679757-0.5_leiden", - "per_group/scvi-SRR28679757-0.5_leiden/characteristic_genes", - "per_group/scvi-SRR28679757-0.5_leiden/characteristic_genes/scvi-SRR28679757-0.5_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679757-1.0", - "per_group/scvi-SRR28679757-1.0/paga", - "per_group/scvi-SRR28679757-1.0/paga/scvi-SRR28679757-1.0_paga.png", - "per_group/scvi-SRR28679757-1.0_leiden", - "per_group/scvi-SRR28679757-1.0_leiden/characteristic_genes", - "per_group/scvi-SRR28679757-1.0_leiden/characteristic_genes/scvi-SRR28679757-1.0_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679757/paga", - "per_group/scvi-SRR28679758", - "per_group/scvi-SRR28679758-0.5", - "per_group/scvi-SRR28679758-0.5/paga", - "per_group/scvi-SRR28679758-0.5/paga/scvi-SRR28679758-0.5_paga.png", - "per_group/scvi-SRR28679758-0.5_leiden", - "per_group/scvi-SRR28679758-0.5_leiden/characteristic_genes", - "per_group/scvi-SRR28679758-0.5_leiden/characteristic_genes/scvi-SRR28679758-0.5_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679758-1.0", - "per_group/scvi-SRR28679758-1.0/paga", - "per_group/scvi-SRR28679758-1.0/paga/scvi-SRR28679758-1.0_paga.png", - "per_group/scvi-SRR28679758-1.0_leiden", - "per_group/scvi-SRR28679758-1.0_leiden/characteristic_genes", - "per_group/scvi-SRR28679758-1.0_leiden/characteristic_genes/scvi-SRR28679758-1.0_leiden_characteristic_genes.png", - "per_group/scvi-SRR28679758/paga", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", - "splitcol", - "splitcol/SRR28679756.h5ad", - "splitcol/SRR28679757.h5ad", - "splitcol/SRR28679758.h5ad" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" ], [ - "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" + ] ], - "timestamp": "2026-03-30T12:49:27.557798", + "timestamp": "2026-03-30T21:35:46.766941546", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } } } \ No newline at end of file From 3cba325d21f3bf2cee8a7dfffd3129ef69f0c9b2 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Tue, 31 Mar 2026 19:47:09 +0200 Subject: [PATCH 43/46] Update test snapshots --- .../local/scanpy/pca/tests/main.nf.test.snap | 10 +- tests/default.nf.test.snap | 170 +++++++++++- tests/main_pipeline_build.nf.test.snap | 251 +++++++++++++++++- tests/main_pipeline_extend.nf.test.snap | 173 +++++++++++- tests/main_pipeline_qc.nf.test.snap | 124 ++++++++- ...in_pipeline_reference_mapping.nf.test.snap | 173 +++++++++++- tests/main_pipeline_sub.nf.test.snap | 115 +++++++- 7 files changed, 984 insertions(+), 32 deletions(-) diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index e89f7585..7b025fb7 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,7 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" ], "h5ad": [ [ @@ -28,14 +28,14 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" ] } ], - "timestamp": "2026-03-30T10:39:25.66784", + "timestamp": "2026-03-31T18:48:09.035201716", "meta": { - "nf-test": "0.9.5", - "nextflow": "25.10.4" + "nf-test": "0.9.4", + "nextflow": "25.10.2" } }, "Should run without failures": { diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 7d1d425b..73710576 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -2,6 +2,18 @@ "-profile test": { "content": [ { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, "ADATA_READRDS": { "anndata": "0.11.1", "anndata2ri": "1.3.2", @@ -9,6 +21,9 @@ "pandas": "2.2.3", "seurat": "5.1.0" }, + "ADATA_TORDS": { + "anndataR": "1.0.2" + }, "ADATA_UNIFY": { "anndata": "0.12.10", "numpy": "2.3.5", @@ -20,12 +35,26 @@ "anndataR": "1.0.2", "celda": "1.26.0" }, + "CELLDEX_FETCHREFERENCE": { + "R": "R version 4.4.1 (2024-06-14)", + "celldex": "1.16.0", + "yaml": "2.3.10", + "SingleCellExperiment": "1.28.0", + "HDF5Array": "1.34.0" + }, "CELLTYPES_CELLTYPIST": { "python": "3.12.8", "pandas": "2.2.3", "scanpy": "1.10.4", "celltypist": "1.6.3" }, + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + }, "COLLECT_SIZES": { "pandas": "2.3.3", "python": "3.13.12" @@ -37,6 +66,17 @@ "python": "3.13.12", "upsetplot": "0.9.0" }, + "ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "FINALIZE_QC_ANNDATAS": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, "GET_DEDOUBLETED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" @@ -53,6 +93,14 @@ "python": "3.13.0", "anndata": "0.10.9" }, + "LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + }, "QC_FILTERED": { "matplotlib": "3.10.8", "python": "3.13.12", @@ -63,18 +111,57 @@ "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_BBKNN": { + "bbknn": "1.6.0", + "pandas": "2.3.3", + "python": "3.12.12", + "scanpy": "1.11.5" + }, "SCANPY_CELLCYCLE": { "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_COMBAT": { + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, "SCANPY_FILTER": { "python": "3.13.12", "scanpy": "1.12" }, + "SCANPY_HARMONY": { + "harmonypy": "0.2.0", + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_HVGS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, "SCANPY_SCRUBLET": { "python": "3.12.11", "scanpy": "1.11.2" }, + "SCVITOOLS_SCVI": { + "scvi": "1.3.3" + }, + "UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, "UPSET_GENES": { "anndata": "0.12.10", "matplotlib": "3.10.8", @@ -83,12 +170,87 @@ }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - } + }, + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" }, [ + "celltypes", + "celltypes/singler", + "celltypes/singler/SRR28679756_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679756_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679756_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679756_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679756_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_predictions.csv", + "celltypes/singler/SRR28679757_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679757_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679757_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679757_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679757_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_predictions.csv", + "celltypes/singler/SRR28679758_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679758_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679758_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679758_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679758_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_predictions.csv", + "cluster_dimred", + "cluster_dimred/bbknn", + "cluster_dimred/bbknn/entropy", + "cluster_dimred/bbknn/entropy/bbknn-global-0.5_entropy.png", + "cluster_dimred/bbknn/entropy/bbknn-global-1.0_entropy.png", + "cluster_dimred/bbknn/leiden", + "cluster_dimred/bbknn/leiden/bbknn-global-0.5_leiden.png", + "cluster_dimred/bbknn/leiden/bbknn-global-1.0_leiden.png", + "cluster_dimred/bbknn/umap", + "cluster_dimred/combat", + "cluster_dimred/combat/entropy", + "cluster_dimred/combat/entropy/combat-global-0.5_entropy.png", + "cluster_dimred/combat/entropy/combat-global-1.0_entropy.png", + "cluster_dimred/combat/leiden", + "cluster_dimred/combat/leiden/combat-global-0.5_leiden.png", + "cluster_dimred/combat/leiden/combat-global-1.0_leiden.png", + "cluster_dimred/combat/umap", + "cluster_dimred/harmony", + "cluster_dimred/harmony/entropy", + "cluster_dimred/harmony/entropy/harmony-global-0.5_entropy.png", + "cluster_dimred/harmony/entropy/harmony-global-1.0_entropy.png", + "cluster_dimred/harmony/leiden", + "cluster_dimred/harmony/leiden/harmony-global-0.5_leiden.png", + "cluster_dimred/harmony/leiden/harmony-global-1.0_leiden.png", + "cluster_dimred/harmony/umap", + "cluster_dimred/scvi", + "cluster_dimred/scvi/entropy", + "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", + "cluster_dimred/scvi/leiden", + "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", + "cluster_dimred/scvi/umap", "combine", + "combine/integrate", + "combine/integrate/scvi", + "combine/integrate/scvi/scvi_model", + "combine/integrate/scvi/scvi_model/model.pt", "combine/merge", "combine/merge/upset_genes.png", + "finalized", + "finalized/merged.h5ad", + "finalized/merged.rds", + "finalized/merged_metadata.csv", + "multiqc", + "per_group", "pipeline_info", "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", "quality_control", @@ -104,13 +266,13 @@ "quality_control/sizes/sizes.tsv" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T23:00:46.95358214", + "timestamp": "2026-03-31T19:29:42.315558141", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index 930dbd52..fd8f162d 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -2,6 +2,18 @@ "Should process data from scratch": { "content": [ { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, "ADATA_READRDS": { "anndata": "0.11.1", "anndata2ri": "1.3.2", @@ -9,6 +21,15 @@ "pandas": "2.2.3", "seurat": "5.1.0" }, + "ADATA_TORDS": { + "anndataR": "1.0.2" + }, + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + }, "CELDA_DECONTX": { "r": "4.5.3", "anndataR": "1.0.2", @@ -21,30 +42,250 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, + "CELLTYPES_CELLTYPIST": { + "python": "3.12.8", + "pandas": "2.2.3", + "scanpy": "1.10.4", + "celltypist": "1.6.3" + }, + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + }, + "COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + }, + "DOUBLET_REMOVAL": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "pandas": "2.3.3", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, + "ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "FINALIZE_QC_ANNDATAS": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "GET_DEDOUBLETED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "GET_THRESHOLDED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "QC_FILTERED": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, + "QC_RAW": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_BBKNN": { + "bbknn": "1.6.0", + "pandas": "2.3.3", + "python": "3.12.12", + "scanpy": "1.11.5" + }, + "SCANPY_CELLCYCLE": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_COMBAT": { + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_HARMONY": { + "harmonypy": "0.2.0", + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_HVGS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + }, + "SCVITOOLS_SCVI": { + "scvi": "1.3.3" + }, + "SEURAT_INTEGRATION": { + "R": "4.5.3", + "Seurat": "5.4.0", + "anndataR": "1.0.2" + }, + "UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "UPSET_GENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - } + }, + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" }, [ + "celltypes", + "celltypes/singler", + "celltypes/singler/SRR28679756_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679756_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679756_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679756_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679756_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_predictions.csv", + "celltypes/singler/SRR28679757_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679757_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679757_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679757_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679757_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_predictions.csv", + "celltypes/singler/SRR28679758_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679758_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679758_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679758_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679758_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_predictions.csv", + "cluster_dimred", + "cluster_dimred/bbknn", + "cluster_dimred/bbknn/entropy", + "cluster_dimred/bbknn/entropy/bbknn-global-0.5_entropy.png", + "cluster_dimred/bbknn/entropy/bbknn-global-1.0_entropy.png", + "cluster_dimred/bbknn/leiden", + "cluster_dimred/bbknn/leiden/bbknn-global-0.5_leiden.png", + "cluster_dimred/bbknn/leiden/bbknn-global-1.0_leiden.png", + "cluster_dimred/bbknn/umap", + "cluster_dimred/combat", + "cluster_dimred/combat/entropy", + "cluster_dimred/combat/entropy/combat-global-0.5_entropy.png", + "cluster_dimred/combat/entropy/combat-global-1.0_entropy.png", + "cluster_dimred/combat/leiden", + "cluster_dimred/combat/leiden/combat-global-0.5_leiden.png", + "cluster_dimred/combat/leiden/combat-global-1.0_leiden.png", + "cluster_dimred/combat/umap", + "cluster_dimred/harmony", + "cluster_dimred/harmony/entropy", + "cluster_dimred/harmony/entropy/harmony-global-0.5_entropy.png", + "cluster_dimred/harmony/entropy/harmony-global-1.0_entropy.png", + "cluster_dimred/harmony/leiden", + "cluster_dimred/harmony/leiden/harmony-global-0.5_leiden.png", + "cluster_dimred/harmony/leiden/harmony-global-1.0_leiden.png", + "cluster_dimred/harmony/umap", + "cluster_dimred/scvi", + "cluster_dimred/scvi/entropy", + "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", + "cluster_dimred/scvi/leiden", + "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", + "cluster_dimred/scvi/umap", + "cluster_dimred/seurat", + "cluster_dimred/seurat/entropy", + "cluster_dimred/seurat/entropy/seurat-global-0.5_entropy.png", + "cluster_dimred/seurat/entropy/seurat-global-1.0_entropy.png", + "cluster_dimred/seurat/leiden", + "cluster_dimred/seurat/leiden/seurat-global-0.5_leiden.png", + "cluster_dimred/seurat/leiden/seurat-global-1.0_leiden.png", + "cluster_dimred/seurat/umap", + "combine", + "combine/integrate", + "combine/integrate/scvi", + "combine/integrate/scvi/scvi_model", + "combine/integrate/scvi/scvi_model/model.pt", + "combine/merge", + "combine/merge/upset_genes.png", + "finalized", + "finalized/merged.h5ad", + "finalized/merged.rds", + "finalized/merged_metadata.csv", + "multiqc", + "per_group", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", + "quality_control", + "quality_control/qc_filtered", + "quality_control/qc_filtered/SRR28679756_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_filtered/SRR28679757_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_filtered/SRR28679758_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_raw", + "quality_control/qc_raw/SRR28679756_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_raw/SRR28679757_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_raw/SRR28679758_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/sizes", + "quality_control/sizes/sizes.tsv" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T21:34:24.960083679", + "timestamp": "2026-03-31T19:33:46.87700552", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_extend.nf.test.snap b/tests/main_pipeline_extend.nf.test.snap index 9ddd93b8..770e8c8e 100644 --- a/tests/main_pipeline_extend.nf.test.snap +++ b/tests/main_pipeline_extend.nf.test.snap @@ -2,6 +2,31 @@ "Should perform scvi reference extension": { "content": [ { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "ADATA_MERGEEMBEDDINGS": { + "anndata": "0.12.10", + "python": "3.13.12" + }, + "ADATA_TORDS": { + "anndataR": "1.0.2" + }, + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + }, "CELDA_DECONTX": { "r": "4.5.3", "anndataR": "1.0.2", @@ -14,30 +39,168 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, + "CELLTYPES_CELLTYPIST": { + "python": "3.12.8", + "pandas": "2.2.3", + "scanpy": "1.10.4", + "celltypist": "1.6.3" + }, + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + }, + "COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + }, + "DOUBLET_REMOVAL": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "pandas": "2.3.3", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, + "ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "FINALIZE_QC_ANNDATAS": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "GET_DEDOUBLETED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "GET_THRESHOLDED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "QC_FILTERED": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, + "QC_RAW": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_CELLCYCLE": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + }, + "SCVITOOLS_SCVI": { + "scvi": "1.3.3" + }, + "UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "UPSET_GENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - } + }, + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" }, [ + "celltypes", + "celltypes/singler", + "celltypes/singler/SRR28679759_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679759_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679759_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679759_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679759_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_predictions.csv", + "cluster_dimred", + "cluster_dimred/scvi", + "cluster_dimred/scvi/entropy", + "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", + "cluster_dimred/scvi/leiden", + "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", + "cluster_dimred/scvi/umap", + "combine", + "combine/integrate", + "combine/integrate/scvi", + "combine/integrate/scvi/scvi_model", + "combine/integrate/scvi/scvi_model/model.pt", + "combine/merge", + "finalized", + "finalized/merged.h5ad", + "finalized/merged.rds", + "finalized/merged_metadata.csv", + "multiqc", + "per_group", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", + "quality_control", + "quality_control/qc_filtered", + "quality_control/qc_filtered/SRR28679759_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_raw", + "quality_control/qc_raw/SRR28679759_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/sizes", + "quality_control/sizes/sizes.tsv" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T21:33:58.038700942", + "timestamp": "2026-03-31T19:27:24.64774367", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_qc.nf.test.snap b/tests/main_pipeline_qc.nf.test.snap index 9f4487ed..8899834e 100644 --- a/tests/main_pipeline_qc.nf.test.snap +++ b/tests/main_pipeline_qc.nf.test.snap @@ -9,6 +9,12 @@ "pandas": "2.2.3", "seurat": "5.1.0" }, + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + }, "CELDA_DECONTX": { "r": "4.5.3", "anndataR": "1.0.2", @@ -21,30 +27,140 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, + "CELLTYPES_CELLTYPIST": { + "python": "3.12.8", + "pandas": "2.2.3", + "scanpy": "1.10.4", + "celltypist": "1.6.3" + }, + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + }, + "COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + }, + "DOUBLET_REMOVAL": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "pandas": "2.3.3", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, + "FINALIZE_QC_ANNDATAS": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "GET_DEDOUBLETED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "GET_THRESHOLDED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "QC_FILTERED": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, + "QC_RAW": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_CELLCYCLE": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + }, + "UPSET_GENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" } }, [ + "celltypes", + "celltypes/singler", + "celltypes/singler/SRR28679756_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679756_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679756_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679756_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679756_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679756_singler_predictions.csv", + "celltypes/singler/SRR28679757_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679757_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679757_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679757_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679757_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679757_singler_predictions.csv", + "celltypes/singler/SRR28679758_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679758_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679758_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679758_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679758_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679758_singler_predictions.csv", + "combine", + "combine/merge", + "combine/merge/upset_genes.png", + "multiqc", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", + "quality_control", + "quality_control/qc_filtered", + "quality_control/qc_filtered/SRR28679756_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_filtered/SRR28679757_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_filtered/SRR28679758_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_raw", + "quality_control/qc_raw/SRR28679756_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_raw/SRR28679757_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_raw/SRR28679758_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/sizes", + "quality_control/sizes/sizes.tsv" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T21:34:25.526334913", + "timestamp": "2026-03-31T19:16:27.846620062", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_reference_mapping.nf.test.snap b/tests/main_pipeline_reference_mapping.nf.test.snap index 5e251de0..15610464 100644 --- a/tests/main_pipeline_reference_mapping.nf.test.snap +++ b/tests/main_pipeline_reference_mapping.nf.test.snap @@ -2,6 +2,27 @@ "Should perform scvi reference mapping": { "content": [ { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "ADATA_MERGE": { + "anndata": "0.12.10", + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "ADATA_TORDS": { + "anndataR": "1.0.2" + }, + "ADATA_UNIFY": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "python": "3.13.12", + "scipy": "1.17.1" + }, "CELDA_DECONTX": { "r": "4.5.3", "anndataR": "1.0.2", @@ -14,30 +35,172 @@ "SingleCellExperiment": "1.28.0", "HDF5Array": "1.34.0" }, + "CELLTYPES_CELLTYPIST": { + "python": "3.12.8", + "pandas": "2.2.3", + "scanpy": "1.10.4", + "celltypist": "1.6.3" + }, + "CELLTYPES_SINGLER": { + "R": "R version 4.5.3 (2026-03-11)", + "SingleR": "2.12.0", + "celldex": "1.20.0", + "anndataR": "1.0.2", + "ggplot2": "4.0.2" + }, + "COLLECT_SIZES": { + "pandas": "2.3.3", + "python": "3.13.12" + }, + "DOUBLET_REMOVAL": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "pandas": "2.3.3", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, + "ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "FINALIZE_QC_ANNDATAS": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "GET_DEDOUBLETED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_FILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "GET_THRESHOLDED_SIZE": { + "python": "3.13.0", + "anndata": "0.10.9" + }, "GET_UNFILTERED_SIZE": { "python": "3.13.0", "anndata": "0.10.9" }, + "LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "QC_FILTERED": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, + "QC_RAW": { + "matplotlib": "3.10.8", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_CELLCYCLE": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_FILTER": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_HVGS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_SCRUBLET": { + "python": "3.12.11", + "scanpy": "1.11.2" + }, + "SCVITOOLS_SCVI": { + "scvi": "1.3.3" + }, + "UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "UPSET_GENES": { + "anndata": "0.12.10", + "matplotlib": "3.10.8", + "python": "3.13.12", + "upsetplot": "0.9.0" + }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" - } + }, + "liana": "1.6.1", + "python": "3.12.12", + "scanpy": "1.11.5" }, [ + "celltypes", + "celltypes/singler", + "celltypes/singler/SRR28679759_singler_hpca_celldex_distribution.pdf", + "celltypes/singler/SRR28679759_singler_hpca_celldex_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_hpca_direct_distribution.pdf", + "celltypes/singler/SRR28679759_singler_hpca_direct_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_immune_celldex_distribution.pdf", + "celltypes/singler/SRR28679759_singler_immune_celldex_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_immune_direct_distribution.pdf", + "celltypes/singler/SRR28679759_singler_immune_direct_heatmap.pdf", + "celltypes/singler/SRR28679759_singler_predictions.csv", + "cluster_dimred", + "cluster_dimred/scvi", + "cluster_dimred/scvi/entropy", + "cluster_dimred/scvi/entropy/scvi-global-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-global-1.0_entropy.png", + "cluster_dimred/scvi/leiden", + "cluster_dimred/scvi/leiden/scvi-global-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-global-1.0_leiden.png", + "cluster_dimred/scvi/umap", + "combine", + "combine/integrate", + "combine/integrate/scvi", + "combine/integrate/scvi/scvi_model", + "combine/integrate/scvi/scvi_model/model.pt", + "combine/merge", + "finalized", + "finalized/merged.h5ad", + "finalized/merged.rds", + "finalized/merged_metadata.csv", + "multiqc", + "per_group", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", + "quality_control", + "quality_control/qc_filtered", + "quality_control/qc_filtered/SRR28679759_preprocessed_total_counts_vs_n_genes_by_counts.png", + "quality_control/qc_raw", + "quality_control/qc_raw/SRR28679759_raw_total_counts_vs_n_genes_by_counts.png", + "quality_control/sizes", + "quality_control/sizes/sizes.tsv" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T23:00:46.211628435", + "timestamp": "2026-03-31T19:23:28.911087783", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nextflow": "25.10.4" } } } \ No newline at end of file diff --git a/tests/main_pipeline_sub.nf.test.snap b/tests/main_pipeline_sub.nf.test.snap index 1a8e0c8d..73abfecf 100644 --- a/tests/main_pipeline_sub.nf.test.snap +++ b/tests/main_pipeline_sub.nf.test.snap @@ -2,6 +2,50 @@ "Should be able to perform subclustering": { "content": [ { + "ADATA_EXTEND": { + "anndata": "0.12.10", + "numpy": "2.3.5", + "pandas": "2.3.3", + "python": "3.13.12" + }, + "ADATA_SPLITEMBEDDINGS": { + "anndata": "0.12.10", + "python": "3.13.12" + }, + "ADATA_TORDS": { + "anndataR": "1.0.2" + }, + "ENTROPY": { + "python": "3.13.12", + "scanpy": "1.12", + "scipy": "1.17.1" + }, + "LEIDEN": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "NEIGHBORS": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_PAGA": { + "python": "3.13.12", + "scanpy": "1.12" + }, + "SCANPY_RANKGENESGROUPS": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, + "SPLITCOL": { + "anndata": "0.12.10", + "python": "3.13.12" + }, + "UMAP": { + "pandas": "2.3.3", + "python": "3.13.12", + "scanpy": "1.12" + }, "Workflow": { "nf-core/scdownstream": "v0.0.1dev" }, @@ -10,17 +54,80 @@ "scanpy": "1.11.5" }, [ + "adata", + "adata/combat.h5ad", + "adata/harmony.h5ad", + "adata/scvi.h5ad", + "cluster_dimred", + "cluster_dimred/combat", + "cluster_dimred/combat/entropy", + "cluster_dimred/combat/entropy/combat-SRR28679756-0.5_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679756-1.0_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679757-0.5_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679757-1.0_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679758-0.5_entropy.png", + "cluster_dimred/combat/entropy/combat-SRR28679758-1.0_entropy.png", + "cluster_dimred/combat/leiden", + "cluster_dimred/combat/leiden/combat-SRR28679756-0.5_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679756-1.0_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679757-0.5_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679757-1.0_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679758-0.5_leiden.png", + "cluster_dimred/combat/leiden/combat-SRR28679758-1.0_leiden.png", + "cluster_dimred/combat/umap", + "cluster_dimred/harmony", + "cluster_dimred/harmony/entropy", + "cluster_dimred/harmony/entropy/harmony-SRR28679756-0.5_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679756-1.0_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679757-0.5_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679757-1.0_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679758-0.5_entropy.png", + "cluster_dimred/harmony/entropy/harmony-SRR28679758-1.0_entropy.png", + "cluster_dimred/harmony/leiden", + "cluster_dimred/harmony/leiden/harmony-SRR28679756-0.5_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679756-1.0_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679757-0.5_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679757-1.0_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679758-0.5_leiden.png", + "cluster_dimred/harmony/leiden/harmony-SRR28679758-1.0_leiden.png", + "cluster_dimred/harmony/umap", + "cluster_dimred/scvi", + "cluster_dimred/scvi/entropy", + "cluster_dimred/scvi/entropy/scvi-SRR28679756-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679756-1.0_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679757-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679757-1.0_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679758-0.5_entropy.png", + "cluster_dimred/scvi/entropy/scvi-SRR28679758-1.0_entropy.png", + "cluster_dimred/scvi/leiden", + "cluster_dimred/scvi/leiden/scvi-SRR28679756-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679756-1.0_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679757-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679757-1.0_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679758-0.5_leiden.png", + "cluster_dimred/scvi/leiden/scvi-SRR28679758-1.0_leiden.png", + "cluster_dimred/scvi/umap", + "finalized", + "finalized/base.h5ad", + "finalized/base.rds", + "finalized/base_metadata.csv", + "multiqc", + "per_group", "pipeline_info", - "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml" + "pipeline_info/nf_core_scdownstream_software_mqc_versions.yml", + "splitcol", + "splitcol/SRR28679756.h5ad", + "splitcol/SRR28679757.h5ad", + "splitcol/SRR28679758.h5ad" ], [ - + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-30T21:35:46.766941546", + "timestamp": "2026-03-31T19:17:28.230563871", "meta": { "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nextflow": "25.10.4" } } } \ No newline at end of file From 38d3f46b16ca999169c1651506a41efeaa3692bc Mon Sep 17 00:00:00 2001 From: Erik Fasterius Date: Wed, 1 Apr 2026 12:56:48 +0200 Subject: [PATCH 44/46] Update snapshots --- modules/local/scanpy/pca/tests/main.nf.test.snap | 10 +++++----- tests/main_pipeline_build.nf.test.snap | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index 7b025fb7..0dcf85ca 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,7 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ], "h5ad": [ [ @@ -28,14 +28,14 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,dc1add0c140202bbbef205a9cc48e097" + "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" ] } ], - "timestamp": "2026-03-31T18:48:09.035201716", + "timestamp": "2026-04-01T08:50:27.684498", "meta": { - "nf-test": "0.9.4", - "nextflow": "25.10.2" + "nf-test": "0.9.5", + "nextflow": "25.10.4" } }, "Should run without failures": { diff --git a/tests/main_pipeline_build.nf.test.snap b/tests/main_pipeline_build.nf.test.snap index fd8f162d..53bdd5cb 100644 --- a/tests/main_pipeline_build.nf.test.snap +++ b/tests/main_pipeline_build.nf.test.snap @@ -282,9 +282,9 @@ "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f" ] ], - "timestamp": "2026-03-31T19:33:46.87700552", + "timestamp": "2026-04-01T12:30:18.209142", "meta": { - "nf-test": "0.9.4", + "nf-test": "0.9.5", "nextflow": "25.10.4" } } From 101ae657f13779871af634852b9b06948f177c47 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Wed, 1 Apr 2026 15:11:21 +0200 Subject: [PATCH 45/46] Align scanpy/pca stub with other scanpy stubs --- modules/local/scanpy/pca/main.nf | 10 +--------- modules/local/scanpy/pca/tests/main.nf.test.snap | 6 +++--- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/modules/local/scanpy/pca/main.nf b/modules/local/scanpy/pca/main.nf index cafe81ed..9a65610f 100644 --- a/modules/local/scanpy/pca/main.nf +++ b/modules/local/scanpy/pca/main.nf @@ -30,16 +30,8 @@ process SCANPY_PCA { stub: prefix = task.ext.prefix ?: "${meta.id}_pca" """ - export MPLCONFIGDIR=./tmp/mpl - export NUMBA_CACHE_DIR=./tmp/numba - touch ${prefix}.h5ad touch X_${prefix}.pkl - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - python: \$(python3 -c 'import platform; print(platform.python_version())') - scanpy: \$(python3 -c 'import scanpy; print(scanpy.__version__)') - END_VERSIONS + touch versions.yml """ } diff --git a/modules/local/scanpy/pca/tests/main.nf.test.snap b/modules/local/scanpy/pca/tests/main.nf.test.snap index 0dcf85ca..24fa90ab 100644 --- a/modules/local/scanpy/pca/tests/main.nf.test.snap +++ b/modules/local/scanpy/pca/tests/main.nf.test.snap @@ -14,7 +14,7 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "2": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ], "h5ad": [ [ @@ -28,11 +28,11 @@ "X_test_pca.pkl:md5,d41d8cd98f00b204e9800998ecf8427e" ], "versions": [ - "versions.yml:md5,85b9ff36f73e94f430edad4b394ba258" + "versions.yml:md5,d41d8cd98f00b204e9800998ecf8427e" ] } ], - "timestamp": "2026-04-01T08:50:27.684498", + "timestamp": "2026-04-01T15:10:58.212224761", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" From ce1cc399e41c9f318f81088bcbf70bdec237b514 Mon Sep 17 00:00:00 2001 From: Nico Trummer Date: Wed, 1 Apr 2026 20:55:47 +0200 Subject: [PATCH 46/46] Update reproducibility rule+docs --- .cursor/rules/nf-test-assertions.mdc | 64 ++++++----- docs/reproducibility.md | 157 +++++++++++++++------------ 2 files changed, 122 insertions(+), 99 deletions(-) diff --git a/.cursor/rules/nf-test-assertions.mdc b/.cursor/rules/nf-test-assertions.mdc index 330170ba..fc15e45b 100644 --- a/.cursor/rules/nf-test-assertions.mdc +++ b/.cursor/rules/nf-test-assertions.mdc @@ -8,18 +8,22 @@ alwaysApply: false ## Core principle -Never snapshot platform-sensitive data (h5ad file hashes, floating-point arrays). Instead, assert structural properties and snapshot only stable values. +Omit **platform-sensitive** content from snapshots when outputs are **non-deterministic** (randomised ML, unstable floats in matrices, live APIs): use **`structural`** snapshots (`versions` YAML + `adata.yaml`, no `process.out` MD5s). + +When a module is **deterministic** (see [`docs/reproducibility.md`](../docs/reproducibility.md)) and **emits H5AD**, **`hash`** snapshots **include** `process.out` file MD5s plus `adata.yaml` — that is intentional regression coverage, not “raw float arrays” in the snap. ## Assertion order — sequential, no `assertAll` All `then {}` blocks use **plain sequential `assert` statements** in this fixed order: -1. `def adata = anndata(...)` — parsed once, reused below (only when h5ad is used 2+ times) -2. `assert process.success` / `assert workflow.success` — bare, runs first so failures show the real error -3. **Field checks** — specific, readable assertions that fire before the snapshot (e.g. `assert "X_pca" in adata.obsm`) -4. `assert snapshot(...).match()` — comprehensive regression net, runs last +1. `assert process.success` / `assert workflow.success` — bare, so the real failure mode is visible before deeper checks +2. `def adata = anndata(...)` — when an output H5AD (or similar) is used in field checks or in `adata.yaml` inside `snapshot()`; extract once if referenced **2+** times +3. **Field checks** — specific assertions before the snapshot (e.g. `assert "X_pca" in adata.obsm`) +4. `assert snapshot(...).match()` — last + +**Why this order**: missing fields fail in step 3 with a short message; the snapshot is the final regression net. -**Why this order**: if the snapshot passes, the field checks would always pass too. But if a field is missing, the specific field assertion fires first with a clear message ("false" on `"X_pca" in adata.obsm`), instead of a verbose YAML diff. +If a test **must** open AnnData only after success and you keep `def adata` before `assert success` for historical reasons, treat **success before field checks and snapshot** as the hard rule when refactoring. **Never use `assertAll`** — it groups all failures into one report which makes CI output harder to read when a process fails. @@ -41,8 +45,8 @@ test("Should run without failures - stub") { ```groovy then { - def adata = anndata(process.out.h5ad[0][1]) assert process.success + def adata = anndata(process.out.h5ad[0][1]) assert "X_pca" in adata.obsm // field checks BEFORE snapshot assert "X_pca" in adata.uns assert snapshot( @@ -74,8 +78,8 @@ def adata = anndata(workflow.out.h5ad[0][1]) When asserting multiple properties of the same AnnData object, use `with(adata)`: ```groovy -def adata = anndata(process.out.h5ad[0][1]) assert process.success +def adata = anndata(process.out.h5ad[0][1]) with(adata) { assert "batch" in obs.colnames assert "label" in obs.colnames @@ -86,28 +90,36 @@ assert snapshot(process.out, path(process.out.versions[0]).yaml, adata.yaml).mat ## What to include in `snapshot()` -### Module tests +Strategy names are **identical** to [`docs/reproducibility.md`](../docs/reproducibility.md) → **Test strategy (this branch)**. The doc assigns each module/subworkflow to a strategy; this table is the **default `snapshot(...)` shape per strategy** (modules use `process.*`; subworkflows use `workflow.out.*` as in the examples below). + +### Module strategies — default snapshot contents -| Situation | What to snapshot | -|-----------|-----------------| -| Deterministic output (pure data transform) | `process.out, path(process.out.versions[0]).yaml, adata.yaml` | -| Non-deterministic output (ML, randomness) | `path(process.out.versions[0]).yaml, adata.yaml` (drop `process.out`) | -| No h5ad output | `process.out, path(process.out.versions[0]).yaml` | +| Strategy | Typical `snapshot(...)` arguments | +|----------|----------------------------------| +| `hash` | `process.out`, `path(process.out.versions[0]).yaml`, `adata.yaml` — module **emits H5AD** | +| `hash (no H5AD output)` | `process.out`, `path(process.out.versions[0]).yaml` — **no** `adata.yaml` | +| `hash + structural` | Same as **`hash`** (label in doc marks modules like `scanpy/filter` with multiple scenarios) | +| `structural` | `path(process.out.versions[0]).yaml`, `adata.yaml` — **omit** `process.out` | +| `column names` | e.g. `path(process.out.versions[0]).yaml`, `adata.obs.colnames` — **omit** `process.out` MD5s | +| `column names only` | Same as **`column names`** (shorthand in `docs/reproducibility.md` module tables only) | +| `obs CSV + file names` | Per module row in doc (obs artefacts + versions; not full H5AD hash) | +| `range assertion` | Imperative range checks **plus** the snapshot mix given in that doc row | +| `stub only` | No non-stub test; stub only: `snapshot(process.out).match()` | ### Subworkflow tests -For subworkflows with multiple `versions.yml` files, collect them as parsed YAML for readability: +Patterns vary by workflow. Use the **Subworkflows** table in `docs/reproducibility.md` as the source of truth. Common building blocks: ```groovy +// Versions as YAML (often + adata.yaml); omit full workflow.out when unstable assert snapshot( workflow.out.versions.collect { path(it).yaml }, adata.yaml ).match() ``` -Or for deterministic subworkflows: - ```groovy +// Deterministic outputs + versions + schema assert snapshot( workflow.out, workflow.out.versions.collect { path(it).yaml }, @@ -115,25 +127,19 @@ assert snapshot( ).match() ``` -## Deterministic vs non-deterministic modules - -See [`docs/reproducibility.md`](../docs/reproducibility.md) for the full classification of every module and subworkflow. The relevant column for tests is **"Test strategy (this branch)"**: +**Passthrough / unstaged H5AD paths:** `snapshot(workflow.out)` only — see later section. -| Strategy | Snapshot pattern | -|----------|-----------------| -| `hash` | `process.out, path(process.out.versions[0]).yaml, adata.yaml` | -| `structural` | drop `process.out`; keep `path(process.out.versions[0]).yaml, adata.yaml` | -| `stub only` | no non-stub test; stub uses `snapshot(process.out).match()` | +## Common mistake — dropping `process.out` from **`hash`** modules that emit H5AD -## Common mistake — do NOT drop `process.out` from `hash`-strategy modules +For modules whose strategy is **`hash`** (H5AD output) in `docs/reproducibility.md`, **`process.out` must stay** in the snapshot. -For modules classified as `hash` in `docs/reproducibility.md`, the original tests used exact MD5 hashes. That means `process.out` **must** remain in the snapshot. Only omit it for `structural`-strategy modules. +Do **not** apply this to **`structural`**, **`column names`**, **`hash (no H5AD output)`**, or other strategies that intentionally omit output MD5s. ```groovy -// ❌ WRONG — drops the full output snapshot for a deterministic module +// ❌ WRONG for strategy `hash` (H5AD) — drops output file hashes assert snapshot(path(process.out.versions[0]).yaml, adata.yaml).match() -// ✅ CORRECT for deterministic modules +// ✅ CORRECT for strategy `hash` (H5AD) assert snapshot(process.out, path(process.out.versions[0]).yaml, adata.yaml).match() ``` diff --git a/docs/reproducibility.md b/docs/reproducibility.md index 6a38a320..b94c984f 100644 --- a/docs/reproducibility.md +++ b/docs/reproducibility.md @@ -2,6 +2,8 @@ Classification of all local modules and subworkflows by output reproducibility. +**Paired docs:** Strategy labels in the **Test strategy (this branch)** column are the same vocabulary as [`.cursor/rules/nf-test-assertions.mdc`](../.cursor/rules/nf-test-assertions.mdc). This file is the **catalog** (every component + the exact snapshot story per row). That rule is the **how-to** (assertion order, stubs, `versions` channel, passthrough H5AD, common mistakes). + ## Legend | Level | Meaning | @@ -10,15 +12,30 @@ Classification of all local modules and subworkflows by output reproducibility. | **Seeded / quasi-deterministic** | A fixed random seed is set, but floating-point results (PCA coordinates, embeddings) can differ slightly across hardware, LAPACK/BLAS backends, or library versions. File hashes may differ between platforms even when logic is correct. | | **Non-deterministic** | Output varies between runs or platforms even with identical inputs — either due to unseeded stochasticity, iterative ML training, or live external API/download calls. | -The **Test strategy (this branch)** column describes what the tests on this branch actually assert: +The **Test strategy (this branch)** column describes what the tests on this branch actually assert. Default `snapshot(...)` contents for each strategy label are in [`.cursor/rules/nf-test-assertions.mdc`](../.cursor/rules/nf-test-assertions.mdc) under **Module strategies — default snapshot contents** (and **Subworkflow tests** there for shared patterns). + +### Module tests + +| Strategy | What is checked | +| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `hash` | Module **emits H5AD**: `process.out`, `path(process.out.versions[0]).yaml`, and `adata.yaml` (AnnData read from the staged output file). Field checks run before the snapshot. Only appropriate when outputs are **deterministic** (or you accept the risk on quasi-deterministic rows such as `scanpy/sample`). | +| `hash (no H5AD output)` | Module **does not emit H5AD** (e.g. RDS, PNG, MultiQC JSON, TSV). Tests snapshot **`process.out` + `path(process.out.versions[0]).yaml` only** — no `adata.yaml` (nothing to parse as AnnData). Same row in nf-test-assertions **Module strategies — default snapshot contents**. | +| `structural` | `path(process.out.versions[0]).yaml` and `adata.yaml`; **`process.out` file hashes omitted** so matrix floats and unstable binaries do not break CI. | +| `hash + structural` | Same snapshot shape as **`hash`** (outputs + versions YAML + `adata.yaml`); the label is kept for modules that also emphasize schema checks in the test name or have multiple scenarios (e.g. `scanpy/filter`). | +| `column names` | `versions.yml` as YAML plus **obs column names** (or similar) — **no** `process.out` file MD5s. Used where cell-level values are intentionally excluded from the snapshot (e.g. annotation scores) or may drift across R/package stacks. | +| `column names only` | Shorthand in tables: same idea as `column names`. | +| `obs CSV + file names` | SingleR tests snapshot **obs-related outputs** (e.g. CSV paths/names) plus versions — not a full H5AD hash. | +| `range assertion` | A numeric value (e.g. cluster count, cell count) is asserted **outside** or **alongside** the snapshot window. | +| `stub only` | No non-stub test; stub uses `snapshot(process.out).match()` only. | + +### Subworkflow tests + +| Strategy | What is checked | +| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `structural` | Typically `workflow.out.versions.collect { path(it).yaml }` and optionally `adata.yaml`, **`workflow.out` omitted** for unstable integration outputs. | +| `hash` | **Deterministic** workflows: often `snapshot(workflow.out)` **or** a deliberate subset (e.g. `workflow.out.h5ad`) **plus** collected versions as YAML and **`adata.yaml`** when the merged H5AD is read from the work directory. **Exact `snapshot(...)` arguments differ per subworkflow** — the **Subworkflows** table below is authoritative; nf-test-assertions links subworkflow authors here. | -| Strategy | What is checked | -| ----------------- | ------------------------------------------------------------------------------------------------------------------------- | -| `hash` | Full `snapshot(process.out)` — bit-identical file MD5 hashes. Only safe for deterministic modules. | -| `structural` | `adata.yaml` schema (obs/var column names, layer/obsm keys) and `versions.yml` content — no matrix values or file hashes. | -| `column names` | Only the names of obs columns are asserted, not their values. | -| `range assertion` | A numeric output (e.g. cluster count) is checked to fall within an expected range. | -| `stub only` | No non-stub test exists; only empty stub outputs are verified. | +**Passthrough outputs:** when workflow outputs still point at **unstaged** test-dataset paths, tests use `snapshot(workflow.out)` only and do **not** call `anndata(...).yaml` on those paths (see **Known nft-anndata limitation: passthrough h5ad files** in [`.cursor/rules/nf-test-assertions.mdc`](../.cursor/rules/nf-test-assertions.mdc)). --- @@ -26,22 +43,22 @@ The **Test strategy (this branch)** column describes what the tests on this bran ### `adata/` -| Module | Description | Reproducibility | Test strategy (this branch) | -| ----------------------- | -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------ | -| `adata/entropy` | Computes per-group normalised Shannon entropy of a categorical obs column and optionally plots it. | Fully deterministic | hash | -| `adata/extend` | Extends an AnnData object with additional obs/var/obsm/obsp/uns/layers data from pickle or CSV files. | Fully deterministic | hash | -| `adata/merge` | Concatenates multiple AnnData objects into inner (gene intersection) and outer (union) merged datasets. | Fully deterministic | hash | -| `adata/mergeembeddings` | Merges embeddings from a newly integrated AnnData back into the combined base+integrated AnnData by cell-index alignment. | Fully deterministic | hash | -| `adata/mygene` | Translates gene identifiers (Ensembl/Entrez/symbol) to HGNC symbols via the MyGene.info REST API. | **Non-deterministic** — live external API call; results depend on database state at query time. | ⚠️ hash — snapshots `process.out` despite the live API | -| `adata/prepcellxgene` | Prepares an AnnData object for CellxGene by renaming embedding keys and converting counts to log-normalised float32. | Fully deterministic | hash | -| `adata/readcsv` | Reads a CSV file and writes it as an AnnData H5AD. | Fully deterministic | hash | -| `adata/readrds` | Converts an RDS file (Seurat or SingleCellExperiment) to AnnData H5AD via anndata2ri/rpy2. | Fully deterministic | hash | -| `adata/setindex` | Sets a specified obs or var column as the new AnnData index. | Fully deterministic | hash | -| `adata/splitcol` | Splits an AnnData object into one H5AD file per unique value of a specified obs column. | Fully deterministic | hash | -| `adata/splitembeddings` | Splits multiple named embeddings from a single AnnData into separate H5AD files each containing `X_emb`. | Fully deterministic | hash | -| `adata/tords` | Converts an AnnData H5AD to an RDS SingleCellExperiment object using anndataR. | Fully deterministic | hash | -| `adata/unify` | Normalises gene symbols, resolves duplicates, unifies batch/label/condition columns, and prefixes barcodes with sample ID. | Fully deterministic | hash | -| `adata/upsetgenes` | Plots an UpSet diagram of gene set overlaps across multiple AnnData objects and outputs a MultiQC JSON image. | Fully deterministic | hash | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `adata/entropy` | Computes per-group normalised Shannon entropy of a categorical obs column and optionally plots it. | Fully deterministic | hash | +| `adata/extend` | Extends an AnnData object with additional obs/var/obsm/obsp/uns/layers data from pickle or CSV files. | Fully deterministic | hash | +| `adata/merge` | Concatenates multiple AnnData objects into inner (gene intersection) and outer (union) merged datasets. | Fully deterministic | hash | +| `adata/mergeembeddings` | Merges embeddings from a newly integrated AnnData back into the combined base+integrated AnnData by cell-index alignment. | Fully deterministic | hash | +| `adata/mygene` | Translates gene identifiers (Ensembl/Entrez/symbol) to HGNC symbols via the MyGene.info REST API. | **Non-deterministic** — live external API call; results depend on database state at query time. | ⚠️ **hash** (`process.out` + versions YAML + `adata.yaml`) — same shape as deterministic modules; **snapshots can drift** when the API response changes. | +| `adata/prepcellxgene` | Prepares an AnnData object for CellxGene by renaming embedding keys and converting counts to log-normalised float32. | Fully deterministic | hash | +| `adata/readcsv` | Reads a CSV file and writes it as an AnnData H5AD. | Fully deterministic | hash | +| `adata/readrds` | Converts an RDS file (Seurat or SingleCellExperiment) to AnnData H5AD via anndata2ri/rpy2. | Fully deterministic | hash | +| `adata/setindex` | Sets a specified obs or var column as the new AnnData index. | Fully deterministic | hash | +| `adata/splitcol` | Splits an AnnData object into one H5AD file per unique value of a specified obs column. | Fully deterministic | hash | +| `adata/splitembeddings` | Splits multiple named embeddings from a single AnnData into separate H5AD files each containing `X_emb`. | Fully deterministic | hash | +| `adata/tords` | Converts an AnnData H5AD to an RDS SingleCellExperiment object using anndataR. | Fully deterministic | hash (no H5AD output — `.rds` + versions) | +| `adata/unify` | Normalises gene symbols, resolves duplicates, unifies batch/label/condition columns, and prefixes barcodes with sample ID. | Fully deterministic | hash | +| `adata/upsetgenes` | Plots an UpSet diagram of gene set overlaps across multiple AnnData objects and outputs a MultiQC JSON image. | Fully deterministic | hash (no H5AD output — plot / MultiQC JSON + versions) | ### `celda/` @@ -57,23 +74,23 @@ The **Test strategy (this branch)** column describes what the tests on this bran ### `celltypes/` -| Module | Description | Reproducibility | Test strategy (this branch) | -| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------- | -| `celltypes/celltypist` | Annotates cell types using one or more CellTypist logistic regression models after normalising and log-transforming counts. | Fully deterministic — uses a fixed, pre-trained model with no stochastic inference at prediction time. | column names only | -| `celltypes/singler` | Assigns cell types using the SingleR correlation-based method against one or more celldex reference datasets. | Fully deterministic — correlation/label-transfer method with no randomness. | obs CSV + file names | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | +| `celltypes/celltypist` | Annotates cell types using one or more CellTypist logistic regression models after normalising and log-transforming counts. | Fully deterministic — uses a fixed, pre-trained model with no stochastic inference at prediction time. | column names — `path(process.out.versions[0]).yaml` + `adata.obs.colnames` (no `process.out` MD5s) | +| `celltypes/singler` | Assigns cell types using the SingleR correlation-based method against one or more celldex reference datasets. | Fully deterministic — correlation/label-transfer method with no randomness. | obs CSV + file names | ### `custom/` -| Module | Description | Reproducibility | Test strategy (this branch) | -| --------------------- | ------------------------------------------------------------------------------------------- | ------------------- | --------------------------- | -| `custom/collectsizes` | Pivots a TSV of per-sample cell counts at different QC stages into a MultiQC summary table. | Fully deterministic | hash | +| Module | Description | Reproducibility | Test strategy (this branch) | +| --------------------- | ------------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------------- | +| `custom/collectsizes` | Pivots a TSV of per-sample cell counts at different QC stages into a MultiQC summary table. | Fully deterministic | hash (no H5AD output — TSV / MultiQC JSON + versions) | ### `doublet_detection/` -| Module | Description | Reproducibility | Test strategy (this branch) | -| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------------- | -| `doublet_detection/doublet_removal` | Removes doublet cells from an AnnData object based on a threshold applied to aggregated doublet-caller predictions. | Fully deterministic | hash | -| `doublet_detection/scds` | Scores and calls doublets using bcds + cxds + hybrid (scds R package) with `set.seed(0)`. | Seeded / quasi-deterministic — seed is fixed, but internal boosting results may vary slightly across R/package versions. | column names only | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ | +| `doublet_detection/doublet_removal` | Removes doublet cells from an AnnData object based on a threshold applied to aggregated doublet-caller predictions. | Fully deterministic | hash | +| `doublet_detection/scds` | Scores and calls doublets using bcds + cxds + hybrid (scds R package) with `set.seed(0)`. | Seeded / quasi-deterministic — seed is fixed, but internal boosting results may vary slightly across R/package versions. | column names — `versions` YAML + obs column names; no `process.out` MD5s | ### `hugounifier/` @@ -90,23 +107,23 @@ The **Test strategy (this branch)** column describes what the tests on this bran ### `scanpy/` -| Module | Description | Reproducibility | Test strategy (this branch) | -| ------------------------ | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | structural — versions + schema only | -| `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | hash | -| `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | structural — versions + schema only | -| `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | hash + structural | -| `scanpy/harmony` | Runs Harmony batch integration after log-normalisation and PCA, storing the corrected embedding as `X_emb`. | **Non-deterministic** — Harmony is an iterative optimisation with no fixed seed; upstream PCA is also unseeded. | structural — versions + schema only; `variance_ratio` output removed | -| `scanpy/hvgs` | Selects highly variable genes and subsets the AnnData to those genes. | Seeded / quasi-deterministic — HVG variance statistics rely on NumPy/SciPy floating-point operations that can produce slightly different results across library versions. | structural — versions + schema only | -| `scanpy/leiden` | Performs Leiden community-detection clustering at a specified resolution. | **Non-deterministic** — Leiden uses random restarts with no fixed seed. | structural — range assertion on cluster count + versions + schema | -| `scanpy/neighbors` | Computes a k-nearest-neighbour graph on a specified embedding. | Fully deterministic given a fixed input embedding. | structural — versions + schema only | -| `scanpy/paga` | Computes PAGA coarse-grained cluster connectivity and saves a graph and plot. | Fully deterministic — PAGA is a deterministic graph-summarisation step given fixed Leiden labels. | hash | -| `scanpy/pca` | Runs PCA with `random_state=0` and stores the result under a specified key. | Seeded / quasi-deterministic — seed is fixed, but float coordinates can differ across LAPACK/MKL backends. | structural — versions + schema only | -| `scanpy/plotqc` | Calculates QC metrics and produces a counts-vs-genes scatter plot for MultiQC. | Fully deterministic | hash | -| `scanpy/rankgenesgroups` | Runs differential gene expression (rank genes groups) across clusters using a configurable statistical method. | **Seeded / quasi-deterministic** — wilcoxon and t-test are deterministic in theory, but tied-rank handling and floating-point tie-breaking can differ across SciPy versions. | structural — versions + schema only | -| `scanpy/readh5` | Reads a 10x Genomics HDF5 (`.h5`) file and writes it as an AnnData H5AD. | Fully deterministic | hash | -| `scanpy/sample` | Down-samples cells to a fixed count or fraction using `rng=0`. | Seeded / quasi-deterministic — seed is fixed, but sampled cell set may vary across NumPy versions. | hash | -| `scanpy/umap` | Computes a UMAP embedding from a pre-built neighbour graph using `random_state=0`. | Seeded / quasi-deterministic — seed is fixed, but float coordinates vary across umap-learn/numba versions. | structural — versions + schema only | +| Module | Description | Reproducibility | Test strategy (this branch) | +| ------------------------ | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| `scanpy/bbknn` | Constructs a batch-balanced k-nearest-neighbour graph (BBKNN) on a PCA embedding. | Fully deterministic — kNN construction is deterministic given the input embedding. | structural — versions + schema only | +| `scanpy/cellcycle` | Scores each cell for S-phase and G2M-phase activity and assigns a predicted cell cycle phase. | Fully deterministic | hash | +| `scanpy/combat` | Applies ComBat batch correction and then runs PCA, storing the result as `X_emb`. | Seeded / quasi-deterministic — ComBat is deterministic; downstream PCA floats may vary across LAPACK backends. | structural — versions + schema only | +| `scanpy/filter` | Filters cells and genes by count, gene, and mitochondrial percentage thresholds. | Fully deterministic | hash + structural — standard `hash` triple; multiple parameter scenarios | +| `scanpy/harmony` | Runs Harmony batch integration after log-normalisation and PCA, storing the corrected embedding as `X_emb`. | **Non-deterministic** — Harmony is an iterative optimisation with no fixed seed; upstream PCA is also unseeded. | structural — versions + schema only; `variance_ratio` output removed | +| `scanpy/hvgs` | Selects highly variable genes and subsets the AnnData to those genes. | Seeded / quasi-deterministic — HVG variance statistics rely on NumPy/SciPy floating-point operations that can produce slightly different results across library versions. | structural — versions + schema only | +| `scanpy/leiden` | Performs Leiden community-detection clustering at a specified resolution. | **Non-deterministic** — Leiden uses random restarts with no fixed seed. | structural — range assertion on cluster count + versions + schema | +| `scanpy/neighbors` | Computes a k-nearest-neighbour graph on a specified embedding. | Fully deterministic given a fixed input embedding. | structural — versions + schema only | +| `scanpy/paga` | Computes PAGA coarse-grained cluster connectivity and saves a graph and plot. | Fully deterministic — PAGA is a deterministic graph-summarisation step given fixed Leiden labels. | hash | +| `scanpy/pca` | Runs PCA with `random_state=0` and stores the result under a specified key. | Seeded / quasi-deterministic — seed is fixed, but float coordinates can differ across LAPACK/MKL backends. | structural — versions + schema only | +| `scanpy/plotqc` | Calculates QC metrics and produces a counts-vs-genes scatter plot for MultiQC. | Fully deterministic | hash (no H5AD output — PNG / MultiQC JSON + versions) | +| `scanpy/rankgenesgroups` | Runs differential gene expression (rank genes groups) across clusters using a configurable statistical method. | **Seeded / quasi-deterministic** — wilcoxon and t-test are deterministic in theory, but tied-rank handling and floating-point tie-breaking can differ across SciPy versions. | structural — versions + `adata.yaml`; one path with **empty h5ad** snapshots **versions only** | +| `scanpy/readh5` | Reads a 10x Genomics HDF5 (`.h5`) file and writes it as an AnnData H5AD. | Fully deterministic | hash | +| `scanpy/sample` | Down-samples cells to a fixed count or fraction using `rng=0`. | Seeded / quasi-deterministic — seed is fixed, but sampled cell set may vary across NumPy versions. | hash | +| `scanpy/umap` | Computes a UMAP embedding from a pre-built neighbour graph using `random_state=0`. | Seeded / quasi-deterministic — seed is fixed, but float coordinates vary across umap-learn/numba versions. | structural — versions + schema only | ### `scimilarity/` @@ -139,21 +156,21 @@ The **Test strategy (this branch)** column describes what the tests on this bran ## Subworkflows -| Subworkflow | Description | Reproducibility | Test strategy (this branch) | -| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | -| `ambient_correction` | Dispatches ambient RNA correction to decontX, SoupX, or none based on a parameter. | **Non-deterministic** for decontX (no seed) and SoupX (seeded clustering but variable results); fully deterministic for the `none` passthrough. | structural — versions + schema only | -| `celltype_assignment` | Orchestrates cell type annotation by running SingleR and/or CellTypist. | Fully deterministic — both methods are deterministic at inference time. | obs size only | -| `cluster` | Full clustering pipeline: neighbours → UMAP → Leiden at multiple resolutions → Shannon entropy. | Seeded / quasi-deterministic for UMAP; **non-deterministic** due to unseeded Leiden. | structural — versions only | -| `combine` | Merges all samples and runs all configured integration methods. | Inherits from constituent modules — ranges from fully deterministic (no integration) to seeded/quasi-deterministic (scVI, Harmony, Seurat). | structural — versions + schema only | -| `differential_expression` | Runs rank-genes-groups DE analysis across all combinations of clustering labels, conditions, and cell-type subsets. | Fully deterministic for the default wilcoxon/t-test methods. | structural — versions only | -| `doublet_detection` | Runs one or more doublet-detection methods (scds, solo, scrublet, doubletdetection) and removes called doublets. | **Non-deterministic** — solo, scrublet, and doubletdetection have stochastic components; scds is seeded. | structural + range assertion on cell count | -| `finalize` | Assembles the final AnnData by extending it with all collected obs/obsm/uns/layers outputs. | Fully deterministic | hash | -| `integrate` | Applies HVG selection then one or more integration methods (scVI, scANVI, Harmony, BBKNN, ComBat, Seurat, SCimilarity). | Seeded / quasi-deterministic for scVI/scANVI/ComBat/Seurat/BBKNN; **non-deterministic** for Harmony. | structural — versions + schema only | -| `load_h5ad` | Loads input files in H5AD, 10x H5, RDS, or CSV format and converts all to AnnData H5AD. | Fully deterministic | hash | -| `per_group` | Runs PAGA, LIANA rank-aggregate, and rank-genes DE per cluster. | **Seeded / quasi-deterministic** — inherits from constituent `liana/rankaggregate` and `scanpy/rankgenesgroups` modules. | structural — versions only | -| `pseudobulking` | Aggregates single-cell data into pseudobulk profiles grouped by specified metadata columns. | Fully deterministic | hash | -| `quality_control` | Full per-sample QC pipeline: empty droplet filtering, ambient correction, gene unification, cell/gene filtering, optional downsampling, doublet detection, and optional cell cycle scoring. | Seeded / quasi-deterministic to **non-deterministic** depending on configured ambient and doublet-detection methods. | structural — versions + multiqc files | -| `scimilarity` | Embeds cells into the SCimilarity pretrained latent space and annotates with cell type labels. | Fully deterministic — fixed pretrained model, inference-only. | stub only | -| `singler` | Downloads (or uses pre-provided) celldex reference datasets and runs SingleR annotation. | Fully deterministic for annotation; **non-deterministic** if downloading references at runtime via ExperimentHub. | hash | -| `unify` | Standardises gene symbols (optionally via MyGene.info and HUGO-unifier) and normalises metadata columns (batch, label, condition). | **Non-deterministic** when `symbol_col == "none"` (triggers MyGene.info API call); fully deterministic otherwise. | hash | -| `unify_genes` | Applies HUGO-unifier to compute and apply a cross-dataset gene symbol renaming table. | **Non-deterministic** — `hugounifier/get` uses a live HUGO API; results depend on database state at query time. | structural — versions + schema only | +| Subworkflow | Description | Reproducibility | Test strategy (this branch) | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ambient_correction` | Dispatches ambient RNA correction to decontX, SoupX, or none based on a parameter. | **Non-deterministic** for decontX (no seed) and SoupX (seeded clustering but variable results); fully deterministic for the `none` passthrough. | **Scenario-dependent:** often `versions` as YAML + `adata.yaml` when an H5AD is produced; **`none` / meta-disabled** paths may snapshot **only `versions` + `workflow.out.h5ad.size()`** (counts, not hashes). | +| `celltype_assignment` | Orchestrates cell type annotation by running SingleR and/or CellTypist. | Fully deterministic — both methods are deterministic at inference time. | **`workflow.out.versions` + `workflow.out.obs.size()`** — not a full obs-file MD5 snapshot. | +| `cluster` | Full clustering pipeline: neighbours → UMAP → Leiden at multiple resolutions → Shannon entropy. | Seeded / quasi-deterministic for UMAP; **non-deterministic** due to unseeded Leiden. | structural — **`workflow.out.versions` only** (each as YAML); graph / embedding presence asserted in code outside `snapshot`. | +| `combine` | Merges all samples and runs all configured integration methods. | Inherits from constituent modules — ranges from fully deterministic (no integration) to seeded/quasi-deterministic (scVI, Harmony, Seurat). | structural — **`workflow.out.versions` (YAML) + `adata.yaml`** on merged H5AD. | +| `differential_expression` | Runs rank-genes-groups DE analysis across all combinations of clustering labels, conditions, and cell-type subsets. | Fully deterministic for the default wilcoxon/t-test methods. | structural — **`workflow.out.versions` only** (YAML); DE / MultiQC presence asserted outside `snapshot` where needed. | +| `doublet_detection` | Runs one or more doublet-detection methods (scds, solo, scrublet, doubletdetection) and removes called doublets. | **Non-deterministic** — solo, scrublet, and doubletdetection have stochastic components; scds is seeded. | structural + **range assertion** on **`n_obs`**; snapshot uses **`versions` (YAML) + `adata.yaml`**. | +| `finalize` | Assembles the final AnnData by extending it with all collected obs/obsm/uns/layers outputs. | Fully deterministic | hash — **`workflow.out.h5ad` + `workflow.out.versions` (YAML) + `adata.yaml`** — not a bare `snapshot(workflow.out)` in non-stub tests. | +| `integrate` | Applies HVG selection then one or more integration methods (scVI, scANVI, Harmony, BBKNN, ComBat, Seurat, SCimilarity). | Seeded / quasi-deterministic for scVI/scANVI/ComBat/Seurat/BBKNN; **non-deterministic** for Harmony. | structural — **`workflow.out.versions` (YAML) + `adata.yaml`** on integration H5AD (e.g. Harmony / BBKNN / ComBat tests). | +| `load_h5ad` | Loads input files in H5AD, 10x H5, RDS, or CSV format and converts all to AnnData H5AD. | Fully deterministic | hash — **`snapshot(workflow.out)` only** (passthrough-safe; avoids `anndata().yaml` on unstaged inputs per nf-test rules). | +| `per_group` | Runs PAGA, LIANA rank-aggregate, and rank-genes DE per cluster. | **Seeded / quasi-deterministic** — inherits from constituent `liana/rankaggregate` and `scanpy/rankgenesgroups` modules. | structural — **`workflow.out.versions` only** (YAML). | +| `pseudobulking` | Aggregates single-cell data into pseudobulk profiles grouped by specified metadata columns. | Fully deterministic | hash — **`workflow.out` + `versions` (YAML) + `adata.yaml`** on pseudobulk H5AD. | +| `quality_control` | Full per-sample QC pipeline: empty droplet filtering, ambient correction, gene unification, cell/gene filtering, optional downsampling, doublet detection, and optional cell cycle scoring. | Seeded / quasi-deterministic to **non-deterministic** depending on configured ambient and doublet-detection methods. | structural — **`versions` (YAML) + `workflow.out.multiqc_files`**; **heavier paths** (e.g. ambient + doublet) also add **`adata.yaml` and/or `n_obs` / `n_vars`**. | +| `scimilarity` | Embeds cells into the SCimilarity pretrained latent space and annotates with cell type labels. | Fully deterministic — fixed pretrained model, inference-only. | stub only | +| `singler` | Downloads (or uses pre-provided) celldex reference datasets and runs SingleR annotation. | Fully deterministic for annotation; **non-deterministic** if downloading references at runtime via ExperimentHub. | hash — **`workflow.out.obs` + `versions` (YAML)** — **not** full `workflow.out` MD5s. | +| `unify` | Standardises gene symbols (optionally via MyGene.info and HUGO-unifier) and normalises metadata columns (batch, label, condition). | **Non-deterministic** when `symbol_col == "none"` (triggers MyGene.info API call); fully deterministic otherwise. | hash — **`workflow.out` + `adata.yaml`**. | +| `unify_genes` | Applies HUGO-unifier to compute and apply a cross-dataset gene symbol renaming table. | **Non-deterministic** — `hugounifier/get` uses a live HUGO API; results depend on database state at query time. | structural — **`workflow.out.versions` (YAML) + `adata.yaml`** (multi-sample tests may include two `adata.yaml`). |