Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: deduplicate with UMIs #1358

Open
wants to merge 176 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
176 commits
Select commit Hold shift + click to select a range
db91c59
restructure fastp trim for TGA to extract UMIs into tags instead of h…
mathiasbio Oct 20, 2023
6bbaa86
divided alignment in two
mathiasbio Oct 20, 2023
33c5e8e
add gzip to interleaved umi trimmed fastqs
mathiasbio Oct 23, 2023
7df5e79
remove detect adapters for pe in fastp
mathiasbio Oct 23, 2023
8d348cf
add rule sleep before starting analysis
mathiasbio Nov 1, 2023
d85089e
merge release13
mathiasbio Dec 12, 2023
5ac29cd
add extra rule to PON workflow
mathiasbio Dec 12, 2023
5b3c2bd
merge release 13
mathiasbio Jan 4, 2024
f184460
increase time to 200 sec
mathiasbio Jan 4, 2024
3ac67a5
add sleep requirement to concatenate umi
mathiasbio Jan 4, 2024
11064da
fix qc workflow
mathiasbio Jan 15, 2024
eb6d5c1
fix merge conflict
mathiasbio Jan 16, 2024
557b064
add new rules and functionality to create consensus reads in dedup
mathiasbio Jan 16, 2024
8e6d29b
fix bugs
mathiasbio Jan 16, 2024
62f3b11
hardcode new version of sentieon
mathiasbio Jan 16, 2024
ad2e0f8
remove failing env variable assignment
mathiasbio Jan 17, 2024
1568ff6
remove env in umi rule
mathiasbio Jan 17, 2024
aa04556
fix header
mathiasbio Jan 18, 2024
e923137
fix bug
mathiasbio Jan 18, 2024
1a38197
fix header command
mathiasbio Jan 18, 2024
985f73c
fix bugs
mathiasbio Jan 19, 2024
ac0af6f
fix bug
mathiasbio Jan 19, 2024
8c8d241
merge develop
mathiasbio Apr 15, 2024
8330ef3
fix changelog
mathiasbio Apr 15, 2024
cadf4c6
add sampletype
mathiasbio Apr 15, 2024
f82be5b
Merge branch 'deduplicate_with_umi' of github.com:Clinical-Genomics/B…
mathiasbio Apr 15, 2024
8882184
update version
mathiasbio Apr 16, 2024
695506e
Merge branch 'deduplicate_with_umi' of github.com:Clinical-Genomics/B…
mathiasbio Apr 16, 2024
cafae9d
Merge branch 'deduplicate_with_umi' of github.com:Clinical-Genomics/B…
mathiasbio Apr 16, 2024
327583a
add new output files
mathiasbio Apr 16, 2024
e524c7c
Merge branch 'deduplicate_with_umi' of github.com:Clinical-Genomics/B…
mathiasbio Apr 16, 2024
8158134
remove arguments
mathiasbio Apr 16, 2024
5a2d5b8
add merge bam step
mathiasbio Apr 16, 2024
56eb324
add base quality cap script to TGA workflow
mathiasbio May 2, 2024
53e40f0
switch container
mathiasbio May 2, 2024
29cf3b7
fix bug
mathiasbio May 2, 2024
dbb2a7b
bug fix
mathiasbio May 2, 2024
d2a28f4
bug fix
mathiasbio May 2, 2024
a44e576
test switching UMI tag to RX instead of XR
mathiasbio May 3, 2024
f949360
merge fastqs
mathiasbio May 6, 2024
5f803f6
bug fix
mathiasbio May 6, 2024
1bbfec0
add concatenation
mathiasbio May 6, 2024
abc2481
fix bug
mathiasbio May 8, 2024
d4d6f67
bug
mathiasbio May 8, 2024
6e28275
go back to parallel trimming
mathiasbio May 14, 2024
a033321
add picard fixmate
mathiasbio May 14, 2024
f66b1d4
revert back to concatenating fastqs
mathiasbio May 14, 2024
19abeeb
nothing
mathiasbio May 15, 2024
9124b00
update multiqc to 1.22.1
mathiasbio May 29, 2024
7bbfb9d
update version in docs
mathiasbio May 29, 2024
59ba636
removed sed command
mathiasbio May 29, 2024
aa2074b
changelog
mathiasbio May 29, 2024
c627d29
add separate multiqc container
mathiasbio May 30, 2024
7932570
remove multiqc from align sif
mathiasbio May 30, 2024
6f6334f
add build to actions
mathiasbio May 30, 2024
2dabf3c
add test script
mathiasbio May 30, 2024
62d76aa
update which container to use
mathiasbio May 30, 2024
b706a5b
temporary alignqc sif
mathiasbio May 30, 2024
a132407
return align sif name
mathiasbio May 30, 2024
4ee5de3
rework QC steps and add samtools fixmate and collate
mathiasbio May 30, 2024
19e0a5b
Merge branch 'update_multiqc' into deduplicate_with_umi
mathiasbio May 30, 2024
f5b97c1
bug fix
mathiasbio May 30, 2024
1d99f7b
fix
mathiasbio May 30, 2024
8665401
fix
mathiasbio May 30, 2024
0757870
fix
mathiasbio May 30, 2024
dd22a81
fix
mathiasbio May 31, 2024
98d06fc
fix
mathiasbio May 31, 2024
57a8014
fix outputdir
mathiasbio May 31, 2024
5380d70
fix
mathiasbio May 31, 2024
74006cf
fix
mathiasbio May 31, 2024
c0ed363
switch bam for vardict
mathiasbio May 31, 2024
1ae4211
fix
mathiasbio May 31, 2024
7aea221
bug fix
mathiasbio May 31, 2024
c999475
fix
mathiasbio May 31, 2024
59e9fc7
fix
mathiasbio May 31, 2024
f7947c7
attempting downgrade to 1.18 to fix somalier issue
mathiasbio May 31, 2024
858ebef
update multiqc to 1.22.2
mathiasbio Jun 3, 2024
5df39fb
fix
mathiasbio Jun 3, 2024
c1514d9
go back to version 1.18
mathiasbio Jun 3, 2024
8188756
change collect qc metrics sample id parsing
mathiasbio Jun 3, 2024
d66a463
split up sort rule
mathiasbio Jun 3, 2024
784f438
switch from sentieon to samtools
mathiasbio Jun 3, 2024
21197d6
bug fix
mathiasbio Jun 3, 2024
b02c55e
set tmpdirs
mathiasbio Jun 3, 2024
50c2171
black
mathiasbio Jun 3, 2024
0bb287d
updated changelog
mathiasbio Jun 3, 2024
c217ec3
fix pytest
mathiasbio Jun 3, 2024
435abec
Merge branch 'develop' of github.com:Clinical-Genomics/BALSAMIC into …
mathiasbio Jun 3, 2024
dd8607c
Merge branch 'develop' into update_multiqc
mathiasbio Jun 3, 2024
6984e5d
move out qc metrics to separate rule
mathiasbio Jun 3, 2024
e77a476
Merge branch 'update_multiqc' of github.com:Clinical-Genomics/BALSAMI…
mathiasbio Jun 3, 2024
6825a5f
Merge branch 'update_multiqc' into deduplicate_with_umi
mathiasbio Jun 3, 2024
6863b36
only use capped qual for manta
mathiasbio Jun 3, 2024
4fa01d9
fix
mathiasbio Jun 3, 2024
0f61eaf
fix
mathiasbio Jun 3, 2024
eace6c3
fix
mathiasbio Jun 3, 2024
9e44cef
divide up SV rules into separate workflows
mathiasbio Jun 3, 2024
4460fff
fix
mathiasbio Jun 3, 2024
04b0576
add rules
mathiasbio Jun 3, 2024
721d282
clean up
mathiasbio Jun 4, 2024
adfa85c
rename
mathiasbio Jun 4, 2024
4fab526
wgs qc fix
mathiasbio Jun 4, 2024
7e7cebc
fix bugs
mathiasbio Jun 5, 2024
e1535de
fix temp
mathiasbio Jun 5, 2024
d673740
add index
mathiasbio Jun 5, 2024
160cfa1
fix
mathiasbio Jun 5, 2024
0135356
fix
mathiasbio Jun 10, 2024
3e6df76
fix
mathiasbio Jun 10, 2024
85b849b
fix
mathiasbio Jun 10, 2024
69e14b8
clean up umi trimming
mathiasbio Jun 12, 2024
a5cf981
black and fix
mathiasbio Jun 12, 2024
827d41f
add fastp adapter trimming before UMI extraction
mathiasbio Jun 12, 2024
21cce7a
fix clean up
mathiasbio Jun 12, 2024
f2047aa
fix
mathiasbio Jun 12, 2024
e9615e1
fix pon
mathiasbio Jun 12, 2024
b338886
fix
mathiasbio Jun 12, 2024
6a83c62
fix
mathiasbio Jun 12, 2024
28cb43d
fix
mathiasbio Jun 12, 2024
0f5a9b9
fix
mathiasbio Jun 13, 2024
de76ec8
restructure UMI workflow to use TGA rules where possible
mathiasbio Jun 20, 2024
9fa992c
fix
mathiasbio Jun 20, 2024
18c5e8f
fix
mathiasbio Jun 20, 2024
f0b7947
fix
mathiasbio Jun 20, 2024
bd1fefc
fix
mathiasbio Jun 20, 2024
fb762c8
fix
mathiasbio Jun 20, 2024
0278de2
fix
mathiasbio Jun 20, 2024
ca53fce
Merge branch 'develop' of github.com:Clinical-Genomics/BALSAMIC into …
mathiasbio Jun 27, 2024
58f0ddc
merge develop
mathiasbio Jul 3, 2024
b732691
Merge branch 'develop' of github.com:Clinical-Genomics/BALSAMIC into …
mathiasbio Jul 3, 2024
13611ea
merge develop
mathiasbio Jul 3, 2024
47c6d45
fix merge conflict
mathiasbio Jul 3, 2024
36ad7a5
fix merge conflict
mathiasbio Jul 3, 2024
3125960
change sent env to model
mathiasbio Jul 3, 2024
faeff5d
same
mathiasbio Jul 3, 2024
8ddd148
black
mathiasbio Jul 4, 2024
4d57f75
clean up
mathiasbio Jul 4, 2024
9074023
fixing errors
mathiasbio Jul 4, 2024
d7e6213
fix bugs
mathiasbio Jul 5, 2024
01f5430
tests fix
mathiasbio Jul 5, 2024
51d14d4
tests
mathiasbio Jul 5, 2024
333f3a1
remove quality trim from umi workflow
mathiasbio Jul 5, 2024
00a891d
fix
mathiasbio Jul 5, 2024
9067e1e
lines
mathiasbio Jul 5, 2024
f261808
refactor
mathiasbio Jul 5, 2024
13b4c47
clean up
mathiasbio Jul 5, 2024
3cac38c
add sleep to msi rule
mathiasbio Jul 5, 2024
065dc5f
fix pon workflow
mathiasbio Jul 5, 2024
39e96c3
add sleep to PON
mathiasbio Jul 5, 2024
5743879
remove extra dedup for percent duplicates
mathiasbio Jul 8, 2024
70c9cf9
divide manta germline into 2 workflows
mathiasbio Jul 8, 2024
1bc1995
start documentation
mathiasbio Jul 9, 2024
2976373
code review
mathiasbio Jul 9, 2024
3bf73b5
update cap base quality
mathiasbio Jul 9, 2024
9ad49f2
code review
mathiasbio Jul 9, 2024
bede373
add qc models
mathiasbio Jul 9, 2024
0f2edaa
fix tests
mathiasbio Jul 9, 2024
38bf95f
fix bugs
mathiasbio Jul 9, 2024
e583ed2
black
mathiasbio Jul 9, 2024
306a93f
code review
mathiasbio Jul 10, 2024
66a43a7
add header param
mathiasbio Jul 10, 2024
aad3daa
black
mathiasbio Jul 10, 2024
737ce7b
remove duplicate rule
mathiasbio Jul 10, 2024
a79d9f9
fix coverage
mathiasbio Jul 10, 2024
d609c99
fix
mathiasbio Jul 11, 2024
133a0dd
update documentation
mathiasbio Jul 11, 2024
21e7032
adjust docs
mathiasbio Jul 11, 2024
33f3df1
remove header params
mathiasbio Jul 12, 2024
0249d05
fix pon final file
mathiasbio Jul 22, 2024
babb85d
remove duplicate rules refactoring
mathiasbio Jul 30, 2024
d7a1e42
fix issues with bam format
mathiasbio Aug 8, 2024
804795f
fix
mathiasbio Aug 9, 2024
f665d0d
fix
mathiasbio Aug 9, 2024
afb731b
add more tmp dirs
mathiasbio Aug 9, 2024
a6589d5
increase speed by sorting before calmd
mathiasbio Aug 9, 2024
154e52b
fix
mathiasbio Aug 9, 2024
a50ff90
change umi edit distance to 1
mathiasbio Aug 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions BALSAMIC/assets/scripts/cap_base_quality_in_bam.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import click
import pysam
import numpy as np


