pipeline/codes/filter_snpindel.pl

330 lines
9.6 KiB
Perl
Raw Normal View History

2023-10-18 15:59:11 +08:00
#!/usr/bin/env perl
2023-12-25 14:06:30 +08:00
2023-10-18 15:59:11 +08:00
use strict;
#use warnings;
use List::Util qw(sum);
2023-11-01 10:09:29 +08:00
die "useage:perl $0 input out tag_out project sample_type pipeline" unless @ARGV == 6;
my ($input, $out, $tag_out, $project, $sample_type, $pipeline) = @ARGV;
2023-10-18 15:59:11 +08:00
2023-11-29 15:13:30 +08:00
my $public_path = defined $ENV{'PUBLIC'} ? $ENV{'PUBLIC'} : "/dataseq/jmdna/codes/public";
2024-01-02 02:01:20 +08:00
print "$pipeline 过滤使用public路径$public_path\n";
2023-11-29 15:13:30 +08:00
my $database_path = defined $ENV{'DATABASE'} ? $ENV{'DATABASE'} : "/dataseq/jmdna/codes/reportbase";
2024-01-02 02:01:20 +08:00
print "$pipeline 过滤使用database路径$database_path\n";
2023-11-29 15:13:30 +08:00
2023-11-01 10:09:29 +08:00
# open OUT, ">$**.hg19_multianno_filter.txt";
open OUT, "> $out";
# open OUT1, ">**.hg19_multianno_tag.txt";
open TAG_OUT, ">$tag_out";
if (-z $input) {
print "文件 $input 为空 \n";
exit(0); # 正常退出脚本
}
2023-10-18 15:59:11 +08:00
open IN, "$input";
my $head = <IN>;
2023-11-29 15:13:30 +08:00
chomp($head);
2023-11-01 10:09:29 +08:00
my @columns = split("\t", $head);
2023-11-29 15:13:30 +08:00
my $new_head = join("\t", "Validated", "ClinicalSign", @columns[0 .. 6],
"Freq", @columns[7 .. 20, 23, 28, 32, 50, 56, 62, 101, 102], "Oncogenic", "Mutation_Effect", "genetag", "process");
2023-11-01 10:09:29 +08:00
2023-11-29 15:13:30 +08:00
if (!($pipeline eq 'somatic' || $pipeline eq 'tmb' || $pipeline eq 'hotspot' || $pipeline eq 'germline')) {
die "useage: pipeline must be 'somatic' or 'germline' or 'hotspot or tmb'";
2023-10-18 15:59:11 +08:00
}
2023-11-29 15:13:30 +08:00
print OUT "$new_head\n";
print TAG_OUT "TAG\t$head\n";
2023-11-01 10:09:29 +08:00
my %blacklist = blacklist();
2023-11-29 15:13:30 +08:00
my ($muts_ref, $hcs_ref, $mmr_ref, $hhr1_ref, $hhr2_ref) = info();
my @muts = @$muts_ref;
my @hcs = @$hcs_ref;
my @mmr = @$mmr_ref;
my @hhr1 = @$hhr1_ref;
my @hhr2 = @$hhr2_ref;
2023-11-01 10:09:29 +08:00
my %transcript = transcript();
2023-11-29 15:13:30 +08:00
my %oncogenic = get_oncogenic();
2023-11-01 10:09:29 +08:00
2023-10-18 15:59:11 +08:00
while (<IN>) {
chomp;
my @line = split(/\t/, $_);
2023-11-01 10:09:29 +08:00
my $freq = ($line[102] =~ /AF=([\d.]+)/) ? $1 : die "AF value not found";
my $filters = split(";", $line[101]);
my $gene = (split(";", $line[6]))[0];
2024-01-08 10:44:50 +08:00
if ($pipeline eq 'germline') {
$freq = (split(";", $line[-1]))[6];
}
2023-11-01 10:09:29 +08:00
my @reason;
# 黑名单
if (exists $blacklist{join("_", @line[0 .. 4])}) {
push @reason, 'blacklist';
}
# 是否检测
2023-11-29 15:13:30 +08:00
if ((@muts) and !(grep {$_ eq $gene} @muts)) {
2023-11-01 10:09:29 +08:00
push @reason, 'notarget_gene';
}
# 人群频率
if (grep {$_ > 0.01} @line[17, 18, 19, 20, 23, 28, 32]) {
push @reason, 'common_snp';
}
# ExonicFunc.refGene 过滤同义突变,未知突变
if ($line[8] eq "synonymous SNV" or $line[8] eq "unknown") {
push @reason, 'synonymous';
}
# CLNSIG benign
if ($line[16] =~ /benign/i and $line[16] !~ /pathogenic|Affects|association|Conflicting|sensitivity|drug|other|risk|protective|Uncertain|not_provided|\./i) {
push @reason, 'benign';
}
# cfdna 样本
if ($sample_type eq 'c') {
2023-12-28 10:53:53 +08:00
if ($line[101] ne 'PASS' and ($freq < 0.005 or ($freq >= 0.005 and $freq < 0.01 and $filters >= 2))) {
push @reason, 'byfilter';
}
2023-11-01 10:09:29 +08:00
# 低频的 cosmic91 无记录的
if ($freq < 0.01 and $line[11] eq '.') {
push @reason, 'cfdna_lowfreq_cosmic';
}
# 低频的cosmic91 只有1条以内的
if ($line[11] =~ /OCCURENCE=(\S+)/) {
my $cosmic = $1;
$cosmic =~ s/\(\S+?\)//g;
my @cosmic = split(",", $cosmic);
$cosmic = sum @cosmic;
if ($freq < 0.01 and $cosmic <= 1) {
push @reason, 'cfdna_lowfreq_cosmic1';
2023-10-18 15:59:11 +08:00
}
2023-11-29 15:13:30 +08:00
if (($cosmic >= 10) and $pipeline eq 'tmb') {
push @reason, 'cfdna_lowfreq_cosmic1';
}
2023-11-01 10:09:29 +08:00
}
}
2023-12-28 10:53:53 +08:00
else {
# 不是pass 低频的; 或者 0.02 < 0.05 之间 个数大于2 血液 0.005 - 0.01
if ($line[101] ne 'PASS' and ($freq < 0.02 or ($freq >= 0.02 and $freq < 0.05 and $filters >= 2))) {
push @reason, 'byfilter';
}
}
2023-11-01 10:09:29 +08:00
2023-11-29 15:13:30 +08:00
my $protein;
2023-12-29 10:11:01 +08:00
# met 基因 在特定区域
if (($gene eq "MET") &&
($line[0] eq "chr7") &&
(($line[1] > 116411872 && $line[1] <= 116411902) or ($line[2] > 116411872 && $line[2] <= 116411902) or
($line[1] > 116412043 && $line[1] <= 116412046) or ($line[2] > 116412043 && $line[2] <= 116412046))) {
$line[9] = join(":", ($gene, "NM_000245", "exon14", "c.xxx"));
$line[8] = 'skipping';
$protein = 'Exon 14 Skipping Mutation';
}
elsif ($line[9] eq '.') {
# splicing 位点
if ($line[5] =~ /splicing/) {
2023-11-01 10:09:29 +08:00
my @hgvs = split(/;/, $line[7]);
my $hgvs = $hgvs[0];
2023-11-29 15:13:30 +08:00
my $transcript_gene;
$transcript_gene = $transcript{$gene} if (exists $transcript{$gene});
if (grep {/$transcript_gene/} @hgvs) {
$hgvs = (grep {/$transcript_gene/} @hgvs)[0];
2023-10-18 15:59:11 +08:00
}
2023-11-01 10:09:29 +08:00
$hgvs =~ /(\S+):exon(\d+):c\.(\S+)$/;
my $spl = $3;
2023-12-11 13:49:59 +08:00
my $exon = $2;
2023-12-29 10:11:01 +08:00
# splicing 位点 的前后 1-2bp 的
2023-12-11 13:49:59 +08:00
if ($spl =~ /\d+\+[1|2]\D+/) {
my $intron = $exon;
$hgvs =~ s/exon(\d+)/exon$exon;intron$intron/;
$line[9] = join(":", ($gene, $hgvs));
}
elsif ($spl =~ /\d+\-[1|2]\D+/) {
2023-12-25 14:06:30 +08:00
my $intron = $exon - 1;
2023-12-11 13:49:59 +08:00
$hgvs =~ s/exon(\d+)/intron$intron;exon$exon/;
2023-11-01 10:09:29 +08:00
$line[9] = join(":", ($gene, $hgvs));
2023-10-18 15:59:11 +08:00
}
else {
2023-11-01 10:09:29 +08:00
push @reason, 'not_need_spl';
2023-10-18 15:59:11 +08:00
}
2023-11-29 15:13:30 +08:00
$protein = 'Truncating Mutations';
2023-10-18 15:59:11 +08:00
}
else {
2023-11-29 15:13:30 +08:00
push @reason, 'not_need_spl_inron';
2023-10-18 15:59:11 +08:00
}
2023-11-01 10:09:29 +08:00
2023-10-18 15:59:11 +08:00
}
else {
2023-11-01 10:09:29 +08:00
my @hgvs = split(/,/, $line[9]);
my $hgvs = $hgvs[0];
my $transcript_gene;
$transcript_gene = $transcript{$gene} if (exists $transcript{$gene});
if (grep {/$transcript_gene/} @hgvs) {
$hgvs = (grep {/$transcript_gene/} @hgvs)[0];
}
$line[9] = $hgvs;
2023-11-29 15:13:30 +08:00
$hgvs =~ /:(NM_\d+):exon\d+:(c\.\S+):p\.(\S+)$/;
$protein = $3;
if ($protein =~ /\d+X$|\d+\*$/ or $line[8] eq 'stopgain' or $line[8] eq 'frameshift deletion' or $line[8] eq 'frameshift insertion') {
$protein = 'Truncating Mutations';
}
2023-11-01 10:09:29 +08:00
}
# hotspot 不过滤但是修改 hgvs
if ($pipeline eq 'hotspot') {
@reason = ();
}
2023-11-29 15:13:30 +08:00
# tmb 流程去掉 不过滤但是修改 hgvs
if ($pipeline eq 'tmb') {
2023-12-28 09:14:58 +08:00
@reason = grep(!/synonymous/, @reason);
2023-11-29 15:13:30 +08:00
if (($freq < 0.05) and ($sample_type eq 't')) {
push @reason, 'lowfreq_tissue_tmb';
}
if (($freq < 0.005) and ($sample_type eq 'c')) {
push @reason, 'lowfreq_cfdna_tmb';
}
}
2023-11-01 10:09:29 +08:00
if (@reason) {
print TAG_OUT join(";", @reason), "\t", join("\t", @line), "\n";
next;
}
2023-11-29 15:13:30 +08:00
my ($oncogenic_col, $mut_effect_col);
my $get_key = "$gene\_$protein";
2023-12-29 10:11:01 +08:00
if (exists $oncogenic{lc $get_key}) {
my @get_values = split('&&', $oncogenic{lc $get_key});
2023-11-29 15:13:30 +08:00
$oncogenic_col = $get_values[0];
$mut_effect_col = $get_values[1];
}
else {
$oncogenic_col = '.';
$mut_effect_col = '.';
}
2023-11-01 10:09:29 +08:00
2023-11-29 15:13:30 +08:00
my $clisig;
if ($line[16] =~ /Likely_pathogenic|drug/i) {
$clisig = '2';
2023-11-01 10:09:29 +08:00
}
2023-11-29 15:13:30 +08:00
elsif ($line[16] =~ /pathogenic/i and $line[16] !~ /Conflicting/i) {
$clisig = '1';
}
else {
$clisig = '3';
}
my @genetags;
if (grep {$_ eq $gene} @hcs) {
push @genetags, 'hcs';
2023-11-01 10:09:29 +08:00
}
2023-11-29 15:13:30 +08:00
if (grep {$_ eq $gene} @mmr) {
push @genetags, 'mmr';
}
if (grep {$_ eq $gene} @hhr1) {
push @genetags, 'hrr1';
}
if (grep {$_ eq $gene} @hhr2) {
push @genetags, 'hrr2';
}
my $validated = '1';
$line[6] = $gene;
my $genetag = join(";", @genetags);
my $new_line = join("\t", $validated, $clisig, @line[0 .. 6], $freq, @line[7 .. 20, 23, 28, 32, 50, 56, 62, 101, 102], $oncogenic_col, $mut_effect_col, $genetag, $pipeline);
print OUT "$new_line\n";
print TAG_OUT "PASS\t", join("\t", @line), "\n";
2023-11-01 10:09:29 +08:00
}
# black list
sub blacklist {
open BKLT, "$public_path/blacklist.txt";
my %bk;
<BKLS>;
while (<BKLT>) {
chomp;
my @line = split("\t");
my $key = join("_", @line[0 .. 4]);
$bk{$key} = 1;
}
2023-11-29 15:13:30 +08:00
return %bk;
2023-11-01 10:09:29 +08:00
}
2023-11-29 15:13:30 +08:00
sub info {
2023-11-30 15:31:35 +08:00
open INFO, "$database_path/info.csv";
2023-11-29 15:13:30 +08:00
# 读取并解析表头
my $header = <INFO>;
chomp($header);
my @column_names = split(',', $header);
2023-11-01 10:09:29 +08:00
while (<INFO>) {
chomp;
my @line = split(/,/, $_);
2023-11-29 15:13:30 +08:00
# 将数据与表头对应
my %record;
@record{@column_names} = @line;
if ($record{'project'} eq $project) {
if ($record{'mutation'} ne "NA") {
@muts = split(/\//, $record{'mutation'});
}
if ($record{'HCS'} ne "NA") {
@hcs = split(/\//, $record{'HCS'});
}
if ($record{'MMR'} ne "NA") {
@mmr = split(/\//, $record{'MMR'});
}
if ($record{'HRR_I'} ne "NA") {
@hhr1 = split(/\//, $record{'HRR_I'});
}
if ($record{'HRR_II'} ne "NA") {
@hhr2 = split(/\//, $record{'HRR_II'});
2023-11-01 10:09:29 +08:00
}
}
2023-10-18 15:59:11 +08:00
}
2023-11-29 15:13:30 +08:00
return \@muts, \@hcs, \@mmr, \@hhr1, \@hhr2
2023-10-18 15:59:11 +08:00
}
sub transcript {
2023-11-29 15:13:30 +08:00
2023-11-01 10:09:29 +08:00
open TR, "$database_path/oncokbgene.txt";
2023-10-18 15:59:11 +08:00
my %oncogene;
while (<TR>) {
chomp;
my @line = split;
$oncogene{$line[0]} = $line[2];
2023-11-01 10:09:29 +08:00
$oncogene{$line[0]} =~ s/\.\d+//;
2023-10-18 15:59:11 +08:00
}
2023-11-01 10:09:29 +08:00
return %oncogene;
2023-10-18 15:59:11 +08:00
}
2023-11-29 15:13:30 +08:00
# oncokb snv_indel 临床意义定义
sub get_oncogenic {
my %sig;
open SNV_INDEL, "$database_path/snv_indel_mutation.csv";
<SNV_INDEL>;
while (<SNV_INDEL>) {
chomp;
my @line = split(",");
my $key = join("_", @line[0, 1]);
2023-12-29 10:11:01 +08:00
$sig{lc $key} = join("&&", @line[2, 3]);
2023-11-29 15:13:30 +08:00
}
return %sig;
}