Merge branch 'gh_8' into 'dev'

Github issues

See merge request epi2melabs/workflow-containers/wf-isoforms!51
This commit is contained in:
Neil Horner 2022-04-11 15:08:47 +00:00
commit ebf814b4e2
5 changed files with 84 additions and 46 deletions

View File

@ -4,20 +4,22 @@ 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.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.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).
# Unreleased ## [v0.1.2]
## Added ### Added
- --direct_rna option. - direct_rna option
- Some extra error handling
- Minor report display improvements
## [v0.1.1] ## [v0.1.1]
## Fixed ### Fixed
- Incorrect numbers and of transcripts caused by merging gff files with same gene and transcript ids - Incorrect numbers and of transcripts caused by merging gff files with same gene and transcript ids
- Error handling in de novo pipeline. Skip clusters in build_backbones that cause an isONclust2 error - Error handling in de novo pipeline. Skip clusters in build_backbones that cause an isONclust2 error
- Several small fixes in report plotting - Several small fixes in report plotting
## [v0.1.0] ## [v0.1.0]
## Added ### Added
- Added the denovo pipeline - Added the denovo pipeline
## Changed ### Changed
- Updates to the report plots - Updates to the report plots
## [v0.0.1] ## [v0.0.1]

View File

@ -7,12 +7,12 @@ import math
from pathlib import Path from pathlib import Path
from aplanat import bars, hist, lines from aplanat import bars, hist, lines
from aplanat.components import fastcat
from aplanat.components import simple as scomponents from aplanat.components import simple as scomponents
from aplanat.components.fastcat import read_length_plot, read_quality_plot
from aplanat.report import WFReport from aplanat.report import WFReport
from aplanat.util import Colors from aplanat.util import Colors
from bokeh.layouts import gridplot from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource, Panel, Tabs from bokeh.models import ColumnDataSource, Legend, Panel, Tabs
from bokeh.models.widgets import DataTable, TableColumn from bokeh.models.widgets import DataTable, TableColumn
from bokeh.palettes import Category10_10 from bokeh.palettes import Category10_10
from bokeh.plotting import figure from bokeh.plotting import figure
@ -253,6 +253,8 @@ def grouped_bar(df, title="", tilted_xlabs=False):
dodge_increment = abs(dodge_range[0] - dodge_range[1]) / \ dodge_increment = abs(dodge_range[0] - dodge_range[1]) / \
(len(df.columns) - 1) (len(df.columns) - 1)
legend_it = []
if tilted_xlabs: if tilted_xlabs:
p.xaxis.major_label_orientation = math.pi / 4 p.xaxis.major_label_orientation = math.pi / 4
@ -270,15 +272,18 @@ def grouped_bar(df, title="", tilted_xlabs=False):
i += 1 i += 1
width = df.size / 60 width = df.size / 60
p.vbar( v = p.vbar(
x=dodge('x_groups', current_dodge, range=p.x_range), top=col, x=dodge('x_groups', current_dodge, range=p.x_range), top=col,
width=width, source=source, color=color, legend_label=col) width=width, source=source, color=color)
current_dodge += dodge_increment current_dodge += dodge_increment
legend_it.append([col, [v]])
legend = Legend(items=legend_it)
p.add_layout(legend, 'right')
p.x_range.range_padding = 0.1 p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None p.xgrid.grid_line_color = None
p.legend.location = "top_left" p.legend.location = "top_left"
p.legend.orientation = "horizontal" p.legend.orientation = "vertical"
return p return p
@ -319,6 +324,7 @@ def gff_compare_plots(report, gffcompare_outdirs: Path, sample_ids):
''') ''')
tabs = [] tabs = []
gff_fails = False
for id_, dir_ in zip(sample_ids, gffcompare_outdirs): for id_, dir_ in zip(sample_ids, gffcompare_outdirs):
stats, _, miss, novel, total = \ stats, _, miss, novel, total = \
parse_gffcmp_stats(dir_ / 'str_merged.stats') parse_gffcmp_stats(dir_ / 'str_merged.stats')
@ -333,16 +339,17 @@ def gff_compare_plots(report, gffcompare_outdirs: Path, sample_ids):
child=gridplot( child=gridplot(
[bar_totals, bar_performance, bar_missed, bar_novel], [bar_totals, bar_performance, bar_missed, bar_novel],
ncols=2, width=350, height=260), title=id_)) ncols=2, width=350, height=260), title=id_))
else:
gff_fails = True
if gff_fails:
gffcompare_md += ('''
__Warning__: Some gffcompare summary cannot be shown.
This could be due to incompatible reference fasta and gff
files.''')
cover_panel = Tabs(tabs=tabs) cover_panel = Tabs(tabs=tabs)
section.markdown(gffcompare_md) section.markdown(gffcompare_md)
section.plot(cover_panel) section.plot(cover_panel)
else:
gffcompare_md = ('''
__Warning__: Gffcompare summary cannot be shown.
This could be due to incompatible reference fasta and gff
files.''')
section.markdown(gffcompare_md)
names = { names = {
'=': 'ExactMatch:=', '=': 'ExactMatch:=',
@ -598,8 +605,8 @@ def transcript_table(report, df_tmaps, covr_threshold):
### Query transcript table ### Query transcript table
Low coverage transcripts are removed to speed up the table viewing. <br> Low coverage transcripts are removed to speed up the table viewing. <br>
This can be set with the parameter `transcript_table_cov_thresh` in the Coverage threshold can be set with the parameter
config. `transcript_table_cov_thresh`.
''') ''')
df = df_tmaps.drop( df = df_tmaps.drop(
@ -614,6 +621,12 @@ def transcript_table(report, df_tmaps, covr_threshold):
df.sort_values('cov', ascending=True, inplace=True) df.sort_values('cov', ascending=True, inplace=True)
counts = list(range(len(df))) counts = list(range(len(df)))
# Filter on coverage threshold
df = df[df['cov'] >= covr_threshold]
if len(df) < 200: # Min size of table should be 200. Don't filter
df = df.sort_values('cov', ascending=False).iloc[:, 0:200]
covr_threshold = 0
# Keep Isoforms with coverage > threshold # Keep Isoforms with coverage > threshold
vline_x = np.argmax(df['cov'] > covr_threshold) vline_x = np.argmax(df['cov'] > covr_threshold)
vline_y = [0, df['cov'].max()] vline_y = [0, df['cov'].max()]
@ -629,10 +642,6 @@ def transcript_table(report, df_tmaps, covr_threshold):
colors=['blue', 'red']) colors=['blue', 'red'])
section.plot(cov_plt) section.plot(cov_plt)
# Filter on coverage threshold
df = df[df['cov'] >= covr_threshold]
if len(df) < 200: # Min size of table should be 200
df = df.sort_values('cov', ascending=False).iloc[:, 0:200]
# Make a column of number of isoforms in parent gene # Make a column of number of isoforms in parent gene
gb = df.groupby(['ref_gene_id', 'sample_id']).count() gb = df.groupby(['ref_gene_id', 'sample_id']).count()
@ -707,6 +716,8 @@ def transcriptome_summary(report, gffs, sample_ids, denovo=False):
bar_isos = hist.histogram( bar_isos = hist.histogram(
[isoforms_per_gene], colors=[Colors.cerulean], [isoforms_per_gene], colors=[Colors.cerulean],
title="isoforms per gene") title="isoforms per gene")
bar_isos.xaxis.axis_label = "Num. isoforms"
bar_isos.yaxis.axis_label = "Num. genes"
bar_isos.xaxis.major_label_orientation = math.pi / 2.8 bar_isos.xaxis.major_label_orientation = math.pi / 2.8
plots.append(bar_isos) plots.append(bar_isos)
@ -723,6 +734,8 @@ def transcriptome_summary(report, gffs, sample_ids, denovo=False):
fig = figure(title="Exons per transcript") fig = figure(title="Exons per transcript")
fig.vbar( fig.vbar(
x, top=list(y), color=Colors.cerulean) x, top=list(y), color=Colors.cerulean)
fig.xaxis.axis_label = 'Num. exons'
fig.yaxis.axis_label = 'Num. genes'
fig.xaxis.major_label_orientation = math.pi / 2.8 fig.xaxis.major_label_orientation = math.pi / 2.8
plots.append(fig) plots.append(fig)
@ -765,6 +778,23 @@ def load_sample_data(files, sample_ids, read_func=None):
return df_ return df_
def seq_stats_tabs(report, sample_ids, stats):
"""Make tabs of sequence summaries by sample."""
tabs = []
for id_, summ in sorted(zip(sample_ids, stats)):
df_sum = pd.read_csv(summ, index_col=False, sep='\t')
rlp = read_length_plot(df_sum)
rqp = read_quality_plot(df_sum)
grid = gridplot(
[rlp, rqp], ncols=2, sizing_mode="stretch_width")
tabs.append(Panel(child=grid, title=id_))
section = report.add_section()
section.markdown("""
### Sequence summaries""")
section.plot(Tabs(tabs=tabs))
def main(): def main():
"""Run the entry point.""" """Run the entry point."""
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@ -815,12 +845,7 @@ def main():
revision=args.revision, commit=args.commit) revision=args.revision, commit=args.commit)
# Add reads summary section # Add reads summary section
for id_, summ in zip(sample_ids, args.summaries): seq_stats_tabs(report, args.sample_ids, args.summaries)
report.add_section(
section=fastcat.full_report(
[summ],
header='#### Read stats: {}'.format(id_)
))
if args.alignment_stats is not None: if args.alignment_stats is not None:
df_aln_stats = load_sample_data(args.alignment_stats, sample_ids) df_aln_stats = load_sample_data(args.alignment_stats, sample_ids)

