From 7c857597390956beed2d323d9d74d13285ed3d32 Mon Sep 17 00:00:00 2001 From: falmeida Date: Fri, 19 May 2023 12:20:34 -0300 Subject: [PATCH 01/26] add module to download sourmash databases --- modules/bacannot_dbs/sourmash.nf | 15 ++++++++++++++ workflows/bacannot_dbs.nf | 34 +++++++++++++++++--------------- 2 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 modules/bacannot_dbs/sourmash.nf diff --git a/modules/bacannot_dbs/sourmash.nf b/modules/bacannot_dbs/sourmash.nf new file mode 100644 index 0000000..150e323 --- /dev/null +++ b/modules/bacannot_dbs/sourmash.nf @@ -0,0 +1,15 @@ +process SOURMASH_DB { + publishDir "${params.output}/sourmash_db", mode: 'copy', overwrite: "$params.force_update" + label = [ 'process_ultralow', 'db_download' ] + + output: + path "genbank-{21,31,51}.lca.json.gz" + + script: + """ + # download sourmash database + curl -L -o genbank-21.lca.json.gz https://osf.io/gk2za/download + curl -L -o genbank-31.lca.json.gz https://osf.io/ypsjq/download + curl -L -o genbank-51.lca.json.gz https://osf.io/297dp/download + """ +} diff --git a/workflows/bacannot_dbs.nf b/workflows/bacannot_dbs.nf index ca6c76e..76d9522 100644 --- a/workflows/bacannot_dbs.nf +++ b/workflows/bacannot_dbs.nf @@ -1,22 +1,23 @@ /* * Include modules */ -include { PROKKA_DB } from '../modules/bacannot_dbs/prokka.nf' -include { MLST_DB } from '../modules/bacannot_dbs/mlst.nf' -include { CARD_DB } from '../modules/bacannot_dbs/card.nf' -include { PLATON_DB } from '../modules/bacannot_dbs/platon.nf' -include { RESFINDER_DB } from '../modules/bacannot_dbs/resfinder.nf' -include { PLASMIDFINDER_DB } from '../modules/bacannot_dbs/plasmidfinder.nf' -include { PHIGARO_DB } from '../modules/bacannot_dbs/phigaro.nf' -include { AMRFINDER_DB } from '../modules/bacannot_dbs/amrfinder.nf' -include { ARGMINER_DB } from '../modules/bacannot_dbs/argminer.nf' -include { VFDB_DB } from '../modules/bacannot_dbs/vfdb.nf' -include { VICTORS_DB } from '../modules/bacannot_dbs/victors.nf' -include { ICEBERG_DB } from '../modules/bacannot_dbs/iceberg.nf' -include { PHAST_DB } from '../modules/bacannot_dbs/phast.nf' -include { KOFAMSCAN_DB } from '../modules/bacannot_dbs/kofamscan.nf' -include { ANTISMASH_DB } from '../modules/bacannot_dbs/antismash.nf' -include { GET_ZENODO_DB } from '../modules/bacannot_dbs/get_zenodo.nf' +include { PROKKA_DB } from '../modules/bacannot_dbs/prokka' +include { MLST_DB } from '../modules/bacannot_dbs/mlst' +include { CARD_DB } from '../modules/bacannot_dbs/card' +include { PLATON_DB } from '../modules/bacannot_dbs/platon' +include { RESFINDER_DB } from '../modules/bacannot_dbs/resfinder' +include { PLASMIDFINDER_DB } from '../modules/bacannot_dbs/plasmidfinder' +include { PHIGARO_DB } from '../modules/bacannot_dbs/phigaro' +include { AMRFINDER_DB } from '../modules/bacannot_dbs/amrfinder' +include { ARGMINER_DB } from '../modules/bacannot_dbs/argminer' +include { VFDB_DB } from '../modules/bacannot_dbs/vfdb' +include { VICTORS_DB } from '../modules/bacannot_dbs/victors' +include { ICEBERG_DB } from '../modules/bacannot_dbs/iceberg' +include { PHAST_DB } from '../modules/bacannot_dbs/phast' +include { KOFAMSCAN_DB } from '../modules/bacannot_dbs/kofamscan' +include { ANTISMASH_DB } from '../modules/bacannot_dbs/antismash' +include { GET_ZENODO_DB } from '../modules/bacannot_dbs/get_zenodo' +include { SOURMASH_DB } from '../modules/bacannot_dbs/sourmash' /* DEF WORKFLOW @@ -40,6 +41,7 @@ workflow CREATE_DBS { download_db("victors", "VICTORS_DB") download_db("iceberg", "ICEBERG_DB") download_db("antismash", "ANTISMASH_DB") + download_db("sourmash", "SOURMASH_DB") } else if ( !params.get_dbs && params.get_zenodo_db ) { GET_ZENODO_DB() } From 1ab71c33ef7eedc0724a668d866c819aa1c2a518 Mon Sep 17 00:00:00 2001 From: falmeida Date: Fri, 19 May 2023 12:36:48 -0300 Subject: [PATCH 02/26] add container for sourmash_lca --- conf/docker.config | 4 ++++ conf/singularity.config | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/conf/docker.config b/conf/docker.config index 562b215..23a03c7 100644 --- a/conf/docker.config +++ b/conf/docker.config @@ -106,5 +106,9 @@ process { container = "quay.io/biocontainers/rgi:5.2.1--pyhdfd78af_1" } + withName: SOURMASH_LCA { + container = "quay.io/biocontainers/sourmash:4.8.2--hdfd78af_0" + } + } diff --git a/conf/singularity.config b/conf/singularity.config index 35707df..eecb691 100644 --- a/conf/singularity.config +++ b/conf/singularity.config @@ -107,5 +107,9 @@ process { container = "https://depot.galaxyproject.org/singularity/rgi:5.2.1--pyhdfd78af_1" } + withName: SOURMASH_LCA { + container = "https://depot.galaxyproject.org/singularity/sourmash:4.8.2--hdfd78af_0" + } + } From 9390ce0156cccc9c3dbdff84bc7713ea5c9dc71e Mon Sep 17 00:00:00 2001 From: falmeida Date: Fri, 19 May 2023 12:36:59 -0300 Subject: [PATCH 03/26] add params for sourmash_lca --- conf/defaults.config | 11 +++++++++++ nextflow_schema.json | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/conf/defaults.config b/conf/defaults.config index 63da85b..24bebc7 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -169,6 +169,17 @@ params { // User's custom database coverage threshold blast_custom_mincov = 65 + /* + * Sourmash configuration + */ +// kmer size (21, 31 or 51) +sourmash_kmer = 31 + +// scale, e.g. a scale 1000 on a 5Mb genome will generate 5000 hashes +// 1000 is generally recommended by the tool's developers +sourmash_scale = 1000 + + /* * Resources allocation configuration * Defaults only, expecting to be overwritten diff --git a/nextflow_schema.json b/nextflow_schema.json index ede2129..287901c 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -112,6 +112,27 @@ }, "fa_icon": "fas fa-cog" }, + "sourmash_optional_parameters": { + "title": "Sourmash optional parameters", + "type": "object", + "description": "Set parameters for sourmash analysis", + "default": "", + "properties": { + "sourmash_kmer": { + "type": "integer", + "default": 31, + "help_text": "Select which kmer size to run sourmash with. Options are: 21, 31 and 51.\nThe bigger the value, the more stringent the results are.", + "enum": [21, 31, 51], + "description": "Kmer size to run sourmash analysis" + }, + "sourmash_scale": { + "type": "integer", + "default": 1000, + "description": "Scale to run sourmash analysis", + "help_text": "The scale define the size of the generated hashes. For example, scale=1000 in a 5MB genome will generate 5000 hashes. 1000 as scale is generally recommended by the tool's developers." + } + } + }, "select_unselect_tasks_to_be_run": { "title": "Select/unselect tasks to be run", "type": "object", @@ -321,7 +342,7 @@ "tracedir": { "type": "string", "description": "Directory to keep pipeline Nextflow logs and reports.", - "default": "${params.output}/pipeline_info", + "default": "results/pipeline_info", "fa_icon": "fas fa-cogs", "hidden": true }, @@ -342,17 +363,23 @@ "unicycler_version": { "type": "string", "description": "Select quay.io image tag for tool", - "default": "0.4.8--py38h8162308_3" + "default": "0.4.8--py38h8162308_3", + "hidden": true, + "help_text": "Select a different version of tool based on the bioconda containers tag." }, "flye_version": { "type": "string", "description": "Select quay.io image tag for tool", - "default": "2.9--py39h6935b12_1" + "default": "2.9--py39h6935b12_1", + "hidden": true, + "help_text": "Select a different version of tool based on the bioconda containers tag." }, "bakta_version": { "type": "string", "description": "Select quay.io image tag for tool", - "default": "1.7.0--pyhdfd78af_1" + "default": "1.7.0--pyhdfd78af_1", + "hidden": true, + "help_text": "Select a different version of tool based on the bioconda containers tag." } } }, @@ -421,6 +448,9 @@ { "$ref": "#/definitions/resfinder_optional_process" }, + { + "$ref": "#/definitions/sourmash_optional_parameters" + }, { "$ref": "#/definitions/select_unselect_tasks_to_be_run" }, From 30cb9b284184ea0aacfa96a30995bca11beb2486 Mon Sep 17 00:00:00 2001 From: falmeida Date: Fri, 19 May 2023 12:41:45 -0300 Subject: [PATCH 04/26] add param to skip sourmash --- conf/defaults.config | 7 +++-- modules/generic/sourmash_lca.nf | 46 +++++++++++++++++++++++++++++++++ workflows/bacannot.nf | 7 +++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 modules/generic/sourmash_lca.nf diff --git a/conf/defaults.config b/conf/defaults.config index 24bebc7..652dd80 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -119,6 +119,9 @@ params { // (NOT RUN?) antiSMASH (secondary metabolite) annotation skip_antismash = false +// (NOT RUN?) sourmash + skip_sourmash = false + /* * Custom databases can be used to annotate additional genes in the genome. * It runs a BLAST alignment against the genome, therefore, the custom database @@ -173,11 +176,11 @@ params { * Sourmash configuration */ // kmer size (21, 31 or 51) -sourmash_kmer = 31 + sourmash_kmer = 31 // scale, e.g. a scale 1000 on a 5Mb genome will generate 5000 hashes // 1000 is generally recommended by the tool's developers -sourmash_scale = 1000 + sourmash_scale = 1000 /* diff --git a/modules/generic/sourmash_lca.nf b/modules/generic/sourmash_lca.nf new file mode 100644 index 0000000..5ff3bac --- /dev/null +++ b/modules/generic/sourmash_lca.nf @@ -0,0 +1,46 @@ +process SOURMASH_LCA { + publishDir "${params.output}/${prefix}", mode: 'copy', saveAs: { filename -> + if (filename.indexOf("_version.txt") > 0) "tools_versioning/$filename" + else "sourmash/$filename" + } + tag "${prefix}" + label = [ 'process_low' ] + + input: + path bacannot_dbs + tuple val(prefix), path(genome) + val scale + val kmer + + output: + path "*" + path "sourmash_version.txt" + + when: !params.skip_sourmash + + script: + def lca_db = "${bacannot_dbs}/sourmash_db/genbank-k${kmer}.lca.json.gz" + """ + # get version file + sourmash --version > sourmash_version.txt + + # sketch input genome + sourmash \\ + sketch dna \\ + -p scaled=${scale},k=${kmer} \\ + --name-from-first \\ + ${genome} + + # classify + sourmash \\ + lca classify \\ + --db ${lca_db} \\ + --query ${genome}.sig + + # summarize + sourmash \\ + lca summarize \\ + --db ${lca_db} \\ + --query some-genome.fa.gz.sig > ${genome}_sourmash.summary.txt + """ +} diff --git a/workflows/bacannot.nf b/workflows/bacannot.nf index 93087ad..f0b946b 100644 --- a/workflows/bacannot.nf +++ b/workflows/bacannot.nf @@ -5,6 +5,7 @@ include { UNICYCLER } from '../modules/assembly/unicycler' include { FLYE } from '../modules/assembly/flye' include { REFSEQ_MASHER } from '../modules/generic/mash' +include { SOURMASH_LCA } from '../modules/generic/sourmash_lca' include { PROKKA } from '../modules/generic/prokka' include { BAKTA } from '../modules/generic/bakta' include { MLST } from '../modules/generic/mlst' @@ -250,6 +251,12 @@ workflow BACANNOT { // species identification REFSEQ_MASHER( annotation_out_ch.genome ) + SOURMASH_LCA ( + dbs_ch, + annotation_out_ch.genome, + params.sourmash_scale, + params.sourmash_kmer + ) // IS identification DIGIS( annotation_out_ch.genome.join(annotation_out_ch.gbk) ) From c16c689f19552a3ab8cb06ddf1f848d9877899b7 Mon Sep 17 00:00:00 2001 From: falmeida Date: Fri, 19 May 2023 12:58:39 -0300 Subject: [PATCH 05/26] 1st version of working module --- modules/generic/sourmash_lca.nf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/generic/sourmash_lca.nf b/modules/generic/sourmash_lca.nf index 5ff3bac..8b6f8f8 100644 --- a/modules/generic/sourmash_lca.nf +++ b/modules/generic/sourmash_lca.nf @@ -19,7 +19,7 @@ process SOURMASH_LCA { when: !params.skip_sourmash script: - def lca_db = "${bacannot_dbs}/sourmash_db/genbank-k${kmer}.lca.json.gz" + def lca_db = "${bacannot_dbs}/sourmash_db/genbank-${kmer}.lca.json.gz" """ # get version file sourmash --version > sourmash_version.txt @@ -41,6 +41,6 @@ process SOURMASH_LCA { sourmash \\ lca summarize \\ --db ${lca_db} \\ - --query some-genome.fa.gz.sig > ${genome}_sourmash.summary.txt + --query ${genome}.sig > ${genome}_sourmash.summary.txt """ } From de22ac9978deafaf87dfa9fb3ee6362e1cb2837b Mon Sep 17 00:00:00 2001 From: falmeida Date: Tue, 30 May 2023 05:30:48 -0300 Subject: [PATCH 06/26] update docker image --- conf/defaults.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/defaults.config b/conf/defaults.config index 652dd80..0bdf205 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -190,7 +190,7 @@ params { // Select versions of bioconda quay.io additional tools // Tools that are not part of the core of the pipeline, // but can eventually be used by users - unicycler_version = '0.4.8--py38h8162308_3' + unicycler_version = '0.5.0--py310h6cc9453_3' flye_version = '2.9--py39h6935b12_1' bakta_version = '1.7.0--pyhdfd78af_1' From f8e388cf3e9d5aa5335d6d099fd48da04155dfaf Mon Sep 17 00:00:00 2001 From: falmeida Date: Wed, 31 May 2023 04:44:05 -0300 Subject: [PATCH 07/26] install unzip in docker image --- docker/misc/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker/misc/Dockerfile b/docker/misc/Dockerfile index 7e718db..89002fa 100644 --- a/docker/misc/Dockerfile +++ b/docker/misc/Dockerfile @@ -90,6 +90,9 @@ RUN python3 -m pip install cryptography==38.0.4 # install get zenodo RUN pip3 install zenodo_get +# install unzip +RUN apt-get install -y unzip + # fix permissions RUN chmod 777 -R /work RUN chmod 777 -R /opt/conda/envs/antismash/lib/*/site-packages/antismash From 8d6cd74d6b2b4c4aa87233faa245365246b14c22 Mon Sep 17 00:00:00 2001 From: falmeida Date: Wed, 31 May 2023 05:08:33 -0300 Subject: [PATCH 08/26] fix indentation --- modules/generic/mash.nf | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/modules/generic/mash.nf b/modules/generic/mash.nf index b2ca896..05b47fd 100644 --- a/modules/generic/mash.nf +++ b/modules/generic/mash.nf @@ -1,28 +1,28 @@ process REFSEQ_MASHER { - publishDir "${params.output}/${prefix}", mode: 'copy', saveAs: { filename -> - if (filename.indexOf("_version.txt") > 0) "tools_versioning/$filename" - else "refseq_masher/$filename" - } - tag "${prefix}" - label = [ 'process_low' ] + publishDir "${params.output}/${prefix}", mode: 'copy', saveAs: { filename -> + if (filename.indexOf("_version.txt") > 0) "tools_versioning/$filename" + else "refseq_masher/$filename" + } + tag "${prefix}" + label = [ 'process_low' ] - input: - tuple val(prefix), path(genome) + input: + tuple val(prefix), path(genome) - output: - tuple val(prefix), path("refseq_masher_results.txt"), emit: results - path("*_version.txt") , emit: version + output: + tuple val(prefix), path("refseq_masher_results.txt"), emit: results + path("*_version.txt") , emit: version - script: - """ - # Get tool version - refseq_masher --version > refseq_masher_version.txt ; + script: + """ + # Get tool version + refseq_masher --version > refseq_masher_version.txt ; - # Run tool - refseq_masher \\ - -vv matches \\ - --top-n-results 10 \\ - --output-type tab \\ - $genome > refseq_masher_results.txt - """ + # Run tool + refseq_masher \\ + -vv matches \\ + --top-n-results 10 \\ + --output-type tab \\ + $genome > refseq_masher_results.txt + """ } From 9f61529bdefd6a093ab428bc88fdb071a1122980 Mon Sep 17 00:00:00 2001 From: falmeida Date: Wed, 31 May 2023 05:08:50 -0300 Subject: [PATCH 09/26] include moduel to download closest genoms --- modules/generic/ncbi_genome.nf | 28 ++++++++++++++++++++++++++++ workflows/bacannot.nf | 12 ++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 modules/generic/ncbi_genome.nf diff --git a/modules/generic/ncbi_genome.nf b/modules/generic/ncbi_genome.nf new file mode 100644 index 0000000..691a123 --- /dev/null +++ b/modules/generic/ncbi_genome.nf @@ -0,0 +1,28 @@ +process GET_NCBI_GENOME { + publishDir "${params.output}/closest_genomes", mode: 'copy' + label = [ 'misc', 'process_low' ] + + input: + file(ncbi_accs) + + output: + path("*.fna"), emit: genomes + + when: !params.skip_sourmash + + script: + """ + # download and format ncbi protein entries for custom blastp + for biosample in \$(cat ${ncbi_accs}) ; do \\ + + acc=\$(esearch -db biosample -query \${biosample} | elink -target assembly | esummary | xtract -pattern DocumentSummary -element Genbank | tr -d '\\n' | tr -d '') && \\ + curl -OJX GET \\ + "https://api.ncbi.nlm.nih.gov/datasets/v2alpha/genome/accession/\${acc}/download?include_annotation_type=GENOME_FASTA&filename=\${acc}.zip" \\ + -H "Accept: application/zip" && \\ + unzip \${acc}.zip && \\ + mv ncbi_dataset/data/*/*.fna . && \\ + rm -rf ncbi_dataset *.zip ; + + done + """ +} diff --git a/workflows/bacannot.nf b/workflows/bacannot.nf index f0b946b..0e858fd 100644 --- a/workflows/bacannot.nf +++ b/workflows/bacannot.nf @@ -35,6 +35,7 @@ include { CALL_METHYLATION } from '../modules/generic/methylation' include { CUSTOM_DATABASE } from '../modules/generic/custom_database' include { CUSTOM_DATABASE_REPORT } from '../modules/generic/custom_database_report' include { GET_NCBI_PROTEIN } from '../modules/generic/ncbi_protein' +include { GET_NCBI_GENOME } from '../modules/generic/ncbi_genome' include { MERGE_ANNOTATIONS } from '../modules/generic/merge_annotations' include { GFF2GBK } from '../modules/generic/gff2gbk' include { CREATE_SQL } from '../modules/generic/gff2sql' @@ -258,6 +259,17 @@ workflow BACANNOT { params.sourmash_kmer ) + // mashing against samples and close related genomes + GET_NCBI_GENOME( + REFSEQ_MASHER.out.results + .map { it[1] } + .splitCsv( sep: '\t', header: true ) + .map{ "${it.biosample}\n" } + .unique() + .collectFile() + ) + // annotation_out_ch.genome.collect() + // IS identification DIGIS( annotation_out_ch.genome.join(annotation_out_ch.gbk) ) From faac1b6d8f35d42b036940cf664887e0d2712a01 Mon Sep 17 00:00:00 2001 From: falmeida Date: Wed, 31 May 2023 06:28:36 -0300 Subject: [PATCH 10/26] fixed ncbi genome download --- modules/generic/ncbi_genome.nf | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/modules/generic/ncbi_genome.nf b/modules/generic/ncbi_genome.nf index 691a123..bc344a9 100644 --- a/modules/generic/ncbi_genome.nf +++ b/modules/generic/ncbi_genome.nf @@ -12,17 +12,23 @@ process GET_NCBI_GENOME { script: """ - # download and format ncbi protein entries for custom blastp - for biosample in \$(cat ${ncbi_accs}) ; do \\ + # download genomes from ncbi + for biosample in \$( cat ${ncbi_accs} | sort -u ) ; do - acc=\$(esearch -db biosample -query \${biosample} | elink -target assembly | esummary | xtract -pattern DocumentSummary -element Genbank | tr -d '\\n' | tr -d '') && \\ + export acc=\$(esearch -db biosample -query \${biosample} | elink -target assembly | esummary | xtract -pattern DocumentSummary -element Genbank | tr -d '\\n' | tr -d '') + echo \${biosample} -- \${acc} curl -OJX GET \\ "https://api.ncbi.nlm.nih.gov/datasets/v2alpha/genome/accession/\${acc}/download?include_annotation_type=GENOME_FASTA&filename=\${acc}.zip" \\ - -H "Accept: application/zip" && \\ - unzip \${acc}.zip && \\ - mv ncbi_dataset/data/*/*.fna . && \\ - rm -rf ncbi_dataset *.zip ; + -H "Accept: application/zip" + + done + # unzip files + for file in *.zip ; do + rm -rf ncbi_dataset *.md *.txt && \\ + unzip -u \$file && \\ + mv ncbi_dataset/data/*/*.fna . && \\ + rm -rf ncbi_dataset *.md *.txt done """ } From 88e0e060926149a26218b53ef5276b7c0308c48e Mon Sep 17 00:00:00 2001 From: falmeida Date: Wed, 31 May 2023 07:04:14 -0300 Subject: [PATCH 11/26] add module to compute sourmash between samples and closest genomes --- conf/docker.config | 2 +- conf/singularity.config | 2 +- modules/generic/ncbi_genome.nf | 2 +- modules/generic/sourmash_all.nf | 48 +++++++++++++++++++++++++++++++++ workflows/bacannot.nf | 10 ++++++- 5 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 modules/generic/sourmash_all.nf diff --git a/conf/docker.config b/conf/docker.config index 23a03c7..7c376d5 100644 --- a/conf/docker.config +++ b/conf/docker.config @@ -106,7 +106,7 @@ process { container = "quay.io/biocontainers/rgi:5.2.1--pyhdfd78af_1" } - withName: SOURMASH_LCA { + withName: 'SOURMASH_LCA|SOURMASH_ALL' { container = "quay.io/biocontainers/sourmash:4.8.2--hdfd78af_0" } diff --git a/conf/singularity.config b/conf/singularity.config index eecb691..c0dc40f 100644 --- a/conf/singularity.config +++ b/conf/singularity.config @@ -107,7 +107,7 @@ process { container = "https://depot.galaxyproject.org/singularity/rgi:5.2.1--pyhdfd78af_1" } - withName: SOURMASH_LCA { + withName: 'SOURMASH_LCA|SOURMASH_ALL' { container = "https://depot.galaxyproject.org/singularity/sourmash:4.8.2--hdfd78af_0" } diff --git a/modules/generic/ncbi_genome.nf b/modules/generic/ncbi_genome.nf index bc344a9..c01f7e2 100644 --- a/modules/generic/ncbi_genome.nf +++ b/modules/generic/ncbi_genome.nf @@ -1,5 +1,5 @@ process GET_NCBI_GENOME { - publishDir "${params.output}/closest_genomes", mode: 'copy' + publishDir "${params.output}/sourmash_all/closest_genomes", mode: 'copy' label = [ 'misc', 'process_low' ] input: diff --git a/modules/generic/sourmash_all.nf b/modules/generic/sourmash_all.nf new file mode 100644 index 0000000..a5dcf0b --- /dev/null +++ b/modules/generic/sourmash_all.nf @@ -0,0 +1,48 @@ +process SOURMASH_ALL { + publishDir "${params.output}/sourmash_all", mode: 'copy', saveAs: { filename -> + if (filename.indexOf("_version.txt") > 0) "tools_versioning/$filename" + else "$filename" + } + label = [ 'process_medium' ] + + input: + path( "genomes/*" ) + val scale + val kmer + + output: + path "*" + path "sourmash_version.txt" + + when: !params.skip_sourmash + + script: + """ + # get version file + sourmash --version > sourmash_version.txt + + # sketch input genomes + mkdir signatures ; + for genome in genomes/* ; do + export name=\$( echo \${genome} | cut -f 2 -d '/' | cut -f 1,2 -d '_' ) ; + sourmash \\ + sketch dna \\ + -p scaled=${scale},k=${kmer} \\ + \${genome} \\ + -o signatures/\${name}.sig ; + done + + # compare + sourmash \\ + compare \\ + signatures/* \\ + -p $task.cpus \\ + -o sourmash_cmp + + # plot + sourmash \\ + plot \\ + --pdf \\ + --labels sourmash_cmp + """ +} diff --git a/workflows/bacannot.nf b/workflows/bacannot.nf index 0e858fd..ffeac37 100644 --- a/workflows/bacannot.nf +++ b/workflows/bacannot.nf @@ -6,6 +6,7 @@ include { UNICYCLER } from '../modules/assembly/unicycler' include { FLYE } from '../modules/assembly/flye' include { REFSEQ_MASHER } from '../modules/generic/mash' include { SOURMASH_LCA } from '../modules/generic/sourmash_lca' +include { SOURMASH_ALL } from '../modules/generic/sourmash_all' include { PROKKA } from '../modules/generic/prokka' include { BAKTA } from '../modules/generic/bakta' include { MLST } from '../modules/generic/mlst' @@ -268,7 +269,14 @@ workflow BACANNOT { .unique() .collectFile() ) - // annotation_out_ch.genome.collect() + SOURMASH_ALL( + annotation_out_ch.genome + .map{ it[1] } + .mix( GET_NCBI_GENOME.out.genomes ) + .collect(), + params.sourmash_scale, + params.sourmash_kmer + ) // IS identification DIGIS( annotation_out_ch.genome.join(annotation_out_ch.gbk) ) From 887f3a39a93dc4fa023b76a2d2d737afe27e5537 Mon Sep 17 00:00:00 2001 From: fmalmeida Date: Sun, 4 Jun 2023 21:00:19 +0200 Subject: [PATCH 12/26] update genome download and labels for sourmash --- modules/generic/ncbi_genome.nf | 6 ++++++ modules/generic/sourmash_all.nf | 21 +++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/modules/generic/ncbi_genome.nf b/modules/generic/ncbi_genome.nf index c01f7e2..12721b5 100644 --- a/modules/generic/ncbi_genome.nf +++ b/modules/generic/ncbi_genome.nf @@ -30,5 +30,11 @@ process GET_NCBI_GENOME { mv ncbi_dataset/data/*/*.fna . && \\ rm -rf ncbi_dataset *.md *.txt done + + # rename + for file in *.fna ; do + name=\$( echo \$file | cut -d '_' -f 1,2 ) ; + mv \$file \${name}.fna + done """ } diff --git a/modules/generic/sourmash_all.nf b/modules/generic/sourmash_all.nf index a5dcf0b..ef44d6a 100644 --- a/modules/generic/sourmash_all.nf +++ b/modules/generic/sourmash_all.nf @@ -23,14 +23,17 @@ process SOURMASH_ALL { # sketch input genomes mkdir signatures ; - for genome in genomes/* ; do - export name=\$( echo \${genome} | cut -f 2 -d '/' | cut -f 1,2 -d '_' ) ; - sourmash \\ - sketch dna \\ - -p scaled=${scale},k=${kmer} \\ - \${genome} \\ - -o signatures/\${name}.sig ; - done + ( + cd genomes && \\ + for genome in * ; do + export name=\$( echo \${genome} | cut -f 2 -d '/' | cut -f 1,2 -d '_' ) ; + sourmash \\ + sketch dna \\ + -p scaled=${scale},k=${kmer} \\ + \${genome} \\ + -o ../signatures/\${name}.sig ; + done ; + ) # compare sourmash \\ @@ -40,9 +43,11 @@ process SOURMASH_ALL { -o sourmash_cmp # plot + sourmash plot --labels sourmash_cmp sourmash \\ plot \\ --pdf \\ + --csv sourmash_plot.csv \\ --labels sourmash_cmp """ } From 1620f2b70f9c2e82f817e5805a8b8e871f7843f8 Mon Sep 17 00:00:00 2001 From: Felipe Almeida Date: Wed, 3 Jul 2024 16:07:09 -0300 Subject: [PATCH 13/26] emi channels --- modules/generic/sourmash_all.nf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/generic/sourmash_all.nf b/modules/generic/sourmash_all.nf index ef44d6a..b9d81e4 100644 --- a/modules/generic/sourmash_all.nf +++ b/modules/generic/sourmash_all.nf @@ -11,8 +11,10 @@ process SOURMASH_ALL { val kmer output: - path "*" - path "sourmash_version.txt" + path "*" , emit: all + path "sourmash_version.txt" , emit: versions + path "sourmash_cmp.matrix.png" , emit: plot + path "sourmash_plot.csv" , emit: csv when: !params.skip_sourmash From 5fd89eeeb6c0c2a5b97c03f9b276a9ee0f19e0e1 Mon Sep 17 00:00:00 2001 From: Felipe Almeida Date: Wed, 3 Jul 2024 16:07:38 -0300 Subject: [PATCH 14/26] include sourmash channels in reports module --- modules/generic/reports.nf | 4 ++++ workflows/bacannot.nf | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/generic/reports.nf b/modules/generic/reports.nf index 772d470..e55ce28 100644 --- a/modules/generic/reports.nf +++ b/modules/generic/reports.nf @@ -5,6 +5,8 @@ process REPORT { input: tuple val(prefix), file('annotation_stats.tsv'), file(gff), file(barrnap), file(mlst), file(keggsvg), file(refseq_masher_txt), file(amrfinder), file(rgi), file(rgi_parsed), file(rgi_heatmap), file(argminer_out), file(resfinder_tab), file(resfinder_point), file(resfinder_phenotable), file(vfdb_blastn), file(victors_blastp), file(phigaro_txt), file(phispy_tsv), file(iceberg_blastp), file(iceberg_blastn), file(plasmids_tsv), file(platon_tsv), file(mobsuite_tsv), file(gi_image), file(phast_blastp), file(digIS), file(integronfinder) + file(sourmash_csv) + file(sourmash_png) output: path '*.html', emit: results @@ -30,6 +32,8 @@ process REPORT { barrnap = "$barrnap", \ mlst = "$mlst", \ refseq_masher = "$refseq_masher_txt", \ + sourmash_csv = "$sourmash_csv", \ + sourmash_png = "$sourmash_png", \ query = "${prefix}" ) ) ; diff --git a/workflows/bacannot.nf b/workflows/bacannot.nf index 039bc6c..e454455 100644 --- a/workflows/bacannot.nf +++ b/workflows/bacannot.nf @@ -258,7 +258,7 @@ workflow BACANNOT { // species identification REFSEQ_MASHER( annotation_out_ch.genome ) - SOURMASH_LCA ( + SOURMASH_LCA( dbs_ch, annotation_out_ch.genome, params.sourmash_scale, @@ -408,7 +408,9 @@ workflow BACANNOT { .join( DRAW_GIS.out.example, remainder: true ) .join( phast_output_ch, remainder: true ) .join( MERGE_ANNOTATIONS.out.digis_gff ) - .join( ch_integron_finder_gff, remainder: true ) + .join( ch_integron_finder_gff, remainder: true ), + SOURMASH_ALL.out.csv.first(), // make value channel + SOURMASH_ALL.out.plot.first() // make value channel ) // From 706dfe388bb245f102c16329301f78ad79815135 Mon Sep 17 00:00:00 2001 From: Felipe Almeida Date: Wed, 3 Jul 2024 16:08:05 -0300 Subject: [PATCH 15/26] add backbone for sourmash entry in report --- docker/renv/reports/report_general.Rmd | 12 ++++++++++++ docker/renv/reports/yes_sourmash.Rmd | 13 +++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 docker/renv/reports/yes_sourmash.Rmd diff --git a/docker/renv/reports/report_general.Rmd b/docker/renv/reports/report_general.Rmd index 0651624..afb3568 100644 --- a/docker/renv/reports/report_general.Rmd +++ b/docker/renv/reports/report_general.Rmd @@ -9,6 +9,8 @@ params: barrnap: mlst: refseq_masher: + sourmash_csv: + sourmash_png: query: output: bookdown::html_document2: @@ -57,6 +59,13 @@ if (file.exists(params$kegg)) { } else { kegg_not_null <- FALSE } +sourmash_csv <- try(read.delim(params$sourmash_csv, header = TRUE), silent = TRUE) +if (file.exists(params$kegg)) { + sourmash_not_null <- TRUE + sourmash_png <- params$sourmash_png +} else { + sourmash_not_null <- FALSE +} if (params$generic_annotator == "prokka") { annotator_url <- "https://github.com/tseemann/prokka" @@ -166,3 +175,6 @@ datatable(barrnap_gff, ```{r kegg_svg, echo=FALSE, results='asis', eval=kegg_not_null, child='yes_kegg.Rmd'} ``` + +```{r sourmash_svg, echo=FALSE, results='asis', eval=sourmash_not_null, child='yes_sourmash.Rmd'} +``` diff --git a/docker/renv/reports/yes_sourmash.Rmd b/docker/renv/reports/yes_sourmash.Rmd new file mode 100644 index 0000000..ae1b79e --- /dev/null +++ b/docker/renv/reports/yes_sourmash.Rmd @@ -0,0 +1,13 @@ +## Sourmash + +[Sourmash](https://sourmash.readthedocs.io/en/latest/) is a command-line tool and Python/Rust library for metagenome analysis and genome comparison using k-mers. It supports the compositional analysis of metagenomes, rapid search of large sequence databases, and flexible taxonomic profiling with both NCBI and GTDB taxonomies (see our prepared databases for more information). sourmash works well with sequences 30kb or larger, including bacterial and viral genomes. + +In Bacannot, the sourmash tool was used for performing genome comparison and dendogram plot with all the genomes given as input, plus, all the 10 first genomes identified as closest to each genome based on refseq_masher results. + +> Duplicate genomes were removed (same genome is closest to multiple inputs). +> +> The sourmash genome comparison results, and the compositional data of each sample is given as output, so that users can further utilize them to make customised sourmash plots as described in their documentation. + +```{r, out.width='100%', fig.cap='Sourmash genome comparison', fig.align='center'} +include_graphics(params$sourmash_png) +``` \ No newline at end of file From 4cdba6f109a15be52456e85030bc51ffb5dfa95f Mon Sep 17 00:00:00 2001 From: Felipe Almeida Date: Sat, 6 Jul 2024 13:24:08 -0300 Subject: [PATCH 16/26] make download more efficient in case of errors --- modules/generic/ncbi_genome.nf | 19 +++++++++---------- workflows/bacannot.nf | 5 ++--- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/modules/generic/ncbi_genome.nf b/modules/generic/ncbi_genome.nf index 12721b5..fbbf15c 100644 --- a/modules/generic/ncbi_genome.nf +++ b/modules/generic/ncbi_genome.nf @@ -1,9 +1,10 @@ process GET_NCBI_GENOME { publishDir "${params.output}/sourmash_all/closest_genomes", mode: 'copy' label = [ 'misc', 'process_low' ] + maxForks 3 input: - file(ncbi_accs) + val biosample_acc output: path("*.fna"), emit: genomes @@ -13,15 +14,13 @@ process GET_NCBI_GENOME { script: """ # download genomes from ncbi - for biosample in \$( cat ${ncbi_accs} | sort -u ) ; do - - export acc=\$(esearch -db biosample -query \${biosample} | elink -target assembly | esummary | xtract -pattern DocumentSummary -element Genbank | tr -d '\\n' | tr -d '') - echo \${biosample} -- \${acc} - curl -OJX GET \\ - "https://api.ncbi.nlm.nih.gov/datasets/v2alpha/genome/accession/\${acc}/download?include_annotation_type=GENOME_FASTA&filename=\${acc}.zip" \\ - -H "Accept: application/zip" - - done + export acc=\$(esearch -db biosample -query '${biosample_acc}' | elink -target assembly | esummary | xtract -pattern DocumentSummary -element Genbank | tr -d '\\n' | tr -d '') + echo ${biosample_acc} -- \${acc} + curl -OJX GET \\ + --retry 5 \\ + --retry-delay 15 \\ + "https://api.ncbi.nlm.nih.gov/datasets/v2alpha/genome/accession/\${acc}/download?include_annotation_type=GENOME_FASTA&filename=\${acc}.zip" \\ + -H "Accept: application/zip" # unzip files for file in *.zip ; do diff --git a/workflows/bacannot.nf b/workflows/bacannot.nf index e454455..9a36807 100644 --- a/workflows/bacannot.nf +++ b/workflows/bacannot.nf @@ -270,14 +270,13 @@ workflow BACANNOT { REFSEQ_MASHER.out.results .map { it[1] } .splitCsv( sep: '\t', header: true ) - .map{ "${it.biosample}\n" } + .map{ "${it.biosample}" } .unique() - .collectFile() ) SOURMASH_ALL( annotation_out_ch.genome .map{ it[1] } - .mix( GET_NCBI_GENOME.out.genomes ) + .mix( GET_NCBI_GENOME.out.genomes.collect() ) .collect(), params.sourmash_scale, params.sourmash_kmer From e772d70f502d1842d8bb4820903ff6008a1c46a8 Mon Sep 17 00:00:00 2001 From: Felipe Almeida Date: Sat, 6 Jul 2024 13:33:50 -0300 Subject: [PATCH 17/26] update docs --- docs/defaults.config | 20 ++++++++++++++++++++ docs/index.md | 2 +- docs/manual.md | 1 + docs/outputs.md | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/defaults.config b/docs/defaults.config index 0d43fe4..e8c5f69 100644 --- a/docs/defaults.config +++ b/docs/defaults.config @@ -122,6 +122,15 @@ params { // (NOT RUN?) antiSMASH (secondary metabolite) annotation skip_antismash = false +// (NOT RUN?) sourmash + skip_sourmash = false + +// (NOT RUN?) integron finder tool + skip_integron_finder = false + +// (NOT RUN?) CIRCOS tool + skip_circos = false + /* * Custom databases can be used to annotate additional genes in the genome. * It runs a BLAST alignment against the genome, therefore, the custom database @@ -172,6 +181,17 @@ params { // User's custom database coverage threshold blast_custom_mincov = 65 + /* + * Sourmash configuration + */ +// kmer size (21, 31 or 51) + sourmash_kmer = 31 + +// scale, e.g. a scale 1000 on a 5Mb genome will generate 5000 hashes +// 1000 is generally recommended by the tool's developers + sourmash_scale = 1000 + + /* * Resources allocation configuration * Defaults only, expecting to be overwritten diff --git a/docs/index.md b/docs/index.md index 4cb28ba..3d1b969 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,7 +23,7 @@ The pipeline's main steps are: | Analysis steps | Used software or databases | | :------------- | :------------------------- | | Genome assembly (if raw reads are given) | [Flye](https://github.com/fenderglass/Flye) and [Unicycler](https://github.com/rrwick/Unicycler) | -| Identification of closest 10 NCBI Refseq genomes | [RefSeq Masher](https://github.com/phac-nml/refseq_masher) | +| Identification of closest 10 NCBI Refseq genomes and comparison of genomes | [RefSeq Masher](https://github.com/phac-nml/refseq_masher) and [Sourmash](https://sourmash.readthedocs.io/en/latest/) | | Generic annotation and gene prediction | [Prokka](https://github.com/tseemann/prokka) or [Bakta](https://github.com/oschwengers/bakta) | | rRNA prediction | [barrnap](https://github.com/tseemann/barrnap) | | Classification within multi-locus sequence types (STs) | [mlst](https://github.com/tseemann/mlst) | diff --git a/docs/manual.md b/docs/manual.md index 1a2b1df..51087e6 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -96,6 +96,7 @@ The use of this parameter sets a default value for input samples. If a sample ha | `--skip_prophage_search` | :material-close: | false | Tells whether not to run prophage annotation modules | | `--skip_kofamscan` | :material-close: | false | Tells whether not to run KEGG orthology (KO) annotation with KofamScan | | `--skip_antismash` | :material-close: | false | Tells whether or not to run antiSMASH (secondary metabolite) annotation. AntiSMASH is executed using only its core annotation modules in order to keep it fast. | +| `--skip_sourmash` | :material-close: | false | Tells whether or not to run sourmash to compare input genomes and closest reference genomes | | `--skip_circos` | :material-close: | false | Tells whether or not to run the final `CIRCOS` module. When the input genome has many contigs, its results are not meaningful. | | `--skip_integron_finder` | :material-close: | false | Tells whether or not to run the integron finder tool. | diff --git a/docs/outputs.md b/docs/outputs.md index ba35080..0903774 100644 --- a/docs/outputs.md +++ b/docs/outputs.md @@ -15,6 +15,7 @@ After a successful execution, you will have something like this: # Directory tree from the running dir . ├── _ANNOTATION +│   └── sourmash_all # Sourmash results of genome comparison of all input genomes and all identified references | └── ecoli_ref.fna │   └── ecoli │   ├── assembly # Assembly files (when raw reads are given) @@ -38,6 +39,7 @@ After a successful execution, you will have something like this: |   ├── resistance # AMR annotation results from ARGminer, AMRFinderPlus, RGI and Resfinder |   ├── rRNA # barrnap annotation results |   ├── SequenceServerDBs # SequenceServer pre-formatted databases to be used with SequenceServer blast application +|   ├── sourmash # Sourmash summary and signature file for the specific sample |   ├── SQLdb # The SQLdb of the annotation used by the shiny server for rapid parsing |   ├── tools_versioning # Versions of tools and databases used (whenever available) |   ├── virulence # Virulence genes annotation results from Victors and VFDB databases From e90b207aa55abba4ba8f70cb45e1ead888fe5e93 Mon Sep 17 00:00:00 2001 From: Felipe Almeida Date: Sat, 6 Jul 2024 13:34:28 -0300 Subject: [PATCH 18/26] update changelog and readme --- README.md | 2 +- markdown/CHANGELOG.md | 7 ++++++- markdown/list_of_tools.md | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2eda798..e60bb6f 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Its main steps are: | Analysis steps | Used software or databases | | :------------- | :------------------------- | | Genome assembly (if raw reads are given) | [Flye](https://github.com/fenderglass/Flye) and [Unicycler](https://github.com/rrwick/Unicycler) | -| Identification of closest 10 NCBI Refseq genomes | [RefSeq Masher](https://github.com/phac-nml/refseq_masher) | +| Identification of closest 10 NCBI Refseq genomes and comparison of genomes | [RefSeq Masher](https://github.com/phac-nml/refseq_masher) and [Sourmash](https://sourmash.readthedocs.io/en/latest/) | | Generic annotation and gene prediction | [Prokka](https://github.com/tseemann/prokka) or [Bakta](https://github.com/oschwengers/bakta) | | rRNA prediction | [barrnap](https://github.com/tseemann/barrnap) | | Classification within multi-locus sequence types (STs) | [mlst](https://github.com/tseemann/mlst) | diff --git a/markdown/CHANGELOG.md b/markdown/CHANGELOG.md index 03654f5..4684ce7 100644 --- a/markdown/CHANGELOG.md +++ b/markdown/CHANGELOG.md @@ -2,9 +2,14 @@ The tracking for changes started in v2.1 +## v3.4.0 [TBD] + +* [[#30](https://github.com/fmalmeida/bacannot/issues/30)] + * Add `sourmash` to workflow + ## v3.3.3 [11-March-2024] -* [[#118](https://github.com/fmalmeida/bacannot/issues/116)] +* [[#118](https://github.com/fmalmeida/bacannot/issues/118)] * Add a parameter to allow user to skip `INTEGRON_FINDER` execution. * Add a parameter to allow user to skip `CIRCOS` execution. * Split antismash docker image, and added some snippets to fix some workarounds to allow pipeline to run with singularity diff --git a/markdown/list_of_tools.md b/markdown/list_of_tools.md index 27a1727..7f9dbcc 100644 --- a/markdown/list_of_tools.md +++ b/markdown/list_of_tools.md @@ -5,7 +5,7 @@ These are the tools that wrapped inside bacannot. **Cite** the tools whenever yo | Analysis steps | Used software or databases | | :------------- | :------------------------- | | Genome assembly (if raw reads are given) | [Flye](https://github.com/fenderglass/Flye) and [Unicycler](https://github.com/rrwick/Unicycler) | -| Identification of closest 10 NCBI Refseq genomes | [RefSeq Masher](https://github.com/phac-nml/refseq_masher) | +| Identification of closest 10 NCBI Refseq genomes and comparison of genomes | [RefSeq Masher](https://github.com/phac-nml/refseq_masher) and [Sourmash](https://sourmash.readthedocs.io/en/latest/) | | Generic annotation and gene prediction | [Prokka](https://github.com/tseemann/prokka) or [Bakta](https://github.com/oschwengers/bakta) | | rRNA prediction | [barrnap](https://github.com/tseemann/barrnap) | | Classification within multi-locus sequence types (STs) | [mlst](https://github.com/tseemann/mlst) | From 29622f65c8f38bf155a713567ffa3f3437c78cb0 Mon Sep 17 00:00:00 2001 From: Felipe Almeida Date: Sat, 6 Jul 2024 13:58:56 -0300 Subject: [PATCH 19/26] update reports --- docs/reports/report_MGEs.html | 503 ++++++++-------------------- docs/reports/report_general.html | 498 ++++++++------------------- docs/reports/report_resistance.html | 483 +++++++------------------- docs/reports/report_virulence.html | 473 +++++++------------------- 4 files changed, 520 insertions(+), 1437 deletions(-) diff --git a/docs/reports/report_MGEs.html b/docs/reports/report_MGEs.html index 9f6e4ed..cec170b 100644 --- a/docs/reports/report_MGEs.html +++ b/docs/reports/report_MGEs.html @@ -11,7 +11,7 @@ - + Annotation of mobile genetic elements @@ -241,7 +241,7 @@ $(this).detach().appendTo(div); // add a show code button right above - var showCodeText = $('' + (showThis ? 'Hide' : 'Code') + ''); + var showCodeText = $('' + (showThis ? 'Hide' : 'Show') + ''); var showCodeButton = $(''); showCodeButton.append(showCodeText); showCodeButton @@ -267,7 +267,7 @@ // * Change text // * add a class for intermediate states styling div.on('hide.bs.collapse', function () { - showCodeText.text('Code'); + showCodeText.text('Show'); showCodeButton.addClass('btn-collapsing'); }); div.on('hidden.bs.collapse', function () { @@ -1575,6 +1575,26 @@ PagedTableDoc.initAll(); }; + - - + - + - + * HTML5 export buttons for Buttons and DataTables. + * © SpryMedia Ltd - datatables.net/license + * + * FileSaver.js (1.3.3) - MIT license + * Copyright © 2016 Eli Grey - http://eligrey.com + */ +!function(n){var r,a;"function"==typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(t){return n(t,window,document)}):"object"==typeof exports?(r=require("jquery"),a=function(t,e){e.fn.dataTable||require("datatables.net")(t,e),e.fn.dataTable.Buttons||require("datatables.net-buttons")(t,e)},"undefined"==typeof window?module.exports=function(t,e,o,l){return t=t||window,e=e||r(t),a(t,e),n(e,t,t.document)}:(a(window,r),module.exports=n(r,window,window.document))):n(jQuery,window,document)}(function(C,T,y,t,e,k){"use strict";var o,l,n=C.fn.dataTable;function S(){return o||T.JSZip}function s(){return l||T.pdfMake}n.Buttons.pdfMake=function(t){if(!t)return s();l=t},n.Buttons.jszip=function(t){if(!t)return S();o=t};function N(t){var e="Sheet1";return e=t.sheetName?t.sheetName.replace(/[\[\]\*\/\\\?\:]/g,""):e}function u(t,e){for(var o=c(e),l=t.buttons.exportData(e.exportOptions),n=e.fieldBoundary,r=e.fieldSeparator,a=new RegExp(n,"g"),d=e.escapeChar!==k?e.escapeChar:"\\",p=function(t){for(var e="",o=0,l=t.length;o',"xl/_rels/workbook.xml.rels":'',"[Content_Types].xml":'',"xl/workbook.xml":'',"xl/worksheets/sheet1.xml":'',"xl/styles.xml":''},R=[{match:/^\-?\d+\.\d%$/,style:60,fmt:function(t){return t/100}},{match:/^\-?\d+\.?\d*%$/,style:56,fmt:function(t){return t/100}},{match:/^\-?\$[\d,]+.?\d*$/,style:57},{match:/^\-?£[\d,]+.?\d*$/,style:58},{match:/^\-?€[\d,]+.?\d*$/,style:59},{match:/^\-?\d+$/,style:65},{match:/^\-?\d+\.\d{2}$/,style:66},{match:/^\([\d,]+\)$/,style:61,fmt:function(t){return-1*t.replace(/[\(\)]/g,"")}},{match:/^\([\d,]+\.\d{2}\)$/,style:62,fmt:function(t){return-1*t.replace(/[\(\)]/g,"")}},{match:/^\-?[\d,]+$/,style:63},{match:/^\-?[\d,]+\.\d{2}$/,style:64},{match:/^[\d]{4}\-[01][\d]\-[0123][\d]$/,style:67,fmt:function(t){return Math.round(25569+Date.parse(t)/864e5)}}];return n.ext.buttons.copyHtml5={className:"buttons-copy buttons-html5",text:function(t){return t.i18n("buttons.copy","Copy")},action:function(t,e,o,l){this.processing(!0);var n=this,r=u(e,l),a=e.buttons.exportInfo(l),d=c(l),p=r.str,i=C("
").css({height:1,width:1,overflow:"hidden",position:"fixed",top:0,left:0}),d=(a.title&&(p=a.title+d+d+p),a.messageTop&&(p=a.messageTop+d+d+p),a.messageBottom&&(p=p+d+d+a.messageBottom),l.customize&&(p=l.customize(p,l,e)),C("'); + } else if (inArray(index, dateCols)) { + $input = $(''); } else { $input = $(''); } @@ -3343,7 +3386,7 @@ if (immediate) $input.on('blur', function(e) { var valueNew = $input.val(); - if (valueNew != value) { + if (valueNew !== value) { _cell.data(valueNew); if (HTMLWidgets.shinyMode) { changeInput('cell_edit', [cellInfo(cell)], 'DT.cellInfo', null, {priority: 'event'}); @@ -3503,6 +3546,9 @@ updateColsSelected(); updateCellsSelected(); }) + updateRowsSelected(); + updateColsSelected(); + updateCellsSelected(); } var selMode = data.selection.mode, selTarget = data.selection.target; @@ -3861,7 +3907,7 @@ changeInput('cell_clicked', {}); // do not trigger table selection when clicking on links unless they have classes - table.on('click.dt', 'tbody td a', function(e) { + table.on('mousedown.dt', 'tbody td a', function(e) { if (this.className === '') e.stopPropagation(); }); @@ -3889,8 +3935,9 @@ console.log('The search keyword for column ' + i + ' is undefined') return; } - $(td).find('input').first().val(v); - searchColumn(i, v); + // Update column search string and values on linked filter widgets. + // 'input' for factor and char filters, 'change' for numeric filters. + $(td).find('input').first().val(v).trigger('input', [true]).trigger('change'); }); table.draw(); } @@ -4005,7 +4052,7 @@ })(); - - + - + - + * HTML5 export buttons for Buttons and DataTables. + * © SpryMedia Ltd - datatables.net/license + * + * FileSaver.js (1.3.3) - MIT license + * Copyright © 2016 Eli Grey - http://eligrey.com + */ +!function(n){var r,a;"function"==typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(t){return n(t,window,document)}):"object"==typeof exports?(r=require("jquery"),a=function(t,e){e.fn.dataTable||require("datatables.net")(t,e),e.fn.dataTable.Buttons||require("datatables.net-buttons")(t,e)},"undefined"==typeof window?module.exports=function(t,e,o,l){return t=t||window,e=e||r(t),a(t,e),n(e,t,t.document)}:(a(window,r),module.exports=n(r,window,window.document))):n(jQuery,window,document)}(function(C,T,y,t,e,k){"use strict";var o,l,n=C.fn.dataTable;function S(){return o||T.JSZip}function s(){return l||T.pdfMake}n.Buttons.pdfMake=function(t){if(!t)return s();l=t},n.Buttons.jszip=function(t){if(!t)return S();o=t};function N(t){var e="Sheet1";return e=t.sheetName?t.sheetName.replace(/[\[\]\*\/\\\?\:]/g,""):e}function u(t,e){for(var o=c(e),l=t.buttons.exportData(e.exportOptions),n=e.fieldBoundary,r=e.fieldSeparator,a=new RegExp(n,"g"),d=e.escapeChar!==k?e.escapeChar:"\\",p=function(t){for(var e="",o=0,l=t.length;o',"xl/_rels/workbook.xml.rels":'',"[Content_Types].xml":'',"xl/workbook.xml":'',"xl/worksheets/sheet1.xml":'',"xl/styles.xml":''},R=[{match:/^\-?\d+\.\d%$/,style:60,fmt:function(t){return t/100}},{match:/^\-?\d+\.?\d*%$/,style:56,fmt:function(t){return t/100}},{match:/^\-?\$[\d,]+.?\d*$/,style:57},{match:/^\-?£[\d,]+.?\d*$/,style:58},{match:/^\-?€[\d,]+.?\d*$/,style:59},{match:/^\-?\d+$/,style:65},{match:/^\-?\d+\.\d{2}$/,style:66},{match:/^\([\d,]+\)$/,style:61,fmt:function(t){return-1*t.replace(/[\(\)]/g,"")}},{match:/^\([\d,]+\.\d{2}\)$/,style:62,fmt:function(t){return-1*t.replace(/[\(\)]/g,"")}},{match:/^\-?[\d,]+$/,style:63},{match:/^\-?[\d,]+\.\d{2}$/,style:64},{match:/^[\d]{4}\-[01][\d]\-[0123][\d]$/,style:67,fmt:function(t){return Math.round(25569+Date.parse(t)/864e5)}}];return n.ext.buttons.copyHtml5={className:"buttons-copy buttons-html5",text:function(t){return t.i18n("buttons.copy","Copy")},action:function(t,e,o,l){this.processing(!0);var n=this,r=u(e,l),a=e.buttons.exportInfo(l),d=c(l),p=r.str,i=C("
").css({height:1,width:1,overflow:"hidden",position:"fixed",top:0,left:0}),d=(a.title&&(p=a.title+d+d+p),a.messageTop&&(p=a.messageTop+d+d+p),a.messageBottom&&(p=p+d+d+a.messageBottom),l.customize&&(p=l.customize(p,l,e)),C("'); + } else if (inArray(index, dateCols)) { + $input = $(''); } else { $input = $(''); } @@ -3343,7 +3386,7 @@ if (immediate) $input.on('blur', function(e) { var valueNew = $input.val(); - if (valueNew != value) { + if (valueNew !== value) { _cell.data(valueNew); if (HTMLWidgets.shinyMode) { changeInput('cell_edit', [cellInfo(cell)], 'DT.cellInfo', null, {priority: 'event'}); @@ -3503,6 +3546,9 @@ updateColsSelected(); updateCellsSelected(); }) + updateRowsSelected(); + updateColsSelected(); + updateCellsSelected(); } var selMode = data.selection.mode, selTarget = data.selection.target; @@ -3861,7 +3907,7 @@ changeInput('cell_clicked', {}); // do not trigger table selection when clicking on links unless they have classes - table.on('click.dt', 'tbody td a', function(e) { + table.on('mousedown.dt', 'tbody td a', function(e) { if (this.className === '') e.stopPropagation(); }); @@ -3889,8 +3935,9 @@ console.log('The search keyword for column ' + i + ' is undefined') return; } - $(td).find('input').first().val(v); - searchColumn(i, v); + // Update column search string and values on linked filter widgets. + // 'input' for factor and char filters, 'change' for numeric filters. + $(td).find('input').first().val(v).trigger('input', [true]).trigger('change'); }); table.draw(); } @@ -4005,7 +4052,7 @@ })(); - - + - + - + * HTML5 export buttons for Buttons and DataTables. + * © SpryMedia Ltd - datatables.net/license + * + * FileSaver.js (1.3.3) - MIT license + * Copyright © 2016 Eli Grey - http://eligrey.com + */ +!function(n){var r,a;"function"==typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(t){return n(t,window,document)}):"object"==typeof exports?(r=require("jquery"),a=function(t,e){e.fn.dataTable||require("datatables.net")(t,e),e.fn.dataTable.Buttons||require("datatables.net-buttons")(t,e)},"undefined"==typeof window?module.exports=function(t,e,o,l){return t=t||window,e=e||r(t),a(t,e),n(e,t,t.document)}:(a(window,r),module.exports=n(r,window,window.document))):n(jQuery,window,document)}(function(C,T,y,t,e,k){"use strict";var o,l,n=C.fn.dataTable;function S(){return o||T.JSZip}function s(){return l||T.pdfMake}n.Buttons.pdfMake=function(t){if(!t)return s();l=t},n.Buttons.jszip=function(t){if(!t)return S();o=t};function N(t){var e="Sheet1";return e=t.sheetName?t.sheetName.replace(/[\[\]\*\/\\\?\:]/g,""):e}function u(t,e){for(var o=c(e),l=t.buttons.exportData(e.exportOptions),n=e.fieldBoundary,r=e.fieldSeparator,a=new RegExp(n,"g"),d=e.escapeChar!==k?e.escapeChar:"\\",p=function(t){for(var e="",o=0,l=t.length;o',"xl/_rels/workbook.xml.rels":'',"[Content_Types].xml":'',"xl/workbook.xml":'',"xl/worksheets/sheet1.xml":'',"xl/styles.xml":''},R=[{match:/^\-?\d+\.\d%$/,style:60,fmt:function(t){return t/100}},{match:/^\-?\d+\.?\d*%$/,style:56,fmt:function(t){return t/100}},{match:/^\-?\$[\d,]+.?\d*$/,style:57},{match:/^\-?£[\d,]+.?\d*$/,style:58},{match:/^\-?€[\d,]+.?\d*$/,style:59},{match:/^\-?\d+$/,style:65},{match:/^\-?\d+\.\d{2}$/,style:66},{match:/^\([\d,]+\)$/,style:61,fmt:function(t){return-1*t.replace(/[\(\)]/g,"")}},{match:/^\([\d,]+\.\d{2}\)$/,style:62,fmt:function(t){return-1*t.replace(/[\(\)]/g,"")}},{match:/^\-?[\d,]+$/,style:63},{match:/^\-?[\d,]+\.\d{2}$/,style:64},{match:/^[\d]{4}\-[01][\d]\-[0123][\d]$/,style:67,fmt:function(t){return Math.round(25569+Date.parse(t)/864e5)}}];return n.ext.buttons.copyHtml5={className:"buttons-copy buttons-html5",text:function(t){return t.i18n("buttons.copy","Copy")},action:function(t,e,o,l){this.processing(!0);var n=this,r=u(e,l),a=e.buttons.exportInfo(l),d=c(l),p=r.str,i=C("
").css({height:1,width:1,overflow:"hidden",position:"fixed",top:0,left:0}),d=(a.title&&(p=a.title+d+d+p),a.messageTop&&(p=a.messageTop+d+d+p),a.messageBottom&&(p=p+d+d+a.messageBottom),l.customize&&(p=l.customize(p,l,e)),C("'); + } else if (inArray(index, dateCols)) { + $input = $(''); } else { $input = $(''); } @@ -3343,7 +3386,7 @@ if (immediate) $input.on('blur', function(e) { var valueNew = $input.val(); - if (valueNew != value) { + if (valueNew !== value) { _cell.data(valueNew); if (HTMLWidgets.shinyMode) { changeInput('cell_edit', [cellInfo(cell)], 'DT.cellInfo', null, {priority: 'event'}); @@ -3503,6 +3546,9 @@ updateColsSelected(); updateCellsSelected(); }) + updateRowsSelected(); + updateColsSelected(); + updateCellsSelected(); } var selMode = data.selection.mode, selTarget = data.selection.target; @@ -3861,7 +3907,7 @@ changeInput('cell_clicked', {}); // do not trigger table selection when clicking on links unless they have classes - table.on('click.dt', 'tbody td a', function(e) { + table.on('mousedown.dt', 'tbody td a', function(e) { if (this.className === '') e.stopPropagation(); }); @@ -3889,8 +3935,9 @@ console.log('The search keyword for column ' + i + ' is undefined') return; } - $(td).find('input').first().val(v); - searchColumn(i, v); + // Update column search string and values on linked filter widgets. + // 'input' for factor and char filters, 'change' for numeric filters. + $(td).find('input').first().val(v).trigger('input', [true]).trigger('change'); }); table.draw(); } @@ -4005,7 +4052,7 @@ })(); - - + - + - + * HTML5 export buttons for Buttons and DataTables. + * © SpryMedia Ltd - datatables.net/license + * + * FileSaver.js (1.3.3) - MIT license + * Copyright © 2016 Eli Grey - http://eligrey.com + */ +!function(n){var r,a;"function"==typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(t){return n(t,window,document)}):"object"==typeof exports?(r=require("jquery"),a=function(t,e){e.fn.dataTable||require("datatables.net")(t,e),e.fn.dataTable.Buttons||require("datatables.net-buttons")(t,e)},"undefined"==typeof window?module.exports=function(t,e,o,l){return t=t||window,e=e||r(t),a(t,e),n(e,t,t.document)}:(a(window,r),module.exports=n(r,window,window.document))):n(jQuery,window,document)}(function(C,T,y,t,e,k){"use strict";var o,l,n=C.fn.dataTable;function S(){return o||T.JSZip}function s(){return l||T.pdfMake}n.Buttons.pdfMake=function(t){if(!t)return s();l=t},n.Buttons.jszip=function(t){if(!t)return S();o=t};function N(t){var e="Sheet1";return e=t.sheetName?t.sheetName.replace(/[\[\]\*\/\\\?\:]/g,""):e}function u(t,e){for(var o=c(e),l=t.buttons.exportData(e.exportOptions),n=e.fieldBoundary,r=e.fieldSeparator,a=new RegExp(n,"g"),d=e.escapeChar!==k?e.escapeChar:"\\",p=function(t){for(var e="",o=0,l=t.length;o',"xl/_rels/workbook.xml.rels":'',"[Content_Types].xml":'',"xl/workbook.xml":'',"xl/worksheets/sheet1.xml":'',"xl/styles.xml":''},R=[{match:/^\-?\d+\.\d%$/,style:60,fmt:function(t){return t/100}},{match:/^\-?\d+\.?\d*%$/,style:56,fmt:function(t){return t/100}},{match:/^\-?\$[\d,]+.?\d*$/,style:57},{match:/^\-?£[\d,]+.?\d*$/,style:58},{match:/^\-?€[\d,]+.?\d*$/,style:59},{match:/^\-?\d+$/,style:65},{match:/^\-?\d+\.\d{2}$/,style:66},{match:/^\([\d,]+\)$/,style:61,fmt:function(t){return-1*t.replace(/[\(\)]/g,"")}},{match:/^\([\d,]+\.\d{2}\)$/,style:62,fmt:function(t){return-1*t.replace(/[\(\)]/g,"")}},{match:/^\-?[\d,]+$/,style:63},{match:/^\-?[\d,]+\.\d{2}$/,style:64},{match:/^[\d]{4}\-[01][\d]\-[0123][\d]$/,style:67,fmt:function(t){return Math.round(25569+Date.parse(t)/864e5)}}];return n.ext.buttons.copyHtml5={className:"buttons-copy buttons-html5",text:function(t){return t.i18n("buttons.copy","Copy")},action:function(t,e,o,l){this.processing(!0);var n=this,r=u(e,l),a=e.buttons.exportInfo(l),d=c(l),p=r.str,i=C("
").css({height:1,width:1,overflow:"hidden",position:"fixed",top:0,left:0}),d=(a.title&&(p=a.title+d+d+p),a.messageTop&&(p=a.messageTop+d+d+p),a.messageBottom&&(p=p+d+d+a.messageBottom),l.customize&&(p=l.customize(p,l,e)),C("