From a6ec7470865f417118649a816e91873f93ac7528 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Wed, 22 Mar 2023 01:47:06 +0100 Subject: [PATCH 01/26] init branch for issue #18 --- learning_cwl.md | 212 ---------- ro-crate-io-metadata.json-template | 308 ++++++++++++++ ...json => ro-crate-source-code-metadata.json | 0 run_wf.sh | 2 +- utils/create-ro-crate.py | 387 ++++++++++++++++++ create_yml.py => utils/create_yml.py | 0 6 files changed, 696 insertions(+), 213 deletions(-) delete mode 100644 learning_cwl.md create mode 100644 ro-crate-io-metadata.json-template rename ro-crate-metadata.json => ro-crate-source-code-metadata.json (100%) create mode 100644 utils/create-ro-crate.py rename create_yml.py => utils/create_yml.py (100%) diff --git a/learning_cwl.md b/learning_cwl.md deleted file mode 100644 index 400e7229..00000000 --- a/learning_cwl.md +++ /dev/null @@ -1,212 +0,0 @@ -# CWL in a nutshell (not 😜) - - -## Conditionals - -To run a conditional, the input parameter that is used in the -expression to be evaluated, needs to be part of the input of the step!! -Not only in the `.cwl` main params. - - - - -## Data concepts - -An **`object`** is a data structure equivalent to the "object" type in JSON, consisting of a *unordered* set of **name/value pairs** (referred to here as **`fields`**) and where the name is a `string` and the value is a `string`, `number`, `boolean`, `array`, or `object`. - -> **`fields`** is a key term! - -A **`document`** is a file containing a serialized `object`, or an `array` of `objects`. - -A **`process`** is a basic unit of computation which accepts input data, performs some computation, and produces output data. -Examples include `CommandLineTools`, `Workflows`, and `ExpressionTools`. - -An **`input object`** is an object describing the inputs to an invocation of a process. -The **fields** of the input object are referred to as "input **parameters**". -Likewise for the **`output object`**. - - -An **`input schema`** describes the valid format (required fields, data types) for an input object. -Similarly for the case of `output schema`. - - - -The **`inputs`** section describes the inputs of the tool. -This is a ***mapped** list of input parameters* -(see the [YAML Guide](https://www.commonwl.org/user_guide/yaml/#maps) for more about the format) and each parameter includes an **identifier**, a **data type**, and *optionally* an **inputBinding**. ->The **`inputBinding`** describes how this input parameter should appear on the command line. - -For example: - -```bash= - inputBinding: - position: 2 - prefix: -i - separate: false -``` -where - -- `position`: the value of position is used to determine where parameter should appear on the command line -- `separate`: when `false`, the prefix and value are combined into a single argument -- `prefix` : argument on the command line before the parameter - - - -## Execution concepts - -A parameter is a named symbolic input or output of process, with an associated datatype or schema. During execution, values are assigned to parameters to make the input object or output object used for concrete process invocation. - -A CommandLineTool is a process characterized by the execution of a standalone, non-interactive program which is invoked on some input, produces output, and then terminates. - -A workflow is a process characterized by multiple subprocess steps, where step outputs are connected to the inputs of downstream steps to form a directed acylic graph, and independent steps may run concurrently. - -A runtime environment is the actual hardware and software environment when executing a command line tool. It includes, but is not limited to, the hardware architecture, hardware resources, operating system, software runtime (if applicable, such as the specific Python interpreter or the specific Java virtual machine), libraries, modules, packages, utilities, and data files required to run the tool. - -A workflow platform is a specific hardware and software implementation capable of interpreting CWL documents and executing the processes specified by the document. The responsibilities of the workflow platform may include scheduling process invocation, setting up the necessary runtime environment, making input data available, invoking the tool process, and collecting output. - -A workflow platform may choose to only implement the Command Line Tool Description part of the CWL specification. - - - -## [Document context](https://www.commonwl.org/v1.0/SchemaSalad.html#Document_model) - -The implicit context consists of the vocabulary defined by the schema and the base URI. By default, the base URI must be the URI that was used to load the document. It may be overridden by an explicit context. - -If a document consists of a root object, this object may contain the fields `$base`, `$namespaces`, `$schemas`, and `$graph`: - - - - - -## Runtime environment (!) - -Output files produced by tool execution must be written to the designated output directory. The initial current working directory when executing the tool must be the designated output directory. - - - - - -### Requirements & hints - -A process `requirement` modifies the semantics or runtime environment of a process. -If an implementation cannot satisfy all requirements, or a requirement is listed which is not recognized by the implementation, it is a fatal error and the implementation must not attempt to run the process, unless overridden at user option. - -A `hint` is similar to a requirement; however, it is not an error if an implementation cannot satisfy all hints. -The implementation may report a warning if a hint cannot be satisfied. - - -Often tool descriptions will be written for a specific version of a software. -To make it easier for others to use your descriptions, you can include a `SoftwareRequirement` field in the `hints` section. -This may also help to avoid confusion about which version of a tool the description was written for. -Here is an example: - -```cwl -hints: - SoftwareRequirement: - packages: - interproscan: - specs: [ "https://identifiers.org/rrid/RRID:SCR_005829" ] - version: [ "5.21-60" ] -``` - - -**Do not confuse with `requirements`**. -`requirements` are - -requirements: - ResourceRequirement: - ramMin: 10240 - coresMin: 3 - SchemaDefRequirement: - types: - - $import: InterProScan-apps.yml - - - -Optionally, implementations may allow requirements to be specified in the input object document as an array of requirements under the field name `cwl:requirements`. -If implementations allow this, then such requirements should be combined with any requirements present in the corresponding Process as if they were specified there. - -**Requirements specified in a parent Workflow are inherited by step processes if they are valid for that step**. If the substep is a `CommandLineTool` only the `InlineJavascriptRequirement`, `SchemaDefRequirement`, `DockerRequirement`, `SoftwareRequirement`, `InitialWorkDirRequirement`, `EnvVarRequirement`, `ShellCommandRequirement`, `ResourceRequirement` are valid. - -*As good practice, it is best to have process requirements be self-contained, such that each process can run successfully by itself.* - -**`Requirements` override `hints`**. If a process implementation provides a process requirement in hints which is also provided in requirements by an enclosing workflow or workflow step, the enclosing requirements takes precedence. - -> When a tool runs under CWL, the starting working directory is the designated output directory. - - -### Test your tool - -Once you have built your `.cwl` and your `.yml` files, you need to figure out whether your `tool` is working ok. -To do that, run the step your `tool` implements and keep track of its exact output. -Then, you may build a second `.yml` file (we will call it `tools-tests.yml`) which is like that: - -```yaml= -- job: tools/my_tool/my_tool_test.yml - tool: ../../tools/tool/my_tool.cwl - short_name: my_tool.cwl - doc: "TOOL" - output: - tool_output: - location: Any - basename: toul_output - class: Directory - listing: - - class: File - .. - .. - .. - -``` - -For a more complete example, you may see [here](https://github.com/mberacochea/microbetag/blob/78140c451ff7034a3bbc6ac1ec34efe9d0b8b742/tests/cwl/tools-tests.yml). - - - -`cwltest` does: -- runs the cwl file with the .yml input file -- compares the output values - - - -```cwl= - -``` - -## Important links to guide you - -A few rather important links to get to know the CWL framework: - -- [Runtime environment](https://www.commonwl.org/v1.0/CommandLineTool.html#Runtime_environment) -- [Writing workflows](https://www.commonwl.org/user_guide/21-1st-workflow/index.html) -- [Best practicies](https://doc.arvados.org/v1.3/user/cwl/cwl-style.html) - - - - -Tutorials: - -- [Getting started with CWL](https://docs.dockstore.org/en/1.11.0/getting-started/getting-started-with-cwl.html) - - -```cwl= -outputs: - compiled_class: - type: File - outputSource: compile/classfile -``` -The `outputs` section describes the outputs of the workflow. -This is a **list** of output parameters where each parameter consists of an identifier and a data type. -The `outputSource` connects the output parameter `classfile` of the `compile` step to the workflow output parameter `compiled_class`. - - - - -## Toil - -Note! Toil checks if the docker image specified by TOIL_APPLIANCE_SELF exists prior to - launching by using the docker v2 schema. This should be valid for any major docker - repository, but there is an option to override this if desired using the option: - `--forceDockerAppliance`. - - diff --git a/ro-crate-io-metadata.json-template b/ro-crate-io-metadata.json-template new file mode 100644 index 00000000..b3d39d60 --- /dev/null +++ b/ro-crate-io-metadata.json-template @@ -0,0 +1,308 @@ +{ "@context": "https://w3id.org/ro/crate/1.1/context", + "@graph": [ + { + "@id": "ro-crate-metadata.json", + "@type": "CreativeWork", + "conformsTo": {"@id": "https://w3id.org/ro/crate/1.1"}, + "about": {"@id": "./"} + }, + { + "@id": "./", + "@type": "Dataset", + "name" : "MetaGoFlow Results for ENA Run Accession Number {ena_accession_raw_data}", + "description" : "RO-Crate for the MetaGOflow analysis EMO BON ENA Accession {ena_accession_raw_data} data ", + "datePublished": "{datePublished}", + "license": {"@id": "https://creativecommons.org/licenses/by/4.0/legalcode"}, + "publisher": {"@id": "https://ror.org/0038zss60"}, + "hasPart": [ + {"@id": "{ena_accession_raw_data}"}, + {"@id": "{metagoflow_version}"}, + {"@id": "{run_parameter}.yml"}, + {"@id": "fastp.html"}, + {"@id": "final.contigs.fa"}, + {"@id": "functional_annotation/"}, + {"@id": "sequence-categorisation/"}, + {"@id": "taxonomic-summary/"}, + {"@id": "RNA-counts"} + + ] + }, + { + "@id": "https://ror.org/0038zss60", + "@type": "Organization", + "name": "European Marine Biological Resource Centre", + "url": "https://ror.org/0038zss60", + "contactPoint": {"@id": "mailto:help@embrc.org"} + }, + { + "@id": "mailto:help@embrc.org", + "@type": "ContactPoint", + "contactType": "Help Desk", + "email": "help@embrc.org", + "identifier": "help@embrc.org", + "url": "https://www.embrc.eu/about-us/contact-us" + }, + { + "@id": "https://creativecommons.org/licenses/by/4.0/legalcode", + "@type": "CreativeWork", + "identifier": "https://creativecommons.org/licenses/by/4.0/legalcode", + "name": "Creative Commons (CC-BY 4.0)" + }, + { + "@id": "{ena_accession_raw_data}", + "@type": "File", + "name": "ENA accession for run raw sequence data", + "description": "FAKE: Raw sequence data and laboratory sequence generation metadata", + "encodingFormat": "text/xml" + }, + { + "@id": "{metagoflow_version}", + "@type": "File", + "name": "MetaGOflow Workflow Version RO-Crate", + "description": "Metadata for the version of the MetaGOflow workflow used to generate the data", + "encodingFormat": "application/zip" + }, + { + "@id": "{run_parameter}.yml", + "@type": "File", + "name": "MetaGOflow YAML configuration file", + "description": "YAML configuration file for execution of MetaGOflow workflow.", + "encodingFormat": "text/yaml" + }, + { + "@id": "fastp.html", + "@type": "File", + "name": "FASTP analysis of raw sequence data", + "description": "Quality control and preprocessing of FASTQ files", + "encodingFormat": "text/html" + }, + { + "@id": "final.contigs.fa", + "@type": "File", + "name": "FASTA formatted contig sequences", + "description": "These are the assembled contig sequences from the merged reads in FASTA format", + "encodingFormat": "text/plain" + }, + { + "@id": "functional_annotation/", + "@type": "Dataset", + "name": "Functional annotation results", + "description": "Functional annotation of merged reads", + "hasPart": [ + {"@id": "stats/"}, + {"@id": "{prefix}.merged_CDS.I5.tsv.gz"}, + {"@id": "{prefix}.merged.hmm.tsv.gz"}, + {"@id": "{prefix}.merged.summary.go"}, + {"@id": "{prefix}.merged.summary.go_slim"}, + {"@id": "{prefix}.merged.summary.ips"}, + {"@id": "{prefix}.merged.summary.ko"}, + {"@id": "{prefix}.merged.summary.pfam"} + ] + }, + { + "@id": "stats/", + "@type": "Dataset", + "name": "Summary statistic for functional annotation", + "hasPart": [ + {"@id": "go.stats"}, + {"@id": "interproscan.stats"}, + {"@id": "ko.stats"}, + {"@id": "orf.stats"}, + {"@id": "pfam.stats"} + ] + }, + { + "@id": "go.stats", + "@type": "File", + "name": "Geno Ontology summary statistics", + "encodingFormat": "text/plain" + }, + { + "@id": "interproscan.stats", + "@type": "File", + "name": "InterProScan summary statistics", + "encodingFormat": "text/plain" + }, + { + "@id": "ko.stats", + "@type": "File", + "name": "Kegg Ontology summary statistics", + "encodingFormat": "text/plain" + }, + { + "@id": "orf.stats", + "@type": "File", + "name": "ORF summary statistics", + "encodingFormat": "text/plain" + }, + { + "@id": "pfam.stats", + "@type": "File", + "name": "Pfam summary statistcs", + "encodingFormat": "text/plain" + }, + { + "@id": "{prefix}.merged_CDS.I5.tsv.gz", + "@type": "File", + "name": "Merged contigs CDS I5 summary", + "encodingFormat": "application/zip" + }, + { + "@id": "{prefix}.merged.hmm.tsv.gz", + "@type": "File", + "name": "Merged contigs HMM summary", + "encodingFormat": "application/zip" + }, + { + "@id": "{prefix}.merged.summary.go", + "@type": "File", + "name": "Merged contigs GO summary", + "encodingFormat": "text/plain" + }, + { + "@id": "{prefix}.merged.summary.go_slim", + "@type": "File", + "name": "Merged contigs InterProScan slim", + "encodingFormat": "text/plain" + }, + { + "@id": "{prefix}.merged.summary.ips", + "@type": "File", + "name": "Merged contigs InterProScan", + "encodingFormat": "text/plain" + }, + { + "@id": "{prefix}.merged.summary.ko", + "@type": "File", + "name": "Merged contigs KO summary", + "encodingFormat": "text/plain" + }, + { + "@id": "{prefix}.merged.summary.pfam", + "@type": "File", + "name": "Merged contigs PFAM summary", + "encodingFormat": "text/plain" + }, + { + "@id": "sequence-categorisation/", + "@type": "Dataset", + "name": "Sequence categorisation", + "description": "Identify specific loci in the sample." + }, + { + "@id": "taxonomic-summary/", + "@type": "Dataset", + "name": "Taxonomic summary", + "description": "Summary of taxonomic identification results", + "hasPart": [ + {"@id": "RNA-counts"}, + {"@id": "LSU/"}, + {"@id": "SSU/"} + ] + }, + { + "@id": "RNA-counts", + "@type": "File", + "name": "Numbers of RNA's counted", + "encodingFormat": "text/plain" + }, + { + "@id": "LSU/", + "@type": "Dataset", + "name": "Summary of LSU taxonomic indentification results", + "hasPart": [ + {"@id": "krona.html"}, + {"@id": "{prefix}.merged_LSU.fasta.mseq.gz"}, + {"@id": "{prefix}.merged_LSU.fasta.mseq_hdf5.biom"}, + {"@id": "{prefix}.merged_LSU.fasta.mseq_json.biom"}, + {"@id": "{prefix}.merged_LSU.fasta.mseq.tsv"}, + {"@id": "{prefix}.merged_LSU.fasta.mseq.txt"} + ] + }, + { + "@id": "krona.html", + "@type": "File", + "name": "Krona summary of LSU taxonomic inventory", + "encodingFormat": "application/html" + }, + { + "@id": "{prefix}.merged_LSU.fasta.mseq.gz", + "@type": "File", + "name": "LSU sequences used for indentification", + "encodingFormat": "application/zip" + }, + { + "@id": "{prefix}.merged_LSU.fasta.mseq_hdf5.biom", + "@type": "File", + "name": "BIOM formatted hdf5 taxon counts for LSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": "{prefix}.merged_LSU.fasta.mseq_json.biom", + "@type": "File", + "name": "BIOM formatted taxon counts for LSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": "{prefix}.merged_LSU.fasta.mseq.tsv", + "@type": "File", + "name": "Tab-separated formatted taxon counts for LSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": "{prefix}.merged_LSU.fasta.mseq.txt", + "@type": "File", + "name": "Text-based taxon counts for LSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": "SSU/", + "@type": "Dataset", + "name": "Summary of SSU taxonomic indentification results", + "hasPart": [ + {"@id": "krona.html"}, + {"@id": "{prefix}.merged_SSU.fasta.mseq.gz"}, + {"@id": "{prefix}.merged_SSU.fasta.mseq_hdf5.biom"}, + {"@id": "{prefix}.merged_SSU.fasta.mseq_json.biom"}, + {"@id": "{prefix}.merged_SSU.fasta.mseq.tsv"}, + {"@id": "{prefix}.merged_SSU.fasta.mseq.txt"} + ] + }, + { + "@id": "krona.html", + "@type": "File", + "name": "Krona summary of SSU taxonomic inventory", + "encodingFormat": "text/html" + }, + { + "@id": "{prefix}.merged_SSU.fasta.mseq.gz", + "@type": "File", + "name": "LSU sequences used for indentification", + "encodingFormat": "application/zip" + }, + { + "@id": "{prefix}.merged_SSU.fasta.mseq_hdf5.biom", + "@type": "File", + "name": "BIOM formatted hdf5 taxon counts for SSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": "{prefix}.merged_SSU.fasta.mseq_json.biom", + "@type": "File", + "name": "BIOM formatted taxon counts for SSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": "{prefix}.merged_SSU.fasta.mseq.tsv", + "@type": "File", + "name": "Tab-separated formatted taxon counts for SSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": "{prefix}.merged_SSU.fasta.mseq.txt", + "@type": "File", + "name": "Text-based formatted taxon counts for SSU sequences", + "encodingFormat": "application/json-ld" + } +] +} \ No newline at end of file diff --git a/ro-crate-metadata.json b/ro-crate-source-code-metadata.json similarity index 100% rename from ro-crate-metadata.json rename to ro-crate-source-code-metadata.json diff --git a/run_wf.sh b/run_wf.sh index abf35ed8..ef9de08a 100755 --- a/run_wf.sh +++ b/run_wf.sh @@ -167,7 +167,7 @@ fi echo "Writing yaml file" # DO NOT leave spaces after "\" in the end of a line -python3 create_yml.py \ +python3 utils/create_yml.py \ -y "${YML}" \ -o "${RENAMED_YML_TMP}" \ -l "${PATH_ENA_RAW_DATA}" \ diff --git a/utils/create-ro-crate.py b/utils/create-ro-crate.py new file mode 100644 index 00000000..d0326798 --- /dev/null +++ b/utils/create-ro-crate.py @@ -0,0 +1,387 @@ +#! /usr/bin/env python3 + +desc = """ +Build a MetaGOflow Data Products ro-crate from a YAML configuration. + +Invoke +$ create-ro-crate.py + +where: + target_directory is the toplevel output directory of MetaGOflow + Note that the name of the directory cannot have a "." in it! + yaml_configuration is a YAML file of metadata specific to this ro-crate + a template is here: + https://raw.githubusercontent.com/emo-bon/MetaGOflow-Data-Products-RO-Crate/main/ro-crate-config.yaml + +e.g. + +$ create-ro-crate.py HWLTKDRXY-UDI210 config.yml + +This script expects to be pointed to directory of MetaGOflow output. + +When invoked, the MetaGOflow run_wf.sh script writes all output to a directory specified by +the "-d" parameter: + + $ run_wf.sh -n green -d HWLTKDRXY-UDI210 -f input_data/${DATA_FORWARD} -r input_data/${DATA_REVERSE} + + $ tree -1 + HWLTKDRXY-UDI210 + β”œβ”€β”€ prov + β”œβ”€β”€ results + β”œβ”€β”€ green.yml + └── tmp + + 3 directories, 1 file + +Cymon J. Cox, Feb '23 +""" + +import os +import argparse +import textwrap +import sys +import yaml +import json +import datetime +import base64 +import requests +import tempfile +import shutil +import glob +import subprocess +import logging as log + +#This is the workflow YAML file, the prefix is the "-n" parameter of the +#"run_wf.sh" script: +yaml_file = "{run_parameter}.yml" +#InterProScan file(s) have to be dealt with separately until the wf is fixed +interproscan_file = "{prefix}.merged_CDS.I5.tsv.gz" +yaml_parameters = ["datePublished", "prefix", "run_parameter", + "ena_accession_raw_data", "metagoflow_version", "missing_files"] + +mandatory_files = [ + "fastp.html", + "final.contigs.fa", + "RNA-counts", + "functional-annotation/stats/go.stats", + "functional-annotation/stats/interproscan.stats", + "functional-annotation/stats/ko.stats", + "functional-annotation/stats/orf.stats", + "functional-annotation/stats/pfam.stats", + "taxonomy-summary/LSU/krona.html", + "taxonomy-summary/SSU/krona.html", + "functional-annotation/{prefix}.merged.hmm.tsv.gz", + "functional-annotation/{prefix}.merged.summary.go", + "functional-annotation/{prefix}.merged.summary.go_slim", + "functional-annotation/{prefix}.merged.summary.ips", + "functional-annotation/{prefix}.merged.summary.ko", + "functional-annotation/{prefix}.merged.summary.pfam", + "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq.gz", + "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq_hdf5.biom", + "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq_json.biom", + "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq.tsv", + "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq.txt", + "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq.gz", + "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq_hdf5.biom", + "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq_json.biom", + "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq.tsv", + "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq.txt" + ] + +YAML_ERROR = """ +Cannot find the run YAML file. Bailing... + +If you invoked run_wf.sh like this, then the YAML configuration file will be +named "green.yml in the "HWLTKDRXY.UDI210" directory: + + $ run_wf.sh -n green -d HWLTKDRXY.UDI210 \ + -f input_data/${DATA_FORWARD} \ + -r input_data/${DATA_REVERSE} + +Configure the "run_parameter" with "-n" parameter value in the config.yml file: +"run_parameter": "green" +""" + +def writeHTMLpreview(tmpdirname): + """Write the HTML preview file using rochtml- + https://www.npmjs.com/package/ro-crate-html + """ + rochtml_path = shutil.which("rochtml") + if not rochtml_path: + log.info("HTML preview file cannot be written due to missing executable (rochtml)") + else: + cmd = "%s %s" % (rochtml_path, os.path.join(tmpdirname, "ro-crate-metadata.json")) + child = subprocess.Popen(str(cmd), stdout=subprocess.PIPE, + stderr=subprocess.PIPE, shell=True) + stdoutdata, stderrdata = child.communicate() + return_code = child.returncode + if return_code != 0: + log.error("Error whilst trying write HTML file") + log.error("Stderr: %s " % stderrdata) + log.error("Command: %s" % cmd) + log.error("Return code: %s" % return_code) + log.error("Bailing...") + sys.exit() + else: + log.info("Written HTML preview file") + +def joinInterProScanOutputFiles(target_directory, conf): + """IPS outputs one, or many, files (sigh) + + {prefix}.merged_CDS.I5.tsv.gz + or + DBB.merged_CDS.I5_00{1-9}.tsv.gz + + An issue has been raised to fix the workflow, but for the + time being we are going to cat them here + """ + log.info("Cat'ing the IPS chunk files... (this could take some time...)") + s = "{prefix}.merged_CDS.I5*tsv.gz".format(**conf) + path = os.path.join(target_directory, "results", "functional-annotation", s) + r = glob.glob(path) + if len(r) < 2: + log.error("Unable to locate 2 or more InterProScan files") + log.error("They should be of the form: {prefix}.merged_CDS.I5_00{1-9}.tsv.gz") + log.error("Bailing...") + sys.exit() + #cat the chunks together + outfile = os.path.join(target_directory, "results", "functional-annotation", + "{prefix}.merged_CDS.I5.tsv.gz".format(**conf)) + cmd = "cat %s > %s" % (" ".join(r), outfile) + child = subprocess.Popen(str(cmd), stdout=subprocess.PIPE, + stderr=subprocess.PIPE, shell=True) + stdoutdata, stderrdata = child.communicate() + return_code = child.returncode + if return_code != 0: + log.error("Error whilst trying to concatenate IPS files") + log.debug("Stderr: %s " % stderrdata) + log.debug("Files = %s" % r) + log.debug("Command: %s" % cmd) + log.debug("Return code: %s" % return_code) + log.error("Bailing...") + sys.exit() + +def sequence_categorisation_stanzas(target_directory, template): + """Glob the sequence_categorisation directory and build a stanza for each + zipped data file + + Return updated template, and list of sequence category filenames + """ + search = os.path.join(target_directory, "results", "sequence-categorisation", "*.gz") + seq_cat_paths = glob.glob(search) + seq_cat_files = [os.path.split(f)[1] for f in seq_cat_paths] + #Sequence-categorisation stanza + for i, stanza in enumerate(template["@graph"]): + if stanza["@id"] == "sequence-categorisation/": + stanza["hasPart"] = [dict([("@id", fn)]) for fn in + seq_cat_files] + sq_index = i + break + + seq_cat_files.reverse() + for fn in seq_cat_files: + d = dict([("@id", fn), ("@type", "File"), + ("encodingFormat", "application/zip")]) + template["@graph"].insert(sq_index+1, d) + return template, seq_cat_files + +def main(target_directory, yaml_config, debug): + + #Logging + if debug: + log_level = log.DEBUG + else: + log_level = log.INFO + log.basicConfig(format='\t%(levelname)s: %(message)s', level=log_level) + + #Check the data directory name + data_dir = os.path.split(target_directory)[1] + if "." in data_dir: + log.error(f"The target data directory ({data_dir}) cannot have a '.' period in it!") + log.error("Change it to '-' and try again") + log.error("Bailing...") + sys.exit() + + #Read the YAML configuration + if not os.path.exists(yaml_config): + log.error(f"YAML configuration file does not exist at {yaml_config}") + log.error("Bailing...") + sys.exit() + with open(yaml_config, "r") as f: + conf = yaml.safe_load(f) + #Check yaml parameters are formated correctly, but not necessarily sane + for param in yaml_parameters: + log.debug("Config paramater: %s" % conf[param]) + if param == "datePublished": + if conf[param] == "None": + #No specified date, delete from conf + #Its absence will trigger formatting + #with today's date + del conf[param] + continue + else: + if not isinstance(conf[param], str): + log.error("'dataPublished' should either be a string or 'None'. Bailing...") + sys.exit() + try: + datetime.datetime.fromisoformat(conf[param]) + except ValueError: + log.error(f"'datePublished' must conform to ISO 8601: {param}") + log.error("Bailing...") + sys.exit() + elif param == "missing_files": + if not param in conf: + continue + else: + for filename in conf[param]: + if not isinstance(filename, str): + log.error(f"Parameter '{filename}' in 'missing_files' list in YAML file must be a string.") + log.error("Bailing...") + sys.exit() + else: + if not conf[param] or not isinstance(conf[param], str): + log.error(f"Parameter '{param}' in YAML file must be a string.") + log.error("Bailing...") + sys.exit() + + #Check all files are present + + #The workflow run YAML - lives in the toplevel dir not /results + filename = yaml_file.format(**conf) + path = os.path.join(target_directory, filename) + if not os.path.exists(path): + log.error(YAML_ERROR) + sys.exit() + + #format the filepaths: + filepaths = [f.format(**conf) for f in mandatory_files] + #The fixed file paths + for filepath in filepaths: + log.debug(f"File path: {filepath}") + path = os.path.join(target_directory, "results", filepath) + if not os.path.exists(path): + if "missing_files" in conf: + if os.path.split(filepath)[1] in conf["missing_files"]: + #This file is known to be missing, ignoring + log.info("Ignoring specified missing file: %s" % + os.path.split(filepath)[1]) + filepaths.remove(filepath) + continue + log.error("Could not find the mandatory file '%s' at the following path: %s" % + (filepath, path)) + log.error("Consider adding it to the 'missing_files' list in the YAML configuration.") + log.error("Bailing...") + sys.exit() + + ### if the IPS files are split, join them + ipsf = os.path.join("functional-annotation", + "{prefix}.merged_CDS.I5.tsv.gz".format(**conf)) + ipsf_path = os.path.join(target_directory, "results", ipsf) + if not os.path.exists(ipsf_path): + ### deal with split DBB.merged_CDS.I5_001.tsv.gz files + joinInterProScanOutputFiles(target_directory, conf) + filepaths.append(ipsf) + + log.info("Data look good...") + + #Let's deal with the JSON metadata file + # Grab the template from Github + # https://stackoverflow.com/questions/38491722/reading-a-github-file-using-python-returns-html-tags + url = "https://raw.githubusercontent.com/emo-bon/MetaGOflow-Data-Products-RO-Crate/main/ro-crate-metadata.json-template" + req = requests.get(url) + if req.status_code == requests.codes.ok: + template = req.json() + else: + log.error("Unable to download the metadata.json file from Github") + log.error(f"Check {url}") + log.error("Bailing...") + sys.exit() + + #Metadata template on disk + #metadata_json_template = "ro-crate-metadata.json-template" + #with open(metadata_json_template, "r") as f: + # template = json.load(f) + + log.info("Writing ro-crate-metadata.json...") + #Deal with the ./ dataset stanza separately + #"accession_number" + template["@graph"][1]["name"] = template["@graph"][1]["name"].format(**conf) + template["@graph"][1]["description"] = template["@graph"][1]["description"].format(**conf) + #"datePublished" + if "datePublished" in conf: + template["@graph"][1]["datePublished"] = template["@graph"][1]["datePublished"].format(**conf) + else: + template["@graph"][1]["datePublished"] = datetime.datetime.now().strftime('%Y-%m-%d') + + # deal with sequence_categorisation separately + template, seq_cat_files = sequence_categorisation_stanzas(target_directory, template) + # add seq cat files to the filepaths + for scf in seq_cat_files: + filepaths.append(os.path.join("sequence-categorisation", scf)) + ### deal with the rest + for section in template["@graph"]: + section["@id"] = section["@id"].format(**conf) + if "hasPart" in section: + for entry in section["hasPart"]: + entry["@id"] = entry["@id"].format(**conf) + #Write the json metadata file: + metadata_json_formatted = json.dumps(template, indent=4) + + #Debug to disk + #with open("testing-ro-crate-metadata.json", "w") as outfile: + # outfile.write(metadata_json_formatted) + #sys.exit() + log.debug("%s" % metadata_json_formatted) + + #OK, all's good, let's build the RO-Crate + log.info("Copying data files...") + with tempfile.TemporaryDirectory() as tmpdirname: + #Deal with the YAML file + yf = yaml_file.format(**conf) + source = os.path.join(target_directory, yf) + shutil.copy(source, os.path.join(tmpdirname, yf)) + + #Build the ro-crate dir structure + output_dirs = ["functional-annotation/stats", "sequence-categorisation", + "taxonomy-summary/LSU", "taxonomy-summary/SSU"] + for d in output_dirs: + os.makedirs(os.path.join(tmpdirname, d)) + #Loop over results files and sequence categorisation files + for fp in filepaths: + source = os.path.join(target_directory, "results", fp) + log.debug("source = %s" % source) + log.debug("dest = %s" % os.path.join(tmpdirname, fp)) + shutil.copy(source, os.path.join(tmpdirname, fp)) + + #Write the json metadata file: + with open(os.path.join(tmpdirname, "ro-crate-metadata.json"), "w") as outfile: + outfile.write(metadata_json_formatted) + + #Write the HTML preview file + writeHTMLpreview(tmpdirname) + + #Zip it up: + log.info("Zipping data to ro-crate... (this could take some time...)") + ro_crate_name = "%s-ro-crate" % os.path.split(target_directory)[1] + shutil.make_archive(ro_crate_name, "zip", tmpdirname) + log.info("done") + +if __name__ == "__main__": + + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent(desc), + ) + parser.add_argument("target_directory", + help="Name of target directory containing MetaGOflow" +\ + "output" + ) + parser.add_argument("yaml_config", + help="Name of YAML config file for building RO-Crate" + ) + parser.add_argument('-d', '--debug', + action='store_true', + help="DEBUG logging") + args = parser.parse_args() + main(args.target_directory, args.yaml_config, args.debug) + diff --git a/create_yml.py b/utils/create_yml.py similarity index 100% rename from create_yml.py rename to utils/create_yml.py From 36e80fbe7b824da98d077aadb219b829a3bf9c4c Mon Sep 17 00:00:00 2001 From: hariszaf Date: Wed, 22 Mar 2023 17:59:34 +0100 Subject: [PATCH 02/26] software versions file --- software_versions.tsv | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 software_versions.tsv diff --git a/software_versions.tsv b/software_versions.tsv new file mode 100644 index 00000000..93e780ae --- /dev/null +++ b/software_versions.tsv @@ -0,0 +1,23 @@ +resource type description version step in metaGOflow official_url Docker pull command +fetch_tool software Allows to download data from ENA 1 - https://github.com/EBI-Metagenomics/fetch_tool hariszaf/fetch-tool:latest +debian_slim OS Debian is a Linux distribution that's composed entirely of free and open-source software 11.5 taxonomy inventory https://www.debian.org/releases/ debian:stable-slim +fastp software 0.20.0 quality control https://github.com/OpenGene/fastp microbiomeinformatics/pipeline-v5.fastp:0.20.0 +easel software computational analysis of biological sequences using probabilistic models. Easel is used by HMMER, the profile hidden Markov model software that underlies several protein and DNA sequence family databases such as Pfam, and by Infernal, 0.45h taxonomy inventory https://github.com/EddyRivasLab/easel microbiomeinformatics/pipeline-v5.easel:v0.45h +python3 programming language a high-level, general-purpose programming language 3.3 - https://www.python.org microbiomeinformatics/pipeline-v5.python3:v3.1 +python2 programming language a high-level, general-purpose programming language 2.7.10 - https://www.python.org microbiomeinformatics/pipeline-v5.python2:v1 +bash-scripts script set of stand-alone scripts for several tasks 1.3 taxonomy inventory https://hub.docker.com/r/microbiomeinformatics/pipeline-v5.bash-scripts microbiomeinformatics/pipeline-v5.bash-scripts:v1.3 +cmsearch software earch CM(s) against a nucleotide sequence database, using profile HMM(s) to prefilter the database. 1.1.2 taxonomy inventory https://github.com/EddyRivasLab/infernal microbiomeinformatics/pipeline-v5.cmsearch:v1.1.2 +cmsearch-deoverlap software convert cmsearch output 0.02 taxonomy inventory https://github.com/nawrockie/cmsearch_tblout_deoverlap microbiomeinformatics/pipeline-v5.cmsearch-deoverlap:v0.02 +alpine OS Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox. 3.7 taxonomy inventory, CGC https://www.alpinelinux.org alpine:3.7 +mapseq software a set of fast and accurate sequence read classification tools designed to assign taxonomy and OTU classifications to ribosomal RNA sequences. 1.2.3 taxonomy inventory https://github.com/jfmrod/MAPseq microbiomeinformatics/pipeline-v5.mapseq:v1.2.3 +mapseq2biom software convert mapseq output 1 taxonomy inventory https://github.com/EBI-Metagenomics/pipeline-v5/blob/develop/tools/RNA_prediction/mapseq2biom/mapseq2biom.pl microbiomeinformatics/pipeline-v5.mapseq2biom:v1.0 +KronaTools software Krona allows hierarchical data to be explored with zooming, multi-layered pie charts. 2.7.1 taxonomy inventory https://github.com/marbl/Krona microbiomeinformatics/pipeline-v5.krona:v2.7.1 +biom convert software Biom convert wrapper 2.1.6 taxonomy inventory https://pypi.org/project/biom-format/ microbiomeinformatics/pipeline-v5.biom-convert:v2.1.6 +FragGeneScan software FragGeneScan is an application for finding (fragmented) genes in short reads. 1.31 CGC https://github.com/EBI-Metagenomics/fraggenescan hariszaf/pipeline-v5.fraggenescan:v1.31.1 +Combined Gene Caller software script from the MGnify group for post-processing of FGS and Prodigal 1.0.1 CGC https://github.com/EBI-Metagenomics/pipeline-v5/tree/pipeline_5.1/tools/Combined_gene_caller microbiomeinformatics/pipeline-v5.protein-post-processing:v1.0.1 +eggNOG-mapper software EggNOG-mapper is a tool for fast functional annotation of novel sequences. It uses precomputed orthologous groups and phylogenies from the eggNOG database ( http://eggnog5.embl.de ) to transfer functional information from fine-grained orthologs only. 2.18 functional annotation https://github.com/eggnogdb/eggnog-mapper/ hariszaf/pipeline-v5.eggnog:v2.1.8 +interproscan database InterPro is a database which integrates together predictive information about proteins’ function from a number of partner resources, giving an overview of the families that a protein belongs to and the domains and sites it contains. 5.57-90.0 functional annotation https://github.com/ebi-pf-team/interproscan hariszaf/pipeline-v5.interproscan:v5.57-90.0 +hmmer software HMMER searches biological sequence databases for homologous sequences, using either single sequences or multiple sequence alignments as queries. HMMER implements a technology called "profile hidden Markov models" (profile HMMs). 3.2.1 functional annotation https://github.com/EddyRivasLab/hmmer microbiomeinformatics/pipeline-v5.hmmer:v3.2.1 +megahit software MEGAHIT is an ultra-fast and memory-efficient NGS assembler. It is optimized for metagenomes, but also works well on generic single genome assembly (small or mammalian size) and single-cell assembly. 1.2.9 assembly https://github.com/voutcn/megahit quay.io/biocontainers/megahit:1.2.9--h2e03b76_1 +mOTUs software The mOTU profiler is a computational tool that estimates relative taxonomic abundance of known and currently unknown microbial community members using metagenomic shotgun sequencing data. 2.5.1 taxonomy inventory https://github.com/motu-tool/mOTUs microbiomeinformatics/pipeline-v5.motus:v2.5.1 +GO-slim script Format IPS output 1.0.0 functional annotation https://github.com/EBI-Metagenomics/pipeline-v5/blob/master/tools/GO-slim/go_summary_pipeline-1.0.py microbiomeinformatics/pipeline-v5.go-summary:v1.0 \ No newline at end of file From 5c85a9726b2dc4140ed1d2fee89b05c253752ce2 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Wed, 22 Mar 2023 17:59:42 +0100 Subject: [PATCH 03/26] remove unecessary output files; init ro-crate script --- ...0b553d37e4255a3291393948f3e308bd88ed301.zip | Bin 141133 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 RunTimeResearchObject-f0b553d37e4255a3291393948f3e308bd88ed301.zip diff --git a/RunTimeResearchObject-f0b553d37e4255a3291393948f3e308bd88ed301.zip b/RunTimeResearchObject-f0b553d37e4255a3291393948f3e308bd88ed301.zip deleted file mode 100644 index bb6ad039eb9a5353085f025f581ceb72a9e2f665..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141133 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
KdC7~z{R5QX^HlFk5kSi`YtaL%W`ytW`S=}L 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 Date: Wed, 22 Mar 2023 17:59:56 +0100 Subject: [PATCH 04/26] remove unecessary output files; init ro-crate script --- ro-crate-io-metadata.json-template | 33 +++-- run_wf.sh | 45 +++--- slurm_run.sh | 3 +- utils/create-ro-crate.py | 131 ++++++++---------- utils/create_yml.py | 16 +-- .../Func_ann_and_post_proccessing-subwf.cwl | 2 - workflows/conditionals/qc.cwl | 8 +- workflows/conditionals/rna-prediction.cwl | 2 +- workflows/gos_wf.cwl | 25 ++-- 9 files changed, 123 insertions(+), 142 deletions(-) diff --git a/ro-crate-io-metadata.json-template b/ro-crate-io-metadata.json-template index b3d39d60..2e5cfe6c 100644 --- a/ro-crate-io-metadata.json-template +++ b/ro-crate-io-metadata.json-template @@ -1,4 +1,4 @@ -{ "@context": "https://w3id.org/ro/crate/1.1/context", +https://github.com/emo-bon/MetaGOflow/blob/eosc-life-gos/config.yml{ "@context": "https://w3id.org/ro/crate/1.1/context", "@graph": [ { "@id": "ro-crate-metadata.json", @@ -9,22 +9,22 @@ { "@id": "./", "@type": "Dataset", - "name" : "MetaGoFlow Results for ENA Run Accession Number {ena_accession_raw_data}", + "name" : "MetaGoFlow Results for ENA Run Accession Number {ena_accession_raw_data}", "description" : "RO-Crate for the MetaGOflow analysis EMO BON ENA Accession {ena_accession_raw_data} data ", - "datePublished": "{datePublished}", - "license": {"@id": "https://creativecommons.org/licenses/by/4.0/legalcode"}, - "publisher": {"@id": "https://ror.org/0038zss60"}, + "datePublished": "{datePublished}", + "license": {"@id": "https://creativecommons.org/licenses/by/4.0/legalcode"}, + "publisher": {"@id": "https://ror.org/0038zss60"}, "hasPart": [ - {"@id": "{ena_accession_raw_data}"}, - {"@id": "{metagoflow_version}"}, + {"@id": "{ena_accession_raw_data}"}, + {"@id": "{metagoflow_version}"}, {"@id": "{run_parameter}.yml"}, - {"@id": "fastp.html"}, + {"@id": "config.yml"}, + {"@id": "fastp.html"} {"@id": "final.contigs.fa"}, {"@id": "functional_annotation/"}, {"@id": "sequence-categorisation/"}, {"@id": "taxonomic-summary/"}, {"@id": "RNA-counts"} - ] }, { @@ -43,10 +43,10 @@ "url": "https://www.embrc.eu/about-us/contact-us" }, { - "@id": "https://creativecommons.org/licenses/by/4.0/legalcode", + "@id": "https://www.apache.org/licenses/LICENSE-2.0", "@type": "CreativeWork", - "identifier": "https://creativecommons.org/licenses/by/4.0/legalcode", - "name": "Creative Commons (CC-BY 4.0)" + "identifier": "https://www.apache.org/licenses/LICENSE-2.0", + "name": "Apache License 2.0" }, { "@id": "{ena_accession_raw_data}", @@ -65,10 +65,17 @@ { "@id": "{run_parameter}.yml", "@type": "File", - "name": "MetaGOflow YAML configuration file", + "name": "The YAML configuration file MetaGOflow builds", "description": "YAML configuration file for execution of MetaGOflow workflow.", "encodingFormat": "text/yaml" }, + { + "@id": "config.yml", + "@type": "File", + "name": "MetaGOflow configuration file", + "description": "The configuration file through which the user sets the values of the metaGOflow parameters.", + "encodingFormat": "text/yaml" + }, { "@id": "fastp.html", "@type": "File", diff --git a/run_wf.sh b/run_wf.sh index ef9de08a..8f6ed33f 100755 --- a/run_wf.sh +++ b/run_wf.sh @@ -1,5 +1,7 @@ #!/bin/bash +METAGOFLOW_VERSION="https://github.com/emo-bon/MetaGOflow/releases/tag/v1.0.0" + # default values # SCRIPT_PATH=$(realpath "$0") PIPELINE_DIR=$(dirname "${SCRIPT_PATH}") @@ -29,6 +31,7 @@ Script arguments. " } +# [TODO] Consider adding a -t argument to run using toil. while getopts :y:f:r:e:u:k:c:d:m:n:l:sph option; do case "${option}" in y) YML=${OPTARG} ;; @@ -82,10 +85,9 @@ _check_mandatory() { } _check_reads() { - #check forward and reverse reads both present - #check if single reads then no other readsgiven - - # BASH SYNTAX: + # check forward and reverse reads both present + # check if single reads then no other readsgiven + # BASH SYNTAX: # to check if a variable has value: # [ -z "$var" ] && echo "Empty" @@ -107,8 +109,6 @@ _check_mandatory "$NAME" "-n" _check_mandatory "$RUN_DIR" "-d" _check_reads "$FORWARD_READS" "$REVERSE_READS" - - # ----------------------------- environment & variables ----------------------------- # # load required environments and packages before running @@ -128,10 +128,9 @@ export OUT_DIR_FINAL=${OUT_DIR}/results export PROV_DIR=${OUT_DIR}/prov export CACHE_DIR=${OUT_DIR}/cache mkdir -p "${OUT_DIR_FINAL}" "${TMPDIR}" "${PROV_DIR}" - #"${CACHE_DIR}" ${JOB_TOIL_FOLDER}" "${LOG_DIR}" -export RENAMED_YML_TMP=${RUN_DIR}/"${NAME}"_temp.yml -export RENAMED_YML=${RUN_DIR}/"${NAME}".yml +export EXTENDED_CONFIG_YAML_TMP=${RUN_DIR}/"${NAME}"_temp.yml +export EXTENDED_CONFIG_YAML=${RUN_DIR}/"${NAME}".yml # Get study id in case of ENA fetch tool if [[ $ENA_RUN_ID != "" ]]; @@ -161,15 +160,14 @@ then fi - # ----------------------------- prepare yml file ----------------------------- # echo "Writing yaml file" # DO NOT leave spaces after "\" in the end of a line -python3 utils/create_yml.py \ +python3.10 utils/create_yml.py \ -y "${YML}" \ - -o "${RENAMED_YML_TMP}" \ + -o "${EXTENDED_CONFIG_YAML_TMP}" \ -l "${PATH_ENA_RAW_DATA}" \ -f "${PIPELINE_DIR}/${FORWARD_READS}" \ -r "${PIPELINE_DIR}/${REVERSE_READS}" \ @@ -178,10 +176,10 @@ python3 utils/create_yml.py \ -e "${ENA_RUN_ID}" mv eosc-wf.yml ${RUN_DIR}/ -cat ${RUN_DIR}/eosc-wf.yml ${RENAMED_YML_TMP} > ${RENAMED_YML} -rm ${RENAMED_YML_TMP} +cat ${RUN_DIR}/eosc-wf.yml ${EXTENDED_CONFIG_YAML_TMP} > ${EXTENDED_CONFIG_YAML} +rm ${EXTENDED_CONFIG_YAML_TMP} rm ${RUN_DIR}/eosc-wf.yml - +cp config.yml ${RUN_DIR}/ # ----------------------------- running pipeline ----------------------------- # @@ -203,24 +201,27 @@ TOIL_PARAMS+=( --retryCount 2 --logDebug "$CWL" - "$RENAMED_YML" + "$EXTENDED_CONFIG_YAML" ) -# Toil parameters documentation +# Toil parameters documentation - just for your information # --disableChaining Disables chaining of jobs (chaining uses one job's resource allocation for its successor job if possible). # --preserve-entire-environment Need to propagate the env vars for Singularity, etc., into the HPC jobs # --disableProgress Disables the progress bar shown when standard error is a terminal. # --retryCount Number of times to retry a failing job before giving up and labeling job failed. default=1 # --disableCaching Disables caching in the file store. This flag must be set to use a batch system that does not support caching such as Grid Engine, Parasol, LSF, or Slurm. - -# # COMMENT IN TO RUN THE TOIL VERSION +# COMMENT IN TO RUN THE TOIL VERSION and MUTE the cwltool case in line 222. # echo "toil-cwl-runner" "${TOIL_PARAMS[@]}" # toil-cwl-runner "${TOIL_PARAMS[@]}" -cwltool --debug ${SINGULARITY} --provenance ${PROV_DIR} --outdir ${OUT_DIR_FINAL} ${CWL} ${RENAMED_YML} +Run the metaGOflow workflow using cwltool +cwltool --debug ${SINGULARITY} --provenance ${PROV_DIR} --outdir ${OUT_DIR_FINAL} ${CWL} ${EXTENDED_CONFIG_YAML} -# --cachedir ${CACHE_DIR} -# --leave-tmpdir --leave-outputs +# Build RO-crate +if [ -z "$ENA_RUN_ID" ]; then + ENA_RUN_ID="None" +fi +# python3.10 utils/create-ro-crate.py ${OUT_DIR} ${METAGOFLOW_VERSION} ${NAME} ${ENA_RUN_ID} diff --git a/slurm_run.sh b/slurm_run.sh index ce4e2603..13557766 100755 --- a/slurm_run.sh +++ b/slurm_run.sh @@ -16,8 +16,7 @@ module load python/3.7.8 module load singularity/3.7.1 # Run the wf -#./run_wf.sh -f test_input/wgs-paired-SRR1620013_1.fastq.gz -r test_input/wgs-paired-SRR1620013_2.fastq.gz -n wgs-SRR1620013 -d MOTUS -s -./run_wf.sh -f test_input/DBB_AABVOSDA_1_1_HMNJKDSX3.UDI256_clean.fastq.gz -r test_input/DBB_AABVOSDA_1_2_HMNJKDSX3.UDI256_clean.fastq.gz -n water-sample-DBB_AABVOSDA_1_2_HMNJKDSX3.UDI256 -d WATER_SAMPLE_TAX_FAT -s +./run_wf.sh -f test_input/wgs-paired-SRR1620013_1.fastq.gz -r test_input/wgs-paired-SRR1620013_2.fastq.gz -n dev_dataset -d DEV_DATASET -s # ./run_wf.sh -e ERR855786 -d TEST_SIMPLIFIED_PFAM -n ERR855786 -s diff --git a/utils/create-ro-crate.py b/utils/create-ro-crate.py index d0326798..e470a71a 100644 --- a/utils/create-ro-crate.py +++ b/utils/create-ro-crate.py @@ -1,23 +1,21 @@ #! /usr/bin/env python3 -desc = """ -Build a MetaGOflow Data Products ro-crate from a YAML configuration. - -Invoke -$ create-ro-crate.py +""" +If you invoked run_wf.sh like this, then the YAML configuration file will be +named "green.yml in the "HWLTKDRXY.UDI210" directory: -where: - target_directory is the toplevel output directory of MetaGOflow - Note that the name of the directory cannot have a "." in it! - yaml_configuration is a YAML file of metadata specific to this ro-crate - a template is here: - https://raw.githubusercontent.com/emo-bon/MetaGOflow-Data-Products-RO-Crate/main/ro-crate-config.yaml + $ run_wf.sh -n green -d HWLTKDRXY.UDI210 \ + -f input_data/${DATA_FORWARD} \ + -r input_data/${DATA_REVERSE} -e.g. +run_parameter it the "-n" value in the config.yml file: +""" -$ create-ro-crate.py HWLTKDRXY-UDI210 config.yml -This script expects to be pointed to directory of MetaGOflow output. +desc = """ +Build a MetaGOflow Data Products ro-crate. +This script is based on Cymon's J. Cox script you can find here: +https://github.com/emo-bon/MetaGOflow-Data-Products-RO-Crate/blob/main/create-ro-crate.py When invoked, the MetaGOflow run_wf.sh script writes all output to a directory specified by the "-d" parameter: @@ -32,8 +30,6 @@ └── tmp 3 directories, 1 file - -Cymon J. Cox, Feb '23 """ import os @@ -51,13 +47,14 @@ import subprocess import logging as log -#This is the workflow YAML file, the prefix is the "-n" parameter of the -#"run_wf.sh" script: +#This is the workflow YAML file, the prefix is the "-n" parameter of the "run_wf.sh" script: yaml_file = "{run_parameter}.yml" + #InterProScan file(s) have to be dealt with separately until the wf is fixed interproscan_file = "{prefix}.merged_CDS.I5.tsv.gz" -yaml_parameters = ["datePublished", "prefix", "run_parameter", - "ena_accession_raw_data", "metagoflow_version", "missing_files"] +yaml_parameters = ["prefix", + "run_parameter", + "ena_accession_raw_data", "metagoflow_version", "missing_files"] mandatory_files = [ "fastp.html", @@ -88,18 +85,10 @@ "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq.txt" ] -YAML_ERROR = """ -Cannot find the run YAML file. Bailing... -If you invoked run_wf.sh like this, then the YAML configuration file will be -named "green.yml in the "HWLTKDRXY.UDI210" directory: - $ run_wf.sh -n green -d HWLTKDRXY.UDI210 \ - -f input_data/${DATA_FORWARD} \ - -r input_data/${DATA_REVERSE} - -Configure the "run_parameter" with "-n" parameter value in the config.yml file: -"run_parameter": "green" +VALIDATION_ERROR = """ +The RO-crate returned fails the validation test. """ def writeHTMLpreview(tmpdirname): @@ -185,7 +174,7 @@ def sequence_categorisation_stanzas(target_directory, template): template["@graph"].insert(sq_index+1, d) return template, seq_cat_files -def main(target_directory, yaml_config, debug): +def main(target_directory, metagoflow_version, run_parameter, ena_run_accession_id, debug): #Logging if debug: @@ -193,6 +182,7 @@ def main(target_directory, yaml_config, debug): else: log_level = log.INFO log.basicConfig(format='\t%(levelname)s: %(message)s', level=log_level) + #Check the data directory name data_dir = os.path.split(target_directory)[1] @@ -203,33 +193,27 @@ def main(target_directory, yaml_config, debug): sys.exit() #Read the YAML configuration - if not os.path.exists(yaml_config): - log.error(f"YAML configuration file does not exist at {yaml_config}") - log.error("Bailing...") - sys.exit() - with open(yaml_config, "r") as f: + user_yaml_config = "config.yml" + with open(user_yaml_config, "r") as f: conf = yaml.safe_load(f) + + + conf["dataPublished"] = datetime.datetime.now().strftime('%Y-%m-%d') + + if ena_run_accession_id == "None": + print("hello friend") + + + sys.exit(0) + + + + #Check yaml parameters are formated correctly, but not necessarily sane for param in yaml_parameters: log.debug("Config paramater: %s" % conf[param]) - if param == "datePublished": - if conf[param] == "None": - #No specified date, delete from conf - #Its absence will trigger formatting - #with today's date - del conf[param] - continue - else: - if not isinstance(conf[param], str): - log.error("'dataPublished' should either be a string or 'None'. Bailing...") - sys.exit() - try: - datetime.datetime.fromisoformat(conf[param]) - except ValueError: - log.error(f"'datePublished' must conform to ISO 8601: {param}") - log.error("Bailing...") - sys.exit() - elif param == "missing_files": + + if param == "missing_files": if not param in conf: continue else: @@ -244,14 +228,13 @@ def main(target_directory, yaml_config, debug): log.error("Bailing...") sys.exit() + + #Check all files are present + # #The workflow run YAML - lives in the toplevel dir not /results + # filename = yaml_file.format(**conf) + # path = os.path.join(target_directory, filename) - #The workflow run YAML - lives in the toplevel dir not /results - filename = yaml_file.format(**conf) - path = os.path.join(target_directory, filename) - if not os.path.exists(path): - log.error(YAML_ERROR) - sys.exit() #format the filepaths: filepaths = [f.format(**conf) for f in mandatory_files] @@ -297,21 +280,17 @@ def main(target_directory, yaml_config, debug): log.error("Bailing...") sys.exit() - #Metadata template on disk - #metadata_json_template = "ro-crate-metadata.json-template" - #with open(metadata_json_template, "r") as f: - # template = json.load(f) log.info("Writing ro-crate-metadata.json...") + + #Deal with the ./ dataset stanza separately #"accession_number" template["@graph"][1]["name"] = template["@graph"][1]["name"].format(**conf) template["@graph"][1]["description"] = template["@graph"][1]["description"].format(**conf) #"datePublished" - if "datePublished" in conf: - template["@graph"][1]["datePublished"] = template["@graph"][1]["datePublished"].format(**conf) - else: - template["@graph"][1]["datePublished"] = datetime.datetime.now().strftime('%Y-%m-%d') + template["@graph"][1]["datePublished"] = template["@graph"][1]["datePublished"].format(**conf) + # deal with sequence_categorisation separately template, seq_cat_files = sequence_categorisation_stanzas(target_directory, template) @@ -376,12 +355,22 @@ def main(target_directory, yaml_config, debug): help="Name of target directory containing MetaGOflow" +\ "output" ) - parser.add_argument("yaml_config", - help="Name of YAML config file for building RO-Crate" + parser.add_argument("metagoflow_version", + help="URL pointing to the metaGOflow version used" + ) + parser.add_argument("run_parameter", + help="Name of run and prefix to output files." + ) + parser.add_argument("ena_run_accession_id", + help="Run accession id in ENA." ) parser.add_argument('-d', '--debug', action='store_true', help="DEBUG logging") + args = parser.parse_args() - main(args.target_directory, args.yaml_config, args.debug) + + + + main(args.target_directory, args.metagoflow_version, args.run_parameter, args.ena_run_accession_id, args.debug) diff --git a/utils/create_yml.py b/utils/create_yml.py index 52ce221e..f0939742 100755 --- a/utils/create_yml.py +++ b/utils/create_yml.py @@ -5,7 +5,6 @@ import os import yaml as yml - db_fields = [ "ssu_db", "lsu_db", @@ -90,13 +89,6 @@ def db_dir(db_path, tools_path, yaml_path): help="The accession number in ENA of the run to be analysed", required=False ) - # parser.add_argument( - # "-s", - # "--study_accession_number", - # dest="study_accession_number", - # help="The accession number in ENA of the study of the run", - # required=False - # ) parser.add_argument( "-p", "--private", @@ -126,10 +118,6 @@ def db_dir(db_path, tools_path, yaml_path): # load template yml file and append database path template_yml = db_dir(args.db_dir, args.tools_dir, args.yml) - # paired_reads = [args.fr.split("/")[-1].split(".fastq.gz")[0], args.rr.split("/")[-1].split(".fastq.gz")[0]] - # paired_reads_names = '"' + paired_reads[0] + '", "' + paired_reads[1] + '"' - - # Building the .yml file with open(args.output, "w") as output_yml: @@ -137,7 +125,9 @@ def db_dir(db_path, tools_path, yaml_path): yaml.dump(template_yml, output_yml) - with open("config.yml", "r") as config_yml: + cwd = os.getcwd() + config_file = os.path.join(cwd, "config.yml") + with open(config_file, "r") as config_yml: config = yml.safe_load(config_yml) diff --git a/workflows/conditionals/Func_ann_and_post_proccessing-subwf.cwl b/workflows/conditionals/Func_ann_and_post_proccessing-subwf.cwl index 8e57533d..74a142c6 100644 --- a/workflows/conditionals/Func_ann_and_post_proccessing-subwf.cwl +++ b/workflows/conditionals/Func_ann_and_post_proccessing-subwf.cwl @@ -96,7 +96,6 @@ steps: - summary_ips - go_summary - go_summary_slim - - chunked_tsvs # << move to functional annotation >> move_to_functional_annotation_folder: @@ -109,7 +108,6 @@ steps: - post_processing/summary_pfam - post_processing/go_summary - post_processing/go_summary_slim - - post_processing/chunked_tsvs linkMerge: merge_flattened dir_name: { default: functional-annotation } out: [ out ] diff --git a/workflows/conditionals/qc.cwl b/workflows/conditionals/qc.cwl index 77833ceb..48605f21 100644 --- a/workflows/conditionals/qc.cwl +++ b/workflows/conditionals/qc.cwl @@ -40,6 +40,10 @@ outputs: type: Directory? outputSource: m_qc-stats/output_dir + m_qc_summary: + type: Directory? + outputSource: m_qc-stats/summary_out + # this is the filtered merged seq file m_filtered_fasta: type: File @@ -49,7 +53,7 @@ outputs: pickValue: first_non_null # outputs for each of the 2 trimmed seq file - fastp_filtering_json: + fastp_filtering_html: type: File? outputSource: fastp_trim_and_overlap/html_report @@ -180,7 +184,7 @@ steps: QCed_reads: m_length_filter/filtered_file sequence_count: m_count_processed_reads/count out_dir_name: qc_stats_folder_for_merged - out: [ output_dir ] + out: [ output_dir, summary_out ] clean_merged_fasta_headers: diff --git a/workflows/conditionals/rna-prediction.cwl b/workflows/conditionals/rna-prediction.cwl index eea137bc..a6585816 100644 --- a/workflows/conditionals/rna-prediction.cwl +++ b/workflows/conditionals/rna-prediction.cwl @@ -134,7 +134,7 @@ steps: in: file_list: source: - - tax_chunking/chunked_by_size_files + # - tax_chunking/chunked_by_size_files - rna_prediction/compressed_rnas - other_ncrnas/ncrnas linkMerge: merge_flattened diff --git a/workflows/gos_wf.cwl b/workflows/gos_wf.cwl index ab120e87..fd54b9c1 100644 --- a/workflows/gos_wf.cwl +++ b/workflows/gos_wf.cwl @@ -169,13 +169,14 @@ steps: # Merged sequence file - m_qc_stats - m_filtered_fasta + - m_qc_summary # Trimmed PE files - qc-statistics - qc_summary - qc-status - input_files_hashsum_paired - - fastp_filtering_json + - fastp_filtering_html - filtered_fasta - motus_input @@ -380,24 +381,15 @@ steps: outputs: # QC FOR RNA PREDICTION # --------------------- - qc-statistics: - type: Directory[]? - outputSource: qc_and_merge/qc-statistics - pickValue: all_non_null qc_summary: type: File[]? outputSource: qc_and_merge/qc_summary pickValue: all_non_null - hashsum_paired: - type: File[]? - outputSource: qc_and_merge/input_files_hashsum_paired - pickValue: all_non_null - - fastp_filtering_json_report: + fastp_filtering_html_report: type: File? - outputSource: qc_and_merge/fastp_filtering_json + outputSource: qc_and_merge/fastp_filtering_html pickValue: all_non_null m_filtered_fasta: # this is the filtered merged seq file @@ -409,9 +401,9 @@ outputs: outputSource: qc_and_merge/filtered_fasta pickValue: all_non_null - m_qc_stats: - type: Directory? - outputSource: qc_and_merge/m_qc_stats + m_qc_summary: + type: File? + outputSource: qc_and_merge/m_qc_summary motus_input: type: File? @@ -488,4 +480,5 @@ $schemas: s:license: "https://www.apache.org/licenses/LICENSE-2.0" s:copyrightHolder: "European Marine Biological Resource Centre" -s:author: "Haris Zafeiropoulos" +s:author: "EMO BON team" +s:version: "v1.0.0" From 4f5e3571128485e8ab601e7833a359448c43f3bf Mon Sep 17 00:00:00 2001 From: hariszaf Date: Wed, 22 Mar 2023 18:30:49 +0100 Subject: [PATCH 05/26] minor edits --- workflows/gos_wf.cwl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/workflows/gos_wf.cwl b/workflows/gos_wf.cwl index fd54b9c1..f049e464 100644 --- a/workflows/gos_wf.cwl +++ b/workflows/gos_wf.cwl @@ -379,7 +379,8 @@ steps: - options outputs: - # QC FOR RNA PREDICTION + + # QUALITY CONTROL # --------------------- qc_summary: @@ -411,12 +412,14 @@ outputs: # mOTUs STEP # ---------------------- + motus: type: File outputSource: motus_taxonomy/motus # RNA PREDICTION STEP # ---------------------- + sequence-categorisation_folder: type: Directory? outputSource: rna_prediction/sequence_categorisation_folder From 08c62ccddf21832fe8016f5d147411489114248b Mon Sep 17 00:00:00 2001 From: hariszaf Date: Wed, 22 Mar 2023 21:27:38 +0200 Subject: [PATCH 06/26] fix summary qc --- run_wf.sh | 6 +++--- slurm_run.sh | 7 +++++-- workflows/conditionals/qc.cwl | 2 +- workflows/gos_wf.cwl | 5 ----- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/run_wf.sh b/run_wf.sh index 8f6ed33f..c6e94cd7 100755 --- a/run_wf.sh +++ b/run_wf.sh @@ -165,7 +165,7 @@ fi echo "Writing yaml file" # DO NOT leave spaces after "\" in the end of a line -python3.10 utils/create_yml.py \ +python utils/create_yml.py \ -y "${YML}" \ -o "${EXTENDED_CONFIG_YAML_TMP}" \ -l "${PATH_ENA_RAW_DATA}" \ @@ -216,7 +216,7 @@ TOIL_PARAMS+=( # toil-cwl-runner "${TOIL_PARAMS[@]}" -Run the metaGOflow workflow using cwltool +# Run the metaGOflow workflow using cwltool cwltool --debug ${SINGULARITY} --provenance ${PROV_DIR} --outdir ${OUT_DIR_FINAL} ${CWL} ${EXTENDED_CONFIG_YAML} @@ -224,4 +224,4 @@ cwltool --debug ${SINGULARITY} --provenance ${PROV_DIR} --outdir ${OUT_DIR_FINAL if [ -z "$ENA_RUN_ID" ]; then ENA_RUN_ID="None" fi -# python3.10 utils/create-ro-crate.py ${OUT_DIR} ${METAGOFLOW_VERSION} ${NAME} ${ENA_RUN_ID} +python utils/create-ro-crate.py ${OUT_DIR} ${METAGOFLOW_VERSION} ${NAME} ${ENA_RUN_ID} diff --git a/slurm_run.sh b/slurm_run.sh index 13557766..7e1c93da 100755 --- a/slurm_run.sh +++ b/slurm_run.sh @@ -8,8 +8,11 @@ #SBATCH --mail-user=haris.zafr@gmail.com #SBATCH --mail-type=ALL #SBATCH --requeue -#SBATCH --job-name="taxInv" -#SBATCH --output=tax_invent_fat_water.output +#SBATCH --job-name="rocr" +#SBATCH --output=rocrates.output + +# Deactivate conda if already there +conda deactivate # Load module module load python/3.7.8 diff --git a/workflows/conditionals/qc.cwl b/workflows/conditionals/qc.cwl index 48605f21..61948900 100644 --- a/workflows/conditionals/qc.cwl +++ b/workflows/conditionals/qc.cwl @@ -41,7 +41,7 @@ outputs: outputSource: m_qc-stats/output_dir m_qc_summary: - type: Directory? + type: File[]? outputSource: m_qc-stats/summary_out # this is the filtered merged seq file diff --git a/workflows/gos_wf.cwl b/workflows/gos_wf.cwl index 5b08f8ba..bc7a018d 100644 --- a/workflows/gos_wf.cwl +++ b/workflows/gos_wf.cwl @@ -64,16 +64,12 @@ inputs: doc: | metaGOflow will perform the functional annotation step - assemble: type: boolean default: false doc: | metaGOflow will perform the assembly step using MEGAHIT - # # Files to run partially the wf - # ncrna_tab_file: {type: File?} - # Pre-process overrepresentation_analysis: type: boolean @@ -115,7 +111,6 @@ inputs: doc: | fastp parameter setting the percentage of bases allowed to be unqualified (0~100). Default 40 means 40%. - min_length_required: type: int default: 100 From e88632d575b42dad73ef51932cd477c8851c9e03 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Thu, 23 Mar 2023 01:54:25 +0200 Subject: [PATCH 07/26] fix qc_summary output filenames --- workflows/conditionals/qc.cwl | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/workflows/conditionals/qc.cwl b/workflows/conditionals/qc.cwl index 39b09779..a0707d54 100644 --- a/workflows/conditionals/qc.cwl +++ b/workflows/conditionals/qc.cwl @@ -40,10 +40,6 @@ outputs: type: Directory? outputSource: m_qc-stats/output_dir - m_qc_summary: - type: File[]? - outputSource: m_qc-stats/summary_out - # this is the filtered merged seq file m_filtered_fasta: type: File @@ -52,6 +48,10 @@ outputs: - m_convert_trimmed_reads_to_fasta/fasta pickValue: first_non_null + m_qc_summary: + type: File + outputSource: m_length_filter/stats_summary_file + # outputs for each of the 2 trimmed seq file fastp_filtering_html: type: File? @@ -158,7 +158,6 @@ steps: in: seq_file: m_convert_trimmed_reads_to_fasta/fasta submitted_seq_count: count_submitted_reads/count - stats_file_name: {default: 'qc_summary'} min_length: min_length_required input_file_format: { default: 'fasta' } out: [ filtered_file, stats_summary_file ] @@ -193,8 +192,6 @@ steps: sequences: fastp_trim_and_overlap/merged_fastq out: [ sequences_with_cleaned_headers ] - - # WITH REPSECT TO EACH OF THE 2 TRIMMED SEQ FILES # ------------------------------------------------- @@ -221,12 +218,10 @@ steps: in: seq_file: convert_trimmed_reads_to_fasta/fasta submitted_seq_count: count_submitted_reads/count - stats_file_name: {default: 'qc_summary' } min_length: min_length_required input_file_format: { default: 'fasta' } out: [ filtered_file, stats_summary_file ] - count_processed_reads: run: ../../utils/count_fasta.cwl scatter: sequences From cfc54fd6bab0985078f4112b31869310572bb090 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Thu, 23 Mar 2023 01:54:56 +0200 Subject: [PATCH 08/26] fix qc_summary output filenames --- tools/qc-filtering/qc-filtering.cwl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/qc-filtering/qc-filtering.cwl b/tools/qc-filtering/qc-filtering.cwl index 6dd1a63d..d875ee33 100644 --- a/tools/qc-filtering/qc-filtering.cwl +++ b/tools/qc-filtering/qc-filtering.cwl @@ -30,12 +30,12 @@ inputs: doc: > Number of originally submitted sequences as in the user submitted FASTQ file - single end FASTQ or pair end merged FASTQ file. - stats_file_name: - type: string - default: stats_summary - label: 'Post QC stats output file name' - doc: > - Give a name for the file which will hold the stats after QC. + # stats_file_name: + # type: string + # default: stats_summary + # label: 'Post QC stats output file name' + # doc: > + # Give a name for the file which will hold the stats after QC. min_length: type: int default: 100 # For assemblies we need to set this in the input YAML to 500 @@ -56,13 +56,13 @@ outputs: label: Stats summary output file type: File outputBinding: - glob: $(inputs.stats_file_name) + glob: $(inputs.seq_file.nameroot).qc_summary arguments: - position: 2 valueFrom: $(inputs.seq_file.nameroot).fasta - position: 3 - valueFrom: $(inputs.stats_file_name) + valueFrom: $(inputs.seq_file.nameroot).qc_summary - position: 4 valueFrom: $(inputs.submitted_seq_count) - position: 5 From e4dc4588233fe21628b4a222b7a7632e599af99a Mon Sep 17 00:00:00 2001 From: hariszaf Date: Thu, 23 Mar 2023 01:55:38 +0200 Subject: [PATCH 09/26] remove prov output folder --- run_wf.sh | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/run_wf.sh b/run_wf.sh index c6e94cd7..ebacfee0 100755 --- a/run_wf.sh +++ b/run_wf.sh @@ -125,9 +125,8 @@ export TMPDIR=${RUN_DIR}/tmp export OUT_DIR=${RUN_DIR} export LOG_DIR=${OUT_DIR}/log-dir/${NAME} export OUT_DIR_FINAL=${OUT_DIR}/results -export PROV_DIR=${OUT_DIR}/prov export CACHE_DIR=${OUT_DIR}/cache -mkdir -p "${OUT_DIR_FINAL}" "${TMPDIR}" "${PROV_DIR}" +mkdir -p "${OUT_DIR_FINAL}" "${TMPDIR}" export EXTENDED_CONFIG_YAML_TMP=${RUN_DIR}/"${NAME}"_temp.yml export EXTENDED_CONFIG_YAML=${RUN_DIR}/"${NAME}".yml @@ -190,7 +189,6 @@ TOIL_PARAMS+=( --preserve-entire-environment --batchSystem slurm --disableChaining - # --provenance "${PROV_DIR}" --disableCaching --logFile "${LOG_DIR}/${NAME}.log" --jobStore "${JOB_TOIL_FOLDER}/${NAME}" @@ -215,10 +213,8 @@ TOIL_PARAMS+=( # echo "toil-cwl-runner" "${TOIL_PARAMS[@]}" # toil-cwl-runner "${TOIL_PARAMS[@]}" - # Run the metaGOflow workflow using cwltool -cwltool --debug ${SINGULARITY} --provenance ${PROV_DIR} --outdir ${OUT_DIR_FINAL} ${CWL} ${EXTENDED_CONFIG_YAML} - +cwltool --parallel ${SINGULARITY} --outdir ${OUT_DIR_FINAL} ${CWL} ${EXTENDED_CONFIG_YAML} # Build RO-crate if [ -z "$ENA_RUN_ID" ]; then From 121c57084477a4ac3bb197ed7e534f5e2b8a44f9 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Thu, 23 Mar 2023 01:56:23 +0200 Subject: [PATCH 10/26] all test cases --- slurm_run.sh | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/slurm_run.sh b/slurm_run.sh index 7e1c93da..c29387fd 100755 --- a/slurm_run.sh +++ b/slurm_run.sh @@ -8,8 +8,8 @@ #SBATCH --mail-user=haris.zafr@gmail.com #SBATCH --mail-type=ALL #SBATCH --requeue -#SBATCH --job-name="rocr" -#SBATCH --output=rocrates.output +#SBATCH --job-name="rocr-tax" +#SBATCH --output=rocrates_tax.output # Deactivate conda if already there conda deactivate @@ -18,10 +18,23 @@ conda deactivate module load python/3.7.8 module load singularity/3.7.1 -# Run the wf -./run_wf.sh -f test_input/wgs-paired-SRR1620013_1.fastq.gz -r test_input/wgs-paired-SRR1620013_2.fastq.gz -n dev_dataset -d DEV_DATASET -s +# Run the wf with mini dataset +./run_wf.sh -f test_input/wgs-paired-SRR1620013_1.fastq.gz -r test_input/wgs-paired-SRR1620013_2.fastq.gz -n mini_dataset -d MINI_DATASET -s + +# Run the wf with short dataset +# ./run_wf.sh -f test_input/test_1_fwd_HWLTKDRXY_600000.fastq.gz -r test_input/test_2_rev_HWLTKDRXY_600000.fastq.gz -n dev_dataset -d DEV_DATASET -s + +# To run the manuscript use cases: +# marine sediment +# ./run_wf.sh -f test_input/DBH_AAAIOSDA_1_1_HMNJKDSX3.UDI224_clean.fastq.gz -r test_input/DBH_AAAIOSDA_1_2_HMNJKDSX3.UDI224_clean.fastq.gz -n DBH_dataset -d marine_sediment_dbh -s + +# column water +# ./run_wf.sh -f test_input/DBB_AABVOSDA_1_1_HMNJKDSX3.UDI256_clean.fastq.gz -r test_input/DBB_AABVOSDA_1_2_HMNJKDSX3.UDI256_clean.fastq.gz -n DBB_dataset -d water_column_dbb -s + +# To run an ENA run # ./run_wf.sh -e ERR855786 -d TEST_SIMPLIFIED_PFAM -n ERR855786 -s + # Disable the module module purge From 5d96e20e7141b49d39d8d9f3c801c32040e5fdd6 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Fri, 24 Mar 2023 03:02:50 +0200 Subject: [PATCH 11/26] logic to address #18 --- utils/edit-ro-crate.py | 293 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100755 utils/edit-ro-crate.py diff --git a/utils/edit-ro-crate.py b/utils/edit-ro-crate.py new file mode 100755 index 00000000..5ddd509b --- /dev/null +++ b/utils/edit-ro-crate.py @@ -0,0 +1,293 @@ +#! /usr/bin/env python3 + +import sys +import argparse +import textwrap +from rocrate.rocrate import ROCrate +from rocrate.model.person import Person + +ena_accession_raw_data= "Raw sequence data and laboratory sequence generation metadata", + +descriptions = [ + { + "@id": "config.yml", + "@type": "File", + "name": "MetaGOflow configuration file", + "description": "The configuration file through which the user sets the values of the metaGOflow parameters.", + "encodingFormat": "text/yaml" + }, + { + "@id": "fastp.html", + "@type": "File", + "name": "FASTP analysis of raw sequence data", + "description": "Quality control and preprocessing of FASTQ files", + "encodingFormat": "text/html" + }, + { + "@id": "final.contigs.fa", + "@type": "File", + "name": "FASTA formatted contig sequences", + "description": "These are the assembled contig sequences from the merged reads in FASTA format", + "encodingFormat": "text/plain" + }, + { + "@id": "go.stats", + "@type": "File", + "name": "Geno Ontology summary statistics", + "encodingFormat": "text/plain" + }, + { + "@id": "interproscan.stats", + "@type": "File", + "name": "InterProScan summary statistics", + "encodingFormat": "text/plain" + }, + { + "@id": "ko.stats", + "@type": "File", + "name": "Kegg Ontology summary statistics", + "encodingFormat": "text/plain" + }, + { + "@id": "orf.stats", + "@type": "File", + "name": "ORF summary statistics", + "encodingFormat": "text/plain" + }, + { + "@id": "pfam.stats", + "@type": "File", + "name": "Pfam summary statistcs", + "encodingFormat": "text/plain" + }, + { + "@id": ".merged_CDS.I5.tsv.gz", + "@type": "File", + "name": "Merged contigs CDS I5 summary", + "encodingFormat": "application/zip" + }, + { + "@id": ".merged.hmm.tsv.gz", + "@type": "File", + "name": "Merged contigs HMM summary", + "encodingFormat": "application/zip" + }, + { + "@id": ".merged.summary.go", + "@type": "File", + "name": "Merged contigs GO summary", + "encodingFormat": "text/plain" + }, + { + "@id": ".merged.summary.go_slim", + "@type": "File", + "name": "Merged contigs InterProScan slim", + "encodingFormat": "text/plain" + }, + { + "@id": ".merged.summary.ips", + "@type": "File", + "name": "Merged contigs InterProScan", + "encodingFormat": "text/plain" + }, + { + "@id": ".merged.summary.ko", + "@type": "File", + "name": "Merged contigs KO summary", + "encodingFormat": "text/plain" + }, + { + "@id": ".merged.summary.pfam", + "@type": "File", + "name": "Merged contigs PFAM summary", + "encodingFormat": "text/plain" + }, + { + "@id": "RNA-counts", + "@type": "File", + "name": "Numbers of RNA's counted", + "encodingFormat": "text/plain" + }, + { + "@id": "krona.html", + "@type": "File", + "name": "Krona summary of LSU taxonomic inventory", + "encodingFormat": "application/html" + }, + { + "@id": ".merged_LSU.fasta.mseq.gz", + "@type": "File", + "name": "LSU sequences used for indentification", + "encodingFormat": "application/zip" + }, + { + "@id": ".merged_LSU.fasta.mseq_hdf5.biom", + "@type": "File", + "name": "BIOM formatted hdf5 taxon counts for LSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": ".merged_LSU.fasta.mseq_json.biom", + "@type": "File", + "name": "BIOM formatted taxon counts for LSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": ".merged_LSU.fasta.mseq.tsv", + "@type": "File", + "name": "Tab-separated formatted taxon counts for LSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": ".merged_LSU.fasta.mseq.txt", + "@type": "File", + "name": "Text-based taxon counts for LSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": "krona.html", + "@type": "File", + "name": "Krona summary of SSU taxonomic inventory", + "encodingFormat": "text/html" + }, + { + "@id": ".merged_SSU.fasta.mseq.gz", + "@type": "File", + "name": "LSU sequences used for indentification", + "encodingFormat": "application/zip" + }, + { + "@id": ".merged_SSU.fasta.mseq_hdf5.biom", + "@type": "File", + "name": "BIOM formatted hdf5 taxon counts for SSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": ".merged_SSU.fasta.mseq_json.biom", + "@type": "File", + "name": "BIOM formatted taxon counts for SSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": ".merged_SSU.fasta.mseq.tsv", + "@type": "File", + "name": "Tab-separated formatted taxon counts for SSU sequences", + "encodingFormat": "application/json-ld" + }, + { + "@id": ".merged_SSU.fasta.mseq.txt", + "@type": "File", + "name": "Text-based formatted taxon counts for SSU sequences", + "encodingFormat": "application/json-ld" + } +] + + + + +def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflow_version ): + + crate = ROCrate(target_directory) # here we use a complete directory, could we use just the json..? + + for entry in crate.get_entities(): + + for description in descriptions: + + try: + pk = description["@id"] in entry.id + except: + # new_crate.add(entry) + pass + finally: + if pk : + for k,v in description.items(): + if k not in entry.properties().keys(): + entry.append_to(k, v) + + print("export...") + + crate.write_zip("exp_crate.zip") + + print(".. goodbye friend") + + + sys.exit(0) + + + metagoflow_id = "workflow/metaGOflow" + license_id = "https://www.apache.org/licenses/LICENSE-2.0" + + + metagoflow_id = crate.add(Person(crate, metagoflow_id, properties={ + "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "name": "metaGOflow", + "affiliation": "University of Flatland", + "author": {"@id": "EMO BON"}, + "url": metagoflow_version, + "license": { "@id": "https://www.apache.org/licenses/LICENSE-2.0"}, + "hasPart": [ + {"@id": "config.yml"}, + {"@id": "mini_dataset.yml"} + ] + })) + + license_id = crate.add(Person(crate, license_id, properties={ + "@type": "CreativeWork", + "name": "Apache License 2.0" + })) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter + # description=textwrap.dedent(desc), + ) + parser.add_argument("target_directory", + help="Name of target directory containing MetaGOflow" +\ + "output" + ) + parser.add_argument("extended_config_yaml", + help="The extened YAML file metaGOflow built and used based on user's config" +\ + "output" + ) + parser.add_argument("ena_run_accession_id", + help="Run accession id in ENA." + ) + parser.add_argument("metagoflow_version", + help="URL pointing to the metaGOflow version used" + ) + + args = parser.parse_args() + + print(args.target_directory) + + main(args.target_directory, args.extended_config_yaml, args.ena_run_accession_id, args.metagoflow_version) + + + + + """ + { + "@id": "workflow/metaGOflow", + "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "author": {"@id": "EMO BON"}, + "name": "metaGOflow", + "description": "Metagenomics analysis based on MGnify for the needs of the EMO BON community", + "license": { "@id": "https://www.apache.org/licenses/LICENSE-2.0"}, + "url": "https://www.imagemagick.org/", + "hasPart": [ + {"@id": "config.yml"}, + {"@id": "mini_dataset.yml"} + + ] + }, + { + "@id": "https://www.apache.org/licenses/LICENSE-2.0", + "@type": "CreativeWork", + "name": "Apache License 2.0" + }, + """ + + + From a3d5ffde6c2a146565f10417dbff04119e37e9df Mon Sep 17 00:00:00 2001 From: hariszaf Date: Fri, 24 Mar 2023 05:48:00 +0200 Subject: [PATCH 12/26] build ro-crate as zip #18 --- run_wf.sh | 7 +- utils/edit-ro-crate.py | 244 +++++++++++++++++++++++++++++++++-------- 2 files changed, 203 insertions(+), 48 deletions(-) diff --git a/run_wf.sh b/run_wf.sh index ebacfee0..72237c80 100755 --- a/run_wf.sh +++ b/run_wf.sh @@ -217,7 +217,12 @@ TOIL_PARAMS+=( cwltool --parallel ${SINGULARITY} --outdir ${OUT_DIR_FINAL} ${CWL} ${EXTENDED_CONFIG_YAML} # Build RO-crate +rm -rf ${TMPDIR} + +rocrate init -c ${RUN_DIR} + if [ -z "$ENA_RUN_ID" ]; then ENA_RUN_ID="None" fi -python utils/create-ro-crate.py ${OUT_DIR} ${METAGOFLOW_VERSION} ${NAME} ${ENA_RUN_ID} +python utils/edit-ro-crate.py ${OUT_DIR} ${EXTENDED_CONFIG_YAML} ${ENA_RUN_ID} ${METAGOFLOW_VERSION} + diff --git a/utils/edit-ro-crate.py b/utils/edit-ro-crate.py index 5ddd509b..dced9d56 100755 --- a/utils/edit-ro-crate.py +++ b/utils/edit-ro-crate.py @@ -5,10 +5,21 @@ import textwrap from rocrate.rocrate import ROCrate from rocrate.model.person import Person +import datetime ena_accession_raw_data= "Raw sequence data and laboratory sequence generation metadata", descriptions = [ + { + "@id": "sequence-categorisation/", + "@type": "Dataset", + "name": "Sequence categorisation", + "description": "Identify specific loci in the sample." + }, + { "@id": "functional_annotation/", + "@type": "Dataset", + "name": "Functional annotation results", + "description": "Functional annotation of merged reads"}, { "@id": "config.yml", "@type": "File", @@ -179,45 +190,191 @@ "@type": "File", "name": "Text-based formatted taxon counts for SSU sequences", "encodingFormat": "application/json-ld" + }, + { + "@id": ".all.tblout.deoverlapped", + "@type": "File", + "name": "Sequence hits against covariance model databases. Mandatory to run partially the functional annotation step of metaGOflow.", + "encodingFormat": "text/plain" + }, + { + "@id": ".merged.fasta", + "@type": "File", + "name": "Merged filtered reads.", + "encodingFormat": "text/plain" + }, + { + "@id": ".fastq.trimmed.fasta", + "@type": "File", + "name": "Filtered .fastq file of the single-end reads (forward/reverse).", + "encodingFormat": "text/plain" + }, + { + "@id": ".fastq.trimmed.qc_summary", + "@type": "File", + "name": "Summary with statistics of the single-end reads (forward/reverse).", + "encodingFormat": "text/plain" + }, + { + "@id": ".fastq.trimmed.qc_summary", + "@type": "File", + "name": "Summary with statistics of the single-end reads (forward/reverse).", + "encodingFormat": "text/plain" + }, + { + "@id": ".all.tblout.deoverlapped", + "@type": "File", + "name": "Sequence hits against covariance model databases", + "encodingFormat": "text/plain" + }, + { + "@id": ".merged.unfiltered_fasta", + "@type": "File", + "name": "", + "encodingFormat": "text/plain" + }, + { + "@id": ".motus.tsv", + "@type": "File", + "name": "", + "encodingFormat": "text/plain" + }, + { + "@id": ".merged.qc_summary", + "@type": "File", + "name": "Summary with statistics of the merged reads.", + "encodingFormat": "text/plain" + }, + { + "@id": "SSU.fasta.gz", + "@type": "File", + "name": "SSU sequences.", + "encodingFormat": "application/zip" + }, + { + "@id": "SSU_rRNA_archaea.RF01959.fa.gz", + "@type": "File", + "name": "SSU sequences mapping to Archaea.", + "encodingFormat": "application/zip" + }, + { + "@id": "SSU_rRNA_bacteria.RF00177.fa.gz", + "@type": "File", + "name": "SSU sequences mapping to Bacteria.", + "encodingFormat": "application/zip" + }, + { + "@id": "SSU_rRNA_eukarya.RF01960.fa.gz", + "@type": "File", + "name": "SSU sequences mapping to Eukaryotes.", + "encodingFormat": "application/zip" + }, + { + "@id": "tmRNA.RF00023.fasta.gz", + "@type": "File", + "name": "Sequences mapping to transfer-messenger RNAs", + "encodingFormat": "application/zip" + }, + { + "@id": "tRNA.RF00005.fasta.gz", + "@type": "File", + "name": "Sequences mapping to tranfer RNAs", + "encodingFormat": "application/zip" + }, + { + "@id": "tRNA-Sec.RF01852.fasta.gz", + "@type": "File", + "name": "Sequences mapping to selenocysteine tRNAs.", + "encodingFormat": "application/zip" + }, + { + "@id": "LSU.fasta.gz", + "@type": "File", + "name": "LSU sequences.", + "encodingFormat": "application/zip" + }, + { + "@id": "LSU_rRNA_archaea.RF02540.fa.gz", + "@type": "File", + "name": "LSU sequences mapping to Archaea.", + "encodingFormat": "application/zip" + }, + { + "@id": "LSU_rRNA_bacteria.RF02541.fa.gz", + "@type": "File", + "name": "LSU sequences mapping to Bacteria.", + "encodingFormat": "application/zip" + }, + { + "@id": "LSU_rRNA_eukarya.RF02543.fa.gz", + "@type": "File", + "name": "LSU sequences mapping to Eukaryotes.", + "encodingFormat": "application/zip" + }, + { + "@id": "RNaseP_bact_a.RF00010.fasta.gz", + "@type": "File", + "name": "Sequences mapping to ribonucleus P bacterial sequences.", + "encodingFormat": "application/zip" + }, + { + "@id": "5_8S.fa.gz", + "@type": "File", + "name": "Sequences mapping to ribonucleus 5_8S rRNA gene.", + "encodingFormat": "application/zip" + }, + { + "@id": "alpha_tmRNA.RF01849.fasta.gz", + "@type": "File", + "name": "Sequences mapping to alpha transfer-messenger RNA.", + "encodingFormat": "application/zip" + }, + { + "@id": "Bacteria_large_SRP.RF01854.fasta.gz", + "@type": "File", + "name": "Sequences mapping to bacterial large signal recognition particle RNAs.", + "encodingFormat": "application/zip" + }, + { + "@id": "Bacteria_small_SRP.RF00169.fasta.gz", + "@type": "File", + "name": "Sequences mapping to bacterial small signal recognition particle RNAs.", + "encodingFormat": "application/zip" + }, + { + "@id": ".merged_CDS.faa", + "@type": "File", + "name": "Coding sequences with amino acids.", + "encodingFormat": "text/plain" + }, + { + "@id": ".merged_CDS.ffn", + "@type": "File", + "name": "Coding sequences with nucleotides.", + "encodingFormat": "text/plain" } ] - - def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflow_version ): crate = ROCrate(target_directory) # here we use a complete directory, could we use just the json..? for entry in crate.get_entities(): - for description in descriptions: - try: pk = description["@id"] in entry.id except: - # new_crate.add(entry) pass finally: if pk : for k,v in description.items(): if k not in entry.properties().keys(): - entry.append_to(k, v) - - print("export...") - - crate.write_zip("exp_crate.zip") - - print(".. goodbye friend") - - - sys.exit(0) - + entry.properties()[k] = v metagoflow_id = "workflow/metaGOflow" license_id = "https://www.apache.org/licenses/LICENSE-2.0" - metagoflow_id = crate.add(Person(crate, metagoflow_id, properties={ "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], "name": "metaGOflow", @@ -227,7 +384,7 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo "license": { "@id": "https://www.apache.org/licenses/LICENSE-2.0"}, "hasPart": [ {"@id": "config.yml"}, - {"@id": "mini_dataset.yml"} + {"@id": extended_config_yaml} ] })) @@ -237,6 +394,27 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo })) + if ena_run_accession_id != "None": + + ena_id = crate.add(Person(crate, ena_run_accession_id, properties={ + + "@id": ena_accession_raw_data, + "@type": "File", + "name": "ENA accession for run raw sequence data", + "description": "FAKE: Raw sequence data and laboratory sequence generation metadata", + "url": "https://www.ebi.ac.uk/ena/browser/view/" + ena_run_accession_id, + "encodingFormat": "text/xml" + })) + + + print("export...") + + crate.write_zip("exp_crate.zip") + + print(".. ro-crate as .zip ready.") + + + if __name__ == "__main__": parser = argparse.ArgumentParser( @@ -260,34 +438,6 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo args = parser.parse_args() - print(args.target_directory) - + # Run main function main(args.target_directory, args.extended_config_yaml, args.ena_run_accession_id, args.metagoflow_version) - - - - """ - { - "@id": "workflow/metaGOflow", - "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], - "author": {"@id": "EMO BON"}, - "name": "metaGOflow", - "description": "Metagenomics analysis based on MGnify for the needs of the EMO BON community", - "license": { "@id": "https://www.apache.org/licenses/LICENSE-2.0"}, - "url": "https://www.imagemagick.org/", - "hasPart": [ - {"@id": "config.yml"}, - {"@id": "mini_dataset.yml"} - - ] - }, - { - "@id": "https://www.apache.org/licenses/LICENSE-2.0", - "@type": "CreativeWork", - "name": "Apache License 2.0" - }, - """ - - - From 74ab4f28fe0c41341c779321b13c7f7acdced7b1 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Fri, 24 Mar 2023 05:48:50 +0200 Subject: [PATCH 13/26] ro-crate example #18 --- ro-crate-io-metadata.json-template | 315 --- ro-crate-metadata-example.json | 384 ++++ ro-crate-source-code-metadata.json | 3277 ---------------------------- 3 files changed, 384 insertions(+), 3592 deletions(-) delete mode 100644 ro-crate-io-metadata.json-template create mode 100644 ro-crate-metadata-example.json delete mode 100644 ro-crate-source-code-metadata.json diff --git a/ro-crate-io-metadata.json-template b/ro-crate-io-metadata.json-template deleted file mode 100644 index 2e5cfe6c..00000000 --- a/ro-crate-io-metadata.json-template +++ /dev/null @@ -1,315 +0,0 @@ -https://github.com/emo-bon/MetaGOflow/blob/eosc-life-gos/config.yml{ "@context": "https://w3id.org/ro/crate/1.1/context", - "@graph": [ - { - "@id": "ro-crate-metadata.json", - "@type": "CreativeWork", - "conformsTo": {"@id": "https://w3id.org/ro/crate/1.1"}, - "about": {"@id": "./"} - }, - { - "@id": "./", - "@type": "Dataset", - "name" : "MetaGoFlow Results for ENA Run Accession Number {ena_accession_raw_data}", - "description" : "RO-Crate for the MetaGOflow analysis EMO BON ENA Accession {ena_accession_raw_data} data ", - "datePublished": "{datePublished}", - "license": {"@id": "https://creativecommons.org/licenses/by/4.0/legalcode"}, - "publisher": {"@id": "https://ror.org/0038zss60"}, - "hasPart": [ - {"@id": "{ena_accession_raw_data}"}, - {"@id": "{metagoflow_version}"}, - {"@id": "{run_parameter}.yml"}, - {"@id": "config.yml"}, - {"@id": "fastp.html"} - {"@id": "final.contigs.fa"}, - {"@id": "functional_annotation/"}, - {"@id": "sequence-categorisation/"}, - {"@id": "taxonomic-summary/"}, - {"@id": "RNA-counts"} - ] - }, - { - "@id": "https://ror.org/0038zss60", - "@type": "Organization", - "name": "European Marine Biological Resource Centre", - "url": "https://ror.org/0038zss60", - "contactPoint": {"@id": "mailto:help@embrc.org"} - }, - { - "@id": "mailto:help@embrc.org", - "@type": "ContactPoint", - "contactType": "Help Desk", - "email": "help@embrc.org", - "identifier": "help@embrc.org", - "url": "https://www.embrc.eu/about-us/contact-us" - }, - { - "@id": "https://www.apache.org/licenses/LICENSE-2.0", - "@type": "CreativeWork", - "identifier": "https://www.apache.org/licenses/LICENSE-2.0", - "name": "Apache License 2.0" - }, - { - "@id": "{ena_accession_raw_data}", - "@type": "File", - "name": "ENA accession for run raw sequence data", - "description": "FAKE: Raw sequence data and laboratory sequence generation metadata", - "encodingFormat": "text/xml" - }, - { - "@id": "{metagoflow_version}", - "@type": "File", - "name": "MetaGOflow Workflow Version RO-Crate", - "description": "Metadata for the version of the MetaGOflow workflow used to generate the data", - "encodingFormat": "application/zip" - }, - { - "@id": "{run_parameter}.yml", - "@type": "File", - "name": "The YAML configuration file MetaGOflow builds", - "description": "YAML configuration file for execution of MetaGOflow workflow.", - "encodingFormat": "text/yaml" - }, - { - "@id": "config.yml", - "@type": "File", - "name": "MetaGOflow configuration file", - "description": "The configuration file through which the user sets the values of the metaGOflow parameters.", - "encodingFormat": "text/yaml" - }, - { - "@id": "fastp.html", - "@type": "File", - "name": "FASTP analysis of raw sequence data", - "description": "Quality control and preprocessing of FASTQ files", - "encodingFormat": "text/html" - }, - { - "@id": "final.contigs.fa", - "@type": "File", - "name": "FASTA formatted contig sequences", - "description": "These are the assembled contig sequences from the merged reads in FASTA format", - "encodingFormat": "text/plain" - }, - { - "@id": "functional_annotation/", - "@type": "Dataset", - "name": "Functional annotation results", - "description": "Functional annotation of merged reads", - "hasPart": [ - {"@id": "stats/"}, - {"@id": "{prefix}.merged_CDS.I5.tsv.gz"}, - {"@id": "{prefix}.merged.hmm.tsv.gz"}, - {"@id": "{prefix}.merged.summary.go"}, - {"@id": "{prefix}.merged.summary.go_slim"}, - {"@id": "{prefix}.merged.summary.ips"}, - {"@id": "{prefix}.merged.summary.ko"}, - {"@id": "{prefix}.merged.summary.pfam"} - ] - }, - { - "@id": "stats/", - "@type": "Dataset", - "name": "Summary statistic for functional annotation", - "hasPart": [ - {"@id": "go.stats"}, - {"@id": "interproscan.stats"}, - {"@id": "ko.stats"}, - {"@id": "orf.stats"}, - {"@id": "pfam.stats"} - ] - }, - { - "@id": "go.stats", - "@type": "File", - "name": "Geno Ontology summary statistics", - "encodingFormat": "text/plain" - }, - { - "@id": "interproscan.stats", - "@type": "File", - "name": "InterProScan summary statistics", - "encodingFormat": "text/plain" - }, - { - "@id": "ko.stats", - "@type": "File", - "name": "Kegg Ontology summary statistics", - "encodingFormat": "text/plain" - }, - { - "@id": "orf.stats", - "@type": "File", - "name": "ORF summary statistics", - "encodingFormat": "text/plain" - }, - { - "@id": "pfam.stats", - "@type": "File", - "name": "Pfam summary statistcs", - "encodingFormat": "text/plain" - }, - { - "@id": "{prefix}.merged_CDS.I5.tsv.gz", - "@type": "File", - "name": "Merged contigs CDS I5 summary", - "encodingFormat": "application/zip" - }, - { - "@id": "{prefix}.merged.hmm.tsv.gz", - "@type": "File", - "name": "Merged contigs HMM summary", - "encodingFormat": "application/zip" - }, - { - "@id": "{prefix}.merged.summary.go", - "@type": "File", - "name": "Merged contigs GO summary", - "encodingFormat": "text/plain" - }, - { - "@id": "{prefix}.merged.summary.go_slim", - "@type": "File", - "name": "Merged contigs InterProScan slim", - "encodingFormat": "text/plain" - }, - { - "@id": "{prefix}.merged.summary.ips", - "@type": "File", - "name": "Merged contigs InterProScan", - "encodingFormat": "text/plain" - }, - { - "@id": "{prefix}.merged.summary.ko", - "@type": "File", - "name": "Merged contigs KO summary", - "encodingFormat": "text/plain" - }, - { - "@id": "{prefix}.merged.summary.pfam", - "@type": "File", - "name": "Merged contigs PFAM summary", - "encodingFormat": "text/plain" - }, - { - "@id": "sequence-categorisation/", - "@type": "Dataset", - "name": "Sequence categorisation", - "description": "Identify specific loci in the sample." - }, - { - "@id": "taxonomic-summary/", - "@type": "Dataset", - "name": "Taxonomic summary", - "description": "Summary of taxonomic identification results", - "hasPart": [ - {"@id": "RNA-counts"}, - {"@id": "LSU/"}, - {"@id": "SSU/"} - ] - }, - { - "@id": "RNA-counts", - "@type": "File", - "name": "Numbers of RNA's counted", - "encodingFormat": "text/plain" - }, - { - "@id": "LSU/", - "@type": "Dataset", - "name": "Summary of LSU taxonomic indentification results", - "hasPart": [ - {"@id": "krona.html"}, - {"@id": "{prefix}.merged_LSU.fasta.mseq.gz"}, - {"@id": "{prefix}.merged_LSU.fasta.mseq_hdf5.biom"}, - {"@id": "{prefix}.merged_LSU.fasta.mseq_json.biom"}, - {"@id": "{prefix}.merged_LSU.fasta.mseq.tsv"}, - {"@id": "{prefix}.merged_LSU.fasta.mseq.txt"} - ] - }, - { - "@id": "krona.html", - "@type": "File", - "name": "Krona summary of LSU taxonomic inventory", - "encodingFormat": "application/html" - }, - { - "@id": "{prefix}.merged_LSU.fasta.mseq.gz", - "@type": "File", - "name": "LSU sequences used for indentification", - "encodingFormat": "application/zip" - }, - { - "@id": "{prefix}.merged_LSU.fasta.mseq_hdf5.biom", - "@type": "File", - "name": "BIOM formatted hdf5 taxon counts for LSU sequences", - "encodingFormat": "application/json-ld" - }, - { - "@id": "{prefix}.merged_LSU.fasta.mseq_json.biom", - "@type": "File", - "name": "BIOM formatted taxon counts for LSU sequences", - "encodingFormat": "application/json-ld" - }, - { - "@id": "{prefix}.merged_LSU.fasta.mseq.tsv", - "@type": "File", - "name": "Tab-separated formatted taxon counts for LSU sequences", - "encodingFormat": "application/json-ld" - }, - { - "@id": "{prefix}.merged_LSU.fasta.mseq.txt", - "@type": "File", - "name": "Text-based taxon counts for LSU sequences", - "encodingFormat": "application/json-ld" - }, - { - "@id": "SSU/", - "@type": "Dataset", - "name": "Summary of SSU taxonomic indentification results", - "hasPart": [ - {"@id": "krona.html"}, - {"@id": "{prefix}.merged_SSU.fasta.mseq.gz"}, - {"@id": "{prefix}.merged_SSU.fasta.mseq_hdf5.biom"}, - {"@id": "{prefix}.merged_SSU.fasta.mseq_json.biom"}, - {"@id": "{prefix}.merged_SSU.fasta.mseq.tsv"}, - {"@id": "{prefix}.merged_SSU.fasta.mseq.txt"} - ] - }, - { - "@id": "krona.html", - "@type": "File", - "name": "Krona summary of SSU taxonomic inventory", - "encodingFormat": "text/html" - }, - { - "@id": "{prefix}.merged_SSU.fasta.mseq.gz", - "@type": "File", - "name": "LSU sequences used for indentification", - "encodingFormat": "application/zip" - }, - { - "@id": "{prefix}.merged_SSU.fasta.mseq_hdf5.biom", - "@type": "File", - "name": "BIOM formatted hdf5 taxon counts for SSU sequences", - "encodingFormat": "application/json-ld" - }, - { - "@id": "{prefix}.merged_SSU.fasta.mseq_json.biom", - "@type": "File", - "name": "BIOM formatted taxon counts for SSU sequences", - "encodingFormat": "application/json-ld" - }, - { - "@id": "{prefix}.merged_SSU.fasta.mseq.tsv", - "@type": "File", - "name": "Tab-separated formatted taxon counts for SSU sequences", - "encodingFormat": "application/json-ld" - }, - { - "@id": "{prefix}.merged_SSU.fasta.mseq.txt", - "@type": "File", - "name": "Text-based formatted taxon counts for SSU sequences", - "encodingFormat": "application/json-ld" - } -] -} \ No newline at end of file diff --git a/ro-crate-metadata-example.json b/ro-crate-metadata-example.json new file mode 100644 index 00000000..4081809b --- /dev/null +++ b/ro-crate-metadata-example.json @@ -0,0 +1,384 @@ +{ + "@context": "https://w3id.org/ro/crate/1.1/context", + "@graph": [ + { + "@id": "ro-crate-metadata.json", + "@type": "CreativeWork", + "about": { + "@id": "./" + }, + "conformsTo": { + "@id": "https://w3id.org/ro/crate/1.1" + } + }, + { + "@id": "./", + "@type": "Dataset", + "datePublished": "2023-03-24T03:00:01+00:00", + "hasPart": [ + { + "@id": "results/" + }, + { + "@id": "dev_dataset.yml" + }, + { + "@id": "config.yml" + }, + { + "@id": "results/sequence-categorisation/" + }, + { + "@id": "results/taxonomy-summary/" + }, + { + "@id": "results/fastp.html" + }, + { + "@id": "results/test_1_fwd_HWLTKDRXY_600000.fastq.trimmed.fasta" + }, + { + "@id": "results/test_2_rev_HWLTKDRXY_600000.fastq.trimmed.fasta" + }, + { + "@id": "results/test.merged.fasta" + }, + { + "@id": "results/test.merged.qc_summary" + }, + { + "@id": "results/test.merged.unfiltered_fasta" + }, + { + "@id": "results/test_1_fwd_HWLTKDRXY_600000.fastq.trimmed.qc_summary" + }, + { + "@id": "results/test_2_rev_HWLTKDRXY_600000.fastq.trimmed.qc_summary" + }, + { + "@id": "results/test.merged.motus.tsv" + }, + { + "@id": "results/test.merged.cmsearch.all.tblout.deoverlapped" + }, + { + "@id": "results/RNA-counts" + }, + { + "@id": "results/sequence-categorisation/5_8S.fa.gz" + }, + { + "@id": "results/sequence-categorisation/LSU_rRNA_archaea.RF02540.fa.gz" + }, + { + "@id": "results/sequence-categorisation/LSU_rRNA_bacteria.RF02541.fa.gz" + }, + { + "@id": "results/sequence-categorisation/LSU_rRNA_eukarya.RF02543.fa.gz" + }, + { + "@id": "results/sequence-categorisation/SSU_rRNA_bacteria.RF00177.fa.gz" + }, + { + "@id": "results/sequence-categorisation/SSU_rRNA_eukarya.RF01960.fa.gz" + }, + { + "@id": "results/sequence-categorisation/tRNA.RF00005.fasta.gz" + }, + { + "@id": "results/taxonomy-summary/SSU/" + }, + { + "@id": "results/taxonomy-summary/LSU/" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.gz" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.tsv" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.txt" + }, + { + "@id": "results/taxonomy-summary/SSU/krona.html" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq_hdf5.biom" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq_json.biom" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.gz" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.tsv" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.txt" + }, + { + "@id": "results/taxonomy-summary/LSU/krona.html" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq_hdf5.biom" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq_json.biom" + } + ] + }, + { + "@id": "results/", + "@type": "Dataset" + }, + { + "@id": "dev_dataset.yml", + "@type": "File" + }, + { + "@id": "config.yml", + "@type": "File", + "description": "The configuration file through which the user sets the values of the metaGOflow parameters.", + "encodingFormat": "text/yaml", + "name": "MetaGOflow configuration file" + }, + { + "@id": "results/sequence-categorisation/", + "@type": "Dataset", + "description": "Identify specific loci in the sample.", + "name": "Sequence categorisation" + }, + { + "@id": "results/taxonomy-summary/", + "@type": "Dataset" + }, + { + "@id": "results/fastp.html", + "@type": "File", + "description": "Quality control and preprocessing of FASTQ files", + "encodingFormat": "text/html", + "name": "FASTP analysis of raw sequence data" + }, + { + "@id": "results/test_1_fwd_HWLTKDRXY_600000.fastq.trimmed.fasta", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Filtered .fastq file of the single-end reads (forward/reverse)." + }, + { + "@id": "results/test_2_rev_HWLTKDRXY_600000.fastq.trimmed.fasta", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Filtered .fastq file of the single-end reads (forward/reverse)." + }, + { + "@id": "results/test.merged.fasta", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Merged filtered reads." + }, + { + "@id": "results/test.merged.qc_summary", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Summary with statistics of the merged reads." + }, + { + "@id": "results/test.merged.unfiltered_fasta", + "@type": "File", + "encodingFormat": "text/plain", + "name": "" + }, + { + "@id": "results/test_1_fwd_HWLTKDRXY_600000.fastq.trimmed.qc_summary", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Summary with statistics of the single-end reads (forward/reverse)." + }, + { + "@id": "results/test_2_rev_HWLTKDRXY_600000.fastq.trimmed.qc_summary", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Summary with statistics of the single-end reads (forward/reverse)." + }, + { + "@id": "results/test.merged.motus.tsv", + "@type": "File", + "encodingFormat": "text/plain", + "name": "" + }, + { + "@id": "results/test.merged.cmsearch.all.tblout.deoverlapped", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Sequence hits against covariance model databases. Mandatory to run partially the functional annotation step of metaGOflow." + }, + { + "@id": "results/RNA-counts", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Numbers of RNA's counted" + }, + { + "@id": "results/sequence-categorisation/5_8S.fa.gz", + "@type": "File", + "description": "Identify specific loci in the sample.", + "encodingFormat": "application/zip", + "name": "Sequence categorisation" + }, + { + "@id": "results/sequence-categorisation/LSU_rRNA_archaea.RF02540.fa.gz", + "@type": "File", + "description": "Identify specific loci in the sample.", + "encodingFormat": "application/zip", + "name": "Sequence categorisation" + }, + { + "@id": "results/sequence-categorisation/LSU_rRNA_bacteria.RF02541.fa.gz", + "@type": "File", + "description": "Identify specific loci in the sample.", + "encodingFormat": "application/zip", + "name": "Sequence categorisation" + }, + { + "@id": "results/sequence-categorisation/LSU_rRNA_eukarya.RF02543.fa.gz", + "@type": "File", + "description": "Identify specific loci in the sample.", + "encodingFormat": "application/zip", + "name": "Sequence categorisation" + }, + { + "@id": "results/sequence-categorisation/SSU_rRNA_bacteria.RF00177.fa.gz", + "@type": "File", + "description": "Identify specific loci in the sample.", + "encodingFormat": "application/zip", + "name": "Sequence categorisation" + }, + { + "@id": "results/sequence-categorisation/SSU_rRNA_eukarya.RF01960.fa.gz", + "@type": "File", + "description": "Identify specific loci in the sample.", + "encodingFormat": "application/zip", + "name": "Sequence categorisation" + }, + { + "@id": "results/sequence-categorisation/tRNA.RF00005.fasta.gz", + "@type": "File", + "description": "Identify specific loci in the sample.", + "encodingFormat": "application/zip", + "name": "Sequence categorisation" + }, + { + "@id": "results/taxonomy-summary/SSU/", + "@type": "Dataset" + }, + { + "@id": "results/taxonomy-summary/LSU/", + "@type": "Dataset" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.gz", + "@type": "File", + "encodingFormat": "application/zip", + "name": "LSU sequences used for indentification" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.tsv", + "@type": "File", + "encodingFormat": "application/json-ld", + "name": "Tab-separated formatted taxon counts for SSU sequences" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.txt", + "@type": "File", + "encodingFormat": "application/json-ld", + "name": "Text-based formatted taxon counts for SSU sequences" + }, + { + "@id": "results/taxonomy-summary/SSU/krona.html", + "@type": "File", + "encodingFormat": "application/html", + "name": "Krona summary of LSU taxonomic inventory" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq_hdf5.biom", + "@type": "File", + "encodingFormat": "application/json-ld", + "name": "BIOM formatted hdf5 taxon counts for SSU sequences" + }, + { + "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq_json.biom", + "@type": "File", + "encodingFormat": "application/json-ld", + "name": "BIOM formatted taxon counts for SSU sequences" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.gz", + "@type": "File", + "encodingFormat": "application/zip", + "name": "LSU sequences used for indentification" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.tsv", + "@type": "File", + "encodingFormat": "application/json-ld", + "name": "Tab-separated formatted taxon counts for LSU sequences" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.txt", + "@type": "File", + "encodingFormat": "application/json-ld", + "name": "Text-based taxon counts for LSU sequences" + }, + { + "@id": "results/taxonomy-summary/LSU/krona.html", + "@type": "File", + "encodingFormat": "application/html", + "name": "Krona summary of LSU taxonomic inventory" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq_hdf5.biom", + "@type": "File", + "encodingFormat": "application/json-ld", + "name": "BIOM formatted hdf5 taxon counts for LSU sequences" + }, + { + "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq_json.biom", + "@type": "File", + "encodingFormat": "application/json-ld", + "name": "BIOM formatted taxon counts for LSU sequences" + }, + { + "@id": "#workflow/metaGOflow", + "@type": [ + "File", + "SoftwareSourceCode", + "ComputationalWorkflow" + ], + "affiliation": "University of Flatland", + "author": { + "@id": "EMO BON" + }, + "hasPart": [ + { + "@id": "config.yml" + }, + { + "@id": "dev_dataset.yml" + } + ], + "license": { + "@id": "https://www.apache.org/licenses/LICENSE-2.0" + }, + "name": "metaGOflow", + "url": "https://github.com/emo-bon/MetaGOflow/releases/tag/v1.0.0" + }, + { + "@id": "https://www.apache.org/licenses/LICENSE-2.0", + "@type": "CreativeWork", + "name": "Apache License 2.0" + } + ] +} \ No newline at end of file diff --git a/ro-crate-source-code-metadata.json b/ro-crate-source-code-metadata.json deleted file mode 100644 index 33381669..00000000 --- a/ro-crate-source-code-metadata.json +++ /dev/null @@ -1,3277 +0,0 @@ -{ - "@context": "https://w3id.org/ro/crate/1.1/context", - "@graph": [ - { - "@id": "./ro-crate-metadata.json", - "@type": "CreativeWork", - "about": { - "@id": "./" - }, - "conformsTo": { - "@id": "https://w3id.org/ro/crate/1.1" - } - }, - { - "@id": "./", - "@type": "Dataset", - "datePublished": "2021-11-25T11:27:08+00:00", - "hasPart": [ - { - "@id": "./docker/" - }, - { - "@id": "./environment/" - }, - { - "@id": "./Installation/" - }, - { - "@id": "./profiling/" - }, - { - "@id": "./test_input/" - }, - { - "@id": "./tools/" - }, - { - "@id": "./utils/" - }, - { - "@id": "./workflows/" - }, - { - "@id": "./config.yml" - }, - { - "@id": "./create_yml.py" - }, - { - "@id": "./dependencies.md" - }, - { - "@id": "./learning_cwl.md" - }, - { - "@id": "./LICENSE" - }, - { - "@id": "./README.md" - }, - { - "@id": "./run_wf.sh" - }, - { - "@id": "./slurm_run.sh" - } - ] - }, - { - "@id": "./docker/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./docker/scripts_bash/" - }, - { - "@id": "./docker/scripts_python2/" - }, - { - "@id": "./docker/scripts_python3/" - }, - { - "@id": "./docker/docker_build.sh" - }, - { - "@id": "./docker/docker_push.sh" - } - ] - }, - { - "@id": "./docker/scripts_bash/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./docker/scripts_bash/add_header" - }, - { - "@id": "./docker/scripts_bash/add_symbol_json.sh" - }, - { - "@id": "./docker/scripts_bash/antismash_json_generation" - }, - { - "@id": "./docker/scripts_bash/awk_tool" - }, - { - "@id": "./docker/scripts_bash/biom-convert.sh" - }, - { - "@id": "./docker/scripts_bash/clean_motus_output.sh" - }, - { - "@id": "./docker/scripts_bash/diamond_post_run_join.sh" - }, - { - "@id": "./docker/scripts_bash/Dockerfile" - }, - { - "@id": "./docker/scripts_bash/empty_tax.sh" - }, - { - "@id": "./docker/scripts_bash/esl-ssplit.sh" - }, - { - "@id": "./docker/scripts_bash/format_bedfile" - }, - { - "@id": "./docker/scripts_bash/pull_ncrnas.sh" - }, - { - "@id": "./docker/scripts_bash/remove_symbol.sh" - }, - { - "@id": "./docker/scripts_bash/run_antismash_short.sh" - }, - { - "@id": "./docker/scripts_bash/run_samtools_docker.sh" - } - ] - }, - { - "@id": "./docker/scripts_bash/add_header", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/add_symbol_json.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/antismash_json_generation", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/awk_tool", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/biom-convert.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/clean_motus_output.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/diamond_post_run_join.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/Dockerfile", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/empty_tax.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/esl-ssplit.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/format_bedfile", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/pull_ncrnas.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/remove_symbol.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/run_antismash_short.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_bash/run_samtools_docker.sh", - "@type": "File" - }, - { - "@id": "./docker/scripts_python2/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./docker/scripts_python2/Dockerfile" - }, - { - "@id": "./docker/scripts_python2/MGRAST_base.py" - }, - { - "@id": "./docker/scripts_python2/run_quality_filtering.py" - } - ] - }, - { - "@id": "./docker/scripts_python2/Dockerfile", - "@type": "File" - }, - { - "@id": "./docker/scripts_python2/MGRAST_base.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python2/run_quality_filtering.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./docker/scripts_python3/antismash_rename_contigs.py" - }, - { - "@id": "./docker/scripts_python3/antismash_to_gff.py" - }, - { - "@id": "./docker/scripts_python3/antismash_to_gff_nojson.py" - }, - { - "@id": "./docker/scripts_python3/build_assembly_gff.py" - }, - { - "@id": "./docker/scripts_python3/change_antismash_output.py" - }, - { - "@id": "./docker/scripts_python3/change_geneclusters_ctg.py" - }, - { - "@id": "./docker/scripts_python3/change_geneclusters_ctg_js.py" - }, - { - "@id": "./docker/scripts_python3/count_fastq.py" - }, - { - "@id": "./docker/scripts_python3/count_lines.py" - }, - { - "@id": "./docker/scripts_python3/Dockerfile" - }, - { - "@id": "./docker/scripts_python3/fastq_to_fasta.py" - }, - { - "@id": "./docker/scripts_python3/functional_stats.py" - }, - { - "@id": "./docker/scripts_python3/generate_checksum.py" - }, - { - "@id": "./docker/scripts_python3/generate_mapfile_prodigal.py" - }, - { - "@id": "./docker/scripts_python3/get_subunits.py" - }, - { - "@id": "./docker/scripts_python3/get_subunits_coords.py" - }, - { - "@id": "./docker/scripts_python3/give_pathways.py" - }, - { - "@id": "./docker/scripts_python3/hmmscan_tab.py" - }, - { - "@id": "./docker/scripts_python3/its-length-new.py" - }, - { - "@id": "./docker/scripts_python3/its-length.py" - }, - { - "@id": "./docker/scripts_python3/make_csv.py" - }, - { - "@id": "./docker/scripts_python3/move_antismash_summary.py" - }, - { - "@id": "./docker/scripts_python3/parsing_hmmscan.py" - }, - { - "@id": "./docker/scripts_python3/reformat-antismash.py" - }, - { - "@id": "./docker/scripts_python3/split_to_chunks.py" - }, - { - "@id": "./docker/scripts_python3/write_summaries.py" - } - ] - }, - { - "@id": "./docker/scripts_python3/antismash_rename_contigs.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/antismash_to_gff.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/antismash_to_gff_nojson.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/build_assembly_gff.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/change_antismash_output.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/change_geneclusters_ctg.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/change_geneclusters_ctg_js.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/count_fastq.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/count_lines.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/Dockerfile", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/fastq_to_fasta.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/functional_stats.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/generate_checksum.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/generate_mapfile_prodigal.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/get_subunits.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/get_subunits_coords.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/give_pathways.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/hmmscan_tab.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/its-length-new.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/its-length.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/make_csv.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/move_antismash_summary.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/parsing_hmmscan.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/reformat-antismash.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/split_to_chunks.py", - "@type": "File" - }, - { - "@id": "./docker/scripts_python3/write_summaries.py", - "@type": "File" - }, - { - "@id": "./docker/docker_build.sh", - "@type": "File" - }, - { - "@id": "./docker/docker_push.sh", - "@type": "File" - }, - { - "@id": "./environment/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./environment/antismash.yml" - }, - { - "@id": "./environment/interproscan.yml" - }, - { - "@id": "./environment/README.md" - }, - { - "@id": "./environment/toil.yml" - } - ] - }, - { - "@id": "./environment/antismash.yml", - "@type": "File" - }, - { - "@id": "./environment/interproscan.yml", - "@type": "File" - }, - { - "@id": "./environment/README.md", - "@type": "File" - }, - { - "@id": "./environment/toil.yml", - "@type": "File" - }, - { - "@id": "./Installation/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./Installation/templates/" - }, - { - "@id": "./Installation/download_dbs.sh" - } - ] - }, - { - "@id": "./Installation/templates/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./Installation/templates/default.yml" - } - ] - }, - { - "@id": "./Installation/templates/default.yml", - "@type": "File" - }, - { - "@id": "./Installation/download_dbs.sh", - "@type": "File" - }, - { - "@id": "./profiling/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./profiling/profiling_parser.py" - }, - { - "@id": "./profiling/run_profiling.sh" - }, - { - "@id": "./profiling/__init__.py" - } - ] - }, - { - "@id": "./profiling/profiling_parser.py", - "@type": "File" - }, - { - "@id": "./profiling/run_profiling.sh", - "@type": "File" - }, - { - "@id": "./profiling/__init__.py", - "@type": "File" - }, - { - "@id": "./test_input/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./test_input/wgs-paired-SRR1620013_1.fastq.gz" - }, - { - "@id": "./test_input/wgs-paired-SRR1620013_2.fastq.gz" - } - ] - }, - { - "@id": "./test_input/wgs-paired-SRR1620013_1.fastq.gz", - "@type": "File" - }, - { - "@id": "./test_input/wgs-paired-SRR1620013_2.fastq.gz", - "@type": "File" - }, - { - "@id": "./tools/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/" - }, - { - "@id": "./tools/chunks/" - }, - { - "@id": "./tools/Combined_gene_caller/" - }, - { - "@id": "./tools/CRISPRCasFinder/" - }, - { - "@id": "./tools/fastp/" - }, - { - "@id": "./tools/GO-slim/" - }, - { - "@id": "./tools/hmmer/" - }, - { - "@id": "./tools/InterProScan/" - }, - { - "@id": "./tools/mask-for-ITS/" - }, - { - "@id": "./tools/Pfam-Parse/" - }, - { - "@id": "./tools/qc-filtering/" - }, - { - "@id": "./tools/qc-stats/" - }, - { - "@id": "./tools/Raw_reads/" - }, - { - "@id": "./tools/RNA_prediction/" - }, - { - "@id": "./tools/SeqPrep/" - }, - { - "@id": "./tools/summaries/" - }, - { - "@id": "./tools/Trimmomatic/" - } - ] - }, - { - "@id": "./tools/Assembly/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/accessioning/" - }, - { - "@id": "./tools/Assembly/antismash/" - }, - { - "@id": "./tools/Assembly/Diamond/" - }, - { - "@id": "./tools/Assembly/EggNOG/" - }, - { - "@id": "./tools/Assembly/generate_mapfile/" - }, - { - "@id": "./tools/Assembly/Genome_properties/" - }, - { - "@id": "./tools/Assembly/GFF/" - }, - { - "@id": "./tools/Assembly/index_fasta/" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/" - } - ] - }, - { - "@id": "./tools/Assembly/accessioning/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/accessioning/add_run_to_db/" - }, - { - "@id": "./tools/Assembly/accessioning/assign_MGYC/" - }, - { - "@id": "./tools/Assembly/accessioning/assign_MGYP/" - }, - { - "@id": "./tools/Assembly/accessioning/scripts/" - }, - { - "@id": "./tools/Assembly/accessioning/Dockerfile" - } - ] - }, - { - "@id": "./tools/Assembly/accessioning/add_run_to_db/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/accessioning/add_run_to_db/add_run_db.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/accessioning/add_run_to_db/add_run_db.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/accessioning/assign_MGYC/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/accessioning/assign_MGYC/assign_mgyc.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/accessioning/assign_MGYC/assign_mgyc.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/accessioning/assign_MGYP/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/accessioning/assign_MGYP/assign_mgyp.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/accessioning/assign_MGYP/assign_mgyp.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/accessioning/scripts/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/accessioning/scripts/add_run.py" - }, - { - "@id": "./tools/Assembly/accessioning/scripts/assign_mgyc.py" - }, - { - "@id": "./tools/Assembly/accessioning/scripts/assign_mgyp_db.py" - } - ] - }, - { - "@id": "./tools/Assembly/accessioning/scripts/add_run.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/accessioning/scripts/assign_mgyc.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/accessioning/scripts/assign_mgyp_db.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/accessioning/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/" - }, - { - "@id": "./tools/Assembly/antismash/move_antismash_summary/" - }, - { - "@id": "./tools/Assembly/antismash/__init__.py" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/antismash/" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/check_value/" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/filtering_fasta/" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/rename_contigs/" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/Dockerfile" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/__init__.py" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/antismash/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/antismash/antismash_v4.cwl" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/antismash/install_4.2.0.sh" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/antismash/run_antismash_short.sh" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/antismash/antismash_v4.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/antismash/install_4.2.0.sh", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/antismash/run_antismash_short.sh", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/check_value/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/check_value/check_value.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/check_value/check_value.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/filtering_fasta/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/filtering_fasta/filtering_fasta_for_antismash.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/filtering_fasta/filtering_fasta_for_antismash.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_embl_gbk/" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_geneclusters_txt/" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/GFF_antismash/" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/reformat_antismash/" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/__init__.py" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_embl_gbk/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_embl_gbk/change_antismash_output.py" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_embl_gbk/change_output.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_embl_gbk/change_antismash_output.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_embl_gbk/change_output.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_geneclusters_txt/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_geneclusters_txt/change_geneclusters_ctg.py" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_geneclusters_txt/change_geneclusters_txt.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_geneclusters_txt/change_geneclusters_ctg.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/fix_geneclusters_txt/change_geneclusters_txt.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/GFF_antismash/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/GFF_antismash/antismash_to_gff.cwl" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/GFF_antismash/antismash_to_gff_nojson.py" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/GFF_antismash/__init__.py" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/GFF_antismash/antismash_to_gff.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/GFF_antismash/antismash_to_gff_nojson.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/GFF_antismash/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/reformat_antismash/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/reformat_antismash/reformat-antismash.cwl" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/reformat_antismash/reformat-antismash.py" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/reformat_antismash/__init__.py" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/reformat_antismash/reformat-antismash.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/reformat_antismash/reformat-antismash.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/reformat_antismash/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/post-processing/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/rename_contigs/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/rename_contigs/antismash_rename_contigs.py" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/rename_contigs/rename_contigs.cwl" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/rename_contigs/__init__.py" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/rename_contigs/antismash_rename_contigs.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/rename_contigs/rename_contigs.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/rename_contigs/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/chunking_antismash_with_conditionals/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/move_antismash_summary/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/antismash/move_antismash_summary/move_antismash_summary.cwl" - }, - { - "@id": "./tools/Assembly/antismash/move_antismash_summary/move_antismash_summary.py" - }, - { - "@id": "./tools/Assembly/antismash/move_antismash_summary/__init__.py" - } - ] - }, - { - "@id": "./tools/Assembly/antismash/move_antismash_summary/move_antismash_summary.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/move_antismash_summary/move_antismash_summary.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/move_antismash_summary/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/antismash/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/Diamond/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/Diamond/Diamond-Post-Processing/" - }, - { - "@id": "./tools/Assembly/Diamond/yml-formats/" - }, - { - "@id": "./tools/Assembly/Diamond/Diamond.blastp.cwl" - }, - { - "@id": "./tools/Assembly/Diamond/Dockerfile" - } - ] - }, - { - "@id": "./tools/Assembly/Diamond/Diamond-Post-Processing/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/Diamond/Diamond-Post-Processing/diamond_join.cwl" - }, - { - "@id": "./tools/Assembly/Diamond/Diamond-Post-Processing/diamond_post_run_join.sh" - }, - { - "@id": "./tools/Assembly/Diamond/Diamond-Post-Processing/diamond_sorting.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/Diamond/Diamond-Post-Processing/diamond_join.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/Diamond/Diamond-Post-Processing/diamond_post_run_join.sh", - "@type": "File" - }, - { - "@id": "./tools/Assembly/Diamond/Diamond-Post-Processing/diamond_sorting.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/Diamond/yml-formats/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/Diamond/yml-formats/Diamond-output_formats.yaml" - }, - { - "@id": "./tools/Assembly/Diamond/yml-formats/Diamond-strand_values.yaml" - } - ] - }, - { - "@id": "./tools/Assembly/Diamond/yml-formats/Diamond-output_formats.yaml", - "@type": "File" - }, - { - "@id": "./tools/Assembly/Diamond/yml-formats/Diamond-strand_values.yaml", - "@type": "File" - }, - { - "@id": "./tools/Assembly/Diamond/Diamond.blastp.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/Diamond/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Assembly/EggNOG/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/EggNOG/Dockerfile" - }, - { - "@id": "./tools/Assembly/EggNOG/eggnog.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/EggNOG/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Assembly/EggNOG/eggnog.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/generate_mapfile/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/generate_mapfile/generate_mapfile_prodigal.cwl" - }, - { - "@id": "./tools/Assembly/generate_mapfile/generate_mapfile_prodigal.py" - }, - { - "@id": "./tools/Assembly/generate_mapfile/__init__.py" - } - ] - }, - { - "@id": "./tools/Assembly/generate_mapfile/generate_mapfile_prodigal.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/generate_mapfile/generate_mapfile_prodigal.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/generate_mapfile/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/Genome_properties/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/Genome_properties/Dockerfile" - }, - { - "@id": "./tools/Assembly/Genome_properties/genome_properties.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/Genome_properties/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Assembly/Genome_properties/genome_properties.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/GFF/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/GFF/build_assembly_gff.py" - }, - { - "@id": "./tools/Assembly/GFF/gff_generation.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/GFF/build_assembly_gff.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/GFF/gff_generation.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/index_fasta/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/index_fasta/fasta_index.cwl" - }, - { - "@id": "./tools/Assembly/index_fasta/run_samtools_docker.sh" - } - ] - }, - { - "@id": "./tools/Assembly/index_fasta/fasta_index.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/index_fasta/run_samtools_docker.sh", - "@type": "File" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/KEGG_analysis/KEGG_pathways/" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/Modification/" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/Parsing_hmmscan/" - } - ] - }, - { - "@id": "./tools/Assembly/KEGG_analysis/KEGG_pathways/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/KEGG_analysis/KEGG_pathways/give_pathways.py" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/KEGG_pathways/kegg_pathways.cwl" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/KEGG_pathways/make_graphs.py" - } - ] - }, - { - "@id": "./tools/Assembly/KEGG_analysis/KEGG_pathways/give_pathways.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/KEGG_pathways/kegg_pathways.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/KEGG_pathways/make_graphs.py", - "@type": "File" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/Modification/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/KEGG_analysis/Modification/modification_table.cwl" - } - ] - }, - { - "@id": "./tools/Assembly/KEGG_analysis/Modification/modification_table.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/Parsing_hmmscan/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Assembly/KEGG_analysis/Parsing_hmmscan/parsing_hmmscan.cwl" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/Parsing_hmmscan/parsing_hmmscan.py" - } - ] - }, - { - "@id": "./tools/Assembly/KEGG_analysis/Parsing_hmmscan/parsing_hmmscan.cwl", - "@type": "File" - }, - { - "@id": "./tools/Assembly/KEGG_analysis/Parsing_hmmscan/parsing_hmmscan.py", - "@type": "File" - }, - { - "@id": "./tools/chunks/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/chunks/dna_chunker/" - }, - { - "@id": "./tools/chunks/protein_chunker.cwl" - }, - { - "@id": "./tools/chunks/split_to_chunks.py" - } - ] - }, - { - "@id": "./tools/chunks/dna_chunker/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/chunks/dna_chunker/Dockerfile" - }, - { - "@id": "./tools/chunks/dna_chunker/esl-ssplit.pl" - }, - { - "@id": "./tools/chunks/dna_chunker/esl-ssplit.sh" - }, - { - "@id": "./tools/chunks/dna_chunker/fasta_chunker.cwl" - } - ] - }, - { - "@id": "./tools/chunks/dna_chunker/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/chunks/dna_chunker/esl-ssplit.pl", - "@type": "File" - }, - { - "@id": "./tools/chunks/dna_chunker/esl-ssplit.sh", - "@type": "File" - }, - { - "@id": "./tools/chunks/dna_chunker/fasta_chunker.cwl", - "@type": "File" - }, - { - "@id": "./tools/chunks/protein_chunker.cwl", - "@type": "File" - }, - { - "@id": "./tools/chunks/split_to_chunks.py", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Combined_gene_caller/CGC/" - }, - { - "@id": "./tools/Combined_gene_caller/FragGeneScan/" - }, - { - "@id": "./tools/Combined_gene_caller/Prodigal/" - }, - { - "@id": "./tools/Combined_gene_caller/Dockerfile" - }, - { - "@id": "./tools/Combined_gene_caller/faselector" - }, - { - "@id": "./tools/Combined_gene_caller/post-processing.cwl" - }, - { - "@id": "./tools/Combined_gene_caller/unite_protein_predictions.py" - }, - { - "@id": "./tools/Combined_gene_caller/__init__.py" - } - ] - }, - { - "@id": "./tools/Combined_gene_caller/CGC/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Combined_gene_caller/CGC/combined_gene_caller.cwl" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/combined_gene_caller.py" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/combined_gene_caller_conf.json" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/combined_gene_caller_docker.py" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/Dockerfile" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/__init__.py" - } - ] - }, - { - "@id": "./tools/Combined_gene_caller/CGC/combined_gene_caller.cwl", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/combined_gene_caller.py", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/combined_gene_caller_conf.json", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/combined_gene_caller_docker.py", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/CGC/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/FragGeneScan/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Combined_gene_caller/FragGeneScan/Dockerfile" - }, - { - "@id": "./tools/Combined_gene_caller/FragGeneScan/FGS.cwl" - } - ] - }, - { - "@id": "./tools/Combined_gene_caller/FragGeneScan/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/FragGeneScan/FGS.cwl", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/Prodigal/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Combined_gene_caller/Prodigal/Dockerfile" - }, - { - "@id": "./tools/Combined_gene_caller/Prodigal/prodigal.cwl" - } - ] - }, - { - "@id": "./tools/Combined_gene_caller/Prodigal/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/Prodigal/prodigal.cwl", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/faselector", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/post-processing.cwl", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/unite_protein_predictions.py", - "@type": "File" - }, - { - "@id": "./tools/Combined_gene_caller/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/CRISPRCasFinder/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/CRISPRCasFinder/CRISPRCasFinder.cwl" - }, - { - "@id": "./tools/CRISPRCasFinder/CRISPRCasFinder2Fasta.cwl" - }, - { - "@id": "./tools/CRISPRCasFinder/CRISPRCasFinder2GFF.cwl" - }, - { - "@id": "./tools/CRISPRCasFinder/crisprcf2fasta.py" - }, - { - "@id": "./tools/CRISPRCasFinder/crisprcf2gff.py" - }, - { - "@id": "./tools/CRISPRCasFinder/Dockerfile" - }, - { - "@id": "./tools/CRISPRCasFinder/runCRISPRCasFinderl.cwl" - } - ] - }, - { - "@id": "./tools/CRISPRCasFinder/CRISPRCasFinder.cwl", - "@type": "File" - }, - { - "@id": "./tools/CRISPRCasFinder/CRISPRCasFinder2Fasta.cwl", - "@type": "File" - }, - { - "@id": "./tools/CRISPRCasFinder/CRISPRCasFinder2GFF.cwl", - "@type": "File" - }, - { - "@id": "./tools/CRISPRCasFinder/crisprcf2fasta.py", - "@type": "File" - }, - { - "@id": "./tools/CRISPRCasFinder/crisprcf2gff.py", - "@type": "File" - }, - { - "@id": "./tools/CRISPRCasFinder/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/CRISPRCasFinder/runCRISPRCasFinderl.cwl", - "@type": "File" - }, - { - "@id": "./tools/fastp/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/fastp/Dockerfile" - }, - { - "@id": "./tools/fastp/fastp.cwl" - }, - { - "@id": "./tools/fastp/fastp.yml" - } - ] - }, - { - "@id": "./tools/fastp/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/fastp/fastp.cwl", - "@type": "File" - }, - { - "@id": "./tools/fastp/fastp.yml", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/GO-slim/owltools/" - }, - { - "@id": "./tools/GO-slim/Dockerfile" - }, - { - "@id": "./tools/GO-slim/go-basic-metagenomics_release_20160705.obo" - }, - { - "@id": "./tools/GO-slim/go-basic-metagenomics_release_20160705.txt" - }, - { - "@id": "./tools/GO-slim/go_summary-config.json" - }, - { - "@id": "./tools/GO-slim/go_summary.cwl" - }, - { - "@id": "./tools/GO-slim/go_summary_pipeline-1.0.py" - }, - { - "@id": "./tools/GO-slim/metagenomics_go_slim_banding.txt" - }, - { - "@id": "./tools/GO-slim/metagenomics_go_slim_ids.txt" - } - ] - }, - { - "@id": "./tools/GO-slim/owltools/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/GO-slim/owltools/owltools" - }, - { - "@id": "./tools/GO-slim/owltools/owltools-runner-all.jar" - }, - { - "@id": "./tools/GO-slim/owltools/owltools.vmoptions" - } - ] - }, - { - "@id": "./tools/GO-slim/owltools/owltools", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/owltools/owltools-runner-all.jar", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/owltools/owltools.vmoptions", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/go-basic-metagenomics_release_20160705.obo", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/go-basic-metagenomics_release_20160705.txt", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/go_summary-config.json", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/go_summary.cwl", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/go_summary_pipeline-1.0.py", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/metagenomics_go_slim_banding.txt", - "@type": "File" - }, - { - "@id": "./tools/GO-slim/metagenomics_go_slim_ids.txt", - "@type": "File" - }, - { - "@id": "./tools/hmmer/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/hmmer/hmmer_tab_modification/" - }, - { - "@id": "./tools/hmmer/hmmscan/" - }, - { - "@id": "./tools/hmmer/hmmsearch/" - }, - { - "@id": "./tools/hmmer/Dockerfile" - }, - { - "@id": "./tools/hmmer/__init__.py" - } - ] - }, - { - "@id": "./tools/hmmer/hmmer_tab_modification/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/hmmer/hmmer_tab_modification/hmmer_tab_modification.cwl" - }, - { - "@id": "./tools/hmmer/hmmer_tab_modification/hmmscan_tab.py" - }, - { - "@id": "./tools/hmmer/hmmer_tab_modification/__init__.py" - } - ] - }, - { - "@id": "./tools/hmmer/hmmer_tab_modification/hmmer_tab_modification.cwl", - "@type": "File" - }, - { - "@id": "./tools/hmmer/hmmer_tab_modification/hmmscan_tab.py", - "@type": "File" - }, - { - "@id": "./tools/hmmer/hmmer_tab_modification/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/hmmer/hmmscan/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/hmmer/hmmscan/hmmscan-subwf.cwl" - }, - { - "@id": "./tools/hmmer/hmmscan/hmmscan.cwl" - }, - { - "@id": "./tools/hmmer/hmmscan/__init__.py" - } - ] - }, - { - "@id": "./tools/hmmer/hmmscan/hmmscan-subwf.cwl", - "@type": "File" - }, - { - "@id": "./tools/hmmer/hmmscan/hmmscan.cwl", - "@type": "File" - }, - { - "@id": "./tools/hmmer/hmmscan/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/hmmer/hmmsearch/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/hmmer/hmmsearch/hmmsearch.cwl" - } - ] - }, - { - "@id": "./tools/hmmer/hmmsearch/hmmsearch.cwl", - "@type": "File" - }, - { - "@id": "./tools/hmmer/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/hmmer/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/InterProScan/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/InterProScan/types-ymls/" - }, - { - "@id": "./tools/InterProScan/Dockerfile" - }, - { - "@id": "./tools/InterProScan/Dockerfile_data" - }, - { - "@id": "./tools/InterProScan/InterProScan-v5.cwl" - } - ] - }, - { - "@id": "./tools/InterProScan/types-ymls/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/InterProScan/types-ymls/InterProScan-apps.yaml" - }, - { - "@id": "./tools/InterProScan/types-ymls/InterProScan-protein_formats.yaml" - } - ] - }, - { - "@id": "./tools/InterProScan/types-ymls/InterProScan-apps.yaml", - "@type": "File" - }, - { - "@id": "./tools/InterProScan/types-ymls/InterProScan-protein_formats.yaml", - "@type": "File" - }, - { - "@id": "./tools/InterProScan/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/InterProScan/Dockerfile_data", - "@type": "File" - }, - { - "@id": "./tools/InterProScan/InterProScan-v5.cwl", - "@type": "File" - }, - { - "@id": "./tools/mask-for-ITS/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/mask-for-ITS/bash_scripts/" - }, - { - "@id": "./tools/mask-for-ITS/bedtools/" - }, - { - "@id": "./tools/mask-for-ITS/bedtools.yml" - }, - { - "@id": "./tools/mask-for-ITS/format-bedfile.cwl" - }, - { - "@id": "./tools/mask-for-ITS/its-length-new.py" - }, - { - "@id": "./tools/mask-for-ITS/suppress_tax.cwl" - } - ] - }, - { - "@id": "./tools/mask-for-ITS/bash_scripts/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/mask-for-ITS/bash_scripts/format_bedfile" - } - ] - }, - { - "@id": "./tools/mask-for-ITS/bash_scripts/format_bedfile", - "@type": "File" - }, - { - "@id": "./tools/mask-for-ITS/bedtools/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/mask-for-ITS/bedtools/bedtools.cwl" - }, - { - "@id": "./tools/mask-for-ITS/bedtools/Dockerfile" - } - ] - }, - { - "@id": "./tools/mask-for-ITS/bedtools/bedtools.cwl", - "@type": "File" - }, - { - "@id": "./tools/mask-for-ITS/bedtools/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/mask-for-ITS/bedtools.yml", - "@type": "File" - }, - { - "@id": "./tools/mask-for-ITS/format-bedfile.cwl", - "@type": "File" - }, - { - "@id": "./tools/mask-for-ITS/its-length-new.py", - "@type": "File" - }, - { - "@id": "./tools/mask-for-ITS/suppress_tax.cwl", - "@type": "File" - }, - { - "@id": "./tools/Pfam-Parse/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Pfam-Parse/pfam_annotations.cwl" - } - ] - }, - { - "@id": "./tools/Pfam-Parse/pfam_annotations.cwl", - "@type": "File" - }, - { - "@id": "./tools/qc-filtering/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/qc-filtering/qc-filtering.cwl" - }, - { - "@id": "./tools/qc-filtering/run_quality_filtering.py" - } - ] - }, - { - "@id": "./tools/qc-filtering/qc-filtering.cwl", - "@type": "File" - }, - { - "@id": "./tools/qc-filtering/run_quality_filtering.py", - "@type": "File" - }, - { - "@id": "./tools/qc-stats/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/qc-stats/MGRAST_base.py" - }, - { - "@id": "./tools/qc-stats/qc-stats.cwl" - } - ] - }, - { - "@id": "./tools/qc-stats/MGRAST_base.py", - "@type": "File" - }, - { - "@id": "./tools/qc-stats/qc-stats.cwl", - "@type": "File" - }, - { - "@id": "./tools/Raw_reads/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Raw_reads/mOTUs/" - } - ] - }, - { - "@id": "./tools/Raw_reads/mOTUs/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Raw_reads/mOTUs/clean_motus_output.cwl" - }, - { - "@id": "./tools/Raw_reads/mOTUs/clean_motus_output.sh" - }, - { - "@id": "./tools/Raw_reads/mOTUs/Dockerfile" - }, - { - "@id": "./tools/Raw_reads/mOTUs/mOTUs.cwl" - }, - { - "@id": "./tools/Raw_reads/mOTUs/mOTUs_download_db.py" - } - ] - }, - { - "@id": "./tools/Raw_reads/mOTUs/clean_motus_output.cwl", - "@type": "File" - }, - { - "@id": "./tools/Raw_reads/mOTUs/clean_motus_output.sh", - "@type": "File" - }, - { - "@id": "./tools/Raw_reads/mOTUs/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Raw_reads/mOTUs/mOTUs.cwl", - "@type": "File" - }, - { - "@id": "./tools/Raw_reads/mOTUs/mOTUs_download_db.py", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/biom-convert/" - }, - { - "@id": "./tools/RNA_prediction/cmsearch/" - }, - { - "@id": "./tools/RNA_prediction/cmsearch-deoverlap/" - }, - { - "@id": "./tools/RNA_prediction/easel/" - }, - { - "@id": "./tools/RNA_prediction/extract-coords/" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_coords/" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_fasta/" - }, - { - "@id": "./tools/RNA_prediction/krona/" - }, - { - "@id": "./tools/RNA_prediction/mapseq/" - }, - { - "@id": "./tools/RNA_prediction/mapseq2biom/" - }, - { - "@id": "./tools/RNA_prediction/pull_ncrnas/" - } - ] - }, - { - "@id": "./tools/RNA_prediction/biom-convert/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/biom-convert/biom-convert-table.yaml" - }, - { - "@id": "./tools/RNA_prediction/biom-convert/biom-convert.cwl" - }, - { - "@id": "./tools/RNA_prediction/biom-convert/biom-convert.sh" - }, - { - "@id": "./tools/RNA_prediction/biom-convert/Dockerfile" - } - ] - }, - { - "@id": "./tools/RNA_prediction/biom-convert/biom-convert-table.yaml", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/biom-convert/biom-convert.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/biom-convert/biom-convert.sh", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/biom-convert/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/cmsearch/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/cmsearch/Dockerfile" - }, - { - "@id": "./tools/RNA_prediction/cmsearch/infernal-cmsearch-v1.1.2.cwl" - } - ] - }, - { - "@id": "./tools/RNA_prediction/cmsearch/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/cmsearch/infernal-cmsearch-v1.1.2.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/cmsearch-deoverlap/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/cmsearch-deoverlap/cmsearch-deoverlap-v0.02.cwl" - }, - { - "@id": "./tools/RNA_prediction/cmsearch-deoverlap/cmsearch-deoverlap.pl" - }, - { - "@id": "./tools/RNA_prediction/cmsearch-deoverlap/Dockerfile" - } - ] - }, - { - "@id": "./tools/RNA_prediction/cmsearch-deoverlap/cmsearch-deoverlap-v0.02.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/cmsearch-deoverlap/cmsearch-deoverlap.pl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/cmsearch-deoverlap/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/easel/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/easel/Dockerfile" - }, - { - "@id": "./tools/RNA_prediction/easel/esl-index.sh" - }, - { - "@id": "./tools/RNA_prediction/easel/esl-sfetch-index.cwl" - }, - { - "@id": "./tools/RNA_prediction/easel/esl-sfetch-manyseqs.cwl" - } - ] - }, - { - "@id": "./tools/RNA_prediction/easel/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/easel/esl-index.sh", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/easel/esl-sfetch-index.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/easel/esl-sfetch-manyseqs.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/extract-coords/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/extract-coords/awk_tool" - }, - { - "@id": "./tools/RNA_prediction/extract-coords/Dockerfile" - }, - { - "@id": "./tools/RNA_prediction/extract-coords/extract-coords.cwl" - }, - { - "@id": "./tools/RNA_prediction/extract-coords/extract-coords_awk.cwl" - } - ] - }, - { - "@id": "./tools/RNA_prediction/extract-coords/awk_tool", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/extract-coords/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/extract-coords/extract-coords.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/extract-coords/extract-coords_awk.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_coords/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/get_subunits_coords/get_subunits_coords.cwl" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_coords/get_subunits_coords.py" - } - ] - }, - { - "@id": "./tools/RNA_prediction/get_subunits_coords/get_subunits_coords.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_coords/get_subunits_coords.py", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_fasta/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/get_subunits_fasta/get_subunits.cwl" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_fasta/get_subunits.py" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_fasta/__init__.py" - } - ] - }, - { - "@id": "./tools/RNA_prediction/get_subunits_fasta/get_subunits.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_fasta/get_subunits.py", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/get_subunits_fasta/__init__.py", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/krona/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/krona/Dockerfile" - }, - { - "@id": "./tools/RNA_prediction/krona/krona.cwl" - } - ] - }, - { - "@id": "./tools/RNA_prediction/krona/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/krona/krona.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/mapseq/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/mapseq/Dockerfile" - }, - { - "@id": "./tools/RNA_prediction/mapseq/mapseq.cwl" - } - ] - }, - { - "@id": "./tools/RNA_prediction/mapseq/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/mapseq/mapseq.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/mapseq2biom/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/mapseq2biom/Dockerfile" - }, - { - "@id": "./tools/RNA_prediction/mapseq2biom/mapseq2biom.cwl" - }, - { - "@id": "./tools/RNA_prediction/mapseq2biom/mapseq2biom.pl" - } - ] - }, - { - "@id": "./tools/RNA_prediction/mapseq2biom/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/mapseq2biom/mapseq2biom.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/mapseq2biom/mapseq2biom.pl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/pull_ncrnas/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/RNA_prediction/pull_ncrnas/pull_ncrnas.cwl" - }, - { - "@id": "./tools/RNA_prediction/pull_ncrnas/pull_ncrnas.sh" - } - ] - }, - { - "@id": "./tools/RNA_prediction/pull_ncrnas/pull_ncrnas.cwl", - "@type": "File" - }, - { - "@id": "./tools/RNA_prediction/pull_ncrnas/pull_ncrnas.sh", - "@type": "File" - }, - { - "@id": "./tools/SeqPrep/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/SeqPrep/Dockerfile" - }, - { - "@id": "./tools/SeqPrep/seqprep.cwl" - } - ] - }, - { - "@id": "./tools/SeqPrep/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/SeqPrep/seqprep.cwl", - "@type": "File" - }, - { - "@id": "./tools/summaries/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/summaries/functional_stats.cwl" - }, - { - "@id": "./tools/summaries/functional_stats.py" - }, - { - "@id": "./tools/summaries/write_summaries.cwl" - }, - { - "@id": "./tools/summaries/write_summaries.py" - } - ] - }, - { - "@id": "./tools/summaries/functional_stats.cwl", - "@type": "File" - }, - { - "@id": "./tools/summaries/functional_stats.py", - "@type": "File" - }, - { - "@id": "./tools/summaries/write_summaries.cwl", - "@type": "File" - }, - { - "@id": "./tools/summaries/write_summaries.py", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Trimmomatic/ymls-types/" - }, - { - "@id": "./tools/Trimmomatic/Dockerfile" - }, - { - "@id": "./tools/Trimmomatic/LICENSE" - }, - { - "@id": "./tools/Trimmomatic/trimmomatic" - }, - { - "@id": "./tools/Trimmomatic/trimmomatic-0.36.jar" - }, - { - "@id": "./tools/Trimmomatic/Trimmomatic-v0.36-PE.cwl" - }, - { - "@id": "./tools/Trimmomatic/Trimmomatic-v0.36-SE.cwl" - }, - { - "@id": "./tools/Trimmomatic/trimmomatic.jar" - }, - { - "@id": "./tools/Trimmomatic/trimmomatic_help.txt" - } - ] - }, - { - "@id": "./tools/Trimmomatic/ymls-types/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-end_mode.yaml" - }, - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-illumina_clipping.yaml" - }, - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-max_info.yaml" - }, - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-phred.yaml" - }, - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-sliding_window.yaml" - } - ] - }, - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-end_mode.yaml", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-illumina_clipping.yaml", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-max_info.yaml", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-phred.yaml", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/ymls-types/trimmomatic-sliding_window.yaml", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/Dockerfile", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/LICENSE", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/trimmomatic", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/trimmomatic-0.36.jar", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/Trimmomatic-v0.36-PE.cwl", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/Trimmomatic-v0.36-SE.cwl", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/trimmomatic.jar", - "@type": "File" - }, - { - "@id": "./tools/Trimmomatic/trimmomatic_help.txt", - "@type": "File" - }, - { - "@id": "./utils/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/add_header/" - }, - { - "@id": "./utils/count_lines/" - }, - { - "@id": "./utils/fastq_to_fasta/" - }, - { - "@id": "./utils/generate_checksum/" - }, - { - "@id": "./utils/make_csv/" - }, - { - "@id": "./utils/pigz/" - }, - { - "@id": "./utils/remove_header/" - }, - { - "@id": "./utils/result-file-chunker/" - }, - { - "@id": "./utils/return_directory/" - }, - { - "@id": "./utils/clean_fasta_headers.cwl" - }, - { - "@id": "./utils/concatenate.cwl" - }, - { - "@id": "./utils/count_fasta.cwl" - }, - { - "@id": "./utils/count_number_lines.cwl" - }, - { - "@id": "./utils/make_flatten.cwl" - }, - { - "@id": "./utils/make_tab_sep.cwl" - }, - { - "@id": "./utils/move.cwl" - }, - { - "@id": "./utils/multiple-gunzip.cwl" - }, - { - "@id": "./utils/qc-flag.cwl" - }, - { - "@id": "./utils/size_file.cwl" - }, - { - "@id": "./utils/touch_file.cwl" - } - ] - }, - { - "@id": "./utils/add_header/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/add_header/add_header" - }, - { - "@id": "./utils/add_header/add_header.cwl" - } - ] - }, - { - "@id": "./utils/add_header/add_header", - "@type": "File" - }, - { - "@id": "./utils/add_header/add_header.cwl", - "@type": "File" - }, - { - "@id": "./utils/count_lines/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/count_lines/count_lines.cwl" - }, - { - "@id": "./utils/count_lines/count_lines.py" - } - ] - }, - { - "@id": "./utils/count_lines/count_lines.cwl", - "@type": "File" - }, - { - "@id": "./utils/count_lines/count_lines.py", - "@type": "File" - }, - { - "@id": "./utils/fastq_to_fasta/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/fastq_to_fasta/fastq_to_fasta.cwl" - }, - { - "@id": "./utils/fastq_to_fasta/fastq_to_fasta.py" - } - ] - }, - { - "@id": "./utils/fastq_to_fasta/fastq_to_fasta.cwl", - "@type": "File" - }, - { - "@id": "./utils/fastq_to_fasta/fastq_to_fasta.py", - "@type": "File" - }, - { - "@id": "./utils/generate_checksum/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/generate_checksum/generate_checksum.cwl" - }, - { - "@id": "./utils/generate_checksum/generate_checksum.py" - } - ] - }, - { - "@id": "./utils/generate_checksum/generate_checksum.cwl", - "@type": "File" - }, - { - "@id": "./utils/generate_checksum/generate_checksum.py", - "@type": "File" - }, - { - "@id": "./utils/make_csv/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/make_csv/make_csv.cwl" - }, - { - "@id": "./utils/make_csv/make_csv.py" - } - ] - }, - { - "@id": "./utils/make_csv/make_csv.cwl", - "@type": "File" - }, - { - "@id": "./utils/make_csv/make_csv.py", - "@type": "File" - }, - { - "@id": "./utils/pigz/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/pigz/gzip.cwl" - } - ] - }, - { - "@id": "./utils/pigz/gzip.cwl", - "@type": "File" - }, - { - "@id": "./utils/remove_header/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/remove_header/remove_headers.cwl" - }, - { - "@id": "./utils/remove_header/remove_headers.yml" - } - ] - }, - { - "@id": "./utils/remove_header/remove_headers.cwl", - "@type": "File" - }, - { - "@id": "./utils/remove_header/remove_headers.yml", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/result-file-chunker/old_scripts/" - }, - { - "@id": "./utils/result-file-chunker/create_chunks_file.cwl" - }, - { - "@id": "./utils/result-file-chunker/Dockerfile" - }, - { - "@id": "./utils/result-file-chunker/result_chunker.cwl" - }, - { - "@id": "./utils/result-file-chunker/result_chunker_subwf.cwl" - }, - { - "@id": "./utils/result-file-chunker/split_fasta.cwl" - }, - { - "@id": "./utils/result-file-chunker/split_fasta_by_size.sh" - }, - { - "@id": "./utils/result-file-chunker/split_tsv.cwl" - } - ] - }, - { - "@id": "./utils/result-file-chunker/old_scripts/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/result-file-chunker/old_scripts/chunkFastaResultFileUtil.py" - }, - { - "@id": "./utils/result-file-chunker/old_scripts/chunkTSVFileUtil.py" - }, - { - "@id": "./utils/result-file-chunker/old_scripts/cleaningUtils.py" - }, - { - "@id": "./utils/result-file-chunker/old_scripts/run_result_file_chunker.py" - } - ] - }, - { - "@id": "./utils/result-file-chunker/old_scripts/chunkFastaResultFileUtil.py", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/old_scripts/chunkTSVFileUtil.py", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/old_scripts/cleaningUtils.py", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/old_scripts/run_result_file_chunker.py", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/create_chunks_file.cwl", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/Dockerfile", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/result_chunker.cwl", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/result_chunker_subwf.cwl", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/split_fasta.cwl", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/split_fasta_by_size.sh", - "@type": "File" - }, - { - "@id": "./utils/result-file-chunker/split_tsv.cwl", - "@type": "File" - }, - { - "@id": "./utils/return_directory/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./utils/return_directory/return_directory.cwl" - } - ] - }, - { - "@id": "./utils/return_directory/return_directory.cwl", - "@type": "File" - }, - { - "@id": "./utils/clean_fasta_headers.cwl", - "@type": "File" - }, - { - "@id": "./utils/concatenate.cwl", - "@type": "File" - }, - { - "@id": "./utils/count_fasta.cwl", - "@type": "File" - }, - { - "@id": "./utils/count_number_lines.cwl", - "@type": "File" - }, - { - "@id": "./utils/make_flatten.cwl", - "@type": "File" - }, - { - "@id": "./utils/make_tab_sep.cwl", - "@type": "File" - }, - { - "@id": "./utils/move.cwl", - "@type": "File" - }, - { - "@id": "./utils/multiple-gunzip.cwl", - "@type": "File" - }, - { - "@id": "./utils/qc-flag.cwl", - "@type": "File" - }, - { - "@id": "./utils/size_file.cwl", - "@type": "File" - }, - { - "@id": "./utils/touch_file.cwl", - "@type": "File" - }, - { - "@id": "./workflows/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/conditionals/" - }, - { - "@id": "./workflows/subworkflows/" - }, - { - "@id": "./workflows/gos_wf.cwl" - } - ] - }, - { - "@id": "./workflows/conditionals/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/conditionals/megahit.cwl" - }, - { - "@id": "./workflows/conditionals/qc.cwl" - }, - { - "@id": "./workflows/conditionals/raw-reads-2.cwl" - }, - { - "@id": "./workflows/conditionals/rna-prediction.cwl" - } - ] - }, - { - "@id": "./workflows/conditionals/megahit.cwl", - "@type": "File" - }, - { - "@id": "./workflows/conditionals/qc.cwl", - "@type": "File" - }, - { - "@id": "./workflows/conditionals/raw-reads-2.cwl", - "@type": "File" - }, - { - "@id": "./workflows/conditionals/rna-prediction.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/amplicon/" - }, - { - "@id": "./workflows/subworkflows/assembly/" - }, - { - "@id": "./workflows/subworkflows/cmsearch/" - }, - { - "@id": "./workflows/subworkflows/functional-annotation/" - }, - { - "@id": "./workflows/subworkflows/hmmer/" - }, - { - "@id": "./workflows/subworkflows/raw_reads/" - }, - { - "@id": "./workflows/subworkflows/chunking-subwf-IPS.cwl" - }, - { - "@id": "./workflows/subworkflows/classify-otu-visualise.cwl" - }, - { - "@id": "./workflows/subworkflows/final_chunking.cwl" - }, - { - "@id": "./workflows/subworkflows/func_summaries.cwl" - }, - { - "@id": "./workflows/subworkflows/other_ncrnas.cwl" - }, - { - "@id": "./workflows/subworkflows/rna_prediction-sub-wf.cwl" - }, - { - "@id": "./workflows/subworkflows/seqprep-qc-cond-subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/seqprep-subwf.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/amplicon/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/amplicon/ITS-wf.cwl" - }, - { - "@id": "./workflows/subworkflows/amplicon/trimming-not-empty-subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/amplicon/trim_and_reformat_reads.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/amplicon/ITS-wf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/amplicon/trimming-not-empty-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/amplicon/trim_and_reformat_reads.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/assembly/antismash/" - }, - { - "@id": "./workflows/subworkflows/assembly/cgc/" - }, - { - "@id": "./workflows/subworkflows/assembly/diamond/" - }, - { - "@id": "./workflows/subworkflows/assembly/accessioning-prediction_subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/change_formats_and_names.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/deal_with_functional_annotation.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/eggnog-subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/Func_ann_and_post_processing-subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/kegg_analysis.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/assembly/antismash/antismash-annotation-subsubwf.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/antismash_chunking_subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/main_antismash_subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/no_antismash_subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/split_subwf_perl.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/antismash-annotation-subsubwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/antismash_chunking_subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/main_antismash_subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/no_antismash_subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/antismash/split_subwf_perl.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/cgc/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/assembly/cgc/CGC-subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/cgc/predict_proteins_assemblies.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/assembly/cgc/CGC-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/cgc/predict_proteins_assemblies.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/diamond/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/assembly/diamond/diamond-postprocessing_subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/assembly/diamond/diamond-subwf.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/assembly/diamond/diamond-postprocessing_subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/diamond/diamond-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/accessioning-prediction_subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/change_formats_and_names.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/deal_with_functional_annotation.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/eggnog-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/Func_ann_and_post_processing-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/assembly/kegg_analysis.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/cmsearch/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/cmsearch/cmsearch-condition.cwl" - }, - { - "@id": "./workflows/subworkflows/cmsearch/cmsearch-multimodel-assembly.cwl" - }, - { - "@id": "./workflows/subworkflows/cmsearch/cmsearch-multimodel-raw-data.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/cmsearch/cmsearch-condition.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/cmsearch/cmsearch-multimodel-assembly.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/cmsearch/cmsearch-multimodel-raw-data.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/functional-annotation/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/functional-annotation/functional-annotation.cwl" - }, - { - "@id": "./workflows/subworkflows/functional-annotation/post-proccessing-go-pfam-stats-subwf.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/functional-annotation/functional-annotation.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/functional-annotation/post-proccessing-go-pfam-stats-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/hmmer/db/" - }, - { - "@id": "./workflows/subworkflows/hmmer/assembly-SRR1620013_smallhmmscan_subwf" - }, - { - "@id": "./workflows/subworkflows/hmmer/assembly-SRR1620013_small_CDS.faa" - }, - { - "@id": "./workflows/subworkflows/hmmer/chunking-subwf-hmmscan.cwl" - }, - { - "@id": "./workflows/subworkflows/hmmer/chunking-subwf-hmmsearch.cwl" - }, - { - "@id": "./workflows/subworkflows/hmmer/hmmscan.yml" - } - ] - }, - { - "@id": "./workflows/subworkflows/hmmer/db/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm" - }, - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm.h3f" - }, - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm.h3i" - }, - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm.h3m" - }, - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm.h3p" - } - ] - }, - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm.h3f", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm.h3i", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm.h3m", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/db/test.hmm.h3p", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/assembly-SRR1620013_smallhmmscan_subwf", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/assembly-SRR1620013_small_CDS.faa", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/chunking-subwf-hmmscan.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/chunking-subwf-hmmsearch.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/hmmer/hmmscan.yml", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/raw_reads/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/raw_reads/cgc/" - }, - { - "@id": "./workflows/subworkflows/raw_reads/Func_ann_and_post_proccessing-subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/raw_reads/mOTUs-workflow.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/raw_reads/cgc/", - "@type": "Dataset", - "hasPart": [ - { - "@id": "./workflows/subworkflows/raw_reads/cgc/CGC-subwf.cwl" - }, - { - "@id": "./workflows/subworkflows/raw_reads/cgc/predict_proteins_reads.cwl" - } - ] - }, - { - "@id": "./workflows/subworkflows/raw_reads/cgc/CGC-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/raw_reads/cgc/predict_proteins_reads.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/raw_reads/Func_ann_and_post_proccessing-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/raw_reads/mOTUs-workflow.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/chunking-subwf-IPS.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/classify-otu-visualise.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/final_chunking.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/func_summaries.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/other_ncrnas.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/rna_prediction-sub-wf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/seqprep-qc-cond-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/subworkflows/seqprep-subwf.cwl", - "@type": "File" - }, - { - "@id": "./workflows/gos_wf.cwl", - "@type": "File" - }, - { - "@id": "./config.yml", - "@type": "File" - }, - { - "@id": "./create_yml.py", - "@type": "File" - }, - { - "@id": "./dependencies.md", - "@type": "File" - }, - { - "@id": "./learning_cwl.md", - "@type": "File" - }, - { - "@id": "./LICENSE", - "@type": "File" - }, - { - "@id": "./README.md", - "@type": "File" - }, - { - "@id": "./run_wf.sh", - "@type": "File" - }, - { - "@id": "./slurm_run.sh", - "@type": "File" - } - ] -} \ No newline at end of file From 2821479c276a7e2368ac666ff26d25faee27cde3 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Fri, 24 Mar 2023 05:55:02 +0200 Subject: [PATCH 14/26] edits to keep only for the record; remove file afterwards --- utils/create-ro-crate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/create-ro-crate.py b/utils/create-ro-crate.py index e470a71a..689d1584 100644 --- a/utils/create-ro-crate.py +++ b/utils/create-ro-crate.py @@ -201,7 +201,7 @@ def main(target_directory, metagoflow_version, run_parameter, ena_run_accession_ conf["dataPublished"] = datetime.datetime.now().strftime('%Y-%m-%d') if ena_run_accession_id == "None": - print("hello friend") + print("hi from the ro-crate.py") sys.exit(0) From 06fa1f2933bbf8da39da80b8b2f40d364c29eab6 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Fri, 24 Mar 2023 05:55:45 +0200 Subject: [PATCH 15/26] drop script --- utils/create-ro-crate.py | 376 --------------------------------------- 1 file changed, 376 deletions(-) delete mode 100644 utils/create-ro-crate.py diff --git a/utils/create-ro-crate.py b/utils/create-ro-crate.py deleted file mode 100644 index 689d1584..00000000 --- a/utils/create-ro-crate.py +++ /dev/null @@ -1,376 +0,0 @@ -#! /usr/bin/env python3 - -""" -If you invoked run_wf.sh like this, then the YAML configuration file will be -named "green.yml in the "HWLTKDRXY.UDI210" directory: - - $ run_wf.sh -n green -d HWLTKDRXY.UDI210 \ - -f input_data/${DATA_FORWARD} \ - -r input_data/${DATA_REVERSE} - -run_parameter it the "-n" value in the config.yml file: -""" - - -desc = """ -Build a MetaGOflow Data Products ro-crate. -This script is based on Cymon's J. Cox script you can find here: -https://github.com/emo-bon/MetaGOflow-Data-Products-RO-Crate/blob/main/create-ro-crate.py - -When invoked, the MetaGOflow run_wf.sh script writes all output to a directory specified by -the "-d" parameter: - - $ run_wf.sh -n green -d HWLTKDRXY-UDI210 -f input_data/${DATA_FORWARD} -r input_data/${DATA_REVERSE} - - $ tree -1 - HWLTKDRXY-UDI210 - β”œβ”€β”€ prov - β”œβ”€β”€ results - β”œβ”€β”€ green.yml - └── tmp - - 3 directories, 1 file -""" - -import os -import argparse -import textwrap -import sys -import yaml -import json -import datetime -import base64 -import requests -import tempfile -import shutil -import glob -import subprocess -import logging as log - -#This is the workflow YAML file, the prefix is the "-n" parameter of the "run_wf.sh" script: -yaml_file = "{run_parameter}.yml" - -#InterProScan file(s) have to be dealt with separately until the wf is fixed -interproscan_file = "{prefix}.merged_CDS.I5.tsv.gz" -yaml_parameters = ["prefix", - "run_parameter", - "ena_accession_raw_data", "metagoflow_version", "missing_files"] - -mandatory_files = [ - "fastp.html", - "final.contigs.fa", - "RNA-counts", - "functional-annotation/stats/go.stats", - "functional-annotation/stats/interproscan.stats", - "functional-annotation/stats/ko.stats", - "functional-annotation/stats/orf.stats", - "functional-annotation/stats/pfam.stats", - "taxonomy-summary/LSU/krona.html", - "taxonomy-summary/SSU/krona.html", - "functional-annotation/{prefix}.merged.hmm.tsv.gz", - "functional-annotation/{prefix}.merged.summary.go", - "functional-annotation/{prefix}.merged.summary.go_slim", - "functional-annotation/{prefix}.merged.summary.ips", - "functional-annotation/{prefix}.merged.summary.ko", - "functional-annotation/{prefix}.merged.summary.pfam", - "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq.gz", - "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq_hdf5.biom", - "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq_json.biom", - "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq.tsv", - "taxonomy-summary/SSU/{prefix}.merged_SSU.fasta.mseq.txt", - "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq.gz", - "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq_hdf5.biom", - "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq_json.biom", - "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq.tsv", - "taxonomy-summary/LSU/{prefix}.merged_LSU.fasta.mseq.txt" - ] - - - -VALIDATION_ERROR = """ -The RO-crate returned fails the validation test. -""" - -def writeHTMLpreview(tmpdirname): - """Write the HTML preview file using rochtml- - https://www.npmjs.com/package/ro-crate-html - """ - rochtml_path = shutil.which("rochtml") - if not rochtml_path: - log.info("HTML preview file cannot be written due to missing executable (rochtml)") - else: - cmd = "%s %s" % (rochtml_path, os.path.join(tmpdirname, "ro-crate-metadata.json")) - child = subprocess.Popen(str(cmd), stdout=subprocess.PIPE, - stderr=subprocess.PIPE, shell=True) - stdoutdata, stderrdata = child.communicate() - return_code = child.returncode - if return_code != 0: - log.error("Error whilst trying write HTML file") - log.error("Stderr: %s " % stderrdata) - log.error("Command: %s" % cmd) - log.error("Return code: %s" % return_code) - log.error("Bailing...") - sys.exit() - else: - log.info("Written HTML preview file") - -def joinInterProScanOutputFiles(target_directory, conf): - """IPS outputs one, or many, files (sigh) - - {prefix}.merged_CDS.I5.tsv.gz - or - DBB.merged_CDS.I5_00{1-9}.tsv.gz - - An issue has been raised to fix the workflow, but for the - time being we are going to cat them here - """ - log.info("Cat'ing the IPS chunk files... (this could take some time...)") - s = "{prefix}.merged_CDS.I5*tsv.gz".format(**conf) - path = os.path.join(target_directory, "results", "functional-annotation", s) - r = glob.glob(path) - if len(r) < 2: - log.error("Unable to locate 2 or more InterProScan files") - log.error("They should be of the form: {prefix}.merged_CDS.I5_00{1-9}.tsv.gz") - log.error("Bailing...") - sys.exit() - #cat the chunks together - outfile = os.path.join(target_directory, "results", "functional-annotation", - "{prefix}.merged_CDS.I5.tsv.gz".format(**conf)) - cmd = "cat %s > %s" % (" ".join(r), outfile) - child = subprocess.Popen(str(cmd), stdout=subprocess.PIPE, - stderr=subprocess.PIPE, shell=True) - stdoutdata, stderrdata = child.communicate() - return_code = child.returncode - if return_code != 0: - log.error("Error whilst trying to concatenate IPS files") - log.debug("Stderr: %s " % stderrdata) - log.debug("Files = %s" % r) - log.debug("Command: %s" % cmd) - log.debug("Return code: %s" % return_code) - log.error("Bailing...") - sys.exit() - -def sequence_categorisation_stanzas(target_directory, template): - """Glob the sequence_categorisation directory and build a stanza for each - zipped data file - - Return updated template, and list of sequence category filenames - """ - search = os.path.join(target_directory, "results", "sequence-categorisation", "*.gz") - seq_cat_paths = glob.glob(search) - seq_cat_files = [os.path.split(f)[1] for f in seq_cat_paths] - #Sequence-categorisation stanza - for i, stanza in enumerate(template["@graph"]): - if stanza["@id"] == "sequence-categorisation/": - stanza["hasPart"] = [dict([("@id", fn)]) for fn in - seq_cat_files] - sq_index = i - break - - seq_cat_files.reverse() - for fn in seq_cat_files: - d = dict([("@id", fn), ("@type", "File"), - ("encodingFormat", "application/zip")]) - template["@graph"].insert(sq_index+1, d) - return template, seq_cat_files - -def main(target_directory, metagoflow_version, run_parameter, ena_run_accession_id, debug): - - #Logging - if debug: - log_level = log.DEBUG - else: - log_level = log.INFO - log.basicConfig(format='\t%(levelname)s: %(message)s', level=log_level) - - - #Check the data directory name - data_dir = os.path.split(target_directory)[1] - if "." in data_dir: - log.error(f"The target data directory ({data_dir}) cannot have a '.' period in it!") - log.error("Change it to '-' and try again") - log.error("Bailing...") - sys.exit() - - #Read the YAML configuration - user_yaml_config = "config.yml" - with open(user_yaml_config, "r") as f: - conf = yaml.safe_load(f) - - - conf["dataPublished"] = datetime.datetime.now().strftime('%Y-%m-%d') - - if ena_run_accession_id == "None": - print("hi from the ro-crate.py") - - - sys.exit(0) - - - - - #Check yaml parameters are formated correctly, but not necessarily sane - for param in yaml_parameters: - log.debug("Config paramater: %s" % conf[param]) - - if param == "missing_files": - if not param in conf: - continue - else: - for filename in conf[param]: - if not isinstance(filename, str): - log.error(f"Parameter '{filename}' in 'missing_files' list in YAML file must be a string.") - log.error("Bailing...") - sys.exit() - else: - if not conf[param] or not isinstance(conf[param], str): - log.error(f"Parameter '{param}' in YAML file must be a string.") - log.error("Bailing...") - sys.exit() - - - - #Check all files are present - # #The workflow run YAML - lives in the toplevel dir not /results - # filename = yaml_file.format(**conf) - # path = os.path.join(target_directory, filename) - - - #format the filepaths: - filepaths = [f.format(**conf) for f in mandatory_files] - #The fixed file paths - for filepath in filepaths: - log.debug(f"File path: {filepath}") - path = os.path.join(target_directory, "results", filepath) - if not os.path.exists(path): - if "missing_files" in conf: - if os.path.split(filepath)[1] in conf["missing_files"]: - #This file is known to be missing, ignoring - log.info("Ignoring specified missing file: %s" % - os.path.split(filepath)[1]) - filepaths.remove(filepath) - continue - log.error("Could not find the mandatory file '%s' at the following path: %s" % - (filepath, path)) - log.error("Consider adding it to the 'missing_files' list in the YAML configuration.") - log.error("Bailing...") - sys.exit() - - ### if the IPS files are split, join them - ipsf = os.path.join("functional-annotation", - "{prefix}.merged_CDS.I5.tsv.gz".format(**conf)) - ipsf_path = os.path.join(target_directory, "results", ipsf) - if not os.path.exists(ipsf_path): - ### deal with split DBB.merged_CDS.I5_001.tsv.gz files - joinInterProScanOutputFiles(target_directory, conf) - filepaths.append(ipsf) - - log.info("Data look good...") - - #Let's deal with the JSON metadata file - # Grab the template from Github - # https://stackoverflow.com/questions/38491722/reading-a-github-file-using-python-returns-html-tags - url = "https://raw.githubusercontent.com/emo-bon/MetaGOflow-Data-Products-RO-Crate/main/ro-crate-metadata.json-template" - req = requests.get(url) - if req.status_code == requests.codes.ok: - template = req.json() - else: - log.error("Unable to download the metadata.json file from Github") - log.error(f"Check {url}") - log.error("Bailing...") - sys.exit() - - - log.info("Writing ro-crate-metadata.json...") - - - #Deal with the ./ dataset stanza separately - #"accession_number" - template["@graph"][1]["name"] = template["@graph"][1]["name"].format(**conf) - template["@graph"][1]["description"] = template["@graph"][1]["description"].format(**conf) - #"datePublished" - template["@graph"][1]["datePublished"] = template["@graph"][1]["datePublished"].format(**conf) - - - # deal with sequence_categorisation separately - template, seq_cat_files = sequence_categorisation_stanzas(target_directory, template) - # add seq cat files to the filepaths - for scf in seq_cat_files: - filepaths.append(os.path.join("sequence-categorisation", scf)) - ### deal with the rest - for section in template["@graph"]: - section["@id"] = section["@id"].format(**conf) - if "hasPart" in section: - for entry in section["hasPart"]: - entry["@id"] = entry["@id"].format(**conf) - #Write the json metadata file: - metadata_json_formatted = json.dumps(template, indent=4) - - #Debug to disk - #with open("testing-ro-crate-metadata.json", "w") as outfile: - # outfile.write(metadata_json_formatted) - #sys.exit() - log.debug("%s" % metadata_json_formatted) - - #OK, all's good, let's build the RO-Crate - log.info("Copying data files...") - with tempfile.TemporaryDirectory() as tmpdirname: - #Deal with the YAML file - yf = yaml_file.format(**conf) - source = os.path.join(target_directory, yf) - shutil.copy(source, os.path.join(tmpdirname, yf)) - - #Build the ro-crate dir structure - output_dirs = ["functional-annotation/stats", "sequence-categorisation", - "taxonomy-summary/LSU", "taxonomy-summary/SSU"] - for d in output_dirs: - os.makedirs(os.path.join(tmpdirname, d)) - #Loop over results files and sequence categorisation files - for fp in filepaths: - source = os.path.join(target_directory, "results", fp) - log.debug("source = %s" % source) - log.debug("dest = %s" % os.path.join(tmpdirname, fp)) - shutil.copy(source, os.path.join(tmpdirname, fp)) - - #Write the json metadata file: - with open(os.path.join(tmpdirname, "ro-crate-metadata.json"), "w") as outfile: - outfile.write(metadata_json_formatted) - - #Write the HTML preview file - writeHTMLpreview(tmpdirname) - - #Zip it up: - log.info("Zipping data to ro-crate... (this could take some time...)") - ro_crate_name = "%s-ro-crate" % os.path.split(target_directory)[1] - shutil.make_archive(ro_crate_name, "zip", tmpdirname) - log.info("done") - -if __name__ == "__main__": - - parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description=textwrap.dedent(desc), - ) - parser.add_argument("target_directory", - help="Name of target directory containing MetaGOflow" +\ - "output" - ) - parser.add_argument("metagoflow_version", - help="URL pointing to the metaGOflow version used" - ) - parser.add_argument("run_parameter", - help="Name of run and prefix to output files." - ) - parser.add_argument("ena_run_accession_id", - help="Run accession id in ENA." - ) - parser.add_argument('-d', '--debug', - action='store_true', - help="DEBUG logging") - - args = parser.parse_args() - - - - main(args.target_directory, args.metagoflow_version, args.run_parameter, args.ena_run_accession_id, args.debug) - From 19e53dbe0d19636a87f1108def47546632043957 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Fri, 24 Mar 2023 17:48:02 +0200 Subject: [PATCH 16/26] edit wf output to remove chunks and merge ips parts to single file --- run_wf.sh | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/run_wf.sh b/run_wf.sh index 72237c80..1e6b6b94 100755 --- a/run_wf.sh +++ b/run_wf.sh @@ -156,7 +156,6 @@ then export PATH_ENA_RAW_DATA=${PIPELINE_DIR}/${OUT_DIR}/raw_data_from_ENA/${ENA_STUDY_ID}/raw/ - fi # ----------------------------- prepare yml file ----------------------------- # @@ -213,12 +212,43 @@ TOIL_PARAMS+=( # echo "toil-cwl-runner" "${TOIL_PARAMS[@]}" # toil-cwl-runner "${TOIL_PARAMS[@]}" +# -------------------------------------------- + # Run the metaGOflow workflow using cwltool cwltool --parallel ${SINGULARITY} --outdir ${OUT_DIR_FINAL} ${CWL} ${EXTENDED_CONFIG_YAML} -# Build RO-crate +# -------------------------------------------- + +# Edit output structure rm -rf ${TMPDIR} +cd ${OUT_DIR}/results/functional-annotation/ + +count=`ls -1 *.chunks 2>/dev/null | wc -l` +if [ $count != 0 ] +then + rm *.chunks +fi + +count=`ls -1 *CDS.I5_001.tsv.gz 2>/dev/null | wc -l` +if [ $count != 0 ] +then + + fullfile=*.merged.CDS.I5_001.tsv.gz + prefix=$(echo $fullfile | sed 's/[^_]*$//') + prefix=${prefix::-1} + + ls *.merged.CDS.I5_*.tsv.gz | xargs -I {} cat {} > allfiles.gz + ls *.merged.CDS.I5_*.tsv.gz | xargs -I {} rm {} + mv allfiles.gz ${prefix}".tsv.gz" +fi + +cd ../../../ + + +# -------------------------------------------- + +# Build RO-crate rocrate init -c ${RUN_DIR} if [ -z "$ENA_RUN_ID" ]; then @@ -226,3 +256,4 @@ if [ -z "$ENA_RUN_ID" ]; then fi python utils/edit-ro-crate.py ${OUT_DIR} ${EXTENDED_CONFIG_YAML} ${ENA_RUN_ID} ${METAGOFLOW_VERSION} +# -------------------------------------------- From 746c603752a2d9bba2c8a2854e089d6eee32681e Mon Sep 17 00:00:00 2001 From: hariszaf Date: Fri, 24 Mar 2023 17:49:40 +0200 Subject: [PATCH 17/26] add embrc records #18 --- utils/edit-ro-crate.py | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/utils/edit-ro-crate.py b/utils/edit-ro-crate.py index dced9d56..6dcd7a1d 100755 --- a/utils/edit-ro-crate.py +++ b/utils/edit-ro-crate.py @@ -215,12 +215,6 @@ "name": "Summary with statistics of the single-end reads (forward/reverse).", "encodingFormat": "text/plain" }, - { - "@id": ".fastq.trimmed.qc_summary", - "@type": "File", - "name": "Summary with statistics of the single-end reads (forward/reverse).", - "encodingFormat": "text/plain" - }, { "@id": ".all.tblout.deoverlapped", "@type": "File", @@ -355,8 +349,12 @@ } ] - def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflow_version ): + """ + Edit the output of the `rocrate init` tool. + Map files descriptions ; should be done through the cwl descriptions but we go that way at a later point. + Add extra ids on the ro-crate describing the metaGOflow workflow and the ENA data (if used). + """ crate = ROCrate(target_directory) # here we use a complete directory, could we use just the json..? @@ -373,9 +371,28 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo entry.properties()[k] = v metagoflow_id = "workflow/metaGOflow" - license_id = "https://www.apache.org/licenses/LICENSE-2.0" + mg_license_id = "https://www.apache.org/licenses/LICENSE-2.0" + embrc_id = "https://ror.org/0038zss60" + mail_id = "mailto:help@embrc.org" + + embrc_mail = crate.add(Person(crate, mail_id, properties={ + "@type": "ContactPoint", + "contactType": "Help Desk", + "email": "help@embrc.org", + "identifier": "help@embrc.org", + "url": "https://www.embrc.eu/about-us/contact-us" + })) + + + embrc = crate.add(Person(crate, embrc_id, properties={ + "@type": "Organization", + "name": "European Marine Biological Resource Centre", + "url": "https://ror.org/0038zss60", + "contactPoint": {"@id": "mailto:help@embrc.org"} + })) + - metagoflow_id = crate.add(Person(crate, metagoflow_id, properties={ + metagoflow = crate.add(Person(crate, metagoflow_id, properties={ "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], "name": "metaGOflow", "affiliation": "University of Flatland", @@ -388,7 +405,7 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo ] })) - license_id = crate.add(Person(crate, license_id, properties={ + mg_license = crate.add(Person(crate, mg_license_id, properties={ "@type": "CreativeWork", "name": "Apache License 2.0" })) From e5fa080a7e8ee3b06c8a569dde5738cbbe46d2e5 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Fri, 24 Mar 2023 17:50:11 +0200 Subject: [PATCH 18/26] return ips chunks --- workflows/conditionals/Func_ann_and_post_proccessing-subwf.cwl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/workflows/conditionals/Func_ann_and_post_proccessing-subwf.cwl b/workflows/conditionals/Func_ann_and_post_proccessing-subwf.cwl index d0e1e7e3..ed1c691b 100644 --- a/workflows/conditionals/Func_ann_and_post_proccessing-subwf.cwl +++ b/workflows/conditionals/Func_ann_and_post_proccessing-subwf.cwl @@ -98,6 +98,7 @@ steps: - summary_ips - go_summary - go_summary_slim + - chunked_tsvs # << move to functional annotation >> move_to_functional_annotation_folder: @@ -110,6 +111,7 @@ steps: - post_processing/summary_pfam - post_processing/go_summary - post_processing/go_summary_slim + - post_processing/chunked_tsvs linkMerge: merge_flattened dir_name: { default: functional-annotation } out: [ out ] From 7a9eb655e743310c3a0cd0992e1082ba6561c017 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Fri, 24 Mar 2023 17:50:55 +0200 Subject: [PATCH 19/26] set threads properly to exploit fat node on zorbas hpc --- config.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config.yml b/config.yml index b4ff4169..6a1e358a 100644 --- a/config.yml +++ b/config.yml @@ -1,15 +1,15 @@ # Steps to go for qc_and_merge_step: true -taxonomic_inventory: false -cgc_step: false -reads_functional_annotation: false +taxonomic_inventory: true +cgc_step: true +reads_functional_annotation: true assemble: false # Global -threads: 20 +threads: 40 -# For parallelization cases might worth decrease global value of threads -interproscan_threads: 20 +# As a rule of thumb keep that as floor(threads/8) where threads the previous parameter +interproscan_threads: 4 # fastp parameters detect_adapter_for_pe: false From d45aaca60e77878b5fb490f4911e380b2cf76a15 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Sat, 25 Mar 2023 00:32:52 +0200 Subject: [PATCH 20/26] edit ENA description #18 --- utils/edit-ro-crate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/edit-ro-crate.py b/utils/edit-ro-crate.py index 6dcd7a1d..2ffc8d7a 100755 --- a/utils/edit-ro-crate.py +++ b/utils/edit-ro-crate.py @@ -418,7 +418,7 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo "@id": ena_accession_raw_data, "@type": "File", "name": "ENA accession for run raw sequence data", - "description": "FAKE: Raw sequence data and laboratory sequence generation metadata", + "description": "Link to the ENA entry of the raw data used for this analysis.", "url": "https://www.ebi.ac.uk/ena/browser/view/" + ena_run_accession_id, "encodingFormat": "text/xml" })) From 9a537aac7f46c3d20f349b0d762809ff842103f4 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Sat, 25 Mar 2023 14:35:59 +0200 Subject: [PATCH 21/26] minor edits reg #18 --- run_wf.sh | 2 ++ utils/edit-ro-crate.py | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/run_wf.sh b/run_wf.sh index 1e6b6b94..f3252cfd 100755 --- a/run_wf.sh +++ b/run_wf.sh @@ -257,3 +257,5 @@ fi python utils/edit-ro-crate.py ${OUT_DIR} ${EXTENDED_CONFIG_YAML} ${ENA_RUN_ID} ${METAGOFLOW_VERSION} # -------------------------------------------- + +# rm -r ${OUT_DIR} diff --git a/utils/edit-ro-crate.py b/utils/edit-ro-crate.py index 2ffc8d7a..35d20957 100755 --- a/utils/edit-ro-crate.py +++ b/utils/edit-ro-crate.py @@ -423,13 +423,11 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo "encodingFormat": "text/xml" })) - print("export...") - crate.write_zip("exp_crate.zip") - - print(".. ro-crate as .zip ready.") - + crate.write_zip("".join([target_directory,".zip"])) + + print("..ro-crate as .zip ready.") if __name__ == "__main__": @@ -457,4 +455,3 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo # Run main function main(args.target_directory, args.extended_config_yaml, args.ena_run_accession_id, args.metagoflow_version) - From a3db2c964c4725c8623af7350781d77daa7254d8 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Sat, 25 Mar 2023 15:05:11 +0200 Subject: [PATCH 22/26] ignore dev outputs --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index c5a1bb45..d2dce263 100644 --- a/.gitignore +++ b/.gitignore @@ -116,8 +116,15 @@ venv.bak/ # Ignore real-world test samples test_input/SRR* +test_input/DB* # Ignore dev output TEST_*/ *.output +STELIOS_TEST/ +marine_sediment_dbh/ + +slurm_run.sh + + From e2ceb74e353a0393b879fcbe3f082f929dc68d05 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Sat, 25 Mar 2023 20:31:24 +0200 Subject: [PATCH 23/26] cwd var --- run_wf.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/run_wf.sh b/run_wf.sh index f3252cfd..8eebdfe0 100755 --- a/run_wf.sh +++ b/run_wf.sh @@ -113,6 +113,8 @@ _check_reads "$FORWARD_READS" "$REVERSE_READS" # load required environments and packages before running +export CWD=$(pwd) + export TOIL_SLURM_ARGS="--array=1-${LIMIT_QUEUE}%20" #schedule 100 jobs 20 running at one time export CWL="${PIPELINE_DIR}/workflows/gos_wf.cwl" @@ -243,7 +245,7 @@ then mv allfiles.gz ${prefix}".tsv.gz" fi -cd ../../../ +cd ${CWD} # -------------------------------------------- @@ -258,4 +260,4 @@ python utils/edit-ro-crate.py ${OUT_DIR} ${EXTENDED_CONFIG_YAML} ${ENA_RUN_ID} $ # -------------------------------------------- -# rm -r ${OUT_DIR} + From c327600a99b2709961c01a03969179eb50f7123e Mon Sep 17 00:00:00 2001 From: hariszaf Date: Sat, 25 Mar 2023 21:47:19 +0200 Subject: [PATCH 24/26] add dataset metadata #18 --- utils/edit-ro-crate.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/utils/edit-ro-crate.py b/utils/edit-ro-crate.py index 35d20957..832e680c 100755 --- a/utils/edit-ro-crate.py +++ b/utils/edit-ro-crate.py @@ -365,7 +365,7 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo except: pass finally: - if pk : + if pk : for k,v in description.items(): if k not in entry.properties().keys(): entry.properties()[k] = v @@ -374,6 +374,20 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo mg_license_id = "https://www.apache.org/licenses/LICENSE-2.0" embrc_id = "https://ror.org/0038zss60" mail_id = "mailto:help@embrc.org" + metagoflow_product_license_id = "https://creativecommons.org/licenses/by/4.0/legalcode" + + + mg_license = crate.add(Person(crate, mg_license_id, properties={ + "@type": "CreativeWork", + "name": "Apache License 2.0", + "identifier": "https://spdx.org/licenses/Apache-2.0.html" + })) + + metagoflow_product_license = crate.add(Person(crate,metagoflow_product_license_id, properties={ + "@type": "CreativeWork", + "name": "Creative Commons (CC-BY 4.0)", + "identifier": "https://spdx.org/licenses/CC-BY-4.0.html" + })) embrc_mail = crate.add(Person(crate, mail_id, properties={ "@type": "ContactPoint", @@ -387,8 +401,8 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo embrc = crate.add(Person(crate, embrc_id, properties={ "@type": "Organization", "name": "European Marine Biological Resource Centre", - "url": "https://ror.org/0038zss60", - "contactPoint": {"@id": "mailto:help@embrc.org"} + "url": embrc_id, + "contactPoint": {"@id": mail_id} })) @@ -398,18 +412,13 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo "affiliation": "University of Flatland", "author": {"@id": "EMO BON"}, "url": metagoflow_version, - "license": { "@id": "https://www.apache.org/licenses/LICENSE-2.0"}, + "license": { "@id": mg_license_id}, "hasPart": [ {"@id": "config.yml"}, {"@id": extended_config_yaml} ] })) - mg_license = crate.add(Person(crate, mg_license_id, properties={ - "@type": "CreativeWork", - "name": "Apache License 2.0" - })) - if ena_run_accession_id != "None": @@ -423,6 +432,10 @@ def main(target_directory, extended_config_yaml, ena_run_accession_id, metagoflo "encodingFormat": "text/xml" })) + crate.root_dataset.properties()["name"] = "MetaGoFlow Results" + # crate.root_dataset.properties()["license"] = {"@id": metagoflow_product_license_id} + crate.root_dataset.properties()["publisher"] = {"@id": embrc_id} + print("export...") crate.write_zip("".join([target_directory,".zip"])) From 4e7f671ce6ec766061b14032b74928ffa70c4253 Mon Sep 17 00:00:00 2001 From: hariszaf Date: Sat, 25 Mar 2023 21:48:50 +0200 Subject: [PATCH 25/26] remove output dir so we keep only the .zip file that includes the proper ro-crate-metadata --- run_wf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run_wf.sh b/run_wf.sh index 8eebdfe0..2e0082ff 100755 --- a/run_wf.sh +++ b/run_wf.sh @@ -260,4 +260,4 @@ python utils/edit-ro-crate.py ${OUT_DIR} ${EXTENDED_CONFIG_YAML} ${ENA_RUN_ID} $ # -------------------------------------------- - +rm -r ${OUT_DIR} From d0421465a712ec014663c3e988604954e2c2013f Mon Sep 17 00:00:00 2001 From: hariszaf Date: Sat, 25 Mar 2023 21:56:55 +0200 Subject: [PATCH 26/26] update the example ro-crate-metadata #18 --- ro-crate-metadata-example.json | 302 +++++++++++++++++++++++---------- 1 file changed, 215 insertions(+), 87 deletions(-) diff --git a/ro-crate-metadata-example.json b/ro-crate-metadata-example.json index 4081809b..1cb33d9a 100644 --- a/ro-crate-metadata-example.json +++ b/ro-crate-metadata-example.json @@ -14,16 +14,19 @@ { "@id": "./", "@type": "Dataset", - "datePublished": "2023-03-24T03:00:01+00:00", + "datePublished": "2023-03-25T19:45:41+00:00", "hasPart": [ { "@id": "results/" }, { - "@id": "dev_dataset.yml" + "@id": "config.yml" }, { - "@id": "config.yml" + "@id": "mini_dataset.yml" + }, + { + "@id": "results/functional-annotation/" }, { "@id": "results/sequence-categorisation/" @@ -32,59 +35,92 @@ "@id": "results/taxonomy-summary/" }, { - "@id": "results/fastp.html" + "@id": "results/wgs-paired-SRR1620013.merged.unfiltered_fasta" }, { - "@id": "results/test_1_fwd_HWLTKDRXY_600000.fastq.trimmed.fasta" + "@id": "results/wgs-paired-SRR1620013.merged.fasta" }, { - "@id": "results/test_2_rev_HWLTKDRXY_600000.fastq.trimmed.fasta" + "@id": "results/wgs-paired-SRR1620013.merged.qc_summary" }, { - "@id": "results/test.merged.fasta" + "@id": "results/wgs-paired-SRR1620013_1.fastq.trimmed.fasta" }, { - "@id": "results/test.merged.qc_summary" + "@id": "results/wgs-paired-SRR1620013_1.fastq.trimmed.qc_summary" }, { - "@id": "results/test.merged.unfiltered_fasta" + "@id": "results/wgs-paired-SRR1620013_2.fastq.trimmed.fasta" }, { - "@id": "results/test_1_fwd_HWLTKDRXY_600000.fastq.trimmed.qc_summary" + "@id": "results/wgs-paired-SRR1620013_2.fastq.trimmed.qc_summary" }, { - "@id": "results/test_2_rev_HWLTKDRXY_600000.fastq.trimmed.qc_summary" + "@id": "results/wgs-paired-SRR1620013.merged_CDS.ffn" }, { - "@id": "results/test.merged.motus.tsv" + "@id": "results/wgs-paired-SRR1620013.merged_CDS.faa" }, { - "@id": "results/test.merged.cmsearch.all.tblout.deoverlapped" + "@id": "results/fastp.html" + }, + { + "@id": "results/wgs-paired-SRR1620013.merged.cmsearch.all.tblout.deoverlapped" }, { "@id": "results/RNA-counts" }, { - "@id": "results/sequence-categorisation/5_8S.fa.gz" + "@id": "results/wgs-paired-SRR1620013.merged.motus.tsv" }, { - "@id": "results/sequence-categorisation/LSU_rRNA_archaea.RF02540.fa.gz" + "@id": "results/functional-annotation/stats/" }, { - "@id": "results/sequence-categorisation/LSU_rRNA_bacteria.RF02541.fa.gz" + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.go" }, { - "@id": "results/sequence-categorisation/LSU_rRNA_eukarya.RF02543.fa.gz" + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.go_slim" }, { - "@id": "results/sequence-categorisation/SSU_rRNA_bacteria.RF00177.fa.gz" + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged_CDS.I5.tsv.gz" + }, + { + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.hmm.tsv.gz" + }, + { + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.ips" + }, + { + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.ko" + }, + { + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.pfam" }, { - "@id": "results/sequence-categorisation/SSU_rRNA_eukarya.RF01960.fa.gz" + "@id": "results/functional-annotation/stats/interproscan.stats" + }, + { + "@id": "results/functional-annotation/stats/go.stats" + }, + { + "@id": "results/functional-annotation/stats/ko.stats" + }, + { + "@id": "results/functional-annotation/stats/pfam.stats" + }, + { + "@id": "results/functional-annotation/stats/orf.stats" }, { "@id": "results/sequence-categorisation/tRNA.RF00005.fasta.gz" }, + { + "@id": "results/sequence-categorisation/LSU_rRNA_bacteria.RF02541.fa.gz" + }, + { + "@id": "results/sequence-categorisation/SSU_rRNA_bacteria.RF00177.fa.gz" + }, { "@id": "results/taxonomy-summary/SSU/" }, @@ -92,51 +128,51 @@ "@id": "results/taxonomy-summary/LSU/" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.gz" + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq.gz" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.tsv" + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq.tsv" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.txt" + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq.txt" }, { "@id": "results/taxonomy-summary/SSU/krona.html" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq_hdf5.biom" + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq_hdf5.biom" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq_json.biom" + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq_json.biom" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.gz" + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq.gz" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.tsv" + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq.tsv" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.txt" + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq.txt" }, { "@id": "results/taxonomy-summary/LSU/krona.html" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq_hdf5.biom" + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq_hdf5.biom" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq_json.biom" + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq_json.biom" } - ] + ], + "name": "MetaGoFlow Results", + "publisher": { + "@id": "https://ror.org/0038zss60" + } }, { "@id": "results/", "@type": "Dataset" }, - { - "@id": "dev_dataset.yml", - "@type": "File" - }, { "@id": "config.yml", "@type": "File", @@ -144,6 +180,14 @@ "encodingFormat": "text/yaml", "name": "MetaGOflow configuration file" }, + { + "@id": "mini_dataset.yml", + "@type": "File" + }, + { + "@id": "results/functional-annotation/", + "@type": "Dataset" + }, { "@id": "results/sequence-categorisation/", "@type": "Dataset", @@ -155,62 +199,68 @@ "@type": "Dataset" }, { - "@id": "results/fastp.html", + "@id": "results/wgs-paired-SRR1620013.merged.unfiltered_fasta", "@type": "File", - "description": "Quality control and preprocessing of FASTQ files", - "encodingFormat": "text/html", - "name": "FASTP analysis of raw sequence data" + "encodingFormat": "text/plain", + "name": "" }, { - "@id": "results/test_1_fwd_HWLTKDRXY_600000.fastq.trimmed.fasta", + "@id": "results/wgs-paired-SRR1620013.merged.fasta", "@type": "File", "encodingFormat": "text/plain", - "name": "Filtered .fastq file of the single-end reads (forward/reverse)." + "name": "Merged filtered reads." }, { - "@id": "results/test_2_rev_HWLTKDRXY_600000.fastq.trimmed.fasta", + "@id": "results/wgs-paired-SRR1620013.merged.qc_summary", "@type": "File", "encodingFormat": "text/plain", - "name": "Filtered .fastq file of the single-end reads (forward/reverse)." + "name": "Summary with statistics of the merged reads." }, { - "@id": "results/test.merged.fasta", + "@id": "results/wgs-paired-SRR1620013_1.fastq.trimmed.fasta", "@type": "File", "encodingFormat": "text/plain", - "name": "Merged filtered reads." + "name": "Filtered .fastq file of the single-end reads (forward/reverse)." }, { - "@id": "results/test.merged.qc_summary", + "@id": "results/wgs-paired-SRR1620013_1.fastq.trimmed.qc_summary", "@type": "File", "encodingFormat": "text/plain", - "name": "Summary with statistics of the merged reads." + "name": "Summary with statistics of the single-end reads (forward/reverse)." }, { - "@id": "results/test.merged.unfiltered_fasta", + "@id": "results/wgs-paired-SRR1620013_2.fastq.trimmed.fasta", "@type": "File", "encodingFormat": "text/plain", - "name": "" + "name": "Filtered .fastq file of the single-end reads (forward/reverse)." }, { - "@id": "results/test_1_fwd_HWLTKDRXY_600000.fastq.trimmed.qc_summary", + "@id": "results/wgs-paired-SRR1620013_2.fastq.trimmed.qc_summary", "@type": "File", "encodingFormat": "text/plain", "name": "Summary with statistics of the single-end reads (forward/reverse)." }, { - "@id": "results/test_2_rev_HWLTKDRXY_600000.fastq.trimmed.qc_summary", + "@id": "results/wgs-paired-SRR1620013.merged_CDS.ffn", "@type": "File", "encodingFormat": "text/plain", - "name": "Summary with statistics of the single-end reads (forward/reverse)." + "name": "Coding sequences with nucleotides." }, { - "@id": "results/test.merged.motus.tsv", + "@id": "results/wgs-paired-SRR1620013.merged_CDS.faa", "@type": "File", "encodingFormat": "text/plain", - "name": "" + "name": "Coding sequences with amino acids." + }, + { + "@id": "results/fastp.html", + "@type": "File", + "description": "Quality control and preprocessing of FASTQ files", + "encodingFormat": "text/html", + "name": "FASTP analysis of raw sequence data" }, { - "@id": "results/test.merged.cmsearch.all.tblout.deoverlapped", + "@id": "results/wgs-paired-SRR1620013.merged.cmsearch.all.tblout.deoverlapped", "@type": "File", "encodingFormat": "text/plain", "name": "Sequence hits against covariance model databases. Mandatory to run partially the functional annotation step of metaGOflow." @@ -222,49 +272,103 @@ "name": "Numbers of RNA's counted" }, { - "@id": "results/sequence-categorisation/5_8S.fa.gz", + "@id": "results/wgs-paired-SRR1620013.merged.motus.tsv", "@type": "File", - "description": "Identify specific loci in the sample.", - "encodingFormat": "application/zip", - "name": "Sequence categorisation" + "encodingFormat": "text/plain", + "name": "" }, { - "@id": "results/sequence-categorisation/LSU_rRNA_archaea.RF02540.fa.gz", + "@id": "results/functional-annotation/stats/", + "@type": "Dataset" + }, + { + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.go", "@type": "File", - "description": "Identify specific loci in the sample.", - "encodingFormat": "application/zip", - "name": "Sequence categorisation" + "encodingFormat": "text/plain", + "name": "Merged contigs GO summary" }, { - "@id": "results/sequence-categorisation/LSU_rRNA_bacteria.RF02541.fa.gz", + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.go_slim", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Merged contigs GO summary" + }, + { + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged_CDS.I5.tsv.gz", "@type": "File", - "description": "Identify specific loci in the sample.", "encodingFormat": "application/zip", - "name": "Sequence categorisation" + "name": "Merged contigs CDS I5 summary" }, { - "@id": "results/sequence-categorisation/LSU_rRNA_eukarya.RF02543.fa.gz", + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.hmm.tsv.gz", "@type": "File", - "description": "Identify specific loci in the sample.", "encodingFormat": "application/zip", - "name": "Sequence categorisation" + "name": "Merged contigs HMM summary" }, { - "@id": "results/sequence-categorisation/SSU_rRNA_bacteria.RF00177.fa.gz", + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.ips", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Merged contigs InterProScan" + }, + { + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.ko", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Merged contigs KO summary" + }, + { + "@id": "results/functional-annotation/wgs-paired-SRR1620013.merged.summary.pfam", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Merged contigs PFAM summary" + }, + { + "@id": "results/functional-annotation/stats/interproscan.stats", + "@type": "File", + "encodingFormat": "text/plain", + "name": "InterProScan summary statistics" + }, + { + "@id": "results/functional-annotation/stats/go.stats", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Geno Ontology summary statistics" + }, + { + "@id": "results/functional-annotation/stats/ko.stats", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Kegg Ontology summary statistics" + }, + { + "@id": "results/functional-annotation/stats/pfam.stats", + "@type": "File", + "encodingFormat": "text/plain", + "name": "Pfam summary statistcs" + }, + { + "@id": "results/functional-annotation/stats/orf.stats", + "@type": "File", + "encodingFormat": "text/plain", + "name": "ORF summary statistics" + }, + { + "@id": "results/sequence-categorisation/tRNA.RF00005.fasta.gz", "@type": "File", "description": "Identify specific loci in the sample.", "encodingFormat": "application/zip", "name": "Sequence categorisation" }, { - "@id": "results/sequence-categorisation/SSU_rRNA_eukarya.RF01960.fa.gz", + "@id": "results/sequence-categorisation/LSU_rRNA_bacteria.RF02541.fa.gz", "@type": "File", "description": "Identify specific loci in the sample.", "encodingFormat": "application/zip", "name": "Sequence categorisation" }, { - "@id": "results/sequence-categorisation/tRNA.RF00005.fasta.gz", + "@id": "results/sequence-categorisation/SSU_rRNA_bacteria.RF00177.fa.gz", "@type": "File", "description": "Identify specific loci in the sample.", "encodingFormat": "application/zip", @@ -279,19 +383,19 @@ "@type": "Dataset" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.gz", + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq.gz", "@type": "File", "encodingFormat": "application/zip", "name": "LSU sequences used for indentification" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.tsv", + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq.tsv", "@type": "File", "encodingFormat": "application/json-ld", "name": "Tab-separated formatted taxon counts for SSU sequences" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq.txt", + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq.txt", "@type": "File", "encodingFormat": "application/json-ld", "name": "Text-based formatted taxon counts for SSU sequences" @@ -303,31 +407,31 @@ "name": "Krona summary of LSU taxonomic inventory" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq_hdf5.biom", + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq_hdf5.biom", "@type": "File", "encodingFormat": "application/json-ld", "name": "BIOM formatted hdf5 taxon counts for SSU sequences" }, { - "@id": "results/taxonomy-summary/SSU/test.merged_SSU.fasta.mseq_json.biom", + "@id": "results/taxonomy-summary/SSU/wgs-paired-SRR1620013.merged_SSU.fasta.mseq_json.biom", "@type": "File", "encodingFormat": "application/json-ld", "name": "BIOM formatted taxon counts for SSU sequences" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.gz", + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq.gz", "@type": "File", "encodingFormat": "application/zip", "name": "LSU sequences used for indentification" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.tsv", + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq.tsv", "@type": "File", "encodingFormat": "application/json-ld", "name": "Tab-separated formatted taxon counts for LSU sequences" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq.txt", + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq.txt", "@type": "File", "encodingFormat": "application/json-ld", "name": "Text-based taxon counts for LSU sequences" @@ -339,17 +443,46 @@ "name": "Krona summary of LSU taxonomic inventory" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq_hdf5.biom", + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq_hdf5.biom", "@type": "File", "encodingFormat": "application/json-ld", "name": "BIOM formatted hdf5 taxon counts for LSU sequences" }, { - "@id": "results/taxonomy-summary/LSU/test.merged_LSU.fasta.mseq_json.biom", + "@id": "results/taxonomy-summary/LSU/wgs-paired-SRR1620013.merged_LSU.fasta.mseq_json.biom", "@type": "File", "encodingFormat": "application/json-ld", "name": "BIOM formatted taxon counts for LSU sequences" }, + { + "@id": "https://www.apache.org/licenses/LICENSE-2.0", + "@type": "CreativeWork", + "identifier": "https://spdx.org/licenses/Apache-2.0.html", + "name": "Apache License 2.0" + }, + { + "@id": "https://creativecommons.org/licenses/by/4.0/legalcode", + "@type": "CreativeWork", + "identifier": "https://spdx.org/licenses/CC-BY-4.0.html", + "name": "Creative Commons (CC-BY 4.0)" + }, + { + "@id": "mailto:help@embrc.org", + "@type": "ContactPoint", + "contactType": "Help Desk", + "email": "help@embrc.org", + "identifier": "help@embrc.org", + "url": "https://www.embrc.eu/about-us/contact-us" + }, + { + "@id": "https://ror.org/0038zss60", + "@type": "Organization", + "contactPoint": { + "@id": "mailto:help@embrc.org" + }, + "name": "European Marine Biological Resource Centre", + "url": "https://ror.org/0038zss60" + }, { "@id": "#workflow/metaGOflow", "@type": [ @@ -366,7 +499,7 @@ "@id": "config.yml" }, { - "@id": "dev_dataset.yml" + "@id": "MINI_DATASET_FA/mini_dataset.yml" } ], "license": { @@ -374,11 +507,6 @@ }, "name": "metaGOflow", "url": "https://github.com/emo-bon/MetaGOflow/releases/tag/v1.0.0" - }, - { - "@id": "https://www.apache.org/licenses/LICENSE-2.0", - "@type": "CreativeWork", - "name": "Apache License 2.0" } ] } \ No newline at end of file