diff --git a/CITATIONS.md b/CITATIONS.md index 495f4220..37967619 100644 --- a/CITATIONS.md +++ b/CITATIONS.md @@ -22,6 +22,24 @@ > Chklovski A, Parks DH, Woodcroft BJ, Tyson GW. CheckM2: a rapid, scalable and accurate tool for assessing microbial genome quality using machine learning. Nat Methods. 2023;20(8):1203-1212. doi: 10.1038/s41592-023-01940-w. PubMed PMID: 37500759; PubMed Central PMCID: not available. +- [EukCC](https://github.com/EBI-Metagenomics/EukCC) + +> Saary P, Mitchell AL, Finn RD. Estimating the quality of eukaryotic genomes recovered from metagenomic analysis with EukCC. Genome Biol. 2020;21(1):244. doi: 10.1186/s13059-020-02155-4. PubMed PMID: 32912302; PubMed Central PMCID: PMC7488429. + +- [MetaEuk](https://github.com/soedinglab/metaeuk) + +> Levy Karin E, Mirdita M, Söding J. MetaEuk-sensitive, high-throughput gene discovery, and annotation for large-scale eukaryotic metagenomics. Microbiome. 2020;8(1):48. doi: 10.1186/s40168-020-00808-x. PubMed PMID: 32245390; PubMed Central PMCID: PMC7126354. + +- [pplacer](https://matsen.fhcrc.org/pplacer/) + +> Matsen FA, Kodner RB, Armbrust EV. pplacer: linear time maximum-likelihood and Bayesian phylogenetic placement of sequences onto a fixed reference tree. BMC Bioinformatics. 2010;11:538. doi: 10.1186/1471-2105-11-538. PubMed PMID: 21034504; PubMed Central PMCID: PMC3098090. + +- [BUSCO](https://busco.ezlab.org) + +> Manni M, Berkeley MR, Seppey M, Simão FA, Zdobnov EM. BUSCO Update: Novel and Streamlined Workflows along with Broader and Deeper Phylogenetic Coverage for Scoring of Eukaryotic, Prokaryotic, and Viral Genomes. Mol Biol Evol. 2021;38(10):4647-4654. doi: 10.1093/molbev/msab199. PubMed PMID: 34320186; PubMed Central PMCID: PMC8476166. + +> Tegenfeldt F, Kuznetsov D, Manni M, Berkeley M, Zdobnov EM, Kriventseva EV. OrthoDB and BUSCO update: annotation of orthologs with wider sampling of genomes. Nucleic Acids Res. 2025;53(D1):D516-D522. doi: 10.1093/nar/gkae987. PubMed PMID: 39535043. + - [CAT and BAT](https://doi.org/10.1186/s13059-019-1817-x) > von Meijenfeldt FAB, Arkhipova K, Cambuy DD, Coutinho FH, Dutilh BE. Robust taxonomic classification of uncharted microbial sequences and bins with CAT and BAT. Genome Biol. 2019;20(1):217. doi: 10.1186/s13059-019-1817-x. PubMed PMID: 31640809; PubMed Central PMCID: PMC6805573. diff --git a/assets/schema_input_assembly.json b/assets/schema_input_assembly.json index a269c481..acd44fe0 100644 --- a/assets/schema_input_assembly.json +++ b/assets/schema_input_assembly.json @@ -97,7 +97,7 @@ "type": "string", "enum": ["metagenome", "metatranscriptome"], "errorMessage": "Assembly type should be metagenome or metatranscriptome", - "description": "Assembly type: metagenome or metatranscriptome. Written to the ENA manifest as ASSEMBLY_TYPE 'primary metagenome' or 'metatranscriptome'. Default: metagenome", + "description": "Assembly type: `metagenome` or `metatranscriptome`. Written to the ENA assembly manifest as ASSEMBLY_TYPE 'primary metagenome' (ENA docs: https://ena-docs.readthedocs.io/en/latest/submit/assembly/metagenome/primary.html) or 'metatranscriptome' (ENA docs: https://ena-docs.readthedocs.io/en/latest/submit/assembly/metatranscriptome.html) respectively. Default: `metagenome`.", "default": "metagenome", "meta": ["assembly_type"] } diff --git a/assets/schema_input_genome.json b/assets/schema_input_genome.json index 4a012224..9b7a379e 100644 --- a/assets/schema_input_genome.json +++ b/assets/schema_input_genome.json @@ -79,7 +79,7 @@ "stats_generation_software": { "type": "string", "default": null, - "description": "Tool, including version, that was used to calculate completeness and contamination, e.g. CheckM2_v1.0.0", + "description": "Tool, including version, that was used to calculate completeness and contamination, e.g. CheckM2_v1.0.0. Several tools are separated by `;`, e.g. busco_v6.1.0;eukcc_v2.2.0. If the pipeline runs additional tools for this genome, they are appended to the provided value.", "meta": ["stats_generation_software"] }, "completeness": { @@ -165,7 +165,7 @@ } ], "default": null, - "description": "Presence or absence of the 23S, 16S, and 5S rRNA genes and at least 18 tRNAs. This is used for MISAG/MIMAG assembly quality classification. Options: 'true' or 'false'", + "description": "Presence or absence of the 23S, 16S, and 5S rRNA genes (prokaryotes) or the 28S, 18S, 5.8S and 5S rRNA genes (eukaryotes) and at least 18 tRNAs. This is used for MISAG/MIMAG assembly quality classification. Options: true or false.", "meta": ["RNA_presence"] }, "NCBI_lineage": { diff --git a/bin/count_rna.py b/bin/count_rna.py index 8f340118..6af073c4 100755 --- a/bin/count_rna.py +++ b/bin/count_rna.py @@ -6,6 +6,7 @@ import argparse import logging +import re # Expected rRNA gene lengths @@ -18,6 +19,13 @@ "5_8S_rRNA": 155, } +# rRNA genes required per domain (gene names as reported by barrnap for each --kingdom) +REQUIRED_RRNA = { + "bac": ["16S_rRNA", "23S_rRNA", "5S_rRNA"], + "arc": ["16S_rRNA", "23S_rRNA", "5S_rRNA"], + "euk": ["18S_rRNA", "28S_rRNA", "5_8S_rRNA", "5S_rRNA"], +} + AA = [ "Ala", "Gly", @@ -41,14 +49,17 @@ "Trp", ] +TRNASCAN_REGEXP = r"^\s*(\S+)\s*:\s*(\d+)" + logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') def parse_args(): parser = argparse.ArgumentParser( description="Script parses tRNAscan-SE output and barrnap GFF output, and writes a decision " "of whether RNA genes are present in the genome. Decision is 'True' if number of tRNA genes " - "is at least --trna-limit and 16S, 23S, and 5S rRNA genes have more than --rrna-limit percentage " - "of gene length recovered, and 'False' otherwise." + "is at least --trna-limit and all rRNA genes required for --domain (16S, 23S and 5S for bac/arc; " + "18S, 28S, 5.8S and 5S for euk) have at least --rrna-limit percentage of gene length recovered, " + "and 'False' otherwise." ) parser.add_argument("-t", "--trna", dest="trna", help="trnas_stats.out from tRNAscan-SE", required=True) @@ -60,8 +71,10 @@ def parse_args(): default="rna_decision.tsv", required=False) parser.add_argument("--trna-limit", dest="trna_limit", help="Minimal required number of tRNA", required=True, type=int) - parser.add_argument("--rrna-limit", dest="rrna_limit", help="Minimum percentage of 16S, 23S, and 5S rRNA gene length recovered to count the gene as present.", - required=True, type=int) + parser.add_argument("--rrna-limit", dest="rrna_limit", help="Minimum percentage of rRNA gene length recovered to count the gene as present.", + required=True, type=float) + parser.add_argument("-d", "--domain", dest="domain", help="Taxonomic domain of the genome, defines which rRNA genes are required (default: bac)", + choices=sorted(REQUIRED_RRNA), default="bac", required=False) return parser.parse_args() @@ -87,18 +100,18 @@ def parse_trna(trna_input): if "Isotype / Anticodon" in line: start_parsing = True elif start_parsing: - cols = line.split() - if len(cols) > 1: - aa_pred = line.split()[0] - counts = int(line.split()[2]) - if aa_pred in AA: + match = re.match(TRNASCAN_REGEXP, line) + if match: + aa_pred = match.group(1) + counts = int(match.group(2)) + if any(i in aa_pred for i in AA): trnas += counts logging.info(f"Found {counts} tRNA genes for amino acid {aa_pred}") return trnas -def parse_rrna(rrna_input, rrna_limit): - """Parses barrnap GFF output and counts 16S, 23S, and 5S rRNA genes that have more than --rrna-limit percentage of gene length recovered. +def parse_rrna(rrna_input, rrna_limit, required_genes): + """Parses barrnap GFF output and counts required rRNA genes that have at least --rrna-limit percentage of gene length recovered. File example: ##gff-version 3 @@ -128,8 +141,7 @@ def parse_rrna(rrna_input, rrna_limit): break # Check if gene length meets the threshold - # For now we only consider bacterial/archaeal rRNA genes - if gene_name in ["16S_rRNA", "23S_rRNA", "5S_rRNA"]: + if gene_name in required_genes: expected_length = EXPECTED_LENGTHS[gene_name] percentage_recovered = (gene_length / expected_length) * 100 logging.info(f"Found {gene_name} with length {gene_length} bp, which is {percentage_recovered:.2f}% of expected length.") @@ -147,11 +159,13 @@ def main(): logging.info(f"Found {trna_count} tRNA in total") # parsing rRNA logging.info(f"Parsing rRNA genes from {args.rrna}") - rrna_count = parse_rrna(rrna_input=args.rrna, rrna_limit=args.rrna_limit) - logging.info(f"Found {rrna_count} rRNA subunit types in total") + required_genes = REQUIRED_RRNA[args.domain] + logging.info(f"Required rRNA genes for domain '{args.domain}': {', '.join(required_genes)}") + rrna_count = parse_rrna(rrna_input=args.rrna, rrna_limit=args.rrna_limit, required_genes=required_genes) + logging.info(f"Found {rrna_count} of {len(required_genes)} required rRNA subunit types") - # rrna_count should be 3 to make sure all 3 rRNA genes are present - decision = "True" if trna_count >= args.trna_limit and rrna_count == 3 else "False" + # all required rRNA genes must be present + decision = "True" if trna_count >= args.trna_limit and rrna_count == len(required_genes) else "False" logging.info(f"RNA presented: {decision}") with open(args.output, 'w') as file_out: diff --git a/conf/containers_conda_lock_files_amd64.config b/conf/containers_conda_lock_files_amd64.config index eb32fe50..9034d752 100644 --- a/conf/containers_conda_lock_files_amd64.config +++ b/conf/containers_conda_lock_files_amd64.config @@ -1 +1,2 @@ +process { withName: 'BUSCO_BUSCO' { container = 'modules/nf-core/busco/busco/.conda-lock/linux_amd64-bd-6d1f7006d91892b3_1.txt' } } process { withName: 'MULTIQC' { conda = 'modules/nf-core/multiqc/.conda-lock/linux_amd64-bd-c17fb751507e9dfc_1.txt' } } diff --git a/conf/containers_docker_amd64.config b/conf/containers_docker_amd64.config index ea18c3f9..7668fe46 100644 --- a/conf/containers_docker_amd64.config +++ b/conf/containers_docker_amd64.config @@ -1 +1,2 @@ +process { withName: 'BUSCO_BUSCO' { container = 'community.wave.seqera.io/library/busco:6.1.0--6d1f7006d91892b3' } } process { withName: 'MULTIQC' { container = 'community.wave.seqera.io/library/multiqc:1.35--c17fb751507e9dfc' } } diff --git a/conf/containers_singularity_https_amd64.config b/conf/containers_singularity_https_amd64.config index 932fc7c0..32547a00 100644 --- a/conf/containers_singularity_https_amd64.config +++ b/conf/containers_singularity_https_amd64.config @@ -1 +1,2 @@ +process { withName: 'BUSCO_BUSCO' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/96/963bad66c10646cf0adb1967cc462ad04d02789ddbfae4fbb94182291dbddf8c/data' } } process { withName: 'MULTIQC' { container = 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/c8/c8e346f4f6080eadf1253505e6ff09ef004454fc18e8d672006fd7b222cc412e/data' } } diff --git a/conf/containers_singularity_oras_amd64.config b/conf/containers_singularity_oras_amd64.config index 2fa065b3..c40dcf68 100644 --- a/conf/containers_singularity_oras_amd64.config +++ b/conf/containers_singularity_oras_amd64.config @@ -1 +1,2 @@ +process { withName: 'BUSCO_BUSCO' { container = 'oras://community.wave.seqera.io/library/busco:6.1.0--c7528d5825eb19b5' } } process { withName: 'MULTIQC' { container = 'oras://community.wave.seqera.io/library/multiqc:1.35--c680f2aea25ccec2' } } diff --git a/conf/modules.config b/conf/modules.config index c14d7f2c..8a91e843 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -43,6 +43,7 @@ process { } withName: 'CATPACK_BINS' { + ext.args = '--no_stars' publishDir = [ path: { "${params.outdir}/${params.mode}/${meta.id}/taxonomy" }, mode: params.publish_dir_mode, @@ -67,7 +68,7 @@ process { ] } - withName: 'RENAME_FASTA_FOR_CATPACK|CAT_DB_UNTAR' { + withName: 'RENAME_FASTA_FOR_CATPACK|CAT_DB_UNTAR|DB_UNTAR' { publishDir = [ enabled: false ] @@ -86,6 +87,7 @@ process { } withName: 'TRNASCANSE' { + ext.args = { [euk: '-E', arc: '-A', bac: '-B'].get(meta.domain, '-G') } publishDir = [ path: { "${params.outdir}/${params.mode}/${meta.id}/rna/trnascanse" }, mode: params.publish_dir_mode, @@ -103,6 +105,39 @@ process { // GENOME QUALITY ASSESSMENT SUBWORKFLOW // + withName: BUSCO_BUSCO { + tag = { "${meta.domain}-${meta.id}" } + ext.args = params.busco_db ? '--offline' : '' + publishDir = [ + [ + path: { "${params.outdir}/${params.mode}/${meta.id}/busco/${meta.domain}-${meta.id}" }, + mode: params.publish_dir_mode, + pattern: "*{.txt,.json,.log}", + ], + [ + path: { "${params.outdir}/${params.mode}/${meta.id}/busco" }, + mode: params.publish_dir_mode, + overwrite: false, + pattern: "busco_downloads/lineages/*", + enabled: params.save_busco_db, + ], + ] + } + + withName: 'EUKCC_SINGLE' { + publishDir = [ + path: { "${params.outdir}/${params.mode}/${meta.id}/eukcc" }, + mode: params.publish_dir_mode, + pattern: "*_eukcc_results/eukcc.tsv", + ] + } + + withName: 'GUNZIP_FASTA' { + publishDir = [ + enabled: false + ] + } + withName: 'CHECKM2_PREDICT' { publishDir = [ path: { "${params.outdir}/${params.mode}/${meta.id}/checkm2" }, diff --git a/conf/test.config b/conf/test.config index 93347675..7f0f987e 100644 --- a/conf/test.config +++ b/conf/test.config @@ -16,19 +16,22 @@ process { memory: '12.GB', time: '1.h' ] + + withName: 'REGISTERSTUDY|SUBMIT|CREATE_MANIFESTS' { + ext.when = false + } } params { config_profile_name = 'Test profile for minimal pipeline test' - config_profile_description = 'Runs --mode mags with multiple mags and missing metadata' + config_profile_description = 'Runs --mode mags with multiple mags and missing metadata. Test skips all modules using ENA queries.' // Input data input = params.pipelines_testdata_base_path + 'seqsubmit/samplesheets/mag_multiple_bins_missing_metadata.csv' outdir = 'test_output' mode = "mags" - submission_study = null - study_metadata = params.pipelines_testdata_base_path + 'seqsubmit/test_data/study_metadata/study_metadata.json' + submission_study = "TEST_STUDY" centre_name = "TEST_CENTER" test_upload = true diff --git a/conf/test_full.config b/conf/test_full.config index b7278aa6..6ad1895a 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -9,6 +9,11 @@ ---------------------------------------------------------------------------------------- */ +process { + withName: 'REGISTERSTUDY|SUBMIT|CREATE_MANIFESTS' { + ext.when = false + } +} params { config_profile_name = 'Full test profile' @@ -19,8 +24,7 @@ params { outdir = 'test_output' mode = "mags" - submission_study = null - study_metadata = params.pipelines_testdata_base_path + 'seqsubmit/test_data/study_metadata/study_metadata.json' + submission_study = "TEST_STUDY" centre_name = "TEST_CENTER" test_upload = true diff --git a/conf/test_mag_complete_metadata.config b/conf/test_mag_complete_metadata.config index 4a1689e5..b4fcbfcb 100644 --- a/conf/test_mag_complete_metadata.config +++ b/conf/test_mag_complete_metadata.config @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/seqsubmit -profile test, --outdir + nextflow run nf-core/seqsubmit -profile test_mag_complete_metadata, --outdir ---------------------------------------------------------------------------------------- */ diff --git a/conf/test_mag_complete_metadata_existing_study.conf b/conf/test_mag_complete_metadata_existing_study.conf index edfba5a8..f18ebe5d 100644 --- a/conf/test_mag_complete_metadata_existing_study.conf +++ b/conf/test_mag_complete_metadata_existing_study.conf @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/seqsubmit -profile test, --outdir + nextflow run nf-core/seqsubmit -profile test_mag_complete_metadata_existing_study, --outdir ---------------------------------------------------------------------------------------- */ diff --git a/conf/test_mag_no_taxonomy.conf b/conf/test_mag_missing_metadata.config similarity index 82% rename from conf/test_mag_no_taxonomy.conf rename to conf/test_mag_missing_metadata.config index 3fea8048..8c335090 100644 --- a/conf/test_mag_no_taxonomy.conf +++ b/conf/test_mag_missing_metadata.config @@ -19,11 +19,11 @@ process { } params { - config_profile_name = 'Test --mode mags no_taxonomy profile' - config_profile_description = 'Single-case MAG test with missing NCBI_lineage value' + config_profile_name = 'Test profile for minimal pipeline test' + config_profile_description = 'Runs --mode mags with multiple mags and missing metadata with ENA test upload' // Input data - input = params.pipelines_testdata_base_path + 'seqsubmit/samplesheets/mag_no_taxonomy.csv' + input = params.pipelines_testdata_base_path + 'seqsubmit/samplesheets/mag_multiple_bins_missing_metadata.csv' outdir = 'test_output' mode = "mags" diff --git a/conf/test_mag_no_coverage_paired_reads.conf b/conf/test_mag_no_coverage_pe_skip_ena_queries.conf similarity index 75% rename from conf/test_mag_no_coverage_paired_reads.conf rename to conf/test_mag_no_coverage_pe_skip_ena_queries.conf index 920e9263..69d737c0 100644 --- a/conf/test_mag_no_coverage_paired_reads.conf +++ b/conf/test_mag_no_coverage_pe_skip_ena_queries.conf @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/seqsubmit -profile test, --outdir + nextflow run nf-core/seqsubmit -profile test_mag_no_coverage_pe_skip_ena_queries, --outdir ---------------------------------------------------------------------------------------- */ @@ -16,19 +16,22 @@ process { memory: '12.GB', time: '1.h' ] + + withName: 'REGISTERSTUDY|SUBMIT|CREATE_MANIFESTS' { + ext.when = false + } } params { config_profile_name = 'Test --mode mags no_coverage_paired_reads profile' - config_profile_description = 'Single-case MAG test with missing genome_coverage and paired-end reads' + config_profile_description = 'Single-case MAG test with missing genome_coverage and paired-end reads. Test skips all modules using ENA queries.' // Input data input = params.pipelines_testdata_base_path + 'seqsubmit/samplesheets/mag_no_coverage_paired_reads.csv' outdir = 'test_output' mode = "mags" - submission_study = null - study_metadata = params.pipelines_testdata_base_path + 'seqsubmit/test_data/study_metadata/study_metadata.json' + submission_study = "TEST_STUDY" centre_name = "TEST_CENTER" test_upload = true diff --git a/conf/test_mag_no_coverage_single_reads.conf b/conf/test_mag_no_coverage_se_skip_ena_queries.conf similarity index 75% rename from conf/test_mag_no_coverage_single_reads.conf rename to conf/test_mag_no_coverage_se_skip_ena_queries.conf index ebbc5ce3..d3e2982c 100644 --- a/conf/test_mag_no_coverage_single_reads.conf +++ b/conf/test_mag_no_coverage_se_skip_ena_queries.conf @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/seqsubmit -profile test, --outdir + nextflow run nf-core/seqsubmit -profile test_mag_no_coverage_se_skip_ena_queries, --outdir ---------------------------------------------------------------------------------------- */ @@ -16,19 +16,22 @@ process { memory: '12.GB', time: '1.h' ] + + withName: 'REGISTERSTUDY|SUBMIT|CREATE_MANIFESTS' { + ext.when = false + } } params { config_profile_name = 'Test --mode mags no_coverage_single_reads profile' - config_profile_description = 'Single-case MAG test with missing genome_coverage and single-end reads' + config_profile_description = 'Single-case MAG test with missing genome_coverage and single-end reads. Test skips all modules using ENA queries.' // Input data input = params.pipelines_testdata_base_path + 'seqsubmit/samplesheets/mag_no_coverage_single_reads.csv' outdir = 'test_output' mode = "mags" - submission_study = null - study_metadata = params.pipelines_testdata_base_path + 'seqsubmit/test_data/study_metadata/study_metadata.json' + submission_study = "TEST_STUDY" centre_name = "TEST_CENTER" test_upload = true diff --git a/conf/test_mag_no_quality.conf b/conf/test_mag_no_quality.conf index 4b8e12ce..f6a43e1b 100644 --- a/conf/test_mag_no_quality.conf +++ b/conf/test_mag_no_quality.conf @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/seqsubmit -profile test, --outdir + nextflow run nf-core/seqsubmit -profile test_mag_no_quality, --outdir ---------------------------------------------------------------------------------------- */ diff --git a/conf/test_mag_no_quality_euk_skip_ena_queries.conf b/conf/test_mag_no_quality_euk_skip_ena_queries.conf new file mode 100644 index 00000000..880aca62 --- /dev/null +++ b/conf/test_mag_no_quality_euk_skip_ena_queries.conf @@ -0,0 +1,45 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running minimal tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a fast and simple pipeline test. + + Use as follows: + nextflow run nf-core/seqsubmit -profile test_mag_no_quality_euk_skip_ena_queries, --outdir + +---------------------------------------------------------------------------------------- +*/ + +process { + resourceLimits = [ + cpus: 2, + memory: '12.GB', + time: '1.h' + ] + + withName: 'EUKCC_SINGLE' { + ext.args = '--clade fungi --simple' + } + + withName: 'REGISTERSTUDY|SUBMIT|CREATE_MANIFESTS' { + ext.when = false + } +} + +params { + config_profile_name = 'Test --mode mags no_quality profile' + config_profile_description = 'Single-case eukaryotic MAG test with missing completeness and contamination values. Test skips all modules using ENA queries.' + + // Input data + input = params.pipelines_testdata_base_path + 'seqsubmit/samplesheets/mag_no_quality_euk.csv' + + mode = "mags" + submission_study = "TEST_STUDY" + centre_name = "TEST_CENTER" + + test_upload = true + + // Using fungi DB only from EukCC + eukcc_db = 'https://ftp.ebi.ac.uk/pub/databases/metagenomics/eukcc/eukcc2_db_tiny_fungi_test.tar.gz' + +} diff --git a/conf/test_mag_no_rna_presence.conf b/conf/test_mag_no_rna_skip_ena_queries.conf similarity index 75% rename from conf/test_mag_no_rna_presence.conf rename to conf/test_mag_no_rna_skip_ena_queries.conf index d9d29909..6a6df87f 100644 --- a/conf/test_mag_no_rna_presence.conf +++ b/conf/test_mag_no_rna_skip_ena_queries.conf @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/seqsubmit -profile test, --outdir + nextflow run nf-core/seqsubmit -profile test_mag_no_rna_skip_ena_queries, --outdir ---------------------------------------------------------------------------------------- */ @@ -16,11 +16,15 @@ process { memory: '12.GB', time: '1.h' ] + + withName: 'REGISTERSTUDY|SUBMIT|CREATE_MANIFESTS' { + ext.when = false + } } params { - config_profile_name = 'Test --mode mags no_rna_presence profile' - config_profile_description = 'Single-case MAG test with missing RNA_presence value' + config_profile_name = 'Test --mode mags no_rna profile' + config_profile_description = 'Single-case MAG test with missing RNA_presence value. Test skips all modules using ENA queries.' // Input data input = params.pipelines_testdata_base_path + 'seqsubmit/samplesheets/mag_no_rna_presence.csv' diff --git a/conf/test_mag_no_taxonomy_skip_ena_queries.conf b/conf/test_mag_no_taxonomy_skip_ena_queries.conf new file mode 100644 index 00000000..1f359745 --- /dev/null +++ b/conf/test_mag_no_taxonomy_skip_ena_queries.conf @@ -0,0 +1,41 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running minimal tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a fast and simple pipeline test. + + Use as follows: + nextflow run nf-core/seqsubmit -profile test_mag_no_taxonomy_skip_ena_queries, --outdir + +---------------------------------------------------------------------------------------- +*/ + +process { + resourceLimits = [ + cpus: 2, + memory: '12.GB', + time: '1.h' + ] + + withName: 'REGISTERSTUDY|SUBMIT|CREATE_MANIFESTS' { + ext.when = false + } +} + +params { + config_profile_name = 'Test --mode mags no_taxonomy profile' + config_profile_description = 'Single-case MAG test with missing NCBI_lineage value. Test skips all modules using ENA queries.' + + // Input data + input = params.pipelines_testdata_base_path + 'seqsubmit/samplesheets/mag_no_taxonomy.csv' + outdir = 'test_output' + + mode = "mags" + submission_study = "TEST_STUDY" + centre_name = "TEST_CENTER" + + test_upload = true + + cat_db = params.pipelines_testdata_base_path + 'seqsubmit/test_data/small_cat_db/tax-db.tar.gz' + checkm2_db = null +} diff --git a/conf/test_mag_one_contig.conf b/conf/test_mag_one_contig_skip_ena_queries.conf similarity index 72% rename from conf/test_mag_one_contig.conf rename to conf/test_mag_one_contig_skip_ena_queries.conf index 06ec0ec1..9b06fc01 100644 --- a/conf/test_mag_one_contig.conf +++ b/conf/test_mag_one_contig_skip_ena_queries.conf @@ -5,7 +5,7 @@ Defines input files and everything required to run a fast and simple pipeline test. Use as follows: - nextflow run nf-core/seqsubmit -profile test, --outdir + nextflow run nf-core/seqsubmit -profile test_mag_one_contig_skip_ena_queries, --outdir ---------------------------------------------------------------------------------------- */ @@ -16,19 +16,22 @@ process { memory: '12.GB', time: '1.h' ] + + withName: 'REGISTERSTUDY|SUBMIT|CREATE_MANIFESTS' { + ext.when = false + } } params { config_profile_name = 'Test --mode mags one_contig profile' - config_profile_description = 'Single-case MAG test with one contig assembly' + config_profile_description = 'Single-case MAG test with one contig assembly. No submission performed, invalid_fastas.tsv file generated. Test skips all modules using ENA queries.' // Input data input = params.pipelines_testdata_base_path + 'seqsubmit/samplesheets/mag_one_contig.csv' outdir = 'test_output' mode = "mags" - submission_study = null - study_metadata = params.pipelines_testdata_base_path + 'seqsubmit/test_data/study_metadata/study_metadata.json' + submission_study = "TEST_STUDY" centre_name = "TEST_CENTER" test_upload = true diff --git a/docs/methods.md b/docs/methods.md index 1504fa1e..0cc5ca5a 100644 --- a/docs/methods.md +++ b/docs/methods.md @@ -42,10 +42,12 @@ The `GENOMESUBMIT` workflow: 1. Reads the samplesheet and associated genome FASTA files. 2. Validates genome FASTA files. -3. Reuses provided or calculates missing values for tRNA and rRNA genes presence, coverage, taxonomy, and genome quality metrics. -4. Collects genome metadata into the tabular format required by `genome_uploader`. -5. Generates submission manifests for ENA. -6. Performs submission to ENA. +3. Reuses provided or calculates missing values for coverage and taxonomy. +4. Assigns the domain of each genome (bacteria, archaea or eukaryote) from its taxonomy. +5. Reuses provided or calculates missing values for tRNA and rRNA genes presence and genome quality metrics, using domain-specific tools and settings. +6. Collects genome metadata into the tabular format required by `genome_uploader`. +7. Generates submission manifests for ENA. +8. Performs submission to ENA. ### Genome FASTA validation @@ -53,6 +55,30 @@ Genome FASTA files are validated with the `fa-lint` before downstream processing Only FASTA files that pass validation are retained for downstream processing and submission. +### Genome coverage calculation + +Entries that already contain `genome_coverage` are passed through unchanged. For entries where coverage is missing, the workflow joins validated FASTA files with their associated read files and runs `coverm genome` through the `COVERM_GENOME` module (single-end or paired-end mode is selected from sample metadata). + +Genome coverage values from `coverm genome` output TSV are parsed and merged into submission metadata. + +### Taxonomy assignment + +If `NCBI_lineage` is already present in the input samplesheet, the value is retained. If it is missing, the workflow runs taxonomy classification using the `CAT_pack` tool. + +Before classification, input FASTA files are normalized to a `.fasta` suffix by `RENAME_FASTA_FOR_CATPACK`. Classification is then run in bin mode (`CAT_pack bins`, followed by `CAT_pack add_names`). + +Database input is taken from `--cat_db` when provided; otherwise the workflow builds CAT_pack database from NCBI non-redundant protein database (`nr`). See [CAT_pack documentation](https://github.com/MGXlab/CAT_pack#downloading-preconstructed-database-files). There are two options available: `nr` - NCBI non-redundant protein database and `gtdb` (Genome Taxonomy Database (GTDB) proteins). We use NCBI proteins because ENA supports only NCBI format of taxonomy for submission. The resulting classification table is parsed, and the lineage field is written to `NCBI_lineage`. + +### Domain assignment + +After taxonomy assignment, the workflow decides the domain of each genome from `NCBI_lineage`, which is either provided in the samplesheet or assigned by `CAT_pack`: + +- `euk` (eukaryote) if the lineage contains `Eukaryota` or the NCBI taxonomy ID `2759` +- `arc` (archaea) if the lineage contains `Archaea` or the NCBI taxonomy ID `2157` +- `bac` (bacteria) otherwise + +The domain defines which tools and settings are used for tRNA and rRNA genes detection and for completeness and contamination assessment. + ### tRNA and rRNA genes detection The workflow only runs tRNA and rRNA genes detection for entries where the `RNA_presence` column is empty. If a value is already supplied in the samplesheet, that value is passed through unchanged. @@ -65,11 +91,16 @@ tRNA and rRNA genes detection is implemented through the `RNA_DETECTION` subwork - `tRNAscan-SE` for tRNA prediction - the custom `count_rna.py` script for the final decision +All three steps use the domain assigned to the genome (see [Domain assignment](#domain-assignment)). + #### rRNA detection -`barrnap` is run in bacterial mode (`"bac"`). +`barrnap` is run with `--kingdom` matching the domain of the genome: `bac`, `arc` or `euk`. + +The custom parser then scans the GFF output and keeps only the rRNA subunits required for the domain: -The custom parser then scans the GFF output and keeps only the following rRNA subunits: `16S_rRNA`, `23S_rRNA`, `5S_rRNA`. +- bacteria and archaea: `16S_rRNA`, `23S_rRNA`, `5S_rRNA` +- eukaryotes: `18S_rRNA`, `28S_rRNA`, `5_8S_rRNA`, `5S_rRNA` For each detected feature, the recovered length is calculated as: @@ -82,6 +113,9 @@ The recovered proportion of each subunit is then estimated relative to the expec - `16S_rRNA`: 1450 bp - `23S_rRNA`: 2800 bp - `5S_rRNA`: 115 bp +- `18S_rRNA`: 1800 bp +- `28S_rRNA`: 4500 bp +- `5_8S_rRNA`: 155 bp $$ \text{recovery percent} = \frac{\text{recovered length}}{\text{expected length}} \times 100 @@ -93,7 +127,7 @@ A subunit is considered present when its best recovered percentage is greater th #### tRNA detection -`tRNAscan-SE` produces a statistics report that is parsed by `count_rna.py`. +`tRNAscan-SE` is run in the search mode matching the domain of the genome: `-B` (bacteria), `-A` (archaea) or `-E` (eukaryotes). It produces a statistics report that is parsed by `count_rna.py`. The parser sums the counts assigned to the 20 standard amino-acid isotypes: @@ -108,29 +142,36 @@ The total number of predicted tRNAs is compared against `params.trna_limit`. The The final decision stored in `RNA_presence` is: -- `True` when at least 18 tRNAs are detected and all three required rRNA subunits pass the recovery threshold +- `True` when at least 18 tRNAs are detected and all rRNA subunits required for the domain pass the recovery threshold - `False` otherwise The final `True`/`False` decision is then merged back into the submission metadata. -### Genome coverage calculation +### Completeness and contamination assessment -Entries that already contain `genome_coverage` are passed through unchanged. For entries where coverage is missing, the workflow joins validated FASTA files with their associated read files and runs `coverm genome` through the `COVERM_GENOME` module (single-end or paired-end mode is selected from sample metadata). +Completeness and contamination are evaluated in a genome quality step split by domain: prokaryotic genomes go to the `PROKARYOTIC_GENOME_EVALUATION` subworkflow and eukaryotic genomes to the `EUKARYOTIC_GENOME_EVALUATION` subworkflow. -Genome coverage values from `coverm genome` output TSV are parsed and merged into submission metadata. +The workflow checks three samplesheet fields: `completeness`, `contamination`, and `stats_generation_software`. If all three are already present, those values are reused. If any of them is missing, the genome is analysed with a tool selected by its domain. -### Taxonomy assignment +#### Prokaryotes (bacteria and archaea) -If `NCBI_lineage` is already present in the input samplesheet, the value is retained. If it is missing, the workflow runs taxonomy classification using the `CAT_pack` tool. +Prokaryotic genomes are analysed with `CheckM2 predict`. If `--checkm2_db` is supplied and exists, that database is used directly. Otherwise, the workflow downloads a CheckM2 database from Zenodo (using `--checkm2_db_download_id`) and then runs prediction. The database is downloaded only if there is at least one prokaryotic genome to analyse. -Before classification, input FASTA files are normalized to a `.fasta` suffix by `RENAME_FASTA_FOR_CATPACK`. Classification is then run in bin mode (`CAT_pack bins`, followed by `CAT_pack add_names`). +Completeness and contamination are extracted from the generated quality report (`quality_report.tsv`). -Database input is taken from `--cat_db` when provided; otherwise the workflow builds CAT_pack database from NCBI non-redundant protein database (`nr`). See [CAT_pack documentation](https://github.com/MGXlab/CAT_pack#downloading-preconstructed-database-files). There are two options available: `nr` - NCBI non-redundant protein database and `gtdb` (Genome Taxonomy Database (GTDB) proteins). We use NCBI proteins because ENA supports only NCBI format of taxonomy for submission. The resulting classification table is parsed, and the lineage field is written to `NCBI_lineage`. +#### Eukaryotes -### Completeness and contamination assessment +Eukaryotic genomes are analysed with [EukCC](https://github.com/EBI-Metagenomics/EukCC) and, optionally, [BUSCO](https://busco.ezlab.org). The tool used for completeness is set by `--eukaryotic_completeness_tool` (`eukcc` by default). Contamination is always calculated by EukCC. + +- `eukcc`: `eukcc single` is run on the uncompressed genome and both completeness and contamination are taken from `eukcc.tsv`. +- `busco`: `BUSCO` is run in `genome` mode with the lineage set by `--busco_db_lineage` (`auto_euk` by default). Completeness is taken from `results` → `Complete percentage` of the BUSCO short summary JSON. With automatic lineage selection, the summary of the selected specific lineage is used. Contamination is taken from EukCC. + +If `contamination` is already present in the samplesheet, it is kept. With `busco`, EukCC is then skipped for that genome, as only completeness has to be calculated. With `eukcc`, EukCC still runs to calculate completeness. + +The EukCC database (`--eukcc_db`) and BUSCO lineage dataset (`--busco_db`) can be given as a folder or as a `.tar.gz`/`.tgz` archive (local path or URL). Archives are extracted by the pipeline, only if there is at least one eukaryotic genome that needs the tool. If `--busco_db` is not provided, BUSCO downloads the lineage dataset itself. -Completeness and contamination are evaluated together in a shared genome quality step. +EukCC exit codes `201` (no marker genes found) and `204` (MetaEuk predicted zero proteins) are not treated as errors: the genome is kept, and its completeness and contamination stay empty. Any other non-zero exit code fails the run. If BUSCO finds no genes and writes no short summary, completeness stays empty. -The workflow checks three samplesheet fields: `completeness`, `contamination`, and `stats_generation_software`. If all three are already present, those values are reused. If any of them is missing, the genome is analysed with `CheckM2 predict`. If `--checkm2_db` is supplied and exists, that database is used directly. Otherwise, the workflow downloads a CheckM2 database from Zenodo (using the configured database ID) and then runs prediction. +#### `stats_generation_software` -For records that run `CheckM2`, completeness and contamination are extracted from the generated quality report (`quality_report.tsv`) and used `CheckM2` version is recorded as `stats_generation_software`. +The tools whose results are used are recorded in `stats_generation_software` as `_v`, separated by `;`, for example `checkm2_v1.1.0`, `eukcc_v2.2.0` or `busco_v6.1.0;eukcc_v2.2.0`. If `stats_generation_software` is already present in the samplesheet, the tools launched by the pipeline are appended to it, e.g. `CustomTool_v1.0;busco_v6.1.0`. diff --git a/docs/output.md b/docs/output.md index 438cf91a..eeec0ca7 100644 --- a/docs/output.md +++ b/docs/output.md @@ -8,36 +8,21 @@ The directories listed below will be created in the results directory (set with ## Pipeline overview -The pipeline is built using [Nextflow](https://www.nextflow.io/) and performs automated submission of sequence data to ENA. Exact steps and generated outputs depend on the data type and `--mode` executed (`mags`, `bins`, `metagenomic_assemblies` or `reads`). +The pipeline is built using [Nextflow](https://www.nextflow.io/) and performs automated submission of sequence data to ENA. Exact steps and generated outputs depend on the data type and `--mode` executed (`reads`, `metagenomic_assemblies`, `mags` or `bins`). -## `mags` and `bins` outputs +## `reads` outputs -When `--mode mags` or `--mode bins` is used, results are written under `mags/` or `bins/`. +When `--mode reads` is used, results are written under `reads/`.
Output files -- `/` - - `upload/genomes_accessions.tsv`: accessions assigned to submitted genomes. - - `upload/genomes_metadata.tsv`: tabular metadata gathered for submission. - - `upload/manifests/`: manifests generated by `genome_uploader`. - - `databases/checkm2/`: downloaded CheckM2 database file (when downloaded during the run). - - `databases/cat_pack/`: prepared CAT_pack database directories (when generated during the run). - - `/coverage/`: `coverm genome` output for samples where `genome_coverage` had to be computed. - - `/rna/barrnap/`: `barrnap` output GFF for samples where `RNA_presence` had to be inferred. - - `/rna/trnascanse/`: `tRNAscan-SE` outputs for the same RNA inference step. - - `/taxonomy/`: CAT/BAT taxonomic classification for samples where `NCBI_lineage` was missing. - - `/checkm2/`: CheckM2 reports for samples where completeness/contamination metadata had to be computed. - - `/upload/webin_cli/`: Webin-CLI wrapper output TSV with accessions for submitted genomes. +- `reads/` + - `upload/reads_accessions.tsv`: experiment and run accessions assigned to submitted reads (also shown in the MultiQC report).
-Many of these per-sample directories are conditional. For example, if `genome_coverage` is already provided in the samplesheet, the corresponding `coverage/` directory will not be created for that sample. - -> [!NOTE] **Assigned accessions (ERZs)** \ -> Users should read the ENA documentation on referencing submitted data: \ -> mags: https://ena-docs.readthedocs.io/en/latest/submit/assembly/metagenome/mag.html#assigned-accession-numbers \ -> bins: https://ena-docs.readthedocs.io/en/latest/submit/assembly/metagenome/binned.html#assigned-accession-numbers +Manifest generation and Webin-CLI submission are executed by the workflow, but their intermediate outputs are not currently published into `--outdir` by the pipeline. ## `metagenomic_assemblies` outputs @@ -59,19 +44,38 @@ Assembly study registration, manifest generation, and Webin-CLI submission are e > Users should read the ENA documentation on referencing submitted data: \ > metagenomic assemblies: https://ena-docs.readthedocs.io/en/latest/submit/assembly/metagenome/primary.html#assigned-accession-numbers -## `reads` outputs +## `mags` and `bins` outputs -When `--mode reads` is used, results are written under `reads/`. +When `--mode mags` or `--mode bins` is used, results are written under `mags/` or `bins/`.
Output files -- `reads/` - - `upload/reads_accessions.tsv`: experiment and run accessions assigned to submitted reads (also shown in the MultiQC report). +- `/` + - `upload/genomes_accessions.tsv`: accessions assigned to submitted genomes. + - `upload/genomes_metadata.tsv`: tabular metadata gathered for submission. + - `upload/manifests/`: manifests generated by `genome_uploader`. + - `databases/checkm2/`: downloaded CheckM2 database file (when downloaded during the run, only if prokaryotic genomes are present). + - `databases/cat_pack/`: prepared CAT_pack database directories (when generated during the run). + - `/coverage/`: `coverm genome` output for samples where `genome_coverage` had to be computed. + - `/rna/barrnap/`: `barrnap` output GFF for samples where `RNA_presence` had to be inferred (run with the kingdom matching the genome domain). + - `/rna/trnascanse/`: `tRNAscan-SE` outputs for the same RNA inference step. + - `/taxonomy/`: CAT/BAT taxonomic classification for samples where `NCBI_lineage` was missing. + - `/checkm2/`: CheckM2 report (`_checkm2_report.tsv`) for prokaryotic (bacteria and archaea) samples where completeness/contamination metadata had to be computed. + - `/eukcc/`: EukCC results (`_eukcc_results/eukcc.tsv`) for eukaryotic samples where completeness/contamination metadata had to be computed. Not created with `--eukaryotic_completeness_tool busco` if `contamination` was provided in the samplesheet. + - `/busco/-/`: BUSCO short summaries (`.txt`, `.json`), batch summary and log for eukaryotic samples, only with `--eukaryotic_completeness_tool busco`. + - `/busco/busco_downloads/lineages/`: BUSCO lineage datasets used in the run, only with `--save_busco_db`. + - `/upload/webin_cli/`: Webin-CLI wrapper output TSV with accessions for submitted genomes. + - `not_assigned_quality_genomes.tsv`: List of eukaryotic genomes skipped during upload because their quality could not be assessed.
-Manifest generation and Webin-CLI submission are executed by the workflow, but their intermediate outputs are not currently published into `--outdir` by the pipeline. +Many of these per-sample directories are conditional. For example, if `genome_coverage` is already provided in the samplesheet, the corresponding `coverage/` directory will not be created for that sample. + +> [!NOTE] **Assigned accessions (ERZs)** \ +> Users should read the ENA documentation on referencing submitted data: \ +> mags: https://ena-docs.readthedocs.io/en/latest/submit/assembly/metagenome/mag.html#assigned-accession-numbers \ +> bins: https://ena-docs.readthedocs.io/en/latest/submit/assembly/metagenome/binned.html#assigned-accession-numbers ## Common outputs diff --git a/docs/usage.md b/docs/usage.md index a8ab3c53..9ae37709 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -9,6 +9,7 @@ - [Introduction](#introduction) - [Before you start](#before-you-start) - [Submission study](#submission-study) +- [Production vs Test submission](#production-vs-test-submission) - [Data privacy](#data-privacy) - [Third party assemblies (TPA)](#third-party-assemblies-tpa) - [`reads` mode](#reads-mode) @@ -116,6 +117,21 @@ study-soil-2026 Soil microbiome study Survey of soil microbiota | `existing_study_type` | No | ENA study type (e.g. `Metagenomics`, `Other`). | | `new_study_type` | No | Custom study type. Only used when `existing_study_type` is set to `Other`. | +## Production vs Test submission + +Real data submissions are always uploaded to the **ENA Production** server (alternatively called LIVE). + +If you want to test the submission process without making a permanent submission, you can use the ENA Test server (alternatively called TEST). This allows you to create all the necessary records (e.g. studies and samples) and upload your data for testing. Submissions to the TEST server are automatically deleted after 24 hours. Check [ENA documentation](https://ena-docs.readthedocs.io/en/latest/submit/general-guide/interactive.html) for more information. + +Alternatively, you can use _validation_ mode to check whether your submission files are valid without uploading any data to either the TEST or LIVE server. This is particularly useful during development and for checking files before a real submission. Those procedures are controlled with `--test_upload` and `--webincli_mode` arguments described in [Running the pipeline](#running-the-pipeline). + +| `--test_upload` | `--webincli_mode` | Action | +| --------------- | ----------------- | ---------------------------------------------------------------------------------- | +| `false` | `submit` | Submission to LIVE server. | +| `true` | `submit` | Submission to TEST server. Pipeline default settings. | +| `false` | `validate` | Registration of records on LIVE server without upload. **Restricted combination**. | +| `true` | `validate` | Registration of records on TEST server without upload. | + ## Data privacy You can reference private ENA data if you have access to it via your Webin account (it was submitted previously under your credentials). To use private data accessions in your submission metadata, specify the `--is_private` flag. The pipeline will then use your provided Webin credentials to fetch the required metadata. @@ -222,17 +238,17 @@ assembly_001,data/assembly_001.fasta.gz,data/assembly_001_R1.fastq.gz,data/assem assembly_002,data/assembly_002.fasta.gz,,,42.7,ERR011323,MEGAHIT,1.2.9,metatranscriptome ``` -| Column | Required | Description | -| ------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `id` | Yes | A unique identifier for this data entry. Must be globally unique within the input dataset. | -| `fasta` | Yes | Path to assembly contigs in FASTA format compressed with `gzip`. | -| `fastq_1` | Conditional | Path to single-end/paired-end forward reads in FASTQ format (optionally gzipped). Required if `coverage` is not provided. | -| `fastq_2` | No | Path to the second read file in FASTQ format for paired-end data used to generate the source metagenomic assembly. Leave empty for single-end reads. | -| `coverage` | Conditional | Estimated sequencing depth of the assembly. If this value is missing, it is computed automatically during pipeline execution when reads are provided. | -| `run_accession` | Yes | ENA run accession for the reads used to generate the metagenomic assembly. Reads must already be submitted to ENA. | -| `assembler` | Yes | Name of the assembler software used to generate the assembly, e.g. MEGAHIT, SPAdes, metaSPAdes, Flye, etc. | -| `assembler_version` | Yes | Version of the assembler software used to generate the assembly, e.g. 1.0.0. | -| `assembly_type` | No | Sequencing library source: `metagenome` for metagenome assembly (would be used as _'primary metagenome'_ in manifest file following [ENA docs](https://ena-docs.readthedocs.io/en/latest/submit/assembly/metagenome/primary.html)) or `metatranscriptome` for metatranscriptome assembly (woule be used _'metatranscriptome'_ in assembly manifest following [ENA docs](https://ena-docs.readthedocs.io/en/latest/submit/assembly/metatranscriptome.html)). Default: `metagenome` | +| Column | Required | Description | +| ------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | Yes | A unique identifier for this data entry. Must be globally unique within the input dataset. | +| `fasta` | Yes | Path to assembly contigs in FASTA format compressed with `gzip`. | +| `fastq_1` | Conditional | Path to single-end/paired-end forward reads in FASTQ format (optionally gzipped). Required if `coverage` is not provided. | +| `fastq_2` | No | Path to the second read file in FASTQ format for paired-end data used to generate the source metagenomic assembly. Leave empty for single-end reads. | +| `coverage` | Conditional | Estimated sequencing depth of the assembly. If this value is missing, it is computed automatically during pipeline execution when reads are provided. | +| `run_accession` | Yes | ENA run accession for the reads used to generate the metagenomic assembly. Reads must already be submitted to ENA. | +| `assembler` | Yes | Name of the assembler software used to generate the assembly, e.g. MEGAHIT, SPAdes, metaSPAdes, Flye, etc. | +| `assembler_version` | Yes | Version of the assembler software used to generate the assembly, e.g. 1.0.0. | +| `assembly_type` | No | Assembly type: `metagenome` or `metatranscriptome`. Written to the ENA assembly manifest as ASSEMBLY_TYPE 'primary metagenome' (ENA docs: https://ena-docs.readthedocs.io/en/latest/submit/assembly/metagenome/primary.html) or 'metatranscriptome' (ENA docs: https://ena-docs.readthedocs.io/en/latest/submit/assembly/metatranscriptome.html) respectively. Default: `metagenome`. | Provide either read files (`fastq_1`, optionally `fastq_2`) or a `coverage` value for each row. If `coverage` is missing and reads are provided, the workflow calculates average coverage with CoverM. See the [Methods documentation](docs/methods.md) for more information on how coverage is calculated. @@ -311,7 +327,7 @@ mag_001,data/mag_001.fasta.gz,SRR24458089,,,SPAdes 3.15.5,MetaBAT2 2.15,default, | `assembly_software` | Yes | Tool name and version that were used to generate the source metagenomic assembly, e.g. MEGAHIT_v1.0, SPAdes_v4.0.0, metaSPAdes_v3.15.0. | | `binning_software` | Yes | Tool name and version that was used to bin data, e.g. MetaBAT2_v1.0, VAMB_2.0, MaxBin2_v1, CONCOCT_v3.0, SemiBin2_v1, COMEBin_v2.3.4, etc. | | `binning_parameters` | Yes | Arguments used to bin data different from default, e.g. -min_contig_length 1000, otherwise use 'default'. | -| `stats_generation_software` | No | Tool, including version, that was used to calculate completeness and contamination, e.g. CheckM2_v1.0.0. | +| `stats_generation_software` | No | Tool, including version, that was used to calculate completeness and contamination, e.g. CheckM2_v1.0.0. Several tools are separated by `;`, e.g. busco_v6.1.0;eukcc_v2.2.0. If the pipeline runs additional tools for this genome, they are appended to the provided value. | | `completeness` | No | MAG/bin completeness score: the 0<= ratio <= 100 of observed single-copy marker genes to total single-copy marker genes in chosen marker gene set (%). ENA docs: https://ena-docs.readthedocs.io/en/latest/faq/metagenomes.html#how-is-the-quality-of-a-metagenomic-assembly-defined. | | `contamination` | No | MAG/bin contamination score: the 0<= ratio <= 100 of observed single-copy marker genes in ≥2 copies to total single-copy marker genes in chosen marker gene set (%). ENA docs: https://ena-docs.readthedocs.io/en/latest/faq/metagenomes.html#how-is-the-quality-of-a-metagenomic-assembly-defined. | | `genome_coverage` | Conditional | Estimated average sequencing depth (>0) across the genome. If the value is missing, it is computed automatically during pipeline execution when reads are provided. | @@ -320,7 +336,7 @@ mag_001,data/mag_001.fasta.gz,SRR24458089,,,SPAdes 3.15.5,MetaBAT2 2.15,default, | `broad_environment` | Yes | Broad ecological context of the sample, for example 'marine biome', 'desert biome'. It is recommended to use subclasses of EnvO 'biome' class (http://purl.obolibrary.org/obo/ENVO_00000428). Documentation: https://github.com/EnvironmentOntology/envo/wiki/Using-ENVO-with-MIxS. | | `local_environment` | Yes | Local environmental context of the sample, for example 'tropical dry broadleaf forest biome', 'marine abyssal zone biome'. It is recommended to use EnvO terms which are of smaller spatial grain than your entry for "broad-scale environmental context". Documentation: https://github.com/EnvironmentOntology/envo/wiki/Using-ENVO-with-MIxS. | | `environmental_medium` | Yes | Material surrounding and in contact with the sample, for example 'mucus', 'lake water'. It is recommended to use subclasses of EnvO 'environmental material' class (http://purl.obolibrary.org/obo/ENVO_00010483). Documentation: https://github.com/EnvironmentOntology/envo/wiki/Using-ENVO-with-MIxS. | -| `RNA_presence` | No | Presence or absence of the 23S, 16S, and 5S rRNA genes and at least 18 tRNAs. This is used for MISAG/MIMAG assembly quality classification. Options: true or false. | +| `RNA_presence` | No | Presence or absence of the 23S, 16S, and 5S rRNA genes (prokaryotes) or the 28S, 18S, 5.8S and 5S rRNA genes (eukaryotes) and at least 18 tRNAs. This is used for MISAG/MIMAG assembly quality classification. Options: true or false. | | `NCBI_lineage` | No | Full NCBI lineage - format: x;y;z. For example, the lineage for E. coli can be: 'Bacteria;Pseudomonadati;Pseudomonadota;Gammaproteobacteria;Enterobacterales;Enterobacteriaceae;Escherichia' or '2;1224;1236;91347;543;561;562'. For more info check https://www.ncbi.nlm.nih.gov/datasets/docs/v2/data-processing/taxonomy-processing/taxonomy/. | > [!NOTE] @@ -328,9 +344,9 @@ mag_001,data/mag_001.fasta.gz,SRR24458089,,,SPAdes 3.15.5,MetaBAT2 2.15,default, If `genome_coverage`, `stats_generation_software`, `completeness`, `contamination`, `RNA_presence`, or `NCBI_lineage` are missing, the workflow can calculate or infer them when the required inputs are available. See the [Methods documentation](docs/methods.md) for more information on how metadata statistics are obtained. -### Preparing the CheckM2 and CAT_pack databases +### Preparing the CheckM2, EukCC, BUSCO and CAT_pack databases -`mags` and `bins` submission modes use CheckM2 and CAT_pack tools that require specialized databases for completeness/contamination assessment and taxonomy assignment. +`mags` and `bins` submission modes use [CheckM2](https://github.com/chklovski/CheckM2) (prokaryotes), [EukCC](https://github.com/EBI-Metagenomics/EukCC) and optionally [BUSCO](https://busco.ezlab.org/busco_userguide.html) (eukaryotes) and [CAT_pack](https://github.com/MGXlab/CAT_pack) tools that require specialized databases for completeness/contamination assessment and taxonomy assignment. You can either provide pre-existing databases or let the pipeline prepare them during execution. @@ -340,11 +356,15 @@ In particular, the CAT_pack database is extremely large and may take a long time - CheckM2: - provide the path to a local database with `--checkm2_db`, otherwise the pipeline downloads the version specified with `--checkm2_db_download_id` (by default Zenodo accession `14897628`). +- EukCC (used only if eukaryotic genomes are present and their completeness/contamination has to be calculated): + - provide the database with `--eukcc_db` as an uncompressed folder or as a `.tar.gz`/`.tgz` archive (local path or URL), otherwise the pipeline downloads `http://ftp.ebi.ac.uk/pub/databases/metagenomics/eukcc/eukcc2_db_ver_1.1.tar.gz`. URLs are downloaded and archives are extracted by the pipeline in every run, so we recommend downloading and extracting the database once and providing the folder. + +- BUSCO (used only with `--eukaryotic_completeness_tool busco`): + - provide a lineage dataset with `--busco_db` as a local folder or as a `.tar.gz`/`.tgz` archive (local path or URL), otherwise BUSCO downloads the lineage set by `--busco_db_lineage` during the run (requires an internet connection). A folder is expected to contain a `lineages` subfolder with the lineage dataset, e.g. `lineages/eukaryota_odb10`. + - CAT_pack: - provide the path to a local database (containing `tax/` and `db/` folders or a `tar.gz` archive) with `--cat_db`, otherwise the pipeline builds CAT_pack DB from NCBI non-redundant protein database (`nr`). -See the [CAT_pack documentation](https://github.com/MGXlab/CAT_pack) and [CheckM2 documentation](https://github.com/chklovski/CheckM2) for more details on usage and creation of databases. - Databases created/downloaded by the pipeline are published under: `/databases/`. In subsequent pipeline runs you can reuse them using `--cat_db /databases/cat_pack/` and `--checkm2_db /databases/checkm2/`. @@ -352,11 +372,17 @@ Databases created/downloaded by the pipeline are published under: In addition to the [common parameters](#running-the-pipeline): -| Parameter | Required | Description | -| -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `--upload_tpa` | No | Mark assemblies as [third party assemblies (TPA)](#third-party-assemblies-tpa) when required. Default: `false`. | -| `--checkm2_db` | No | Path to a pre-downloaded CheckM2 database. If omitted, downloads the version set by `--checkm2_db_download_id`. Default: `14897628` (Zenodo accession). | -| `--cat_db` | No | Path to a local CAT_pack database. If omitted, builds CAT_pack DB from NCBI non-redundant protein database (`nr`). | +| Parameter | Required | Description | +| -------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--upload_tpa` | No | Mark assemblies as [third party assemblies (TPA)](#third-party-assemblies-tpa) when required. Default: `false`. | +| `--checkm2_db` | No | Path to a pre-downloaded CheckM2 database. If omitted, downloads the version set by `--checkm2_db_download_id`. Default: `14897628` (Zenodo accession). | +| `--cat_db` | No | Path to a local CAT_pack database. If omitted, builds CAT_pack DB from NCBI non-redundant protein database (`nr`). | +| `--eukaryotic_completeness_tool` | No | Tool used to calculate completeness of eukaryotic MAGs/bins: `eukcc` or `busco`. Contamination is always calculated by EukCC, unless it is provided in the samplesheet. Default: `eukcc`. | +| `--eukcc_db` | No | EukCC database as an uncompressed folder or a `.tar.gz`/`.tgz` archive (local path or URL). Used to calculate completeness and contamination of eukaryotic MAGs/bins if those values were not provided in the samplesheet. URLs are downloaded and archives are extracted by the pipeline in every run, so we recommend downloading and extracting the database once and providing the folder. Default: `http://ftp.ebi.ac.uk/pub/databases/metagenomics/eukcc/eukcc2_db_ver_1.1.tar.gz`. | +| `--busco_db` | No | BUSCO `*_odb10` or `*_odb12` lineage dataset as an uncompressed folder or a `.tar.gz`/`.tgz` archive (local path or URL), e.g. `https://busco-data.ezlab.org/v5/data/lineages/eukaryota_odb10.2024-01-08.tar.gz`. A folder is expected to contain a `lineages` subfolder with the lineage dataset, e.g. `lineages/eukaryota_odb10`. If provided, BUSCO runs in offline mode. If omitted, BUSCO downloads the lineage set by `--busco_db_lineage` during the run (requires an internet connection). Used only with `--eukaryotic_completeness_tool busco`. | +| `--busco_db_lineage` | No | Name of the BUSCO `*_odb10` or `*_odb12` lineage to check eukaryotic genomes against (e.g. `eukaryota_odb10`), or `auto`, `auto_prok`, `auto_euk` for automatic lineage selection. When used with `--busco_db`, it should correspond to the lineage supplied there. Without `--busco_db`, the lineage is downloaded during the run (requires an internet connection). Used only with `--eukaryotic_completeness_tool busco`. Default: `auto_euk`. | +| `--save_busco_db` | No | Save BUSCO lineage datasets downloaded during the run (when `--busco_db` is not provided) to the output directory. Useful for reproducibility, as BUSCO datasets are frequently updated and old versions do not always remain accessible. Used only with `--eukaryotic_completeness_tool busco`. Default: `false`. | +| `--busco_clean` | No | Remove BUSCO intermediate files after each run. BUSCO creates a large number of intermediate files, which may cause problems on clusters with file number limits, particularly with many MAGs/bins. Used only with `--eukaryotic_completeness_tool busco`. Default: `false`. | Example `mags` mode upload to TEST server, run command with docker: @@ -378,7 +404,15 @@ nextflow run nf-core/seqsubmit \ - **Co-assemblies**: MAGs/bins generated from co-assemblies are not supported. The pipeline currently expects each MAG/bin to be derived from an assembly generated from a single run. Tracked in [issue #61](https://github.com/nf-core/seqsubmit/issues/61). -- **Eukaryotic and viral bins/MAGs**: Submitting eukaryotic or viral genomes that require additional metadata generation is not supported. For such genomes tRNA and rRNA prediction, quality assessment (completeness/contamination estimation) and taxonomy assignment are not implemented. If all the required metadata (`completeness`, `contamination`, `stats_generation_software`, `RNA_presence` and `NCBI_lineage`) is already provided in the samplesheet, eukaryotic and viral bins/MAGs can still be submitted normally. Tracked in [issue #40](https://github.com/nf-core/seqsubmit/issues/40) (eukaryotic) and [issue #63](https://github.com/nf-core/seqsubmit/issues/63) (viral). +- **Viral bins/MAGs**: Submitting viral genomes that require additional metadata generation is not supported. For such genomes tRNA and rRNA prediction, quality assessment (completeness/contamination estimation) and taxonomy assignment are not implemented. If all the required metadata (`completeness`, `contamination`, `stats_generation_software`, `RNA_presence` and `NCBI_lineage`) is already provided in the samplesheet, viral bins/MAGs can still be submitted normally. Tracked in [issue #63](https://github.com/nf-core/seqsubmit/issues/63). + +- **Domain assignment**: the domain of each genome (bacteria, archaea or eukaryote) is decided from `NCBI_lineage` (provided in the samplesheet or assigned by CAT_pack). Genomes whose lineage does not contain `Eukaryota`/`2759` or `Archaea`/`2157` or `Bacteria`/`2` are raising pipeline error. + +- **Eukaryotic bins/MAGs**: + - Taxonomic lineage assignment is implemented using CAT_pack that is using Prodigal (prokaryotic gene caller) which can raise errors on long sequences. + - EukCC database (`--eukcc_db`) is downloaded and extracted in every run unless a local folder is provided. + - BUSCO is used only for completeness, contamination is always taken from EukCC (or from the samplesheet). + - If EukCC finds no marker genes or MetaEuk predicts no proteins for a genome, completeness and contamination stay empty for that genome. The same happens for completeness when BUSCO finds no genes. - **Submission of a MAG/bin without submitting the assembly or raw reads**: If a MAG/bin cannot be traced back to an assembly accession or a reads accession — i.e. only a sample accession is available — it cannot currently be submitted, since the pipeline relies on that lineage to build the required metadata. Tracked in [issue #87](https://github.com/nf-core/seqsubmit/issues/87). @@ -388,7 +422,7 @@ nextflow run nf-core/seqsubmit \ ## Scalability -Some processes in this pipeline are resource intensive — in particular coverage calculation (CoverM), quality assessment (CheckM2), and taxonomic classification of MAGs/bins (BAT). For real-world data, these steps should be run on an HPC cluster or another compute environment with sufficient CPU, memory, and job scheduling capacity, rather than on a single local machine. +Some processes in this pipeline are resource intensive — in particular coverage calculation (CoverM), quality assessment (CheckM2, EukCC, BUSCO), and taxonomic classification of MAGs/bins (BAT). For real-world data, these steps should be run on an HPC cluster or another compute environment with sufficient CPU, memory, and job scheduling capacity, rather than on a single local machine. Depending on the resources available on your machine or cluster, you will likely need to adapt the Nextflow configuration to limit the maximum number of concurrently running jobs and other resource settings using [resourceLimits](https://nf-co.re/docs/developing/institutional-profiles/configuration#resource-limits) in a custom config, so that the pipeline does not try to claim more resources than are actually available. See the [nf-core configuration documentation](https://nf-co.re/docs/usage/getting_started/configuration) for guidance on writing a custom config for your infrastructure. @@ -410,17 +444,17 @@ nextflow run nf-core/seqsubmit \ Parameters common to all modes: -| Parameter | Required | Description | -| ------------------------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `--mode` | Yes | Type of the data to be submitted. Options: `mags`, `bins`, `metagenomic_assemblies`, `reads`. | -| `--input` | Yes | Path to samplesheet describing the data to be submitted (supported formats: csv, tsv, yaml, yml, json). Columns/fields depend on the pipeline mode. See [usage docs](https://nf-co.re/seqsubmit/usage#samplesheet-input). | -| `--outdir` | Yes | Path to the output directory for pipeline results. You have to use absolute paths to storage on Cloud infrastructure. | -| `--submission_study` OR `--study_metadata` | Yes (one of) | ENA study accession (PRJ/ERP) to submit the data to OR metadata file in JSON/TSV/CSV format to register a new study. | -| `--centre_name` | Yes | Name of the submitter's organisation (mandatory for broker accounts). | -| `--test_upload` | No | Submit to the ENA TEST server instead of the LIVE server. Use that flag for development purposes or for validation of your submissions. Submission would be done to TEST ENA server instead of LIVE server. TEST server holds data 24h and removes afterwords. LIVE server does not have option to modify your submission, you can only suppress data and re-upload. Default: `true`. | -| `--webincli_mode` | No | Webin-CLI mode for ENA interaction: `submit` uploads data, `validate` performs validation only. `validate` mode checks correctness of manifest files, data access and validity. `submit` mode does validation and push data to ENA server. Default: `submit`. | -| `--is_private` | No | Use if you are referencing private data accessions in your submission. Set to true when the referenced project/reads/assembly are still private in ENA, so metadata is fetched via authenticated access. Does NOT affect the privacy of your own submission, use --release_date for that. Default: `false`. | -| `--release_date` | No | Use if you want to keep your data private in ENA after submission until a particular date (format: YYYY-MM-DD). Data stays private until this date, then is automatically released and indexed by ENA. Must be no more than 2 years from today. Omit to release the study publicly immediately. | +| Parameter | Required | Description | +| ------------------------------------------ | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--mode` | Yes | Type of the data to be submitted. Options: `mags`, `bins`, `metagenomic_assemblies`, `reads`. | +| `--input` | Yes | Path to samplesheet describing the data to be submitted (supported formats: csv, tsv, yaml, yml, json). Columns/fields depend on the pipeline mode. See [usage docs](https://nf-co.re/seqsubmit/usage#samplesheet-input). | +| `--outdir` | Yes | Path to the output directory for pipeline results. You have to use absolute paths to storage on Cloud infrastructure. | +| `--submission_study` OR `--study_metadata` | Yes (one of) | ENA study accession (PRJ/ERP) to submit the data to OR metadata file in JSON/TSV/CSV format to register a new study. | +| `--centre_name` | Yes | Name of the submitter's organisation (mandatory for broker accounts). | +| `--test_upload` | No | Submit to the ENA TEST server instead of the LIVE server. Use that flag for development purposes or for validation of your submissions. Submission would be done to TEST ENA server instead of LIVE server. TEST server holds data 24h and removes afterwords. LIVE server does not have option to modify your submission, you can only suppress data and re-upload. Default: `true`. It is restricted to use `--test-upload=false` with `--webincli_mode validate` because study and/or samples would be registered on LIVE server but data would not be submitted. | +| `--webincli_mode` | No | Webin-CLI mode for ENA interaction: `submit` uploads data, `validate` performs validation only. `validate` mode checks correctness of manifest files, data access and validity. `submit` mode does validation and push data to ENA server. Default: `submit`. | +| `--is_private` | No | Use if you are referencing private data accessions in your submission. Set to true when the referenced project/reads/assembly are still private in ENA, so metadata is fetched via authenticated access. Does NOT affect the privacy of your own submission, use --release_date for that. Default: `false`. | +| `--release_date` | No | Use if you want to keep your data private in ENA after submission until a particular date (format: YYYY-MM-DD). Data stays private until this date, then is automatically released and indexed by ENA. Must be no more than 2 years from today. Omit to release the study publicly immediately. | Each mode also has additional parameters and example commands — see its own "`` parameters and example" subsection above. diff --git a/main.nf b/main.nf index 1c9223ab..54ae7d63 100644 --- a/main.nf +++ b/main.nf @@ -60,7 +60,12 @@ workflow NFCORE_SEQSUBMIT { params.test_upload, params.webincli_mode, params.is_private, - params.release_date ? channel.value(params.release_date): channel.value(false) + params.release_date ? channel.value(params.release_date): channel.value(false), + params.busco_db_lineage, + params.busco_db, + params.busco_clean, + params.eukaryotic_completeness_tool, + params.eukcc_db ) ch_multiqc_report = GENOMESUBMIT.out.multiqc_report } else if (params.mode == "metagenomic_assemblies") { diff --git a/modules.json b/modules.json index 8b1d819d..dc27d29d 100644 --- a/modules.json +++ b/modules.json @@ -10,6 +10,12 @@ "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", "installed_by": ["modules"] }, + "busco/busco": { + "branch": "master", + "git_sha": "3927a974459b80b8e24d73e00da029e8c7335c4d", + "installed_by": ["modules"], + "patch": "modules/nf-core/busco/busco/busco-busco.diff" + }, "catpack/addnames": { "branch": "master", "git_sha": "6d46786420b4d7bc88eba026eb389c0c5535d120", @@ -71,6 +77,11 @@ "installed_by": ["modules"], "patch": "modules/nf-core/find/concatenate/find-concatenate.diff" }, + "gunzip": { + "branch": "master", + "git_sha": "0902eac3012baaf4f9ab6513c8c55acc9353c96c", + "installed_by": ["modules"] + }, "multiqc": { "branch": "master", "git_sha": "98403d15b0e50edae1f3fec5eae5e24982f1fade", diff --git a/modules/local/count_rna/main.nf b/modules/local/count_rna/main.nf index 2bf5758a..e78f58d8 100644 --- a/modules/local/count_rna/main.nf +++ b/modules/local/count_rna/main.nf @@ -25,11 +25,13 @@ process COUNT_RNA { script: def prefix = task.ext.prefix ?: "${meta.id}" + def domain = meta.domain ?: 'bac' """ count_rna.py \\ --trna ${trnas_stats} \\ --rrna ${rrna_gff} \\ --name ${prefix} \\ + --domain ${domain} \\ --trna-limit ${min_trna_count} \\ --rrna-limit ${min_rrna_percentage} \\ --output ${prefix}_rna_decision.tsv diff --git a/modules/local/count_rna/meta.yml b/modules/local/count_rna/meta.yml index 4b505cfe..e4926897 100644 --- a/modules/local/count_rna/meta.yml +++ b/modules/local/count_rna/meta.yml @@ -11,42 +11,48 @@ tools: - count_rna: description: | Script that parses tRNAscan-SE output and barrnap GFF output to determine - whether RNA genes are present in the genome. Returns 'Yes' if the number of - tRNA genes meets the threshold and all three rRNA subunits (16S, 23S, 5S) - have sufficient length coverage, otherwise 'No'. + whether RNA genes are present in the genome. Returns 'True' if the number of + tRNA genes meets the threshold and all rRNA genes required for the genome's + domain have sufficient length coverage, otherwise 'False'. + Required rRNA genes: 16S, 23S and 5S for bacteria and archaea; + 18S, 28S, 5.8S and 5S for eukaryotes. licence: ["GPL v3"] input: - meta: type: map description: | - Groovy Map containing sample information - e.g. [ id:'test' ] + Groovy Map containing sample information. + `domain` defines which rRNA genes are required: 'bac', 'arc' or 'euk' (default: 'bac'). + e.g. [ id:'test', domain:'bac' ] - trnas_stats: type: file description: tRNA statistics file from tRNAscan-SE (.stats format) pattern: "*.stats" - rrna_gff: type: file - description: rRNA annotation file from barrnap (GFF3 format) + description: rRNA annotation file from barrnap (GFF3 format), predicted with the kingdom matching meta.domain pattern: "*.gff" - min_trna_count: - type: value - description: Minimum required number of tRNA genes. + type: integer + description: | + Minimum required total number of tRNA genes for the 20 standard amino acids (e.g. 18). - min_rrna_percentage: - type: value - description: Minimum required percentage coverage for each rRNA subunit. + type: float + description: | + Minimum percentage of expected gene length that must be recovered for each + required rRNA gene to count it as present (e.g. 80). output: - meta: type: map description: | Groovy Map containing sample information - e.g. [ id:'test' ] + e.g. [ id:'test', domain:'bac' ] - rna_decision: type: file description: | - Tab-separated file containing genome ID and decision (Yes/No) on whether + Tab-separated file with one line: genome ID and decision (True/False) on whether sufficient RNA genes are present pattern: "*_rna_decision.tsv" diff --git a/modules/local/eukcc/single/environment.yml b/modules/local/eukcc/single/environment.yml new file mode 100644 index 00000000..67914348 --- /dev/null +++ b/modules/local/eukcc/single/environment.yml @@ -0,0 +1,13 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + # versions match the container quay.io/biocontainers/eukcc:2.2.0--pyhdfd78af_0 + - bioconda::epa-ng=0.3.8 + - bioconda::eukcc=2.2.0 + - bioconda::hmmer=3.3 + - bioconda::metaeuk=4.a0f584d + - bioconda::pplacer=1.1.alpha19 + - conda-forge::python=3.8.12 diff --git a/modules/local/eukcc/single/main.nf b/modules/local/eukcc/single/main.nf new file mode 100644 index 00000000..4512e30c --- /dev/null +++ b/modules/local/eukcc/single/main.nf @@ -0,0 +1,59 @@ +process EUKCC_SINGLE { + + tag "${meta.id}" + label 'process_high' + + conda "${moduleDir}/environment.yml" + container 'quay.io/biocontainers/eukcc:2.2.0--pyhdfd78af_0' + + input: + tuple val(meta), path(fasta) + tuple val(meta_db), path(eukcc_db) + + output: + tuple val(meta), path("${prefix}_eukcc_results/eukcc.tsv"), emit: eukcc_tsv + tuple val("${task.process}"), val('eukcc'), eval('eukcc -v 2>&1 | grep -oE "[0-9]+\\.[0-9]+\\.[0-9]+" | head -n1'), emit: versions_eukcc, topic: versions + tuple val("${task.process}"), val('metaeuk'), eval('metaeuk -h 2>&1 | grep "Version" | sed "s/.*Version: //"'), emit: versions_metaeuk, topic: versions + tuple val("${task.process}"), val('pplacer'), eval('pplacer --version'), emit: versions_pplacer, topic: versions + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + + """ + # EukCC exit codes: + # 201 - no marker genes found, 204 - MetaEuk predicted zero proteins: not an error, genome has no estimate + # any other non-zero code (e.g. 1, 200, 202, 203, 222) is a real failure + set +e + eukcc single \\ + ${args} \\ + --db ${eukcc_db} \\ + --out ${prefix}_eukcc_results \\ + --threads ${task.cpus} \\ + ${fasta} + exit_code=\$? + set -e + + case \$exit_code in + 0) + ;; + 201|204) + # write header-only table so the genome is kept downstream with empty completeness/contamination + echo "EukCC exited with code \$exit_code: no completeness estimate for ${prefix}" >&2 + mkdir -p ${prefix}_eukcc_results + printf 'fasta\\tcompleteness\\tcontamination\\tncbi_lng\\n' > ${prefix}_eukcc_results/eukcc.tsv + ;; + *) + echo "EukCC failed with exit code \$exit_code" >&2 + exit \$exit_code + ;; + esac + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + """ + mkdir -p ${prefix}_eukcc_results + printf 'fasta\\tcompleteness\\tcontamination\\tncbi_lng\\n${fasta}\\t90.0\\t1.0\\t1-131567-2759-33154-4751\\n' > ${prefix}_eukcc_results/eukcc.tsv + """ +} diff --git a/modules/local/eukcc/single/meta.yml b/modules/local/eukcc/single/meta.yml new file mode 100644 index 00000000..662cb635 --- /dev/null +++ b/modules/local/eukcc/single/meta.yml @@ -0,0 +1,129 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "eukcc_single" +description: Estimate completeness and contamination of a single eukaryotic genome or MAG with EukCC +keywords: + - eukaryotes + - mag + - metagenome + - quality + - completeness + - contamination +tools: + - "eukcc": + description: "EukCC - completeness and contamination estimation for eukaryotic genomes using marker genes" + homepage: "https://github.com/EBI-Metagenomics/EukCC" + documentation: "https://eukcc.readthedocs.io" + doi: "10.1186/s13059-020-02155-4" + licence: ["GPL v3"] + identifier: "" + - "metaeuk": + description: "MetaEuk - gene discovery and annotation of eukaryotic contigs, used by EukCC to predict proteins" + homepage: "https://github.com/soedinglab/metaeuk" + doi: "10.1186/s40168-020-00808-x" + licence: ["GPL v3"] + identifier: biotools:MetaEuk + - "pplacer": + description: "pplacer - phylogenetic placement of sequences on a reference tree, used by EukCC to select the lineage marker set" + homepage: "https://matsen.fhcrc.org/pplacer/" + doi: "10.1186/1471-2105-11-538" + licence: ["GPL v3"] + identifier: biotools:pplacer +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', domain:'euk' ]` + - fasta: + type: file + description: Uncompressed nucleotide FASTA file of the genome + pattern: "*.{fasta,fna,fa}" + ontologies: + - edam: http://edamontology.org/format_1929 # FASTA + - - meta_db: + type: map + description: | + Groovy Map containing database information + e.g. `[ id:'eukcc_db' ]` + - eukcc_db: + type: directory + description: Uncompressed EukCC database directory (e.g. eukcc2_db_ver_1.1) +output: + eukcc_tsv: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', domain:'euk' ]` + - ${prefix}_eukcc_results/eukcc.tsv: + type: file + description: | + Tab-separated table with columns fasta, completeness, contamination, ncbi_lng. + Contains only the header if EukCC exited with code 201 (no marker genes found) + or 204 (MetaEuk predicted zero proteins). + pattern: "*_eukcc_results/eukcc.tsv" + ontologies: + - edam: http://edamontology.org/format_3475 # TSV + versions_eukcc: + - - ${task.process}: + type: string + description: The name of the process + - eukcc: + type: string + description: The name of the tool + - 'eukcc -v 2>&1 | grep -oE "[0-9]+\\.[0-9]+\\.[0-9]+" | head -n1': + type: eval + description: The expression to obtain the version of the tool + versions_metaeuk: + - - ${task.process}: + type: string + description: The name of the process + - metaeuk: + type: string + description: The name of the tool + - 'metaeuk -h 2>&1 | grep "Version" | sed "s/.*Version: //"': + type: eval + description: The expression to obtain the version of the tool + versions_pplacer: + - - ${task.process}: + type: string + description: The name of the process + - pplacer: + type: string + description: The name of the tool + - "pplacer --version": + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - eukcc: + type: string + description: The name of the tool + - 'eukcc -v 2>&1 | grep -oE "[0-9]+\\.[0-9]+\\.[0-9]+" | head -n1': + type: eval + description: The expression to obtain the version of the tool + - - ${task.process}: + type: string + description: The name of the process + - metaeuk: + type: string + description: The name of the tool + - 'metaeuk -h 2>&1 | grep "Version" | sed "s/.*Version: //"': + type: eval + description: The expression to obtain the version of the tool + - - ${task.process}: + type: string + description: The name of the process + - pplacer: + type: string + description: The name of the tool + - "pplacer --version": + type: eval + description: The expression to obtain the version of the tool +authors: + - "@KateSakharova" +maintainers: + - "@KateSakharova" diff --git a/modules/nf-core/busco/busco/.conda-lock/linux_amd64-bd-6d1f7006d91892b3_1.txt b/modules/nf-core/busco/busco/.conda-lock/linux_amd64-bd-6d1f7006d91892b3_1.txt new file mode 100644 index 00000000..bbad0b6b --- /dev/null +++ b/modules/nf-core/busco/busco/.conda-lock/linux_amd64-bd-6d1f7006d91892b3_1.txt @@ -0,0 +1,3042 @@ + +version: 6 +environments: +default: +channels: +- url: https://conda.anaconda.org/conda-forge/ +- url: https://conda.anaconda.org/bioconda/ +- url: https://conda.anaconda.org/bioconda/ +options: +pypi-prerelease-mode: if-necessary-or-explicit +packages: +linux-64: +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.16.1-hb03c661_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/augustus-3.5.0-pl5321h9716f88_9.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.6.0-py312h90b7ffd_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/bamtools-2.5.3-he132191_0.tar.bz2 +- conda: https://conda.anaconda.org/bioconda/linux-64/bbmap-39.81-h9b5c0a0_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/biopython-1.87-py312h4c3975b_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/blast-2.17.0-h66d330f_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/boost-cpp-1.85.0-h3c6214e_4.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda +- conda: https://conda.anaconda.org/bioconda/noarch/busco-6.1.0-pyhdfd78af_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/linux-64/c-ares-1.34.6-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-h3394656_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/cdbtools-0.99-h077b44d_12.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.6.17-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.8-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/clustalw-2.1-h9948957_12.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py312h0a2e395_4.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/curl-8.21.0-hcf29cc6_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda +- conda: https://conda.anaconda.org/bioconda/noarch/dendropy-5.0.8-pyhdfd78af_1.tar.bz2 +- conda: https://conda.anaconda.org/bioconda/linux-64/diamond-2.2.3-he361c42_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/dnspython-2.8.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/entrez-direct-24.0-he881be0_0.tar.bz2 +- conda: https://conda.anaconda.org/bioconda/linux-64/fasttree-2.2.0-h7b50bb2_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.1-h27c8c51_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.63.0-py312h8a5da7c_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.3-ha770c72_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/gawk-5.4.0-h0a3468a_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.15-hecca717_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/harfbuzz-12.2.0-h15599e2_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/hmmer-3.4-h503566f_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/htslib-1.23.1-h633afcb_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-75.1-he02047a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.18-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/jsoncpp-1.9.6-hf42df4d_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py312h0a2e395_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbde042b_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_1.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/libamd-3.3.3-h456b2da_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-0.25.1-h3f43e3d_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-8_h4a7cf45_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-1.85.0-h0ccab89_4.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-devel-1.85.0-h00ab1b0_4.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-headers-1.85.0-ha770c72_4.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbtf-2.3.2-hf02c80a_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcamd-3.3.3-hf02c80a_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libccolamd-3.3.4-hf02c80a_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcholmod-5.3.1-h9cf07ce_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcolamd-3.3.4-hf02c80a_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.21.0-hcf29cc6_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcxsparse-4.4.1-hf02c80a_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgettextpo-0.25.1-h3f43e3d_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-15.2.0-h69a702a_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.2-h0d30a3d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libidn2-2.3.8-hfac485b_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libklu-2.3.5-h95ff59c_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libldl-3.3.2-hf02c80a_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenssl-static-3.6.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libparu-1.0.0-hc6afc67_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/librbio-4.3.4-hf02c80a_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libspex-3.2.3-h9226d62_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libspqr-4.3.4-h23b7119_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.3-h0c1763c_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsuitesparseconfig-7.10.1-h901830b_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.2-h9d88235_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libumfpack-6.3.5-h873dde6_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libunistring-0.9.10-h7f98852_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/lp_solve-5.5.2.11-hd590300_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/mafft-7.526-h4bc722e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.10.9-py312he3d6523_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/metaeuk-7.bba0d80-pl5321hd6d6fdc_2.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/metis-5.1.0-hd0bcaf9_1007.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/miniprot-0.18-h577a1d6_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mpfr-4.2.2-he0a73b1_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/mpi-1.0-openmpi.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/muscle-3.8.1551-h9948957_9.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mysql-connector-c-6.1.11-h659d440_1008.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/ncbi-vdb-3.4.1-hd63eeec_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.3.5-py312h33ff503_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.1-h5755bd7_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/openmpi-4.1.6-hc5af2df_101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-3.0.3-py312h8ecdadd_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/pasta-1.9.3-py312h85383db_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre-8.45-h9c3ff4c_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-app-cpanminus-1.7048-pl5321hd8ed1ab_0.conda +- conda: https://conda.anaconda.org/bioconda/noarch/perl-archive-tar-3.12-pl5321hdfd78af_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-carp-1.50-pl5321hd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-class-method-modifiers-2.13-pl5321ha770c72_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-common-sense-3.75-pl5321hd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-compress-raw-bzip2-2.214-pl5321hda65f42_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-compress-raw-zlib-2.214-pl5321h4dac143_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-constant-1.33-pl5321hd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-dbi-1.649-pl5321hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-encode-3.24-pl5321hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-exporter-5.74-pl5321hd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-exporter-tiny-1.002002-pl5321hd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-extutils-makemaker-7.70-pl5321hd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-file-path-2.18-pl5321hd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-file-temp-0.2304-pl5321hd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-file-which-1.24-pl5321hd8ed1ab_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-inc-latest-0.500-pl5321ha770c72_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/perl-io-compress-2.216-pl5321h503566f_0.conda +- conda: https://conda.anaconda.org/bioconda/noarch/perl-io-zlib-1.15-pl5321hdfd78af_1.tar.bz2 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-json-4.11-pl5321hdfd78af_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/perl-json-xs-4.04-pl5321h9948957_0.conda +- conda: https://conda.anaconda.org/bioconda/noarch/perl-list-moreutils-0.430-pl5321hdfd78af_0.tar.bz2 +- conda: https://conda.anaconda.org/bioconda/linux-64/perl-list-moreutils-xs-0.430-pl5321h7b50bb2_5.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-module-build-0.4234-pl5321ha770c72_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-moo-2.005004-pl5321ha770c72_0.tar.bz2 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-parallel-forkmanager-2.04-pl5321hdfd78af_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-parent-0.243-pl5321hd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-pathtools-3.75-pl5321hb9d3cd8_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-role-tiny-2.002004-pl5321ha770c72_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-scalar-list-utils-1.70-pl5321hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-storable-3.15-pl5321hb9d3cd8_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-sub-quote-2.006006-pl5321ha770c72_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-test-fatal-0.016-pl5321ha770c72_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-try-tiny-0.31-pl5321ha770c72_0.tar.bz2 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-types-serialiser-1.01-pl5321hdfd78af_0.tar.bz2 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-yaml-1.30-pl5321hdfd78af_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.3.0-py312h50c33e8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/prank-251117-hd63eeec_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/procps-ng-4.0.6-h18c060e_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/prodigal-2.6.3-h577a1d6_11.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/pymongo-4.17.0-py312h1289d80_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_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.12.13-hd63d673_0_cpython.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/raxml-8.2.13-h7b50bb2_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.34.2-pyhcf101f3_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/samtools-1.23.1-ha83d96e_0.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/sepp-4.5.5-py312h0fa9677_3.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.3-hbc0de68_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/suitesparse-7.10.1-h5b2951e_7100101.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/tar-1.35-h3b78370_0.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/tzdata-2025c-hc9c84f9_1.conda +- conda: https://conda.anaconda.org/bioconda/linux-64/ucsc-fatotwobit-482-hdc0a859_0.tar.bz2 +- conda: https://conda.anaconda.org/bioconda/linux-64/ucsc-twobitinfo-482-hdc0a859_0.tar.bz2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/wget-1.25.0-h653f8fd_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.8.3-ha02ee65_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-gpl-tools-5.8.3-ha02ee65_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-tools-5.8.3-hb03c661_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_2.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/linux-64/alsa-lib-1.2.16.1-hb03c661_0.conda +sha256: cf93ca0f1f107e95a35969a4622684e08fcb8cf37f8cf4a1e9e424828386c921 +md5: 8904e09bda369377b3dd07e2ac828c5d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: LGPL-2.1-or-later +license_family: LGPL +size: 592377 +timestamp: 1781521980743 +- conda: https://conda.anaconda.org/bioconda/linux-64/augustus-3.5.0-pl5321h9716f88_9.conda +sha256: 383dad598de1014d694f1822172a9d25411617ed6f07d36e8287ebfe7e67c2ff +md5: aff97814997ccca7ada6f3131c1a75f6 +depends: +- bamtools >=2.5.3,<3.0a0 +- biopython +- boost-cpp +- cdbtools +- diamond +- gsl >=2.8 +- gsl >=2.8,<2.9.0a0 +- htslib >=1.22.1,<1.24.0a0 +- libamd >=3.3.3,<4.0a0 +- libblas >=3.9.0,<4.0a0 +- libbtf >=2.3.2,<3.0a0 +- libcamd >=3.3.3,<4.0a0 +- libcblas >=3.9.0,<4.0a0 +- libccolamd >=3.3.4,<4.0a0 +- libcholmod >=5.3.1,<6.0a0 +- libcolamd >=3.3.4,<4.0a0 +- libcxsparse >=4.4.1,<5.0a0 +- libgcc >=13 +- libklu >=2.3.5,<3.0a0 +- libldl >=3.3.2,<4.0a0 +- libparu >=1.0.0,<2.0a0 +- librbio >=4.3.4,<5.0a0 +- libspex >=3.2.3,<4.0a0 +- libspqr >=4.3.4,<5.0a0 +- libsqlite >=3.50.4,<4.0a0 +- libstdcxx >=13 +- libsuitesparseconfig >=7.10.1,<8.0a0 +- libumfpack >=6.3.5,<7.0a0 +- libzlib >=1.3.1,<2.0a0 +- lp_solve +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-app-cpanminus +- perl-dbi +- perl-file-which +- perl-module-build 0.4234.* +- perl-parallel-forkmanager +- perl-scalar-list-utils +- perl-yaml +- samtools >=1.22.1,<2.0a0 +- sqlite +- suitesparse >=7.10.1,<8.0a0 +- tar +- ucsc-fatotwobit +- ucsc-twobitinfo +license: Artistic License +license_family: Other +size: 27006331 +timestamp: 1755723767609 +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.6.0-py312h90b7ffd_0.conda +sha256: 95b3d6d44c17c4061db703289f39915646e455f75f0c8c9d949bf081d2e61579 +md5: 55811da425538da800b89c0c588652fa +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.12.* *_cp312 +- zstd >=1.5.7,<1.6.0a0 +license: BSD-3-Clause AND MIT AND EPL-2.0 +size: 239892 +timestamp: 1781450817988 +- conda: https://conda.anaconda.org/bioconda/linux-64/bamtools-2.5.3-he132191_0.tar.bz2 +sha256: 18d0c7e69cc6c775184ca7034d8e2f8b6de4a516c3de74792391882ef1bdcd0d +md5: e3302f3cd140ded877f39abe612bed08 +depends: +- jsoncpp >=1.9.6,<1.9.7.0a0 +- libgcc >=13 +- libstdcxx >=13 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 783519 +timestamp: 1747609084710 +- conda: https://conda.anaconda.org/bioconda/linux-64/bbmap-39.81-h9b5c0a0_1.conda +sha256: 96e2ed5f82a928fe6a71893e366166390c63034b45976211cf91baf90d4e41d9 +md5: 4af20865073c32418b8553da02e436bb +depends: +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=14 +- openjdk >=11.0.1 +- samtools >=1.23.1,<2.0a0 +license: BSD-3-Clause-LBNL +size: 93105368 +timestamp: 1774976438094 +- conda: https://conda.anaconda.org/conda-forge/linux-64/biopython-1.87-py312h4c3975b_0.conda +sha256: 8439485bab2f8ae5af4069b624d76186939c5218d3fdf33c49fc67a48605ccc5 +md5: 2eb5b71dfcfb2a316d0307eb696bf11e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- numpy +- python >=3.12,<3.13.0a0 +- python_abi 3.12.* *_cp312 +license: LicenseRef-Biopython +size: 3306754 +timestamp: 1774882187035 +- conda: https://conda.anaconda.org/bioconda/linux-64/blast-2.17.0-h66d330f_0.conda +sha256: 53a319c984d8aafcf7f2d7d4c21ad2590e1bacd674443e09d79ac19694ccf99a +md5: 405ce6d52eba06fcd48197ae1eb8f5a9 +depends: +- bzip2 >=1.0.8,<2.0a0 +- curl +- entrez-direct >=24.0,<25.0a0 +- libgcc >=13 +- libsqlite >=3.50.4,<4.0a0 +- libstdcxx >=13 +- libzlib >=1.3.1,<2.0a0 +- ncbi-vdb >=3.2.1,<4.0a0 +- perl +- perl-archive-tar +- perl-json +- perl-list-moreutils +- zlib +license: NCBI-PD +size: 84832339 +timestamp: 1754909742570 +- conda: https://conda.anaconda.org/conda-forge/linux-64/boost-cpp-1.85.0-h3c6214e_4.conda +sha256: dec1f52d8869b94a9cb2b4d9a727a00ae2c54e7b5a66a51d3d9f1c33159ebb45 +md5: cc4533eabf5caa8b4fbb56418d1617a9 +depends: +- bzip2 >=1.0.8,<2.0a0 +- icu >=75.1,<76.0a0 +- libboost-devel 1.85.0 h00ab1b0_4 +- libzlib >=1.3.1,<2.0a0 +- xz >=5.2.6,<6.0a0 +- zstd >=1.5.6,<1.6.0a0 +license: BSL-1.0 +size: 18122 +timestamp: 1722289881184 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-1.2.0-hed03a55_1.conda +sha256: e511644d691f05eb12ebe1e971fd6dc3ae55a4df5c253b4e1788b789bdf2dfa6 +md5: 8ccf913aaba749a5496c17629d859ed1 +depends: +- __glibc >=2.17,<3.0.a0 +- brotli-bin 1.2.0 hb03c661_1 +- libbrotlidec 1.2.0 hb03c661_1 +- libbrotlienc 1.2.0 hb03c661_1 +- libgcc >=14 +license: MIT +license_family: MIT +size: 20103 +timestamp: 1764017231353 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-bin-1.2.0-hb03c661_1.conda +sha256: 64b137f30b83b1dd61db6c946ae7511657eead59fdf74e84ef0ded219605aa94 +md5: af39b9a8711d4a8d437b52c1d78eb6a1 +depends: +- __glibc >=2.17,<3.0.a0 +- libbrotlidec 1.2.0 hb03c661_1 +- libbrotlienc 1.2.0 hb03c661_1 +- libgcc >=14 +license: MIT +license_family: MIT +size: 21021 +timestamp: 1764017221344 +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda +sha256: 49df13a1bb5e388ca0e4e87022260f9501ed4192656d23dc9d9a1b4bf3787918 +md5: 64088dffd7413a2dd557ce837b4cbbdb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.12,<3.13.0a0 +- python_abi 3.12.* *_cp312 +constrains: +- libbrotlicommon 1.2.0 hb03c661_1 +license: MIT +license_family: MIT +size: 368300 +timestamp: 1764017300621 +- conda: https://conda.anaconda.org/bioconda/noarch/busco-6.1.0-pyhdfd78af_1.conda +sha256: d80c2e51ad7017e6bb82e3fee982af5800ea507cdf4e46a8077936a81af3e96a +md5: 5750abc786560cfa22f409bc1cc16ca4 +depends: +- augustus >=3.3 +- bbmap +- biopython >=1.79 +- blast >=2.10.1 +- fonts-conda-ecosystem +- hmmer >=3.1b2 +- matplotlib-base +- metaeuk >=6.a5d39d9 +- miniprot +- numpy <2.4 +- pandas +- prodigal +- python >=3.3 +- requests +- sepp 4.5.5 +- wget +license: MIT +license_family: MIT +size: 355322 +timestamp: 1781104516494 +- 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/linux-64/c-ares-1.34.6-hb03c661_0.conda +sha256: cc9accf72fa028d31c2a038460787751127317dcfa991f8d1f1babf216bb454e +md5: 920bb03579f15389b9e512095ad995b7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 207882 +timestamp: 1765214722852 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.6.17-hbd8a1cb_0.conda +sha256: f8e3c730fa14ee3f170493779f06522c4acf89169f43db4f039727709b6419cf +md5: a9965dd99f683c5f444428f896635716 +depends: +- __unix +license: ISC +size: 128866 +timestamp: 1781708962055 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.4-h3394656_0.conda +sha256: 3bd6a391ad60e471de76c0e9db34986c4b5058587fbf2efa5a7f54645e28c2c7 +md5: 09262e66b19567aff4f592fb53b28760 +depends: +- __glibc >=2.17,<3.0.a0 +- fontconfig >=2.15.0,<3.0a0 +- fonts-conda-ecosystem +- freetype >=2.12.1,<3.0a0 +- icu >=75.1,<76.0a0 +- libexpat >=2.6.4,<3.0a0 +- libgcc >=13 +- libglib >=2.82.2,<3.0a0 +- libpng >=1.6.47,<1.7.0a0 +- libstdcxx >=13 +- libxcb >=1.17.0,<2.0a0 +- libzlib >=1.3.1,<2.0a0 +- pixman >=0.44.2,<1.0a0 +- xorg-libice >=1.1.2,<2.0a0 +- xorg-libsm >=1.2.5,<2.0a0 +- xorg-libx11 >=1.8.11,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: LGPL-2.1-only or MPL-1.1 +size: 978114 +timestamp: 1741554591855 +- conda: https://conda.anaconda.org/bioconda/linux-64/cdbtools-0.99-h077b44d_12.tar.bz2 +sha256: b70324c9af58110d40b8ed9b5210fe7829cadd59ffef66cf01fa818cc9476fa6 +md5: 6b938da47db28f06ca9258f92d80e7cb +depends: +- libgcc >=13 +- libstdcxx >=13 +- libzlib >=1.3.1,<2.0a0 +license: Public Domain +size: 80142 +timestamp: 1744771014271 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.6.17-pyhd8ed1ab_0.conda +sha256: 6c13620e458ba43278379d0cdacc30c497336bddfda81681fd50d114a65c702f +md5: c13824fedced67005d3832c152fe9c2f +depends: +- python >=3.10 +license: ISC +size: 133877 +timestamp: 1781719949728 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.8-pyhd8ed1ab_0.conda +sha256: a51c9aed4a0f364fe72f4730a19daef7370446b107cd5dd9a5d7ad6d00895de1 +md5: b2e6755844f4c74239dff62f1cb4adda +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 61278 +timestamp: 1783374645872 +- conda: https://conda.anaconda.org/bioconda/linux-64/clustalw-2.1-h9948957_12.tar.bz2 +sha256: d82a95c35cfdb590c266131fdbb0ec62c7977a1edbc95ac43a03220886c855a4 +md5: 5989fcb871dabc90d1bb5de3d5c79185 +depends: +- libgcc >=13 +- libstdcxx >=13 +license: LGPL-3.0-or-later +license_family: LGPL +size: 384703 +timestamp: 1738739696573 +- conda: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.3.3-py312h0a2e395_4.conda +sha256: 62447faf7e8eb691e407688c0b4b7c230de40d5ecf95bf301111b4d05c5be473 +md5: 43c2bc96af3ae5ed9e8a10ded942aa50 +depends: +- numpy >=1.25 +- python +- __glibc >=2.17,<3.0.a0 +- libstdcxx >=14 +- libgcc >=14 +- python_abi 3.12.* *_cp312 +license: BSD-3-Clause +license_family: BSD +size: 320386 +timestamp: 1769155979897 +- conda: https://conda.anaconda.org/conda-forge/linux-64/curl-8.21.0-hcf29cc6_1.conda +sha256: 8eb4ebeae7230110569da734e2420aee84f6977850bae4af94dc7f0b382f9d89 +md5: 58609be98a9725cd359a1c63ff329628 +depends: +- __glibc >=2.17,<3.0.a0 +- krb5 >=1.22.2,<1.23.0a0 +- libcurl 8.21.0 hcf29cc6_1 +- libgcc >=14 +- libssh2 >=1.11.1,<2.0a0 +- libzlib >=1.3.2,<2.0a0 +- openssl >=3.5.7,<4.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: curl +license_family: MIT +size: 194657 +timestamp: 1782802525727 +- conda: https://conda.anaconda.org/conda-forge/noarch/cycler-0.12.1-pyhcf101f3_2.conda +sha256: bb47aec5338695ff8efbddbc669064a3b10fe34ad881fb8ad5d64fbfa6910ed1 +md5: 4c2a8fef270f6c69591889b93f9f55c1 +depends: +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 14778 +timestamp: 1764466758386 +- conda: https://conda.anaconda.org/bioconda/noarch/dendropy-5.0.8-pyhdfd78af_1.tar.bz2 +sha256: 102790b465893f5a5c4c3fa045f677e23f990ecc6d1b61d240153c3569a5b99f +md5: 0fa94922431d1074792639704d19461d +depends: +- python >=3.6 +license: BSD-3-Clause +license_family: BSD +size: 335113 +timestamp: 1750372782364 +- conda: https://conda.anaconda.org/bioconda/linux-64/diamond-2.2.3-he361c42_0.conda +sha256: 171f8cd041aad153fe25b5f994d1e2084d7d3a6fb576172ba4520c1d47a6e1a2 +md5: a2fee5dc0c0e7a9837464ad9c17e451c +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libsqlite >=3.53.3,<4.0a0 +- libstdcxx >=14 +- libzlib >=1.3.2,<2.0a0 +license: GPL-3.0-or-later +license_family: GPL3 +size: 3078934 +timestamp: 1783427329995 +- conda: https://conda.anaconda.org/conda-forge/noarch/dnspython-2.8.0-pyhcf101f3_0.conda +sha256: ef1e7b8405997ed3d6e2b6722bd7088d4a8adf215e7c88335582e65651fb4e05 +md5: d73fdc05f10693b518f52c994d748c19 +depends: +- python >=3.10,<4.0.0 +- sniffio +- python +constrains: +- aioquic >=1.2.0 +- cryptography >=45 +- httpcore >=1.0.0 +- httpx >=0.28.0 +- h2 >=4.2.0 +- idna >=3.10 +- trio >=0.30 +- wmi >=1.5.1 +license: ISC +size: 196500 +timestamp: 1757292856922 +- conda: https://conda.anaconda.org/bioconda/linux-64/entrez-direct-24.0-he881be0_0.tar.bz2 +sha256: 71a8f349659c9c18efa544663de2db1a20b5e3d32f8e4e88cd33110a0caf4eb3 +md5: 52a3fabee9201c2c6093c13b4eaf29b4 +depends: +- wget +license: Public Domain +size: 17127014 +timestamp: 1748473197798 +- conda: https://conda.anaconda.org/bioconda/linux-64/fasttree-2.2.0-h7b50bb2_1.conda +sha256: d9a6d06fab5f22e5d6a0dfcaf2d51fa07fd9b080f12794ab53e60b1ea1d3ac97 +md5: 2d5c9b69e3dd027849eb8e29ca2bebae +depends: +- _openmp_mutex >=4.5 +- libgcc >=13 +- libgomp +license: GPL-2.0-or-later +license_family: GPL +size: 197973 +timestamp: 1764102501456 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-dejavu-sans-mono-2.37-hab24e00_0.tar.bz2 +sha256: 58d7f40d2940dd0a8aa28651239adbf5613254df0f75789919c4e6762054403b +md5: 0c96522c6bdaed4b1566d11387caaf45 +license: BSD-3-Clause +license_family: BSD +size: 397370 +timestamp: 1566932522327 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-inconsolata-3.000-h77eed37_0.tar.bz2 +sha256: c52a29fdac682c20d252facc50f01e7c2e7ceac52aa9817aaf0bb83f7559ec5c +md5: 34893075a5c9e55cdafac56607368fc6 +license: OFL-1.1 +license_family: Other +size: 96530 +timestamp: 1620479909603 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-source-code-pro-2.038-h77eed37_0.tar.bz2 +sha256: 00925c8c055a2275614b4d983e1df637245e19058d79fc7dd1a93b8d9fb4b139 +md5: 4d59c254e01d9cde7957100457e2d5fb +license: OFL-1.1 +license_family: Other +size: 700814 +timestamp: 1620479612257 +- conda: https://conda.anaconda.org/conda-forge/noarch/font-ttf-ubuntu-0.83-h77eed37_3.conda +sha256: 2821ec1dc454bd8b9a31d0ed22a7ce22422c0aef163c59f49dfdf915d0f0ca14 +md5: 49023d73832ef61042f6a237cb2687e7 +license: LicenseRef-Ubuntu-Font-Licence-Version-1.0 +license_family: Other +size: 1620504 +timestamp: 1727511233259 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fontconfig-2.18.1-h27c8c51_0.conda +sha256: 2e50bdcebdf70a865b81f2456bbc586386451ec601c60f2b6cd22b8c40a2d384 +md5: e0e050cfa9fa85fe39632ab11cb7f3e0 +depends: +- __glibc >=2.17,<3.0.a0 +- libexpat >=2.8.1,<3.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +- libgcc >=14 +- libuuid >=2.42.1,<3.0a0 +- libzlib >=1.3.2,<2.0a0 +license: MIT +license_family: MIT +size: 281880 +timestamp: 1780450077431 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-ecosystem-1-0.tar.bz2 +sha256: a997f2f1921bb9c9d76e6fa2f6b408b7fa549edd349a77639c9fe7a23ea93e61 +md5: fee5683a3f04bd15cbd8318b096a27ab +depends: +- fonts-conda-forge +license: BSD-3-Clause +license_family: BSD +size: 3667 +timestamp: 1566974674465 +- conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-hc364b38_1.conda +sha256: 54eea8469786bc2291cc40bca5f46438d3e062a399e8f53f013b6a9f50e98333 +md5: a7970cd949a077b7cb9696379d338681 +depends: +- font-ttf-ubuntu +- font-ttf-inconsolata +- font-ttf-dejavu-sans-mono +- font-ttf-source-code-pro +license: BSD-3-Clause +license_family: BSD +size: 4059 +timestamp: 1762351264405 +- conda: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.63.0-py312h8a5da7c_0.conda +sha256: d235ae7075642044ceb3d922ef2a710a82665755ac9bbb7e8dad7daa72bc6d87 +md5: 294fb524171e2a2748cb7fe708aba826 +depends: +- __glibc >=2.17,<3.0.a0 +- brotli +- libgcc >=14 +- munkres +- python >=3.12,<3.13.0a0 +- python_abi 3.12.* *_cp312 +- unicodedata2 >=15.1.0 +license: MIT +license_family: MIT +size: 3007892 +timestamp: 1778770568019 +- conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.14.3-ha770c72_0.conda +sha256: c934c385889c7836f034039b43b05ccfa98f53c900db03d8411189892ced090b +md5: 8462b5322567212beeb025f3519fb3e2 +depends: +- libfreetype 2.14.3 ha770c72_0 +- libfreetype6 2.14.3 h73754d4_0 +license: GPL-2.0-only OR FTL +size: 173839 +timestamp: 1774298173462 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gawk-5.4.0-h0a3468a_0.conda +sha256: 0c98fc1fd2d66dbac3f97e9721a523cd5a4bb15ad115a2dbb96d46a130a6f89a +md5: 85817e8a5230ebde83b9ca2a8282e004 +depends: +- gmp +- mpfr +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- readline >=8.3,<9.0a0 +- gmp >=6.3.0,<7.0a0 +- libasprintf >=0.25.1,<1.0a0 +- libgettextpo >=0.25.1,<1.0a0 +- mpfr >=4.2.2,<5.0a0 +license: GPL-3.0-or-later +license_family: GPL +size: 1505698 +timestamp: 1777297022541 +- conda: https://conda.anaconda.org/conda-forge/linux-64/giflib-5.2.2-hd590300_0.conda +sha256: aac402a8298f0c0cc528664249170372ef6b37ac39fdc92b40601a6aed1e32ff +md5: 3bf7b9fd5a7136126e0234db4b87c8b6 +depends: +- libgcc-ng >=12 +license: MIT +license_family: MIT +size: 77248 +timestamp: 1712692454246 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gmp-6.3.0-hac33072_2.conda +sha256: 309cf4f04fec0c31b6771a5809a1909b4b3154a2208f52351e1ada006f4c750c +md5: c94a5994ef49749880a8139cf9afcbe1 +depends: +- libgcc-ng >=12 +- libstdcxx-ng >=12 +license: GPL-2.0-or-later OR LGPL-3.0-or-later +size: 460055 +timestamp: 1718980856608 +- conda: https://conda.anaconda.org/conda-forge/linux-64/graphite2-1.3.15-hecca717_0.conda +sha256: 885fa7d1d7e2ad9ed0a700ee0d81ceb49de278253082d517959b22d6336eecce +md5: cf09e9fc938518e91d0706572cadf17a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: LGPL-2.0-or-later +license_family: LGPL +size: 100054 +timestamp: 1780454302233 +- conda: https://conda.anaconda.org/conda-forge/linux-64/gsl-2.8-hbf7d49c_1.conda +sha256: f923af07c3a3db746d3be8efebdaa9c819a6007ee3cc12445cee059641611e05 +md5: 04e128d2adafe3c844cde58f103c481b +depends: +- __glibc >=2.17,<3.0.a0 +- libblas >=3.9.0,<4.0a0 +- libcblas >=3.9.0,<4.0a0 +- libgcc >=13 +license: GPL-3.0-or-later +license_family: GPL +size: 2486744 +timestamp: 1737621160295 +- 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/linux-64/harfbuzz-12.2.0-h15599e2_0.conda +sha256: 6bd8b22beb7d40562b2889dc68232c589ff0d11a5ad3addd41a8570d11f039d9 +md5: b8690f53007e9b5ee2c2178dd4ac778c +depends: +- __glibc >=2.17,<3.0.a0 +- cairo >=1.18.4,<2.0a0 +- graphite2 >=1.3.14,<2.0a0 +- icu >=75.1,<76.0a0 +- libexpat >=2.7.1,<3.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libglib >=2.86.1,<3.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 2411408 +timestamp: 1762372726141 +- conda: https://conda.anaconda.org/bioconda/linux-64/hmmer-3.4-h503566f_3.tar.bz2 +sha256: d3c37ebbd6254cded0937c1f3d389f8c8c0ca59986aa61846c476e41a82e3c27 +md5: 0536103ba1af5d75454868affd7575c1 +depends: +- libgcc >=13 +- libstdcxx >=13 +license: BSD +size: 11627027 +timestamp: 1733932139092 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.2.0-pyhd8ed1ab_0.conda +sha256: fdcea5d7cb314485d3907192ef024c704311548c5b0cbeb390cd1951051e29d2 +md5: b395909221b9bd1df066e5930e18855b +depends: +- python >=3.10 +license: MIT +license_family: MIT +size: 32884 +timestamp: 1782283986153 +- conda: https://conda.anaconda.org/bioconda/linux-64/htslib-1.23.1-h633afcb_0.conda +sha256: d0977efb1885c9f00ca76ee13e7c0f9a8936bf271eec25ffa78606cd816a13c9 +md5: 209caa9e4ff0b9ed02dd09c3161917e5 +depends: +- bzip2 >=1.0.8,<2.0a0 +- libcurl >=8.19.0,<9.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- liblzma >=5.8.2,<6.0a0 +- libzlib >=1.3.1,<2.0a0 +- openssl >=3.5.5,<4.0a0 +license: MIT +license_family: MIT +size: 1195461 +timestamp: 1773854995668 +- 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-75.1-he02047a_0.conda +sha256: 71e750d509f5fa3421087ba88ef9a7b9be11c53174af3aa4d06aff4c18b38e8e +md5: 8b189310083baabfb622af68fd9d3ae3 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc-ng >=12 +- libstdcxx-ng >=12 +license: MIT +license_family: MIT +size: 12129203 +timestamp: 1720853576813 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.18-pyhcf101f3_0.conda +sha256: c75632ea624aa450a394f570749420c5a2e0997d0216bc29d5d45b0f39df0426 +md5: 577b04680ae422adb86fc60d7b940659 +depends: +- python >=3.10 +- python +license: BSD-3-Clause +license_family: BSD +size: 163869 +timestamp: 1781620148226 +- conda: https://conda.anaconda.org/conda-forge/linux-64/jsoncpp-1.9.6-hf42df4d_1.conda +sha256: ed4b1878be103deb2e4c6d0eea3c9bdddfd7fc3178383927dce7578fb1063520 +md5: 7bdc5e2cc11cb0a0f795bdad9732b0f2 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libstdcxx >=13 +license: LicenseRef-Public-Domain OR MIT +size: 169093 +timestamp: 1733780223643 +- conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda +sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 +md5: b38117a3c920364aff79f870c984b4a3 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: LGPL-2.1-or-later +size: 134088 +timestamp: 1754905959823 +- conda: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.5.0-py312h0a2e395_0.conda +sha256: eec7654c2d68f06590862c6e845cc70987b6d6559222b6f0e619dea4268f5dd5 +md5: cd74a9525dc74bbbf93cf8aa2fa9eb5b +depends: +- python +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.12.* *_cp312 +license: BSD-3-Clause +license_family: BSD +size: 77120 +timestamp: 1773067050308 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-hbde042b_1.conda +sha256: 9b07046870772f28740e3f6149f09ff222843733087a33c5540b169c6289652d +md5: 54157a1c8c0bb70f62dd0b17fba7e7f2 +depends: +- __glibc >=2.17,<3.0.a0 +- keyutils >=1.6.3,<2.0a0 +- libedit >=3.1.20250104,<3.2.0a0 +- libedit >=3.1.20250104,<4.0a0 +- libgcc >=14 +- libstdcxx >=14 +- openssl >=3.5.7,<4.0a0 +license: MIT +license_family: MIT +size: 1388990 +timestamp: 1781859420533 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.19.1-h0c24ade_1.conda +sha256: 112b5b9462572d970f4abd2912f76a25ee7db158b1e7260163d91dd8a630db84 +md5: 8b3ce45e929cd8e8e5f4d18586b56d8b +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.4.1,<4.0a0 +- libtiff >=4.7.1,<4.8.0a0 +license: MIT +license_family: MIT +size: 251971 +timestamp: 1780211695895 +- 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/libamd-3.3.3-h456b2da_7100101.conda +sha256: 5fc32a5497c9919ffde729a604b0acfa97c403ce5b2b27b28ca261cf0c4643aa +md5: a067596d679bcde85375143e7c374738 +depends: +- __glibc >=2.17,<3.0.a0 +- libgfortran5 >=13.3.0 +- libgfortran +- libgcc >=13 +- libsuitesparseconfig >=7.10.1,<8.0a0 +license: BSD-3-Clause +license_family: BSD +size: 48250 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libasprintf-0.25.1-h3f43e3d_1.conda +sha256: cb728a2a95557bb6a5184be2b8be83a6f2083000d0c7eff4ad5bbe5792133541 +md5: 3b0d184bc9404516d418d4509e418bdc +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libstdcxx >=14 +license: LGPL-2.1-or-later +size: 53582 +timestamp: 1753342901341 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-8_h4a7cf45_openblas.conda +build_number: 8 +sha256: b2da6bfd72a1c9cb143ccf64bf5b28790cb4eb58bd1cb978f6537b2322f7d48b +md5: 00fc660ab1b2f5ca07e92b4900d10c79 +depends: +- libopenblas >=0.3.33,<0.3.34.0a0 +- libopenblas >=0.3.33,<1.0a0 +constrains: +- blas 2.308 openblas +- mkl <2027 +- libcblas 3.11.0 8*_openblas +- liblapack 3.11.0 8*_openblas +- liblapacke 3.11.0 8*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18804 +timestamp: 1779859100675 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-1.85.0-h0ccab89_4.conda +sha256: dc19dfc636c363871763384219269ce6a027fcf3831f17e018caeecb2ffbb20a +md5: 4da1690badd566fc1041f91cd5655727 +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- icu >=75.1,<76.0a0 +- libgcc-ng >=12 +- libstdcxx-ng >=12 +- libzlib >=1.3.1,<2.0a0 +- xz >=5.2.6,<6.0a0 +- zstd >=1.5.6,<1.6.0a0 +constrains: +- boost-cpp =1.85.0 +license: BSL-1.0 +size: 2869710 +timestamp: 1722289756758 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-devel-1.85.0-h00ab1b0_4.conda +sha256: 04ec5a59e87d75cf6f8b539493f7f71c0cca3f50976251895f51da45e39cddf7 +md5: ded76b8670cb505006c891c4d45844a5 +depends: +- libboost 1.85.0 h0ccab89_4 +- libboost-headers 1.85.0 ha770c72_4 +constrains: +- boost-cpp =1.85.0 +license: BSL-1.0 +size: 40881 +timestamp: 1722289871820 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-headers-1.85.0-ha770c72_4.conda +sha256: 55aa2ac604bd7ed76fae0c93698d37aae455ca2fb229ff9aa45e085ff7ad48ec +md5: 00e4848983222729ccb7c69f1039f4b9 +constrains: +- boost-cpp =1.85.0 +license: BSL-1.0 +size: 13961521 +timestamp: 1722289776587 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda +sha256: 318f36bd49ca8ad85e6478bd8506c88d82454cc008c1ac1c6bf00a3c42fa610e +md5: 72c8fd1af66bd67bf580645b426513ed +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 79965 +timestamp: 1764017188531 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda +sha256: 12fff21d38f98bc446d82baa890e01fd82e3b750378fedc720ff93522ffb752b +md5: 366b40a69f0ad6072561c1d09301c886 +depends: +- __glibc >=2.17,<3.0.a0 +- libbrotlicommon 1.2.0 hb03c661_1 +- libgcc >=14 +license: MIT +license_family: MIT +size: 34632 +timestamp: 1764017199083 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda +sha256: a0c15c79997820bbd3fbc8ecf146f4fe0eca36cc60b62b63ac6cf78857f1dd0d +md5: 4ffbb341c8b616aa2494b6afb26a0c5f +depends: +- __glibc >=2.17,<3.0.a0 +- libbrotlicommon 1.2.0 hb03c661_1 +- libgcc >=14 +license: MIT +license_family: MIT +size: 298378 +timestamp: 1764017210931 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libbtf-2.3.2-hf02c80a_7100101.conda +sha256: fe36f414f48ab87251f02aeef1fcbb6f3929322316842dada0f8142db2710264 +md5: 6f4aec52002defbdf3e24eb79e56a209 +depends: +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- libsuitesparseconfig >=7.10.1,<8.0a0 +license: LGPL-2.1-or-later +size: 26913 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcamd-3.3.3-hf02c80a_7100101.conda +sha256: 16e9ae4e173a8606b0b8be118dbdcf4e03c9dd9777eea6bf9dff4397133d0d06 +md5: 1c9d1532caadece8adc2d14c6d4fc726 +depends: +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- libsuitesparseconfig >=7.10.1,<8.0a0 +license: BSD-3-Clause +license_family: BSD +size: 44119 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda +build_number: 8 +sha256: 1a2bc77bb26520255904a3d9b1f40e6bf0bf9d8d3405c7709dd162282820915a +md5: 33a413f1095f8325e5c30fde3b0d2445 +depends: +- libblas 3.11.0 8_h4a7cf45_openblas +constrains: +- blas 2.308 openblas +- liblapacke 3.11.0 8*_openblas +- liblapack 3.11.0 8*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18778 +timestamp: 1779859107964 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libccolamd-3.3.4-hf02c80a_7100101.conda +sha256: cc90aa5e0ad1f7ae9a29d9a42aacd7f7f02aba0bf5467513bfda7e6b18a4cbc8 +md5: e5107e02dc4c2f9f41eef72d72c23517 +depends: +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- libsuitesparseconfig >=7.10.1,<8.0a0 +license: BSD-3-Clause +license_family: BSD +size: 41578 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcholmod-5.3.1-h9cf07ce_7100101.conda +sha256: 69540315b4b8de93b383243334151ed19e98968baaa59440ba645a3bff68d765 +md5: f51e24ce110ae24c92074736a308e47e +depends: +- libgcc >=13 +- libstdcxx >=13 +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +- liblapack >=3.9.0,<4.0a0 +- libcolamd >=3.3.4,<4.0a0 +- libamd >=3.3.3,<4.0a0 +- libsuitesparseconfig >=7.10.1,<8.0a0 +- libccolamd >=3.3.4,<4.0a0 +- libblas >=3.9.0,<4.0a0 +- libcamd >=3.3.3,<4.0a0 +license: LGPL-2.1-or-later AND GPL-2.0-or-later AND Apache-2.0 +size: 990886 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcolamd-3.3.4-hf02c80a_7100101.conda +sha256: 00d1b976b914f0c20ae6f81f4e4713fa87717542eba8757b9a3c9e8abcc29858 +md5: 56d4c5542887e8955f21f8546ad75d9d +depends: +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- libsuitesparseconfig >=7.10.1,<8.0a0 +license: BSD-3-Clause +license_family: BSD +size: 33160 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcups-2.3.3-h7a8fb5f_6.conda +sha256: 205c4f19550f3647832ec44e35e6d93c8c206782bdd620c1d7cf66237580ff9c +md5: 49c553b47ff679a6a1e9fc80b9c5a2d4 +depends: +- __glibc >=2.17,<3.0.a0 +- krb5 >=1.22.2,<1.23.0a0 +- libgcc >=14 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +license: Apache-2.0 +license_family: Apache +size: 4518030 +timestamp: 1770902209173 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.21.0-hcf29cc6_1.conda +sha256: 7d243f45a48f62cb8e3b871dd336137fe0fb90094a191756fb553508837f6338 +md5: 2c1e55d695b11525c760b486ac0be517 +depends: +- __glibc >=2.17,<3.0.a0 +- krb5 >=1.22.2,<1.23.0a0 +- libgcc >=14 +- libnghttp2 >=1.68.1,<2.0a0 +- libssh2 >=1.11.1,<2.0a0 +- libzlib >=1.3.2,<2.0a0 +- openssl >=3.5.7,<4.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: curl +license_family: MIT +size: 478914 +timestamp: 1782802520033 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcxsparse-4.4.1-hf02c80a_7100101.conda +sha256: ab40fc8a4662f550d053576a56db896247bc81eb291eff3811f24c231829e3dd +md5: 917931d508582ef891bbac172294d9fb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- _openmp_mutex >=4.5 +- libsuitesparseconfig >=7.10.1,<8.0a0 +license: LGPL-2.1-or-later +size: 113979 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.25-h17f619e_0.conda +sha256: aa8e8c4be9a2e81610ddf574e05b64ee131fab5e0e3693210c9d6d2fba32c680 +md5: 6c77a605a7a689d17d4819c0f8ac9a00 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 73490 +timestamp: 1761979956660 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda +sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 +md5: c277e0a4d549b03ac1e9d6cbbe3d017b +depends: +- ncurses +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- ncurses >=6.5,<7.0a0 +license: BSD-2-Clause +license_family: BSD +size: 134676 +timestamp: 1738479519902 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda +sha256: 1cd6048169fa0395af74ed5d8f1716e22c19a81a8a36f934c110ca3ad4dd27b4 +md5: 172bf1cd1ff8629f2b1179945ed45055 +depends: +- libgcc-ng >=12 +license: BSD-2-Clause +license_family: BSD +size: 112766 +timestamp: 1702146165126 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.8.1-hecca717_1.conda +sha256: 16feffd9ddbbe5b718515d38ee376c685ba95491cd901244e24671d20b952a77 +md5: b24d3c612f71e7aa74158d92106318b2 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- expat 2.8.1.* +license: MIT +license_family: MIT +size: 77856 +timestamp: 1781203599810 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda +sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 +md5: a360c33a5abe61c07959e449fa1453eb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 58592 +timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.3-ha770c72_0.conda +sha256: 38f014a7129e644636e46064ecd6b1945e729c2140e21d75bb476af39e692db2 +md5: e289f3d17880e44b633ba911d57a321b +depends: +- libfreetype6 >=2.14.3 +license: GPL-2.0-only OR FTL +size: 8049 +timestamp: 1774298163029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype6-2.14.3-h73754d4_0.conda +sha256: 16f020f96da79db1863fcdd8f2b8f4f7d52f177dd4c58601e38e9182e91adf1d +md5: fb16b4b69e3f1dcfe79d80db8fd0c55d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libpng >=1.6.55,<1.7.0a0 +- libzlib >=1.3.2,<2.0a0 +constrains: +- freetype >=2.14.3 +license: GPL-2.0-only OR FTL +size: 384575 +timestamp: 1774298162622 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_19.conda +sha256: 8e0a3b5e41272e5678499b5dfc4cddb673f9e935de01eb0767ce857001229f46 +md5: 57736f29cc2b0ec0b6c2952d3f101b6a +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +constrains: +- libgcc-ng ==15.2.0=*_19 +- libgomp 15.2.0 he0feb66_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 1041084 +timestamp: 1778269013026 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_19.conda +sha256: 9dcf54adfaa5e861123c2da4f2f0451a685464ea7e5a41ad91cf67b31d658d98 +md5: 331ee9b72b9dff570d56b1302c5ab37d +depends: +- libgcc 15.2.0 he0feb66_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27694 +timestamp: 1778269016987 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgettextpo-0.25.1-h3f43e3d_1.conda +sha256: 50a9e9815cf3f5bce1b8c5161c0899cc5b6c6052d6d73a4c27f749119e607100 +md5: 2f4de899028319b27eb7a4023be5dfd2 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libiconv >=1.18,<2.0a0 +license: GPL-3.0-or-later +license_family: GPL +size: 188293 +timestamp: 1753342911214 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-15.2.0-h69a702a_19.conda +sha256: 561a42758ef25b9ce308c4e2cf56daee4f06138385a17e29a492cd928e00be6f +md5: 42bf7eca1a951735fa06c0e3c0d5c8e6 +depends: +- libgfortran5 15.2.0 h68bc16d_19 +constrains: +- libgfortran-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27655 +timestamp: 1778269042954 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-15.2.0-h69a702a_19.conda +sha256: 9ca1d254a3e44e608abec6186b18d372cec21e5253e6da9750f4a8f4780ea0bb +md5: 35d07243abf828674d273aecd1dd537e +depends: +- libgfortran 15.2.0 h69a702a_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27727 +timestamp: 1778269220455 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-15.2.0-h68bc16d_19.conda +sha256: 057978bb69fea29ed715a9b98adf71015c31baecc4aeb2bfc20d4fd5d83579d4 +md5: 85072b0ad177c966294f129b7c04a2d5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=15.2.0 +constrains: +- libgfortran 15.2.0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 2483673 +timestamp: 1778269025089 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.88.2-h0d30a3d_0.conda +sha256: 4bee10e62796f01e4fa2b5849135b1cc061337fe9cf5eb9bd79e9664922ae0e4 +md5: 889febc66cd9e4190f80ef9718fa239b +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libiconv >=1.18,<2.0a0 +- libzlib >=1.3.2,<2.0a0 +- libffi >=3.5.2,<3.6.0a0 +- pcre2 >=10.47,<10.48.0a0 +constrains: +- glib >2.66 +license: LGPL-2.1-or-later +size: 4754220 +timestamp: 1782463895250 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_19.conda +sha256: 5abe4ab9d93f6c9757d654f1969ae2267d4505315c1f2f8fe705fd60af084f1b +md5: faac990cb7aedc7f3a2224f2c9b0c26c +depends: +- __glibc >=2.17,<3.0.a0 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 603817 +timestamp: 1778268942614 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda +sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f +md5: 915f5995e94f60e9a4826e0b0920ee88 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: LGPL-2.1-only +size: 790176 +timestamp: 1754908768807 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libidn2-2.3.8-hfac485b_1.conda +sha256: cc38c900b9a20fe75e61cbb594e749c57a06d96510722f5ddfa309682062b065 +md5: 842a81de672ddcf476337c8bde3cad33 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libunistring >=0,<1.0a0 +license: LGPL-2.0-only +license_family: LGPL +size: 139036 +timestamp: 1760385590993 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.4.1-hb03c661_0.conda +sha256: 10056646c28115b174de81a44e23e3a0a3b95b5347d2e6c45cc6d49d35294256 +md5: 6178c6f2fb254558238ef4e6c56fb782 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- jpeg <0.0.0a +license: IJG AND BSD-3-Clause AND Zlib +size: 633831 +timestamp: 1775962768273 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libklu-2.3.5-h95ff59c_7100101.conda +sha256: 6b4d462642c240dc3671af74f7705b23f34eea0f71e0d9dbcf14b4ed008311ff +md5: efaa5e7dc6989363585fbb591480b256 +depends: +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +- metis >=5.1.0,<5.1.1.0a0 +- libcamd >=3.3.3,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- libcblas >=3.9.0,<4.0a0 +- libsuitesparseconfig >=7.10.1,<8.0a0 +- libcolamd >=3.3.4,<4.0a0 +- libamd >=3.3.3,<4.0a0 +- libcholmod >=5.3.1,<6.0a0 +- libblas >=3.9.0,<4.0a0 +- libbtf >=2.3.2,<3.0a0 +- libccolamd >=3.3.4,<4.0a0 +license: LGPL-2.1-or-later +size: 131775 +timestamp: 1741963824816 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda +build_number: 8 +sha256: 168e327d737059553e15cc6ec36d76b9bbb3931c2a7721555fd68b4c9348b247 +md5: 809be8ba8712c77bc7d44c2d99390dc4 +depends: +- libblas 3.11.0 8_h4a7cf45_openblas +constrains: +- blas 2.308 openblas +- libcblas 3.11.0 8*_openblas +- liblapacke 3.11.0 8*_openblas +license: BSD-3-Clause +license_family: BSD +size: 18790 +timestamp: 1779859115086 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libldl-3.3.2-hf02c80a_7100101.conda +sha256: 590232cd302047023ab31b80458833a71b10aeabee7474304dc65db322b5cd70 +md5: 19b71122fea7f6b1c4815f385b2da419 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libsuitesparseconfig >=7.10.1,<8.0a0 +license: LGPL-2.1-or-later +size: 23391 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_0.conda +sha256: ec30e52a3c1bf7d0425380a189d209a52baa03f22fb66dd3eb587acaa765bd6d +md5: b88d90cad08e6bc8ad540cb310a761fb +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- xz 5.8.3.* +license: 0BSD +size: 113478 +timestamp: 1775825492909 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-devel-5.8.3-hb03c661_0.conda +sha256: 7858f6a173206bc8a5bdc8e75690483bb66c0dcc3809ac1cb43c561a4723623a +md5: 55c20edec8e90c4703787acaade60808 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- liblzma 5.8.3 hb03c661_0 +license: 0BSD +size: 491429 +timestamp: 1775825511214 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.68.1-h877daf1_0.conda +sha256: 663444d77a42f2265f54fb8b48c5450bfff4388d9c0f8253dd7855f0d993153f +md5: 2a45e7f8af083626f009645a6481f12d +depends: +- __glibc >=2.17,<3.0.a0 +- c-ares >=1.34.6,<2.0a0 +- libev >=4.33,<4.34.0a0 +- libev >=4.33,<5.0a0 +- libgcc >=14 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- openssl >=3.5.5,<4.0a0 +license: MIT +license_family: MIT +size: 663344 +timestamp: 1773854035739 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda +sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 +md5: d864d34357c3b65a4b731f78c0801dc4 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: LGPL-2.1-only +license_family: GPL +size: 33731 +timestamp: 1750274110928 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-pthreads_h94d23a6_0.conda +sha256: 3d9aa85648e5e18a6d66db98b8c4317cc426721ad7a220aa86330d1ccedc8903 +md5: 2d3278b721e40468295ca755c3b84070 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libgfortran +- libgfortran5 >=14.3.0 +constrains: +- openblas >=0.3.33,<0.3.34.0a0 +license: BSD-3-Clause +license_family: BSD +size: 5931919 +timestamp: 1776993658641 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenssl-static-3.6.3-hb03c661_0.conda +sha256: ec9e1bc233830e8532df6cb91e210196909f9e7217693a995f0a5acf5e15008f +md5: b7fab41859799a59ede70d3bc608b8d6 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- openssl 3.6.3 h35e630c_0 +license: Apache-2.0 +license_family: Apache +size: 2889172 +timestamp: 1781069869884 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libparu-1.0.0-hc6afc67_7100101.conda +sha256: 50144e87b95d1309d2043aa5bf02035b948b1ae9ec6ec44ee97b7aec1cccd70a +md5: fd1d3e26c1b12c70f7449369ae3d9c1a +depends: +- libgcc >=13 +- libstdcxx >=13 +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +- libsuitesparseconfig >=7.10.1,<8.0a0 +- libblas >=3.9.0,<4.0a0 +- libumfpack >=6.3.5,<7.0a0 +license: GPL-3.0-or-later +license_family: GPL +size: 89738 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.58-h421ea60_0.conda +sha256: 377cfe037f3eeb3b1bf3ad333f724a64d32f315ee1958581fc671891d63d3f89 +md5: eba48a68a1a2b9d3c0d9511548db85db +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: zlib-acknowledgement +size: 317729 +timestamp: 1776315175087 +- conda: https://conda.anaconda.org/conda-forge/linux-64/librbio-4.3.4-hf02c80a_7100101.conda +sha256: c502b4203cc0d38f49005994b5c80c89660bcd40ff170c529cda90827ec6b1f4 +md5: 4b3a3d711d1c1f76f7f440e51458f512 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libsuitesparseconfig >=7.10.1,<8.0a0 +license: GPL-2.0-or-later +license_family: GPL +size: 46633 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libspex-3.2.3-h9226d62_7100101.conda +sha256: 24dffff614943c547ba094f8eb03b412a18cc4654663202f1aab9158bfa875ba +md5: 63323b258079a75133ccecbb0902614d +depends: +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +- libamd >=3.3.3,<4.0a0 +- libcolamd >=3.3.4,<4.0a0 +- libsuitesparseconfig >=7.10.1,<8.0a0 +- gmp >=6.3.0,<7.0a0 +- mpfr >=4.2.1,<5.0a0 +license: LGPL-2.0-or-later +license_family: LGPL +size: 79220 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libspqr-4.3.4-h23b7119_7100101.conda +sha256: 52851575496122f9088c9f5a4283da7fbb277d9a877b5ce60a939554df542f3c +md5: c1ee33a71065c1f0efd9c8174d5f18b0 +depends: +- libgcc >=13 +- libstdcxx >=13 +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- libcholmod >=5.3.1,<6.0a0 +- libblas >=3.9.0,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- libsuitesparseconfig >=7.10.1,<8.0a0 +license: GPL-2.0-or-later +license_family: GPL +size: 203419 +timestamp: 1741963824816 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.53.3-h0c1763c_0.conda +sha256: 365376f4815e5e80def2b3462a2419708b7c292da0da85278386c2618621fff4 +md5: 4aed8e657e9ff156bdbe849b4df44389 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libzlib >=1.3.2,<2.0a0 +license: blessing +size: 962119 +timestamp: 1782519076616 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-hcf80075_0.conda +sha256: fa39bfd69228a13e553bd24601332b7cfeb30ca11a3ca50bb028108fe90a7661 +md5: eecce068c7e4eddeb169591baac20ac4 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libzlib >=1.3.1,<2.0a0 +- openssl >=3.5.0,<4.0a0 +license: BSD-3-Clause +license_family: BSD +size: 304790 +timestamp: 1745608545575 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_19.conda +sha256: dff1058c76ec6b8759e41cefa2508162d00e4a5e6721aa68ec3fd10094e702dc +md5: 5794b3bdc38177caf969dabd3af08549 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc 15.2.0 he0feb66_19 +constrains: +- libstdcxx-ng ==15.2.0=*_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 5852044 +timestamp: 1778269036376 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-hdf11a46_19.conda +sha256: 0672b6b6e1791c92e8eccad58081a99d614fcf82bca5841f9dfa3c3e658f83b9 +md5: e5ce228e579726c07255dbf90dc62101 +depends: +- libstdcxx 15.2.0 h934c35e_19 +license: GPL-3.0-only WITH GCC-exception-3.1 +license_family: GPL +size: 27776 +timestamp: 1778269074600 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsuitesparseconfig-7.10.1-h901830b_7100101.conda +sha256: d8f32a0b0ee17fbace7af4bd34ad554cc855b9c18e0aeccf8395e1478c161f37 +md5: 57ae1dd979da7aa88a9b38bfa2e1d6b2 +depends: +- libgcc >=13 +- __glibc >=2.17,<3.0.a0 +- libgfortran5 >=13.3.0 +- libgfortran +- libgcc >=13 +- _openmp_mutex >=4.5 +license: BSD-3-Clause +license_family: BSD +size: 42708 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.7.2-h9d88235_0.conda +sha256: b31346e1c01ab40a170e91147092ee8fd92b1dee3c66ee47ef025571c879b159 +md5: c1fcb4a88bc15a9f77ad8d27d7af1df9 +depends: +- __glibc >=2.17,<3.0.a0 +- lerc >=4.1.0,<5.0a0 +- libdeflate >=1.25,<1.26.0a0 +- libgcc >=14 +- libjpeg-turbo >=3.1.4.1,<4.0a0 +- liblzma >=5.8.3,<6.0a0 +- libstdcxx >=14 +- libwebp-base >=1.6.0,<2.0a0 +- libzlib >=1.3.2,<2.0a0 +- zstd >=1.5.7,<1.6.0a0 +license: HPND +size: 452337 +timestamp: 1783084902636 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libumfpack-6.3.5-h873dde6_7100101.conda +sha256: 9a2c0049210c0223084c29b39404ad6da6538e7a4d1ed74ee8423212998fd686 +md5: 9626fc7667bc6c901c7a0a4004938c71 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libsuitesparseconfig >=7.10.1,<8.0a0 +- libcholmod >=5.3.1,<6.0a0 +- libblas >=3.9.0,<4.0a0 +- libamd >=3.3.3,<4.0a0 +license: GPL-2.0-or-later +license_family: GPL +size: 404065 +timestamp: 1741963824815 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libunistring-0.9.10-h7f98852_0.tar.bz2 +sha256: e88c45505921db29c08df3439ddb7f771bbff35f95e7d3103bf365d5d6ce2a6d +md5: 7245a044b4a1980ed83196176b78b73a +depends: +- libgcc-ng >=9.3.0 +license: GPL-3.0-only OR LGPL-3.0-only +size: 1433436 +timestamp: 1626955018689 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.2-h5347b49_0.conda +sha256: 9b1bdce27a7e31f7d241aeecff67a1f3101d52a2b1e33ccc2cdf2613072bf81f +md5: 01bb81d12c957de066ea7362007df642 +depends: +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +license: BSD-3-Clause +license_family: BSD +size: 40017 +timestamp: 1781625522462 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.6.0-hd42ef1d_0.conda +sha256: 3aed21ab28eddffdaf7f804f49be7a7d701e8f0e46c856d801270b470820a37b +md5: aea31d2e5b1091feca96fcfe945c3cf9 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +constrains: +- libwebp 1.6.0 +license: BSD-3-Clause +license_family: BSD +size: 429011 +timestamp: 1752159441324 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.17.0-h8a09558_0.conda +sha256: 666c0c431b23c6cec6e492840b176dde533d48b7e6fb8883f5071223433776aa +md5: 92ed62436b625154323d40d5f2f11dd7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- pthread-stubs +- xorg-libxau >=1.0.11,<2.0a0 +- xorg-libxdmcp +license: MIT +license_family: MIT +size: 395888 +timestamp: 1727278577118 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda +sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c +md5: 5aa797f8787fe7a17d1b0821485b5adc +depends: +- libgcc-ng >=12 +license: LGPL-2.1-or-later +size: 100393 +timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_2.conda +sha256: 55044c403570f0dc26e6364de4dc5368e5f3fc7ff103e867c487e2b5ab2bcda9 +md5: d87ff7921124eccd67248aa483c23fec +depends: +- __glibc >=2.17,<3.0.a0 +constrains: +- zlib 1.3.2 *_2 +license: Zlib +license_family: Other +size: 63629 +timestamp: 1774072609062 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lp_solve-5.5.2.11-hd590300_0.conda +sha256: 3c28e1494834f77cbd23467fdac0f701cb9a0c17a4251e79e83f0946e788abf9 +md5: c9ca19b1a4b4f1038b23fb8b5918929c +depends: +- libgcc-ng >=12 +license: LGPL-2.1-only +size: 410024 +timestamp: 1697545354266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mafft-7.526-h4bc722e_0.conda +sha256: e307b4d817c5f1d1173896d8d54b1b11761b0fc7889bf618ff59dd6407b11d36 +md5: cf3b2acf649bc31e576ed43a2fa4aaa3 +depends: +- __glibc >=2.17 +- __glibc >=2.17,<3.0.a0 +- gawk +- libgcc-ng >=12 +license: BSD-3-Clause +license_family: BSD +size: 2610460 +timestamp: 1720680384725 +- conda: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.10.9-py312he3d6523_0.conda +sha256: c7e133837376e53e6a52719c205a3067c42f05769bc3e8307417f8d817dfc63e +md5: 7d499b5b6d150f133800dc3a582771c7 +depends: +- __glibc >=2.17,<3.0.a0 +- contourpy >=1.0.1 +- cycler >=0.10 +- fonttools >=4.22.0 +- freetype +- kiwisolver >=1.3.1 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +- libgcc >=14 +- libstdcxx >=14 +- numpy >=1.23 +- numpy >=1.23,<3 +- packaging >=20.0 +- pillow >=8 +- pyparsing >=2.3.1 +- python >=3.12,<3.13.0a0 +- python-dateutil >=2.7 +- python_abi 3.12.* *_cp312 +- qhull >=2020.2,<2020.3.0a0 +- tk >=8.6.13,<8.7.0a0 +license: PSF-2.0 +license_family: PSF +size: 8336056 +timestamp: 1777000573501 +- conda: https://conda.anaconda.org/bioconda/linux-64/metaeuk-7.bba0d80-pl5321hd6d6fdc_2.tar.bz2 +sha256: 868647bb8b9a2827cdf98ba80310900b6b7d20fee438b59a1a68616db0452781 +md5: 92d44566468d6b5f4c854d5966069de4 +depends: +- _openmp_mutex >=4.5 +- bzip2 >=1.0.8,<2.0a0 +- gawk +- libgcc >=13 +- libstdcxx >=13 +- libzlib >=1.3.1,<2.0a0 +- perl >=5.32.1,<5.33.0a0 *_perl5 +- wget +- zlib +license: GPL-3 +license_family: GPL +size: 4534632 +timestamp: 1733936657790 +- conda: https://conda.anaconda.org/conda-forge/linux-64/metis-5.1.0-hd0bcaf9_1007.conda +sha256: e8a00971e6d00bd49f375c5d8d005b37a9abba0b1768533aed0f90a422bf5cc7 +md5: 28eb714416de4eb83e2cbc47e99a1b45 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libstdcxx >=13 +license: Apache-2.0 +license_family: APACHE +size: 3923560 +timestamp: 1728064567817 +- conda: https://conda.anaconda.org/bioconda/linux-64/miniprot-0.18-h577a1d6_0.tar.bz2 +sha256: a7785a0db01773819ba1c3b897d2987a5ec18f4c80165096c87d924c7e4e845b +md5: e60a264d0b4ba975ac1fb1c8e66753a3 +depends: +- libgcc >=13 +- libzlib >=1.3.1,<2.0a0 +license: MIT +license_family: MIT +size: 70915 +timestamp: 1752254293809 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mpfr-4.2.2-he0a73b1_0.conda +sha256: 8690f550a780f75d9c47f7ffc15f5ff1c149d36ac17208e50eda101ca16611b9 +md5: 85ce2ffa51ab21da5efa4a9edc5946aa +depends: +- __glibc >=2.17,<3.0.a0 +- gmp >=6.3.0,<7.0a0 +- libgcc >=14 +license: LGPL-3.0-only +license_family: LGPL +size: 730422 +timestamp: 1773413915171 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mpi-1.0-openmpi.tar.bz2 +sha256: 54cf44ee2c122bce206f834a825af06e3b14fc4fd58c968ae9329715cc281d1e +md5: 1dcc49e16749ff79ba2194fa5d4ca5e7 +license: BSD 3-clause +size: 4204 +- conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda +sha256: d09c47c2cf456de5c09fa66d2c3c5035aa1fa228a1983a433c47b876aa16ce90 +md5: 37293a85a0f4f77bbd9cf7aaefc62609 +depends: +- python >=3.9 +license: Apache-2.0 +license_family: Apache +size: 15851 +timestamp: 1749895533014 +- conda: https://conda.anaconda.org/bioconda/linux-64/muscle-3.8.1551-h9948957_9.tar.bz2 +sha256: 07f12b158989bd98b4d7af97a2739ccd7bbef0728ddc5a036bd9784363ab0ba9 +md5: abeab9c9f2802eae4f867260650837f6 +depends: +- libgcc >=13 +- libstdcxx >=13 +license: GPL-3.0-only +size: 273543 +timestamp: 1752497842816 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mysql-connector-c-6.1.11-h659d440_1008.conda +sha256: 0d796529e90bf6f511fd7199acfb5cc788e04d853e1afd48aa6bad33a6e49008 +md5: 149e0b89cbbe09397f1147cb3736bcbe +depends: +- libgcc-ng >=12 +- libstdcxx-ng >=12 +- openssl >=3.1.3,<4.0a0 +license: GPL-2.0-only +license_family: GPL +size: 1268505 +timestamp: 1697651492989 +- conda: https://conda.anaconda.org/bioconda/linux-64/ncbi-vdb-3.4.1-hd63eeec_0.conda +sha256: 1c876e74214ef7269de12286e1b9b370e3167c0825d215de3b81bf46f3956072 +md5: 70de9f284c305131b458cf69676f1b2f +depends: +- libgcc >=14 +- libstdcxx >=14 +license: Public Domain +size: 9227191 +timestamp: 1774474370894 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_0.conda +sha256: fc89f74bbe362fb29fa3c037697a89bec140b346a2469a90f7936d1d7ea4d8a3 +md5: fc21868a1a5aacc937e7a18747acb8a5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: X11 AND BSD-3-Clause +size: 918956 +timestamp: 1777422145199 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.3.5-py312h33ff503_1.conda +sha256: 76ad6a6f4761084b074a587fe1512956891f04b5250cec0fd39aca0f39ad122b +md5: 03baecffb72fa96fe234fd505908065f +depends: +- python +- __glibc >=2.17,<3.0.a0 +- libstdcxx >=14 +- libgcc >=14 +- libblas >=3.9.0,<4.0a0 +- liblapack >=3.9.0,<4.0a0 +- python_abi 3.12.* *_cp312 +- libcblas >=3.9.0,<4.0a0 +constrains: +- numpy-base <0a0 +license: BSD-3-Clause +license_family: BSD +size: 8820597 +timestamp: 1766383409220 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openjdk-25.0.1-h5755bd7_0.conda +sha256: 19b2268bf2d1fc4b4f48a68b9bfac620370c1b7f539671279053b0d3bcc348f1 +md5: a40ce38da029d1d272bfd9bd7510f901 +depends: +- __glibc >=2.17,<3.0.a0 +- alsa-lib >=1.2.14,<1.3.0a0 +- fontconfig >=2.15.0,<3.0a0 +- fonts-conda-ecosystem +- giflib >=5.2.2,<5.3.0a0 +- harfbuzz >=12.1.0 +- lcms2 >=2.17,<3.0a0 +- libcups >=2.3.3,<2.4.0a0 +- libfreetype >=2.14.1 +- libfreetype6 >=2.14.1 +- libgcc >=14 +- libjpeg-turbo >=3.1.0,<4.0a0 +- libpng >=1.6.50,<1.7.0a0 +- libstdcxx >=14 +- libzlib >=1.3.1,<2.0a0 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxi >=1.8.2,<2.0a0 +- xorg-libxrandr >=1.5.4,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +- xorg-libxt >=1.3.1,<2.0a0 +- xorg-libxtst >=1.2.5,<2.0a0 +license: GPL-2.0-or-later WITH Classpath-exception-2.0 +license_family: GPL +size: 117033638 +timestamp: 1762057253080 +- 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/openmpi-4.1.6-hc5af2df_101.conda +sha256: f0769dd891e1735be4606ec8643951e5cbca199f774e58c7d933f70a70134ce4 +md5: f9a2ad0088ee38f396350515fa37d243 +depends: +- libgcc-ng >=12 +- libgfortran-ng +- libgfortran5 >=12.3.0 +- libstdcxx-ng >=12 +- libzlib >=1.2.13,<2.0.0a0 +- mpi 1.0 openmpi +- zlib +constrains: +- cudatoolkit >= 10.2 +- ucx >=1.15.0,<2.0a0 +- libpmix ==0.0.0 +- libprrte ==0.0.0 +license: BSD-3-Clause +license_family: BSD +size: 4069632 +timestamp: 1696593196408 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.3-h35e630c_0.conda +sha256: d48f5c22b9897c01e4dff3680f1f57ceb02711ab9c62f74339b080419dfad34b +md5: 79dd2074b5cd5c5c6b2930514a11e22d +depends: +- __glibc >=2.17,<3.0.a0 +- ca-certificates +- libgcc >=14 +license: Apache-2.0 +license_family: Apache +size: 3159683 +timestamp: 1781069855778 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.2-pyhc364b38_0.conda +sha256: 3906abfb6511a3bb309e39b9b1b7bc38f50a723971de2395489fd1f379255890 +md5: 4c06a92e74452cfa53623a81592e8934 +depends: +- python >=3.8 +- python +license: Apache-2.0 +license_family: APACHE +size: 91574 +timestamp: 1777103621679 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-3.0.3-py312h8ecdadd_0.conda +sha256: 009408dcfdc789b8a1748d6a63fd2134ea2edc8474231ea7beba0ac3ad772a37 +md5: 15c437bfa4cbddd379b95357c9aa4150 +depends: +- python +- numpy >=1.26.0 +- python-dateutil >=2.8.2 +- libgcc >=14 +- libstdcxx >=14 +- __glibc >=2.17,<3.0.a0 +- python_abi 3.12.* *_cp312 +- numpy >=1.23,<3 +constrains: +- adbc-driver-postgresql >=1.2.0 +- adbc-driver-sqlite >=1.2.0 +- beautifulsoup4 >=4.12.3 +- blosc >=1.21.3 +- bottleneck >=1.4.2 +- fastparquet >=2024.11.0 +- fsspec >=2024.10.0 +- gcsfs >=2024.10.0 +- html5lib >=1.1 +- hypothesis >=6.116.0 +- jinja2 >=3.1.5 +- lxml >=5.3.0 +- matplotlib >=3.9.3 +- numba >=0.60.0 +- numexpr >=2.10.2 +- odfpy >=1.4.1 +- openpyxl >=3.1.5 +- psycopg2 >=2.9.10 +- pyarrow >=13.0.0 +- pyiceberg >=0.8.1 +- pymysql >=1.1.1 +- pyqt5 >=5.15.9 +- pyreadstat >=1.2.8 +- pytables >=3.10.1 +- pytest >=8.3.4 +- pytest-xdist >=3.6.1 +- python-calamine >=0.3.0 +- pytz >=2024.2 +- pyxlsb >=1.0.10 +- qtpy >=2.4.2 +- scipy >=1.14.1 +- s3fs >=2024.10.0 +- sqlalchemy >=2.0.36 +- tabulate >=0.9.0 +- xarray >=2024.10.0 +- xlrd >=2.0.1 +- xlsxwriter >=3.2.0 +- zstandard >=0.23.0 +license: BSD-3-Clause +license_family: BSD +size: 14872605 +timestamp: 1778602625175 +- conda: https://conda.anaconda.org/bioconda/linux-64/pasta-1.9.3-py312h85383db_1.conda +sha256: e93307492e9c4767e082db35dcf2274c7dd69f4a0e79cd20770a79198a32cfa1 +md5: a2760ddddfd4417f90003bb57a54e3b1 +depends: +- __glibc >=2.17,<3.0.a0 +- _openmp_mutex >=4.5 +- clustalw >=2.1,<3.0a0 +- dendropy >=5.0.8,<6.0a0 +- fasttree >=2.2.0,<3.0a0 +- hmmer >=3.4,<3.5.0a0 +- libgcc >=14 +- libgomp +- mafft >=7.526,<8.0a0 +- muscle <4 +- muscle >=3.8.1551,<4.0a0 +- openjdk +- openmpi >=4.1.6,<5.0a0 +- pcre >=8.45,<9.0a0 +- prank >=251117 +- pymongo +- python >=3.12,<3.13.0a0 +- python_abi 3.12.* *_cp312 +- raxml >=8.2.13,<9.0a0 +license: GPL-3.0-or-later +license_family: GPL3 +size: 1180080 +timestamp: 1781610923262 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre-8.45-h9c3ff4c_0.tar.bz2 +sha256: 8f35c244b1631a4f31fb1d66ab6e1d9bfac0ca9b679deced1112c7225b3ad138 +md5: c05d1820a6d34ff07aaaab7a9b7eddaa +depends: +- libgcc-ng >=9.3.0 +- libstdcxx-ng >=9.3.0 +license: BSD-3-Clause +license_family: BSD +size: 259377 +timestamp: 1623788789327 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda +sha256: 5e6f7d161356fefd981948bea5139c5aa0436767751a6930cb1ca801ebb113ff +md5: 7a3bff861a6583f1889021facefc08b1 +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +license: BSD-3-Clause +license_family: BSD +size: 1222481 +timestamp: 1763655398280 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda +build_number: 7 +sha256: 9ec32b6936b0e37bcb0ed34f22ec3116e75b3c0964f9f50ecea5f58734ed6ce9 +md5: f2cfec9406850991f4e3d960cc9e3321 +depends: +- libgcc-ng >=12 +- libxcrypt >=4.4.36 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 13344463 +timestamp: 1703310653947 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-app-cpanminus-1.7048-pl5321hd8ed1ab_0.conda +sha256: 20850458e691b12fc4da209e204fc4c4d1abe93311913929dc536b9b3857b681 +md5: adb8fae79589a7bb03aa9ad976e3bd92 +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 229935 +timestamp: 1730267467434 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-archive-tar-3.12-pl5321hdfd78af_0.conda +sha256: fb56a9489a87fc238fc70da7a2329495204eec30f7a5f5af1014a6fb22b528f4 +md5: 4ee2727440bf9b0b055c1f17a72701f6 +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +- perl-io-compress +- perl-io-zlib +- perl-pathtools +license: Perl_5 +size: 38811 +timestamp: 1780439474451 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-carp-1.50-pl5321hd8ed1ab_0.tar.bz2 +sha256: 1981e31113e1e77a2cdc13db657c636f047cd3be2a64d9a0bffac03c5427c1bd +md5: bdddc03e28019b902da71b722f2288d7 +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +- perl-exporter +- perl-extutils-makemaker +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 22257 +timestamp: 1636653208008 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-class-method-modifiers-2.13-pl5321ha770c72_0.tar.bz2 +sha256: bed763551ecf5e47249f4596b642f6279d64ee6e1c73998236456829c29ea6c2 +md5: 7b7ec3dd22b056c2d5ea53f9033c26b8 +depends: +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-test-fatal 0.016.* +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 22098 +timestamp: 1666342663240 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-common-sense-3.75-pl5321hd8ed1ab_0.tar.bz2 +sha256: 38ef218e9b9d55b9fbdce6b31cf81bcf6f1b16f21b8e7cb9279b41399522a320 +md5: ef70dc77e8b10bbb62f5e843b401ef0e +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 20291 +timestamp: 1660429950685 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-compress-raw-bzip2-2.214-pl5321hda65f42_0.conda +sha256: 2cbd3fcb7028415654057ab3142cee1e5cc4cf9bdd0e590f072e8ecd29cb6382 +md5: 1ec33b9f74a71c17cc5579e35027832a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- perl >=5.32.1,<5.33.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 55733 +timestamp: 1761332551110 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-compress-raw-zlib-2.214-pl5321h4dac143_0.conda +sha256: 4fd3a11f8dbd2c9d1a1c5547e344ad20412a3f0d36967502d9764e1b2734dd47 +md5: 943e7033e6f709adf0d89a3af51ab81b +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- perl >=5.32.1,<5.33.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 81114 +timestamp: 1761332700914 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-constant-1.33-pl5321hd8ed1ab_0.tar.bz2 +sha256: cfd5ef9af8de221292f7059d1ff88ff10f1340fc4dbbd0dc81ce2275bf76651d +md5: 7f9fc9cfa08a3fe36ffcff820c65c3ac +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 15711 +timestamp: 1636645107290 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-dbi-1.649-pl5321hb03c661_0.conda +sha256: 714c4922a4b7e84862c5daa22466d4bac874061bf8390c4b90f0ca2a319db768 +md5: 180ac4ad798ea3aae1065017f7b80602 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- perl >=5.32.1,<5.33.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 601329 +timestamp: 1782243103202 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-encode-3.24-pl5321hb03c661_0.conda +sha256: c83d8de38ce43ca15af05f76bc933ff76894aef84baed47300e463dae0c11857 +md5: 35776d4c5766e9d98754d1e7530c2961 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-exporter +- perl-parent +- perl-storable +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 1725053 +timestamp: 1780396038421 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-exporter-5.74-pl5321hd8ed1ab_0.tar.bz2 +sha256: 42271d0b79043a10a89044acb5febea50046b745dd2fc37e02943bc3bc75bf8e +md5: fd2eac4e35f8c970870a3961c1df3e29 +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 19071 +timestamp: 1636696009075 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-exporter-tiny-1.002002-pl5321hd8ed1ab_0.tar.bz2 +sha256: abdf86828a12a389d0feb0d70501b267842557bae11820e266526aeb6ab2bebe +md5: 48d709826875be1f2c108d3d1d8efec7 +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 28592 +timestamp: 1660341479867 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-extutils-makemaker-7.70-pl5321hd8ed1ab_0.conda +sha256: 1d3f342ca74cf2948c3edcfe0d3367b1db0fc64bb163393a2e025336dec3a40c +md5: ec3e57ed34f7765bfc7054a05868ce5d +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 157323 +timestamp: 1679847836884 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-file-path-2.18-pl5321hd8ed1ab_0.tar.bz2 +sha256: ac7a0e0c36ec199709c8523132ded35efb84941a1a476b271fd25362dfbf5339 +md5: e13e456f61b8261ba074c0aa93086afe +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +- perl-exporter +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 22382 +timestamp: 1636696260633 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-file-temp-0.2304-pl5321hd8ed1ab_0.tar.bz2 +sha256: 91f9fe152b38441386053876198d0c9437e7b4b5fa7da1e5db48b9e1b21fdae9 +md5: 0a039c4fc36748942287ee10d0431515 +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +- perl-carp +- perl-constant +- perl-exporter +- perl-file-path +- perl-parent +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 31509 +timestamp: 1636696164992 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-file-which-1.24-pl5321hd8ed1ab_0.tar.bz2 +sha256: 901e9c4177b6bdb23600446fd64a105a437112e63bc23a6163f669bc5098c502 +md5: 94e5b2c9d56ef7c4c70ddf51ac38ae3d +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 17329 +timestamp: 1636695979827 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-inc-latest-0.500-pl5321ha770c72_0.conda +sha256: ff6b6ffffd6ecbed19a00ee41bb54c283d171f3feff7f45e840441551b5ab876 +md5: 0879971f134628d37bc4b13581113134 +depends: +- perl >=5.32.1,<5.33.0a0 *_perl5 +license: Apache-2.0 +license_family: APACHE +size: 16039 +timestamp: 1669240163980 +- conda: https://conda.anaconda.org/bioconda/linux-64/perl-io-compress-2.216-pl5321h503566f_0.conda +sha256: 5241c33cf55ba0cbfc0ccab96b4a31123761db00310eab4fedd7a95226c4fca7 +md5: 0784cb3c120f934a5fe61961c8238330 +depends: +- libgcc >=13 +- libstdcxx >=13 +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-compress-raw-bzip2 >=2.214 +- perl-compress-raw-zlib >=2.214 +- perl-encode +- perl-scalar-list-utils +license: Perl_5 +size: 87231 +timestamp: 1769815108308 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-io-zlib-1.15-pl5321hdfd78af_1.tar.bz2 +sha256: 771a44b338cac68a22893897450222b886e24bbb291b014897d561f2ba3b588f +md5: db92645dabe9467115729e4479841b5d +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 12760 +timestamp: 1752069858135 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-json-4.11-pl5321hdfd78af_0.conda +sha256: 1c1649f491c76f4ae2984b547701df91c8abfda2e3b7b44e0c007f5e78a87c08 +md5: 56411755d21870a9ec16c76fd7b66dba +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +- perl-json-xs +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 52845 +timestamp: 1774152885168 +- conda: https://conda.anaconda.org/bioconda/linux-64/perl-json-xs-4.04-pl5321h9948957_0.conda +sha256: f16cf35917a5d75fb55cfc69d8651dc72ff4e06370142b447a4864f5de7d97c6 +md5: 7916b2e794393b3389535ba750f489da +depends: +- libgcc >=13 +- libstdcxx >=13 +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-common-sense +- perl-types-serialiser +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 70770 +timestamp: 1757352008878 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-list-moreutils-0.430-pl5321hdfd78af_0.tar.bz2 +sha256: 2190cc8430bb218ea80f5fc5e2bf75e4e20a27fb83e8c3cb789a18c32854a56c +md5: 7f04c79d216d0f8e7b6d5a51de4aafa0 +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +- perl-exporter-tiny +- perl-list-moreutils-xs >=0.430 +license: apache_2_0 +size: 32468 +timestamp: 1644871004171 +- conda: https://conda.anaconda.org/bioconda/linux-64/perl-list-moreutils-xs-0.430-pl5321h7b50bb2_5.tar.bz2 +sha256: fe2d360770fe5b856ee1e625eac6b07cea386c64b0866e323c6535eb62b9ceee +md5: 9192770eb08524038c3fcf24e915b10c +depends: +- libgcc >=13 +- perl >=5.32.1,<5.33.0a0 *_perl5 +license: apache_2_0 +size: 51506 +timestamp: 1741776389435 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-module-build-0.4234-pl5321ha770c72_1.conda +sha256: 40bc64172a969e87ade758320049c86c6a0d83cf8aeaa69ad218fa463ac6cb5b +md5: 358d42e9f08dd917b649089526e2ae1f +depends: +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-inc-latest 0.500.* +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 137087 +timestamp: 1738241035046 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-moo-2.005004-pl5321ha770c72_0.tar.bz2 +sha256: e82a11e50392c965e88db4cba4d23ed0be5c4917319385ea23d32d9484246227 +md5: 3499fef1ed2c74f253b1f032f22deb51 +depends: +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-class-method-modifiers 2.13.* +- perl-role-tiny 2.002004.* +- perl-sub-quote 2.006006.* +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 47669 +timestamp: 1666344231925 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-parallel-forkmanager-2.04-pl5321hdfd78af_0.conda +sha256: d71f83a9d415beb11e4f9832122236cd13686393f6336863ebc8a46d5e3e315f +md5: c0d5b1238870d70b3af64854901d7f62 +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +- perl-carp +- perl-file-path +- perl-file-temp +- perl-moo +- perl-storable +license: perl_5 +size: 24120 +timestamp: 1756574734791 +- conda: https://conda.anaconda.org/conda-forge/noarch/perl-parent-0.243-pl5321hd8ed1ab_0.conda +sha256: ec57d9e56ba86d840d5a9e65c665365fb6a290851cd13e6719628f3295eabf34 +md5: 314caa3b72d65f8078d426c6721dcacc +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 13933 +timestamp: 1733429736293 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-pathtools-3.75-pl5321hb9d3cd8_2.conda +sha256: a80bc265aa749ae03fdd6d5f2098312ea6f43cc193ea7aba0e6e4304d84ce8c0 +md5: 03d88c89dfac8a26adcdeff242f94007 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-carp +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 50681 +timestamp: 1741783312134 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-role-tiny-2.002004-pl5321ha770c72_0.tar.bz2 +sha256: 7895ed40c44c08ee3ddbb48a3ee70e1eda32a6c529b632af98663e7603adda08 +md5: 83b5b630aeddca09e26fded9af4f3ce5 +depends: +- perl >=5.32.1,<5.33.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 23283 +timestamp: 1666339833893 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-scalar-list-utils-1.70-pl5321hb03c661_0.conda +sha256: 00678b34a57df53fa31585ff1579f42a6dfc8b1b059fd1b386c6e89573959a9f +md5: 046486011bf7674e3c2f2a1513ac4f3d +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- perl >=5.32.1,<5.33.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 51958 +timestamp: 1753965684679 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-storable-3.15-pl5321hb9d3cd8_2.conda +sha256: 25beba40154a394189d0ff2afd31683d79c9106d47e77e12d20900d053dffaf6 +md5: 212f63a5c7c753ecf0a74c349b9270c5 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- perl >=5.32.1,<5.33.0a0 *_perl5 +license: GPL-1.0-or-later OR Artistic-1.0-Perl +license_family: OTHER +size: 71475 +timestamp: 1741353849888 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-sub-quote-2.006006-pl5321ha770c72_0.tar.bz2 +sha256: 4200429318a1a2d9276c4095bb63e29d655fc98208341b6db0752788d3016587 +md5: 3d58e92f33b2382c10ac7eccd883a42f +depends: +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-test-fatal 0.016.* +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 26698 +timestamp: 1666342630627 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-test-fatal-0.016-pl5321ha770c72_0.tar.bz2 +sha256: d5420f90b3bca641cdad0c5674b356a060bf1587e82d3828f382a466bdaba6d1 +md5: 5c397b1fd3095004f4ff149af1c0dd3c +depends: +- perl >=5.32.1,<5.33.0a0 *_perl5 +- perl-try-tiny 0.31.* +license: GPL-1.0-or-later OR Artistic-1.0-Perl +size: 19528 +timestamp: 1666339958976 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-try-tiny-0.31-pl5321ha770c72_0.tar.bz2 +sha256: 7e74c95eb085b095a258a22ee2f30192d79f23a58cbbcb8ca2b14f4fe0a8c406 +md5: cc23b14ed56bf51d84832d98ebd156af +depends: +- perl >=5.32.1,<5.33.0a0 *_perl5 +license: MIT +license_family: MIT +size: 17704 +timestamp: 1659695570098 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-types-serialiser-1.01-pl5321hdfd78af_0.tar.bz2 +sha256: 20f61217b16235d0161ad6fa0a234585afcc04ec5a6142c65b5867e26216dfe3 +md5: cfc65753e827bbef80c00eaa395f6ae7 +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +- perl-common-sense +license: perl_5 +size: 13136 +timestamp: 1644512391683 +- conda: https://conda.anaconda.org/bioconda/noarch/perl-yaml-1.30-pl5321hdfd78af_0.tar.bz2 +noarch: true +sha256: 6813626ecc8859b4f16de20f35c9bfdfbdf0a60d7da33494bca6c0c34511a76e +md5: da9ef80f4c4c2374d7f4ec7af6d96b6a +depends: +- perl >=5.32.1,<6.0a0 *_perl5 +license: perl_5 +size: 43572 +timestamp: 1644444148032 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-12.3.0-py312h50c33e8_0.conda +sha256: 76b2e56c7a903a06be1210d35f35c2a8dcdc57912fda5c96b2e68acfd2b281fe +md5: d749d04e1965315078f29320565c595a +depends: +- python +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +- libtiff >=4.7.1,<4.8.0a0 +- libxcb >=1.17.0,<2.0a0 +- tk >=8.6.13,<8.7.0a0 +- openjpeg >=2.5.4,<3.0a0 +- zlib-ng >=2.3.3,<2.4.0a0 +- python_abi 3.12.* *_cp312 +- libjpeg-turbo >=3.1.4.1,<4.0a0 +- lcms2 >=2.19.1,<3.0a0 +- libfreetype >=2.14.3 +- libfreetype6 >=2.14.3 +- libwebp-base >=1.6.0,<2.0a0 +license: HPND +size: 1064129 +timestamp: 1782912080163 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.46.4-h54a6638_1.conda +sha256: 43d37bc9ca3b257c5dd7bf76a8426addbdec381f6786ff441dc90b1a49143b6a +md5: c01af13bdc553d1a8fbfff6e8db075f0 +depends: +- libgcc >=14 +- libstdcxx >=14 +- libgcc >=14 +- __glibc >=2.17,<3.0.a0 +license: MIT +license_family: MIT +size: 450960 +timestamp: 1754665235234 +- conda: https://conda.anaconda.org/bioconda/linux-64/prank-251117-hd63eeec_0.conda +sha256: b1b6b8c79e42951a2a9a549a15b53cd080d738df187e1af7b9b5c455926035e9 +md5: 62e656e8faac6f46598cfdda62215869 +depends: +- libgcc >=14 +- libstdcxx >=14 +license: GPL-3.0-or-later +license_family: GPL3 +size: 453551 +timestamp: 1775699386639 +- 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/bioconda/linux-64/prodigal-2.6.3-h577a1d6_11.tar.bz2 +sha256: 1211d9f01128f141154cb4616aa5b15890afc26699767886f6655cabfd67ec06 +md5: 7b083f573760cbd88a206e05f73f5e9d +depends: +- libgcc >=13 +- libzlib >=1.3.1,<2.0a0 +license: GPL-3.0-or-later +license_family: GPL3 +size: 601984 +timestamp: 1752712731224 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-hb9d3cd8_1002.conda +sha256: 9c88f8c64590e9567c6c80823f0328e58d3b1efb0e1c539c0315ceca764e0973 +md5: b3c17d95b5a10c6e64a21fa17573e70e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 8252 +timestamp: 1726802366959 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pymongo-4.17.0-py312h1289d80_0.conda +sha256: 9d5c726b2f6cf3aa0a384a4807789d1153e7e4696f01d3aaa9fd1bd978912342 +md5: 955dab0e5b7f1299628c6ca58c1a8d05 +depends: +- __glibc >=2.17,<3.0.a0 +- dnspython <3.0.0,>=2.6.1 +- libgcc >=14 +- libstdcxx >=14 +- python >=3.12,<3.13.0a0 +- python_abi 3.12.* *_cp312 +license: Apache-2.0 +license_family: APACHE +size: 2400390 +timestamp: 1776765918970 +- conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.3.2-pyhcf101f3_0.conda +sha256: 417fba4783e528ee732afa82999300859b065dc59927344b4859c64aae7182de +md5: 3687cc0b82a8b4c17e1f0eb7e47163d5 +depends: +- python >=3.10 +- python +license: MIT +license_family: MIT +size: 110893 +timestamp: 1769003998136 +- 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.12.13-hd63d673_0_cpython.conda +sha256: a44655c1c3e1d43ed8704890a91e12afd68130414ea2c0872e154e5633a13d7e +md5: 7eccb41177e15cc672e1babe9056018e +depends: +- __glibc >=2.17,<3.0.a0 +- bzip2 >=1.0.8,<2.0a0 +- ld_impl_linux-64 >=2.36.1 +- libexpat >=2.7.4,<3.0a0 +- libffi >=3.5.2,<3.6.0a0 +- libgcc >=14 +- liblzma >=5.8.2,<6.0a0 +- libnsl >=2.0.1,<2.1.0a0 +- libsqlite >=3.51.2,<4.0a0 +- libuuid >=2.41.3,<3.0a0 +- libxcrypt >=4.4.36 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +- openssl >=3.5.5,<4.0a0 +- readline >=8.3,<9.0a0 +- tk >=8.6.13,<8.7.0a0 +- tzdata +constrains: +- python_abi 3.12.* *_cp312 +license: Python-2.0 +size: 31608571 +timestamp: 1772730708989 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0.post0-pyhe01879c_2.conda +sha256: d6a17ece93bbd5139e02d2bd7dbfa80bee1a4261dced63f65f679121686bf664 +md5: 5b8d21249ff20967101ffa321cab24e8 +depends: +- python >=3.9 +- six >=1.5 +- python +license: Apache-2.0 +license_family: APACHE +size: 233310 +timestamp: 1751104122689 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda +build_number: 8 +sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809 +md5: c3efd25ac4d74b1584d2f7a57195ddf1 +constrains: +- python 3.12.* *_cpython +license: BSD-3-Clause +license_family: BSD +size: 6958 +timestamp: 1752805918820 +- conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda +sha256: 776363493bad83308ba30bcb88c2552632581b143e8ee25b1982c8c743e73abc +md5: 353823361b1d27eb3960efb076dfcaf6 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc-ng >=12 +- libstdcxx-ng >=12 +license: LicenseRef-Qhull +size: 552937 +timestamp: 1720813982144 +- conda: https://conda.anaconda.org/bioconda/linux-64/raxml-8.2.13-h7b50bb2_3.tar.bz2 +sha256: 2a974acb73d07dc7e142c997101f14ce865ea4b8f8fb203849002848c37171b9 +md5: 48880314905ab03663a8fb4d97c835ff +depends: +- libgcc >=13 +license: GPL +size: 3227304 +timestamp: 1734060260551 +- 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/requests-2.34.2-pyhcf101f3_0.conda +sha256: 1715246b19c9f85ee022933b4845f2fc14ac9184981b7b7d9b728bec8e9588da +md5: 4a85203c1d80c1059086ae860836ffb9 +depends: +- python >=3.10 +- certifi >=2023.5.7 +- charset-normalizer >=2,<4 +- idna >=2.5,<4 +- urllib3 >=1.26,<3 +- python +constrains: +- chardet >=3.0.2,<8 +license: Apache-2.0 +license_family: APACHE +size: 68709 +timestamp: 1778851103479 +- conda: https://conda.anaconda.org/bioconda/linux-64/samtools-1.23.1-ha83d96e_0.conda +sha256: 2cb721907a2df7c54580298d655ae7587dbed593bd5536fa8ef4a22c9ae2a496 +md5: 89624fbd17c069abcbc8b19b96d497a0 +depends: +- htslib >=1.23.1,<1.24.0a0 +- libgcc >=14 +- libzlib >=1.3.1,<2.0a0 +- ncurses >=6.5,<7.0a0 +license: MIT +size: 489995 +timestamp: 1773861794171 +- conda: https://conda.anaconda.org/bioconda/linux-64/sepp-4.5.5-py312h0fa9677_3.tar.bz2 +sha256: 5fbf02bc26469c1906a13a9d51bea271bb39587be85867d5f79ee6edae91acce +md5: fa93b481d4e0b4632e24d57434d3e41f +depends: +- dendropy >=5.0.6,<6.0a0 +- hmmer >=3.4,<3.5.0a0 +- libgcc >=13 +- pasta +- python >=3.12,<3.13.0a0 +- python_abi 3.12.* *_cp312 +license: GPL-3.0-or-later +license_family: GPL3 +size: 6991084 +timestamp: 1746011168040 +- conda: https://conda.anaconda.org/conda-forge/noarch/six-1.17.0-pyhe01879c_1.conda +sha256: 458227f759d5e3fcec5d9b7acce54e10c9e1f4f4b7ec978f3bfd54ce4ee9853d +md5: 3339e3b65d58accf4ca4fb8748ab16b3 +depends: +- python >=3.9 +- python +license: MIT +license_family: MIT +size: 18455 +timestamp: 1753199211006 +- conda: https://conda.anaconda.org/conda-forge/noarch/sniffio-1.3.1-pyhd8ed1ab_2.conda +sha256: dce518f45e24cd03f401cb0616917773159a210c19d601c5f2d4e0e5879d30ad +md5: 03fe290994c5e4ec17293cfb6bdce520 +depends: +- python >=3.10 +license: Apache-2.0 +license_family: Apache +size: 15698 +timestamp: 1762941572482 +- conda: https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.53.3-hbc0de68_0.conda +sha256: ef17725138fa72aa5a0f8ccace9727831c4b333e39575f78fb5ad1755826b687 +md5: b345ea7f13e4cae9809c69b1d1af2c99 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libsqlite 3.53.3 h0c1763c_0 +- libzlib >=1.3.2,<2.0a0 +- ncurses >=6.6,<7.0a0 +- readline >=8.3,<9.0a0 +license: blessing +size: 206481 +timestamp: 1782519082269 +- conda: https://conda.anaconda.org/conda-forge/linux-64/suitesparse-7.10.1-h5b2951e_7100101.conda +sha256: 7c1c5bd2ba8385202ac3cb4c9c7f9bb87a2e677e977afd72c910314c014b28be +md5: e927e0f248a498050443dab8bb1203a9 +depends: +- libsuitesparseconfig ==7.10.1 h901830b_7100101 +- libamd ==3.3.3 h456b2da_7100101 +- libbtf ==2.3.2 hf02c80a_7100101 +- libcamd ==3.3.3 hf02c80a_7100101 +- libccolamd ==3.3.4 hf02c80a_7100101 +- libcolamd ==3.3.4 hf02c80a_7100101 +- libcholmod ==5.3.1 h9cf07ce_7100101 +- libcxsparse ==4.4.1 hf02c80a_7100101 +- libldl ==3.3.2 hf02c80a_7100101 +- libklu ==2.3.5 h95ff59c_7100101 +- libumfpack ==6.3.5 h873dde6_7100101 +- libparu ==1.0.0 hc6afc67_7100101 +- librbio ==4.3.4 hf02c80a_7100101 +- libspex ==3.2.3 h9226d62_7100101 +- libspqr ==4.3.4 h23b7119_7100101 +license: LGPL-2.1-or-later AND BSD-3-Clause AND GPL-2.0-or-later AND Apache-2.0 +size: 12135 +timestamp: 1741963824816 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tar-1.35-h3b78370_0.conda +sha256: eab162cadb948c91c14f18b6f30a7c270d682e820c4f2fdb0030c9fc99b3fa49 +md5: 8e037804a92c84cb901bdd83a8e5ff46 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libiconv >=1.18,<2.0a0 +license: GPL-3.0-or-later +license_family: GPL +size: 778622 +timestamp: 1753467956747 +- 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/tzdata-2025c-hc9c84f9_1.conda +sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c +md5: ad659d0a2b3e47e38d829aa8cad2d610 +license: LicenseRef-Public-Domain +size: 119135 +timestamp: 1767016325805 +- conda: https://conda.anaconda.org/bioconda/linux-64/ucsc-fatotwobit-482-hdc0a859_0.tar.bz2 +sha256: 49a3812350d8bcde5993e1620e36921e7419fb98db8b160e186fff16a4bfdaf9 +md5: bfac086f1764d2aedfb35540a9009cdf +depends: +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=13 +- liblzma >=5.8.1,<6.0a0 +- libopenssl-static +- libpng >=1.6.49,<1.7.0a0 +- libuuid >=2.38.1,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +- mysql-connector-c >=6.1.11,<6.1.12.0a0 +license: Varies; see https://genome.ucsc.edu/license +size: 383232 +timestamp: 1750330214400 +- conda: https://conda.anaconda.org/bioconda/linux-64/ucsc-twobitinfo-482-hdc0a859_0.tar.bz2 +sha256: 113321fb70d6cd6b75c04dbd0925cb7a2f4aabfd138d0206af82f899412a1bb6 +md5: 91466585cc720548e4e4c105686fecb8 +depends: +- bzip2 >=1.0.8,<2.0a0 +- libgcc >=13 +- liblzma >=5.8.1,<6.0a0 +- libopenssl-static +- libpng >=1.6.49,<1.7.0a0 +- libuuid >=2.38.1,<3.0a0 +- libzlib >=1.3.1,<2.0a0 +- mysql-connector-c >=6.1.11,<6.1.12.0a0 +license: Varies; see https://genome.ucsc.edu/license +size: 378240 +timestamp: 1750330740699 +- conda: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-17.0.1-py312h4c3975b_0.conda +sha256: 895bbfe9ee25c98c922799de901387d842d7c01cae45c346879865c6a907f229 +md5: 0b6c506ec1f272b685240e70a29261b8 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- python >=3.12,<3.13.0a0 +- python_abi 3.12.* *_cp312 +license: Apache-2.0 +license_family: Apache +size: 410641 +timestamp: 1770909099497 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.7.0-pyhd8ed1ab_0.conda +sha256: feff959a816f7988a0893201aa9727bbb7ee1e9cec2c4f0428269b489eb93fb4 +md5: cbb88288f74dbe6ada1c6c7d0a97223e +depends: +- backports.zstd >=1.0.0 +- brotli-python >=1.2.0 +- h2 >=4,<5 +- pysocks >=1.5.6,<2.0,!=1.5.7 +- python >=3.10 +license: MIT +license_family: MIT +size: 103560 +timestamp: 1778188657149 +- conda: https://conda.anaconda.org/conda-forge/linux-64/wget-1.25.0-h653f8fd_1.conda +sha256: 66a5a05e0e44fd7a57e24d77665d5d6672646a7b316575b2f679108966d9124e +md5: 3b97a15e7345c7f6c51bb57bffad7c93 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libidn2 >=2,<3.0a0 +- libunistring >=0,<1.0a0 +- libzlib >=1.3.1,<2.0a0 +- openssl >=3.5.5,<4.0a0 +- pcre2 >=10.47,<10.48.0a0 +- zlib +license: GPL-3.0-or-later +license_family: GPL +size: 746336 +timestamp: 1772232737502 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.2-hb9d3cd8_0.conda +sha256: c12396aabb21244c212e488bbdc4abcdef0b7404b15761d9329f5a4a39113c4b +md5: fb901ff28063514abb6046c9ec2c4a45 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +license: MIT +license_family: MIT +size: 58628 +timestamp: 1734227592886 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.6-he73a12e_0.conda +sha256: 277841c43a39f738927145930ff963c5ce4c4dacf66637a3d95d802a64173250 +md5: 1c74ff8c35dcadf952a16f752ca5aa49 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- libuuid >=2.38.1,<3.0a0 +- xorg-libice >=1.1.2,<2.0a0 +license: MIT +license_family: MIT +size: 27590 +timestamp: 1741896361728 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.13-he1eb515_0.conda +sha256: 516d4060139dbb4de49a4dcdc6317a9353fb39ebd47789c14e6fe52de0deee42 +md5: 861fb6ccbc677bb9a9fb2468430b9c6a +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- libxcb >=1.17.0,<2.0a0 +license: MIT +license_family: MIT +size: 839652 +timestamp: 1770819209719 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_1.conda +sha256: 6bc6ab7a90a5d8ac94c7e300cc10beb0500eeba4b99822768ca2f2ef356f731b +md5: b2895afaf55bf96a8c8282a2e47a5de0 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 15321 +timestamp: 1762976464266 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb03c661_1.conda +sha256: 25d255fb2eef929d21ff660a0c687d38a6d2ccfbcbf0cc6aa738b12af6e9d142 +md5: 1dafce8548e38671bea82e3f5c6ce22f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +license: MIT +license_family: MIT +size: 20591 +timestamp: 1762976546182 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.7-hb03c661_0.conda +sha256: 79c60fc6acfd3d713d6340d3b4e296836a0f8c51602327b32794625826bd052f +md5: 34e54f03dfea3e7a2dcf1453a85f1085 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 50326 +timestamp: 1769445253162 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxfixes-6.0.2-hb03c661_0.conda +sha256: 83c4c99d60b8784a611351220452a0a85b080668188dce5dfa394b723d7b64f4 +md5: ba231da7fccf9ea1e768caf5c7099b84 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +license: MIT +license_family: MIT +size: 20071 +timestamp: 1759282564045 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxi-1.8.3-hb03c661_0.conda +sha256: 495f99c8eacfa4ae2d8fed2a7f2105777af89acdc204df145d2bbbc380ac631b +md5: adba2e334082bb218db806d4c12277c9 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.13,<2.0a0 +- xorg-libxext >=1.3.7,<2.0a0 +- xorg-libxfixes >=6.0.2,<7.0a0 +license: MIT +license_family: MIT +size: 47717 +timestamp: 1779111857071 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrandr-1.5.5-hb03c661_0.conda +sha256: 80ed047a5cb30632c3dc5804c7716131d767089f65877813d4ae855ee5c9d343 +md5: e192019153591938acf7322b6459d36e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- xorg-libx11 >=1.8.12,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxrender >=0.9.12,<0.10.0a0 +license: MIT +license_family: MIT +size: 30456 +timestamp: 1769445263457 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxrender-0.9.12-hb9d3cd8_0.conda +sha256: 044c7b3153c224c6cedd4484dd91b389d2d7fd9c776ad0f4a34f099b3389f4a1 +md5: 96d57aba173e878a2089d5638016dc5e +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 33005 +timestamp: 1734229037766 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxt-1.3.1-hb9d3cd8_0.conda +sha256: a8afba4a55b7b530eb5c8ad89737d60d60bc151a03fbef7a2182461256953f0e +md5: 279b0de5f6ba95457190a1c459a64e31 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libice >=1.1.1,<2.0a0 +- xorg-libsm >=1.2.4,<2.0a0 +- xorg-libx11 >=1.8.10,<2.0a0 +license: MIT +license_family: MIT +size: 379686 +timestamp: 1731860547604 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxtst-1.2.5-hb9d3cd8_3.conda +sha256: 752fdaac5d58ed863bbf685bb6f98092fe1a488ea8ebb7ed7b606ccfce08637a +md5: 7bbe9a0cc0df0ac5f5a8ad6d6a11af2f +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=13 +- xorg-libx11 >=1.8.10,<2.0a0 +- xorg-libxext >=1.3.6,<2.0a0 +- xorg-libxi >=1.7.10,<2.0a0 +license: MIT +license_family: MIT +size: 32808 +timestamp: 1727964811275 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.8.3-ha02ee65_0.conda +sha256: 2553fd3ec0a1020b2ca05ca10b0036a596cb0d4bf3645922fcf69dacce0e6679 +md5: 6a1b6af49a334e4e06b9f103367762bf +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- liblzma 5.8.3 hb03c661_0 +- liblzma-devel 5.8.3 hb03c661_0 +- xz-gpl-tools 5.8.3 ha02ee65_0 +- xz-tools 5.8.3 hb03c661_0 +license: 0BSD AND LGPL-2.1-or-later AND GPL-2.0-or-later +size: 24360 +timestamp: 1775825568523 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-gpl-tools-5.8.3-ha02ee65_0.conda +sha256: 8f139666ea18dc8340a44a54056627dd4e89e242e8cd136ab2467d6dc2c192ba +md5: 8f5e2c6726c1339287a3c76a2c138ac7 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- liblzma 5.8.3 hb03c661_0 +constrains: +- xz 5.8.3.* +license: 0BSD AND LGPL-2.1-or-later AND GPL-2.0-or-later +size: 34213 +timestamp: 1775825548743 +- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-tools-5.8.3-hb03c661_0.conda +sha256: 162ebd76803464b8c8ebc7d45df32edf0ec717b3bf369a437ae3b0254f22dc2e +md5: b62b615caa60812640f24db3a8d0fc87 +depends: +- __glibc >=2.17,<3.0.a0 +- libgcc >=14 +- liblzma 5.8.3 hb03c661_0 +constrains: +- xz 5.8.3.* +license: 0BSD AND LGPL-2.1-or-later +size: 95955 +timestamp: 1775825530484 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.2-h25fd6f3_2.conda +sha256: 245c9ee8d688e23661b95e3c6dd7272ca936fabc03d423cdb3cdee1bbcf9f2f2 +md5: c2a01a08fc991620a74b32420e97868a +depends: +- __glibc >=2.17,<3.0.a0 +- libzlib 1.3.2 h25fd6f3_2 +license: Zlib +license_family: Other +size: 95931 +timestamp: 1774072620848 +- 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/busco/busco/busco-busco.diff b/modules/nf-core/busco/busco/busco-busco.diff new file mode 100644 index 00000000..fc1c60e8 --- /dev/null +++ b/modules/nf-core/busco/busco/busco-busco.diff @@ -0,0 +1,27 @@ +Changes in component 'nf-core/busco/busco' +'modules/nf-core/busco/busco/environment.yml' is unchanged +'modules/nf-core/busco/busco/meta.yml' is unchanged +Changes in 'busco/busco/main.nf': +--- modules/nf-core/busco/busco/main.nf ++++ modules/nf-core/busco/busco/main.nf +@@ -67,7 +67,13 @@ + export BUSCO_BBTOOLS_MEMORY=${bbtools_memory} + + # Fix Augustus for Apptainer +- ENV_AUGUSTUS=/opt/conda/etc/conda/activate.d/augustus.sh ++ # Pixi-based Wave images activate the environment only via the entrypoint, which Singularity/Apptainer skip ++ if [ -d /opt/wave/.pixi/envs/default/bin ]; then ++ export PATH="/opt/wave/.pixi/envs/default/bin:\${PATH}" ++ ENV_AUGUSTUS=/opt/wave/.pixi/envs/default/etc/conda/activate.d/augustus.sh ++ else ++ ENV_AUGUSTUS=/opt/conda/etc/conda/activate.d/augustus.sh ++ fi + set +u + if [ -z "\${AUGUSTUS_CONFIG_PATH}" ] && [ -f "\${ENV_AUGUSTUS}" ]; then + source "\${ENV_AUGUSTUS}" + +'modules/nf-core/busco/busco/tests/main.nf.test.snap' is unchanged +'modules/nf-core/busco/busco/tests/nextflow.config' is unchanged +'modules/nf-core/busco/busco/tests/main.nf.test' is unchanged +'modules/nf-core/busco/busco/.conda-lock/linux_amd64-bd-6d1f7006d91892b3_1.txt' is unchanged +************************************************************ diff --git a/modules/nf-core/busco/busco/environment.yml b/modules/nf-core/busco/busco/environment.yml new file mode 100644 index 00000000..21c7223a --- /dev/null +++ b/modules/nf-core/busco/busco/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::busco=6.1.0 diff --git a/modules/nf-core/busco/busco/main.nf b/modules/nf-core/busco/busco/main.nf new file mode 100644 index 00000000..261d0ec7 --- /dev/null +++ b/modules/nf-core/busco/busco/main.nf @@ -0,0 +1,138 @@ +process BUSCO_BUSCO { + tag "${meta.id}" + label 'process_medium' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/96/963bad66c10646cf0adb1967cc462ad04d02789ddbfae4fbb94182291dbddf8c/data' + : 'community.wave.seqera.io/library/busco:6.1.0--6d1f7006d91892b3'}" + // Note: one test had to be disabled when switching to Busco 6.0.0, cf https://github.com/nf-core/modules/pull/8781/files + // Try to restore it when upgrading Busco to a later version + + input: + tuple val(meta), path(fasta, stageAs: 'tmp_input/*') + // Required: One of genome, proteins, or transcriptome + val mode + // Required: lineage for checking against, or "auto/auto_prok/auto_euk" for enabling auto-lineage + val lineage + // Recommended: BUSCO lineages file - downloads if not set + path busco_lineages_path + // Optional: BUSCO configuration file + path config_file + val clean_intermediates + + output: + tuple val(meta), path("*-busco.batch_summary.txt"), emit: batch_summary + tuple val(meta), path("*-busco.batch_summary.failed.txt"), emit: batch_summary_failed, optional: true + tuple val(meta), path("short_summary.*.txt"), emit: short_summaries_txt, optional: true + tuple val(meta), path("short_summary.*.json"), emit: short_summaries_json, optional: true + tuple val(meta), path("*-busco.log"), emit: log, optional: true + tuple val(meta), path("*-busco/*/run_*/full_table.tsv"), emit: full_table, optional: true + tuple val(meta), path("*-busco/*/run_*/missing_busco_list.tsv"), emit: missing_busco_list, optional: true + tuple val(meta), path("*-busco/*/run_*/single_copy_proteins.faa"), emit: single_copy_proteins, optional: true + tuple val(meta), path("*-busco/*/run_*/busco_sequences"), emit: seq_dir, optional: true + tuple val(meta), path("*-busco/*/translated_proteins"), emit: translated_dir, optional: true + tuple val(meta), path("*-busco"), emit: busco_dir + tuple val(meta), path("busco_downloads/lineages/*"), emit: downloaded_lineages, optional: true + tuple val(meta), path("*-busco/*/run_*/busco_sequences/single_copy_busco_sequences/*.faa"), emit: single_copy_faa, optional: true + tuple val(meta), path("*-busco/*/run_*/busco_sequences/single_copy_busco_sequences/*.fna"), emit: single_copy_fna, optional: true + tuple val("${task.process}"), val('busco'), eval("busco --version 2> /dev/null | sed 's/BUSCO //g'"), emit: versions_busco, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + if (mode !in ['genome', 'proteins', 'transcriptome']) { + error("Mode must be one of 'genome', 'proteins', or 'transcriptome'.") + } + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}-${lineage}" + def busco_config = config_file ? "--config ${config_file}" : '' + def busco_lineage = lineage in ['auto', 'auto_prok', 'auto_euk'] + ? lineage.replaceFirst('auto', '--auto-lineage').replaceAll('_', '-') + : "--lineage_dataset ${lineage}" + def busco_lineage_dir = busco_lineages_path ? "--download_path ${busco_lineages_path}" : '' + def intermediate_files = [ + './*-busco/*/auto_lineage', + './*-busco/*/**/{miniprot,hmmer,.bbtools}_output', + './*-busco/*/prodigal_output/predicted_genes/tmp/', + './*-busco/*/tmp/', + ] + def clean_cmd = clean_intermediates ? "rm -fr ${intermediate_files.join(' ')}" : '' + + def bbtools_memory_preferred = task.memory * 0.25 + def bbtools_memory_minimum = 120.Mb + def bbtools_memory = bbtools_memory_preferred > bbtools_memory_minimum ? "${bbtools_memory_preferred.toGiga()}g" : "${bbtools_memory_minimum.toMega()}m" + """ + export BUSCO_BBTOOLS_MEMORY=${bbtools_memory} + + # Fix Augustus for Apptainer + # Pixi-based Wave images activate the environment only via the entrypoint, which Singularity/Apptainer skip + if [ -d /opt/wave/.pixi/envs/default/bin ]; then + export PATH="/opt/wave/.pixi/envs/default/bin:\${PATH}" + ENV_AUGUSTUS=/opt/wave/.pixi/envs/default/etc/conda/activate.d/augustus.sh + else + ENV_AUGUSTUS=/opt/conda/etc/conda/activate.d/augustus.sh + fi + set +u + if [ -z "\${AUGUSTUS_CONFIG_PATH}" ] && [ -f "\${ENV_AUGUSTUS}" ]; then + source "\${ENV_AUGUSTUS}" + fi + set -u + + # If the augustus config directory is not writable, then copy to writeable area + if [ ! -w "\${AUGUSTUS_CONFIG_PATH}" ]; then + # Create writable tmp directory for augustus + AUG_CONF_DIR=\$( mktemp -d -p \$PWD ) + cp -r \$AUGUSTUS_CONFIG_PATH/* \$AUG_CONF_DIR + export AUGUSTUS_CONFIG_PATH=\$AUG_CONF_DIR + echo "New AUGUSTUS_CONFIG_PATH=\${AUGUSTUS_CONFIG_PATH}" + fi + + # Ensure the input is uncompressed + INPUT_SEQS=input_seqs + mkdir "\$INPUT_SEQS" + cd "\$INPUT_SEQS" + for FASTA in ../tmp_input/*; do + if [ "\${FASTA##*.}" == 'gz' ]; then + gzip -cdf "\$FASTA" > \$( basename "\$FASTA" .gz ) + else + ln -s "\$FASTA" . + fi + done + cd .. + + busco \\ + --cpu ${task.cpus} \\ + --in "\$INPUT_SEQS" \\ + --out ${prefix}-busco \\ + --mode ${mode} \\ + ${busco_lineage} \\ + ${busco_lineage_dir} \\ + ${busco_config} \\ + ${args} + + # clean up + rm -rf "\$INPUT_SEQS" + ${clean_cmd} + # find and remove broken symlinks from the cleanup + find . -xtype l -delete + + # Move files to avoid staging/publishing issues + grep -v 'Run failed; check logs' ${prefix}-busco/batch_summary.txt > ${prefix}-busco.batch_summary.txt + mv ${prefix}-busco/*/short_summary.*.{json,txt} . || echo "Short summaries were not available: No genes were found." + mv ${prefix}-busco/logs/busco.log ${prefix}-busco.log + + if grep -q 'Run failed; check logs' ${prefix}-busco/batch_summary.txt; then + grep 'Run failed; check logs' ${prefix}-busco/batch_summary.txt > ${prefix}-busco.batch_summary.failed.txt + fi + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}-${lineage}" + def fasta_name = files(fasta).first().name - '.gz' + """ + touch ${prefix}-busco.batch_summary.txt + mkdir -p ${prefix}-busco/${fasta_name}/run_${lineage}/busco_sequences + """ +} diff --git a/modules/nf-core/busco/busco/meta.yml b/modules/nf-core/busco/busco/meta.yml new file mode 100644 index 00000000..f7969637 --- /dev/null +++ b/modules/nf-core/busco/busco/meta.yml @@ -0,0 +1,248 @@ +name: busco_busco +description: Benchmarking Universal Single Copy Orthologs +keywords: + - quality control + - genome + - transcriptome + - proteome +tools: + - busco: + description: BUSCO provides measures for quantitative assessment of genome assembly, gene set, and transcriptome completeness based on evolutionarily informed expectations of gene content from near-universal single-copy orthologs selected from OrthoDB. + homepage: https://busco.ezlab.org/ + documentation: https://busco.ezlab.org/busco_userguide.html + tool_dev_url: https://gitlab.com/ezlab/busco + doi: "10.1007/978-1-4939-9173-0_14" + licence: + - "MIT" + identifier: biotools:busco +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - fasta: + type: file + description: Nucleic or amino acid sequence file in FASTA format. + pattern: "*.{fasta,fna,fa,fasta.gz,fna.gz,fa.gz}" + ontologies: [] + - mode: + type: string + description: The mode to run Busco in. One of genome, proteins, or transcriptome + pattern: "{genome,proteins,transcriptome}" + - lineage: + type: string + description: The BUSCO lineage to use, or "auto", "auto_prok" or "auto_euk" to automatically select lineage + - busco_lineages_path: + type: directory + description: Path to local BUSCO lineages directory. + - config_file: + type: file + description: Path to BUSCO config file. + ontologies: [] + - clean_intermediates: + type: boolean + description: Flag to remove intermediate files. +output: + batch_summary: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco.batch_summary.txt": + type: file + description: Summary of all sequence files analyzed + pattern: "*-busco.batch_summary.txt" + ontologies: [] + batch_summary_failed: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco.batch_summary.failed.txt": + type: file + description: Batch summary lines indicating BUSCO run failures + pattern: "*-busco.batch_summary.failed.txt" + ontologies: [] + short_summaries_txt: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - short_summary.*.txt: + type: file + description: Short Busco summary in plain text format + pattern: "short_summary.*.txt" + ontologies: [] + short_summaries_json: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - short_summary.*.json: + type: file + description: Short Busco summary in JSON format + pattern: "short_summary.*.json" + ontologies: + - edam: http://edamontology.org/format_3464 + log: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco.log": + type: file + description: BUSCO main log + pattern: "*-busco.log" + ontologies: [] + full_table: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco/*/run_*/full_table.tsv": + type: file + description: Full BUSCO results table + pattern: "full_table.tsv" + ontologies: + - edam: http://edamontology.org/format_3475 + missing_busco_list: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco/*/run_*/missing_busco_list.tsv": + type: file + description: List of missing BUSCOs + pattern: "missing_busco_list.tsv" + ontologies: + - edam: http://edamontology.org/format_3475 + single_copy_proteins: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco/*/run_*/single_copy_proteins.faa": + type: file + description: Fasta file of single copy proteins (transcriptome mode) + pattern: "single_copy_proteins.faa" + ontologies: [] + seq_dir: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco/*/run_*/busco_sequences": + type: directory + description: BUSCO sequence directory + pattern: "busco_sequences" + translated_dir: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco/*/translated_proteins": + type: directory + description: Six frame translations of each transcript made by the transcriptome mode + pattern: "translated_dir" + busco_dir: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco": + type: directory + description: BUSCO lineage specific output + pattern: "*-busco" + downloaded_lineages: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - busco_downloads/lineages/*: + type: directory + description: Lineages downloaded by BUSCO when running the analysis, for example bacteria_odb12 + pattern: "busco_downloads/lineages/*" + single_copy_faa: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco/*/run_*/busco_sequences/single_copy_busco_sequences/*.faa": + type: file + description: Single copy .faa sequence files + pattern: "*-busco/*/run_*/busco_sequences/single_copy_busco_sequences/*.faa" + ontologies: [] + single_copy_fna: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test' ] + - "*-busco/*/run_*/busco_sequences/single_copy_busco_sequences/*.fna": + type: file + description: Single copy .fna sequence files + pattern: "*-busco/*/run_*/busco_sequences/single_copy_busco_sequences/*.fna" + ontologies: [] + versions_busco: + - - ${task.process}: + type: string + description: The name of the process + - busco: + type: string + description: The name of the tool + - busco --version 2> /dev/null | sed 's/BUSCO //g': + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - busco: + type: string + description: The name of the tool + - busco --version 2> /dev/null | sed 's/BUSCO //g': + type: eval + description: The expression to obtain the version of the tool +authors: + - "@priyanka-surana" + - "@charles-plessy" + - "@mahesh-panchal" + - "@muffato" + - "@jvhagey" + - "@gallvp" +maintainers: + - "@priyanka-surana" + - "@charles-plessy" + - "@mahesh-panchal" + - "@muffato" + - "@jvhagey" + - "@gallvp" +containers: + docker: + linux/amd64: + name: community.wave.seqera.io/library/busco:6.1.0--6d1f7006d91892b3 + build_id: bd-6d1f7006d91892b3_1 + scan_id: sc-7ee408324c396471_1 + singularity: + linux/amd64: + name: oras://community.wave.seqera.io/library/busco:6.1.0--c7528d5825eb19b5 + build_id: bd-c7528d5825eb19b5_1 + https: https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/96/963bad66c10646cf0adb1967cc462ad04d02789ddbfae4fbb94182291dbddf8c/data + conda: + linux/amd64: + lock_file: modules/nf-core/busco/busco/.conda-lock/linux_amd64-bd-6d1f7006d91892b3_1.txt diff --git a/modules/nf-core/busco/busco/tests/main.nf.test b/modules/nf-core/busco/busco/tests/main.nf.test new file mode 100644 index 00000000..3f1ad0d0 --- /dev/null +++ b/modules/nf-core/busco/busco/tests/main.nf.test @@ -0,0 +1,422 @@ +nextflow_process { + + name "Test Process BUSCO_BUSCO" + script "../main.nf" + process "BUSCO_BUSCO" + + tag "modules" + tag "modules_nfcore" + tag "busco" + tag "busco/busco" + + test("test_busco_genome_single_fasta") { + + config './nextflow.config' + + when { + params { + busco_args = '--tar' + } + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ] + input[1] = 'genome' + input[2] = 'bacteria_odb10' // Launch with 'auto' to use --auto-lineage, and specified lineages // 'auto' removed from test due to memory issues + input[3] = [] // Download busco lineage + input[4] = [] // No config + input[5] = false // Clean intermediates + """ + } + } + + then { + assert process.success + + with(path(process.out.short_summaries_txt[0][1]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_json[0][1]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + assert snapshot( + process.out.batch_summary[0][1], + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.findAll { key, val -> key.startsWith("versions")} + ).match() + + with(file(process.out.seq_dir[0][1]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(path(process.out.log[0][1]).text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + } + + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + } + + test("test_busco_genome_multi_fasta") { + + config './nextflow.config' + + when { + params { + busco_args = '--tar' + } + process { + """ + input[0] = [ + [ id:'test' ], // meta map + [ + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/genome/genome.fasta', checkIfExists: true) + ] + ] + input[1] = 'genome' + input[2] = 'bacteria_odb10' + input[3] = [] + input[4] = [] + input[5] = false + """ + } + } + + then { + assert process.success + + with(path(process.out.short_summaries_txt[0][1][0]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_txt[0][1][1]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_json[0][1][0]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + with(path(process.out.short_summaries_json[0][1][1]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + assert snapshot( + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.findAll { key, val -> key.startsWith("versions")} + ).match() + + with(file(process.out.seq_dir[0][1][0]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(file(process.out.seq_dir[0][1][1]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(path(process.out.log[0][1]).text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + } + + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + + } + + + test("test_busco_eukaryote_augustus") { + + config './nextflow.config' + + when { + params { + busco_args = '--tar --augustus' + } + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ] + input[1] = 'genome' + input[2] = 'eukaryota_odb10' + input[3] = [] + input[4] = [] + input[5] = false + """ + } + } + + then { + assert process.success + + assert snapshot( + process.out.batch_summary[0][1], + process.out.findAll { key, val -> key.startsWith("versions")} + ).match() + + with(path(process.out.log[0][1]).text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Augustus did not recognize any genes') + + } + + assert process.out.short_summaries_json == [] + assert process.out.short_summaries_txt == [] + assert process.out.missing_busco_list == [] + assert process.out.full_table == [] + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + + } + + test("test_busco_protein") { + + config './nextflow.config' + + when { + params { + busco_args = '--tar' + } + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/candidatus_portiera_aleyrodidarum/genome/proteome.fasta', checkIfExists: true) + ] + input[1] = 'proteins' + input[2] = 'bacteria_odb10' + input[3] = [] + input[4] = [] + input[5] = false + """ + } + } + + then { + assert process.success + + with(path(process.out.short_summaries_txt[0][1]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_json[0][1]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + assert snapshot( + process.out.batch_summary[0][1], + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.findAll { key, val -> key.startsWith("versions")} + ).match() + + with(file(process.out.seq_dir[0][1]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(path(process.out.log[0][1]).text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + } + + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + + } + + test("test_busco_transcriptome") { + + config './nextflow.config' + + when { + params { + busco_args = '--tar' + } + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/illumina/fasta/test1.contigs.fa.gz', checkIfExists: true) + ] + input[1] = 'transcriptome' + input[2] = 'bacteria_odb10' + input[3] = [] + input[4] = [] + input[5] = false + """ + } + } + + then { + assert process.success + + with(path(process.out.short_summaries_txt[0][1]).text) { + assert contains('BUSCO version') + assert contains('The lineage dataset is') + assert contains('BUSCO was run in mode') + assert contains('Complete BUSCOs') + assert contains('Missing BUSCOs') + assert contains('Dependencies and versions') + } + + with(path(process.out.short_summaries_json[0][1]).text) { + assert contains('one_line_summary') + assert contains('mode') + assert contains('dataset') + } + + assert snapshot( + process.out.batch_summary[0][1], + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.translated_dir[0][1], + process.out.single_copy_proteins[0][1], + process.out.findAll { key, val -> key.startsWith("versions")} + ).match() + + with(file(process.out.seq_dir[0][1]).listFiles().collect { it.name }) { + assert contains('single_copy_busco_sequences.tar.gz') + assert contains('multi_copy_busco_sequences.tar.gz') + assert contains('fragmented_busco_sequences.tar.gz') + } + + with(path(process.out.log[0][1]).text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + } + } + + } + + test("test_busco_cleanup") { + + config './nextflow.config' + + when { + params { + busco_args = '--tar' + } + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ] + input[1] = 'genome' + input[2] = 'bacteria_odb10' + input[3] = [] + input[4] = [] + input[5] = true + """ + } + } + + then { + assert process.success + + assert snapshot( + process.out.batch_summary[0][1], + process.out.full_table[0][1], + process.out.missing_busco_list[0][1], + process.out.findAll { key, val -> key.startsWith("versions")} + ).match() + + with(path(process.out.log[0][1]).text) { + assert contains('DEBUG:busco.run_BUSCO') + assert contains('Results from dataset') + assert contains('how to cite BUSCO') + } + + assert path("${process.out.busco_dir[0][1]}/*/auto_lineage").exists() == false + assert path("${process.out.busco_dir[0][1]}/*/**/{miniprot,hmmer,.bbtools}_output").exists() == false + + assert process.out.single_copy_proteins == [] + assert process.out.translated_dir == [] + } + } + + test("minimal-stub") { + + options '-stub' + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ] + input[1] = 'genome' + input[2] = 'bacteria_odb10' + input[3] = [] + input[4] = [] + input[5] = false + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + process.out.batch_summary, + process.out.findAll { key, val -> key.startsWith("versions")} + ).match() } + ) + } + } +} diff --git a/modules/nf-core/busco/busco/tests/main.nf.test.snap b/modules/nf-core/busco/busco/tests/main.nf.test.snap new file mode 100644 index 00000000..ff72464f --- /dev/null +++ b/modules/nf-core/busco/busco/tests/main.nf.test.snap @@ -0,0 +1,182 @@ +{ + "minimal-stub": { + "content": [ + [ + [ + { + "id": "test" + }, + "test-bacteria_odb10-busco.batch_summary.txt:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + { + "versions_busco": [ + [ + "BUSCO_BUSCO", + "busco", + "6.1.0" + ] + ] + } + ], + "timestamp": "2026-06-08T11:11:55.813665798", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "test_busco_eukaryote_augustus": { + "content": [ + "test-eukaryota_odb10-busco.batch_summary.txt:md5,3ea3bdc423a461dae514d816bdc61c89", + { + "versions_busco": [ + [ + "BUSCO_BUSCO", + "busco", + "6.1.0" + ] + ] + } + ], + "timestamp": "2026-06-08T11:10:25.880669484", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "test_busco_genome_single_fasta": { + "content": [ + "test-bacteria_odb10-busco.batch_summary.txt:md5,12e911830d66bab6dbf3523ac4392597", + "full_table.tsv:md5,327aa7603dca43e7c4adf85f89a85e8e", + "missing_busco_list.tsv:md5,268d346a92e1297999d96c98a6e7c260", + { + "versions_busco": [ + [ + "BUSCO_BUSCO", + "busco", + "6.1.0" + ] + ] + } + ], + "timestamp": "2026-06-08T11:08:58.703644026", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "test_busco_genome_multi_fasta": { + "content": [ + [ + "full_table.tsv:md5,223cff423706f07a121f53115bcd6d69", + "full_table.tsv:md5,327aa7603dca43e7c4adf85f89a85e8e" + ], + [ + "missing_busco_list.tsv:md5,9a8eb41928d1c21677b9d38abaf2e790", + "missing_busco_list.tsv:md5,268d346a92e1297999d96c98a6e7c260" + ], + { + "versions_busco": [ + [ + "BUSCO_BUSCO", + "busco", + "6.1.0" + ] + ] + } + ], + "timestamp": "2026-06-08T11:09:46.527087612", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "test_busco_cleanup": { + "content": [ + "test-bacteria_odb10-busco.batch_summary.txt:md5,12e911830d66bab6dbf3523ac4392597", + "full_table.tsv:md5,327aa7603dca43e7c4adf85f89a85e8e", + "missing_busco_list.tsv:md5,268d346a92e1297999d96c98a6e7c260", + { + "versions_busco": [ + [ + "BUSCO_BUSCO", + "busco", + "6.1.0" + ] + ] + } + ], + "timestamp": "2026-06-08T11:11:47.192817683", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "test_busco_transcriptome": { + "content": [ + "test-bacteria_odb10-busco.batch_summary.txt:md5,8734b3f379c4c0928e5dd4ea1873dc64", + "full_table.tsv:md5,e9ab16f5dfe319d30828186658c5d02a", + "missing_busco_list.tsv:md5,5d5bbb10940f6cf862c0f4c979980a21", + [ + "1024388at2.faa:md5,797d603d262a6595a112e25b73e878b0", + "1054741at2.faa:md5,cd4b928cba6b19b4437746ba507e7195", + "1093223at2.faa:md5,df9549708e5ffcfaee6a74dd70a0e5dc", + "1151822at2.faa:md5,12726afc1cdc40c13392e1596e93df3a", + "143460at2.faa:md5,d887431fd988a5556a523440f02d9594", + "1491686at2.faa:md5,d03362d19979b27306c192f1c74a84e5", + "1504821at2.faa:md5,4f5f6e5c57bac0092c1d85ded73d7e67", + "1574817at2.faa:md5,1153e55998c2929eacad2aed7d08d248", + "1592033at2.faa:md5,bb7a59e5f3a57ba12d10dabf4c77ab57", + "1623045at2.faa:md5,8fe38155feb1802beb97ef7714837bf5", + "1661836at2.faa:md5,6c6d592c2fbb0d7a4e5e1f47a15644f0", + "1674344at2.faa:md5,bb41b44e53565a54cadf0b780532fe08", + "1698718at2.faa:md5,f233860000028eb00329aa85236c71e5", + "1990650at2.faa:md5,34a2d29c5f8b6253159ddb7a43fa1829", + "223233at2.faa:md5,dec6705c7846c989296e73942f953cbc", + "402899at2.faa:md5,acc0f271f9a586d2ce1ee41669b22999", + "505485at2.faa:md5,aa0391f8fa5d9bd19b30d844d5a99845", + "665824at2.faa:md5,47f8ad43b6a6078206feb48c2e552793", + "776861at2.faa:md5,f8b90c13f7c6be828dea3bb920195e3d", + "874197at2.faa:md5,8d22a35a768debe6f376fc695d233a69", + "932854at2.faa:md5,2eff2de1ab83b22f3234a529a44e22bb", + "95696at2.faa:md5,247bfd1aef432f7b5456307768e9149c" + ], + "single_copy_proteins.faa:md5,73e2c5d6a9b0f01f2deea3cc5f21b764", + { + "versions_busco": [ + [ + "BUSCO_BUSCO", + "busco", + "6.1.0" + ] + ] + } + ], + "timestamp": "2026-06-08T11:11:06.934053195", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "test_busco_protein": { + "content": [ + "test-bacteria_odb10-busco.batch_summary.txt:md5,942dbb2d8ff26240860a794213db14a8", + "full_table.tsv:md5,6cea99feda083a56bf8eb6d9bd19f4be", + "missing_busco_list.tsv:md5,9a8eb41928d1c21677b9d38abaf2e790", + { + "versions_busco": [ + [ + "BUSCO_BUSCO", + "busco", + "6.1.0" + ] + ] + } + ], + "timestamp": "2026-06-08T11:10:44.297381698", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/busco/busco/tests/nextflow.config b/modules/nf-core/busco/busco/tests/nextflow.config new file mode 100644 index 00000000..db73a7ee --- /dev/null +++ b/modules/nf-core/busco/busco/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: 'BUSCO_BUSCO' { + ext.args = params.busco_args + } +} diff --git a/modules/nf-core/gunzip/environment.yml b/modules/nf-core/gunzip/environment.yml new file mode 100644 index 00000000..9b926b1f --- /dev/null +++ b/modules/nf-core/gunzip/environment.yml @@ -0,0 +1,12 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::coreutils=9.5 + - conda-forge::grep=3.11 + - conda-forge::gzip=1.13 + - conda-forge::lbzip2=2.5 + - conda-forge::sed=4.8 + - conda-forge::tar=1.34 diff --git a/modules/nf-core/gunzip/main.nf b/modules/nf-core/gunzip/main.nf new file mode 100644 index 00000000..6edffc59 --- /dev/null +++ b/modules/nf-core/gunzip/main.nf @@ -0,0 +1,47 @@ +process GUNZIP { + tag "${archive}" + label 'process_single' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/52/52ccce28d2ab928ab862e25aae26314d69c8e38bd41ca9431c67ef05221348aa/data' + : 'community.wave.seqera.io/library/coreutils_grep_gzip_lbzip2_pruned:838ba80435a629f8'}" + + input: + tuple val(meta), path(archive) + + output: + tuple val(meta), path("${gunzip}"), emit: gunzip + tuple val("${task.process}"), val('gunzip'), eval('gunzip --version 2>&1 | head -1 | sed "s/^.*(gzip) //; s/ Copyright.*//"'), topic: versions, emit: versions_gunzip + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def nameWithoutGz = archive.extension == 'gz' ? archive.baseName : archive.name + def extension = file(nameWithoutGz).extension + def name = file(nameWithoutGz).baseName + def prefix = task.ext.prefix ?: name + gunzip = prefix + ".${extension}" + """ + # Not calling gunzip itself because it creates files + # with the original group ownership rather than the + # default one for that user / the work directory + gzip \\ + -cd \\ + ${args} \\ + ${archive} \\ + > ${gunzip} + """ + + stub: + def nameWithoutGz = archive.extension == 'gz' ? archive.baseName : archive.name + def extension = file(nameWithoutGz).extension + def name = file(nameWithoutGz).baseName + def prefix = task.ext.prefix ?: name + gunzip = prefix + ".${extension}" + """ + touch ${gunzip} + """ +} diff --git a/modules/nf-core/gunzip/meta.yml b/modules/nf-core/gunzip/meta.yml new file mode 100644 index 00000000..bba6b3ba --- /dev/null +++ b/modules/nf-core/gunzip/meta.yml @@ -0,0 +1,68 @@ +name: gunzip +description: Compresses and decompresses files. +keywords: + - gunzip + - compression + - decompression +tools: + - gunzip: + description: | + gzip is a file format and a software application used for file compression and decompression. + documentation: https://www.gnu.org/software/gzip/manual/gzip.html + licence: ["GPL-3.0-or-later"] + identifier: "" +input: + - - meta: + type: map + description: | + Optional groovy Map containing meta information + e.g. [ id:'test', single_end:false ] + - archive: + type: file + description: File to be compressed/uncompressed + pattern: "*.*" + ontologies: [] +output: + gunzip: + - - meta: + type: file + description: Compressed/uncompressed file + pattern: "*.*" + ontologies: [] + - ${gunzip}: + type: file + description: Compressed/uncompressed file + pattern: "*.*" + ontologies: [] + versions_gunzip: + - - ${task.process}: + type: string + description: The process the versions were collected from + - gunzip: + type: string + description: The tool name + - gunzip --version 2>&1 | head -1 | sed "s/^.*(gzip) //; s/ Copyright.*//": + type: eval + description: The expression to obtain the version of the tool + +topics: + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - gunzip: + type: string + description: The tool name + - gunzip --version 2>&1 | head -1 | sed "s/^.*(gzip) //; s/ Copyright.*//": + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@joseespinosa" + - "@drpatelh" + - "@jfy133" +maintainers: + - "@joseespinosa" + - "@drpatelh" + - "@jfy133" + - "@gallvp" diff --git a/modules/nf-core/gunzip/tests/main.nf.test b/modules/nf-core/gunzip/tests/main.nf.test new file mode 100644 index 00000000..33cb75ae --- /dev/null +++ b/modules/nf-core/gunzip/tests/main.nf.test @@ -0,0 +1,175 @@ +nextflow_process { + + name "Test Process GUNZIP" + script "../main.nf" + process "GUNZIP" + tag "gunzip" + tag "modules_nfcore" + tag "modules" + + test("Should run without failures") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - prefix") { + + config './nextflow.config' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - stub") { + + options '-stub' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should decompress file with extension appearing multiple times in filename") { + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true).copyTo('test.fa.v1.fa.gz') + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert file(process.out.gunzip[0][1]).name == 'test.fa.v1.fa' } + ) + } + + } + + test("Should decompress file with extension appearing multiple times in filename - prefix") { + + config './nextflow.config' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true).copyTo('test.fa.v1.fa.gz') + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - prefix - stub") { + + options '-stub' + config './nextflow.config' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/gunzip/tests/main.nf.test.snap b/modules/nf-core/gunzip/tests/main.nf.test.snap new file mode 100644 index 00000000..980e95a2 --- /dev/null +++ b/modules/nf-core/gunzip/tests/main.nf.test.snap @@ -0,0 +1,207 @@ +{ + "Should decompress file with extension appearing multiple times in filename - prefix": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.xyz.fa:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ], + "gunzip": [ + [ + { + "id": "test" + }, + "test.xyz.fa:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions_gunzip": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ] + } + ], + "timestamp": "2026-04-15T15:20:52.59447", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "Should run without failures - prefix - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ], + "gunzip": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_gunzip": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ] + } + ], + "timestamp": "2026-01-19T17:21:56.633550769", + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + } + }, + "Should run without failures - stub": { + "content": [ + { + "0": [ + [ + [ + + ], + "test_1.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ], + "gunzip": [ + [ + [ + + ], + "test_1.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_gunzip": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ] + } + ], + "timestamp": "2026-01-19T17:21:51.435621199", + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + } + }, + "Should run without failures": { + "content": [ + { + "0": [ + [ + [ + + ], + "test_1.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ], + "gunzip": [ + [ + [ + + ], + "test_1.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions_gunzip": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ] + } + ], + "timestamp": "2026-01-19T17:21:40.613975821", + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + } + }, + "Should run without failures - prefix": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ], + "gunzip": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions_gunzip": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] + ] + } + ], + "timestamp": "2026-01-19T17:21:46.086880414", + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.2" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/gunzip/tests/nextflow.config b/modules/nf-core/gunzip/tests/nextflow.config new file mode 100644 index 00000000..dec77642 --- /dev/null +++ b/modules/nf-core/gunzip/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: GUNZIP { + ext.prefix = { "${meta.id}.xyz" } + } +} diff --git a/nextflow.config b/nextflow.config index dcfeb4c0..177b5b85 100644 --- a/nextflow.config +++ b/nextflow.config @@ -25,9 +25,20 @@ params { rrna_limit = 80 trna_limit = 18 - // checkm2: completeness and contamination + // completeness and contamination + // --- prokaryotes + // -- checkm2 checkm2_db = null checkm2_db_download_id = 14897628 + // --- eukaryotes + // -- busco + busco_db = null + busco_db_lineage = 'auto_euk' + save_busco_db = false + busco_clean = true + // -- eukcc + eukaryotic_completeness_tool = 'eukcc' + eukcc_db = 'http://ftp.ebi.ac.uk/pub/databases/metagenomics/eukcc/eukcc2_db_ver_1.1.tar.gz' // NCBI taxonomy cat_db = null @@ -240,24 +251,26 @@ profiles { singularity.runOptions = '--nv' } - test { includeConfig 'conf/test.config' } - test_full { includeConfig 'conf/test_full.config' } - test_mag_complete_metadata_existing_study { includeConfig 'conf/test_mag_complete_metadata_existing_study.conf' } - test_mag_complete_metadata { includeConfig 'conf/test_mag_complete_metadata.config' } - test_mag_no_coverage_single_reads { includeConfig 'conf/test_mag_no_coverage_single_reads.conf' } - test_mag_no_coverage_paired_reads { includeConfig 'conf/test_mag_no_coverage_paired_reads.conf' } - test_mag_no_quality { includeConfig 'conf/test_mag_no_quality.conf' } - test_mag_one_contig { includeConfig 'conf/test_mag_one_contig.conf' } - test_mag_no_rna_presence { includeConfig 'conf/test_mag_no_rna_presence.conf' } - test_mag_no_taxonomy { includeConfig 'conf/test_mag_no_taxonomy.conf' } - test_assembly_complete_metadata_existing_study { includeConfig 'conf/test_assembly_complete_metadata_existing_study.config' } - test_assembly_complete_metadata { includeConfig 'conf/test_assembly_complete_metadata.config' } - test_assembly_no_coverage_single_reads { includeConfig 'conf/test_assembly_no_coverage_single_reads.config' } - test_assembly_no_coverage_paired_reads { includeConfig 'conf/test_assembly_no_coverage_paired_reads.config' } - test_assembly_one_contig { includeConfig 'conf/test_assembly_one_contig.config' } - test_reads_paired { includeConfig 'conf/test_reads_paired.config' } - test_reads_long_bam { includeConfig 'conf/test_reads_long_bam.config' } - test_reads_long_bam_validate { includeConfig 'conf/test_reads_long_bam_validate.config' } + test { includeConfig 'conf/test.config' } + test_full { includeConfig 'conf/test_full.config' } + test_mag_complete_metadata_existing_study { includeConfig 'conf/test_mag_complete_metadata_existing_study.conf' } + test_mag_complete_metadata { includeConfig 'conf/test_mag_complete_metadata.config' } + test_mag_missing_metadata { includeConfig 'conf/test_mag_missing_metadata.config' } + test_mag_no_coverage_se_skip_ena_queries { includeConfig 'conf/test_mag_no_coverage_se_skip_ena_queries.conf' } + test_mag_no_coverage_pe_skip_ena_queries { includeConfig 'conf/test_mag_no_coverage_pe_skip_ena_queries.conf' } + test_mag_no_quality { includeConfig 'conf/test_mag_no_quality.conf' } + test_mag_no_quality_euk_skip_ena_queries { includeConfig 'conf/test_mag_no_quality_euk_skip_ena_queries.conf' } + test_mag_one_contig_skip_ena_queries { includeConfig 'conf/test_mag_one_contig_skip_ena_queries.conf' } + test_mag_no_rna_skip_ena_queries { includeConfig 'conf/test_mag_no_rna_skip_ena_queries.conf' } + test_mag_no_taxonomy_skip_ena_queries { includeConfig 'conf/test_mag_no_taxonomy_skip_ena_queries.conf' } + test_assembly_complete_metadata_existing_study { includeConfig 'conf/test_assembly_complete_metadata_existing_study.config' } + test_assembly_complete_metadata { includeConfig 'conf/test_assembly_complete_metadata.config' } + test_assembly_no_coverage_single_reads { includeConfig 'conf/test_assembly_no_coverage_single_reads.config' } + test_assembly_no_coverage_paired_reads { includeConfig 'conf/test_assembly_no_coverage_paired_reads.config' } + test_assembly_one_contig { includeConfig 'conf/test_assembly_one_contig.config' } + test_reads_paired { includeConfig 'conf/test_reads_paired.config' } + test_reads_long_bam { includeConfig 'conf/test_reads_long_bam.config' } + test_reads_long_bam_validate { includeConfig 'conf/test_reads_long_bam_validate.config' } } // Load nf-core custom profiles from different institutions @@ -349,7 +362,7 @@ manifest { email: 'sofia@ebi.ac.uk', github: 'https://github.com/ochkalova', contribution: ['author', 'maintainer'], // List of contribution types ('author', 'maintainer' or 'contributor') - orcid: '' + orcid: '0000-0003-2814-6012' ], [ name: 'Timothy Rozday', diff --git a/nextflow_schema.json b/nextflow_schema.json index bbd9f5d5..d24f69a8 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -78,12 +78,12 @@ } } }, - "genome_evaluation_options": { - "title": "Evaluation options", + "genome_evaluation_options_proks": { + "title": "Prokaryotic genome evaluation options", "type": "object", "fa_icon": "fas fa-university", - "description": "Parameters used to run Checkm2", - "help_text": "These options are used to run Checkm2 that will calculate completeness and contamination of genome if those were not provided as input", + "description": "Parameters used to run CheckM2 on prokaryotic genomes", + "help_text": "These options are used to run CheckM2, which calculates completeness and contamination of prokaryotic (bacterial and archaeal) genomes if those values were not provided in the samplesheet.", "properties": { "checkm2_db": { "format": "file-path", @@ -98,6 +98,50 @@ } } }, + "genome_evaluation_options_euks": { + "title": "Eukaryotic genome evaluation options", + "type": "object", + "fa_icon": "fas fa-university", + "description": "Parameters used to run EukCC and BUSCO on eukaryotic genomes", + "help_text": "These options are used to calculate completeness and contamination of eukaryotic genomes if those values were not provided in the samplesheet. By default, EukCC calculates both completeness and contamination. With `--eukaryotic_completeness_tool busco`, completeness is calculated by BUSCO, and contamination is calculated by EukCC (or taken from the samplesheet if provided).", + "properties": { + "busco_db": { + "type": "string", + "description": "BUSCO `*_odb10` or `*_odb12` lineage dataset as an uncompressed folder or a `.tar.gz`/`.tgz` archive (local path or URL), e.g. `https://busco-data.ezlab.org/v5/data/lineages/eukaryota_odb10.2024-01-08.tar.gz`. A folder is expected to contain a `lineages` subfolder with the lineage dataset, e.g. `lineages/eukaryota_odb10`. If provided, BUSCO runs in offline mode. If omitted, BUSCO downloads the lineage set by `--busco_db_lineage` during the run (requires an internet connection). Used only with `--eukaryotic_completeness_tool busco`.", + "format": "path", + "exists": true + }, + "busco_db_lineage": { + "type": "string", + "description": "Name of the BUSCO `*_odb10` or `*_odb12` lineage to check eukaryotic genomes against (e.g. `eukaryota_odb10`), or `auto`, `auto_prok`, `auto_euk` for automatic lineage selection. When used with `--busco_db`, it should correspond to the lineage supplied there. Without `--busco_db`, the lineage is downloaded during the run (requires an internet connection). Used only with `--eukaryotic_completeness_tool busco`.", + "pattern": "(.*_odb(10|12))|auto(_prok|_euk)?$", + "default": "auto_euk" + }, + "save_busco_db": { + "type": "boolean", + "description": "Save BUSCO lineage datasets downloaded during the run (when `--busco_db` is not provided) to the output directory. Useful for reproducibility, as BUSCO datasets are frequently updated and old versions do not always remain accessible. Used only with `--eukaryotic_completeness_tool busco`.", + "default": false + }, + "busco_clean": { + "type": "boolean", + "description": "Remove BUSCO intermediate files after each run. BUSCO creates a large number of intermediate files, which may cause problems on clusters with file number limits, particularly with many MAGs/bins. Used only with `--eukaryotic_completeness_tool busco`.", + "default": true + }, + "eukcc_db": { + "type": "string", + "description": "EukCC database as an uncompressed folder or a `.tar.gz`/`.tgz` archive (local path or URL). Used to calculate completeness and contamination of eukaryotic MAGs/bins if those values were not provided in the samplesheet. URLs are downloaded and archives are extracted by the pipeline in every run, so we recommend downloading and extracting the database once and providing the folder.", + "format": "path", + "exists": true, + "default": "http://ftp.ebi.ac.uk/pub/databases/metagenomics/eukcc/eukcc2_db_ver_1.1.tar.gz" + }, + "eukaryotic_completeness_tool": { + "type": "string", + "description": "Tool used to calculate completeness of eukaryotic MAGs/bins: `eukcc` or `busco`. Contamination is always calculated by EukCC, unless it is provided in the samplesheet.", + "enum": ["eukcc", "busco"], + "default": "eukcc" + } + } + }, "institutional_config_options": { "title": "Institutional config options", "type": "object", @@ -276,7 +320,7 @@ "type": "boolean", "description": "Upload to ENA TEST server instead of LIVE server", "default": true, - "help_text": "Use that flag for development purposes or for validation of your submissions. Submission would be done to TEST ENA server instead of LIVE server. TEST server holds data 24h and removes afterwords. LIVE server does not have option to modify your submission, you can only suppress data and re-upload" + "help_text": "Use that flag for development purposes or for validation of your submissions. Submission would be done to TEST ENA server instead of LIVE server. TEST server holds data 24h and removes afterwords. LIVE server does not have option to modify your submission, you can only suppress data and re-upload. It is restricted to use --test-upload=false with --webincli_mode validate because study and/or samples would be registered on LIVE server but data would not be submitted." }, "is_private": { "type": "boolean", @@ -310,7 +354,32 @@ "enum": ["submit", "validate"], "help_text": "Controls ENA Webin-CLI mode. `validate` mode checks correctness of manifest files, data access and validity. `submit` mode does validation and push data to ENA server. Default: submit." } - } + }, + "allOf": [ + { + "if": { + "properties": { + "test_upload": { + "const": false + } + }, + "required": ["test_upload"] + }, + "then": { + "properties": { + "webincli_mode": { + "const": "submit" + } + }, + "required": ["webincli_mode"], + "errorMessage": { + "properties": { + "webincli_mode": "LIVE ENA submissions require webincli_mode to be 'submit'. Validation-only mode cannot be used with the LIVE server." + } + } + } + } + ] } }, "oneOf": [ @@ -335,7 +404,10 @@ "$ref": "#/$defs/rna_detection_options" }, { - "$ref": "#/$defs/genome_evaluation_options" + "$ref": "#/$defs/genome_evaluation_options_proks" + }, + { + "$ref": "#/$defs/genome_evaluation_options_euks" }, { "$ref": "#/$defs/taxonomy_assignment_options" diff --git a/nf-test.config b/nf-test.config index 2d67bcf5..372bac9e 100644 --- a/nf-test.config +++ b/nf-test.config @@ -9,9 +9,15 @@ config { configFile = "tests/nextflow.config" // ignore tests coming from the nf-core/modules repo + // ignore euk_mags_quality assessment because Eukcc DB is big for GA + // ignore prokaryotic_genome_evaluation test because checkm2 container is too big + // ignore eukaryotic_genome_evaluation test with Eukcc DB download which is big for GA ignore = [ 'modules/nf-core/**/tests/*', 'subworkflows/nf-core/**/tests/*', + 'tests/mag_no_quality_euk_skip_ena_queries.nf.test', + 'subworkflows/local/prokaryotic_genome_evaluation/tests/*', + 'subworkflows/local/eukaryotic_genome_evaluation/tests/main.nf.test' ] // run all test with defined profile(s) from the main nextflow.config diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 2e5a831e..59c9d61c 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -23,7 +23,7 @@ "@type": "Dataset", "creativeWorkStatus": "Stable", "datePublished": "2026-09-01T12:58:45+00:00", - "description": "

\n \n \n \"nf-core/seqsubmit\"\n \n

\n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/seqsubmit)\n[![GitHub Actions CI Status](https://github.com/nf-core/seqsubmit/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/seqsubmit/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/seqsubmit/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/seqsubmit/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/seqsubmit/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/seqsubmit)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23seqsubmit-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/seqsubmit)[![Follow on Bluesky](https://img.shields.io/badge/bluesky-%40nf__core-1185fe?labelColor=000000&logo=bluesky)](https://bsky.app/profile/nf-co.re)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core)\n\n## Introduction\n\n![seqsubmit workflow diagram](docs/images/seqsubmit_schema.png)\n\n**nf-core/seqsubmit** is a Nextflow pipeline for submitting sequence data to [ENA](https://www.ebi.ac.uk/ena/browser/home).\nThe pipeline currently supports the following submission modes, each routed to a dedicated workflow:\n\n- `reads` \u2014 raw sequencing reads submission via the `READSUBMIT` workflow (pink)\n- `metagenomic_assemblies` \u2014 assembly submission via the `ASSEMBLYSUBMIT` workflow (green)\n- `mags` \u2014 metagenome-assembled genomes (MAGs) submission via the `GENOMESUBMIT` workflow (blue)\n- `bins` \u2014 bins submission via the `GENOMESUBMIT` workflow (blue)\n\n\n\nEach workflow has its own samplesheet structure, prerequisites, and limitations \u2014 they are briefly described below. See the [usage documentation](https://nf-co.re/seqsubmit/usage) for more detailed explanations.\n\n## Requirements\n\n- [Nextflow](https://www.nextflow.io/) `>=25.04.0`\n- A Webin account registered at \n\n Set your Webin credentials as Nextflow secrets:\n\n ```bash\n nextflow secrets set ENA_WEBIN \"Webin-XXX\"\n nextflow secrets set ENA_WEBIN_PASSWORD \"XXX\"\n ```\n\n Make sure to replace the values above with your own credentials.\n\n- Provide either a study accession or a study registration metadata file for the study the submission will be associated with. See the [Submission study](docs/usage.md#submission-study) section of the usage documentation for details.\n\n- Depending on the chosen mode, samples, reads, or metagenomic assemblies must be pre-submitted to ENA to obtain the corresponding accessions, which you then reference in your submission. Refer to the relevant mode section in the [usage documentation](https://nf-co.re/seqsubmit/usage) for details.\n\n## Input samplesheets\n\n### `reads` mode\n\nExample:\n\n```csv\nid,sample_accession,fastq_1,fastq_2,platform,instrument,library_source,library_selection,library_strategy,insert_size,library_name,description\nillumina_run_001,SAMEA1234567,data/reads_R1.fastq.gz,data/reads_R2.fastq.gz,ILLUMINA,Illumina HiSeq 2000,GENOMIC,RANDOM,WGS,500,HiSeq_library_001,Illumina sequencing of sample XYZ\n```\n\nSee the [`reads` mode section](docs/usage.md#samplesheet-input) of the usage documentation for more details.\n\n### `metagenomic_assemblies` mode\n\nExample:\n\n```csv\nid,fasta,fastq_1,fastq_2,coverage,run_accession,assembler,assembler_version\nassembly_1,data/contigs_1.fasta.gz,data/reads_1.fastq.gz,data/reads_2.fastq.gz,,ERR011322,SPAdes,3.15.5\nassembly_2,data/contigs_2.fasta.gz,,,42.7,ERR011323,MEGAHIT,1.2.9\n```\n\nSee the [`metagenomic_assemblies` mode section](docs/usage.md#samplesheet-input-1) of the usage documentation for more details.\n\n### `mags` and `bins` modes\n\nExample:\n\n```csv\nid,fasta,accession,fastq_1,fastq_2,assembly_software,binning_software,binning_parameters,stats_generation_software,completeness,contamination,genome_coverage,metagenome,co-assembly,broad_environment,local_environment,environmental_medium,RNA_presence,NCBI_lineage\nlachnospira_eligens,data/bin_lachnospira_eligens.fa.gz,SRR24458089,,,spades_v3.15.5,metabat2_v2.6,default,CheckM2_v1.0.1,61.0,0.21,32.07,sediment metagenome,false,marine,cable_bacteria,marine_sediment,false,d__Bacteria;p__Proteobacteria;s__unclassified_Proteobacteria\n```\n\nSee the [`mags` and `bins` modes section](docs/usage.md#samplesheet-input-2) of the usage documentation for the full list of required and optional columns.\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n### Running the pipeline\n\nEach mode also has its own additional parameters and example commands \u2014 see the [usage documentation](https://nf-co.re/seqsubmit/usage) for details. General command template:\n\n```bash\nnextflow run nf-core/seqsubmit \\\n -profile \\\n --mode \\\n --input \\\n --centre_name \\\n --submission_study \\\n --outdir \n```\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/seqsubmit/usage) and the [parameter documentation](https://nf-co.re/seqsubmit/parameters).\n\n## Pipeline output\n\nKey output locations in `--outdir`:\n\n- `reads/`: per-sample submission receipts and accessions\n- `metagenomic_assemblies/`: assembly metadata CSVs and per-sample coverage files\n- `mags/` or `bins/`: genome metadata, manifests, and per-sample submission support files\n- `multiqc/`: MultiQC summary report\n- `pipeline_info/`: execution reports, trace, DAG, and software versions\n\nFor full details, see the [output documentation](https://nf-co.re/seqsubmit/output).\n\n## Credits\n\nnf-core/seqsubmit was originally written by [Martin Beracochea](https://github.com/mberacochea), [Ekaterina Sakharova](https://github.com/KateSakharova), [Sofia Ochkalova](https://github.com/ochkalova) and [Tim Rozday](https://github.com/timrozday-mgnify).\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n[Evangelos Karatzas](https://github.com/vagkaratzas)\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#seqsubmit` channel](https://nfcore.slack.com/channels/seqsubmit) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\nIf you use this pipeline please make sure to cite all used software.\nThis pipeline uses code and infrastructure developed and maintained by the [nf-core](https://nf-co.re) community, reused here under the [MIT license](https://github.com/nf-core/tools/blob/main/LICENSE).\n\n> **MGnify: the microbiome sequence data analysis resource in 2023**\n>\n> Richardson L, Allen B, Baldi G, Beracochea M, Bileschi ML, Burdett T, et al.\n>\n> Vol. 51, Nucleic Acids Research. Oxford University Press (OUP); 2022. p. D753\u20139. Available from: http://dx.doi.org/10.1093/nar/gkac1080\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nYou can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n", + "description": "

\n \n \n \"nf-core/seqsubmit\"\n \n

\n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](https://github.com/codespaces/new/nf-core/seqsubmit)\n[![GitHub Actions CI Status](https://github.com/nf-core/seqsubmit/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/seqsubmit/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/seqsubmit/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/seqsubmit/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/seqsubmit/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.XXXXXXX-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.XXXXXXX)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.10.4-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-4.1.0-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/4.1.0)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/seqsubmit)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23seqsubmit-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/seqsubmit)[![Follow on Bluesky](https://img.shields.io/badge/bluesky-%40nf__core-1185fe?labelColor=000000&logo=bluesky)](https://bsky.app/profile/nf-co.re)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core)\n\n## Introduction\n\n![seqsubmit workflow diagram](docs/images/seqsubmit_schema.png)\n\n**nf-core/seqsubmit** is a Nextflow pipeline for submitting sequence data to [ENA](https://www.ebi.ac.uk/ena/browser/home).\nThe pipeline currently supports the following submission modes, each routed to a dedicated workflow:\n\n- `reads` \u2014 raw sequencing reads submission via the `READSUBMIT` workflow (pink)\n- `metagenomic_assemblies` \u2014 assembly submission via the `ASSEMBLYSUBMIT` workflow (green)\n- `mags` \u2014 metagenome-assembled genomes (MAGs) submission via the `GENOMESUBMIT` workflow (blue)\n- `bins` \u2014 bins submission via the `GENOMESUBMIT` workflow (blue)\n\n\n\nEach workflow has its own samplesheet structure, prerequisites, and limitations \u2014 they are briefly described below. See the [usage documentation](https://nf-co.re/seqsubmit/usage) for more detailed explanations.\n\n## Requirements\n\n- [Nextflow](https://www.nextflow.io/) `>=25.04.0`\n- A Webin account registered at \n\n Set your Webin credentials as Nextflow secrets:\n\n ```bash\n nextflow secrets set ENA_WEBIN \"Webin-XXX\"\n nextflow secrets set ENA_WEBIN_PASSWORD \"XXX\"\n ```\n\n Make sure to replace the values above with your own credentials.\n\n- Provide either a study accession or a study registration metadata file for the study the submission will be associated with. See the [Submission study](docs/usage.md#submission-study) section of the usage documentation for details.\n\n- Depending on the chosen mode, samples, reads, or metagenomic assemblies must be pre-submitted to ENA to obtain the corresponding accessions, which you then reference in your submission. Refer to the relevant mode section in the [usage documentation](https://nf-co.re/seqsubmit/usage) for details.\n\n## Input samplesheets\n\n### `reads` mode\n\nExample:\n\n```csv\nid,sample_accession,fastq_1,fastq_2,platform,instrument,library_source,library_selection,library_strategy,insert_size,library_name,description\nillumina_run_001,SAMEA1234567,data/reads_R1.fastq.gz,data/reads_R2.fastq.gz,ILLUMINA,Illumina HiSeq 2000,GENOMIC,RANDOM,WGS,500,HiSeq_library_001,Illumina sequencing of sample XYZ\n```\n\nSee the [`reads` mode section](docs/usage.md#samplesheet-input) of the usage documentation for more details.\n\n### `metagenomic_assemblies` mode\n\nExample:\n\n```csv\nid,fasta,fastq_1,fastq_2,coverage,run_accession,assembler,assembler_version,assembly_type\nassembly_1,data/contigs_1.fasta.gz,data/reads_1.fastq.gz,data/reads_2.fastq.gz,,ERR011322,SPAdes,3.15.5,metagenome\nassembly_2,data/contigs_2.fasta.gz,,,42.7,ERR011323,MEGAHIT,1.2.9,metatranscriptome\n```\n\nSee the [`metagenomic_assemblies` mode section](docs/usage.md#samplesheet-input-1) of the usage documentation for more details.\n\n### `mags` and `bins` modes\n\nExample:\n\n```csv\nid,fasta,accession,fastq_1,fastq_2,assembly_software,binning_software,binning_parameters,stats_generation_software,completeness,contamination,genome_coverage,metagenome,co-assembly,broad_environment,local_environment,environmental_medium,RNA_presence,NCBI_lineage\nlachnospira_eligens,data/bin_lachnospira_eligens.fa.gz,SRR24458089,,,spades_v3.15.5,metabat2_v2.6,default,CheckM2_v1.0.1,61.0,0.21,32.07,sediment metagenome,false,marine,cable_bacteria,marine_sediment,false,d__Bacteria;p__Proteobacteria;s__unclassified_Proteobacteria\n```\n\nSee the [`mags` and `bins` modes section](docs/usage.md#samplesheet-input-2) of the usage documentation for the full list of required and optional columns.\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/get_started/environment_setup/overview) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/get_started/run-your-first-pipeline) with `-profile test` before running the workflow on actual data.\n\n### Running the pipeline\n\nEach mode also has its own additional parameters and example commands \u2014 see the [usage documentation](https://nf-co.re/seqsubmit/usage) for details. General command template:\n\n```bash\nnextflow run nf-core/seqsubmit \\\n -profile \\\n --mode \\\n --input \\\n --centre_name \\\n --submission_study \\\n --outdir \n```\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/running/run-pipelines#using-parameter-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/seqsubmit/usage) and the [parameter documentation](https://nf-co.re/seqsubmit/parameters).\n\n## Pipeline output\n\nKey output locations in `--outdir`:\n\n- `reads/`: per-sample submission receipts and accessions\n- `metagenomic_assemblies/`: assembly metadata CSVs and per-sample coverage files\n- `mags/` or `bins/`: genome metadata, manifests, and per-sample submission support files\n- `multiqc/`: MultiQC summary report\n- `pipeline_info/`: execution reports, trace, DAG, and software versions\n\nFor full details, see the [output documentation](https://nf-co.re/seqsubmit/output).\n\n## Credits\n\nnf-core/seqsubmit was originally written by [Martin Beracochea](https://github.com/mberacochea), [Ekaterina Sakharova](https://github.com/KateSakharova), [Sofia Ochkalova](https://github.com/ochkalova) and [Tim Rozday](https://github.com/timrozday-mgnify).\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n[Evangelos Karatzas](https://github.com/vagkaratzas)\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](docs/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#seqsubmit` channel](https://nfcore.slack.com/channels/seqsubmit) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\nIf you use this pipeline please make sure to cite all used software.\nThis pipeline uses code and infrastructure developed and maintained by the [nf-core](https://nf-co.re) community, reused here under the [MIT license](https://github.com/nf-core/tools/blob/main/LICENSE).\n\n> **MGnify: the microbiome sequence data analysis resource in 2023**\n>\n> Richardson L, Allen B, Baldi G, Beracochea M, Bileschi ML, Burdett T, et al.\n>\n> Vol. 51, Nucleic Acids Research. Oxford University Press (OUP); 2022. p. D753\u20139. Available from: http://dx.doi.org/10.1093/nar/gkac1080\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nYou can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n", "hasPart": [ { "@id": "main.nf" diff --git a/subworkflows/local/eukaryotic_genome_evaluation/main.nf b/subworkflows/local/eukaryotic_genome_evaluation/main.nf new file mode 100644 index 00000000..7879a3ef --- /dev/null +++ b/subworkflows/local/eukaryotic_genome_evaluation/main.nf @@ -0,0 +1,207 @@ +// +// Subworkflow that calculates completeness and contamination for eukaryotic genomes +// + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ +include { EUKCC_SINGLE } from '../../../modules/local/eukcc/single/main' + +include { BUSCO_BUSCO } from '../../../modules/nf-core/busco/busco/main' +include { UNTAR as DB_UNTAR } from '../../../modules/nf-core/untar/main' +include { GUNZIP as GUNZIP_FASTA } from '../../../modules/nf-core/gunzip/main' + +include { parseStatsTable; mergeSoftware; isNotAssigned } from '../utils_nfcore_seqsubmit_pipeline' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + SUBWORKFLOW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +workflow EUKARYOTIC_GENOME_EVALUATION { + + take: + ch_fasta // channel: [ val(meta), path(fasta) ] - eukaryotic genomes only + busco_db_lineage // val: lineage for checking against, default: auto_euk + busco_db // val: BUSCO database - local directory or .tar.gz/.tgz archive (path or URL), or null to download + busco_clean // boolean: clean intermediate busco files + eukaryotic_completeness_tool // val: busco or eukcc + eukcc_db // val: EukCC database - local directory or .tar.gz/.tgz archive (path or URL) + + main: + + // Contamination can only be calculated by EukCC. If contamination is already given in the samplesheet + // and BUSCO calculates completeness, EukCC is skipped for that genome. + // Without BUSCO, EukCC runs as usual for completeness and contamination from the samplesheet is kept. + euks_split = ch_fasta + .branch { meta, _fasta -> + busco_only: eukaryotic_completeness_tool == 'busco' && meta.contamination != null + eukcc: true + } + + // Databases for eukaryotes can be given as a directory or as a .tar.gz/.tgz archive (local path or URL). + // Archives are extracted with a single DB_UNTAR step, only if there is at least one genome that needs the tool. + // BUSCO database directory is expected to have the structure `/lineages/_odb(10|12)` + def busco_db_file = (eukaryotic_completeness_tool == 'busco' && busco_db) ? file(busco_db, checkIfExists: true) : null + def eukcc_db_file = eukcc_db ? file(eukcc_db, checkIfExists: true) : null + + ch_db_archives = ch_fasta + .first() + .filter { _meta, _fasta -> isArchive(busco_db_file) } + .map { _meta, _fasta -> [[id: 'busco_db'], busco_db_file] } + .mix( + euks_split.eukcc + .first() + .filter { _meta, _fasta -> isArchive(eukcc_db_file) } + .map { _meta, _fasta -> [[id: 'eukcc_db'], eukcc_db_file] } + ) + + DB_UNTAR ( ch_db_archives ) + + if (eukaryotic_completeness_tool == 'busco') { + // Without a database BUSCO downloads the lineages itself + def ch_busco_db = busco_db_file + ? prepareDatabase(busco_db_file, 'busco_db', DB_UNTAR.out.untar).map { _db_meta, db -> db } + : [] + + // Genome evaluation with BUSCO + + BUSCO_BUSCO ( + ch_fasta, + 'genome', // busco mode (choice of: genome, proteins, or transcriptome) + busco_db_lineage, // busco lineages file - downloads if not set + ch_busco_db, + [], + busco_clean + ) + } + + // Run EukCC for completeness and contamination of eukaryotes + // Database is required only when there is at least one eukaryotic genome to run EukCC on + def eukcc_database = eukcc_db_file + ? prepareDatabase(eukcc_db_file, 'eukcc_db', DB_UNTAR.out.untar) + : euks_split.eukcc.first().map { _meta, _fasta -> + error("Eukaryotic genomes were found, but --eukcc_db is not provided. Please provide the EukCC database.") + } + + GUNZIP_FASTA ( euks_split.eukcc ) + + EUKCC_SINGLE ( + GUNZIP_FASTA.out.gunzip, + eukcc_database + ) + + // ------ Combine completeness and contamination from all tools into one channel + // Tools are listed in stats_generation_software separated by ';'. + // If stats_generation_software is given in the samplesheet, launched tools are appended to it. + + // Software name with version, e.g. eukcc_v2.2.0, assigned per tool + def eukcc_software = EUKCC_SINGLE.out.versions_eukcc + .map { _process_name, tool_name, version -> "${tool_name}_v${version}" } + .first() + + // [ meta, completeness, contamination, software ], contamination from the samplesheet is kept if present + ch_eukcc_stats = EUKCC_SINGLE.out.eukcc_tsv + .combine(eukcc_software) + .map { meta, table, software -> parseStatsTable(meta, table, software) } + .map { meta, completeness, contamination, software -> + [ meta, completeness, meta.contamination != null ? meta.contamination : contamination, software ] + } + + if (eukaryotic_completeness_tool == 'busco') { + // With BUSCO activated, completeness is taken from BUSCO and contamination from EukCC or samplesheet + def busco_software = BUSCO_BUSCO.out.versions_busco + .map { _process_name, tool_name, version -> "${tool_name}_v${version}" } + .first() + def ch_busco_completeness = BUSCO_BUSCO.out.short_summaries_json + .map { meta, summaries -> [ meta, parseBuscoCompleteness(summaries) ] } + + // BUSCO short summary is optional (no genes found) and EukCC is skipped for busco_only genomes - + // remainder keeps every eukaryotic genome, missing results are null + ch_euk_stats = ch_fasta + .map { meta, _fasta -> [ meta, true ] } + .join(ch_busco_completeness, remainder: true) + .join(ch_eukcc_stats.map { meta, completeness, contamination, software -> [ meta, [completeness, contamination, software] ] }, remainder: true) + .combine(busco_software) + .map { meta, _is_euk, busco_completeness, eukcc_stats, busco_sw -> + def contamination = eukcc_stats ? eukcc_stats[1] : meta.contamination + def tools = [ busco_sw, eukcc_stats ? eukcc_stats[2] : null ] + [ meta, busco_completeness, contamination, mergeSoftware(meta.stats_generation_software, tools) ] + } + } else { + ch_euk_stats = ch_eukcc_stats + .map { meta, completeness, contamination, software -> + [ meta, completeness, contamination, mergeSoftware(meta.stats_generation_software, [software]) ] + } + } + + // ------ Filter out genomes without completeness or contamination + // EukCC reports NA when it cannot place a genome, BUSCO summary is missing when no genes are found. + // Values are not checked in -stub mode, where empty tool outputs give null values. + ch_euk_stats_branched = ch_euk_stats + .branch { _meta, completeness, contamination, _software -> + not_assigned: !workflow.stubRun && [completeness, contamination].any { value -> isNotAssigned(value) } + assigned: true + } + + ch_euk_stats_branched.not_assigned + .map { meta, completeness, contamination, software -> + log.warn("Genome '${meta.id}' is excluded from submission: ${software} returned completeness='${completeness}', contamination='${contamination}'") + "${meta.id}\t${completeness}\t${contamination}\t${software}" + } + .collectFile( + name: "${params.outdir}/${params.mode}/not_assigned_quality_genomes.tsv", + newLine: true, + seed: "sample\tcompleteness\tcontamination\tstats_generation_software\n" + ) + + emit: + stats = ch_euk_stats_branched.assigned // channel: [ val(meta), val(completeness), val(contamination), val(stats_generation_software) ] + not_assigned = ch_euk_stats_branched.not_assigned // channel: [ val(meta), val(completeness), val(contamination), val(stats_generation_software) ] + +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + FUNCTIONS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +// +// True if the database is a compressed tar archive that has to be extracted before use +// +def isArchive(db) { + return db && (db.name.endsWith('.tar.gz') || db.name.endsWith('.tgz')) +} + +// +// Return a value channel [ val(meta), path(db_dir) ] with a ready-to-use database: +// - archive (.tar.gz/.tgz, local or URL): the matching DB_UNTAR output, selected by meta.id +// - directory: used as is +// Anything else (single uncompressed file, remote directory) is an error +// +def prepareDatabase(db, db_id, ch_untarred) { + if (isArchive(db)) { + return ch_untarred + .filter { db_meta, _dir -> db_meta.id == db_id } + .first() + } + if (db.isDirectory()) { + return channel.value([[id: db_id], db]) + } + error("Database '${db}' for ${db_id} must be a local directory or a .tar.gz/.tgz archive (local path or URL)") +} + +// +// Read completeness ([results][Complete percentage]) from BUSCO short_summary json. +// With auto-lineage BUSCO writes a generic and a specific summary - the specific lineage is preferred. +// +def parseBuscoCompleteness(summaries) { + def summary_files = summaries instanceof List ? summaries : [summaries] + def summary = summary_files.find { json -> json.name.startsWith('short_summary.specific.') } ?: summary_files[0] + def completeness = new groovy.json.JsonSlurper().parseText(summary.text)?.results?.get('Complete percentage') + return completeness != null ? completeness.toString() : null +} diff --git a/subworkflows/local/eukaryotic_genome_evaluation/meta.yml b/subworkflows/local/eukaryotic_genome_evaluation/meta.yml new file mode 100644 index 00000000..ac99b995 --- /dev/null +++ b/subworkflows/local/eukaryotic_genome_evaluation/meta.yml @@ -0,0 +1,70 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "eukaryotic_genome_evaluation" +description: | + Estimates completeness and contamination of eukaryotic genomes. + Contamination is calculated by EukCC (or kept from the samplesheet). + Completeness is calculated by EukCC (default) or BUSCO, selected by eukaryotic_completeness_tool. + Databases can be given as a directory or as a .tar.gz/.tgz archive that is extracted by the subworkflow. +keywords: + - genome + - completeness + - contamination + - eukcc + - busco + - eukaryotes + - metagenomics + - MAGs + - bins +components: + - busco/busco + - untar + - gunzip + - eukcc/single +input: + - ch_fasta: + type: file + description: | + Channel containing eukaryotic genome FASTA files to evaluate. + Structure: [ val(meta), path(fasta) ] + pattern: "*.{fa,fasta,fna,fa.gz,fasta.gz,fna.gz}" + ontologies: + - edam: "http://edamontology.org/format_1929" # FASTA + - busco_db_lineage: + type: string + description: | + BUSCO lineage to check against, e.g. 'auto_euk' or '_odb(10|12)'. + Only used when eukaryotic_completeness_tool is 'busco'. + - busco_db: + type: directory + description: | + BUSCO database as a local directory or .tar.gz/.tgz archive (local path or URL), + expected structure `/lineages/_odb(10|12)`. + Provide null to let BUSCO download the lineage itself. + - busco_clean: + type: boolean + description: Clean intermediate BUSCO files. + - eukaryotic_completeness_tool: + type: string + description: Tool used to calculate completeness of eukaryotic genomes. + enum: ["eukcc", "busco"] + - eukcc_db: + type: directory + description: | + EukCC database as a local directory or .tar.gz/.tgz archive (local path or URL). + Required if at least one genome has to be evaluated with EukCC. +output: + - stats: + type: list + description: | + Channel containing completeness, contamination and software used per genome. + stats_generation_software lists the tools separated by ';', appended to the value given in the samplesheet. + Structure: [ val(meta), val(completeness), val(contamination), val(stats_generation_software) ] + - not_assigned: + type: list + description: | + Channel containing genomes excluded from submission because completeness or contamination + could not be estimated (missing, empty or NA). They are also reported in not_assigned_quality_genomes.tsv. + Structure: [ val(meta), val(completeness), val(contamination), val(stats_generation_software) ] +authors: + - "@KateSakharova" + - "@ochkalova" diff --git a/subworkflows/local/eukaryotic_genome_evaluation/tests/main.nf.test b/subworkflows/local/eukaryotic_genome_evaluation/tests/main.nf.test new file mode 100644 index 00000000..84e1b3c3 --- /dev/null +++ b/subworkflows/local/eukaryotic_genome_evaluation/tests/main.nf.test @@ -0,0 +1,56 @@ +nextflow_workflow { + + name "Test Subworkflow EUKARYOTIC_GENOME_EVALUATION" + script "../main.nf" + workflow "EUKARYOTIC_GENOME_EVALUATION" + + tag "subworkflows" + tag "subworkflows_local" + tag "subworkflows/eukaryotic_genome_evaluation" + tag "eukcc" + + test("eukaryote without estimate - eukcc - not assigned") { + + // Not a stub: values are not checked in -stub mode. + // SARS-CoV-2 genome has no fungal marker genes, so EukCC gives no estimate (exit code 201/204) + // and the genome is reported in not_assigned_quality_genomes.tsv instead of stats. + + when { + params { + mode = 'mags' + } + workflow { + """ + input[0] = channel.of([ + [ id:'test_not_assigned', domain:'euk' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta.gz', checkIfExists: true) + ]) + input[1] = 'auto_euk' + input[2] = null + input[3] = true + input[4] = 'eukcc' + input[5] = 'https://ftp.ebi.ac.uk/pub/databases/metagenomics/eukcc/eukcc2_db_tiny_fungi_test.tar.gz' + """ + } + } + + then { + def report = path("${params.outdir}/mags/not_assigned_quality_genomes.tsv") + assert workflow.success + assertAll( + { assert workflow.out.stats.size() == 0 }, + { assert workflow.out.not_assigned.size() == 1 }, + { assert workflow.out.not_assigned[0][0].id == 'test_not_assigned' }, + { assert workflow.out.not_assigned[0][1] == null }, + { assert workflow.out.not_assigned[0][2] == null }, + { assert report.exists() }, + { assert report.readLines()[0] == 'sample\tcompleteness\tcontamination\tstats_generation_software' }, + { assert report.readLines().size() == 2 }, + { assert report.readLines()[1].startsWith('test_not_assigned\tnull\tnull\teukcc_v') }, + { assert workflow.stdout.any { it.contains("Genome 'test_not_assigned' is excluded from submission") } } + ) + } + + } + +} diff --git a/subworkflows/local/eukaryotic_genome_evaluation/tests/main_stub.nf.test b/subworkflows/local/eukaryotic_genome_evaluation/tests/main_stub.nf.test new file mode 100644 index 00000000..1d273290 --- /dev/null +++ b/subworkflows/local/eukaryotic_genome_evaluation/tests/main_stub.nf.test @@ -0,0 +1,215 @@ +nextflow_workflow { + + name "Test Subworkflow EUKARYOTIC_GENOME_EVALUATION -stub" + script "../main.nf" + workflow "EUKARYOTIC_GENOME_EVALUATION" + + tag "subworkflows" + tag "subworkflows_local" + tag "subworkflows/eukaryotic_genome_evaluation" + tag "subworkflows/eukaryotic_genome_evaluation_stub" + tag "busco" + tag "busco/busco" + tag "eukcc" + tag "untar" + tag "gunzip" + + test("eukaryote - eukcc - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.of([ + [ id:'test_euk', domain:'euk' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.gz', checkIfExists: true) + ]) + input[1] = 'auto_euk' // busco_db_lineage + input[2] = null // busco_db + input[3] = true // busco_clean + input[4] = 'eukcc' // eukaryotic_completeness_tool + input[5] = '.' // fake folder replacing eukcc_db because test DB https://ftp.ebi.ac.uk/pub/databases/metagenomics/eukcc/eukcc2_db_tiny_fungi_test.tar.gz is big + """ + } + } + + then { + assert workflow.success + assertAll( + { assert snapshot(workflow.out.stats).match() }, + { assert workflow.out.stats.size() == 1 }, + { assert workflow.out.stats[0][1] == '90.0' }, // fake values assigned by eukcc in -stub + { assert workflow.out.stats[0][2] == '1.0' }, // fake values assigned by eukcc in -stub + { assert workflow.out.stats[0][3].startsWith('eukcc_v') }, + { assert !workflow.trace.tasks().any { it.name.contains('BUSCO') } } + ) + } + + } + + test("eukaryote - busco - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.of([ + [ id:'test_euk', domain:'euk' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.gz', checkIfExists: true) + ]) + input[1] = 'auto_euk' + input[2] = null // busco_db - BUSCO downloads lineages itself + input[3] = true + input[4] = 'busco' + input[5] = '.' // fake folder replacing eukcc_db + """ + } + } + + then { + assert workflow.success + assertAll( + { assert snapshot(workflow.out.stats).match() }, + { assert workflow.out.stats.size() == 1 }, + // completeness is taken from BUSCO - stub writes no short summary json, so it is empty + { assert workflow.out.stats[0][1] == null }, + // contamination is always taken from EukCC + { assert workflow.out.stats[0][2] == '1.0' }, + { assert workflow.out.stats[0][3] ==~ /busco_v[^;]+;eukcc_v[^;]+/ }, + { assert workflow.trace.tasks().any { it.name.contains('BUSCO_BUSCO') } } + ) + } + + } + + test("eukaryote with contamination - busco - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.of([ + [ id:'test_euk', domain:'euk', contamination:2.5, stats_generation_software:'CustomTool_v1.0' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.gz', checkIfExists: true) + ]) + input[1] = 'auto_euk' + input[2] = null + input[3] = true + input[4] = 'busco' + input[5] = null // eukcc_db is not required - EukCC is skipped + """ + } + } + + then { + assert workflow.success + assertAll( + { assert snapshot(workflow.out.stats).match() }, + { assert workflow.out.stats.size() == 1 }, + // completeness from BUSCO (stub - empty), contamination kept from samplesheet + { assert workflow.out.stats[0][1] == null }, + { assert workflow.out.stats[0][2] == 2.5 }, + // BUSCO is appended to the software given in samplesheet, EukCC is not listed + { assert workflow.out.stats[0][3] ==~ /CustomTool_v1\.0;busco_v[^;]+/ }, + { assert !workflow.trace.tasks().any { it.name =~ /EUKCC|GUNZIP_FASTA|DB_UNTAR/ } }, + { assert workflow.trace.tasks().any { it.name.contains('BUSCO_BUSCO') } } + ) + } + + } + + test("eukaryote with contamination - eukcc - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.of([ + [ id:'test_euk', domain:'euk', contamination:2.5, stats_generation_software:'CustomTool_v1.0' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.gz', checkIfExists: true) + ]) + input[1] = 'auto_euk' + input[2] = null + input[3] = true + input[4] = 'eukcc' + input[5] = '.' // fake folder replacing eukcc_db + """ + } + } + + then { + assert workflow.success + assertAll( + { assert snapshot(workflow.out.stats).match() }, + { assert workflow.out.stats.size() == 1 }, + // completeness from EukCC, contamination kept from samplesheet + { assert workflow.out.stats[0][1] == '90.0' }, + { assert workflow.out.stats[0][2] == 2.5 }, + { assert workflow.out.stats[0][3] ==~ /CustomTool_v1\.0;eukcc_v[^;]+/ }, + { assert workflow.trace.tasks().any { it.name.contains('EUKCC_SINGLE') } } + ) + } + + } + + test("eukaryote - no eukcc_db - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.of([ + [ id:'test_euk', domain:'euk' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta.gz', checkIfExists: true) + ]) + input[1] = 'auto_euk' + input[2] = null + input[3] = true + input[4] = 'eukcc' + input[5] = null // eukcc_db missing while eukaryotes are present + """ + } + } + + then { + assert workflow.failed + assert workflow.stdout.any { it.contains('--eukcc_db is not provided') } || + workflow.stderr.any { it.contains('--eukcc_db is not provided') } + } + + } + + test("no genomes - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.empty() + input[1] = 'auto_euk' + input[2] = null + input[3] = true + input[4] = 'eukcc' + input[5] = null // eukcc_db is not required without eukaryotes + """ + } + } + + then { + assert workflow.success + assertAll( + { assert workflow.out.stats.size() == 0 }, + // no eukaryotes - eukaryotic steps must not run + { assert !workflow.trace.tasks().any { it.name =~ /EUKCC|BUSCO|DB_UNTAR|GUNZIP_FASTA/ } } + ) + } + + } + +} diff --git a/subworkflows/local/eukaryotic_genome_evaluation/tests/main_stub.nf.test.snap b/subworkflows/local/eukaryotic_genome_evaluation/tests/main_stub.nf.test.snap new file mode 100644 index 00000000..97d22b2e --- /dev/null +++ b/subworkflows/local/eukaryotic_genome_evaluation/tests/main_stub.nf.test.snap @@ -0,0 +1,86 @@ +{ + "eukaryote - busco - stub": { + "content": [ + [ + [ + { + "id": "test_euk", + "domain": "euk" + }, + null, + "1.0", + "busco_v6.1.0;eukcc_v2.2.0" + ] + ] + ], + "timestamp": "2026-10-21T18:04:58.162808", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + }, + "eukaryote with contamination - eukcc - stub": { + "content": [ + [ + [ + { + "id": "test_euk", + "domain": "euk", + "contamination": 2.5, + "stats_generation_software": "CustomTool_v1.0" + }, + "90.0", + 2.5, + "CustomTool_v1.0;eukcc_v2.2.0" + ] + ] + ], + "timestamp": "2026-10-21T18:05:55.032161", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + }, + "eukaryote - eukcc - stub": { + "content": [ + [ + [ + { + "id": "test_euk", + "domain": "euk" + }, + "90.0", + "1.0", + "eukcc_v2.2.0" + ] + ] + ], + "timestamp": "2026-10-21T18:04:14.72553", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + }, + "eukaryote with contamination - busco - stub": { + "content": [ + [ + [ + { + "id": "test_euk", + "domain": "euk", + "contamination": 2.5, + "stats_generation_software": "CustomTool_v1.0" + }, + null, + 2.5, + "CustomTool_v1.0;busco_v6.1.0" + ] + ] + ], + "timestamp": "2026-10-21T18:05:21.38848", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + } +} \ No newline at end of file diff --git a/subworkflows/local/genome_evaluation/main.nf b/subworkflows/local/genome_evaluation/main.nf deleted file mode 100644 index 8b74a36a..00000000 --- a/subworkflows/local/genome_evaluation/main.nf +++ /dev/null @@ -1,57 +0,0 @@ -// -// Subworkflow that calculates completeness and contamination for genome -// - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -include { CHECKM2_DATABASEDOWNLOAD } from '../../../modules/nf-core/checkm2/databasedownload/main' -include { CHECKM2_PREDICT } from '../../../modules/nf-core/checkm2/predict/main' - -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - SUBWORKFLOW -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*/ - -workflow GENOME_EVALUATION { - - take: - ch_fasta // channel: [ val(meta), path(fasta) ] - ch_checkm2_db // val: path to local CheckM2 database or null to trigger automatic download - ch_checkm2_db_download_id // val: CheckM2 database Zenodo download ID - - main: - - // - // Database preparation - // - ch_do_download = ch_fasta - .first() - .map { _meta_fasta -> ch_checkm2_db_download_id } - - // Download and prepare db from scratch if no pre-built db provided - if (ch_checkm2_db) { - ch_checkm2_db_ready = channel.value([[id: 'checkm2_db'], file(params.checkm2_db, checkIfExists: true)]) - } else { - CHECKM2_DATABASEDOWNLOAD(ch_do_download) - ch_checkm2_db_ready = CHECKM2_DATABASEDOWNLOAD.out.database - } - - // - // Genome evaluation - // - - CHECKM2_PREDICT( - ch_fasta, - ch_checkm2_db_ready, - ) - - emit: - genome_evaluation = CHECKM2_PREDICT.out.checkm2_tsv // channel: [ val(meta), path(tsv) ] - stats_versions = CHECKM2_PREDICT.out.versions_checkm2_predict - -} diff --git a/subworkflows/local/genome_evaluation/meta.yml b/subworkflows/local/genome_evaluation/meta.yml deleted file mode 100644 index 33af059b..00000000 --- a/subworkflows/local/genome_evaluation/meta.yml +++ /dev/null @@ -1,55 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json -name: "genome_evaluation" -description: | - Estimates genome completeness and contamination using CheckM2. - Downloads the CheckM2 database automatically when no pre-built database is provided. -keywords: - - genome - - completeness - - contamination - - checkm2 - - metagenomics - - MAGs - - bins -components: - - checkm2/databasedownload - - checkm2/predict -input: - - ch_fasta: - type: file - description: | - Channel containing genome FASTA files to evaluate. - Structure: [ val(meta), path(fasta) ] - pattern: "*.{fa,fasta,fna,fa.gz,fasta.gz,fna.gz}" - ontologies: - - edam: "http://edamontology.org/format_1929" # FASTA - - ch_checkm2_db: - type: directory - description: | - Channel containing a pre-built CheckM2 database directory. - Provide channel.empty() to trigger automatic download via ch_checkm2_db_download_id. - Structure: [ val(meta), path(db) ] - - ch_checkm2_db_download_id: - type: string - description: | - Channel containing the Zenodo record ID used to download the CheckM2 database - via CHECKM2_DATABASEDOWNLOAD (e.g. '1234567'). - Only used when ch_checkm2_db is channel.empty(). - Structure: [ val(meta), val(db_id) ] -output: - - genome_evaluation: - type: file - description: | - Channel containing per-genome CheckM2 quality summary TSV files. - Structure: [ val(meta), path(tsv) ] - pattern: "*.tsv" - ontologies: - - edam: "http://edamontology.org/format_3475" # TSV - - stats_versions: - type: file - description: | - Channel containing software versions from CheckM2. - Structure: versions -authors: - - "@KateSakharova" - - "@ochkalova" diff --git a/subworkflows/local/prokaryotic_genome_evaluation/main.nf b/subworkflows/local/prokaryotic_genome_evaluation/main.nf new file mode 100644 index 00000000..fe1ef7b5 --- /dev/null +++ b/subworkflows/local/prokaryotic_genome_evaluation/main.nf @@ -0,0 +1,70 @@ +// +// Subworkflow that calculates completeness and contamination for prokaryotic genomes +// + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IMPORT FUNCTIONS / MODULES / SUBWORKFLOWS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ +include { CHECKM2_DATABASEDOWNLOAD } from '../../../modules/nf-core/checkm2/databasedownload/main' +include { CHECKM2_PREDICT } from '../../../modules/nf-core/checkm2/predict/main' + +include { parseStatsTable; mergeSoftware } from '../utils_nfcore_seqsubmit_pipeline' + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + SUBWORKFLOW +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +workflow PROKARYOTIC_GENOME_EVALUATION { + + take: + ch_fasta // channel: [ val(meta), path(fasta) ] - prokaryotic genomes only + ch_checkm2_db // val: path to local CheckM2 database or null to trigger automatic download + ch_checkm2_db_download_id // val: CheckM2 database Zenodo download ID + + main: + + // Database preparation for checkm2 + // that step would be launched only if input is not empty + ch_do_download = ch_fasta + .first() + .map { _meta_fasta -> ch_checkm2_db_download_id } + + // Download and prepare db from scratch if no pre-built db provided + if (ch_checkm2_db) { + ch_checkm2_db_ready = channel.value([[id: 'checkm2_db'], file(ch_checkm2_db, checkIfExists: true)]) + } else { + CHECKM2_DATABASEDOWNLOAD(ch_do_download) + ch_checkm2_db_ready = CHECKM2_DATABASEDOWNLOAD.out.database + } + + // Genome evaluation with CheckM2 + + CHECKM2_PREDICT( + ch_fasta, + ch_checkm2_db_ready, + ) + + // ------ Completeness and contamination from CheckM2 + // Tools are listed in stats_generation_software separated by ';'. + // If stats_generation_software is given in the samplesheet, CheckM2 is appended to it. + + // Software name with version, e.g. checkm2_v1.0.2 + def checkm2_software = CHECKM2_PREDICT.out.versions_checkm2_predict + .map { _process_name, tool_name, version -> "${tool_name}_v${version}" } + .first() + + ch_prok_stats = CHECKM2_PREDICT.out.checkm2_tsv + .combine(checkm2_software) + .map { meta, table, software -> parseStatsTable(meta, table, software) } + .map { meta, completeness, contamination, software -> + [ meta, completeness, contamination, mergeSoftware(meta.stats_generation_software, [software]) ] + } + + emit: + stats = ch_prok_stats // channel: [ val(meta), val(completeness), val(contamination), val(stats_generation_software) ] + +} diff --git a/subworkflows/local/prokaryotic_genome_evaluation/meta.yml b/subworkflows/local/prokaryotic_genome_evaluation/meta.yml new file mode 100644 index 00000000..02c4ad77 --- /dev/null +++ b/subworkflows/local/prokaryotic_genome_evaluation/meta.yml @@ -0,0 +1,46 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: "prokaryotic_genome_evaluation" +description: | + Estimates completeness and contamination of prokaryotic (bacterial and archaeal) genomes using CheckM2. + Downloads the CheckM2 database automatically when no pre-built database is provided. +keywords: + - genome + - completeness + - contamination + - checkm2 + - prokaryotes + - metagenomics + - MAGs + - bins +components: + - checkm2/databasedownload + - checkm2/predict +input: + - ch_fasta: + type: file + description: | + Channel containing prokaryotic genome FASTA files to evaluate. + Structure: [ val(meta), path(fasta) ] + pattern: "*.{fa,fasta,fna,fa.gz,fasta.gz,fna.gz}" + ontologies: + - edam: "http://edamontology.org/format_1929" # FASTA + - ch_checkm2_db: + type: directory + description: | + Path to a pre-built CheckM2 database. + Provide null to trigger automatic download via ch_checkm2_db_download_id. + - ch_checkm2_db_download_id: + type: integer + description: | + Zenodo record ID used to download the CheckM2 database via CHECKM2_DATABASEDOWNLOAD (e.g. 14897628). + Only used when ch_checkm2_db is null. +output: + - stats: + type: list + description: | + Channel containing completeness, contamination and software used per genome. + stats_generation_software lists the tools separated by ';', appended to the value given in the samplesheet. + Structure: [ val(meta), val(completeness), val(contamination), val(stats_generation_software) ] +authors: + - "@KateSakharova" + - "@ochkalova" diff --git a/subworkflows/local/prokaryotic_genome_evaluation/tests/main.nf.test b/subworkflows/local/prokaryotic_genome_evaluation/tests/main.nf.test new file mode 100644 index 00000000..db54291f --- /dev/null +++ b/subworkflows/local/prokaryotic_genome_evaluation/tests/main.nf.test @@ -0,0 +1,106 @@ +nextflow_workflow { + + name "Test Subworkflow PROKARYOTIC_GENOME_EVALUATION" + script "../main.nf" + workflow "PROKARYOTIC_GENOME_EVALUATION" + + tag "subworkflows" + tag "subworkflows_local" + tag "subworkflows/prokaryotic_genome_evaluation" + tag "checkm2" + tag "checkm2/predict" + tag "checkm2/databasedownload" + + test("prokaryotes - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.of( + [ + [ id:'test_bac', domain:'bac' ], + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ], + [ + [ id:'test_arc', domain:'arc' ], + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ] + ) + input[1] = null // checkm2_db - triggers CHECKM2_DATABASEDOWNLOAD + input[2] = 14897628 // checkm2_db_download_id + """ + } + } + + then { + assert workflow.success + assertAll( + { assert snapshot(workflow.out.stats.sort { it[0].id }).match() }, + { assert workflow.out.stats.size() == 2 }, + // CheckM2 stub writes an empty report - no values + { assert workflow.out.stats.every { it[1] == null && it[2] == null } }, + { assert workflow.out.stats.every { it[3].startsWith('checkm2_v') } }, + // CheckM2 database is downloaded once for all prokaryotes + { assert workflow.trace.tasks().count { it.name.contains('CHECKM2_DATABASEDOWNLOAD') } == 1 } + ) + } + + } + + test("prokaryote with stats_generation_software - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.of([ + [ id:'test_bac', domain:'bac', stats_generation_software:'CustomTool_v1.0' ], + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ]) + input[1] = null + input[2] = 14897628 + """ + } + } + + then { + assert workflow.success + assertAll( + { assert snapshot(workflow.out.stats).match() }, + { assert workflow.out.stats.size() == 1 }, + // CheckM2 is appended to the software given in samplesheet + { assert workflow.out.stats[0][3] ==~ /CustomTool_v1\.0;checkm2_v[^;]+/ } + ) + } + + } + + test("no genomes - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.empty() + input[1] = null + input[2] = 14897628 + """ + } + } + + then { + assert workflow.success + assertAll( + { assert workflow.out.stats.size() == 0 }, + // CheckM2 database must not be downloaded without prokaryotes + { assert !workflow.trace.tasks().any { it.name.contains('CHECKM2') } } + ) + } + + } + +} diff --git a/subworkflows/local/prokaryotic_genome_evaluation/tests/main.nf.test.snap b/subworkflows/local/prokaryotic_genome_evaluation/tests/main.nf.test.snap new file mode 100644 index 00000000..f9ffeab8 --- /dev/null +++ b/subworkflows/local/prokaryotic_genome_evaluation/tests/main.nf.test.snap @@ -0,0 +1,52 @@ +{ + "prokaryote with stats_generation_software - stub": { + "content": [ + [ + [ + { + "id": "test_bac", + "domain": "bac", + "stats_generation_software": "CustomTool_v1.0" + }, + null, + null, + "CustomTool_v1.0;checkm2_v1.1.0" + ] + ] + ], + "timestamp": "2026-10-21T18:09:23.381378", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + }, + "prokaryotes - stub": { + "content": [ + [ + [ + { + "id": "test_arc", + "domain": "arc" + }, + null, + null, + "checkm2_v1.1.0" + ], + [ + { + "id": "test_bac", + "domain": "bac" + }, + null, + null, + "checkm2_v1.1.0" + ] + ] + ], + "timestamp": "2026-10-21T18:08:46.296846", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + } +} \ No newline at end of file diff --git a/subworkflows/local/rna_detection/main.nf b/subworkflows/local/rna_detection/main.nf index 0cac5bb8..22b2a996 100644 --- a/subworkflows/local/rna_detection/main.nf +++ b/subworkflows/local/rna_detection/main.nf @@ -27,7 +27,7 @@ workflow RNA_DETECTION { main: BARRNAP( - fasta.map {id, fasta_file -> [id, fasta_file, "bac"]} + fasta.map {meta, fasta_file -> [meta, fasta_file, meta.domain]} ) TRNASCANSE( diff --git a/subworkflows/local/rna_detection/meta.yml b/subworkflows/local/rna_detection/meta.yml index 84902bab..6f7f06a3 100644 --- a/subworkflows/local/rna_detection/meta.yml +++ b/subworkflows/local/rna_detection/meta.yml @@ -3,6 +3,7 @@ name: "rna_detection" description: | Detects tRNA and rRNA genes in genome FASTA files using tRNAscan-SE and Barrnap, then evaluates whether the genome meets MIMAG RNA completeness standards. + Prediction mode and required rRNA genes depend on the genome's domain (meta.domain). keywords: - rna - trna @@ -14,33 +15,39 @@ keywords: components: - barrnap - trnascanse - - countrna + - count_rna input: - fasta: type: file description: | Channel containing genome FASTA files. + meta.domain must be one of 'bac', 'arc' or 'euk'. It sets the Barrnap kingdom, + the tRNAscan-SE search mode (-B/-A/-E, via conf/modules.config) and the rRNA genes + required by COUNT_RNA. Structure: [ val(meta), path(fasta) ] + e.g. [ [ id:'test', domain:'bac' ], genome.fasta ] pattern: "*.{fa,fasta,fna,fa.gz,fasta.gz,fna.gz}" ontologies: - edam: "http://edamontology.org/format_1929" # FASTA - min_trna_count: type: integer description: | - Minimum number of distinct tRNA types required to pass the MIMAG standard (e.g. 18). + Minimum total number of tRNA genes for the 20 standard amino acids required + to pass the MIMAG standard (e.g. 18). - min_rrna_percentage: type: float description: | - Minimum percentage of the three rRNA genes (5S, 16S, 23S) required to pass - the MIMAG standard (e.g. 75.0). + Minimum percentage of expected gene length that must be recovered for each + required rRNA gene to count it as present (e.g. 80). + Required genes: 16S, 23S and 5S for 'bac'/'arc'; 18S, 28S, 5.8S and 5S for 'euk'. output: - rna_detected: type: file description: | - Channel containing per-genome TSV files with tRNA/rRNA counts and a - MIMAG pass/fail decision. + Channel containing per-genome TSV files with one line: genome ID and + RNA presence decision (True/False). Structure: [ val(meta), path(tsv) ] - pattern: "*.tsv" + pattern: "*_rna_decision.tsv" ontologies: - edam: "http://edamontology.org/format_3475" # TSV authors: diff --git a/subworkflows/local/rna_detection/tests/main.nf.test b/subworkflows/local/rna_detection/tests/main.nf.test new file mode 100644 index 00000000..dbe844c1 --- /dev/null +++ b/subworkflows/local/rna_detection/tests/main.nf.test @@ -0,0 +1,132 @@ +nextflow_workflow { + + name "Test Subworkflow RNA_DETECTION" + script "../main.nf" + workflow "RNA_DETECTION" + + tag "subworkflows" + tag "subworkflows_local" + tag "subworkflows/rna_detection" + tag "barrnap" + tag "trnascanse" + tag "count_rna" + + test("bacteroides_fragilis - bac") { + + when { + workflow { + """ + input[0] = channel.of([ + [ id:'test_bac', domain:'bac' ], + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ]) + input[1] = 18 + input[2] = 80 + """ + } + } + + then { + assert workflow.success + assertAll( + { assert snapshot(workflow.out.rna_detected).match() }, + { assert workflow.out.rna_detected.size() == 1 }, + // complete bacterial isolate genome - all rRNA genes and enough tRNAs are expected + { assert path(workflow.out.rna_detected[0][1]).text.contains("True") } + ) + } + + } + + test("homo_sapiens - euk") { + + when { + workflow { + """ + input[0] = channel.of([ + [ id:'test_euk', domain:'euk' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ]) + input[1] = 18 + input[2] = 80 + """ + } + } + + then { + assert workflow.success + assertAll( + { assert snapshot(workflow.out.rna_detected).match() }, + { assert workflow.out.rna_detected.size() == 1 }, + // small chromosome fragment - eukaryotic rRNA set is not expected to be complete + { assert path(workflow.out.rna_detected[0][1]).text.contains("False") } + ) + } + + } + + test("multiple genomes - mixed domains") { + + when { + workflow { + """ + input[0] = channel.of( + [ + [ id:'test_bac', domain:'bac' ], + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ], + [ + [ id:'test_euk', domain:'euk' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.fasta', checkIfExists: true) + ] + ) + input[1] = 18 + input[2] = 80 + """ + } + } + + then { + assert workflow.success + // TRNASCANSE and BARRNAP outputs are joined by meta - each genome must get exactly one decision + def decisions = workflow.out.rna_detected + .collectEntries { meta, tsv -> [ (meta.id): path(tsv).text ] } + assertAll( + { assert snapshot(workflow.out.rna_detected.sort { it[0].id }).match() }, + { assert workflow.out.rna_detected.size() == 2 }, + { assert decisions.keySet() == ['test_bac', 'test_euk'] as Set }, + { assert decisions['test_bac'].contains("True") }, + { assert decisions['test_euk'].contains("False") } + ) + } + + } + + test("bacteroides_fragilis - bac - stub") { + + options "-stub" + + when { + workflow { + """ + input[0] = channel.of([ + [ id:'test_bac', domain:'bac' ], + file(params.modules_testdata_base_path + 'genomics/prokaryotes/bacteroides_fragilis/genome/genome.fna.gz', checkIfExists: true) + ]) + input[1] = 18 + input[2] = 80 + """ + } + } + + then { + assert workflow.success + assertAll( + { assert snapshot(workflow.out.rna_detected).match() }, + { assert workflow.out.rna_detected.size() == 1 } + ) + } + + } + +} diff --git a/subworkflows/local/rna_detection/tests/main.nf.test.snap b/subworkflows/local/rna_detection/tests/main.nf.test.snap new file mode 100644 index 00000000..05bad786 --- /dev/null +++ b/subworkflows/local/rna_detection/tests/main.nf.test.snap @@ -0,0 +1,81 @@ +{ + "bacteroides_fragilis - bac - stub": { + "content": [ + [ + [ + { + "id": "test_bac", + "domain": "bac" + }, + "test_bac_rna_decision.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ] + ], + "timestamp": "2026-10-14T15:01:52.546789", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + }, + "homo_sapiens - euk": { + "content": [ + [ + [ + { + "id": "test_euk", + "domain": "euk" + }, + "test_euk_rna_decision.tsv:md5,70447fb76ec179475ad2f4eca8ef9892" + ] + ] + ], + "timestamp": "2026-10-14T14:55:50.441162", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + }, + "multiple genomes - mixed domains": { + "content": [ + [ + [ + { + "id": "test_bac", + "domain": "bac" + }, + "test_bac_rna_decision.tsv:md5,99228ffd59107b1168a98f5c69d4e3e3" + ], + [ + { + "id": "test_euk", + "domain": "euk" + }, + "test_euk_rna_decision.tsv:md5,70447fb76ec179475ad2f4eca8ef9892" + ] + ] + ], + "timestamp": "2026-10-14T16:46:52.104684", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + }, + "bacteroides_fragilis - bac": { + "content": [ + [ + [ + { + "id": "test_bac", + "domain": "bac" + }, + "test_bac_rna_decision.tsv:md5,99228ffd59107b1168a98f5c69d4e3e3" + ] + ] + ], + "timestamp": "2026-10-14T16:40:41.699153", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + } +} \ No newline at end of file diff --git a/subworkflows/local/utils_nfcore_seqsubmit_pipeline/main.nf b/subworkflows/local/utils_nfcore_seqsubmit_pipeline/main.nf index d4e930e3..c89133d1 100644 --- a/subworkflows/local/utils_nfcore_seqsubmit_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_seqsubmit_pipeline/main.nf @@ -209,7 +209,10 @@ def toolCitationText() { ].join(' ').trim() def stats_tools = [ - params.mode == "bins" || params.mode == "mags" ? "Completeness and contamination metrics was performed by CheckM2 (Chklovski et al. 2023)." : "", + params.mode == "bins" || params.mode == "mags" ? "Completeness and contamination metrics for prokaryotic genomes were calculated by CheckM2 (Chklovski et al. 2023)." : "", + params.mode == "bins" || params.mode == "mags" ? "Contamination metrics for eukaryotic genomes were calculated by EukCC (Saary et al. 2020), which uses MetaEuk (Levy Karin et al. 2020) and pplacer (Matsen et al. 2010)." : "", + (params.mode == "bins" || params.mode == "mags") && params.eukaryotic_completeness_tool == "busco" ? "Completeness metrics for eukaryotic genomes were calculated by BUSCO (Manni et al. 2021; Tegenfeldt et al. 2025)." : "", + (params.mode == "bins" || params.mode == "mags") && params.eukaryotic_completeness_tool != "busco" ? "Completeness metrics for eukaryotic genomes were calculated by EukCC (Saary et al. 2020)." : "", params.mode == "metagenomic_assemblies" ? "Coverage calculation for metagenomic assemblies was done by CoverM contig (Aroney et el. 2025)." : "", params.mode == "bins" || params.mode == "mags" ? "Coverage calculation for bins/MAGs was done by CoverM genome (Aroney et el. 2025)." : "" ].join(' ').trim() @@ -219,7 +222,7 @@ def toolCitationText() { ].join(' ').trim() def rna_tools = [ - params.mode == "bins" || params.mode == "mags" ? "Bacterial ribosomal RNA prediction was performed by barrnap (Seemann T. 2013)." : "", + params.mode == "bins" || params.mode == "mags" ? "Ribosomal RNA prediction was performed by barrnap (Seemann T. 2013)." : "", params.mode == "bins" || params.mode == "mags" ? "Transfer RNA genes were detected by tRNAscan-SE (Chan et al. 2021)." : "" ].join(' ').trim() @@ -246,6 +249,11 @@ def toolBibliographyText() { '
  • Edwards, R. (2023). linsalrob/py_fasta_validator: Compressy. doi: 10.5281/zenodo.5002710
  • ', '
  • Chklovski, A., Parks, D. H., Woodcroft, B. J., & Tyson, G. W. (2023). CheckM2: a rapid, scalable and accurate tool for assessing microbial genome quality using machine learning. Nature Methods, 20(8), 1203-1212. doi: 10.1038/s41592-023-01940-w
  • ', '
  • Aroney, S. T., Newell, R. J., Nissen, J. N., Camargo, A. P., Tyson, G. W., & Woodcroft, B. J. (2025). CoverM: read alignment statistics for metagenomics. Bioinformatics, 41(4), btaf147. doi: 10.1093/bioinformatics/btaf147
  • ', + '
  • Saary, P., Mitchell, A. L., & Finn, R. D. (2020). Estimating the quality of eukaryotic genomes recovered from metagenomic analysis with EukCC. Genome Biology, 21(1), 244. doi: 10.1186/s13059-020-02155-4
  • ', + '
  • Levy Karin, E., Mirdita, M., & Söding, J. (2020). MetaEuk—sensitive, high-throughput gene discovery, and annotation for large-scale eukaryotic metagenomics. Microbiome, 8(1), 48. doi: 10.1186/s40168-020-00808-x
  • ', + '
  • Matsen, F. A., Kodner, R. B., & Armbrust, E. V. (2010). pplacer: linear time maximum-likelihood and Bayesian phylogenetic placement of sequences onto a fixed reference tree. BMC Bioinformatics, 11, 538. doi: 10.1186/1471-2105-11-538
  • ', + params.eukaryotic_completeness_tool == "busco" ? '
  • Manni, M., Berkeley, M. R., Seppey, M., Simão, F. A., & Zdobnov, E. M. (2021). BUSCO Update: Novel and Streamlined Workflows along with Broader and Deeper Phylogenetic Coverage for Scoring of Eukaryotic, Prokaryotic, and Viral Genomes. Molecular Biology and Evolution, 38(10), 4647-4654. doi: 10.1093/molbev/msab199
  • ' : "", + params.eukaryotic_completeness_tool == "busco" ? '
  • Tegenfeldt, F., Kuznetsov, D., Manni, M., Berkeley, M., Zdobnov, E. M., & Kriventseva, E. V. (2025). OrthoDB and BUSCO update: annotation of orthologs with wider sampling of genomes. Nucleic Acids Research, 53(D1), D516-D522. doi: 10.1093/nar/gkae987
  • ' : "", '
  • Von Meijenfeldt, F. B., Arkhipova, K., Cambuy, D. D., Coutinho, F. H., & Dutilh, B. E. (2019). Robust taxonomic classification of uncharted microbial sequences and bins with CAT and BAT. Genome biology, 20(1), 217. doi: 10.1038/s41467-024-47155-1
  • ', '
  • Seemann, T. (2014). barrnap: Bacterial ribosomal RNA predictor. barrnap: Bacterial ribosomal RNA predictor. vicbioinformatics.com
  • ', '
  • Chan, P. P., Lin, B. Y., Mak, A. J., & Lowe, T. M. (2021). tRNAscan-SE 2.0: improved detection and functional classification of transfer RNA genes. Nucleic acids research, 49(16), 9077-9096. doi: 10.1093/nar/gkab688
  • ', @@ -290,3 +298,36 @@ def methodsDescriptionText(mqc_methods_yaml) { return description_html.toString() } + +// +// Read completeness and contamination from a CheckM2 quality_report.tsv or EukCC eukcc.tsv. +// Both are tab-separated with a header and genome name, completeness, contamination as first three columns. +// Empty or header-only tables (-stub mode, EukCC exit codes 201/204) give null values. +// +def parseStatsTable(meta, table, software) { + def lines = table.readLines() + def values = lines.size() > 1 ? lines[1].split('\t') : null + return [ + meta, + values ? values[1] : null, + values ? values[2] : null, + software + ] +} + +// +// Check if completeness or contamination value was not assigned by a tool: missing, empty or NA/NaN +// +def isNotAssigned(value) { + return value == null || value.toString().trim().toUpperCase() in ['', 'NA', 'NAN'] +} + +// +// Join software names with ';', appending launched tools to the software given in the samplesheet. +// Duplicates and empty values are removed, e.g. "CheckM2_v1.0.0;eukcc_v2.2.0" +// +def mergeSoftware(existing, tools) { + def existing_tools = existing ? existing.toString().tokenize(';').collect { tool -> tool.trim() } : [] + def merged = (existing_tools + tools.findAll { tool -> tool }.collect { tool -> tool.toString() }).unique() + return merged ? merged.join(';') : null +} diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index fd8cda70..5589d52b 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -1,7 +1,7 @@ { "-profile test": { "content": [ - 22, + 16, { "BARRNAP": { "barrnap": 0.9 @@ -15,11 +15,6 @@ "CAT_DB_UNTAR": { "untar": 1.34 }, - "CONCAT_ACCESSIONS": { - "coreutils": 9.4, - "find": "4.6.0", - "pigz": 2.8 - }, "CONCAT_METADATA": { "coreutils": 9.4, "find": "4.6.0", @@ -34,23 +29,12 @@ "CREATE_GENOME_METADATA_TSV": { "bash": "5.2.37(1)-release" }, - "CREATE_MANIFESTS": { - "genome_uploader": "3.0.4" - }, "FALINT": { "falint": "1.2.0" }, - "REGISTERSTUDY": { - "mgnify-pipelines-toolkit": "1.5.5" - }, "RENAME_FASTA_FOR_CATPACK": { "bash": "5.2.37(1)-release" }, - "SUBMIT": { - "ena-webin-cli": "9.0.3", - "mgnify-pipelines-toolkit": "1.5.5", - "python": "3.12.16" - }, "TRNASCANSE": { "tRNAscan-SE": "2.0.12" }, @@ -63,9 +47,6 @@ "mags/no_coverage_paired_reads", "mags/no_coverage_paired_reads/coverage", "mags/no_coverage_paired_reads/coverage/no_coverage_paired_reads.depth.tsv", - "mags/no_coverage_paired_reads/upload", - "mags/no_coverage_paired_reads/upload/webin_cli", - "mags/no_coverage_paired_reads/upload/webin_cli/no_coverage_paired_reads_accessions.tsv", "mags/no_rna_presence", "mags/no_rna_presence/rna", "mags/no_rna_presence/rna/barrnap", @@ -74,51 +55,29 @@ "mags/no_rna_presence/rna/trnascanse/no_rna_presence.log", "mags/no_rna_presence/rna/trnascanse/no_rna_presence.stats", "mags/no_rna_presence/rna/trnascanse/no_rna_presence.tsv", - "mags/no_rna_presence/upload", - "mags/no_rna_presence/upload/webin_cli", - "mags/no_rna_presence/upload/webin_cli/no_rna_presence_accessions.tsv", "mags/no_taxonomy", "mags/no_taxonomy/taxonomy", "mags/no_taxonomy/taxonomy/no_taxonomy.bin2classification.txt", "mags/no_taxonomy/taxonomy/no_taxonomy.txt", - "mags/no_taxonomy/upload", - "mags/no_taxonomy/upload/webin_cli", - "mags/no_taxonomy/upload/webin_cli/no_taxonomy_accessions.tsv", "mags/upload", - "mags/upload/genomes_accessions.tsv", "mags/upload/genomes_metadata.tsv", - "mags/upload/manifests", - "mags/upload/manifests/results", - "mags/upload/manifests/results/MAG_upload", - "mags/upload/manifests/results/MAG_upload/ENA_backup.json", - "mags/upload/manifests/results/MAG_upload/genome_samples.xml", - "mags/upload/manifests/results/MAG_upload/manifests_test", - "mags/upload/manifests/results/MAG_upload/registered_MAGs_test.tsv", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", "multiqc/multiqc_data/multiqc.log", "multiqc/multiqc_data/multiqc.parquet", - "multiqc/multiqc_data/multiqc_Genomes assigned accessions.txt", "multiqc/multiqc_data/multiqc_citations.txt", "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_genome_metadata.txt", - "multiqc/multiqc_data/multiqc_sample_registration.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/Genomes assigned accessions.pdf", "multiqc/multiqc_plots/pdf/genome_metadata.pdf", - "multiqc/multiqc_plots/pdf/sample_registration.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/Genomes assigned accessions.png", "multiqc/multiqc_plots/png/genome_metadata.png", - "multiqc/multiqc_plots/png/sample_registration.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/Genomes assigned accessions.svg", "multiqc/multiqc_plots/svg/genome_metadata.svg", - "multiqc/multiqc_plots/svg/sample_registration.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml" @@ -126,7 +85,7 @@ [ "no_coverage_paired_reads.depth.tsv:md5,fb8374996c3bad9ddd296684d8c28628", "no_rna_presence_bac.gff:md5,df19e1b84ba6f691d20c72b397c88abf", - "no_rna_presence.tsv:md5,abd958e8addba39c9e4d7f6b97a1a7c6", + "no_rna_presence.tsv:md5,373265f59324d05128361a34a3edad84", "no_taxonomy.bin2classification.txt:md5,e24c109efe807c7044a866999fd736f1", "no_taxonomy.txt:md5,0f2082d3e397fd630d605dd60993b131", "genomes_metadata.tsv:md5,2d7b5d99cd3058c7e7cd325e184cc7e9", @@ -134,10 +93,10 @@ "multiqc_genome_metadata.txt:md5,2f42824e9296d918b7f944037c27c717" ] ], - "timestamp": "2026-10-19T15:27:49.508151", + "timestamp": "2026-10-30T15:44:32.057076", "meta": { "nf-test": "0.9.5", - "nextflow": "26.04.1" + "nextflow": "26.10.4" } } } \ No newline at end of file diff --git a/tests/mag_no_taxonomy.nf.test b/tests/mag_missing_metadata.nf.test similarity index 88% rename from tests/mag_no_taxonomy.nf.test rename to tests/mag_missing_metadata.nf.test index d5296c47..1e1ddd97 100644 --- a/tests/mag_no_taxonomy.nf.test +++ b/tests/mag_missing_metadata.nf.test @@ -1,13 +1,13 @@ nextflow_pipeline { - name "Test genome submission workflow - no_taxonomy" + name "Test genome submission workflow - missing_metadata" script "../main.nf" tag "pipeline" tag "mode_mag" - tag "test_mag_no_taxonomy" - profile "test_mag_no_taxonomy" + tag "test_mag_missing_metadata" + profile "test_mag_missing_metadata" - test("-profile test_mag_no_taxonomy") { + test("-profile test_mag_missing_metadata") { when { params { diff --git a/tests/mag_no_taxonomy.nf.test.snap b/tests/mag_missing_metadata.nf.test.snap similarity index 69% rename from tests/mag_no_taxonomy.nf.test.snap rename to tests/mag_missing_metadata.nf.test.snap index 5a4d987c..72c96102 100644 --- a/tests/mag_no_taxonomy.nf.test.snap +++ b/tests/mag_missing_metadata.nf.test.snap @@ -1,8 +1,11 @@ { - "-profile test_mag_no_taxonomy": { + "-profile test_mag_missing_metadata": { "content": [ - 12, + 22, { + "BARRNAP": { + "barrnap": 0.9 + }, "CATPACK_ADDNAMES_BINS": { "catpack": 6.0 }, @@ -22,6 +25,12 @@ "find": "4.6.0", "pigz": 2.8 }, + "COUNT_RNA": { + "python": "3.12.12" + }, + "COVERM_GENOME": { + "coverm": "0.7.0" + }, "CREATE_GENOME_METADATA_TSV": { "bash": "5.2.37(1)-release" }, @@ -42,12 +51,32 @@ "mgnify-pipelines-toolkit": "1.5.5", "python": "3.12.16" }, + "TRNASCANSE": { + "tRNAscan-SE": "2.0.12" + }, "Workflow": { "nf-core/seqsubmit": "v1.0.0" } }, [ "mags", + "mags/no_coverage_paired_reads", + "mags/no_coverage_paired_reads/coverage", + "mags/no_coverage_paired_reads/coverage/no_coverage_paired_reads.depth.tsv", + "mags/no_coverage_paired_reads/upload", + "mags/no_coverage_paired_reads/upload/webin_cli", + "mags/no_coverage_paired_reads/upload/webin_cli/no_coverage_paired_reads_accessions.tsv", + "mags/no_rna_presence", + "mags/no_rna_presence/rna", + "mags/no_rna_presence/rna/barrnap", + "mags/no_rna_presence/rna/barrnap/no_rna_presence_bac.gff", + "mags/no_rna_presence/rna/trnascanse", + "mags/no_rna_presence/rna/trnascanse/no_rna_presence.log", + "mags/no_rna_presence/rna/trnascanse/no_rna_presence.stats", + "mags/no_rna_presence/rna/trnascanse/no_rna_presence.tsv", + "mags/no_rna_presence/upload", + "mags/no_rna_presence/upload/webin_cli", + "mags/no_rna_presence/upload/webin_cli/no_rna_presence_accessions.tsv", "mags/no_taxonomy", "mags/no_taxonomy/taxonomy", "mags/no_taxonomy/taxonomy/no_taxonomy.bin2classification.txt", @@ -95,17 +124,20 @@ "pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml" ], [ + "no_coverage_paired_reads.depth.tsv:md5,fb8374996c3bad9ddd296684d8c28628", + "no_rna_presence_bac.gff:md5,df19e1b84ba6f691d20c72b397c88abf", + "no_rna_presence.tsv:md5,373265f59324d05128361a34a3edad84", "no_taxonomy.bin2classification.txt:md5,e24c109efe807c7044a866999fd736f1", "no_taxonomy.txt:md5,0f2082d3e397fd630d605dd60993b131", - "genomes_metadata.tsv:md5,b1d01539d787b77e30b9bacd5b23d51f", + "genomes_metadata.tsv:md5,2d7b5d99cd3058c7e7cd325e184cc7e9", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", - "multiqc_genome_metadata.txt:md5,c2bdf8ba36b55b5f48fa07a26e5222f5" + "multiqc_genome_metadata.txt:md5,2f42824e9296d918b7f944037c27c717" ] ], - "timestamp": "2026-10-15T16:23:14.854681", + "timestamp": "2026-10-30T16:02:47.901797", "meta": { "nf-test": "0.9.5", - "nextflow": "26.10.0" + "nextflow": "26.10.4" } } } \ No newline at end of file diff --git a/tests/mag_no_coverage_paired_reads.nf.test b/tests/mag_no_coverage_pe_skip_ena_queries.nf.test similarity index 88% rename from tests/mag_no_coverage_paired_reads.nf.test rename to tests/mag_no_coverage_pe_skip_ena_queries.nf.test index 406fd332..e5fdc09b 100644 --- a/tests/mag_no_coverage_paired_reads.nf.test +++ b/tests/mag_no_coverage_pe_skip_ena_queries.nf.test @@ -1,13 +1,13 @@ nextflow_pipeline { - name "Test genome submission workflow - no_coverage_paired_reads" + name "Test genome submission workflow - no_coverage_paired_reads skip_ena_queries" script "../main.nf" tag "pipeline" tag "mode_mag" - tag "test_mag_no_coverage_paired_reads" - profile "test_mag_no_coverage_paired_reads" + tag "test_mag_no_coverage_pe_skip_ena_queries" + profile "test_mag_no_coverage_pe_skip_ena_queries" - test("-profile test_mag_no_coverage_paired_reads") { + test("-profile test_mag_no_coverage_pe_skip_ena_queries") { when { params { diff --git a/tests/mag_no_coverage_paired_reads.nf.test.snap b/tests/mag_no_coverage_pe_skip_ena_queries.nf.test.snap similarity index 54% rename from tests/mag_no_coverage_paired_reads.nf.test.snap rename to tests/mag_no_coverage_pe_skip_ena_queries.nf.test.snap index a8d4989c..b6138dcb 100644 --- a/tests/mag_no_coverage_paired_reads.nf.test.snap +++ b/tests/mag_no_coverage_pe_skip_ena_queries.nf.test.snap @@ -1,13 +1,8 @@ { - "-profile test_mag_no_coverage_paired_reads": { + "-profile test_mag_no_coverage_pe_skip_ena_queries": { "content": [ - 9, + 5, { - "CONCAT_ACCESSIONS": { - "coreutils": 9.4, - "find": "4.6.0", - "pigz": 2.8 - }, "CONCAT_METADATA": { "coreutils": 9.4, "find": "4.6.0", @@ -19,20 +14,9 @@ "CREATE_GENOME_METADATA_TSV": { "bash": "5.2.37(1)-release" }, - "CREATE_MANIFESTS": { - "genome_uploader": "3.0.4" - }, "FALINT": { "falint": "1.2.0" }, - "REGISTERSTUDY": { - "mgnify-pipelines-toolkit": "1.5.5" - }, - "SUBMIT": { - "ena-webin-cli": "9.0.3", - "mgnify-pipelines-toolkit": "1.5.5", - "python": "3.12.16" - }, "Workflow": { "nf-core/seqsubmit": "v1.0.0" } @@ -42,44 +26,25 @@ "mags/no_coverage_paired_reads", "mags/no_coverage_paired_reads/coverage", "mags/no_coverage_paired_reads/coverage/no_coverage_paired_reads.depth.tsv", - "mags/no_coverage_paired_reads/upload", - "mags/no_coverage_paired_reads/upload/webin_cli", - "mags/no_coverage_paired_reads/upload/webin_cli/no_coverage_paired_reads_accessions.tsv", "mags/upload", - "mags/upload/genomes_accessions.tsv", "mags/upload/genomes_metadata.tsv", - "mags/upload/manifests", - "mags/upload/manifests/results", - "mags/upload/manifests/results/MAG_upload", - "mags/upload/manifests/results/MAG_upload/ENA_backup.json", - "mags/upload/manifests/results/MAG_upload/genome_samples.xml", - "mags/upload/manifests/results/MAG_upload/manifests_test", - "mags/upload/manifests/results/MAG_upload/registered_MAGs_test.tsv", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", "multiqc/multiqc_data/multiqc.log", "multiqc/multiqc_data/multiqc.parquet", - "multiqc/multiqc_data/multiqc_Genomes assigned accessions.txt", "multiqc/multiqc_data/multiqc_citations.txt", "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_genome_metadata.txt", - "multiqc/multiqc_data/multiqc_sample_registration.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/Genomes assigned accessions.pdf", "multiqc/multiqc_plots/pdf/genome_metadata.pdf", - "multiqc/multiqc_plots/pdf/sample_registration.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/Genomes assigned accessions.png", "multiqc/multiqc_plots/png/genome_metadata.png", - "multiqc/multiqc_plots/png/sample_registration.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/Genomes assigned accessions.svg", "multiqc/multiqc_plots/svg/genome_metadata.svg", - "multiqc/multiqc_plots/svg/sample_registration.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml" @@ -91,10 +56,10 @@ "multiqc_genome_metadata.txt:md5,73ca3eaa259e29711518c466246aeed5" ] ], - "timestamp": "2026-10-16T11:28:13.637453", + "timestamp": "2026-10-30T11:24:46.224163", "meta": { "nf-test": "0.9.5", - "nextflow": "26.10.0" + "nextflow": "26.10.4" } } } \ No newline at end of file diff --git a/tests/mag_no_coverage_single_reads.nf.test b/tests/mag_no_coverage_se_skip_ena_queries.nf.test similarity index 88% rename from tests/mag_no_coverage_single_reads.nf.test rename to tests/mag_no_coverage_se_skip_ena_queries.nf.test index 5ec80f3e..72644af3 100644 --- a/tests/mag_no_coverage_single_reads.nf.test +++ b/tests/mag_no_coverage_se_skip_ena_queries.nf.test @@ -1,13 +1,13 @@ nextflow_pipeline { - name "Test genome submission workflow - no_coverage_single_reads" + name "Test genome submission workflow - no_coverage_single_reads skip_ena_queries" script "../main.nf" tag "pipeline" tag "mode_mag" - tag "test_mag_no_coverage_single_reads" - profile "test_mag_no_coverage_single_reads" + tag "test_mag_no_coverage_se_skip_ena_queries" + profile "test_mag_no_coverage_se_skip_ena_queries" - test("-profile test_mag_no_coverage_single_reads") { + test("-profile test_mag_no_coverage_se_skip_ena_queries") { when { params { diff --git a/tests/mag_no_coverage_single_reads.nf.test.snap b/tests/mag_no_coverage_se_skip_ena_queries.nf.test.snap similarity index 54% rename from tests/mag_no_coverage_single_reads.nf.test.snap rename to tests/mag_no_coverage_se_skip_ena_queries.nf.test.snap index f2fa2e8a..0a4c2c87 100644 --- a/tests/mag_no_coverage_single_reads.nf.test.snap +++ b/tests/mag_no_coverage_se_skip_ena_queries.nf.test.snap @@ -1,13 +1,8 @@ { - "-profile test_mag_no_coverage_single_reads": { + "-profile test_mag_no_coverage_se_skip_ena_queries": { "content": [ - 9, + 5, { - "CONCAT_ACCESSIONS": { - "coreutils": 9.4, - "find": "4.6.0", - "pigz": 2.8 - }, "CONCAT_METADATA": { "coreutils": 9.4, "find": "4.6.0", @@ -19,20 +14,9 @@ "CREATE_GENOME_METADATA_TSV": { "bash": "5.2.37(1)-release" }, - "CREATE_MANIFESTS": { - "genome_uploader": "3.0.4" - }, "FALINT": { "falint": "1.2.0" }, - "REGISTERSTUDY": { - "mgnify-pipelines-toolkit": "1.5.5" - }, - "SUBMIT": { - "ena-webin-cli": "9.0.3", - "mgnify-pipelines-toolkit": "1.5.5", - "python": "3.12.16" - }, "Workflow": { "nf-core/seqsubmit": "v1.0.0" } @@ -42,44 +26,25 @@ "mags/no_coverage_single_reads", "mags/no_coverage_single_reads/coverage", "mags/no_coverage_single_reads/coverage/no_coverage_single_reads.depth.tsv", - "mags/no_coverage_single_reads/upload", - "mags/no_coverage_single_reads/upload/webin_cli", - "mags/no_coverage_single_reads/upload/webin_cli/no_coverage_single_reads_accessions.tsv", "mags/upload", - "mags/upload/genomes_accessions.tsv", "mags/upload/genomes_metadata.tsv", - "mags/upload/manifests", - "mags/upload/manifests/results", - "mags/upload/manifests/results/MAG_upload", - "mags/upload/manifests/results/MAG_upload/ENA_backup.json", - "mags/upload/manifests/results/MAG_upload/genome_samples.xml", - "mags/upload/manifests/results/MAG_upload/manifests_test", - "mags/upload/manifests/results/MAG_upload/registered_MAGs_test.tsv", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", "multiqc/multiqc_data/multiqc.log", "multiqc/multiqc_data/multiqc.parquet", - "multiqc/multiqc_data/multiqc_Genomes assigned accessions.txt", "multiqc/multiqc_data/multiqc_citations.txt", "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_genome_metadata.txt", - "multiqc/multiqc_data/multiqc_sample_registration.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/Genomes assigned accessions.pdf", "multiqc/multiqc_plots/pdf/genome_metadata.pdf", - "multiqc/multiqc_plots/pdf/sample_registration.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/Genomes assigned accessions.png", "multiqc/multiqc_plots/png/genome_metadata.png", - "multiqc/multiqc_plots/png/sample_registration.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/Genomes assigned accessions.svg", "multiqc/multiqc_plots/svg/genome_metadata.svg", - "multiqc/multiqc_plots/svg/sample_registration.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml" @@ -91,10 +56,10 @@ "multiqc_genome_metadata.txt:md5,f87520e8673df42da7971d6b4723d020" ] ], - "timestamp": "2026-10-16T11:59:29.524504", + "timestamp": "2026-10-30T11:25:33.120308", "meta": { "nf-test": "0.9.5", - "nextflow": "26.10.0" + "nextflow": "26.10.4" } } } \ No newline at end of file diff --git a/tests/mag_no_quality_euk_skip_ena_queries.nf.test b/tests/mag_no_quality_euk_skip_ena_queries.nf.test new file mode 100644 index 00000000..75ade752 --- /dev/null +++ b/tests/mag_no_quality_euk_skip_ena_queries.nf.test @@ -0,0 +1,57 @@ +nextflow_pipeline { + + name "Test genome submission workflow - no_quality_euk without ENA interaction" + script "../main.nf" + tag "pipeline" + tag "mode_mag" + tag "test_mag_no_quality_euk_skip_ena_queries" + profile "test_mag_no_quality_euk_skip_ena_queries" + + test("-profile test_mag_no_quality_euk_skip_ena_queries") { + + when { + params { + outdir = "$outputDir" + } + } + + then { + // stable_name: All files + folders in ${params.outdir}/ with a stable name + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', '**/manifests_test/*']) + // stable_path: All files in ${params.outdir}/ with stable content + def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + // Early failure no need to test the rest of snapshots + assert workflow.success + // Completeness, contamination and stats software per genome, read from the submission metadata table + def metadata_lines = path("$outputDir/mags/upload/genomes_metadata.tsv").readLines() + def metadata_header = metadata_lines[0].split('\t') as List + def stats = metadata_lines.drop(1) + .findAll { line -> line.trim() } + .collectEntries { line -> + def values = line.split('\t', -1) + [ (values[metadata_header.indexOf('genome_name')]): [ + completeness: values[metadata_header.indexOf('completeness')], + contamination: values[metadata_header.indexOf('contamination')], + software: values[metadata_header.indexOf('stats_generation_software')] + ] ] + } + assertAll( + { assert stats.keySet() == ['no_quality_euk'] as Set }, + // eukaryotic genome - completeness and contamination are calculated by EukCC + { assert stats['no_quality_euk'].software.toLowerCase().startsWith('eukcc') }, + { assert stats['no_quality_euk'].completeness }, + { assert stats['no_quality_euk'].contamination }, + { assert snapshot( + // Number of successful tasks + workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path + ).match() } + ) + } + } +} diff --git a/tests/mag_no_quality_euk_skip_ena_queries.nf.test.snap b/tests/mag_no_quality_euk_skip_ena_queries.nf.test.snap new file mode 100644 index 00000000..d23244ce --- /dev/null +++ b/tests/mag_no_quality_euk_skip_ena_queries.nf.test.snap @@ -0,0 +1,74 @@ +{ + "-profile test_mag_no_quality_euk_skip_ena_queries": { + "content": [ + 7, + { + "CONCAT_METADATA": { + "coreutils": 9.4, + "find": "4.6.0", + "pigz": 2.8 + }, + "CREATE_GENOME_METADATA_TSV": { + "bash": "5.2.37(1)-release" + }, + "DB_UNTAR": { + "untar": 1.34 + }, + "EUKCC_SINGLE": { + "eukcc": "2.2.0", + "metaeuk": "4.a0f584d", + "pplacer": "v1.1.alpha19-0-g807f6f3" + }, + "FALINT": { + "falint": "1.2.0" + }, + "GUNZIP_FASTA": { + "gunzip": 1.13 + }, + "Workflow": { + "nf-core/seqsubmit": "v1.0.0" + } + }, + [ + "mags", + "mags/no_quality_euk", + "mags/no_quality_euk/eukcc", + "mags/no_quality_euk/eukcc/no_quality_euk_eukcc_results", + "mags/no_quality_euk/eukcc/no_quality_euk_eukcc_results/eukcc.tsv", + "mags/upload", + "mags/upload/genomes_metadata.tsv", + "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_genome_metadata.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/genome_metadata.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/genome_metadata.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/genome_metadata.svg", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml" + ], + [ + "eukcc.tsv:md5,f30a5cae1c74b9c5e0e0b1d0f4c3c3f6", + "genomes_metadata.tsv:md5,e3c541346f66663954e19d114dd744c0", + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "multiqc_genome_metadata.txt:md5,22652d4228d3297c03baf7ff1505f8bc" + ] + ], + "timestamp": "2026-10-23T15:01:23.80635663", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.10.3" + } + } +} \ No newline at end of file diff --git a/tests/mag_no_rna_skip_ena_queries.nf.test b/tests/mag_no_rna_skip_ena_queries.nf.test new file mode 100644 index 00000000..7778deb9 --- /dev/null +++ b/tests/mag_no_rna_skip_ena_queries.nf.test @@ -0,0 +1,53 @@ +nextflow_pipeline { + + name "Test genome submission workflow - no_rna_presence without ENA interaction" + script "../main.nf" + tag "pipeline" + tag "mode_mag" + tag "test_mag_no_rna_skip_ena_queries" + profile "test_mag_no_rna_skip_ena_queries" + + test("-profile test_mag_no_rna_skip_ena_queries") { + + when { + params { + outdir = "$outputDir" + } + } + + then { + // stable_name: All files + folders in ${params.outdir}/ with a stable name + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', '**/manifests_test/*']) + // stable_path: All files in ${params.outdir}/ with stable content + def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + // Early failure no need to test the rest of snapshots + assert workflow.success + // Final RNA_presence decision per genome, read from the submission metadata table + def metadata_lines = path("$outputDir/mags/upload/genomes_metadata.tsv").readLines() + def metadata_header = metadata_lines[0].split('\t') as List + def rna_presence = metadata_lines.drop(1) + .findAll { line -> line.trim() } + .collectEntries { line -> + def values = line.split('\t', -1) + [ (values[metadata_header.indexOf('genome_name')]): values[metadata_header.indexOf('rRNA_presence')] ] + } + assertAll( + { assert rna_presence.keySet() == ['no_rna_presence_prok', 'no_rna_presence_euk'] as Set }, + // complete bacterial isolate genome - all rRNA genes and enough tRNAs are expected + { assert rna_presence['no_rna_presence_prok'] == 'True' }, + // small eukaryotic genome fragment - eukaryotic rRNA set is not expected to be complete + { assert rna_presence['no_rna_presence_euk'] == 'False' }, + { assert snapshot( + // Number of successful tasks + workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path + ).match() } + ) + } + } +} diff --git a/tests/mag_no_rna_presence.nf.test.snap b/tests/mag_no_rna_skip_ena_queries.nf.test.snap similarity index 60% rename from tests/mag_no_rna_presence.nf.test.snap rename to tests/mag_no_rna_skip_ena_queries.nf.test.snap index 24b5fb33..c3836415 100644 --- a/tests/mag_no_rna_presence.nf.test.snap +++ b/tests/mag_no_rna_skip_ena_queries.nf.test.snap @@ -1,16 +1,11 @@ { - "-profile test_mag_no_rna_presence": { + "-profile test_mag_no_rna_skip_ena_queries": { "content": [ - 17, + 12, { "BARRNAP": { "barrnap": 0.9 }, - "CONCAT_ACCESSIONS": { - "coreutils": 9.4, - "find": "4.6.0", - "pigz": 2.8 - }, "CONCAT_METADATA": { "coreutils": 9.4, "find": "4.6.0", @@ -22,20 +17,9 @@ "CREATE_GENOME_METADATA_TSV": { "bash": "5.2.37(1)-release" }, - "CREATE_MANIFESTS": { - "genome_uploader": "3.0.4" - }, "FALINT": { "falint": "1.2.0" }, - "REGISTERSTUDY": { - "mgnify-pipelines-toolkit": "1.5.5" - }, - "SUBMIT": { - "ena-webin-cli": "9.0.3", - "mgnify-pipelines-toolkit": "1.5.5", - "python": "3.12.16" - }, "TRNASCANSE": { "tRNAscan-SE": "2.0.12" }, @@ -48,14 +32,11 @@ "mags/no_rna_presence_euk", "mags/no_rna_presence_euk/rna", "mags/no_rna_presence_euk/rna/barrnap", - "mags/no_rna_presence_euk/rna/barrnap/no_rna_presence_euk_bac.gff", + "mags/no_rna_presence_euk/rna/barrnap/no_rna_presence_euk_euk.gff", "mags/no_rna_presence_euk/rna/trnascanse", "mags/no_rna_presence_euk/rna/trnascanse/no_rna_presence_euk.log", "mags/no_rna_presence_euk/rna/trnascanse/no_rna_presence_euk.stats", "mags/no_rna_presence_euk/rna/trnascanse/no_rna_presence_euk.tsv", - "mags/no_rna_presence_euk/upload", - "mags/no_rna_presence_euk/upload/webin_cli", - "mags/no_rna_presence_euk/upload/webin_cli/no_rna_presence_euk_accessions.tsv", "mags/no_rna_presence_prok", "mags/no_rna_presence_prok/rna", "mags/no_rna_presence_prok/rna/barrnap", @@ -64,59 +45,40 @@ "mags/no_rna_presence_prok/rna/trnascanse/no_rna_presence_prok.log", "mags/no_rna_presence_prok/rna/trnascanse/no_rna_presence_prok.stats", "mags/no_rna_presence_prok/rna/trnascanse/no_rna_presence_prok.tsv", - "mags/no_rna_presence_prok/upload", - "mags/no_rna_presence_prok/upload/webin_cli", - "mags/no_rna_presence_prok/upload/webin_cli/no_rna_presence_prok_accessions.tsv", "mags/upload", - "mags/upload/genomes_accessions.tsv", "mags/upload/genomes_metadata.tsv", - "mags/upload/manifests", - "mags/upload/manifests/results", - "mags/upload/manifests/results/MAG_upload", - "mags/upload/manifests/results/MAG_upload/ENA_backup.json", - "mags/upload/manifests/results/MAG_upload/genome_samples.xml", - "mags/upload/manifests/results/MAG_upload/manifests_test", - "mags/upload/manifests/results/MAG_upload/registered_MAGs_test.tsv", "multiqc", "multiqc/multiqc_data", "multiqc/multiqc_data/llms-full.txt", "multiqc/multiqc_data/multiqc.log", "multiqc/multiqc_data/multiqc.parquet", - "multiqc/multiqc_data/multiqc_Genomes assigned accessions.txt", "multiqc/multiqc_data/multiqc_citations.txt", "multiqc/multiqc_data/multiqc_data.json", "multiqc/multiqc_data/multiqc_genome_metadata.txt", - "multiqc/multiqc_data/multiqc_sample_registration.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/Genomes assigned accessions.pdf", "multiqc/multiqc_plots/pdf/genome_metadata.pdf", - "multiqc/multiqc_plots/pdf/sample_registration.pdf", "multiqc/multiqc_plots/png", - "multiqc/multiqc_plots/png/Genomes assigned accessions.png", "multiqc/multiqc_plots/png/genome_metadata.png", - "multiqc/multiqc_plots/png/sample_registration.png", "multiqc/multiqc_plots/svg", - "multiqc/multiqc_plots/svg/Genomes assigned accessions.svg", "multiqc/multiqc_plots/svg/genome_metadata.svg", - "multiqc/multiqc_plots/svg/sample_registration.svg", "multiqc/multiqc_report.html", "pipeline_info", "pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml" ], [ - "no_rna_presence_euk_bac.gff:md5,df19e1b84ba6f691d20c72b397c88abf", + "no_rna_presence_euk_euk.gff:md5,df19e1b84ba6f691d20c72b397c88abf", "no_rna_presence_euk.tsv:md5,68d0b807755e195d09aaa082d59827e7", "no_rna_presence_prok_bac.gff:md5,468c2be7060d743f95295f1ecf751e19", - "no_rna_presence_prok.tsv:md5,23c19ff33ce36f041803b5b3e7b7681b", + "no_rna_presence_prok.tsv:md5,55ef27998a528dd2f97f761becd7e4ea", "genomes_metadata.tsv:md5,2acbde2a328213ee6b5153bffa72d697", "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", "multiqc_genome_metadata.txt:md5,40f68f54d23fdb12371b9b69991101ea" ] ], - "timestamp": "2026-10-26T20:52:59.848025", + "timestamp": "2026-10-22T10:01:43.171583", "meta": { "nf-test": "0.9.5", "nextflow": "26.04.0" diff --git a/tests/mag_no_taxonomy_skip_ena_queries.nf.test b/tests/mag_no_taxonomy_skip_ena_queries.nf.test new file mode 100644 index 00000000..d78cfecf --- /dev/null +++ b/tests/mag_no_taxonomy_skip_ena_queries.nf.test @@ -0,0 +1,39 @@ +nextflow_pipeline { + + name "Test genome submission workflow - no_taxonomy without ENA interaction" + script "../main.nf" + tag "pipeline" + tag "mode_mag" + tag "test_mag_no_taxonomy_skip_ena_queries" + profile "test_mag_no_taxonomy_skip_ena_queries" + + test("-profile test_mag_no_taxonomy_skip_ena_queries") { + + when { + params { + outdir = "$outputDir" + } + } + + then { + // stable_name: All files + folders in ${params.outdir}/ with a stable name + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', '**/manifests_test/*']) + // stable_path: All files in ${params.outdir}/ with stable content + def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + // Early failure no need to test the rest of snapshots + assert workflow.success + assertAll( + { assert snapshot( + // Number of successful tasks + workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path + ).match() } + ) + } + } +} diff --git a/tests/mag_no_taxonomy_skip_ena_queries.nf.test.snap b/tests/mag_no_taxonomy_skip_ena_queries.nf.test.snap new file mode 100644 index 00000000..9cbbf2dd --- /dev/null +++ b/tests/mag_no_taxonomy_skip_ena_queries.nf.test.snap @@ -0,0 +1,76 @@ +{ + "-profile test_mag_no_taxonomy_skip_ena_queries": { + "content": [ + 8, + { + "CATPACK_ADDNAMES_BINS": { + "catpack": 6.0 + }, + "CATPACK_BINS": { + "catpack": 6.0 + }, + "CAT_DB_UNTAR": { + "untar": 1.34 + }, + "CONCAT_METADATA": { + "coreutils": 9.4, + "find": "4.6.0", + "pigz": 2.8 + }, + "CREATE_GENOME_METADATA_TSV": { + "bash": "5.2.37(1)-release" + }, + "FALINT": { + "falint": "1.2.0" + }, + "RENAME_FASTA_FOR_CATPACK": { + "bash": "5.2.37(1)-release" + }, + "Workflow": { + "nf-core/seqsubmit": "v1.0.0" + } + }, + [ + "mags", + "mags/no_taxonomy", + "mags/no_taxonomy/taxonomy", + "mags/no_taxonomy/taxonomy/no_taxonomy.bin2classification.txt", + "mags/no_taxonomy/taxonomy/no_taxonomy.txt", + "mags/upload", + "mags/upload/genomes_metadata.tsv", + "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_genome_metadata.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/genome_metadata.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/genome_metadata.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/genome_metadata.svg", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml" + ], + [ + "no_taxonomy.bin2classification.txt:md5,e24c109efe807c7044a866999fd736f1", + "no_taxonomy.txt:md5,0f2082d3e397fd630d605dd60993b131", + "genomes_metadata.tsv:md5,b1d01539d787b77e30b9bacd5b23d51f", + "multiqc_citations.txt:md5,4c806e63a283ec1b7e78cdae3a923d4f", + "multiqc_genome_metadata.txt:md5,c2bdf8ba36b55b5f48fa07a26e5222f5" + ] + ], + "timestamp": "2026-10-23T14:57:41.967071271", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.10.3" + } + } +} \ No newline at end of file diff --git a/tests/mag_one_contig.nf.test b/tests/mag_one_contig.nf.test deleted file mode 100644 index 1904dff7..00000000 --- a/tests/mag_one_contig.nf.test +++ /dev/null @@ -1,39 +0,0 @@ -nextflow_pipeline { - - name "Test genome submission workflow - one_contig" - script "../main.nf" - tag "pipeline" - tag "mode_mag" - tag "test_mag_one_contig" - profile "test_mag_one_contig" - - test("-profile test_mag_one_contig") { - - when { - params { - outdir = "$outputDir" - } - } - - then { - // stable_name: All files + folders in ${params.outdir}/ with a stable name - def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}', '**/manifests_test/*']) - // stable_path: All files in ${params.outdir}/ with stable content - def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') - // Early failure no need to test the rest of snapshots - assert workflow.success - assertAll( - { assert snapshot( - // Number of successful tasks - workflow.trace.succeeded().size(), - // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions - removeNextflowVersion("$outputDir/pipeline_info/nf_core_seqsubmit_software_mqc_versions.yml"), - // All stable path name, with a relative path - stable_name, - // All files with stable contents - stable_path - ).match() } - ) - } - } -} diff --git a/tests/mag_no_rna_presence.nf.test b/tests/mag_one_contig_skip_ena_queries.nf.test similarity index 85% rename from tests/mag_no_rna_presence.nf.test rename to tests/mag_one_contig_skip_ena_queries.nf.test index 9f4c0051..fe6dcad4 100644 --- a/tests/mag_no_rna_presence.nf.test +++ b/tests/mag_one_contig_skip_ena_queries.nf.test @@ -1,13 +1,13 @@ nextflow_pipeline { - name "Test genome submission workflow - no_rna_presence" + name "Test genome submission workflow - one_contig. No ENA interaction." script "../main.nf" tag "pipeline" tag "mode_mag" - tag "test_mag_no_rna_presence" - profile "test_mag_no_rna_presence" + tag "test_mag_one_contig_skip_ena_queries" + profile "test_mag_one_contig_skip_ena_queries" - test("-profile test_mag_no_rna_presence") { + test("-profile test_mag_one_contig_skip_ena_queries") { when { params { diff --git a/tests/mag_one_contig.nf.test.snap b/tests/mag_one_contig_skip_ena_queries.nf.test.snap similarity index 95% rename from tests/mag_one_contig.nf.test.snap rename to tests/mag_one_contig_skip_ena_queries.nf.test.snap index be530c2e..8cc913f1 100644 --- a/tests/mag_one_contig.nf.test.snap +++ b/tests/mag_one_contig_skip_ena_queries.nf.test.snap @@ -1,5 +1,5 @@ { - "-profile test_mag_one_contig": { + "-profile test_mag_one_contig_skip_ena_queries": { "content": [ 1, { diff --git a/workflows/genomesubmit.nf b/workflows/genomesubmit.nf index 17edbf94..3a3ecc72 100644 --- a/workflows/genomesubmit.nf +++ b/workflows/genomesubmit.nf @@ -16,7 +16,8 @@ include { MULTIQC } from '../modules/nf-core/multi include { paramsSummaryMap } from 'plugin/nf-schema' include { FASTA_VALIDATION } from '../subworkflows/local/fasta_validation/main' -include { GENOME_EVALUATION } from '../subworkflows/local/genome_evaluation/main' +include { EUKARYOTIC_GENOME_EVALUATION } from '../subworkflows/local/eukaryotic_genome_evaluation/main' +include { PROKARYOTIC_GENOME_EVALUATION } from '../subworkflows/local/prokaryotic_genome_evaluation/main' include { RNA_DETECTION } from '../subworkflows/local/rna_detection/main' include { FASTA_CLASSIFY_CATPACK } from '../subworkflows/nf-core/fasta_classify_catpack/main' @@ -33,25 +34,30 @@ include { methodsDescriptionText } from '../subworkflows/local/ut workflow GENOMESUBMIT { take: - ch_samplesheet // channel: samplesheet read in from --input + ch_samplesheet // channel: samplesheet read in from --input multiqc_config multiqc_logo multiqc_methods_description outdir - mags_or_bins_flag // val: submission mode (mags or bins) - submission_study // val: accession of the study to submit to (optional) - study_metadata // val: path to study metadata file for study creation (used if no submission_study provided) - trna_limit // val: tRNA count threshold - rrna_limit // val: rRNA length percentage threshold - checkm2_db // val: path to CheckM2 database - checkm2_db_download_id // val: CheckM2 database download ID - cat_db // val: path to CAT database - centre_name // val: submission centre name - upload_tpa // val: upload as TPA (Third Party Annotation) - test_upload // val: true for test upload mode - webincli_mode // val: either 'validate' or 'submit' to specify WebinCLI mode of operation - is_private // val: fetch metadata from private/public account - release_date // val: keep submitted data private until given date + mags_or_bins_flag // val: submission mode (mags or bins) + submission_study // val: accession of the study to submit to (optional) + study_metadata // val: path to study metadata file for study creation (used if no submission_study provided) + trna_limit // val: tRNA count threshold + rrna_limit // val: rRNA length percentage threshold + checkm2_db // val: path to CheckM2 database + checkm2_db_download_id // val: CheckM2 database download ID + cat_db // val: path to CAT database + centre_name // val: submission centre name + upload_tpa // val: upload as TPA (Third Party Annotation) + test_upload // val: true for test upload mode + webincli_mode // val: either 'validate' or 'submit' to specify WebinCLI mode of operation + is_private // val: fetch metadata from private/public account + release_date // val: keep submitted data private until given date + busco_db_lineage // val: name of the busco supported lineage + busco_db // val: download URL or local tar.gz archive/directory + busco_clean // boolean: clean intermediate busco files + eukaryotic_completeness_tool // val: busco or eukcc + eukcc_db // val: EukCC database - local directory or .tar.gz/.tgz archive (path or URL) main: @@ -110,8 +116,70 @@ workflow GENOMESUBMIT { } .mix(branched_coverage_results.genome_coverage_present) + // --------- Taxonomy + branched_taxonomy_results = fasta_updated_with_coverage + .branch { meta, _fasta -> + taxonomy_absent: !(meta.NCBI_lineage) + taxonomy_present: true // Everything else goes here + } + + // Change extension for all files required taxonomy to .fasta because CATPACK requires suffix as input + RENAME_FASTA_FOR_CATPACK ( + branched_taxonomy_results.taxonomy_absent + ) + + // build input structures for CAT_DB depending on what provided as input + def cat_db_input = cat_db + ? channel.of( [['id': 'CAT_DB'], file(cat_db)] ) + : channel.empty() + + cat_db_download_id = "nr" // NCBI non-redundant protein database identifier + def cat_db_id_input = cat_db + ? channel.empty() + : channel.of( [['id': 'CAT_DB_id'], cat_db_download_id] ) + + FASTA_CLASSIFY_CATPACK ( + RENAME_FASTA_FOR_CATPACK.out.renamed_fasta, // ch_bins + channel.empty(), // ch_contigs - empty because we classify bins, not contigs + cat_db_input, + cat_db_id_input, + false, // disable summary generation + '.fasta' // bin_suffix - the suffix of the renamed fasta files + ) + + fasta_updated_with_taxonomy = FASTA_CLASSIFY_CATPACK.out.bat_classification + .join(branched_taxonomy_results.taxonomy_absent) + .map { meta, taxa_tsv, fasta -> + def lines = taxa_tsv.readLines() + def updated_meta = meta.clone() + // support for empty taxonomy files required for -stub mode + // skip header and take 4th column from table corresponding to lineage + updated_meta.NCBI_lineage = lines ? lines[1].split('\t')[3] : null + return [updated_meta, fasta] + } + .mix(branched_taxonomy_results.taxonomy_present) + + // --------- Add meta.domain value for eukaryotes (euk) and prokaryotes (bac and arc) + domain_identification = fasta_updated_with_taxonomy + .map { meta, fasta -> + def lineage = meta.NCBI_lineage.toLowerCase() + def parts = lineage.tokenize(';').collect { p -> p.trim() } + def is_euk = lineage.contains('eukaryot') || parts.contains('2759') + def is_arc = lineage.contains('archaea') || parts.contains('2157') + def is_bac = lineage.contains('bacteria') || parts.contains('2') + + if (!is_euk && !is_arc && !is_bac) { + throw new IllegalStateException( + "Unassigned or unrecognized taxonomic lineage for ${meta.id}: '${meta.NCBI_lineage}. \ + Provide NCBI format taxonomy or remove it from MAG/bin submission'" + ) + } + + [ meta + [domain: is_euk ? 'euk' : (is_arc ? 'arc' : 'bac')], fasta ] + } + // --------- For genomes without RNA_presence info, calculate rRNA and tRNA - branched_rna_results = fasta_updated_with_coverage + branched_rna_results = domain_identification .branch { meta, _fasta -> rna_prediction_input: meta.RNA_presence == null // it might be True/False rna_present: true // Everything else goes here @@ -142,76 +210,47 @@ workflow GENOMESUBMIT { evaluation_present: true // Everything else goes here } - GENOME_EVALUATION ( - branched_stats_results.genome_evaluation_input, + // Split genomes to evaluate into prokaryotes and eukaryotes + domain_split_stats = branched_stats_results.genome_evaluation_input + .branch { meta, _fasta -> + prokaryotes: meta.domain in ['arc', 'bac'] + eukaryotes: meta.domain == 'euk' + } + + PROKARYOTIC_GENOME_EVALUATION ( + domain_split_stats.prokaryotes, checkm2_db, checkm2_db_download_id ) - // Create a value channel with the version string - def stats_version_ch = GENOME_EVALUATION.out.stats_versions - .map { _process_name, tool_name, version_output -> return "${tool_name}_v${version_output}" - }.first() + EUKARYOTIC_GENOME_EVALUATION ( + domain_split_stats.eukaryotes, + busco_db_lineage, + busco_db, + busco_clean, + eukaryotic_completeness_tool, + eukcc_db + ) - fasta_updated_with_stats = GENOME_EVALUATION.out.genome_evaluation + // Update metadata with completeness and contamination from CheckM2 (prokaryotes) or EukCC/BUSCO (eukaryotes) + // Eukaryotic genomes without completeness or contamination are filtered out in EUKARYOTIC_GENOME_EVALUATION + fasta_updated_with_stats = PROKARYOTIC_GENOME_EVALUATION.out.stats + .mix(EUKARYOTIC_GENOME_EVALUATION.out.stats) .join(branched_stats_results.genome_evaluation_input) - .combine(stats_version_ch) - .map { meta, stats_tsv, fasta, stats_version -> - def lines = stats_tsv.readLines() - // support for empty checkm files required for -stub mode - def updated_meta = meta.clone() - updated_meta.completeness = lines ? lines[1].split('\t')[1] : null - updated_meta.contamination = lines ? lines[1].split('\t')[2] : null - updated_meta.stats_generation_software = stats_version + .map { meta, completeness, contamination, stats_software, fasta -> + def updated_meta = meta + [ + completeness: completeness, + contamination: contamination, + stats_generation_software: stats_software + ] return [updated_meta, fasta] } .mix(branched_stats_results.evaluation_present) - // --------- Taxonomy - branched_taxonomy_results = fasta_updated_with_stats - .branch { meta, _fasta -> - genome_taxonomy_input: !(meta.NCBI_lineage) - taxonomy_present: true // Everything else goes here - } - - // Change extension for all files required taxonomy to .fasta because CATPACK requires suffix as input - RENAME_FASTA_FOR_CATPACK ( - branched_taxonomy_results.genome_taxonomy_input - ) - - // build input structures for CAT_DB depending on what provided as input - def cat_db_input = cat_db - ? channel.of( [['id': 'CAT_DB'], file(cat_db)] ) - : channel.empty() - - cat_db_download_id = "nr" // NCBI non-redundant protein database identifier - def cat_db_id_input = cat_db - ? channel.empty() - : channel.of( [['id': 'CAT_DB_id'], cat_db_download_id] ) - - FASTA_CLASSIFY_CATPACK ( - RENAME_FASTA_FOR_CATPACK.out.renamed_fasta, // ch_bins - channel.empty(), // ch_contigs - empty because we classify bins, not contigs - cat_db_input, - cat_db_id_input, - false, // disable summary generation - '.fasta' // bin_suffix - the suffix of the renamed fasta files - ) - - fasta_updated_with_taxonomy = FASTA_CLASSIFY_CATPACK.out.bat_classification - .join(branched_taxonomy_results.genome_taxonomy_input) - .map { meta, taxa_tsv, fasta -> - def lines = taxa_tsv.readLines() - def updated_meta = meta.clone() - // support for empty taxonomy files required for -stub mode - updated_meta.NCBI_lineage = lines ? lines[1].split('\t')[3] : null - return [updated_meta, fasta] - } - .mix(branched_taxonomy_results.taxonomy_present) // --------- Combine metadata into TSV using module CREATE_GENOME_METADATA_TSV ( - fasta_updated_with_taxonomy + fasta_updated_with_stats ) // Collect all TSV rows into a single file @@ -241,7 +280,7 @@ workflow GENOMESUBMIT { // --------- Generate manifests CREATE_MANIFESTS( - fasta_updated_with_taxonomy.map{_meta, fasta -> fasta}.collect(), + fasta_updated_with_stats.map{_meta, fasta -> fasta}.collect(), CONCAT_METADATA.out.file_out.map { _meta, file -> file }.first(), mags_or_bins_flag, // mags or bins study_accession_ch.first(), @@ -262,7 +301,7 @@ workflow GENOMESUBMIT { [ meta, manifest ] } // Combine fasta and manifests - ch_combined = fasta_updated_with_taxonomy + ch_combined = fasta_updated_with_stats .map { meta, fasta -> [meta.id, meta, fasta] } .join( manifests_ch.map { meta, manifest -> [meta.id, manifest] } // Has only [id: prefix]