# Copyright (C) 2002  Apuã Paquola, Abimael Machado - Instituto de Química -
#                     Universidade de São Paulo - Brasil
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
package Zerg::Report;
use strict;
use Zerg;

our $VERSION = '1.0.4';
 
sub new
{

    my $self =  { };

    my $class = shift;

    my $file = shift;

    my $blast_report = ();  
   
    Zerg::zerg_open_file($file);
       
    Zerg::zerg_unignore_all();  

    $self->{report} = $blast_report;
 
    bless $self,$class;
 
    return $self;
}


sub getReport
{

    my $self=shift;

    my $blast_report = $self->{report};

    my ($c,$v,$hit_counter,$hsp_counter);

    $hit_counter=-1;

    $hsp_counter=-1;

    while((($c, $v)= Zerg::zerg_get_token()) && $c)
    {
	if($c==BLAST_VERSION)
	{
	    $blast_report->{blast_version}=$v;
	    $blast_report->{byte_offset}=Zerg::zerg_get_token_offset();
            $hit_counter=-1;
        }
        elsif($c==QUERY_NAME)
        {
            $blast_report->{query_name}=$v;
        }
        elsif($c==QUERY_ANNOTATION)
        {
	    $blast_report->{query_annotation}=$v;
        }
        elsif($c==QUERY_LENGTH)
        {
            $blast_report->{query_length}=$v;
        }
        elsif($c==SUBJECT_NAME)
        {
            $hit_counter++;

            $hsp_counter=-1;
              
            $blast_report->{hits}[$hit_counter]{"subject_name"}=$v;
        }
        elsif($c==SUBJECT_ANNOTATION)
	{
	    $blast_report->{hits}[$hit_counter]{"subject_annotation"}=$v;
	}
	elsif($c==SUBJECT_LENGTH)
	{
	    $blast_report->{hits}[$hit_counter]{"subject_length"}=$v;
	}
	elsif($c==SCORE_BITS)
	{
            $hsp_counter++; 
            $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"score_bits"}=$v;
	}
	elsif($c==SCORE)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"score"}=$v;
	}
	elsif($c==EVALUE)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"evalue"}=$v;
	}
	elsif($c==IDENTITIES)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"identities"}=$v;
	}
	elsif($c==ALIGNMENT_LENGTH)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"alignment_length"}=$v;
	}
	elsif($c==PERCENT_IDENTITIES)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"percent_identities"}=$v;
	}
	elsif($c==GAPS)
	{
	    
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"gaps"}=$v;
	}
	elsif($c==QUERY_ORIENTATION)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"query_orientation"}=$v;
	}
	elsif($c==SUBJECT_ORIENTATION)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"subject_orientation"}=$v;
	}
        elsif($c==QUERY_START)
        {
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"query_start"}=$v;
	    
        }
        elsif($c==QUERY_END)
        {
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"query_end"}=$v;
        }
        elsif($c==SUBJECT_START)
        {
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"subject_start"}=$v;
        }
        elsif($c==SUBJECT_END)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"subject_end"}=$v;
	}
	elsif($c==POSITIVES)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"positives"}=$v;
	}
	elsif($c==PERCENT_POSITIVES)
	{
            $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"percent_positives"}=$v;
	}
	elsif($c==QUERY_FRAME)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"query_frame"}=$v;
	}
	elsif($c==SUBJECT_FRAME)
	{
	    $blast_report->{hits}[$hit_counter]{"hsps"}[$hsp_counter]{"subject_frame"}=$v;
	}
	elsif($c==UNMATCHED)
	{
	    die "Syntax error in blast report\n";
	}
	elsif($c==END_OF_REPORT)
	{
	    my $r=$blast_report;
	    $blast_report=();
	    return $r;
	}
    }
    return ();
}

sub closeFile
{
  Zerg::zerg_close_file();
}


1;

# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.

# This allows declaration	use Zerg::Report ':all';
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
# will save memory.


# Preloaded methods go here.

# Autoload methods go after =cut, and are processed by the autosplit program.


__END__
# Below is stub documentation for your module. You better edit it!

=head1 NAME

Zerg::Report - get attributes from a BLAST file in a data structure

=head1 SYNOPSIS

  use Zerg::Report;
  
  my $zerg_report = new Zerg::Report("output.blastn");
  
  while($r=$zerg_report->getReport())
  { 
    foreach my $hit (@{$r->{hits}})
    {
      foreach my $hsp (@{$hit->{hsps}})
	{
	    print "$r->{query_name} $hit->{subject_name} $hsp->{score_bits}\n";        }
    }
  }

  $zerg_report->closeFile();

=head1 DESCRIPTION

  Zerg::Report uses Zerg to parse a file containing multiple BLAST
  reports and, for each report, stores the obtained fields in a data
  structure made of arrays and hashes. Please consult the Zerg man
  page to see which fields are extracted.

  The method getReport() reads a BLAST report from the input file and
  returns a reference to a data structure like the one in the example
  below. When no report is found, it returns false. It dies from
  syntax errors in BLAST reports.

  Example of a data structure returned by getReport():
  
  $r = {
          'query_name' => 'ME1-0081T-R227-B12-U.G',
          'blast_version' => 'BLASTX 1.3.6 [2002-03-05]',
          'byte_offset' => 4981,
          'query_length' => '444',
          'query_annotation' => ''
    
          'hits' => [
                      {
                        'subject_annotation' => '(NC_003210) similar to cation (calcium) transporting ATPase [Listeria monocytogenes EGD-e]',
                        'hsps' => [
                                    {
                                      'query_end' => '428',
                                      'subject_end' => '151',
                                      'identities' => '59',
                                      'score' => '252',
                                      'percent_positives' => '57',
                                      'gaps' => '0',
                                      'score_bits' => '101',
                                      'alignment_length' => '142',
                                      'evalue' => '2e-21',
                                      'percent_identities' => '41',
                                      'positives' => '83',
                                      'query_start' => '3',
                                      'subject_start' => '22',
                                      'query_frame' => '+3'
                                    }
                                  ],
                        'subject_length' => '880',
                        'subject_name' => 'gi|16802882|ref|NP_464367.1|'
                      },
                    ],
        };
   
=head1 AUTHORS

Apuã Paquola <apua@iq.usp.br>, Abimael Machado <abimael@iq.usp.br>
IQ-USP Bioinformatics Lab

=head1 SEE ALSO

Zerg

=cut