21
main.nf
View File

@ -130,20 +130,31 @@ process split_bam{
output: output:
tuple val(sample_id), path('*.bam'), emit: bundles tuple val(sample_id), path('*.bam'), emit: bundles
script: script:
if (params["bundle_min_reads"] != false)
""" """
n=`samtools view -c $bam`
if [[ n -lt 1 ]]
then
echo 'There are no reads mapping for $sample_id. Exiting!'
exit 1
fi
re='^[0-9]+\$'
if [[ $params.bundle_min_reads =~ \$re ]]
then
echo "Bundling up the bams"
seqkit bam -j ${params.threads} -N ${params.bundle_min_reads} ${bam} -o bam_bundles/ seqkit bam -j ${params.threads} -N ${params.bundle_min_reads} ${bam} -o bam_bundles/
mv bam_bundles/* .
let i=1 let i=1
for b in *.bam; do for b in bam_bundles/*.bam; do
echo \$b
newname="${sample_id}_batch_\${i}.bam" newname="${sample_id}_batch_\${i}.bam"
mv \$b \$newname mv \$b \$newname
((i++)) ((i++))
done done
"""
else else
""" echo 'no bundling'
ln -s ${bam} ${sample_id}_batch_1.bam ln -s ${bam} ${sample_id}_batch_1.bam
fi
""" """
} }

View File

@ -23,7 +23,7 @@ params {
sample = null sample = null
sample_sheet = null sample_sheet = null
sanitize_fastq = false sanitize_fastq = false
wfversion = "v0.1.1" wfversion = "v0.1.2"
aws_image_prefix = null aws_image_prefix = null
aws_queue = null aws_queue = null
report_name = "report" report_name = "report"
@ -34,7 +34,7 @@ params {
schema_ignore_params = 'show_hidden_params,validate_params,monochrome_logs,aws_queue,aws_image_prefix,wfversion' schema_ignore_params = 'show_hidden_params,validate_params,monochrome_logs,aws_queue,aws_image_prefix,wfversion'
// Process cDNA reads using pychopper, turn off for direct RNA: // Process cDNA reads using pychopper, turn off for direct RNA:
direct_rna = true direct_rna = false
// Options passed to pychopper: // Options passed to pychopper:
pychopper_opts = "-m edlib" pychopper_opts = "-m edlib"

View File

@ -280,7 +280,7 @@
}, },
"wfversion": { "wfversion": {
"type": "string", "type": "string",
"default": "v0.1.1", "default": "v0.1.2",
"hidden": true "hidden": true
}, },
"monochrome_logs": { "monochrome_logs": {