Denovo bug fixes

This commit is contained in:
Neil Horner 2022-03-02 11:34:21 +00:00
parent b56cec9994
commit 03b8ba51f6
7 changed files with 225 additions and 186 deletions

View File

@ -116,12 +116,11 @@ For example:
- Summary and plots of reads, alignments and the transcript assembly and annotation
- One file per run with results from each sample merged
####Transcript isoform table
Note: Currently only available for the reference-guilded assembly
The report includes a searchable filterable table of transcript isoforms<br>
Note transcript isoform table is currently only available for the reference-guilded assembly.
Note: If using a large dataset with 10s of thousands of predicted isoforms, to speed up searching, the table can be limited
by read coverage, which can be set with `transcript_table_cov_thresh = 50` (default 50x)
#### Output files
Each sample will also have it's own directory containing the following (dependent on assembly approach and input options)
* {sampleid}_gffcompare
* Directory containing all output from gffcompare
@ -133,9 +132,6 @@ Each sample will also have it's own directory containing the following (dependen
- A transcriptome derived from the query reads + reference annotation
* merged_transcriptome.fas
-A transcriptome made from the combined query reads and reference annotation
* final_polished_cds.fas (de novo only)
* CDS sequences derived from reads
## Useful links

54
bin/merge_gff.py Executable file
View File

@ -0,0 +1,54 @@
#!/usr/bin/env python
"""
Merge and fix gff files.
Merge multiple gff files into single file.
Rename gene and transcript ids to avoid attribute conflicts from
independently-created files.
"""
import argparse
from pathlib import Path
import re
from natsort import natsorted
def main(gff_files: str, outfile: str):
"""Entry point."""
regx_id = re.compile(r'gene_id "STRG\.(\d+)"')
start = 1
with open(outfile, 'w') as fh:
for gff in gff_files:
text = Path(gff).read_text()
if start != 1:
# Strip headers
text = [x for x in text.splitlines() if not x.startswith('#')]
text = '\n'.join(text)
ids = natsorted(set(re.findall(regx_id, text)))
new_gene_ids = list(range(start, start + len(ids)))
id_map = dict(zip(ids, new_gene_ids))
for old_id, new_id in id_map.items():
text = text.replace(
f'gene_id "STRG.{old_id}"',
f'gene_id "STRG.{new_id}"')
text = text.replace(
f'transcript_id "STRG.{old_id}.',
f'transcript_id "STRG.{new_id}.')
fh.write(text)
fh.write('\n')
start += len(ids)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("--gff_files", help="gff files to merge",
required=True, nargs='+')
parser.add_argument("--out_file", help="where to save merged files",
required=True)
args = parser.parse_args()
main(args.gff_files, args.out_file)

View File

