Merge branch 'CW-2498' into 'dev'
tidy up DE outputs Closes CW-2498 See merge request epi2melabs/workflows/wf-transcriptomes!118
This commit is contained in:
commit
1153e705fa
10
CHANGELOG.md
10
CHANGELOG.md
@ -4,11 +4,19 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [updated]
|
## [unreleased]
|
||||||
### Changed
|
### Changed
|
||||||
|
- Improve differential expression outputs.
|
||||||
|
- Include transcript and gene count tables in DE_final folder.
|
||||||
|
- If differential expression subworkflow is used a non redundant transcriptome will be output which includes novel transcripts.
|
||||||
|
- Added wording to the report about how to identify novel transcripts in the DE tables.
|
||||||
- Nextflow minimum required version to 23.04.2
|
- Nextflow minimum required version to 23.04.2
|
||||||
- `--minimap_index_opts` parameter has been changed to `minimap2_index_opts` for consistency.
|
- `--minimap_index_opts` parameter has been changed to `minimap2_index_opts` for consistency.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- An additional gene name column to the differential gene expression results. This is especially handy for transcriptomes where the gene ID is not the same as gene name (e.g. Ensembl).
|
||||||
|
- Wording to the report about how to identify novel transcripts in the DE tables.
|
||||||
|
|
||||||
## [v0.2.1]
|
## [v0.2.1]
|
||||||
### Changed
|
### Changed
|
||||||
- Any sample aliases that contain spaces will be replaced with underscores.
|
- Any sample aliases that contain spaces will be replaced with underscores.
|
||||||
|
|||||||
@ -276,6 +276,11 @@ in `${out_dir}/jaffal_output_${sample_id}` you will find:
|
|||||||
* `de_analysis/results_dtu_gene.tsv`, `de_analysis/results_dtu_transcript.tsv` and `de_analysis/results_dtu.pdf` - results of differential transcript usage by `DEXSeq`.
|
* `de_analysis/results_dtu_gene.tsv`, `de_analysis/results_dtu_transcript.tsv` and `de_analysis/results_dtu.pdf` - results of differential transcript usage by `DEXSeq`.
|
||||||
* `de_analysis/results_dtu_stageR.tsv` - results of the `stageR` analysis of the `DEXSeq` output.
|
* `de_analysis/results_dtu_stageR.tsv` - results of the `stageR` analysis of the `DEXSeq` output.
|
||||||
* `de_analysis/dtu_plots.pdf` - DTU results plot based on the `stageR` results and filtered counts.
|
* `de_analysis/dtu_plots.pdf` - DTU results plot based on the `stageR` results and filtered counts.
|
||||||
|
* `de_analysis/all_gene_counts.tsv` - Gene counts generated by the `salmon` tool before filtering.
|
||||||
|
* `de_analysis/de_transcript_counts.tsv` - Transcript counts generated by the `salmon` tool before filtering.
|
||||||
|
* `de_analysis/de_tpm_transcript_counts.tsv` - To facilitate comparisons across samples this file shows transcript per million (TPM) of the raw counts.
|
||||||
|
* `de_analysis/all_counts_filtered.tsv` - Transcript counts filtered with input criteria. Used for 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.
|
||||||
|
|
||||||
### References
|
### References
|
||||||
|
|
||||||
|
|||||||
@ -237,6 +237,13 @@ def dtu_section(dtu_file, section, gt_dic, ge_dic):
|
|||||||
section.table(dtu_results.loc[dtu_pvals.index])
|
section.table(dtu_results.loc[dtu_pvals.index])
|
||||||
|
|
||||||
|
|
||||||
|
def dge_names(dge_file, geid_gname):
|
||||||
|
"""Add gene name column to DGE tsv."""
|
||||||
|
dge_results = pd.read_csv(dge_file, sep='\t')
|
||||||
|
dge_results["gene_name"] = dge_results.index.map(lambda x: geid_gname.get(x))
|
||||||
|
dge_results.to_csv('results_dge.tsv', index=True, index_label="gene_id")
|
||||||
|
|
||||||
|
|
||||||
def dge_section(dge_file, section, ids_dic):
|
def dge_section(dge_file, section, ids_dic):
|
||||||
"""Create DGE table and plot."""
|
"""Create DGE table and plot."""
|
||||||
section.markdown('### Differential gene expression')
|
section.markdown('### Differential gene expression')
|
||||||
@ -312,6 +319,7 @@ def get_translations(gtf):
|
|||||||
fn = open(gtf).readlines()
|
fn = open(gtf).readlines()
|
||||||
gene_txid = {}
|
gene_txid = {}
|
||||||
gene_geid = {}
|
gene_geid = {}
|
||||||
|
geid_gname = {}
|
||||||
|
|
||||||
def get_feature(row, feature):
|
def get_feature(row, feature):
|
||||||
return row.split(feature)[1].split(
|
return row.split(feature)[1].split(
|
||||||
@ -347,7 +355,8 @@ def get_translations(gtf):
|
|||||||
gene_id = gene_name
|
gene_id = gene_name
|
||||||
gene_txid[transcript_id] = gene_name
|
gene_txid[transcript_id] = gene_name
|
||||||
gene_geid[gene_id] = gene_reference
|
gene_geid[gene_id] = gene_reference
|
||||||
return gene_txid, gene_geid
|
geid_gname[gene_reference] = gene_name
|
||||||
|
return gene_txid, gene_geid, geid_gname
|
||||||
|
|
||||||
|
|
||||||
def de_section(
|
def de_section(
|
||||||
@ -364,6 +373,10 @@ the GTF-format annotation.
|
|||||||
These counts were used to perform a statistical analysis to identify
|
These counts were used to perform a statistical analysis to identify
|
||||||
the genes and isoforms that show differences in abundance between
|
the genes and isoforms that show differences in abundance between
|
||||||
the experimental conditions.
|
the experimental conditions.
|
||||||
|
Any novel genes or transcripts that do not have relevant gene or transcript IDs
|
||||||
|
are prefixed with MSTRG for use in differential expression analysis.
|
||||||
|
Find the full sequences of any transcripts in the
|
||||||
|
`final_non_redundant_transcriptome.fasta` file.
|
||||||
""")
|
""")
|
||||||
section.markdown("### Alignment summary stats")
|
section.markdown("### Alignment summary stats")
|
||||||
alignment_stats = pool_csvs("seqkit")
|
alignment_stats = pool_csvs("seqkit")
|
||||||
@ -371,8 +384,9 @@ the experimental conditions.
|
|||||||
alignment_summary_df = alignment_summary_df.fillna(0).applymap(np.int64)
|
alignment_summary_df = alignment_summary_df.fillna(0).applymap(np.int64)
|
||||||
section.table(alignment_summary_df, key='alignment-stats', index=True)
|
section.table(alignment_summary_df, key='alignment-stats', index=True)
|
||||||
salmon_table(tpm, section)
|
salmon_table(tpm, section)
|
||||||
gene_txid, gene_name = get_translations(stringtie)
|
gene_txid, gene_name, geid_gname = get_translations(stringtie)
|
||||||
dge_section(dge, section, gene_name)
|
dge_section(dge, section, gene_name)
|
||||||
|
dge_names(dge, geid_gname)
|
||||||
dexseq_section(dexseq, section, gene_name)
|
dexseq_section(dexseq, section, gene_name)
|
||||||
dtu_section(dtu, section, gene_txid, gene_name)
|
dtu_section(dtu, section, gene_txid, gene_name)
|
||||||
# missing dtu plots at the moment as too many
|
# missing dtu plots at the moment as too many
|
||||||
|
|||||||
@ -888,7 +888,8 @@ def de_section(report):
|
|||||||
dge = os.path.join("de_report", "results_dge.tsv")
|
dge = os.path.join("de_report", "results_dge.tsv")
|
||||||
dtu = os.path.join("de_report", "results_dtu_stageR.tsv")
|
dtu = os.path.join("de_report", "results_dtu_stageR.tsv")
|
||||||
stringtie = os.path.join("de_report", "stringtie_merged.gtf")
|
stringtie = os.path.join("de_report", "stringtie_merged.gtf")
|
||||||
tpm = os.path.join("de_report", "tpm_counts.tsv")
|
tpm = os.path.join("de_report", "de_tpm_transcript_counts.tsv")
|
||||||
|
# This will also add a gene name column to the "results_dge.tsv"
|
||||||
de_plots.de_section(
|
de_plots.de_section(
|
||||||
stringtie=stringtie,
|
stringtie=stringtie,
|
||||||
dexseq=dexseq,
|
dexseq=dexseq,
|
||||||
|
|||||||
@ -186,6 +186,11 @@ in `${out_dir}/jaffal_output_${sample_id}` you will find:
|
|||||||
* `de_analysis/results_dtu_gene.tsv`, `de_analysis/results_dtu_transcript.tsv` and `de_analysis/results_dtu.pdf` - results of differential transcript usage by `DEXSeq`.
|
* `de_analysis/results_dtu_gene.tsv`, `de_analysis/results_dtu_transcript.tsv` and `de_analysis/results_dtu.pdf` - results of differential transcript usage by `DEXSeq`.
|
||||||
* `de_analysis/results_dtu_stageR.tsv` - results of the `stageR` analysis of the `DEXSeq` output.
|
* `de_analysis/results_dtu_stageR.tsv` - results of the `stageR` analysis of the `DEXSeq` output.
|
||||||
* `de_analysis/dtu_plots.pdf` - DTU results plot based on the `stageR` results and filtered counts.
|
* `de_analysis/dtu_plots.pdf` - DTU results plot based on the `stageR` results and filtered counts.
|
||||||
|
* `de_analysis/all_gene_counts.tsv` - Gene counts generated by the `salmon` tool before filtering.
|
||||||
|
* `de_analysis/de_transcript_counts.tsv` - Transcript counts generated by the `salmon` tool before filtering.
|
||||||
|
* `de_analysis/de_tpm_transcript_counts.tsv` - To facilitate comparisons across samples this file shows transcript per million (TPM) of the raw counts.
|
||||||
|
* `de_analysis/all_counts_filtered.tsv` - Transcript counts filtered with input criteria. Used for 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.
|
||||||
|
|
||||||
### References
|
### References
|
||||||
|
|
||||||
|
|||||||
23
main.nf
23
main.nf
@ -309,14 +309,14 @@ process merge_transcriptomes {
|
|||||||
path ref_annotation
|
path ref_annotation
|
||||||
path ref_genome
|
path ref_genome
|
||||||
output:
|
output:
|
||||||
path "non_redundant.fasta", emit: fasta
|
path "final_non_redundant_transcriptome.fasta", emit: fasta
|
||||||
path "stringtie.gtf", emit: gtf
|
path "stringtie.gtf", emit: gtf
|
||||||
"""
|
"""
|
||||||
stringtie --merge -G $ref_annotation -p ${task.cpus} -o stringtie.gtf query_annotations/*
|
stringtie --merge -G $ref_annotation -p ${task.cpus} -o stringtie.gtf query_annotations/*
|
||||||
seqkit subseq --feature "transcript" --gtf-tag "transcript_id" --gtf stringtie.gtf $ref_genome > temp_transcriptome.fasta
|
seqkit subseq --feature "transcript" --gtf-tag "transcript_id" --gtf stringtie.gtf $ref_genome > temp_transcriptome.fasta
|
||||||
seqkit rmdup -s < temp_transcriptome.fasta > temp_del_repeats.fasta
|
seqkit rmdup -s < temp_transcriptome.fasta > temp_del_repeats.fasta
|
||||||
cat temp_del_repeats.fasta | sed 's/>.* />/' | sed -e 's/_[0-9]* \\[/ \\[/' > temp_rm_empty_seq.fasta
|
cat temp_del_repeats.fasta | sed 's/>.* />/' | sed -e 's/_[0-9]* \\[/ \\[/' > temp_rm_empty_seq.fasta
|
||||||
awk 'BEGIN {RS = ">" ; FS = "\\n" ; ORS = ""} \$2 {print ">"\$0}' temp_rm_empty_seq.fasta > non_redundant.fasta
|
awk 'BEGIN {RS = ">" ; FS = "\\n" ; ORS = ""} \$2 {print ">"\$0}' temp_rm_empty_seq.fasta > "final_non_redundant_transcriptome.fasta"
|
||||||
rm temp_transcriptome.fasta
|
rm temp_transcriptome.fasta
|
||||||
rm temp_del_repeats.fasta
|
rm temp_del_repeats.fasta
|
||||||
rm temp_rm_empty_seq.fasta
|
rm temp_rm_empty_seq.fasta
|
||||||
@ -342,6 +342,9 @@ process makeReport {
|
|||||||
path "seqkit/*"
|
path "seqkit/*"
|
||||||
output:
|
output:
|
||||||
path("wf-transcriptomes-*.html"), emit: report
|
path("wf-transcriptomes-*.html"), emit: report
|
||||||
|
// for DE analysis, a `gene_name` column will be added to
|
||||||
|
// `de_report/results_dge.tsv`
|
||||||
|
path "results_dge.tsv", emit: de_analysis, optional: true
|
||||||
script:
|
script:
|
||||||
// Convert the sample_id arrayList.
|
// Convert the sample_id arrayList.
|
||||||
sids = new BlankSeparatedList(sample_ids)
|
sids = new BlankSeparatedList(sample_ids)
|
||||||
@ -387,7 +390,6 @@ process makeReport {
|
|||||||
\$OPT_JAFFAL_CSV \
|
\$OPT_JAFFAL_CSV \
|
||||||
$OPT_DENOVO \
|
$OPT_DENOVO \
|
||||||
\$dereport
|
\$dereport
|
||||||
|
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +580,7 @@ workflow pipeline {
|
|||||||
gtf = merge_transcriptomes.out.gtf
|
gtf = merge_transcriptomes.out.gtf
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
transcriptome = ref_transcriptome
|
transcriptome = Channel.fromPath(ref_transcriptome)
|
||||||
gtf = ref_annotation
|
gtf = ref_annotation
|
||||||
}
|
}
|
||||||
de = differential_expression(transcriptome, input_reads, sample_sheet, gtf)
|
de = differential_expression(transcriptome, input_reads, sample_sheet, gtf)
|
||||||
@ -586,6 +588,7 @@ workflow pipeline {
|
|||||||
count_transcripts_file = de.count_transcripts
|
count_transcripts_file = de.count_transcripts
|
||||||
dtu_plots = de.dtu_plots
|
dtu_plots = de.dtu_plots
|
||||||
de_outputs = de.de_outputs
|
de_outputs = de.de_outputs
|
||||||
|
counts = de.counts
|
||||||
} else{
|
} else{
|
||||||
de_report = file("$projectDir/data/OPTIONAL_FILE")
|
de_report = file("$projectDir/data/OPTIONAL_FILE")
|
||||||
count_transcripts_file = file("$projectDir/data/OPTIONAL_FILE")
|
count_transcripts_file = file("$projectDir/data/OPTIONAL_FILE")
|
||||||
@ -606,6 +609,8 @@ workflow pipeline {
|
|||||||
|
|
||||||
report = makeReport.out.report
|
report = makeReport.out.report
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
results = results.concat(makeReport.out.report)
|
results = results.concat(makeReport.out.report)
|
||||||
|
|
||||||
if (use_ref_ann){
|
if (use_ref_ann){
|
||||||
@ -646,14 +651,18 @@ workflow pipeline {
|
|||||||
.map {it -> it[1]})
|
.map {it -> it[1]})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
results = results.map{ [it, null] }.concat(fastq_ingress_results.map { [it, "fastq_ingress_results"] })
|
||||||
|
|
||||||
if (params.de_analysis){
|
if (params.de_analysis){
|
||||||
results = results.concat(de.dtu_plots, de_outputs)
|
de_update = makeReport.out.de_analysis
|
||||||
|
de_results = report.concat(transcriptome, de_outputs.flatten(), counts.flatten(), de_update)
|
||||||
|
results = results.concat(de_results.map{ [it, "de_analysis"] })
|
||||||
}
|
}
|
||||||
|
|
||||||
results = fastq_ingress_results.map { [it, "fastq_ingress_results"] }.concat(results.map{ [it, null]})
|
results.concat(workflow_params.map{ [it, null]})
|
||||||
|
|
||||||
emit:
|
emit:
|
||||||
results
|
results
|
||||||
telemetry = workflow_params
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// entrypoint workflow
|
// entrypoint workflow
|
||||||
|
|||||||
@ -32,9 +32,9 @@ process mergeCounts {
|
|||||||
input:
|
input:
|
||||||
path counts
|
path counts
|
||||||
output:
|
output:
|
||||||
path "all_counts.tsv"
|
path "de_transcript_counts.tsv"
|
||||||
"""
|
"""
|
||||||
workflow-glue merge_count_tsvs -z -o all_counts.tsv -tsvs ${counts}
|
workflow-glue merge_count_tsvs -z -o de_transcript_counts.tsv -tsvs ${counts}
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,9 +43,9 @@ process mergeTPM {
|
|||||||
input:
|
input:
|
||||||
path counts
|
path counts
|
||||||
output:
|
output:
|
||||||
path "tpm_counts.tsv"
|
path "de_tpm_transcript_counts.tsv"
|
||||||
"""
|
"""
|
||||||
workflow-glue merge_count_tsvs -o tpm_counts.tsv -z -tpm True -tsvs $counts
|
workflow-glue merge_count_tsvs -o de_tpm_transcript_counts.tsv -z -tpm True -tsvs $counts
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ process plotResults {
|
|||||||
output:
|
output:
|
||||||
path "de_analysis/dtu_plots.pdf", emit: dtu_plots
|
path "de_analysis/dtu_plots.pdf", emit: dtu_plots
|
||||||
path "sample_sheet.tsv", emit: sample_sheet_csv
|
path "sample_sheet.tsv", emit: sample_sheet_csv
|
||||||
path "de_analysis", emit: stageR
|
path "de_analysis/*", emit: stageR
|
||||||
"""
|
"""
|
||||||
mkdir merged
|
mkdir merged
|
||||||
mv $sample_sheet de_analysis/coldata.tsv
|
mv $sample_sheet de_analysis/coldata.tsv
|
||||||
@ -173,9 +173,11 @@ workflow differential_expression {
|
|||||||
analysis.stageR).combine(plotResults.out.sample_sheet_csv).combine(merged).combine(
|
analysis.stageR).combine(plotResults.out.sample_sheet_csv).combine(merged).combine(
|
||||||
ref_annotation).combine(merged_TPM)
|
ref_annotation).combine(merged_TPM)
|
||||||
count_transcripts_file = count_transcripts.out.seqkit_stats.collect()
|
count_transcripts_file = count_transcripts.out.seqkit_stats.collect()
|
||||||
|
all_counts = merged_TPM.concat(merged, analysis.flt_counts, analysis.gene_counts)
|
||||||
emit:
|
emit:
|
||||||
all_de = de_report
|
all_de = de_report
|
||||||
count_transcripts = count_transcripts_file
|
count_transcripts = count_transcripts_file
|
||||||
dtu_plots = plotResults.out.dtu_plots
|
dtu_plots = plotResults.out.dtu_plots
|
||||||
de_outputs = plotResults.out.stageR
|
de_outputs = plotResults.out.stageR
|
||||||
|
counts = all_counts
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user