@click.command()
@click.argument("input_bam", type=click.Path(exists=True))
@click.argument("output_bam", type=click.Path())
@click.option(
"--max-quality",
default=70,
type=int,
help="Maximum quality value to cap to.",
)
def cap_base_qualities(input_bam: str, output_bam: str, max_quality: int):
"""
Cap the base qualities in a BAM file.

Args:
input_bam (str): Input BAM file path.
output_bam (str): Output BAM file path.
max_quality (int): Maximum quality value to cap to.
"""
# Open input BAM file for reading
samfile = pysam.AlignmentFile(input_bam, "rb")
out_bam = pysam.AlignmentFile(output_bam, "wb", header=samfile.header)
for read in samfile.fetch():
qualities = np.array(read.query_qualities)
capped_qualities = np.minimum(qualities, max_quality)
# Update the base qualities in the read
read.query_qualities = capped_qualities.tolist()
# Write the modified read to the output BAM file
out_bam.write(read)


if __name__ == "__main__":
cap_base_qualities()
1 change: 0 additions & 1 deletion BALSAMIC/assets/scripts/collect_qc_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ def get_sample_id(multiqc_key: str) -> str:
Returns
str: The extracted sample ID with the ACCXXXXXX format.
"""

if "_align_sort_" in multiqc_key:
return multiqc_key.split("_")[0]
return multiqc_key.split(".")[1].split("_")[0]
Expand Down
32 changes: 32 additions & 0 deletions BALSAMIC/assets/scripts/postprocess_fixmate_bam.awk
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/awk -f

BEGIN { OFS = "\t" }
/^@/ { print; next }
{
flag = $2

# If the mate is unmapped, remove the MC tag if it's "*"
if (and(flag, 8) != 0) {
for (i = 12; i <= NF; i++) {
if ($i ~ /^MC:Z:\*$/) {
$i = ""
}
}
}

# Check if any of the specific bitwise flags are set (2, 8, 32, 64, 128)
if (and(flag, 2 + 8 + 32 + 64 + 128) != 0) {
# Add mate unmapped flag if the mate is unmapped
if ($7 == "*" || and(flag, 8) != 0) {
flag = or(flag, 8)
}

# Ensure the read paired flag (1) is set if any of these are present
flag = or(flag, 1)
}

# Set the modified flag
$2 = flag

print
}
18 changes: 0 additions & 18 deletions BALSAMIC/commands/config/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

from BALSAMIC import __version__ as balsamic_version
from BALSAMIC.commands.options import (
OPTION_ADAPTER_TRIM,
OPTION_ANALYSIS_DIR,
OPTION_ANALYSIS_WORKFLOW,
OPTION_BACKGROUND_VARIANTS,
Expand All @@ -32,15 +31,12 @@
OPTION_NORMAL_SAMPLE_NAME,
OPTION_PANEL_BED,
OPTION_PON_CNN,
OPTION_QUALITY_TRIM,
OPTION_SENTIEON_INSTALL_DIR,
OPTION_SENTIEON_LICENSE,
OPTION_SWEGEN_SNV,
OPTION_SWEGEN_SV,
OPTION_TUMOR_SAMPLE_NAME,
OPTION_UMI,
OPTION_UMI_MIN_READS,
OPTION_UMI_TRIM_LENGTH,
)
from BALSAMIC.constants.analysis import BIOINFO_TOOL_ENV, AnalysisWorkflow, Gender
from BALSAMIC.constants.cache import GenomeVersion
Expand All @@ -66,7 +62,6 @@


@click.command("case", short_help="Create a sample config file from input sample data")
@OPTION_ADAPTER_TRIM
@OPTION_ANALYSIS_DIR
@OPTION_ANALYSIS_WORKFLOW
@OPTION_BACKGROUND_VARIANTS
Expand All @@ -89,19 +84,15 @@
@OPTION_NORMAL_SAMPLE_NAME
@OPTION_PANEL_BED
@OPTION_PON_CNN
@OPTION_QUALITY_TRIM
@OPTION_SENTIEON_INSTALL_DIR
@OPTION_SENTIEON_LICENSE
@OPTION_SWEGEN_SNV
@OPTION_SWEGEN_SV
@OPTION_TUMOR_SAMPLE_NAME
@OPTION_UMI
@OPTION_UMI_TRIM_LENGTH
mathiasbio marked this conversation as resolved.
Show resolved Hide resolved
@OPTION_UMI_MIN_READS
@click.pass_context
def case_config(
context: click.Context,
adapter_trim: bool,
analysis_dir: Path,
analysis_workflow: AnalysisWorkflow,
background_variants: Path,
Expand All @@ -124,14 +115,11 @@ def case_config(
normal_sample_name: str,
panel_bed: Path,
pon_cnn: Path,
quality_trim: bool,
sentieon_install_dir: Path,
sentieon_license: str,
swegen_snv: Path,
swegen_sv: Path,
tumor_sample_name: str,
umi: bool,
umi_trim_length: int,
umi_min_reads: str | None,
):
references_path: Path = Path(balsamic_cache, cache_version, genome_version)
Expand Down Expand Up @@ -205,12 +193,6 @@ def case_config(
"dnascope_model": SENTIEON_DNASCOPE_MODEL.as_posix(),
"tnscope_model": SENTIEON_TNSCOPE_MODEL.as_posix(),
},
QC={
"quality_trim": quality_trim,
"adapter_trim": adapter_trim,
"umi_trim": umi if panel_bed else False,
"umi_trim_length": umi_trim_length,
},
analysis={
"case_id": case_id,
"gender": gender,
Expand Down
18 changes: 0 additions & 18 deletions BALSAMIC/commands/config/pon.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from BALSAMIC import __version__ as balsamic_version
from BALSAMIC.commands.options import (
OPTION_ADAPTER_TRIM,
OPTION_ANALYSIS_DIR,
OPTION_BALSAMIC_CACHE,
OPTION_CACHE_VERSION,
Expand All @@ -21,9 +20,6 @@
OPTION_PANEL_BED,
OPTION_PON_VERSION,
OPTION_PON_WORKFLOW,
OPTION_QUALITY_TRIM,
OPTION_UMI,
OPTION_UMI_TRIM_LENGTH,
)
from BALSAMIC.constants.analysis import BIOINFO_TOOL_ENV, PONWorkflow
from BALSAMIC.constants.cache import GenomeVersion
Expand All @@ -47,7 +43,6 @@


@click.command("pon", short_help="Create a sample config file for PON analysis")
@OPTION_ADAPTER_TRIM
@OPTION_ANALYSIS_DIR
@OPTION_BALSAMIC_CACHE
@OPTION_CACHE_VERSION
Expand All @@ -60,13 +55,9 @@
@OPTION_PANEL_BED
@OPTION_PON_WORKFLOW
@OPTION_PON_VERSION
@OPTION_QUALITY_TRIM
@OPTION_UMI
@OPTION_UMI_TRIM_LENGTH
@click.pass_context
def pon_config(
context: click.Context,
adapter_trim: bool,
analysis_dir: Path,
balsamic_cache: Path,
cache_version: str,
Expand All @@ -78,9 +69,6 @@ def pon_config(
sentieon_license: str,
panel_bed: Path,
pon_workflow: PONWorkflow,
quality_trim: bool,
umi: bool,
umi_trim_length: bool,
version: str,
):
references_path: Path = Path(balsamic_cache, cache_version, genome_version)
Expand Down Expand Up @@ -122,12 +110,6 @@ def pon_config(
"dnascope_model": SENTIEON_DNASCOPE_MODEL.as_posix(),
"tnscope_model": SENTIEON_TNSCOPE_MODEL.as_posix(),
},
QC={
"adapter_trim": adapter_trim,
"quality_trim": quality_trim,
"umi_trim": umi if panel_bed else False,
"umi_trim_length": umi_trim_length,
},
analysis={
"case_id": case_id,
"analysis_dir": analysis_dir,
Expand Down
32 changes: 0 additions & 32 deletions BALSAMIC/commands/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,6 @@
validate_umi_min_reads,
)

OPTION_ADAPTER_TRIM = click.option(
"--adapter-trim/--no-adapter-trim",
default=True,
show_default=True,
is_flag=True,
help="Trim adapters from reads in FASTQ file",
)

OPTION_ANALYSIS_DIR = click.option(
"--analysis-dir",
type=click.Path(exists=True, resolve_path=True),
Expand Down Expand Up @@ -319,14 +311,6 @@
help="Print list of analysis files. Otherwise only final count will be printed.",
)

OPTION_QUALITY_TRIM = click.option(
"--quality-trim/--no-quality-trim",
default=True,
show_default=True,
is_flag=True,
help="Trim low quality reads in FASTQ file",
)

OPTION_QUIET = click.option(
"-q",
"--quiet",
Expand Down Expand Up @@ -427,22 +411,6 @@
help="Tumor sample name",
)

OPTION_UMI = click.option(
"--umi/--no-umi",
default=True,
show_default=True,
is_flag=True,
help="UMI processing steps for samples with UMI tags. For WGS cases, UMI is always disabled.",
)

OPTION_UMI_TRIM_LENGTH = click.option(
"--umi-trim-length",
default=5,
show_default=True,
type=click.INT,
help="Trim N bases from reads in FASTQ file",
)

OPTION_UMI_MIN_READS = click.option(
"--umi-min-reads",
type=click.STRING,
Expand Down
2 changes: 2 additions & 0 deletions BALSAMIC/constants/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class BioinfoTools(StrEnum):
VCFANNO: str = "vcfanno"
CADD: str = "cadd"
PURECN: str = "purecn"
PYSAM: str = "pysam"


class FastqName(StrEnum):
Expand Down Expand Up @@ -177,4 +178,5 @@ class PonParams:
BioinfoTools.CADD: DockerContainers.CADD,
BioinfoTools.PURECN: DockerContainers.PURECN,
BioinfoTools.GATK: DockerContainers.GATK,
BioinfoTools.PYSAM: DockerContainers.PYTHON_3,
}
16 changes: 14 additions & 2 deletions BALSAMIC/constants/cluster_analysis.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
"time": "03:00:00",
"n": 12
},
"cap_base_quality": {
"time": "05:00:00",
"n": 10
},
"finalize_gens_outputfiles": {
"time": "01:00:00",
"n": 2
Expand Down Expand Up @@ -132,10 +136,18 @@
"time": "02:30:00",
"n": 8
},
"samtools_sort_index": {
"time": "02:30:00",
"samtools_fixmate": {
"time": "04:30:00",
"n": 16
},
"sentieon_qc_metrics": {
"time": "06:00:00",
"n": 8
},
"sentieon_plot_qc_metrics": {
"time": "03:00:00",
"n": 2
},
"sentieon_DNAscope": {
"time": "24:00:00",
"n": 36
Expand Down
Loading
Loading