@ -6,7 +6,7 @@ from collections import Counter, defaultdict, OrderedDict
import math
from pathlib import Path
from aplanat import bars, lines
from aplanat import bars, hist, lines
from aplanat.components import fastcat
from aplanat.components import simple as scomponents
from aplanat.report import WFReport
@ -648,7 +648,8 @@ def transcript_table(report, df_tmaps, covr_threshold):
### Query transcript table
Low coverage transcripts are removed to speed up the table viewing. <br>
This can be set with the parameter `args.min_isoform_cov` in the config.
This can be set with the parameter `transcript_table_cov_thresh` in the
config.
''')
section.plot(cov_plt)
# Filter on converge threshold
@ -724,17 +725,9 @@ def tanscriptome_summary(report, gffs, sample_ids, denovo=False):
transcript_lens.append(tr_len)
num_bins = max(isoforms_per_gene)
if num_bins > 12:
num_bins = 12
hist_, bins = np.histogram(isoforms_per_gene, bins=num_bins)
bar_isos = bars.simple_bar([str(round(x_, 1)) for x_ in bins], hist_,
title="Isoforms per gene",
colors=Colors.cerulean,
x_axis_label='Num. isoforms',
y_axis_label='Num. genes')
bar_isos = hist.histogram(
[isoforms_per_gene], colors=[Colors.cerulean],
title="isoforms per gene")
bar_isos.xaxis.major_label_orientation = math.pi / 2.8
plots.append(bar_isos)

View File

@ -39,16 +39,13 @@ process dump_clusters {
process build_backbones {
/*
This step can fail in what seems to at the racon stage giving an 'empty overlap error set' message
As a temporary fix, do racon_cmd || true to prevent it crashing the pipeline, and then move on to next cluster
This process needs some work
Build coding
*/
label "isoforms"
input:
tuple val(sample_id), path(cluster_fq)
output:
tuple val(sample_id), path("*final_polished_cds.fa"), emit: polished_cds
tuple val(sample_id), path("*final_polished_cds.fa"), emit: polished_cds, optional: true
script:
def cluster_fq_bl = new BlankSeparatedList(cluster_fq)
"""
@ -56,64 +53,70 @@ process build_backbones {
UNID=\$(echo ${cluster_fq_bl[1]} | grep -o -E '[0-9]+')
for cluster in $cluster_fq_bl
do
clfq=`basename \$cluster`
cln=\${clfq%.*}
do
clfq=`basename \$cluster`
cln=\${clfq%.*}
echo Building backbone for cluster: \$cln
echo "\tSampling input reads for backbone construction."
sample=\${cln}_sample.fq
seqkit head --quiet -n 100 \$cluster > \$sample
seqkit sample --quiet -n 500 -2 -s 100 \$cluster >> \$sample
echo "\tConstructing spoa consensus."
spoa_cons=\${cln}_spoa.fa
spoa -m 5 -n -4 -g -8 -e -6 -q -10 -c -15 -l 1 -r 0 \$sample > \$spoa_cons
echo Building backbone for cluster: \$cln
echo "\tSampling input reads for backbone construction."
sample=\${cln}_sample.fq
seqkit head --quiet -n 100 \$cluster > \$sample
seqkit sample --quiet -n 500 -2 -s 100 \$cluster >> \$sample
echo "\tConstructing spoa consensus."
spoa_cons=\${cln}_spoa.fa
spoa -m 5 -n -4 -g -8 -e -6 -q -10 -c -15 -l 1 -r 0 \$sample > \$spoa_cons
echo "\tPolishing the consensus using racon."
echo "\tPolishing the consensus using racon."
# polish 1
samgz=\${cln}_aln.sam.gz
racon_cons=\${cln}_racon.fa
racon_cons1=\${cln}_racon1.fa
# polish 1
samgz=\${cln}_aln.sam.gz
racon_cons=\${cln}_racon.fa
tmpcons=\${cln}_tmcons.fa
minimap2 -t ${params.threads} -ax splice ${params.minimap2_opts} \$spoa_cons \$sample | gzip - > \$samgz
racon -t ${params.threads} --no-trimming -u -w 2000 \$sample \$samgz \$spoa_cons > \$racon_cons || true
if [ -f \$racon_cons ];
then
cat \$racon_cons | seqkit replace -p ".*" -r cluster_\${cln} > \$racon_cons1
else
continue
fi
minimap2 -t ${params.threads} -ax splice ${params.minimap2_opts} \$spoa_cons \$sample | gzip - > \$samgz
exitcode=0
racon -t ${params.threads} --no-trimming -u -w 2000 \$sample \$samgz \$spoa_cons > \$racon_cons || exitcode=1
if [[ \$exitcode -eq 0 ]];
then
# Rename consensus sequence name with cluster id
cat \$racon_cons | seqkit replace -p ".*" -r cluster_\${cln} > \$tmpcons
mv \$tmpcons \$racon_cons
else
echo "Polishing failed for \${cln}"
continue
fi
# polish 2
samgz1=\${cln}_aln_1.sam.gz
racon_cons2=\${cln}_racon2.fa
minimap2 -t ${params.threads} -ax splice ${params.minimap2_opts} \$racon_cons1 \$sample | gzip - > \$samgz1
racon -t ${params.threads} -u --no-trimming \$sample \$samgz1 \$racon_cons1 > \$racon_cons2 || true
if [ -f \$racon_cons2 ];
then
echo "success polish 2"
else
continue
fi
# polish 2
minimap2 -t ${params.threads} -ax splice ${params.minimap2_opts} \$racon_cons \$sample | gzip - > \$samgz
exitcode=0
racon -t ${params.threads} -u --no-trimming \$sample \$samgz \$racon_cons > \$tmpcons || exitcode=1
if [[ \$exitcode -eq 0 ]];
then
echo "success polish 2"
mv \$tmpcons \$racon_cons
else
echo "Polishing failed for \${cln}"
continue
fi
# polish 3
samgz2=\${cln}_aln_2.sam.gz
minimap2 -t ${params.threads} -ax splice ${params.minimap2_opts} \$racon_cons2 \$sample | gzip - > \$samgz2
EXITCODE=0
racon -t ${params.threads} -u \$sample \$samgz2 \$racon_cons2 >> ${sample_id}_\${UNID}_final_polished_cds.fa || EXITCODE=\$?
if [ \$EXITCODE -eq 0 ];
then
echo "finished"
fi
# polish 3
minimap2 -t ${params.threads} -ax splice ${params.minimap2_opts} \$racon_cons \$sample | gzip - > \$samgz
exitcode=0
racon -t ${params.threads} -u \$sample \$samgz \$racon_cons > \$tmpcons || exitcode=1
if [[ \$exitcode -eq 0 ]];
then
cat \$tmpcons >> ${sample_id}_\${UNID}_final_polished_cds.fa
echo "polishing 3 success"
else
echo "Polishing failed for \${cln}"
fi
done
done
echo "Finished backbones"
"""
}
process merge_cds {
label "isoforms"
input:
@ -121,7 +124,6 @@ process merge_cds {
output:
tuple val(sample_id), path("${sample_id}_cds.fa"), emit: final_polished_cds
script:
def merge_list
"""
for FILE in *final_polished_cds.fa
do
@ -138,14 +140,13 @@ process cds_align {
tuple val(sample_id), path("${sample_id}_reads_aln_sorted.bam"), emit: bam
tuple val(sample_id), path("${sample_id}_read_aln_stats.tsv"), emit: stats
script:
def ab = "${sample_id}_reads_aln_sorted.bam"
"""
minimap2 -t ${params.threads} \
-ax splice ${params.minimap2_opts} $polished_cds $sorted_reads_dir/sorted_reads.fastq |\
samtools view -b - |\
samtools sort -o $ab;
samtools index $ab;
((seqkit bam -s -j ${params.threads} ${ab} 2>&1) | tee ${sample_id}_read_aln_stats.tsv ) || true
minimap2 -t ${params.threads} \
-ax splice ${params.minimap2_opts} $polished_cds $sorted_reads_dir/sorted_reads.fastq |\
samtools view -b - |\
samtools sort -o "${sample_id}_reads_aln_sorted.bam";
samtools index "${sample_id}_reads_aln_sorted.bam";
((seqkit bam -s -j ${params.threads} "${sample_id}_reads_aln_sorted.bam" 2>&1) | tee ${sample_id}_read_aln_stats.tsv ) || true
"""
}
@ -168,16 +169,14 @@ process make_batches {
minimum_batch_size = 2000
"""
nr_bases=\$(seqkit stats -T $fastq|cut -f 5| sed '2q;d')
b=0
if [ ${params.batch_size} -lt \$b ];
then
nr_bases=\$(seqkit stats -T $fastq|cut -f 5| sed '2q;d')
let batch_size=\$nr_bases/1000/$maxcpus
if [ \$batch_size -lt $minimum_batch_size ];
then
batch_size=$minimum_batch_size
then
batch_size=$minimum_batch_size
fi
else
batch_size=${params.batch_size}
@ -186,11 +185,12 @@ process make_batches {
echo "Batch size:\$batch_size";
echo "Num bases: \$nr_bases";
init_cls_options="--batch-size \$batch_size --kmer-size ${params.kmer_size} \
--window-size ${params.window_size} --min-shared ${params.min_shared} --min-qual ${params.min_qual} \
--mapped-threshold ${params.mapped_threshold} --aligned-threshold ${params.aligned_threshold} \
--min-fraction ${params.min_fraction} --min-prob-no-hits ${params.min_prob_no_hits} \
-M ${params.batch_max_seq} -P ${params.consensus_period} -g ${params.consensus_minimum} -c ${params.consensus_maximum} -F ${params.min_left_cls} "
init_cls_options="--batch-size \$batch_size --kmer-size ${params.kmer_size} --window-size ${params.window_size} \
--min-shared ${params.min_shared} --min-qual ${params.min_qual} \
--mapped-threshold ${params.mapped_threshold} --aligned-threshold ${params.aligned_threshold} \
--min-fraction ${params.min_fraction} --min-prob-no-hits ${params.min_prob_no_hits} \
-M ${params.batch_max_seq} -P ${params.consensus_period} -g ${params.consensus_minimum} \
-c ${params.consensus_maximum} -F ${params.min_left_cls} "
mkdir -p sorted; isONclust2 sort \$init_cls_options -v -o sorted $fastq;
"""
@ -206,7 +206,6 @@ process clustering() {
script:
"""
run_isonclust2.py $sorted_batches
"""
}
@ -216,8 +215,8 @@ process cluster_quality() {
label "isoforms"
input:
tuple val(sample_id), path(reads_fl), path(final_clusters_dir)
path reference
tuple val(sample_id), path(reads_fl), path(final_clusters_dir)
output:
tuple val(sample_id),
path("${sample_id}_cluster_qc"), emit: cluster_qc_dir
@ -229,16 +228,15 @@ process cluster_quality() {
def bam = "${qc_dir}/ref_aln.bam"
"""
echo $qc_dir_raw
mkdir $qc_dir
mkdir $qc_dir_raw
minimap2 -ax splice -t 2 $reference $reads_fl |\
samtools view -q 2 -F 2304 -b - |\
samtools sort - -o $bam;
samtools view -q 2 -F 2304 -b - |\
samtools sort - -o $bam;
samtools index $bam;
compute_cluster_quality.py --sizes $final_clusters_dir/clusters_info.tsv \
--outfile ${qc_dir}/cluster_quality.csv --ont --clusters $final_clusters_dir/clusters.tsv \
--classes $bam --report ${qc_dir}/cluster_quality.pdf --raw_data_out $qc_dir_raw
--outfile ${qc_dir}/cluster_quality.csv --ont --clusters $final_clusters_dir/clusters.tsv \
--classes $bam --report ${qc_dir}/cluster_quality.pdf --raw_data_out $qc_dir_raw
"""
}
@ -248,37 +246,35 @@ workflow denovo_assembly {
fastq_reads_fl
reference
main:
make_batches(fastq_reads_fl)
clustering(make_batches.output.sorted_batches)
clustering(make_batches.out.sorted_batches)
dump_clusters(clustering.output.root_cluster
.join(make_batches.output.sorted_reads_dir))
dump_clusters(
clustering.out.root_cluster
.join(make_batches.out.sorted_reads_dir))
build_backbones(dump_clusters.output.final_clusters
.flatMap(map_sample_ids_cls)
.groupTuple(size: 10, remainder: true)
)
build_backbones(
dump_clusters.out.final_clusters
.flatMap(map_sample_ids_cls)
.groupTuple(size: 10, remainder: true))
merge_cds(build_backbones.output.polished_cds
.flatMap(map_sample_ids_cls)
.groupTuple()
)
merge_cds(
build_backbones.out.polished_cds
.flatMap(map_sample_ids_cls)
.groupTuple())
cds_align(merge_cds.out.final_polished_cds.view()
.join(make_batches.output.sorted_reads_dir))
cds_align(
merge_cds.out.final_polished_cds
.join(make_batches.out.sorted_reads_dir))
if (!reference.name.startsWith('OPTIONAL_FILE')){
cluster_quality(reference, fastq_reads_fl
.join(dump_clusters.out.final_clusters_dir))
cluster_quality(fastq_reads_fl
.join(dump_clusters.output.final_clusters_dir), reference)
cluster_quality.out.cluster_qc_dir.set { opt_qual_ch }
cluster_quality.out.cluster_qc_dir
.set { opt_qual_ch }
cluster_quality.output.cluster_qc_raw
.set { opt_qual_raw_ch }
cluster_quality.out.cluster_qc_raw.set { opt_qual_raw_ch }
} else{
Channel.empty().set { opt_qual_ch }
@ -286,9 +282,9 @@ workflow denovo_assembly {
}
emit:
bam = cds_align.output.bam
bam = cds_align.out.bam
cds = merge_cds.out.final_polished_cds
stats = cds_align.output.stats
stats = cds_align.out.stats
opt_qual_ch
opt_qual_raw_ch
}

View File

@ -1,4 +1,4 @@
name: epi2melabs-wf-isoforms-test
name: epi2melabs-wf-isoforms
channels:
- epi2melabs
- bioconda
@ -26,3 +26,4 @@ dependencies:
- isonclust2==2.3
- parallel
- scikit-learn==1.0.2
- natsort

99
main.nf
View File

@ -42,6 +42,7 @@ process getVersions {
python -c "import pysam; print(f'pysam,{pysam.__version__}')" >> versions.txt
python -c "import aplanat; print(f'aplanat,{aplanat.__version__}')" >> versions.txt
python -c "import pandas; print(f'pandas,{pandas.__version__}')" >> versions.txt
python -c "import sklearn; print(f'scikit-learn,{sklearn.__version__}')" >> versions.txt
fastcat --version | sed 's/^/fastcat,/' >> versions.txt
minimap2 --version | sed 's/^/minimap2,/' >> versions.txt
samtools --version | head -n 1 | sed 's/ /,/' >> versions.txt
@ -105,7 +106,7 @@ process build_minimap_index{
path "genome_index.mmi", emit: index
script:
"""
minimap2 -t ${params.threads} ${params.minimap_index_opts} -I 1000G -d "genome_index.mmi" ${reference}
minimap2 -t ${params.threads} ${params.minimap_index_opts} -I 1000G -d "genome_index.mmi" ${reference}
"""
}
@ -128,7 +129,7 @@ process split_bam{
if (params["bundle_min_reads"] != false)
"""
seqkit bam -j ${params.threads} -N ${params.bundle_min_reads} ${bam} -o bam_bundles/
mv bam_bundles/* .
mv bam_bundles/* .
for f in *:*; do mv -v "\$f" \$(echo "\$f" | tr ':' '-'); done
"""
else
@ -145,7 +146,7 @@ process assemble_transcripts{
Take aligned reads in bam format that may be a chunk of a larger alignment file.
Optionally use reference annotation to guide assembly.
Output gff annotation files in a tuple with `sample_id` for combining into samples late rin the pipeline.
Output gff annotation files in a tuple with `sample_id` for combining into samples later in the pipeline.
*/
label 'isoforms'
cpus params.threads
@ -158,16 +159,17 @@ process assemble_transcripts{
script:
def out_filename = bam.name.replaceFirst(~/\.[^\.]+$/, '') + "_${sample_id}.gff"
def G_FLAG = ref_annotation.name.startsWith('OPTIONAL_FILE') ? '' : "-G ${ref_annotation}"
def prefix = bam.name.split('-')[0][5..-1]
"""
stringtie --rf ${G_FLAG} -L -v -A gene_abund.tab -p ${params.threads} ${params.stringtie_opts} -o ${out_filename} \
${bam} 2>/dev/null
"""
-l $prefix ${bam} 2>/dev/null
"""
}
process merge_gff_bundles{
/*
Merge gff bundles into a single gff file.
Merge gff bundles into a single gff file per sample.
*/
label 'isoforms'
@ -215,14 +217,14 @@ process run_gffcompare{
mkdir $out_dir
echo "Doing comparison of reference annotation: ${ref_annotation} and the query annotation"
gffcompare -o ${out_dir}/str_merged -r ${ref_annotation} \
${params.gffcompare_opts} ${query_annotation}
gffcompare -o ${out_dir}/str_merged -r ${ref_annotation} \
${params.gffcompare_opts} ${query_annotation}
generate_tracking_summary.py --tracking $out_dir/str_merged.tracking \
--output_dir ${out_dir} --annotation ${ref_annotation}
--output_dir ${out_dir} --annotation ${ref_annotation}
mv *.tmap $out_dir
mv *.refmap $out_dir
mv *.tmap $out_dir
mv *.refmap $out_dir
"""
}
}
@ -231,7 +233,6 @@ process run_gffcompare{
process get_transcriptome{
/*
Write out a transcriptome file based on the query gff annotations.
TODO: Do we need to touch merged_transcriptome or can we just pass it?
*/
label 'isoforms'
@ -244,13 +245,10 @@ process get_transcriptome{
def transcriptome = "${sample_id}_transcriptome.fas"
def merged_transcriptome = "${sample_id}_merged_transcriptome.fas"
"""
gffread -g ${reference_seq} -w ${transcriptome} ${transcripts_gff}
if [ "\$(ls -A $gffcmp_dir)" ];
then
echo "Yes"
gffread -F -g ${reference_seq} -w ${merged_transcriptome} \
$gffcmp_dir/str_merged.annotated.gtf
then
gffread -F -g ${reference_seq} -w ${merged_transcriptome} $gffcmp_dir/str_merged.annotated.gtf
fi
"""
}
@ -274,7 +272,6 @@ process makeReport {
script:
// Convert the sample_id arrayList.
sids = new BlankSeparatedList(sample_ids)
def report_name = "wf-isoforms-report.html"
def OPT_ALN = denovo ? '' : "--alignment_stats ${aln_stats}"
def OPT_DENOVO = denovo ? "--denovo" : ''
@ -365,61 +362,63 @@ workflow pipeline {
run_gffcompare(merge_gff_bundles.out.gff, ref_annotation)
if (params.denovo){
// Use the perd-sample, de novo-assembled CDS
// Use the per-sample, de novo-assembled CDS
seq_for_transcriptome_build = m.cds
}else {
// If doing reference based assembly, there is only one reference
// For reference based assembly, there is only one reference
// So map this reference to all sample_ids
seq_for_transcriptome_build = sample_ids.flatten().combine(Channel.fromPath(params.ref_genome))
}
makeReport(software_versions,
workflow_params,
params.denovo,
summariseConcatReads.out.summary
.join(m.stats)
.join(run_gffcompare.out.gffcmp_dir)
.join(preprocess_reads.out.report)
.join(merge_gff_bundles.out.gff)
.toList().transpose().toList()
)
makeReport(
software_versions,
workflow_params,
params.denovo,
summariseConcatReads.out.summary
.join(m.stats)
.join(run_gffcompare.out.gffcmp_dir)
.join(preprocess_reads.out.report)
.join(merge_gff_bundles.out.gff)
.toList().transpose().toList())
report = makeReport.out.report
get_transcriptome(merge_gff_bundles.out.gff
get_transcriptome(
merge_gff_bundles.out.gff
.join(run_gffcompare.out.gffcmp_dir)
.join(seq_for_transcriptome_build))
if (use_ref_ann){
results = preprocess_reads.out.report
.concat(run_gffcompare.output.gffcmp_dir,
m.stats,
get_transcriptome.out.flatMap(map_sample_ids_cls))
.map {it -> it[1]}
.concat(makeReport.out.report)
.concat(
run_gffcompare.output.gffcmp_dir,
m.stats,
get_transcriptome.out.flatMap(map_sample_ids_cls))
.map {it -> it[1]}
.concat(makeReport.out.report)
}
if (!use_ref_ann && !params.denovo){
results = preprocess_reads.out.report
.concat(m.stats,
get_transcriptome.out.flatMap(map_sample_ids_cls))
.map {it -> it[1]}
.concat(makeReport.out.report)
.concat(m.stats,
get_transcriptome.out.flatMap(map_sample_ids_cls))
.map {it -> it[1]}
.concat(makeReport.out.report)
}
if (params.denovo){
results = m.cds
.concat(m.stats,
seq_for_transcriptome_build,
get_transcriptome.out.flatMap(map_sample_ids_cls),
merge_gff_bundles.out.gff,
m.opt_qual_ch.flatMap {it ->
l = []
for (x in it[1..-1]){
l.add(tuple(it[0], x))
}
return l
})
seq_for_transcriptome_build,
get_transcriptome.out.flatMap(map_sample_ids_cls),
merge_gff_bundles.out.gff,
m.opt_qual_ch.flatMap {it ->
l = []
for (x in it[1..-1]){
l.add(tuple(it[0], x))
}
return l
})
.map {it -> it[1]}
.concat(makeReport.out.report)
}

View File

@ -16,23 +16,23 @@ process map_reads{
tuple val(sample_id), path("${sample_id}_reads_aln_sorted.bam"), emit: bam
tuple val(sample_id), path("${sample_id}_read_aln_stats.tsv"), emit: stats
script:
def ContextFilter = """AlnContext: { Ref: "${reference}", LeftShift: -${params.poly_context}, RightShift: ${params.poly_context},
RegexEnd: "[Aa]{${params.max_poly_run},}",
Stranded: True,Invert: True, Tsv: "internal_priming_fail.tsv"} """
"""
seqkit fq2fa ${fastq_reads} -o "reads.fa";
minimap2 -t ${params.threads} -ax splice ${params.minimap2_opts} ${index} "reads.fa"\
| samtools view -q ${params.minimum_mapping_quality} -F 2304 -Sb -\
| seqkit bam -j ${params.threads} -x -T '${ContextFilter}' -\
| samtools sort -@ ${params.threads} -o "${sample_id}_reads_aln_sorted.bam" - ;
((cat "${sample_id}_reads_aln_sorted.bam" | seqkit bam -s -j ${params.threads} - 2>&1) | tee ${sample_id}_read_aln_stats.tsv ) || true
def ContextFilter = """AlnContext: { Ref: "${reference}", LeftShift: -${params.poly_context},
RightShift: ${params.poly_context}, RegexEnd: "[Aa]{${params.max_poly_run},}",
Stranded: True,Invert: True, Tsv: "internal_priming_fail.tsv"} """
"""
seqkit fq2fa ${fastq_reads} -o "reads.fa";
minimap2 -t ${params.threads} -ax splice ${params.minimap2_opts} ${index} "reads.fa"\
| samtools view -q ${params.minimum_mapping_quality} -F 2304 -Sb -\
| seqkit bam -j ${params.threads} -x -T '${ContextFilter}' -\
| samtools sort -@ ${params.threads} -o "${sample_id}_reads_aln_sorted.bam" - ;
((cat "${sample_id}_reads_aln_sorted.bam" | seqkit bam -s -j ${params.threads} - 2>&1) | tee ${sample_id}_read_aln_stats.tsv ) || true
if [[ -s "internal_priming_fail.tsv" ]];
then
tail -n +2 "internal_priming_fail.tsv" | awk '{{print ">" \$1 "\\n" \$4 }}' - > "context_internal_priming_fail_start.fasta"
tail -n +2 "internal_priming_fail.tsv" | awk '{{print ">" \$1 "\\n" \$6 }}' - > "context_internal_priming_fail_end.fasta"
fi
"""
if [[ -s "internal_priming_fail.tsv" ]];
then
tail -n +2 "internal_priming_fail.tsv" | awk '{{print ">" \$1 "\\n" \$4 }}' - > "context_internal_priming_fail_start.fasta"
tail -n +2 "internal_priming_fail.tsv" | awk '{{print ">" \$1 "\\n" \$6 }}' - > "context_internal_priming_fail_end.fasta"
fi
"""
}
workflow reference_assembly {