123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- #!/usr/bin/perl -w
- package filterAlignments;
- require Exporter;
- use strict;
- use config;
- use utilities;
- our @ISA = qw(Exporter);
- our @EXPORT = qw(Filtering FilteringRanking RemoveSSFromA3m);
- ## TODO: what about scopdir??, see below
- sub RemoveSSFromA3m {
- my $a3mFile = shift;
- open (A3M, "< $a3mFile") or die "Cant open $a3mFile: $!\n";
- my @a3m = <A3M>;
- close(A3M);
- ## assume sequence ID starts with a number
- ## remove all lines before ID
- while($a3m[0] !~ /^>\d/) {
- shift(@a3m);
- }
- open (A3M, "> $a3mFile") or die "Cant open $a3mFile: $!\n";
- print (A3M @a3m);
- close(A3M);
- }
- #######################################################
- ## input: inbase, i.e. basename of hhr, a3m and hhm
- ## outbase, i.e. where to write output for query
- ## (filtered query a3m, hhm); also base
- ## for other output files (filtered a3m
- ## templates)
- ## output: list of templates with parameters
- ## obtained by the following procedure
- ##
- ## description:
- ## first create a template info array
- ## take the first HITS templates and use them as
- ## "database" for the filter steps
- ## do filter-steps: for each filtering strength:
- ## create new filtered a3m files (templates and query)
- ## => create hhm files
- ## => do hhsearch => hhr file => CreateInfoArray
- ## append the templates from CreateInfoArray to
- ## list of templates, update best templates for
- ## each position in query
- ## do filtering until either last filter step is
- ## reached or filtering gives no more templates
- ##
- #######################################################
- sub Filtering {
- my $queryName = shift;
- my $outbase = shift; ## basename of outputs wrt query during filtering (e.g. filt.a3m), remove these outputs later
- my $templateList = shift;
- my $server = shift;
- my $config = shift;
- my $qscStep = shift || 0.1;
- my $outdir; ## directory where to write output during filtering, e.g. *.filt.a3m files
- ## setup
- my $verbose = 1;
- my $v = 1;
- if ($outbase =~ /^(.*?)\/([^\/]*)$/) {
- $outdir = $1;
- } else {
- $outdir = ".";
- }
- my $cpus = $config->get_cpus();
- my $options = "-mact " . $config->get_hhsearch_mact();
- my $qscmax = 0; #-qsc (max similarity)
- ## TODO: remove limitation, all preselected hits are filtered
- my $HITS = 50; #number of hits to be filtered
- my %bestscores; #hash with raw scores for each hit (in order to update SCOREs correctly)
- my $MAXOVLAP = 20; #maximum allowable overlap to treat same templatehits independently
- my $hhmake = $config->get_hhmake();
- my $hhfilter = $config->get_hhfilter();
- my $pdbdir = $config->get_pdbdir();
-
- ## fill bestscores hash
- for (my $i=0; $i<$templateList->size(); $i++){
- my $template = $templateList->get($i);
- #new template:
- if (! $bestscores{$template->get_Hit()}){
- push (@{$bestscores{$template->get_Hit()}}, [$template->get_Qstart(),
- $template->get_Qend(),
- $template->get_Score(),
- $template->get_SumProbL()]);
- }
- #template exists already: check if independent one
- else {
- if ($bestscores{$template->get_Hit()}[0][0] < $template->get_Qstart()) {
- #existing template "in front of" new one
- if (($bestscores{$template->get_Hit()}[0][1]-$template->get_Qstart())<=$MAXOVLAP) {
- #overlap <= 20 residues
- #push to key -> additional array
- push (@{$bestscores{$template->get_Hit()}}, [$template->get_Qstart(),
- $template->get_Qend(),
- $template->get_Score(),
- $template->get_SumProbL()]);
- }
- else{
- if ($bestscores{$template->get_Hit()}[0][2]< $template->get_Score()){
- #if existing score is smaller than the score of
- #another part of the query-template alignment: update it
- $bestscores{$template->get_Hit()}[0][2] = $template->get_Score();
- }
- }
- }
- else {
- #existing template "behind"
- if (($template->get_Qend() - $bestscores{$template->get_Hit()}[0][0]) <= $MAXOVLAP) {
- #overlap <= 20 residues
- #push to key -> additional array
- push (@{$bestscores{$template->get_Hit()}}, [$template->get_Qstart(),
- $template->get_Qend(),
- $template->get_Score(),
- $template->get_SumProbL()]);
- }
- else{
- if ($bestscores{$template->get_Hit()}[0][2]< $template->get_Score()){
- #if existing score is smaller than the score of another
- #part of the query-template alignment: update it
- $bestscores{$template->get_Hit()}[0][2] = $template->get_Score();
- }
- }
- }
- }
- }
- ####################
- #search for -qsc max
- ####################
- for (my $i=0; $i<$templateList->size(); $i++) {
- my $tt = $templateList->get($i);
- if ($tt->get_Sim() > $qscmax) { $qscmax = $tt->get_Sim(); }
- }
-
- my @hits = (); #array with hits of prob>80%
- my $db = ""; #contains hhms of templates (for filtering)
- my $a3msToFilter = ""; #contains a3ms of templates (for filtering)
- # my $pid = getppid();
- ## copy a3m files into temporary directory
- my $randID = &randBetween(1000, 9999);
- my $tmpDir = "/tmp/Filtering$queryName$randID";
- while (-e $tmpDir) {
- $randID = &randBetween(1000, 9999);
- $tmpDir .= "$randID";
- }
-
- &System("mkdir $tmpDir");
- for (my $i=0; $i<$templateList->size(); $i++) {
- my $tt = $templateList->get($i);
- #if probability of hit is greater than 80%
- if ($tt->get_Prob() >= 80){
- my $hhm = "$tmpDir/" . $tt->get_Hit() . ".filt.hhm";
- #check for double entries!
- if ($db !~ /$hhm/){
- $db .= "$hhm ";
- $a3msToFilter .= "$tmpDir/" . $tt->get_Hit() . ".filt.a3m ";
- &System("cp " . $config->get_pdbdir() . "/" . $tt->get_Hit() . ".a3m $tmpDir/" . $tt->get_Hit() . ".filt.a3m");
-
- push (@hits, $tt->get_Hit());
- }
- }
- }
- #############
- #filtersteps:
- #############
- &System("cp $outbase.a3m $tmpDir/$queryName.filt.a3m");
-
- my $hhrnr = -1;
-
- for (my $qsc=0; $qsc<$qscmax+0.1; $qsc+=$qscStep)
- {
- #if there are hits with more than 80% probability:
- if (@hits>0){
- $hhrnr++;
- #filter all hits with prob>= 80% from previous search with "-qsc $qsc"
-
- my $filteredA3mFiles = "";
- if ($config->get_parallelFiltering()) {
- my $multithread = $config->get_multithread();
- my $cpus = $config->get_cpus();
- my $cmd = "$multithread '$a3msToFilter' '$hhfilter -i \$file -id 100 -diff 0 -qsc $qsc -o \$file.out &> /dev/null' -cpu $cpus";
- &System("$cmd");
- sleep(1);
- $cmd = "$multithread '$a3msToFilter' '$hhmake -i \$file.out -id 100 -diff 0 -qsc $qsc -o $tmpDir/\$base.hhm &> /dev/null' -cpu $cpus";
- &System("$cmd");
- sleep(1);
- } else {
- foreach my $fileToFilter (split(/\s+/, $a3msToFilter)) {
- &System("$hhfilter -i $fileToFilter -id 100 -diff 0 -qsc $qsc -o $fileToFilter.out -v $v &> /dev/null");
- sleep 1 while (! -e "$fileToFilter.out");
- $filteredA3mFiles .= "$fileToFilter.out ";
- }
-
- foreach my $fileToMake (split(/\s+/, $filteredA3mFiles)) {
- my $base = $fileToMake;
- $base =~ s/\.a3m\.out$//;
-
- &System("$hhmake -i $fileToMake -diff 100 -o $base.hhm -v $v &> /dev/null");
- sleep 1 while (! -e "$base.hhm");
- }
- }
-
- #filter query:
- &System("$hhfilter -i $tmpDir/$queryName.filt.a3m -id 100 -diff 0 -qsc $qsc -o $tmpDir/$queryName.filt.a3m -v 1");
-
- sleep 1 while ( !(-e "$tmpDir/$queryName.filt.a3m") );
- &System("$hhmake -i $tmpDir/$queryName.filt.a3m -diff 100 -o $tmpDir/$queryName.filt.hhm -v 1");
- sleep 1 while ( !(-e "$tmpDir/$queryName.filt.hhm") );
-
- #hhsearch:
- &System($config->get_hhsearch() . " -cpu " . $config->get_cpus() . " -i $tmpDir/$queryName.filt.hhm -d \"$db\" -o $outbase.$hhrnr.hhr $options -Z $HITS -B $HITS -atab $outbase.$hhrnr.tab");
- sleep 1 while ( !(-e "$outbase.$hhrnr.hhr") );
- my $tListFiltered = TemplateList->new();
- $tListFiltered->hhr_to_TemplateList("$outbase.$hhrnr.hhr");
- ###########################################
- #update rawscores & SumProbs/Length & @hits
- ###########################################
- @hits = ();
- $db = "";
- $a3msToFilter = "";
- for (my $i=0; $i<$tListFiltered->size(); $i++) {
- my $filtTemplate = $tListFiltered->get($i);
-
- my $difference = 1000;
- my $chooseScore;
- my $templ = -1;
- my $choostempl;
- #to distinguish between "same" or "different" covered part of query
- foreach my $e (@{$bestscores{$filtTemplate->get_Hit()}}) {
- $templ++;
-
- my $startdifference = abs(@{$e}[0] - $filtTemplate->get_Qstart());
- #difference between start of observed and start of actual queryalignmentpositon
- #score belongs to template with smallest difference between startpositions
- if ($startdifference < $difference){
- $chooseScore = @{$e}[2];
- $choostempl = $templ;
- $difference = $startdifference;
- }
- }
- if ($chooseScore< $filtTemplate->get_Score()){
- #if existing score is smaller than the filtered score: update it
- $bestscores{$filtTemplate->get_Hit()}[$choostempl][2] = $filtTemplate->get_Score(); #update scores in %bestscores
- }
- if ($filtTemplate->get_Prob() >= 80) {
- my $hhm = "$tmpDir/" . $filtTemplate->get_Hit() . ".filt.hhm";
- #check for double entries!
- if ($db !~ /$hhm/) {
- $db .= "$hhm ";
- $a3msToFilter .= "$tmpDir/" . $filtTemplate->get_Hit() . ".filt.a3m ";
- push (@hits, $filtTemplate->get_Hit());
- }
- }
- }
-
- ## add filtered hits to final templates list
- for (my $j=0; $j<$tListFiltered->size(); $j++) {
- $templateList->add_template($tListFiltered->get($j));
- }
- }
- }
-
- #update rawscores in array with all possible templates
- for (my $i=0; $i<$templateList->size(); $i++) {
- my $template = $templateList->get($i);
- my $difference = 1000;
- my $templ = -1;
- my $choostempl;
-
- foreach my $e (@{$bestscores{$template->get_Hit()}}){
- $templ++;
- #difference between start of observed and start of actual queryalignmentpositon
- my $startdifference = abs(@{$e}[0] - $template->get_Qstart());
- if ($startdifference < $difference) {
- $choostempl = $templ;
- $difference = $startdifference;
- } #score belongs to template with smallest difference between startpositions
- }
- #update scores in @prediction; omg this is ugly
- $template->set_Score( $bestscores{$template->get_Hit()}[$choostempl][2] );
- }
-
- &System("rm -R $tmpDir");
- return $templateList;
- }
- 1;
|