Bring up to date
This commit is contained in:
parent
c7bebf6428
commit
abbd3537ec
@ -21,11 +21,14 @@ macos-run:
|
|||||||
- macos
|
- macos
|
||||||
- x86
|
- x86
|
||||||
|
|
||||||
aws-run:
|
|
||||||
artifacts:
|
|
||||||
when: always
|
|
||||||
|
|
||||||
|
# run all our test in AWS, cos EKS runners don't work
|
||||||
docker-run:
|
docker-run:
|
||||||
|
rules:
|
||||||
|
- when: never
|
||||||
|
|
||||||
|
aws-run:
|
||||||
|
stage: test
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
paths:
|
paths:
|
||||||
@ -42,6 +45,7 @@ docker-run:
|
|||||||
- ${CI_PROJECT_NAME}/**/*.fasta
|
- ${CI_PROJECT_NAME}/**/*.fasta
|
||||||
- ${CI_PROJECT_NAME}/**/*.mmi
|
- ${CI_PROJECT_NAME}/**/*.mmi
|
||||||
|
|
||||||
|
|
||||||
# Define a 1D job matrix to inject a variable named MATRIX_NAME into
|
# Define a 1D job matrix to inject a variable named MATRIX_NAME into
|
||||||
# the CI environment, we can use the value of MATRIX_NAME to determine
|
# the CI environment, we can use the value of MATRIX_NAME to determine
|
||||||
# which options to apply as part of the rules block below
|
# which options to apply as part of the rules block below
|
||||||
@ -220,22 +224,22 @@ docker-run:
|
|||||||
NF_IGNORE_PROCESSES: >
|
NF_IGNORE_PROCESSES: >
|
||||||
preprocess_reads,validate_ref_annotation,merge_transcriptomes,assemble_transcripts,
|
preprocess_reads,validate_ref_annotation,merge_transcriptomes,assemble_transcripts,
|
||||||
build_minimap_index,get_transcriptome,merge_gff_bundles,run_gffcompare,build_minimap_index,split_bam,decompress_transcriptome,preprocess_ref_transcriptome,faidx,gz_faidx
|
build_minimap_index,get_transcriptome,merge_gff_bundles,run_gffcompare,build_minimap_index,split_bam,decompress_transcriptome,preprocess_ref_transcriptome,faidx,gz_faidx
|
||||||
- if: $MATRIX_NAME == "mismatch_seqid_error"
|
#- if: $MATRIX_NAME == "mismatch_seqid_error"
|
||||||
variables:
|
# variables:
|
||||||
NF_BEFORE_SCRIPT: "mkdir -p ${CI_PROJECT_NAME}/data/ && wget -O ${CI_PROJECT_NAME}/data/differential_expression_ncbi.tar.gz https://ont-exd-int-s3-euwst1-epi2me-labs.s3.amazonaws.com/wf-isoforms/differential_expression_ncbi.tar.gz && tar -xzvf ${CI_PROJECT_NAME}/data/differential_expression_ncbi.tar.gz -C ${CI_PROJECT_NAME}/data/ && wget -O ${CI_PROJECT_NAME}/data/demo.nextflow.config https://ont-exd-int-s3-euwst1-epi2me-labs.s3.amazonaws.com/wf-isoforms/demo.nextflow.config;"
|
# NF_BEFORE_SCRIPT: "mkdir -p ${CI_PROJECT_NAME}/data/ && wget -O ${CI_PROJECT_NAME}/data/differential_expression_ncbi.tar.gz https://ont-exd-int-s3-euwst1-epi2me-labs.s3.amazonaws.com/wf-isoforms/differential_expression_ncbi.tar.gz && tar -xzvf ${CI_PROJECT_NAME}/data/differential_expression_ncbi.tar.gz -C ${CI_PROJECT_NAME}/data/ && wget -O ${CI_PROJECT_NAME}/data/demo.nextflow.config https://ont-exd-int-s3-euwst1-epi2me-labs.s3.amazonaws.com/wf-isoforms/demo.nextflow.config;"
|
||||||
NF_WORKFLOW_OPTS:
|
# NF_WORKFLOW_OPTS:
|
||||||
"--fastq ${CI_PROJECT_NAME}/data/differential_expression_ncbi/differential_expression_fastq \
|
# "--fastq ${CI_PROJECT_NAME}/data/differential_expression_ncbi/differential_expression_fastq \
|
||||||
--de_analysis \
|
# --de_analysis \
|
||||||
--ref_genome ${CI_PROJECT_NAME}/data/differential_expression_ncbi/hg38_chr20.fa \
|
# --ref_genome ${CI_PROJECT_NAME}/data/differential_expression_ncbi/hg38_chr20.fa \
|
||||||
--ref_annotation ${CI_PROJECT_NAME}/data/differential_expression_ncbi/GRCh38.p14_NCBI_test.gtf.gz \
|
# --ref_annotation ${CI_PROJECT_NAME}/data/differential_expression_ncbi/GRCh38.p14_NCBI_test.gtf.gz \
|
||||||
--direct_rna \
|
# --direct_rna \
|
||||||
--sample_sheet test_data/sample_sheet.csv \
|
# --sample_sheet test_data/sample_sheet.csv \
|
||||||
-c ${CI_PROJECT_NAME}/data/demo.nextflow.config "
|
# -c ${CI_PROJECT_NAME}/data/demo.nextflow.config "
|
||||||
NF_IGNORE_PROCESSES: >
|
# NF_IGNORE_PROCESSES: >
|
||||||
preprocess_reads,faidx,gz_faidx,merge_transcriptomes,assemble_transcripts,
|
# preprocess_reads,faidx,gz_faidx,merge_transcriptomes,assemble_transcripts,
|
||||||
build_minimap_index,get_transcriptome,merge_gff_bundles,run_gffcompare,build_minimap_index,split_bam,decompress_transcriptome,preprocess_ref_transcriptome
|
# build_minimap_index,get_transcriptome,merge_gff_bundles,run_gffcompare,build_minimap_index,split_bam,decompress_transcriptome,preprocess_ref_transcriptome
|
||||||
ASSERT_NEXTFLOW_FAILURE: 1
|
# ASSERT_NEXTFLOW_FAILURE: 1
|
||||||
ASSERT_NEXTFLOW_FAILURE_REXP: Seqid mismatch found between the provided ref_annotation
|
# ASSERT_NEXTFLOW_FAILURE_REXP: Seqid mismatch found between the provided ref_annotation
|
||||||
- if: $MATRIX_NAME == "mismatch_seqid_warn"
|
- if: $MATRIX_NAME == "mismatch_seqid_warn"
|
||||||
variables:
|
variables:
|
||||||
NF_BEFORE_SCRIPT: "mkdir -p ${CI_PROJECT_NAME}/data/ && wget -O ${CI_PROJECT_NAME}/data/differential_expression_ncbi.tar.gz https://ont-exd-int-s3-euwst1-epi2me-labs.s3.amazonaws.com/wf-isoforms/differential_expression_ncbi.tar.gz && tar -xzvf ${CI_PROJECT_NAME}/data/differential_expression_ncbi.tar.gz -C ${CI_PROJECT_NAME}/data/ && wget -O ${CI_PROJECT_NAME}/data/demo.nextflow.config https://ont-exd-int-s3-euwst1-epi2me-labs.s3.amazonaws.com/wf-isoforms/demo.nextflow.config;"
|
NF_BEFORE_SCRIPT: "mkdir -p ${CI_PROJECT_NAME}/data/ && wget -O ${CI_PROJECT_NAME}/data/differential_expression_ncbi.tar.gz https://ont-exd-int-s3-euwst1-epi2me-labs.s3.amazonaws.com/wf-isoforms/differential_expression_ncbi.tar.gz && tar -xzvf ${CI_PROJECT_NAME}/data/differential_expression_ncbi.tar.gz -C ${CI_PROJECT_NAME}/data/ && wget -O ${CI_PROJECT_NAME}/data/demo.nextflow.config https://ont-exd-int-s3-euwst1-epi2me-labs.s3.amazonaws.com/wf-isoforms/demo.nextflow.config;"
|
||||||
@ -253,4 +257,3 @@ docker-run:
|
|||||||
AFTER_NEXTFLOW_CMD: "grep 'are only present in the reference genome' '.nextflow.log'"
|
AFTER_NEXTFLOW_CMD: "grep 'are only present in the reference genome' '.nextflow.log'"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,12 +3,12 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: docs_readme
|
- id: docs_readme
|
||||||
name: docs_readme
|
name: docs_readme
|
||||||
entry: parse_docs -p docs -e .md -s 01_brief_description 02_introduction 03_compute_requirements 04_install_and_run 05_related_protocols 06_input_example 07_pipeline_overview 08_input_parameters 09_outputs 10_troubleshooting 11_FAQ 12_other -ot README.md -od output_definition.json -ns nextflow_schema.json
|
entry: parse_docs -p docs -e .md -s 01_brief_description 02_introduction 03_compute_requirements 04_install_and_run 05_input_example 06_pipeline_overview 07_input_parameters 08_outputs 09_related_protocols 10_troubleshooting 11_FAQ 12_other -ot README.md -od output_definition.json -ns nextflow_schema.json
|
||||||
language: python
|
language: python
|
||||||
always_run: true
|
always_run: true
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- epi2melabs==0.0.59
|
- epi2melabs==0.0.62
|
||||||
- repo: https://github.com/pycqa/flake8
|
- repo: https://github.com/pycqa/flake8
|
||||||
rev: 5.0.4
|
rev: 5.0.4
|
||||||
hooks:
|
hooks:
|
||||||
|
|||||||
10
CHANGELOG.md
10
CHANGELOG.md
@ -62,8 +62,6 @@ This patch release of wf-transcriptomes updates internal workflow naming, and do
|
|||||||
- Bug where incorrect gene_id assigned in the DE tables.
|
- Bug where incorrect gene_id assigned in the DE tables.
|
||||||
|
|
||||||
## [v1.5.0]
|
## [v1.5.0]
|
||||||
### Updated
|
|
||||||
- Workflow report updated to use `ezcharts`.
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Exons per isoforms histogram reporting incorrect numbers.
|
- Exons per isoforms histogram reporting incorrect numbers.
|
||||||
- Output the `results_dexseq.tsv` file when `--de_analysis` enabled.
|
- Output the `results_dexseq.tsv` file when `--de_analysis` enabled.
|
||||||
@ -71,8 +69,8 @@ This patch release of wf-transcriptomes updates internal workflow naming, and do
|
|||||||
- per-class gffcompare tracking files as there exists a combine tracking file.
|
- per-class gffcompare tracking files as there exists a combine tracking file.
|
||||||
|
|
||||||
## [v1.4.0]
|
## [v1.4.0]
|
||||||
## Added
|
### Added
|
||||||
- `--igv` parameter (default: false) for outputting IGV config allowing visualisation of read alignments in the EPI2ME App.
|
- Added `--igv` parameter (default: false) for outputting IGV config allowing visualisation of read alignments in the EPI2ME App.
|
||||||
- If required for IGV, reference indexes are output in to a `igv_reference` directory
|
- If required for IGV, reference indexes are output in to a `igv_reference` directory
|
||||||
### Changed
|
### Changed
|
||||||
- BAMS are output in to a BAMS directory.
|
- BAMS are output in to a BAMS directory.
|
||||||
@ -83,8 +81,8 @@ This patch release of wf-transcriptomes updates internal workflow naming, and do
|
|||||||
- Fusion detection subworkflow, as the functionality is not robust enough for general use at this time.
|
- Fusion detection subworkflow, as the functionality is not robust enough for general use at this time.
|
||||||
### Changed
|
### Changed
|
||||||
- Updated pychopper to 2.7.10
|
- Updated pychopper to 2.7.10
|
||||||
## Added
|
### Added
|
||||||
- new `cdna_kit` options: PCS114 and PCB111/114
|
- New `--cdna_kit` options: PCS114 and PCB111/114
|
||||||
|
|
||||||
## [v1.2.1]
|
## [v1.2.1]
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
26
README.md
26
README.md
@ -40,7 +40,7 @@ ARM processor support: False
|
|||||||
|
|
||||||
These are instructions to install and run the workflow on command line.
|
These are instructions to install and run the workflow on command line.
|
||||||
You can also access the workflow via the
|
You can also access the workflow via the
|
||||||
[EPI2ME Desktop application](https://labs.epi2me.io/downloads/).
|
[EPI2ME Desktop application](https://epi2me.nanoporetech.com/downloads/).
|
||||||
|
|
||||||
The workflow uses [Nextflow](https://www.nextflow.io/) to manage
|
The workflow uses [Nextflow](https://www.nextflow.io/) to manage
|
||||||
compute and software resources,
|
compute and software resources,
|
||||||
@ -60,7 +60,8 @@ parameter as exemplified below.
|
|||||||
It is not required to clone or download the git repository
|
It is not required to clone or download the git repository
|
||||||
in order to run the workflow.
|
in order to run the workflow.
|
||||||
More information on running EPI2ME workflows can
|
More information on running EPI2ME workflows can
|
||||||
be found on our [website](https://labs.epi2me.io/wfindex).
|
be found in the
|
||||||
|
[documentation](https://epi2me.nanoporetech.com/epi2me-docs/wfquickstart/).
|
||||||
|
|
||||||
The following command can be used to obtain the workflow.
|
The following command can be used to obtain the workflow.
|
||||||
This will pull the repository in to the assets folder of
|
This will pull the repository in to the assets folder of
|
||||||
@ -95,17 +96,6 @@ nextflow run epi2me-labs/wf-transcriptomes \
|
|||||||
-profile standard
|
-profile standard
|
||||||
```
|
```
|
||||||
|
|
||||||
For further information about running a workflow on
|
|
||||||
the command line see https://labs.epi2me.io/wfquickstart/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Related protocols
|
|
||||||
|
|
||||||
This workflow is designed to take input sequences that have been produced from [Oxford Nanopore Technologies](https://nanoporetech.com/) devices.
|
|
||||||
|
|
||||||
Find related protocols in the [Nanopore community](https://community.nanoporetech.com/docs/).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -320,6 +310,16 @@ Output files may be aggregated including information for all samples or provided
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Related protocols
|
||||||
|
|
||||||
|
This workflow is designed to take input sequences that have been produced from [Oxford Nanopore Technologies](https://nanoporetech.com/) devices.
|
||||||
|
|
||||||
|
Find related RNA and cDNA sequencing protocols in the
|
||||||
|
[Nanopore community](https://community.nanoporetech.com/docs/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
+ If the workflow fails please run it with the demo data set to ensure the workflow itself is working. This will help us determine if the issue is related to the environment, input parameters or a bug.
|
+ If the workflow fails please run it with the demo data set to ensure the workflow itself is working. This will help us determine if the issue is related to the environment, input parameters or a bug.
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
"""Common model classes used across all workflows."""
|
"""Common model classes used across all workflows."""
|
||||||
from dataclasses import asdict, dataclass, field
|
from dataclasses import asdict, dataclass, field
|
||||||
|
from decimal import Decimal
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -34,7 +35,8 @@ class WorkflowBaseModel:
|
|||||||
field_name: str,
|
field_name: str,
|
||||||
*,
|
*,
|
||||||
decimal_places: int = None,
|
decimal_places: int = None,
|
||||||
default_value: str = "N/A") -> Optional[str]:
|
default_value: str = "N/A",
|
||||||
|
show_unit: bool = True) -> Optional[str]:
|
||||||
"""Get the value of a value and make it reportable."""
|
"""Get the value of a value and make it reportable."""
|
||||||
# Get the field info using the field name
|
# Get the field info using the field name
|
||||||
field_info = self.__dataclass_fields__.get(field_name)
|
field_info = self.__dataclass_fields__.get(field_name)
|
||||||
@ -48,11 +50,14 @@ class WorkflowBaseModel:
|
|||||||
if value is None:
|
if value is None:
|
||||||
return default_value
|
return default_value
|
||||||
|
|
||||||
if isinstance(value, (int, float)):
|
if isinstance(value, (int, float, Decimal)):
|
||||||
if decimal_places:
|
# Apply scientific notation for Decimal or small/large int/float
|
||||||
|
if isinstance(value, Decimal) or value < 0.0001 or value > 99999999:
|
||||||
|
precision = decimal_places if decimal_places is not None else 2
|
||||||
|
value = f"{value:.{precision}E}"
|
||||||
|
# Otherwise, apply rounding
|
||||||
|
elif decimal_places is not None:
|
||||||
value = round(value, decimal_places)
|
value = round(value, decimal_places)
|
||||||
if value < 0.0001 or value > 99999999:
|
|
||||||
value = f"{value:.2E}"
|
|
||||||
else:
|
else:
|
||||||
if decimal_places:
|
if decimal_places:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
@ -60,7 +65,7 @@ class WorkflowBaseModel:
|
|||||||
|
|
||||||
unit = field_info.metadata.get('unit')
|
unit = field_info.metadata.get('unit')
|
||||||
|
|
||||||
if unit:
|
if unit and show_unit:
|
||||||
return f"{value} {unit}"
|
return f"{value} {unit}"
|
||||||
|
|
||||||
return str(value)
|
return str(value)
|
||||||
@ -113,6 +118,10 @@ class CheckResult:
|
|||||||
metadata={
|
metadata={
|
||||||
"title": "Check pass",
|
"title": "Check pass",
|
||||||
"description": "If true the check has passed"})
|
"description": "If true the check has passed"})
|
||||||
|
check_messages: list | None = field(
|
||||||
|
default=None, metadata={
|
||||||
|
"title": "Check messages",
|
||||||
|
"description": "A list of messages about the check performed"})
|
||||||
check_threshold: str | None = field(
|
check_threshold: str | None = field(
|
||||||
default=None, metadata={
|
default=None, metadata={
|
||||||
"title": "Check threshold",
|
"title": "Check threshold",
|
||||||
@ -245,11 +254,11 @@ class RunStats:
|
|||||||
total_reads: int | None = field(
|
total_reads: int | None = field(
|
||||||
default=None, metadata={
|
default=None, metadata={
|
||||||
"title": "Total reads",
|
"title": "Total reads",
|
||||||
"description": "Total number of reads on run"})
|
"description": """Total number of reads after basecalling. This value is
|
||||||
total_ambiguous_reads: int | None = field(
|
calculated from the full BAM file generated by the workflow, includes both
|
||||||
default=None, metadata={
|
aligned and unaligned reads, and excludes non-primary alignments to prevent
|
||||||
"title": "Total ambiguous reads",
|
double counting. It may differ from the estimate shown in the technical
|
||||||
"description": "Number of reads of unknown provenance"})
|
run report."""})
|
||||||
total_unaligned_reads: int | None = field(
|
total_unaligned_reads: int | None = field(
|
||||||
default=None, metadata={
|
default=None, metadata={
|
||||||
"title": "Total unaligned reads",
|
"title": "Total unaligned reads",
|
||||||
|
|||||||
@ -64,38 +64,49 @@ def main(args):
|
|||||||
)
|
)
|
||||||
|
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
csv_reader = csv.DictReader(f)
|
csv_reader = csv.DictReader(f)
|
||||||
n_row = 0
|
columns = csv_reader.fieldnames
|
||||||
for row in csv_reader:
|
alias_field = "alias"
|
||||||
n_row += 1
|
required_fields = ["barcode"]
|
||||||
if n_row == 1:
|
prohibited_fields = []
|
||||||
n_cols = len(row)
|
|
||||||
else:
|
if args.no_barcode:
|
||||||
# check we got the same number of fields
|
alias_field = "sample_name"
|
||||||
if len(row) != n_cols:
|
required_fields = []
|
||||||
|
prohibited_fields = ["alias", "barcode"]
|
||||||
|
|
||||||
|
required_fields.append(alias_field)
|
||||||
|
|
||||||
|
for field in prohibited_fields:
|
||||||
|
if field in columns:
|
||||||
|
sys.stdout.write(
|
||||||
|
f"'{field}' column must not be present with --no_barcode"
|
||||||
|
)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
for field in required_fields:
|
||||||
|
if field not in columns:
|
||||||
|
sys.stdout.write(f"'{field}' column missing")
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
# Skip header row for n_row
|
||||||
|
for n_row, row in enumerate(csv_reader, start=1):
|
||||||
|
if len(row) != len(columns):
|
||||||
sys.stdout.write(
|
sys.stdout.write(
|
||||||
f"Unexpected number of cells in row number {n_row}"
|
f"Unexpected number of cells in row number {n_row}"
|
||||||
)
|
)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
try:
|
if not args.no_barcode:
|
||||||
barcodes.append(row["barcode"])
|
barcodes.append(row.get("barcode"))
|
||||||
except KeyError:
|
aliases.append(row.get(alias_field))
|
||||||
sys.stdout.write("'barcode' column missing")
|
|
||||||
sys.exit()
|
# Optional fields check for not None, empty strings are falsey
|
||||||
try:
|
sample_type = row.get("type")
|
||||||
aliases.append(row["alias"])
|
if sample_type is not None:
|
||||||
except KeyError:
|
sample_types.append(sample_type)
|
||||||
sys.stdout.write("'alias' column missing")
|
analysis_group = row.get("analysis_group")
|
||||||
sys.exit()
|
if analysis_group is not None:
|
||||||
try:
|
analysis_groups.append(analysis_group)
|
||||||
sample_types.append(row["type"])
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
analysis_groups.append(row["analysis_group"])
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sys.stdout.write(f"Parsing error: {e}")
|
sys.stdout.write(f"Parsing error: {e}")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
@ -110,10 +121,13 @@ def main(args):
|
|||||||
# for now we have decided they may not start with "barcode"
|
# for now we have decided they may not start with "barcode"
|
||||||
for alias in aliases:
|
for alias in aliases:
|
||||||
if alias.startswith("barcode"):
|
if alias.startswith("barcode"):
|
||||||
sys.stdout.write("values in 'alias' column must not begin with 'barcode'")
|
sys.stdout.write(
|
||||||
|
f"values in '{alias_field}' column must "
|
||||||
|
"not begin with 'barcode'")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
# check barcodes are all the same length
|
# check barcodes are all the same length
|
||||||
|
if barcodes:
|
||||||
first_length = len(barcodes[0])
|
first_length = len(barcodes[0])
|
||||||
for barcode in barcodes[1:]:
|
for barcode in barcodes[1:]:
|
||||||
if len(barcode) != first_length:
|
if len(barcode) != first_length:
|
||||||
@ -125,7 +139,7 @@ def main(args):
|
|||||||
sys.stdout.write("values in 'barcode' column not unique")
|
sys.stdout.write("values in 'barcode' column not unique")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
if len(aliases) > len(set(aliases)):
|
if len(aliases) > len(set(aliases)):
|
||||||
sys.stdout.write("values in 'alias' column not unique")
|
sys.stdout.write(f"values in '{alias_field}' column not unique")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
if sample_types:
|
if sample_types:
|
||||||
@ -170,4 +184,10 @@ def argparser():
|
|||||||
"appear at least once in the sample sheet",
|
"appear at least once in the sample sheet",
|
||||||
nargs="*"
|
nargs="*"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no_barcode",
|
||||||
|
action="store_true",
|
||||||
|
help="Allow sample sheets without a barcode column "
|
||||||
|
"and match rows by sample_name only",
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|||||||
@ -18,6 +18,7 @@ DATA_TYPES_LISTS = {
|
|||||||
"vcf_idx": ["vcf.gz.tbi", "vcf.gz.csi"],
|
"vcf_idx": ["vcf.gz.tbi", "vcf.gz.csi"],
|
||||||
"bcf": ["bcf"],
|
"bcf": ["bcf"],
|
||||||
"bcf_idx": ["bcf.csi"],
|
"bcf_idx": ["bcf.csi"],
|
||||||
|
"bigwig": ["bw", "bigwig"],
|
||||||
"gtf": ["gtf", "gtf.gz"],
|
"gtf": ["gtf", "gtf.gz"],
|
||||||
"gtf_idx": ["gtf.gz.tbi"],
|
"gtf_idx": ["gtf.gz.tbi"],
|
||||||
"gff": ["gff", "gff.gz", "gff3", "gff3.gz"],
|
"gff": ["gff", "gff.gz", "gff3", "gff3.gz"],
|
||||||
@ -43,6 +44,7 @@ INDEX_PAIRS = {
|
|||||||
"cram": ("crai",),
|
"cram": ("crai",),
|
||||||
"vcf": ("tbi", "csi"),
|
"vcf": ("tbi", "csi"),
|
||||||
"bcf": ("csi",),
|
"bcf": ("csi",),
|
||||||
|
"bigwig": (),
|
||||||
"bed": ("tbi",),
|
"bed": ("tbi",),
|
||||||
"bedmethyl": ("tbi",),
|
"bedmethyl": ("tbi",),
|
||||||
"gff": ("tbi",),
|
"gff": ("tbi",),
|
||||||
@ -68,6 +70,7 @@ class TrackBuilder:
|
|||||||
"cram": "alignment",
|
"cram": "alignment",
|
||||||
"bcf": "variant",
|
"bcf": "variant",
|
||||||
"vcf": "variant",
|
"vcf": "variant",
|
||||||
|
"bigwig": "wig",
|
||||||
"bedmethyl": "annotation",
|
"bedmethyl": "annotation",
|
||||||
"bed": "annotation",
|
"bed": "annotation",
|
||||||
"gtf": "annotation",
|
"gtf": "annotation",
|
||||||
@ -82,6 +85,7 @@ class TrackBuilder:
|
|||||||
"cram": {},
|
"cram": {},
|
||||||
"bcf": {},
|
"bcf": {},
|
||||||
"vcf": {},
|
"vcf": {},
|
||||||
|
"bigwig": {},
|
||||||
"bed": {},
|
"bed": {},
|
||||||
"bedmethyl": {},
|
"bedmethyl": {},
|
||||||
"gtf": {},
|
"gtf": {},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
These are instructions to install and run the workflow on command line.
|
These are instructions to install and run the workflow on command line.
|
||||||
You can also access the workflow via the
|
You can also access the workflow via the
|
||||||
[EPI2ME Desktop application](https://labs.epi2me.io/downloads/).
|
[EPI2ME Desktop application](https://epi2me.nanoporetech.com/downloads/).
|
||||||
|
|
||||||
The workflow uses [Nextflow](https://www.nextflow.io/) to manage
|
The workflow uses [Nextflow](https://www.nextflow.io/) to manage
|
||||||
compute and software resources,
|
compute and software resources,
|
||||||
@ -21,7 +21,8 @@ parameter as exemplified below.
|
|||||||
It is not required to clone or download the git repository
|
It is not required to clone or download the git repository
|
||||||
in order to run the workflow.
|
in order to run the workflow.
|
||||||
More information on running EPI2ME workflows can
|
More information on running EPI2ME workflows can
|
||||||
be found on our [website](https://labs.epi2me.io/wfindex).
|
be found in the
|
||||||
|
[documentation](https://epi2me.nanoporetech.com/epi2me-docs/wfquickstart/).
|
||||||
|
|
||||||
The following command can be used to obtain the workflow.
|
The following command can be used to obtain the workflow.
|
||||||
This will pull the repository in to the assets folder of
|
This will pull the repository in to the assets folder of
|
||||||
@ -55,6 +56,3 @@ nextflow run epi2me-labs/wf-transcriptomes \
|
|||||||
--sample_sheet 'wf-transcriptomes-demo/sample_sheet.csv' \
|
--sample_sheet 'wf-transcriptomes-demo/sample_sheet.csv' \
|
||||||
-profile standard
|
-profile standard
|
||||||
```
|
```
|
||||||
|
|
||||||
For further information about running a workflow on
|
|
||||||
the command line see https://labs.epi2me.io/wfquickstart/
|
|
||||||
|
|||||||
65
docs/07_input_parameters.md
Normal file
65
docs/07_input_parameters.md
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
### Input Options
|
||||||
|
|
||||||
|
| Nextflow parameter name | Type | Description | Help | Default |
|
||||||
|
|--------------------------|------|-------------|------|---------|
|
||||||
|
| fastq | string | FASTQ files to use in the analysis. | This accepts one of three cases: (i) the path to a single FASTQ file; (ii) the path to a top-level directory containing FASTQ files; (iii) the path to a directory containing one level of sub-directories which in turn contain FASTQ files. In the first and second case, a sample name can be supplied with `--sample`. In the last case, the data is assumed to be multiplexed with the names of the sub-directories as barcodes. In this case, a sample sheet can be provided with `--sample_sheet`. | |
|
||||||
|
| bam | string | BAM or unaligned BAM (uBAM) files to use in the analysis. | This accepts one of three cases: (i) the path to a single BAM file; (ii) the path to a top-level directory containing BAM files; (iii) the path to a directory containing one level of sub-directories which in turn contain BAM files. In the first and second case, a sample name can be supplied with `--sample`. In the last case, the data is assumed to be multiplexed with the names of the sub-directories as barcodes. In this case, a sample sheet can be provided with `--sample_sheet`. | |
|
||||||
|
| transcriptome_source | string | Select how the transcriptome used for analysis should be prepared. | For differential expression analysis, use of an existing transcriptome may be preferred and so 'precomputed' should be selected. In this case the 'ref_transcriptome' parameter should be specified. To create a reference transcriptome using an existing reference genome, select 'reference guided' and specify the 'ref_genome' parameter. | reference-guided |
|
||||||
|
| ref_genome | string | Path to reference genome sequence [.fa/.fq/.fa.gz/fq.gz]. Required for reference-based workflow. | A reference genome is required for reference-based assembly of a transcriptome. | |
|
||||||
|
| ref_transcriptome | string | Transcriptome reference file. Required for precomputed transcriptome calculation and for differential expression analysis. | A reference transcriptome related to the sample under study. Must be supplied when the 'Transcriptome source' parameter has been set to 'precomputed' or to perform differential expression. | |
|
||||||
|
| ref_annotation | string | A reference annotation in GFF2 or GFF3 format (extensions .gtf(.gz), .gff(.gz), .gff3(.gz)). Only annotation files from [Encode](https://www.encodeproject.org), [Ensembl](https://www.ensembl.org/index.html) and [NCBI](https://www.ncbi.nlm.nih.gov/) are supported. | This will be used for guiding the transcriptome assembly and to label transcripts with their corresponding gene identifiers. Note: If in de_analysis mode transcript strands must be only + or -. | |
|
||||||
|
| direct_rna | boolean | Set to true for direct RNA sequencing. | Omits the pychopper step. | False |
|
||||||
|
| analyse_unclassified | boolean | Analyse unclassified reads from input directory. By default the workflow will not process reads in the unclassified directory. | If selected and if the input is a multiplex directory the workflow will also process the unclassified directory. | False |
|
||||||
|
|
||||||
|
|
||||||
|
### Output Options
|
||||||
|
|
||||||
|
| Nextflow parameter name | Type | Description | Help | Default |
|
||||||
|
|--------------------------|------|-------------|------|---------|
|
||||||
|
| out_dir | string | Directory for output of all user-facing files. | | output |
|
||||||
|
| igv | boolean | Visualize outputs in the EPI2ME IGV visualizer. | Enabling this option will visualize the output alignment files in the EPI2ME Desktop App IGV visualizer. | False |
|
||||||
|
|
||||||
|
|
||||||
|
### Sample Options
|
||||||
|
|
||||||
|
| Nextflow parameter name | Type | Description | Help | Default |
|
||||||
|
|--------------------------|------|-------------|------|---------|
|
||||||
|
| sample_sheet | string | A CSV file used to map barcodes to sample aliases. The sample sheet can be provided when the input data is a directory containing sub-directories with FASTQ files. If you are running the differential expression workflow, there must be an additional column `condition` with two labels, one of which must be `control` (e.g. `control` and `treated`). Control will indicate which samples will be used as the reference. There should be at least 3 repeats for each condition. | The sample sheet is a CSV file with, minimally, columns named `barcode` and `alias`. Extra columns are allowed. | |
|
||||||
|
| sample | string | A single sample name for non-multiplexed data. Permissible if passing a single .fastq(.gz) file or directory of .fastq(.gz) files. | | |
|
||||||
|
|
||||||
|
|
||||||
|
### Options for reference-based workflow
|
||||||
|
|
||||||
|
| Nextflow parameter name | Type | Description | Help | Default |
|
||||||
|
|--------------------------|------|-------------|------|---------|
|
||||||
|
| plot_gffcmp_stats | boolean | Create a PDF of plots from showing gffcompare results | If set to true, a PDF file containing detailed gffcompare reults will be output | True |
|
||||||
|
| gffcompare_opts | string | Extra command-line options to give to gffcompare -r | For a list of possible options see [gffcompare](https://ccb.jhu.edu/software/stringtie/gffcompare.shtml). | -R |
|
||||||
|
| minimap2_index_opts | string | Extra command-line options for minimap2 indexing. | See [minimap2 index options](https://lh3.github.io/minimap2/minimap2.html#4) for more information. These will only be relevant in the reference based transcriptome assembly. | -k 14 |
|
||||||
|
| minimap2_opts | string | Additional command-line options for minimap2 alignment. | See [minimap2 options](https://lh3.github.io/minimap2/minimap2.html#5) for further information. These will only be relevant in the reference based transcriptome assembly. | -uf |
|
||||||
|
| minimum_mapping_quality | integer | filter aligned reads by MAPQ quality. | Reads that do not meet this mapping quality after minimap2 alignment, will be filtered out. | 40 |
|
||||||
|
| stringtie_opts | string | Extra command-line options for stringtie transcript assembly. | For additional String tie options see [here](https://github.com/gpertea/stringtie#stringtie-options). | --conservative |
|
||||||
|
|
||||||
|
|
||||||
|
### Differential Expression Options
|
||||||
|
|
||||||
|
| Nextflow parameter name | Type | Description | Help | Default |
|
||||||
|
|--------------------------|------|-------------|------|---------|
|
||||||
|
| de_analysis | boolean | Run DE anaylsis | Running this requires you to provide at least two replicates for a control and treated sample as well as a sample sheet param. | False |
|
||||||
|
| min_gene_expr | integer | The minimum number of total mapped sequence reads required for a gene to be considered in differential transcript usage analysis. | Filtering at the gene level ensures that the observed transcript ratios are calculated with a minimum number of counts per gene. | 10 |
|
||||||
|
| min_feature_expr | integer | The minimum number of reads assigned to a transcript for it to be considered in differential transcript usage analysis. | Filter out transcripts that do not have this minimum number of transcript expression, reducing noise. | 3 |
|
||||||
|
| min_samps_gene_expr | integer | Set the minimum number of samples in which a gene is expressed to be included in the differential transcript usage analysis. | A gene must be expressed in at least this number of samples for the gene be included in the differential transcript usage analysis. Filtering at the gene level improves the reliability of the observed transcript ratios. | 3 |
|
||||||
|
| min_samps_feature_expr | integer | Set the minimum number of samples in which a transcript is expressed to be included in the differential transcript usage analysis. | A transcript must expressed in at least this minimum number of samples to be included in the analysis. Should be equal to the number of replicates per sample you have. | 1 |
|
||||||
|
|
||||||
|
|
||||||
|
### Advanced Options
|
||||||
|
|
||||||
|
| Nextflow parameter name | Type | Description | Help | Default |
|
||||||
|
|--------------------------|------|-------------|------|---------|
|
||||||
|
| threads | integer | Number of CPU threads. | Only provided to processes including alignment and and assembly that benefit from multiple threads. | 4 |
|
||||||
|
| cdna_kit | string | If cDNA reads are used, select the kit used. | This will be used by pychopper to preprocess the reads for downstream analysis. | SQK-PCS109 |
|
||||||
|
| pychopper_backend | string | Pychopper can use one of two available backends for identifying primers in the raw reads | 'edlib' is set by default due to its high performance. However, it may be less sensitive than 'phmm'. | edlib |
|
||||||
|
| pychopper_opts | string | Extra pychopper opts | See available options (here)[https://github.com/epi2me-labs/pychopper#usage] | |
|
||||||
|
| bundle_min_reads | integer | Minimum size of bam bundle for parallel processing. | | 50000 |
|
||||||
|
| isoform_table_nrows | integer | Maximum rows to dispay in the isoform report table | | 5000 |
|
||||||
|
|
||||||
|
|
||||||
33
docs/08_outputs.md
Normal file
33
docs/08_outputs.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
Output files may be aggregated including information for all samples or provided per sample. Per-sample files will be prefixed with respective aliases and represented below as {{ alias }}.
|
||||||
|
|
||||||
|
| Title | File path | Description | Per sample or aggregated |
|
||||||
|
|-------|-----------|-------------|--------------------------|
|
||||||
|
| workflow report | wf-transcriptomes-report.html | a HTML report document detailing the primary findings of the workflow | aggregated |
|
||||||
|
| Per file read stats | fastq_ingress_results/{{ alias }}//reads/fastcat_stats/per-file-stats.tsv | A TSV with per file read stats, including all samples. | aggregated |
|
||||||
|
| Read stats | fastq_ingress_results/{{ alias }}//reads/fastcat_stats/per-read-stats.tsv | A TSV with per read stats, including all samples. | aggregated |
|
||||||
|
| Run ID's | fastq_ingress_results/{{ alias }}//reads/fastcat_stats/run_ids | List of run IDs present in reads. | aggregated |
|
||||||
|
| Meta map json | fastq_ingress_results/{{ alias }}//reads/metamap.json | Metadata used in workflow presented in a JSON. | aggregated |
|
||||||
|
| Concatenated sequence data | fastq_ingress_results/{{ alias }}//reads/{{ alias }}.fastq.gz | Per sample reads concatenated in to one FASTQ file. | per-sample |
|
||||||
|
| Assembled transcriptome | {{ alias }}_transcriptome.fas | Per sample assembled transcriptome. Not output if a reference annotation was supplied | per-sample |
|
||||||
|
| Annotated assembled transcriptome | {{ alias }}_merged_transcriptome.fas | Per sample annotated assembled transcriptome. Only output if a reference annotation was supplied | per-sample |
|
||||||
|
| Alignment summary statistics | {{ alias }}_read_aln_stats.tsv | Per sample alignment summary statistics. | per-sample |
|
||||||
|
| GFF compare results. | {{ alias }}_gffcompare | All GFF compare output files. | per-sample |
|
||||||
|
| Differential gene expression results | de_analysis/results_dge.tsv | This is a gene-level result file that describes genes and their probability of showing differential expression between experimental conditions. | aggregated |
|
||||||
|
| Differential gene expression report | de_analysis/results_dge.pdf | Summary report of differential gene expression analysis as a PDF. | aggregated |
|
||||||
|
| Differential transcript usage gene TSV | de_analysis/results_dtu_gene.tsv | This is a gene-level result file from DEXSeq that lists annotated genes and their probabilities of differential expression. | aggregated |
|
||||||
|
| Differential transcript usage report | de_analysis/results_dtu.pdf | Summary report of differential transcript usage results as a PDF. | aggregated |
|
||||||
|
| Differential transcript usage TSV | de_analysis/results_dtu_transcript.tsv | This is a transcript-level result file from DEXSeq that lists annotated genes and their probabilities of differential expression. | aggregated |
|
||||||
|
| Differential transcript usage stageR TSV | de_analysis/results_dtu_stageR.tsv | This is the output from StageR and it shows both gene and transcript probabilities of differential expression | aggregated |
|
||||||
|
| Differential transcript usage DEXSeq TSV | de_analysis/results_dexseq.tsv | The complete output from the DEXSeq-analysis, shows both gene and transcript probabilities of differential expression. | aggregated |
|
||||||
|
| Gene counts | de_analysis/all_gene_counts.tsv | Raw gene counts created by the Salmon tool, before filtering. | aggregated |
|
||||||
|
| Gene counts per million | de_analysis/cpm_gene_counts.tsv | This file shows counts per million (CPM) of the raw gene counts to facilitate comparisons across samples. | aggregated |
|
||||||
|
| Transcript counts | de_analysis/unfiltered_transcript_counts_with_genes.tsv | Raw transcript counts created by the Salmon tool, before filtering. Includes reference to the associated gene ID. | aggregated |
|
||||||
|
| Transcript per million counts | de_analysis/unfiltered_tpm_transcript_counts.tsv | This file shows transcripts per million (TPM) of the raw counts to facilitate comparisons across samples. | aggregated |
|
||||||
|
| Transcript counts filtered | de_analysis/filtered_transcript_counts_with_genes.tsv | Filtered transcript counts, used for differential transcript usage analysis. Includes a reference to the associated gene ID. | aggregated |
|
||||||
|
| Transcript info table | {{ alias }}_transcripts_table.tsv | This file details each isoform that was reconstructed from the input reads. It contains a subset of columns from the .tmap output from [gffcompare](https://ccb.jhu.edu/software/stringtie/gffcompare.shtml) | per-sample |
|
||||||
|
| Final non redundant transcriptome | de_analysis/final_non_redundant_transcriptome.fasta | Transcripts that were used for differential expression analysis including novel transcripts with the identifiers used for DE analysis. Only applicable when the ref_transcriptome parameter is not provided. | aggregated |
|
||||||
|
| Index of reference FASTA file | igv_reference/{{ ref_genome_file }}.fai | Reference genome index of the FASTA file required for IGV config. | aggregated |
|
||||||
|
| GZI index of the reference FASTA file | igv_reference/{{ ref_genome_file }}.gzi | GZI Index of the reference FASTA file. | aggregated |
|
||||||
|
| JSON configuration file for IGV browser | igv.json | JSON configuration file to be loaded in IGV for visualising alignments against the reference. | aggregated |
|
||||||
|
| BAM file (minimap2) | BAMS/{{ alias }}.reads_aln_sorted.bam | BAM file generated from mapping input reads to the reference. | per-sample |
|
||||||
|
| BAM index file (minimap2) | BAMS/{{ alias }}.reads_aln_sort.bam.bai | Index file generated from mapping input reads to the reference. | per-sample |
|
||||||
4
docs/09_related_protocols.md
Normal file
4
docs/09_related_protocols.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
This workflow is designed to take input sequences that have been produced from [Oxford Nanopore Technologies](https://nanoporetech.com/) devices.
|
||||||
|
|
||||||
|
Find related RNA and cDNA sequencing protocols in the
|
||||||
|
[Nanopore community](https://community.nanoporetech.com/docs/).
|
||||||
@ -23,4 +23,28 @@ class CWUtil {
|
|||||||
nf_params.allowNames(s)
|
nf_params.allowNames(s)
|
||||||
nf_params.put0(key, value)
|
nf_params.put0(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Safely get the workflow entrypoint from the Nextflow params map
|
||||||
|
*
|
||||||
|
* Our workflows support alternative "entrypoints". For example, a workflow
|
||||||
|
* may expose an entrypoint that can be used to validate parameters and
|
||||||
|
* dry run the workflow, or to automatically set different defaults or
|
||||||
|
* behaviours. This is controlled by setting `params.wf.entrypoint`.
|
||||||
|
*
|
||||||
|
* This util safely checks and extracts this parameter if set and avoids
|
||||||
|
* "Access to undefined parameter" errors otherwise raised during strict
|
||||||
|
* Nextflow execution.
|
||||||
|
*
|
||||||
|
* Note that entrypoint is expected to be null for the "main" entrypoint.
|
||||||
|
*/
|
||||||
|
public static def getEntrypoint(nf_params) {
|
||||||
|
def entrypoint = null
|
||||||
|
if( nf_params.containsKey('wf')
|
||||||
|
&& nf_params.wf instanceof Map
|
||||||
|
&& nf_params.wf.containsKey('entrypoint') )
|
||||||
|
{
|
||||||
|
entrypoint = nf_params.wf.entrypoint
|
||||||
|
}
|
||||||
|
return entrypoint
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,8 +40,14 @@ class NfcoreSchema {
|
|||||||
//
|
//
|
||||||
// Resolve Schema path relative to main workflow directory
|
// Resolve Schema path relative to main workflow directory
|
||||||
//
|
//
|
||||||
public static String getSchemaPath(workflow, schema_filename='nextflow_schema.json') {
|
public static String getSchemaPath(workflow, params, schema_filename='nextflow_schema.json') {
|
||||||
return "${workflow.projectDir}/${schema_filename}"
|
String entrypoint_prefix = "" // default "main" prefix
|
||||||
|
// if our params.wf namespace defines an entrypoint, override the schema location
|
||||||
|
def wf_entrypoint = CWUtil.getEntrypoint(params)
|
||||||
|
if (wf_entrypoint) {
|
||||||
|
entrypoint_prefix = "entrypoints/${wf_entrypoint}/"
|
||||||
|
}
|
||||||
|
return "${workflow.projectDir}/${entrypoint_prefix}${schema_filename}"
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -53,7 +59,7 @@ class NfcoreSchema {
|
|||||||
def has_error = false
|
def has_error = false
|
||||||
//=====================================================================//
|
//=====================================================================//
|
||||||
// Check for nextflow core params and unexpected params
|
// Check for nextflow core params and unexpected params
|
||||||
def json = new File(getSchemaPath(workflow, schema_filename=schema_filename)).text
|
def json = new File(getSchemaPath(workflow, params, schema_filename=schema_filename)).text
|
||||||
def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions')
|
def Map schemaParams = (Map) new JsonSlurper().parseText(json).get('definitions')
|
||||||
def nf_params = [
|
def nf_params = [
|
||||||
// Options for base `nextflow` command
|
// Options for base `nextflow` command
|
||||||
@ -160,7 +166,7 @@ class NfcoreSchema {
|
|||||||
|
|
||||||
//=====================================================================//
|
//=====================================================================//
|
||||||
// Validate parameters against the schema
|
// Validate parameters against the schema
|
||||||
InputStream input_stream = new File(getSchemaPath(workflow, schema_filename=schema_filename)).newInputStream()
|
InputStream input_stream = new File(getSchemaPath(workflow, params, schema_filename=schema_filename)).newInputStream()
|
||||||
JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream))
|
JSONObject raw_schema = new JSONObject(new JSONTokener(input_stream))
|
||||||
|
|
||||||
// Remove anything that's in params.schema_ignore_params
|
// Remove anything that's in params.schema_ignore_params
|
||||||
@ -215,7 +221,7 @@ class NfcoreSchema {
|
|||||||
String output = ''
|
String output = ''
|
||||||
output += 'Typical pipeline command:\n\n'
|
output += 'Typical pipeline command:\n\n'
|
||||||
output += " ${colors.cyan}${command}${colors.reset}\n\n"
|
output += " ${colors.cyan}${command}${colors.reset}\n\n"
|
||||||
Map params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename))
|
Map params_map = paramsLoad(getSchemaPath(workflow, params, schema_filename=schema_filename))
|
||||||
Integer max_chars = paramsMaxChars(params_map) + 1
|
Integer max_chars = paramsMaxChars(params_map) + 1
|
||||||
Integer type_pad = 10
|
Integer type_pad = 10
|
||||||
String param_prefix = " --"
|
String param_prefix = " --"
|
||||||
@ -296,7 +302,7 @@ class NfcoreSchema {
|
|||||||
// Get pipeline parameters defined in JSON Schema
|
// Get pipeline parameters defined in JSON Schema
|
||||||
def Map params_summary = [:]
|
def Map params_summary = [:]
|
||||||
def blacklist = ['hostnames']
|
def blacklist = ['hostnames']
|
||||||
def params_map = paramsLoad(getSchemaPath(workflow, schema_filename=schema_filename))
|
def params_map = paramsLoad(getSchemaPath(workflow, params, schema_filename=schema_filename))
|
||||||
for (group in params_map.keySet()) {
|
for (group in params_map.keySet()) {
|
||||||
def sub_params = new LinkedHashMap()
|
def sub_params = new LinkedHashMap()
|
||||||
def group_params = params_map.get(group) // This gets the parameters of that particular group
|
def group_params = params_map.get(group) // This gets the parameters of that particular group
|
||||||
|
|||||||
@ -33,7 +33,7 @@ process configure_igv {
|
|||||||
script:
|
script:
|
||||||
// the locus argument just makes sure that the initial view in IGV shows something
|
// the locus argument just makes sure that the initial view in IGV shows something
|
||||||
// interesting
|
// interesting
|
||||||
String locus_arg = locus_str ? "--locus $locus_str" : ""
|
String locus_arg = locus_str ? "--locus '$locus_str'" : ""
|
||||||
// extra options for alignment tracks
|
// extra options for alignment tracks
|
||||||
def aln_opts_json_str = \
|
def aln_opts_json_str = \
|
||||||
aln_extra_opts ? new JsonBuilder(aln_extra_opts).toPrettyString() : ""
|
aln_extra_opts ? new JsonBuilder(aln_extra_opts).toPrettyString() : ""
|
||||||
|
|||||||
156
lib/ingress.nf
156
lib/ingress.nf
@ -43,7 +43,8 @@ def is_excluded(Path p, Map margs) {
|
|||||||
* Take a channel of the shape `[meta, reads, path-to-stats-dir | null]` (or
|
* Take a channel of the shape `[meta, reads, path-to-stats-dir | null]` (or
|
||||||
* `[meta, [reads, index], path-to-stats-dir | null]` in the case of XAM) and extract the
|
* `[meta, [reads, index], path-to-stats-dir | null]` in the case of XAM) and extract the
|
||||||
* run IDs and basecall model, from the `run_ids` and `basecaller` files in the stats
|
* run IDs and basecall model, from the `run_ids` and `basecaller` files in the stats
|
||||||
* directory, into the metamap. If the path to the stats dir is `null`, add an empty list.
|
* directory, into the metamap. If the path to the stats dir is `null` due to samples with no reads,
|
||||||
|
* add an empty list.
|
||||||
*
|
*
|
||||||
* @param ch: input channel of shape `[meta, reads, path-to-stats-dir | null]`
|
* @param ch: input channel of shape `[meta, reads, path-to-stats-dir | null]`
|
||||||
* @param allow_multiple_basecall_models: Boolean. If true, emit any sample to have been basecalled
|
* @param allow_multiple_basecall_models: Boolean. If true, emit any sample to have been basecalled
|
||||||
@ -58,6 +59,7 @@ def add_run_IDs_and_basecall_models_to_meta(ch, boolean allow_multiple_basecall_
|
|||||||
// extract run_ids from fastcat stats / bamstats results and add to metadata as well
|
// extract run_ids from fastcat stats / bamstats results and add to metadata as well
|
||||||
// as `ingressed_run_ids`
|
// as `ingressed_run_ids`
|
||||||
ch = ch | map { meta, reads, stats ->
|
ch = ch | map { meta, reads, stats ->
|
||||||
|
// stats will be null only if the sample had no reads (empty BAM/FASTQ)
|
||||||
if (stats) {
|
if (stats) {
|
||||||
def run_ids = stats.resolve("run_ids").splitText().collect { it.strip() }
|
def run_ids = stats.resolve("run_ids").splitText().collect { it.strip() }
|
||||||
ingressed_run_ids += run_ids
|
ingressed_run_ids += run_ids
|
||||||
@ -112,6 +114,7 @@ def add_number_of_reads_to_meta(ch, String input_type_format) {
|
|||||||
// extract reads from fastcat stats / bamstats results and add to metadata
|
// extract reads from fastcat stats / bamstats results and add to metadata
|
||||||
ch = ch | map { meta, reads, stats ->
|
ch = ch | map { meta, reads, stats ->
|
||||||
// Check that stats directory is present.
|
// Check that stats directory is present.
|
||||||
|
// stats will be null only if the sample had no reads (empty BAM/FASTQ)
|
||||||
if (stats) {
|
if (stats) {
|
||||||
if (input_type_format == "fastq") {
|
if (input_type_format == "fastq") {
|
||||||
// Stats from fastcat
|
// Stats from fastcat
|
||||||
@ -148,7 +151,7 @@ def add_number_of_reads_to_meta(ch, String input_type_format) {
|
|||||||
* with elements of `[metamap, seqs.fastq.gz | null, path-to-fastcat-stats | null]`.
|
* with elements of `[metamap, seqs.fastq.gz | null, path-to-fastcat-stats | null]`.
|
||||||
* The second item is `null` for sample sheet entries without a matching barcode
|
* The second item is `null` for sample sheet entries without a matching barcode
|
||||||
* directory. The last item is `null` if `fastcat` was not run (it is only run on
|
* directory. The last item is `null` if `fastcat` was not run (it is only run on
|
||||||
* directories containing more than one FASTQ file or when `stats: true`).
|
* directories containing one or more FASTQ files).
|
||||||
*
|
*
|
||||||
* @param arguments: map with arguments containing
|
* @param arguments: map with arguments containing
|
||||||
* - "input": path to either: (i) input FASTQ file, (ii) top-level directory containing
|
* - "input": path to either: (i) input FASTQ file, (ii) top-level directory containing
|
||||||
@ -159,13 +162,11 @@ def add_number_of_reads_to_meta(ch, String input_type_format) {
|
|||||||
* - "analyse_unclassified": boolean. Whether to ingress unclassified (failed to demux) reads
|
* - "analyse_unclassified": boolean. Whether to ingress unclassified (failed to demux) reads
|
||||||
* - "analyse_fail": boolean. Whether to ingress any sequence files contained in `*_fail`
|
* - "analyse_fail": boolean. Whether to ingress any sequence files contained in `*_fail`
|
||||||
* directories.
|
* directories.
|
||||||
* - "stats": boolean whether to write the `fastcat` stats
|
|
||||||
* - "fastcat_extra_args": string with extra arguments to pass to `fastcat`
|
* - "fastcat_extra_args": string with extra arguments to pass to `fastcat`
|
||||||
* - "required_sample_types": list of zero or more required sample types expected to be present
|
* - "required_sample_types": list of zero or more required sample types expected to be present
|
||||||
* in the sample sheet
|
* in the sample sheet
|
||||||
* - "watch_path": boolean whether to use `watchPath` and run in streaming mode
|
|
||||||
* - "per_read_stats": boolean. If true, output a bgzipped TSV containing a summary
|
* - "per_read_stats": boolean. If true, output a bgzipped TSV containing a summary
|
||||||
of each read to fastcat_stats/per-read-stats.tsv.gz.
|
* of each read to fastcat_stats/per-read-stats.tsv.gz.
|
||||||
* - "fastq_chunk": null or a number of reads to place into chunked FASTQ files
|
* - "fastq_chunk": null or a number of reads to place into chunked FASTQ files
|
||||||
* - "allow_multiple_basecall_models": emit data of samples that had more than one
|
* - "allow_multiple_basecall_models": emit data of samples that had more than one
|
||||||
* basecall model; if this is `false`, such samples will be emitted as `[meta, null,
|
* basecall model; if this is `false`, such samples will be emitted as `[meta, null,
|
||||||
@ -175,7 +176,7 @@ def add_number_of_reads_to_meta(ch, String input_type_format) {
|
|||||||
* `.fastq.gz` file with the (potentially concatenated) sequences and the third is
|
* `.fastq.gz` file with the (potentially concatenated) sequences and the third is
|
||||||
* the path to the directory with the `fastcat` statistics. The second element is
|
* the path to the directory with the `fastcat` statistics. The second element is
|
||||||
* `null` for sample sheet entries for which no corresponding barcode directory was
|
* `null` for sample sheet entries for which no corresponding barcode directory was
|
||||||
* found. The third element is `null` if `fastcat` was not run.
|
* found. The third element is `null` if there were no reads.
|
||||||
*/
|
*/
|
||||||
def fastq_ingress(Map arguments)
|
def fastq_ingress(Map arguments)
|
||||||
{
|
{
|
||||||
@ -191,27 +192,10 @@ def fastq_ingress(Map arguments)
|
|||||||
|
|
||||||
ArrayList fq_extensions = [".fastq", ".fastq.gz", ".fq", ".fq.gz"]
|
ArrayList fq_extensions = [".fastq", ".fastq.gz", ".fq", ".fq.gz"]
|
||||||
|
|
||||||
// `watch_path` will be handled within `get_valid_inputs()`
|
|
||||||
def input = get_valid_inputs(margs, fq_extensions)
|
def input = get_valid_inputs(margs, fq_extensions)
|
||||||
|
|
||||||
def ch_result
|
def ch_result = fastcat(input.files.mix(input.dirs), margs, "FASTQ")
|
||||||
if (margs.stats) {
|
|
||||||
// run fastcat regardless of input type
|
|
||||||
ch_result = fastcat(input.files.mix(input.dirs), margs, "FASTQ")
|
|
||||||
} else {
|
|
||||||
// run `fastcat` only on directories and rename / compress single files
|
|
||||||
ch_dir = fastcat(input.dirs, margs, "FASTQ")
|
|
||||||
.map { meta, path, stats -> [meta, path] }
|
|
||||||
def ch_file
|
|
||||||
if (margs["fastq_chunk"] > 0) {
|
|
||||||
ch_file = split_fq_file(input.files, margs["fastq_chunk"])
|
|
||||||
} else {
|
|
||||||
ch_file = move_or_compress_fq_file(input.files)
|
|
||||||
}
|
|
||||||
ch_result = ch_dir
|
|
||||||
| mix(ch_file)
|
|
||||||
| map { meta, path -> [meta, path, null] }
|
|
||||||
}
|
|
||||||
// TODO: xam_ingress mixes in a .no_files channel here. Do we need to do the same?
|
// TODO: xam_ingress mixes in a .no_files channel here. Do we need to do the same?
|
||||||
|
|
||||||
// The above may have returned a channel with multiple fastqs if chunking
|
// The above may have returned a channel with multiple fastqs if chunking
|
||||||
@ -252,10 +236,9 @@ def fastq_ingress(Map arguments)
|
|||||||
/**
|
/**
|
||||||
* Take a map of input arguments, find valid (u)BAM inputs, and return a channel
|
* Take a map of input arguments, find valid (u)BAM inputs, and return a channel
|
||||||
* with elements of `[metamap, reads.bam | null, path-to-bamstats-results | null]`.
|
* with elements of `[metamap, reads.bam | null, path-to-bamstats-results | null]`.
|
||||||
* The second item is `null` for sample sheet entries without a matching barcode
|
* The second and last items are `null` for sample sheet entries without a matching barcode
|
||||||
* directory or samples containing only uBAM files when `keep_unaligned` is `false`.
|
* directory or samples containing only uBAM files when `keep_unaligned` is `false`.
|
||||||
* The last item is `null` if `bamstats` was not run (it is only run when `stats:
|
* The last item is `null` if `bamstats` was not run due to no reads for the sample.
|
||||||
* true`).
|
|
||||||
*
|
*
|
||||||
* @param arguments: map with arguments containing
|
* @param arguments: map with arguments containing
|
||||||
* - "input": path to either: (i) input (u)BAM file, (ii) top-level directory
|
* - "input": path to either: (i) input (u)BAM file, (ii) top-level directory
|
||||||
@ -266,14 +249,12 @@ def fastq_ingress(Map arguments)
|
|||||||
* - "analyse_unclassified": boolean. Whether to ingress unclassified (failed to demux) reads
|
* - "analyse_unclassified": boolean. Whether to ingress unclassified (failed to demux) reads
|
||||||
* - "analyse_fail": boolean. Whether to ingress any sequence files contained in `*_fail`
|
* - "analyse_fail": boolean. Whether to ingress any sequence files contained in `*_fail`
|
||||||
* directories.
|
* directories.
|
||||||
* - "stats": boolean whether to run `bamstats`
|
|
||||||
* - "keep_unaligned": boolean whether to include uBAM files
|
* - "keep_unaligned": boolean whether to include uBAM files
|
||||||
* - "return_fastq": boolean whether to convert to FASTQ (this will always run
|
* - "return_fastq": boolean whether to convert to FASTQ (this will always run
|
||||||
* `fastcat`)
|
* `fastcat`)
|
||||||
* - "fastcat_extra_args": string with extra arguments to pass to `fastcat`
|
* - "fastcat_extra_args": string with extra arguments to pass to `fastcat`
|
||||||
* - "required_sample_types": list of zero or more required sample types expected to be present
|
* - "required_sample_types": list of zero or more required sample types expected to be present
|
||||||
* in the sample sheet
|
* in the sample sheet
|
||||||
* - "watch_path": boolean whether to use `watchPath` and run in streaming mode
|
|
||||||
* - "per_read_stats": boolean. If true, output a bgzipped TSV containing a summary
|
* - "per_read_stats": boolean. If true, output a bgzipped TSV containing a summary
|
||||||
of each read to fastcat_stats/per-read-stats.tsv.gz.
|
of each read to fastcat_stats/per-read-stats.tsv.gz.
|
||||||
* - "fastq_chunk": null or a number of reads to place into chunked FASTQ files
|
* - "fastq_chunk": null or a number of reads to place into chunked FASTQ files
|
||||||
@ -511,9 +492,6 @@ def xam_ingress(Map arguments)
|
|||||||
ch_catsorted,
|
ch_catsorted,
|
||||||
)
|
)
|
||||||
|
|
||||||
// run `bamstats` if requested
|
|
||||||
if (margs["stats"]) {
|
|
||||||
// branch and run `bamstats` only on the non-`null` paths
|
|
||||||
ch_result = ch_result.branch { meta, path, index ->
|
ch_result = ch_result.branch { meta, path, index ->
|
||||||
has_reads: path
|
has_reads: path
|
||||||
is_null: true
|
is_null: true
|
||||||
@ -535,10 +513,6 @@ def xam_ingress(Map arguments)
|
|||||||
| mix(
|
| mix(
|
||||||
ch_result.is_null.map{it + [null]}
|
ch_result.is_null.map{it + [null]}
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
// add `null` instead of path to `bamstats` results dir
|
|
||||||
ch_result = ch_result | map { meta, bam, bai -> [meta, bam, bai, null] }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove metadata that are unnecessary downstream:
|
// Remove metadata that are unnecessary downstream:
|
||||||
// meta.src_xai: not needed, as it will be part of the channel as a file
|
// meta.src_xai: not needed, as it will be part of the channel as a file
|
||||||
@ -790,97 +764,6 @@ process bamstats {
|
|||||||
' bamstats_results/bamstats.basecallers.tsv | sort | uniq > bamstats_results/basecallers
|
' bamstats_results/bamstats.basecallers.tsv | sort | uniq > bamstats_results/basecallers
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Run `watchPath` on the input directory and return a channel of shape [metamap,
|
|
||||||
* path-to-target-file]. The meta data is taken from the sample sheet in case one was
|
|
||||||
* provided. Otherwise it only contains the `alias` (either `margs["sample"]` or the
|
|
||||||
* name of the parent directory of the file).
|
|
||||||
*
|
|
||||||
* @param input: path to a directory to watch
|
|
||||||
* @param margs: Map with parsed input arguments
|
|
||||||
* @param extensions: list of valid extensions for the target file type
|
|
||||||
* @return: Channel of [metamap, path-to-target-file]
|
|
||||||
*/
|
|
||||||
def watch_path(Path input, Map margs, ArrayList extensions) {
|
|
||||||
// we have two cases to consider: (i) files being generated in the top-level
|
|
||||||
// directory and (ii) files being generated in sub-directories. If we find files of
|
|
||||||
// both kinds, throw an error.
|
|
||||||
if (input.isFile()) {
|
|
||||||
error "Input ($input) must be a folder when using `watch_path`."
|
|
||||||
}
|
|
||||||
// get existing target files first (look for relevant files in the top-level dir and
|
|
||||||
// all sub-dirs)
|
|
||||||
def ch_existing_input = Channel.fromPath(input)
|
|
||||||
| concat(Channel.fromPath("$input/*", type: 'dir'))
|
|
||||||
| map { get_target_files_in_dir(it, extensions, margs, recursive=false) }
|
|
||||||
| flatten
|
|
||||||
// now get channel with files found by `watchPath`
|
|
||||||
def ch_watched = Channel.watchPath("$input/**").until { it.name.startsWith('STOP') }
|
|
||||||
// only keep target files
|
|
||||||
| filter { is_target_file(it, extensions) && !is_excluded(it, margs) }
|
|
||||||
// merge the channels
|
|
||||||
ch_watched = ch_existing_input | concat(ch_watched)
|
|
||||||
// check if input is as expected; start by throwing an error when finding files in
|
|
||||||
// top-level dir and sub-directories
|
|
||||||
String prev_input_type
|
|
||||||
ch_watched
|
|
||||||
| map {
|
|
||||||
String input_type = (it.parent == input) ? "top-level" : "sub-dir"
|
|
||||||
if (prev_input_type && (input_type != prev_input_type)) {
|
|
||||||
error "`watchPath` found input files in the top-level folder " +
|
|
||||||
"as well as in sub-directories."
|
|
||||||
}
|
|
||||||
// if file is in a sub-dir, make sure it's not a sub-sub-dir
|
|
||||||
if ((input_type == "sub-dir") && (it.parent.parent != input)) {
|
|
||||||
error "`watchPath` found an input file more than one level of " +
|
|
||||||
"sub-directories deep ('$it')."
|
|
||||||
}
|
|
||||||
// we also don't want files in the top-level dir when we got a sample sheet
|
|
||||||
if ((input_type == "top-level") && margs["sample_sheet"]) {
|
|
||||||
error "`watchPath` found input files in top-level folder even though " +
|
|
||||||
"a sample sheet was provided ('${margs["sample_sheet"]}')."
|
|
||||||
}
|
|
||||||
prev_input_type = input_type
|
|
||||||
}
|
|
||||||
if (margs.sample_sheet) {
|
|
||||||
// add metadata from sample sheet (we can't use join here since it does not work
|
|
||||||
// with repeated keys; we therefore need to transform the sample sheet data into
|
|
||||||
// a map with the barcodes as keys)
|
|
||||||
def ch_sample_sheet = get_sample_sheet(file(margs.sample_sheet), margs.required_sample_types)
|
|
||||||
| collect
|
|
||||||
| map { it.collectEntries { [(it["barcode"]): it] } }
|
|
||||||
// now we can use this channel to annotate all files with the corresponding info
|
|
||||||
// from the sample sheet
|
|
||||||
ch_watched = ch_watched
|
|
||||||
| combine(ch_sample_sheet)
|
|
||||||
| map { file_path, sample_sheet_map ->
|
|
||||||
String barcode = file_path.parent.name
|
|
||||||
Map sample_sheet_entry = sample_sheet_map[barcode]
|
|
||||||
// throw error if the barcode was not in the sample sheet
|
|
||||||
if (!sample_sheet_entry) {
|
|
||||||
error "Sub-folder $barcode was not found in the sample sheet."
|
|
||||||
}
|
|
||||||
[create_metamap(sample_sheet_entry), file_path]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ch_watched = ch_watched
|
|
||||||
| map {
|
|
||||||
// This file could be in the top-level dir or a sub-dir. In the first case
|
|
||||||
// check if a sample name was provided. In the second case, the alias is
|
|
||||||
// always the name of the sub-dir.
|
|
||||||
String alias
|
|
||||||
if (it.parent == input) {
|
|
||||||
// top-level dir
|
|
||||||
alias = margs["sample"] ?: it.parent.name
|
|
||||||
} else {
|
|
||||||
// sub-dir
|
|
||||||
alias = it.parent.name
|
|
||||||
}
|
|
||||||
[create_metamap([alias: alias]), it]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ch_watched
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
process move_or_compress_fq_file {
|
process move_or_compress_fq_file {
|
||||||
@ -950,9 +833,7 @@ Map parse_arguments(String func_name, Map arguments, Map extra_kwargs=[:]) {
|
|||||||
"sample_sheet": null,
|
"sample_sheet": null,
|
||||||
"analyse_unclassified": false,
|
"analyse_unclassified": false,
|
||||||
"analyse_fail": false,
|
"analyse_fail": false,
|
||||||
"stats": true,
|
|
||||||
"required_sample_types": [],
|
"required_sample_types": [],
|
||||||
"watch_path": false,
|
|
||||||
"per_read_stats": false,
|
"per_read_stats": false,
|
||||||
"allow_multiple_basecall_models": false,
|
"allow_multiple_basecall_models": false,
|
||||||
]
|
]
|
||||||
@ -970,7 +851,7 @@ Map parse_arguments(String func_name, Map arguments, Map extra_kwargs=[:]) {
|
|||||||
* null]` (with `input_path` pointing to a target file or a directory containing target
|
* null]` (with `input_path` pointing to a target file or a directory containing target
|
||||||
* files, respectively). `missing` contains sample sheet entries for which no
|
* files, respectively). `missing` contains sample sheet entries for which no
|
||||||
* corresponding barcodes were found.
|
* corresponding barcodes were found.
|
||||||
* Unless `watchPath` was requested, the function checks whether the input is a single
|
* Checks whether the input is a single
|
||||||
* target file, a top-level directory with target files, or a directory containing
|
* target file, a top-level directory with target files, or a directory containing
|
||||||
* sub-directories (usually barcodes) with target files.
|
* sub-directories (usually barcodes) with target files.
|
||||||
*
|
*
|
||||||
@ -992,12 +873,8 @@ def get_valid_inputs(Map margs, ArrayList extensions){
|
|||||||
// declare resulting input channel
|
// declare resulting input channel
|
||||||
def ch_input
|
def ch_input
|
||||||
|
|
||||||
// run `watchPath` if requested
|
|
||||||
if (margs["watch_path"]) {
|
|
||||||
ch_input = watch_path(input, margs, extensions)
|
|
||||||
|
|
||||||
// otherwise, easy case is this a file?
|
if (input.isFile()) {
|
||||||
} else if (input.isFile()) {
|
|
||||||
if (!is_target_file(input, extensions)) {
|
if (!is_target_file(input, extensions)) {
|
||||||
error "Input file is not of required file type."
|
error "Input file is not of required file type."
|
||||||
}
|
}
|
||||||
@ -1270,7 +1147,8 @@ def get_sample_sheet(Path sample_sheet, ArrayList required_sample_types) {
|
|||||||
// in STDOUT. Thus, we use the somewhat clunky construct with `concat` and `last`
|
// in STDOUT. Thus, we use the somewhat clunky construct with `concat` and `last`
|
||||||
// below. This lets the CSV channel only start to emit once the error checking is
|
// below. This lets the CSV channel only start to emit once the error checking is
|
||||||
// done.
|
// done.
|
||||||
ch_err = validate_sample_sheet(sample_sheet, required_sample_types).map { stdoutput, sample_sheet_file ->
|
boolean no_barcode_mode = false // CW-7025
|
||||||
|
ch_err = validate_sample_sheet(sample_sheet, required_sample_types, no_barcode_mode).map { stdoutput, sample_sheet_file ->
|
||||||
// check if there was an error message
|
// check if there was an error message
|
||||||
if (stdoutput) error "Invalid sample sheet: ${stdoutput}."
|
if (stdoutput) error "Invalid sample sheet: ${stdoutput}."
|
||||||
stdoutput
|
stdoutput
|
||||||
@ -1324,12 +1202,14 @@ process validate_sample_sheet {
|
|||||||
input:
|
input:
|
||||||
path "sample_sheet.csv"
|
path "sample_sheet.csv"
|
||||||
val required_sample_types
|
val required_sample_types
|
||||||
|
val no_barcode
|
||||||
output:
|
output:
|
||||||
tuple stdout, path("sample_sheet.csv")
|
tuple stdout, path("sample_sheet.csv")
|
||||||
script:
|
script:
|
||||||
String req_types_arg = required_sample_types ? "--required_sample_types "+required_sample_types.join(" ") : ""
|
String req_types_arg = required_sample_types ? "--required_sample_types "+required_sample_types.join(" ") : ""
|
||||||
|
String no_barcode_arg = no_barcode ? "--no_barcode" : ""
|
||||||
"""
|
"""
|
||||||
workflow-glue check_sample_sheet sample_sheet.csv $req_types_arg
|
workflow-glue check_sample_sheet sample_sheet.csv $req_types_arg $no_barcode_arg
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
main.nf
8
main.nf
@ -450,8 +450,6 @@ process makeReport {
|
|||||||
|
|
||||||
output:
|
output:
|
||||||
path ("wf-transcriptomes-*.html"), emit: report
|
path ("wf-transcriptomes-*.html"), emit: report
|
||||||
path ("results_dge.tsv"), emit: results_dge, optional: true
|
|
||||||
path ("unfiltered_tpm_transcript_counts.tsv"), emit: tpm, optional: true
|
|
||||||
path ("unfiltered_transcript_counts_with_genes.tsv"), emit: unfiltered, optional: true
|
path ("unfiltered_transcript_counts_with_genes.tsv"), emit: unfiltered, optional: true
|
||||||
path ("filtered_transcript_counts_with_genes.tsv"), emit: filtered, optional: true
|
path ("filtered_transcript_counts_with_genes.tsv"), emit: filtered, optional: true
|
||||||
path ("all_gene_counts.tsv"), emit: gene_counts, optional: true
|
path ("all_gene_counts.tsv"), emit: gene_counts, optional: true
|
||||||
@ -835,9 +833,11 @@ workflow pipeline {
|
|||||||
results = results.map{ [it, null] }.concat(fastq_ingress_results.map { [it, "fastq_ingress_results"] })
|
results = results.map{ [it, null] }.concat(fastq_ingress_results.map { [it, "fastq_ingress_results"] })
|
||||||
|
|
||||||
if (params.de_analysis){
|
if (params.de_analysis){
|
||||||
|
// `makeReport` stages copies of some DE files into its work dir; only publish
|
||||||
|
// the original `results_dge.tsv` and `unfiltered_tpm_transcript_counts.tsv`
|
||||||
|
// from `de_outputs` to avoid duplicate publish targets under `de_analysis/`.
|
||||||
de_results = report.concat(
|
de_results = report.concat(
|
||||||
transcriptome, de_outputs.flatten(),
|
transcriptome, de_outputs.flatten(),
|
||||||
makeReport.out.results_dge, makeReport.out.tpm,
|
|
||||||
makeReport.out.filtered, makeReport.out.unfiltered,
|
makeReport.out.filtered, makeReport.out.unfiltered,
|
||||||
makeReport.out.gene_counts)
|
makeReport.out.gene_counts)
|
||||||
// Output de_analysis results in the dedicated directory.
|
// Output de_analysis results in the dedicated directory.
|
||||||
@ -1004,7 +1004,6 @@ workflow {
|
|||||||
"sample":params.sample,
|
"sample":params.sample,
|
||||||
"sample_sheet":params.sample_sheet,
|
"sample_sheet":params.sample_sheet,
|
||||||
"analyse_unclassified":params.analyse_unclassified,
|
"analyse_unclassified":params.analyse_unclassified,
|
||||||
"stats": true,
|
|
||||||
"fastcat_extra_args": "",
|
"fastcat_extra_args": "",
|
||||||
"per_read_stats": true])
|
"per_read_stats": true])
|
||||||
} else {
|
} else {
|
||||||
@ -1015,7 +1014,6 @@ workflow {
|
|||||||
"analyse_unclassified":params.analyse_unclassified,
|
"analyse_unclassified":params.analyse_unclassified,
|
||||||
"keep_unaligned": true,
|
"keep_unaligned": true,
|
||||||
"return_fastq": true,
|
"return_fastq": true,
|
||||||
"stats": true,
|
|
||||||
"per_read_stats": true])
|
"per_read_stats": true])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -72,10 +72,8 @@ process deAnalysis {
|
|||||||
path "de_analysis/results_dge.tsv", emit: dge
|
path "de_analysis/results_dge.tsv", emit: dge
|
||||||
path "de_analysis/results_dexseq.tsv", emit: dexseq
|
path "de_analysis/results_dexseq.tsv", emit: dexseq
|
||||||
path "de_analysis/results_dge.pdf", emit: dge_pdf
|
path "de_analysis/results_dge.pdf", emit: dge_pdf
|
||||||
path "de_analysis/results_dge.tsv", emit: dge_tsv
|
|
||||||
path "de_analysis/results_dtu_gene.tsv", emit: dtu_gene
|
path "de_analysis/results_dtu_gene.tsv", emit: dtu_gene
|
||||||
path "de_analysis/results_dtu_transcript.tsv", emit: dtu_transcript
|
path "de_analysis/results_dtu_transcript.tsv", emit: dtu_transcript
|
||||||
path "de_analysis/results_dtu_stageR.tsv", emit: dtu_stageR
|
|
||||||
path "de_analysis/results_dtu.pdf", emit: dtu_pdf
|
path "de_analysis/results_dtu.pdf", emit: dtu_pdf
|
||||||
path "de_analysis/cpm_gene_counts.tsv", emit: cpm
|
path "de_analysis/cpm_gene_counts.tsv", emit: cpm
|
||||||
script:
|
script:
|
||||||
@ -195,8 +193,8 @@ workflow differential_expression {
|
|||||||
analysis.gene_counts, analysis.dge, analysis.dexseq,
|
analysis.gene_counts, analysis.dge, analysis.dexseq,
|
||||||
analysis.stageR, sample_sheet, merged, ref_annotation, merged_TPM, analysis.unflt_counts).collect()
|
analysis.stageR, sample_sheet, merged, ref_annotation, merged_TPM, analysis.unflt_counts).collect()
|
||||||
// Concat files required to be output to user without any changes
|
// Concat files required to be output to user without any changes
|
||||||
de_outputs_concat = analysis.cpm.concat(analysis.dexseq, plotResults.out.dtu_plots, analysis.dge_pdf, analysis.dge_tsv,
|
de_outputs_concat = analysis.cpm.concat(analysis.dexseq, plotResults.out.dtu_plots, analysis.dge_pdf, analysis.dge,
|
||||||
analysis.dtu_gene, analysis.dtu_transcript, analysis.dtu_stageR, analysis.dtu_pdf, merged_TPM).collect()
|
analysis.dtu_gene, analysis.dtu_transcript, analysis.stageR, analysis.dtu_pdf, merged_TPM).collect()
|
||||||
collected_de_alignment_stats = mapped.align_stats.collect()
|
collected_de_alignment_stats = mapped.align_stats.collect()
|
||||||
emit:
|
emit:
|
||||||
all_de = de_report
|
all_de = de_report
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user