20251125
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
|
||||
use lib ("$FindBin::RealBin/../../PerlLib/");
|
||||
use Ascii_genome_illustrator;
|
||||
use Cwd;
|
||||
|
||||
my $usage = "usage: $0 refseqs.fa target.fa min_per_id [min_pct_aligned]\n\n";
|
||||
|
||||
my $REFSEQS_FA = $ARGV[0] or die $usage;
|
||||
my $TARGET_FA = $ARGV[1] or die $usage;
|
||||
my $MIN_PER_ID = $ARGV[2] or die $usage;
|
||||
my $MIN_PCT_ALIGNED = $ARGV[3] || 0;
|
||||
|
||||
main: {
|
||||
|
||||
|
||||
my $cmd = "blat $TARGET_FA $REFSEQS_FA -t=dna -q=dna -out=blast9 $TARGET_FA.blat.out";
|
||||
|
||||
&process_cmd($cmd);
|
||||
|
||||
# tried blastn, but it doesnt like the Trinity.fasta header format...
|
||||
#my $cmd = "makeblastdb -in trinity_out_dir/Trinity.fasta -dbtype nucl";
|
||||
#$cmd = " blastn -db trinity_out_dir/Trinity.fasta -query refseqs.fa -outfmt 6 > blast.blastn.out";
|
||||
#&process_cmd($cmd);
|
||||
|
||||
&generate_ascii_illustration("$TARGET_FA.blat.out");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
####
|
||||
sub generate_ascii_illustration {
|
||||
my ($align_out_file) = @_;
|
||||
|
||||
my %ref_seq_lengths = &get_seq_lengths($REFSEQS_FA);
|
||||
my %target_seq_lengths = &get_seq_lengths($TARGET_FA);
|
||||
|
||||
my @hits = &parse_align_out($align_out_file);
|
||||
|
||||
## Generate a reference view.
|
||||
foreach my $ref_acc (keys %ref_seq_lengths) {
|
||||
my $length = $ref_seq_lengths{$ref_acc};
|
||||
my $ascii_illustration = new Ascii_genome_illustrator($ref_acc, 60);
|
||||
|
||||
#$ascii_illustration->add_feature($ref_acc, 1, $length, "=");
|
||||
|
||||
my @matches = grep { $_->{ref_acc} eq $ref_acc } @hits;
|
||||
#@matches = reverse sort {$a->{bitscore}<=>$b->{bitscore}} @matches;
|
||||
@matches = sort {$a->{ref_start}<=>$b->{ref_start}} @matches;
|
||||
|
||||
|
||||
foreach my $match (@matches) {
|
||||
|
||||
my $target_acc = $match->{target_acc};
|
||||
my $target_start = $match->{target_start};
|
||||
my $target_end = $match->{target_end};
|
||||
my $per_id = $match->{per_id};
|
||||
|
||||
if ($per_id < $MIN_PER_ID) { next; }
|
||||
|
||||
my $ref_start = $match->{ref_start};
|
||||
my $ref_end = $match->{ref_end};
|
||||
|
||||
my $target_length = $target_seq_lengths{$target_acc};
|
||||
my $pct_of_target_aligned = sprintf("%.2f", (abs($target_end-$target_start) + 1) / $target_length * 100);
|
||||
|
||||
if ($pct_of_target_aligned < $MIN_PCT_ALIGNED) { next; }
|
||||
|
||||
my $target_feature_name = "$target_acc $target_start-$target_end:$target_length ($pct_of_target_aligned\% aln, $per_id\% ID)";
|
||||
|
||||
if ($target_start > $target_end) {
|
||||
($ref_start, $ref_end) = ($ref_end, $ref_start);
|
||||
}
|
||||
|
||||
$ascii_illustration->add_feature($target_feature_name, $ref_start, $ref_end, "-");
|
||||
|
||||
}
|
||||
|
||||
print $ascii_illustration->illustrate(1, $length);
|
||||
print "\n"; # spacer
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
####
|
||||
sub parse_align_out {
|
||||
my ($align_out_file) = @_;
|
||||
|
||||
my @alignments;
|
||||
|
||||
open (my $fh, $align_out_file) or die $!;
|
||||
while (<$fh>) {
|
||||
if (/^\#/) { next; }
|
||||
chomp;
|
||||
|
||||
=blast_outfmt6
|
||||
|
||||
# Fields: query id, subject id, % identity, alignment length, mismatches, gap opens, q. start, q. end, s. start, s. end, evalue, bit score
|
||||
|
||||
|
||||
0 NM_012009_Sh2d1b1
|
||||
1 comp0_c0_seq1
|
||||
2 100.00
|
||||
3 1433
|
||||
4 0
|
||||
5 0
|
||||
6 1
|
||||
7 1433
|
||||
8 1
|
||||
9 1433
|
||||
10 0.0
|
||||
11 2647
|
||||
|
||||
=cut
|
||||
|
||||
my @x = split(/\t/);
|
||||
my ($ref_acc, $target_acc, $per_id, $align_len, $mismatches, $gaps, $ref_start, $ref_end, $target_start, $target_end, $evalue, $bitscore) = @x;
|
||||
|
||||
my $struct = { target_acc => $target_acc,
|
||||
ref_acc => $ref_acc,
|
||||
|
||||
per_id => $per_id,
|
||||
mismatches => $mismatches,
|
||||
gaps => $gaps,
|
||||
|
||||
target_start => $target_start,
|
||||
target_end => $target_end,
|
||||
|
||||
ref_start => $ref_start,
|
||||
ref_end => $ref_end,
|
||||
|
||||
evalue => $evalue,
|
||||
bitscore => $bitscore,
|
||||
};
|
||||
|
||||
push (@alignments, $struct);
|
||||
}
|
||||
|
||||
return(@alignments);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
####
|
||||
sub get_seq_lengths {
|
||||
my ($refseqs_fa) = @_;
|
||||
|
||||
my %lengths;
|
||||
my $acc;
|
||||
|
||||
open (my $fh, $refseqs_fa) or die $!;
|
||||
while (<$fh>) {
|
||||
if (/>(\S+)/) {
|
||||
$acc = $1;
|
||||
}
|
||||
else {
|
||||
my $seq = $_;
|
||||
chomp $seq;
|
||||
my $len = length($seq);
|
||||
$lengths{$acc} += $len;
|
||||
}
|
||||
}
|
||||
close $fh;
|
||||
|
||||
return(%lengths);
|
||||
}
|
||||
|
||||
####
|
||||
sub process_cmd {
|
||||
my ($cmd) = @_;
|
||||
|
||||
print STDERR "CMD: $cmd\n";
|
||||
my $ret = system($cmd);
|
||||
|
||||
if ($ret) {
|
||||
die "Error, cmd: $cmd died with ret $ret";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user