[Bio] / FigKernelPackages / Observation.pm Repository:
ViewVC logotype

Diff of /FigKernelPackages/Observation.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.10, Wed Jun 20 20:55:36 2007 UTC revision 1.27, Wed Jul 25 17:06:40 2007 UTC
# Line 1  Line 1 
1  package Observation;  package Observation;
2    
3    use lib '/vol/ontologies';
4    use DBMaster;
5    
6  require Exporter;  require Exporter;
7  @EXPORT_OK = qw(get_objects);  @EXPORT_OK = qw(get_objects);
8    
9    use FIG_Config;
10  use strict;  use strict;
11  use warnings;  #use warnings;
12  use HTML;  use HTML;
13    
14  1;  1;
# Line 22  Line 26 
26    
27  The data can be used to display information for a given sequence feature (protein or other, but primarily information is computed for proteins).  The data can be used to display information for a given sequence feature (protein or other, but primarily information is computed for proteins).
28    
 Example:  
   
   
 use FIG;  
 use Observation;  
   
 my $fig = new FIG;  
 my $fid = "fig|83333.1.peg.3";  
   
 my $observations = Observation::get_objects($fid);  
 foreach my $observation (@$observations) {  
     print "ID: " . $fid . "\n";  
     print "Start: " . $observation->start() . "\n";  
     ...  
 }  
   
 B<return an array of objects>  
   
   
 print "$Observation->acc\n" prints the Accession number if present for the Observation  
   
29  =cut  =cut
30    
31  =head1 BACKGROUND  =head1 BACKGROUND
# Line 66  Line 49 
49    
50  The public methods this package provides are listed below:  The public methods this package provides are listed below:
51    
 =head3 acc()  
52    
53  A valid accession or remote ID (in the style of a db_xref) or a valid local ID (FID) in case this is supported.  =head3 context()
54    
55    Returns close or diverse for purposes of displaying genomic context
56    
57  =cut  =cut
58    
59  sub acc {  sub context {
60    my ($self) = @_;    my ($self) = @_;
61    
62    return $self->{acc};    return $self->{context};
63  }  }
64    
65  =head3 description()  =head3 rows()
66    
67  The description of the hit. Taken from the data or from the our Ontology database for some cases e.g. IPR or PFAM.  each row in a displayed table
   
 B<Please note:>  
 Either remoteid or description is required.  
68    
69  =cut  =cut
70    
71  sub description {  sub rows {
72    my ($self) = @_;    my ($self) = @_;
73    
74    return $self->{description};    return $self->{rows};
75    }
76    
77    =head3 acc()
78    
79    A valid accession or remote ID (in the style of a db_xref) or a valid local ID (FID) in case this is supported.
80    
81    =cut
82    
83    sub acc {
84      my ($self) = @_;
85      return $self->{acc};
86  }  }
87    
88  =head3 class()  =head3 class()
# Line 118  Line 110 
110    
111  =item PFAM (dom)  =item PFAM (dom)
112    
113  =item SIGNALP (dom)  =item SIGNALP_CELLO_TMPRED (loc)
114    
115  =item  CELLO(loc)  =item PDB (seq)
116    
117  =item TMHMM (loc)  =item TMHMM (loc)
118    
# Line 159  Line 151 
151  sub type {  sub type {
152    my ($self) = @_;    my ($self) = @_;
153    
154    return $self->{acc};    return $self->{type};
155  }  }
156    
157  =head3 start()  =head3 start()
# Line 186  Line 178 
178    return $self->{stop};    return $self->{stop};
179  }  }
180    
181  =head3 evalue()  =head3 start()
182    
183  E-value or P-Value if present.  Start of hit in query sequence.
184    
185  =cut  =cut
186    
187  sub evalue {  sub qstart {
188    my ($self) = @_;    my ($self) = @_;
189    
190    return $self->{evalue};      return $self->{qstart};
191  }  }
192    
193  =head3 score()  =head3 qstop()
   
 Score if present.  
194    
195  B<Please note: >  End of the hit in query sequence.
 Either score or eval are required.  
196    
197  =cut  =cut
198    
199  sub score {  sub qstop {
200    my ($self) = @_;    my ($self) = @_;
201    return $self->{score};  
202        return $self->{qstop};
203  }  }
204    
205    =head3 hstart()
206    
207  =head3 display_method()  Start of hit in hit sequence.
208    
209  If available use the function specified here to display the "raw" observation.  =cut
 In the case of a BLAST alignment of fid1 and fid2 a cgi script  
 will be called to display the results of running the command "bl2seq fid1 fid2".  
210    
211  B<Please note> that URL linked to in display_method() is an external component and needs to added to the code for every class of evidence.  sub hstart {
212        my ($self) = @_;
213    
214  =cut      return $self->{hstart};
215    }
216    
217  sub display {  =head3 end()
218    
219    die "Abstract Method Called\n";  End of the hit in hit sequence.
220    
221  }  =cut
222    
223    sub hstop {
224        my ($self) = @_;
225    
226  =head3 rank()      return $self->{hstop};
227    }
228    
229  Returns an integer from 1 - 10 indicating the importance of this observations.  =head3 qlength()
230    
231  Currently always returns 1.  length of the query sequence in similarities
232    
233  =cut  =cut
234    
235  sub rank {  sub qlength {
236    my ($self) = @_;    my ($self) = @_;
237    
238  #  return $self->{rank};      return $self->{qlength};
   
   return 1;  
239  }  }
240    
241  =head3 supports_annotation()  =head3 hlength()
242    
243  Does a this observation support the annotation of its feature?  length of the hit sequence in similarities
244    
245  Returns  =cut
   
 =over 3  
246    
247  =item 10, if feature annotation is identical to $self->description  sub hlength {
248        my ($self) = @_;
249    
250  =item 1, Feature annotation is similar to $self->annotation; this is computed using FIG::SameFunc()      return $self->{hlength};
251    }
252    
253  =item undef  =head3 evalue()
254    
255  =back  E-value or P-Value if present.
256    
257  =cut  =cut
258    
259  sub supports_annotation {  sub evalue {
260    my ($self) = @_;    my ($self) = @_;
261    
262    # no code here so far    return $self->{evalue};
   
   return $self->{supports_annotation};  
263  }  }
264    
265  =head3 url()  =head3 score()
266    
267  URL describing the subject. In case of a BLAST hit against a sequence, this URL will lead to a page displaying the sequence record for the sequence. In case of an HMM hit, the URL will be to the URL description.  Score if present.
268    
269  =cut  =cut
270    
271  sub url {  sub score {
272    my ($self) = @_;    my ($self) = @_;
273      return $self->{score};
274    }
275    
276    =head3 display()
277    
278    will be different for each type
279    
280    =cut
281    
282    my $url = get_url($self->type, $self->acc);  sub display {
283    
284      die "Abstract Method Called\n";
285    
   return $url;  
286  }  }
287    
288  =head3 get_objects()  =head3 display_table()
289    
290  This is the B<REAL WORKHORSE> method of this Package.  will be different for each type
291    
292    =cut
293    
294    sub display_table {
295    
296  It will probably have to:    die "Abstract Table Method Called\n";
297    
 - get all sims for the feature  
 - get all bbhs for the feature  
 - copy information from sim to bbh (bbh have no match location etc)  
 - get pchs (difficult)  
 - get attributes (there is code for this that in get_attribute_based_observations  
 - get_attributes_based_observations returns an array of arrays of hashes like this"  
   
   my $dataset  
      [  
        [ { name => 'acc', value => '1234' },  
         { name => 'from', value => '4' },  
         { name => 'to', value => '400' },  
         ....  
        ],  
        [ { name => 'acc', value => '456' },  
         { name => 'from', value => '1' },  
         { name => 'to', value => '100' },  
         ....  
        ],  
        ...  
      ];  
    return $datasets;  
298   }   }
299    
300  It will invoke the required calls to the SEED API to retrieve the information required.  =head3 get_objects()
301    
302    This is the B<REAL WORKHORSE> method of this Package.
303    
304  =cut  =cut
305    
306  sub get_objects {  sub get_objects {
307      my ($self,$fid,$classes) = @_;      my ($self,$fid,$scope) = @_;
   
308    
309      my $objects = [];      my $objects = [];
310      my @matched_datasets=();      my @matched_datasets=();
# Line 330  Line 312 
312      # call function that fetches attribute based observations      # call function that fetches attribute based observations
313      # returns an array of arrays of hashes      # returns an array of arrays of hashes
314    
315      if(scalar(@$classes) < 1){      if($scope){
316          get_attribute_based_observations($fid,\@matched_datasets);          get_cluster_observations($fid,\@matched_datasets,$scope);
         get_sims_observations($fid,\@matched_datasets);  
         get_identical_proteins($fid,\@matched_datasets);  
         get_functional_coupling($fid,\@matched_datasets);  
317      }      }
318      else{      else{
         #IPR,CDD,CELLO,PFAM,SIGNALP - attribute based  
319          my %domain_classes;          my %domain_classes;
320          my $identical_flag=0;          $domain_classes{'CDD'} = 1;
         my $pch_flag=0;  
         my $sims_flag=0;  
         foreach my $class (@$classes){  
             if($class =~ /(IPR|CDD|PFAM)/){  
                 $domain_classes{$class} = 1;  
             }  
             elsif ($class eq "IDENTICAL")  
             {  
                 $identical_flag = 1;  
             }  
             elsif ($class eq "PCH")  
             {  
                 $pch_flag = 1;  
             }  
             elsif ($class eq "SIM")  
             {  
                 $sims_flag = 1;  
             }  
         }  
   
         if ($identical_flag ==1)  
         {  
321              get_identical_proteins($fid,\@matched_datasets);              get_identical_proteins($fid,\@matched_datasets);
         }  
         if ( (defined($domain_classes{IPR})) || (defined($domain_classes{CDD})) || (defined($domain_classes{PFAM})) ) {  
322              get_attribute_based_domain_observations($fid,\%domain_classes,\@matched_datasets);              get_attribute_based_domain_observations($fid,\%domain_classes,\@matched_datasets);
         }  
         if ($pch_flag == 1)  
         {  
             get_functional_coupling($fid,\@matched_datasets);  
         }  
         if ($sims_flag == 1)  
         {  
323              get_sims_observations($fid,\@matched_datasets);              get_sims_observations($fid,\@matched_datasets);
324          }          get_functional_coupling($fid,\@matched_datasets);
325            get_attribute_based_location_observations($fid,\@matched_datasets);
326          #add CELLO and SignalP later          get_pdb_observations($fid,\@matched_datasets);
327      }      }
328    
329      foreach my $dataset (@matched_datasets) {      foreach my $dataset (@matched_datasets) {
# Line 390  Line 337 
337          if ($dataset->{'class'} eq "IDENTICAL"){          if ($dataset->{'class'} eq "IDENTICAL"){
338              $object = Observation::Identical->new($dataset);              $object = Observation::Identical->new($dataset);
339          }          }
340            if ($dataset->{'class'} eq "SIGNALP_CELLO_TMPRED"){
341                $object = Observation::Location->new($dataset);
342            }
343          if ($dataset->{'class'} eq "SIM"){          if ($dataset->{'class'} eq "SIM"){
344              $object = Observation::Sims->new($dataset);              $object = Observation::Sims->new($dataset);
345          }          }
346            if ($dataset->{'class'} eq "CLUSTER"){
347                $object = Observation::Cluster->new($dataset);
348            }
349            if ($dataset->{'class'} eq "PDB"){
350                $object = Observation::PDB->new($dataset);
351            }
352    
353          push (@$objects, $object);          push (@$objects, $object);
354      }      }
355    
# Line 408  Line 365 
365    
366  =cut  =cut
367    
   
 =head3 get_url (internal)  
   
 get_url() return a valid URL or undef for any observation.  
   
 URLs are constructed by looking at the Accession acc()  and  name()  
   
 Info from both attributes is combined with a table of base URLs stored in this function.  
   
 =cut  
   
 sub get_url {  
   
  my ($self) = @_;  
  my $url='';  
   
 # a hash with a URL for each observation; identified by name()  
 #my $URL             => { 'PFAM' => "http://www.sanger.ac.uk/cgi-bin/Pfam/getacc?" ,\  
 #                       'IPR'    => "http://www.ebi.ac.uk/interpro/DisplayIproEntry?ac=" ,\  
 #                          'CDD' => "http://www.ncbi.nlm.nih.gov/Structure/cdd/cddsrv.cgi?uid=",\  
 #                       'PIR'    => "http://www.ncbi.nlm.nih.gov/Structure/cdd/cddsrv.cgi?uid=",\  
 #                       'FIGFAM' => '',\  
 #                          'sim'=> "http://www.theseed.org/linkin.cgi?id=",\  
 #                          'bbh'=> "http://www.theseed.org/linkin.cgi?id="  
 #};  
   
 # if (defined $URL{$self->name}) {  
 #     $url = $URL{$self->name}.$self->acc;  
 #     return $url;  
 # }  
 # else  
      return undef;  
 }  
   
 =head3 get_display_method (internal)  
   
 get_display_method() return a valid URL or undef for any observation.  
   
 URLs are constructed by looking at the Accession acc()  and  name()  
 and Info from both attributes is combined with a table of base URLs stored in this function.  
   
 =cut  
   
 sub get_display_method {  
   
  my ($self) = @_;  
   
 # a hash with a URL for each observation; identified by name()  
 #my $URL             => { 'sim'=> "http://www.theseed.org/featalign.cgi?id1=",\  
 #                        'bbh'=> "http://www.theseed.org/featalign.cgi?id1="  
 # };  
   
 #if (defined $URL{$self->name}) {  
 #     $url = $URL{$self->name}.$self->feature_id."&id2=".$self->acc;  
 #     return $url;  
 # }  
 # else  
      return undef;  
 }  
   
   
368  sub get_attribute_based_domain_observations{  sub get_attribute_based_domain_observations{
369    
370      # we read a FIG ID and a reference to an array (of arrays of hashes, see above)      # we read a FIG ID and a reference to an array (of arrays of hashes, see above)
# Line 502  Line 398 
398                                 'type' => "dom" ,                                 'type' => "dom" ,
399                                 'evalue' => $evalue,                                 'evalue' => $evalue,
400                                 'start' => $from,                                 'start' => $from,
401                                 'stop' => $to                                 'stop' => $to,
402                                   'fig_id' => $fid,
403                                   'score' => $raw_evalue
404                                 };                                 };
405    
406                  push (@{$datasets_ref} ,$dataset);                  push (@{$datasets_ref} ,$dataset);
# Line 511  Line 409 
409      }      }
410  }  }
411    
412  =head3 get_attribute_based_evidence (internal)  sub get_attribute_based_location_observations{
   
 This method retrieves evidence from the attribute server  
413    
414  =cut      my ($fid,$datasets_ref) = (@_);
415        my $fig = new FIG;
416    
417  sub get_attribute_based_observations{      my $location_attributes = ['SignalP','CELLO','TMPRED'];
418    
419      # we read a FIG ID and a reference to an array (of arrays of hashes, see above)      my $dataset = {'type' => "loc",
420      my ($fid,$datasets_ref) = (@_);                     'class' => 'SIGNALP_CELLO_TMPRED',
421                       'fig_id' => $fid
422                       };
423    
424      my $_myfig = new FIG;      foreach my $attr_ref ($fig->get_attributes($fid,$location_attributes)) {
425            my $key = @$attr_ref[1];
426            my @parts = split("::",$key);
427            my $sub_class = $parts[0];
428            my $sub_key = $parts[1];
429            my $value = @$attr_ref[2];
430            if($sub_class eq "SignalP"){
431                if($sub_key eq "cleavage_site"){
432                    my @value_parts = split(";",$value);
433                    $dataset->{'cleavage_prob'} = $value_parts[0];
434                    $dataset->{'cleavage_loc'} = $value_parts[1];
435                }
436                elsif($sub_key eq "signal_peptide"){
437                    $dataset->{'signal_peptide_score'} = $value;
438                }
439            }
440            elsif($sub_class eq "CELLO"){
441                $dataset->{'cello_location'} = $sub_key;
442                $dataset->{'cello_score'} = $value;
443            }
444            elsif($sub_class eq "TMPRED"){
445                my @value_parts = split(/\;/,$value);
446                $dataset->{'tmpred_score'} = $value_parts[0];
447                $dataset->{'tmpred_locations'} = $value_parts[1];
448            }
449        }
450    
451      foreach my $attr_ref ($_myfig->get_attributes($fid)) {      push (@{$datasets_ref} ,$dataset);
452    
453          # convert the ref into a string for easier handling  }
         my ($string) = "@$attr_ref";  
454    
455  #       print "S:$string\n";  =head3 get_pdb_observations() (internal)
         my ($key,$val) = ( $string =~ /\S+\s(\S+)\s(\S+)/);  
456    
457          # THIS SHOULD BE DONE ANOTHER WAY FM->TD  This methods sets the type and class for pdb observations
         # we need to do the right thing for each type, ie no evalue for CELLO and no coordinates, but a score, etc  
         # as fas as possible this should be configured so that the type of observation and the regexp are  
         # stored somewhere for easy expansion  
         #  
458    
459          if (($key =~ /PFAM::/) || ( $key =~ /IPR::/) || ( $key =~ /CDD::/) ) {  =cut
460    
461              # some keys are composite CDD::1233244 or PFAM:PF1233  sub get_pdb_observations{
462        my ($fid,$datasets_ref) = (@_);
463    
464              if ( $key =~ /::/ ) {      my $fig = new FIG;
                 my ($firstkey,$restkey) = ( $key =~ /([a-zA-Z0-9]+)::(.*)/);  
                 $val=$restkey.";".$val;  
                 $key=$firstkey;  
             }  
465    
466              my ($acc,$raw_evalue, $from,$to) = ($val =~ /(\S+);(\S+);(\d+)-(\d+)/ );      foreach my $attr_ref ($fig->get_attributes($fid,'PDB')) {
467    
468              my $evalue= 255;          my $key = @$attr_ref[1];
469              if (defined $raw_evalue) { # some of the tool do not give us an evalue          my($key1,$key2) =split("::",$key);
470            my $value = @$attr_ref[2];
471            my ($evalue,$location) = split(";",$value);
472    
473                  my ($k,$expo) = ( $raw_evalue =~ /(\d+).(\d+)/);          if($evalue =~/(\d+)\.(\d+)/){
474                  my ($new_k, $new_exp);              my $part2 = 1000 - $1;
475                my $part1 = $2/100;
476                $evalue = $part1."e-".$part2;
477            }
478    
479                  #          my($start,$stop) =split("-",$location);
                 #  THIS DOES NOT WORK PROPERLY  
                 #  
                 if($raw_evalue =~/(\d+).(\d+)/){  
480    
481  #                   $new_exp = (1000+$expo);          my $url = @$attr_ref[3];
482          #           $new_k = $k / 100;          my $dataset = {'class' => 'PDB',
483                           'type' => 'seq' ,
484                           'acc' => $key2,
485                           'evalue' => $evalue,
486                           'start' => $start,
487                           'stop' => $stop,
488                           'fig_id' => $fid
489                           };
490    
491            push (@{$datasets_ref} ,$dataset);
492                  }                  }
                 $evalue = "0.01"#new_k."e-".$new_exp;  
493              }              }
494    
495              # unroll it all into an array of hashes  =head3 get_cluster_observations() (internal)
496              # this needs to be done differently for different types of observations  
497              my $dataset = [ { name => 'class', value => $key },  This methods sets the type and class for cluster observations
498                              { name => 'acc' , value => $acc},  
499                              { name => 'type', value => "dom"} , # this clearly needs to be done properly FM->TD  =cut
500                              { name => 'evalue', value => $evalue },  
501                              { name => 'start', value => $from},  sub get_cluster_observations{
502                              { name => 'stop' , value => $to}      my ($fid,$datasets_ref,$scope) = (@_);
                             ];  
503    
504        my $dataset = {'class' => 'CLUSTER',
505                       'type' => 'fc',
506                       'context' => $scope,
507                       'fig_id' => $fid
508                       };
509              push (@{$datasets_ref} ,$dataset);              push (@{$datasets_ref} ,$dataset);
510          }          }
511      }  
 }  
512    
513  =head3 get_sims_observations() (internal)  =head3 get_sims_observations() (internal)
514    
# Line 593  Line 520 
520    
521      my ($fid,$datasets_ref) = (@_);      my ($fid,$datasets_ref) = (@_);
522      my $fig = new FIG;      my $fig = new FIG;
523      my @sims= $fig->nsims($fid,100,1e-20,"fig");      my @sims= $fig->nsims($fid,500,1e-20,"all");
524      my ($dataset);      my ($dataset);
525    
526        my %id_list;
527        foreach my $sim (@sims){
528            my $hit = $sim->[1];
529    
530            next if ($hit !~ /^fig\|/);
531            my @aliases = $fig->feature_aliases($hit);
532            foreach my $alias (@aliases){
533                $id_list{$alias} = 1;
534            }
535        }
536    
537        my %already;
538        my (@new_sims, @uniprot);
539      foreach my $sim (@sims){      foreach my $sim (@sims){
540          my $hit = $sim->[1];          my $hit = $sim->[1];
541            my ($id) = ($hit) =~ /\|(.*)/;
542            next if (defined($already{$id}));
543            next if (defined($id_list{$hit}));
544            push (@new_sims, $sim);
545            $already{$id} = 1;
546        }
547    
548        foreach my $sim (@new_sims){
549            my $hit = $sim->[1];
550            my $percent = $sim->[2];
551          my $evalue = $sim->[10];          my $evalue = $sim->[10];
552          my $from = $sim->[8];          my $qfrom = $sim->[6];
553          my $to = $sim->[9];          my $qto = $sim->[7];
554            my $hfrom = $sim->[8];
555            my $hto = $sim->[9];
556            my $qlength = $sim->[12];
557            my $hlength = $sim->[13];
558            my $db = get_database($hit);
559            my $func = $fig->function_of($hit);
560            my $organism = $fig->org_of($hit);
561    
562          $dataset = {'class' => 'SIM',          $dataset = {'class' => 'SIM',
563                      'acc' => $hit,                      'acc' => $hit,
564                        'identity' => $percent,
565                      'type' => 'seq',                      'type' => 'seq',
566                      'evalue' => $evalue,                      'evalue' => $evalue,
567                      'start' => $from,                      'qstart' => $qfrom,
568                      'stop' => $to                      'qstop' => $qto,
569                        'hstart' => $hfrom,
570                        'hstop' => $hto,
571                        'database' => $db,
572                        'organism' => $organism,
573                        'function' => $func,
574                        'qlength' => $qlength,
575                        'hlength' => $hlength,
576                        'fig_id' => $fid
577                      };                      };
578    
579          push (@{$datasets_ref} ,$dataset);          push (@{$datasets_ref} ,$dataset);
580      }      }
581  }  }
582    
583    =head3 get_database (internal)
584    This method gets the database association from the sequence id
585    
586    =cut
587    
588    sub get_database{
589        my ($id) = (@_);
590    
591        my ($db);
592        if ($id =~ /^fig\|/)              { $db = "FIG" }
593        elsif ($id =~ /^gi\|/)            { $db = "NCBI" }
594        elsif ($id =~ /^^[NXYZA]P_/)      { $db = "RefSeq" }
595        elsif ($id =~ /^sp\|/)            { $db = "SwissProt" }
596        elsif ($id =~ /^uni\|/)           { $db = "UniProt" }
597        elsif ($id =~ /^tigr\|/)          { $db = "TIGR" }
598        elsif ($id =~ /^pir\|/)           { $db = "PIR" }
599        elsif ($id =~ /^kegg\|/)          { $db = "KEGG" }
600        elsif ($id =~ /^tr\|/)            { $db = "TrEMBL" }
601        elsif ($id =~ /^eric\|/)          { $db = "ASAP" }
602        elsif ($id =~ /^img\|/)           { $db = "JGI" }
603    
604        return ($db);
605    
606    }
607    
608    
609  =head3 get_identical_proteins() (internal)  =head3 get_identical_proteins() (internal)
610    
611  This methods retrieves sims fills the internal data structures.  This methods retrieves sims fills the internal data structures.
# Line 622  Line 616 
616    
617      my ($fid,$datasets_ref) = (@_);      my ($fid,$datasets_ref) = (@_);
618      my $fig = new FIG;      my $fig = new FIG;
619      my @funcs = ();      my $funcs_ref;
620    
621        my %id_list;
622      my @maps_to = grep { $_ ne $fid and $_ !~ /^xxx/ } map { $_->[0] } $fig->mapped_prot_ids($fid);      my @maps_to = grep { $_ ne $fid and $_ !~ /^xxx/ } map { $_->[0] } $fig->mapped_prot_ids($fid);
623        my @aliases = $fig->feature_aliases($fid);
624        foreach my $alias (@aliases){
625            $id_list{$alias} = 1;
626        }
627    
628      foreach my $id (@maps_to) {      foreach my $id (@maps_to) {
629          my ($tmp, $who);          my ($tmp, $who);
630          if (($id ne $fid) && ($tmp = $fig->function_of($id))) {          if (($id ne $fid) && ($tmp = $fig->function_of($id)) && (! defined ($id_list{$id}))) {
631              if ($id =~ /^fig\|/)           { $who = "FIG" }              $who = &get_database($id);
632              elsif ($id =~ /^gi\|/)            { $who = "NCBI" }              push(@$funcs_ref, [$id,$who,$tmp]);
             elsif ($id =~ /^^[NXYZA]P_/)      { $who = "RefSeq" }  
             elsif ($id =~ /^sp\|/)            { $who = "SwissProt" }  
             elsif ($id =~ /^uni\|/)           { $who = "UniProt" }  
             elsif ($id =~ /^tigr\|/)          { $who = "TIGR" }  
             elsif ($id =~ /^pir\|/)           { $who = "PIR" }  
             elsif ($id =~ /^kegg\|/)          { $who = "KEGG" }  
             elsif ($id =~ /^tr\|/)            { $who = "TrEMBL" }  
             elsif ($id =~ /^eric\|/)          { $who = "ASAP" }  
   
             push(@funcs, [$id,$who,$tmp]);  
633          }          }
634      }      }
635    
636      my ($dataset);      my ($dataset);
     foreach my $row (@funcs){  
         my $id = $row->[0];  
         my $organism = $fig->org_of($fid);  
         my $who = $row->[1];  
         my $assignment = $row->[2];  
   
637          my $dataset = {'class' => 'IDENTICAL',          my $dataset = {'class' => 'IDENTICAL',
                        'id' => $id,  
                        'organism' => $organism,  
638                         'type' => 'seq',                         'type' => 'seq',
639                         'database' => $who,                     'fig_id' => $fid,
640                         'function' => $assignment                     'rows' => $funcs_ref
641                         };                         };
642    
643          push (@{$datasets_ref} ,$dataset);          push (@{$datasets_ref} ,$dataset);
644      }  
645    
646  }  }
647    
# Line 691  Line 672 
672                    } @fc_data;                    } @fc_data;
673    
674      my ($dataset);      my ($dataset);
     foreach my $row (@rows){  
         my $id = $row->[1];  
         my $score = $row->[0];  
         my $description = $row->[2];  
675          my $dataset = {'class' => 'PCH',          my $dataset = {'class' => 'PCH',
                        'score' => $score,  
                        'id' => $id,  
676                         'type' => 'fc',                         'type' => 'fc',
677                         'function' => $description                     'fig_id' => $fid,
678                       'rows' => \@rows
679                         };                         };
680    
681          push (@{$datasets_ref} ,$dataset);          push (@{$datasets_ref} ,$dataset);
682      }  
683  }  }
684    
685  =head3 get_sims_and_bbhs() (internal)  =head3 new (internal)
686    
687  This methods retrieves sims and also BBHs and fills the internal data structures.  Instantiate a new object.
688    
689  =cut  =cut
690    
691  #     sub get_sims_and_bbhs{  sub new {
692      my ($class,$dataset) = @_;
 #       # blast m8 output format  
 #       # id1, id2, %ident, align len, mismatches, gaps, q.start, q.stop, s. start, s.stop, eval, bit  
   
 #       my $Sims=();  
 #       @sims_src = $fig->sims($fid,80,500,"fig",0);  
 #       print "found $#sims_src SIMs\n";  
 #       foreach $sims (@sims_src) {  
 #           my ($sims_string) = "@$sims";  
 # #       print "$sims_string\n";  
 #           my ($rfid,$start,$stop,$eval) = ( $sims_string =~ /\S+\s+(\S+)\s+\S+\s\S+\s+(\S+)\s+(\S+)\s+  
 #                                             \S+\s+\S+\s+\S+\s+\S+\s+(\S+)+.*/);  
 # #       print "ID: $rfid, E:$eval, Start:$start stop:$stop\n";  
 #           $Sims{$rfid}{'eval'}=$eval;  
 #           $Sims{$rfid}{'start'}=$start;  
 #           $Sims{$rfid}{'stop'}=$stop;  
 #           print "$rfid $Sims{$rfid}{'eval'}\n";  
 #       }  
   
 #       # BBHs  
 #       my $BBHs=();  
   
 #       @bbhs_src = $fig->bbhs($fid,1.0e-10);  
 #       print "found $#bbhs_src BBHs\n";  
 #       foreach $bbh (@bbhs_src) {  
 #           #print "@$bbh\n";  
 #           my ($bbh_string) = "@$bbh";  
 #           my ($rfid,$eval,$score) = ( $bbh_string =~ /(\S+)\s(\S+)\s(\S+)/);  
 #           #print "ID: $rfid, E:$eval, S:$score\n";  
 #           $BBHs{$rfid}{'eval'}=$eval;  
 #           $BBHs{$rfid}{'score'}=$score;  
 # #print "$rfid $BBHs{$rfid}{'eval'}\n";  
 #       }  
693    
694  #     }    my $self = { class => $dataset->{'class'},
695                   type => $dataset->{'type'},
696                   fig_id => $dataset->{'fig_id'},
697                   score => $dataset->{'score'},
698               };
699    
700      bless($self,$class);
701    
702      return $self;
703    }
704    
705  =head3 new (internal)  =head3 identity (internal)
706    
707  Instantiate a new object.  Returns the % identity of the similar sequence
708    
709  =cut  =cut
710    
711  sub new {  sub identity {
712    my ($class,$dataset) = @_;      my ($self) = @_;
   
713    
714    #$self = { acc => '',      return $self->{identity};
715  #           description => '',  }
 #           class => '',  
 #           type => '',  
 #           start => '',  
 #           stop => '',  
 #           evalue => '',  
 #           score => '',  
 #           display_method => '',  
 #           feature_id => '',  
 #           rank => '',  
 #           supports_annotation => '',  
 #           id => '',  
 #            organism => '',  
 #            who => ''  
 #         };  
716    
717    my $self = { class => $dataset->{'class'},  =head3 fig_id (internal)
                type => $dataset->{'type'}  
            };  
718    
719    bless($self,$class);  =cut
720    
721    return $self;  sub fig_id {
722      my ($self) = @_;
723      return $self->{fig_id};
724  }  }
725    
726  =head3 feature_id (internal)  =head3 feature_id (internal)
# Line 846  Line 782 
782      return $self->{database};      return $self->{database};
783  }  }
784    
785    sub score {
786      my ($self) = @_;
787    
788      return $self->{score};
789    }
790    
791  ############################################################  ############################################################
792  ############################################################  ############################################################
793  package Observation::Identical;  package Observation::PDB;
794    
795  use base qw(Observation);  use base qw(Observation);
796    
# Line 857  Line 798 
798    
799      my ($class,$dataset) = @_;      my ($class,$dataset) = @_;
800      my $self = $class->SUPER::new($dataset);      my $self = $class->SUPER::new($dataset);
801      $self->{id} = $dataset->{'id'};      $self->{acc} = $dataset->{'acc'};
802      $self->{organism} = $dataset->{'organism'};      $self->{evalue} = $dataset->{'evalue'};
803      $self->{function} = $dataset->{'function'};      $self->{start} = $dataset->{'start'};
804      $self->{database} = $dataset->{'database'};      $self->{stop} = $dataset->{'stop'};
805        bless($self,$class);
806      bless($self,$class);      return $self;
     return $self;  
807  }  }
808    
809  =head3 display()  =head3 display()
810    
811    displays data stored in best_PDB attribute and in Ontology server for given PDB id
812    
813    =cut
814    
815    sub display{
816        my ($self,$gd) = @_;
817    
818        my $fid = $self->fig_id;
819        my $dbmaster = DBMaster->new(-database =>'Ontology');
820    
821        my $acc = $self->acc;
822    
823        my ($pdb_description,$pdb_source,$pdb_ligand);
824        my $pdb_objs = $dbmaster->pdb->get_objects( { 'id' => $acc } );
825        if(!scalar(@$pdb_objs)){
826            $pdb_description = "not available";
827            $pdb_source = "not available";
828            $pdb_ligand = "not available";
829        }
830        else{
831            my $pdb_obj = $pdb_objs->[0];
832            $pdb_description = $pdb_obj->description;
833            $pdb_source = $pdb_obj->source;
834            $pdb_ligand = $pdb_obj->ligand;
835        }
836    
837        my $lines = [];
838        my $line_data = [];
839        my $line_config = { 'title' => "PDB hit for $fid",
840                            'short_title' => "best PDB",
841                            'basepair_offset' => '1' };
842    
843        my $fig = new FIG;
844        my $seq = $fig->get_translation($fid);
845        my $fid_stop = length($seq);
846    
847        my $fid_element_hash = {
848            "title" => $fid,
849            "start" => '1',
850            "end" =>  $fid_stop,
851            "color"=> '1',
852            "zlayer" => '1'
853            };
854    
855        push(@$line_data,$fid_element_hash);
856    
857        my $links_list = [];
858        my $descriptions = [];
859    
860        my $name;
861        $name = {"title" => 'id',
862                 "value" => $acc};
863        push(@$descriptions,$name);
864    
865        my $description;
866        $description = {"title" => 'pdb description',
867                        "value" => $pdb_description};
868        push(@$descriptions,$description);
869    
870        my $score;
871        $score = {"title" => "score",
872                  "value" => $self->evalue};
873        push(@$descriptions,$score);
874    
875        my $start_stop;
876        my $start_stop_value = $self->start."_".$self->stop;
877        $start_stop = {"title" => "start-stop",
878                       "value" => $start_stop_value};
879        push(@$descriptions,$start_stop);
880    
881        my $source;
882        $source = {"title" => "source",
883                  "value" => $pdb_source};
884        push(@$descriptions,$source);
885    
886        my $ligand;
887        $ligand = {"title" => "pdb ligand",
888                   "value" => $pdb_ligand};
889        push(@$descriptions,$ligand);
890    
891        my $link;
892        my $link_url ="http://www.rcsb.org/pdb/explore/explore.do?structureId=".$acc;
893    
894        $link = {"link_title" => $acc,
895                 "link" => $link_url};
896        push(@$links_list,$link);
897    
898        my $pdb_element_hash = {
899            "title" => "PDB homology",
900            "start" => $self->start,
901            "end" =>  $self->stop,
902            "color"=> '6',
903            "zlayer" => '3',
904            "links_list" => $links_list,
905            "description" => $descriptions};
906    
907        push(@$line_data,$pdb_element_hash);
908        $gd->add_line($line_data, $line_config);
909    
910        return $gd;
911    }
912    
913    1;
914    
915    ############################################################
916    ############################################################
917    package Observation::Identical;
918    
919    use base qw(Observation);
920    
921    sub new {
922    
923        my ($class,$dataset) = @_;
924        my $self = $class->SUPER::new($dataset);
925        $self->{rows} = $dataset->{'rows'};
926    
927        bless($self,$class);
928        return $self;
929    }
930    
931    =head3 display_table()
932    
933  If available use the function specified here to display the "raw" observation.  If available use the function specified here to display the "raw" observation.
934  This code will display a table for the identical protein  This code will display a table for the identical protein
935    
# Line 877  Line 939 
939    
940  =cut  =cut
941    
 sub display{  
     my ($self, $cgi, $dataset) = @_;  
942    
943    sub display_table{
944        my ($self) = @_;
945    
946        my $fig = new FIG;
947        my $fid = $self->fig_id;
948        my $rows = $self->rows;
949        my $cgi = new CGI;
950      my $all_domains = [];      my $all_domains = [];
951      my $count_identical = 0;      my $count_identical = 0;
952      my $content;      my $content;
953      foreach my $thing (@$dataset) {      foreach my $row (@$rows) {
954          next if ($thing->class ne "IDENTICAL");          my $id = $row->[0];
955            my $who = $row->[1];
956            my $assignment = $row->[2];
957            my $organism = $fig->org_of($id);
958          my $single_domain = [];          my $single_domain = [];
959          push(@$single_domain,$thing->database);          push(@$single_domain,$who);
         my $id = $thing->id;  
         $count_identical++;  
960          push(@$single_domain,&HTML::set_prot_links($cgi,$id));          push(@$single_domain,&HTML::set_prot_links($cgi,$id));
961          push(@$single_domain,$thing->organism);          push(@$single_domain,$organism);
962          #push(@$single_domain,$thing->type);          push(@$single_domain,$assignment);
         push(@$single_domain,$thing->function);  
963          push(@$all_domains,$single_domain);          push(@$all_domains,$single_domain);
964            $count_identical++;
965      }      }
966    
967      if ($count_identical >0){      if ($count_identical >0){
# Line 907  Line 975 
975    
976  1;  1;
977    
   
978  #########################################  #########################################
979  #########################################  #########################################
980  package Observation::FC;  package Observation::FC;
# Line 919  Line 986 
986    
987      my ($class,$dataset) = @_;      my ($class,$dataset) = @_;
988      my $self = $class->SUPER::new($dataset);      my $self = $class->SUPER::new($dataset);
989      $self->{score} = $dataset->{'score'};      $self->{rows} = $dataset->{'rows'};
     $self->{id} = $dataset->{'id'};  
     $self->{function} = $dataset->{'function'};  
990    
991      bless($self,$class);      bless($self,$class);
992      return $self;      return $self;
993  }  }
994    
995  =head3 display()  =head3 display_table()
996    
997  If available use the function specified here to display the "raw" observation.  If available use the function specified here to display the "raw" observation.
998  This code will display a table for the identical protein  This code will display a table for the identical protein
# Line 938  Line 1003 
1003    
1004  =cut  =cut
1005    
1006  sub display {  sub display_table {
     my ($self,$cgi,$dataset, $fid) = @_;  
1007    
1008        my ($self,$dataset) = @_;
1009        my $fid = $self->fig_id;
1010        my $rows = $self->rows;
1011        my $cgi = new CGI;
1012      my $functional_data = [];      my $functional_data = [];
1013      my $count = 0;      my $count = 0;
1014      my $content;      my $content;
1015    
1016      foreach my $thing (@$dataset) {      foreach my $row (@$rows) {
1017          my $single_domain = [];          my $single_domain = [];
         next if ($thing->class ne "PCH");  
1018          $count++;          $count++;
1019    
1020          # construct the score link          # construct the score link
1021          my $score = $thing->score;          my $score = $row->[0];
1022          my $toid = $thing->id;          my $toid = $row->[1];
1023          my $link = $cgi->url(-relative => 1) . "?user=master&request=show_coupling_evidence&prot=$fid&to=$toid&SPROUT=";          my $link = $cgi->url(-relative => 1) . "?user=master&request=show_coupling_evidence&prot=$fid&to=$toid&SPROUT=";
1024          my $sc_link = "<a href=$link>$score</a>";          my $sc_link = "<a href=$link>$score</a>";
1025    
1026          push(@$single_domain,$sc_link);          push(@$single_domain,$sc_link);
1027          push(@$single_domain,$thing->id);          push(@$single_domain,$row->[1]);
1028          push(@$single_domain,$thing->function);          push(@$single_domain,$row->[2]);
1029          push(@$functional_data,$single_domain);          push(@$functional_data,$single_domain);
1030      }      }
1031    
# Line 995  Line 1062 
1062  sub display {  sub display {
1063      my ($thing,$gd) = @_;      my ($thing,$gd) = @_;
1064      my $lines = [];      my $lines = [];
1065      my $line_config = { 'title' => $thing->acc,  #    my $line_config = { 'title' => $thing->acc,
1066                          'short_title' => $thing->type,  #                       'short_title' => $thing->type,
1067                          'basepair_offset' => '1' };  #                       'basepair_offset' => '1' };
1068      my $color = "4";      my $color = "4";
1069    
1070      my $line_data = [];      my $line_data = [];
1071      my $links_list = [];      my $links_list = [];
1072      my $descriptions = [];      my $descriptions = [];
1073    
1074      my $description_function;      my $db_and_id = $thing->acc;
1075      $description_function = {"title" => $thing->class,      my ($db,$id) = split("::",$db_and_id);
                              "value" => $thing->acc};  
1076    
1077      push(@$descriptions,$description_function);      my $dbmaster = DBMaster->new(-database =>'Ontology');
1078    
1079        my ($name_title,$name_value,$description_title,$description_value);
1080        if($db eq "CDD"){
1081            my $cdd_objs = $dbmaster->cdd->get_objects( { 'id' => $id } );
1082            if(!scalar(@$cdd_objs)){
1083                $name_title = "name";
1084                $name_value = "not available";
1085                $description_title = "description";
1086                $description_value = "not available";
1087            }
1088            else{
1089                my $cdd_obj = $cdd_objs->[0];
1090                $name_title = "name";
1091                $name_value = $cdd_obj->term;
1092                $description_title = "description";
1093                $description_value = $cdd_obj->description;
1094            }
1095        }
1096    
1097        my $line_config = { 'title' => $thing->acc,
1098                            'short_title' => $name_value,
1099                            'basepair_offset' => '1' };
1100    
1101        my $name;
1102        $name = {"title" => $name_title,
1103                 "value" => $name_value};
1104        push(@$descriptions,$name);
1105    
1106        my $description;
1107        $description = {"title" => $description_title,
1108                                 "value" => $description_value};
1109        push(@$descriptions,$description);
1110    
1111      my $score;      my $score;
1112      $score = {"title" => "score",      $score = {"title" => "score",
# Line 1016  Line 1114 
1114      push(@$descriptions,$score);      push(@$descriptions,$score);
1115    
1116      my $link_id;      my $link_id;
1117      if ($thing->acc =~/CDD::(\d+)/){      if ($thing->acc =~/\w+::(\d+)/){
1118          $link_id = $1;          $link_id = $1;
1119      }      }
1120    
1121      my $link;      my $link;
1122        my $link_url;
1123        if ($thing->class eq "CDD"){$link_url = "http://0-www.ncbi.nlm.nih.gov.library.vu.edu.au:80/Structure/cdd/cddsrv.cgi?uid=$link_id"}
1124        elsif($thing->class eq "PFAM"){$link_url = "http://www.sanger.ac.uk/cgi-bin/Pfam/getacc?$link_id"}
1125        else{$link_url = "NO_URL"}
1126    
1127      $link = {"link_title" => $thing->acc,      $link = {"link_title" => $thing->acc,
1128               "link" => "http://0-www.ncbi.nlm.nih.gov.library.vu.edu.au:80/Structure/cdd/cddsrv.cgi?uid=$link_id"};               "link" => $link_url};
1129      push(@$links_list,$link);      push(@$links_list,$link);
1130    
1131      my $element_hash = {      my $element_hash = {
# Line 1043  Line 1146 
1146    
1147  #########################################  #########################################
1148  #########################################  #########################################
1149    package Observation::Location;
1150    
1151    use base qw(Observation);
1152    
1153    sub new {
1154    
1155        my ($class,$dataset) = @_;
1156        my $self = $class->SUPER::new($dataset);
1157        $self->{cleavage_prob} = $dataset->{'cleavage_prob'};
1158        $self->{cleavage_loc} = $dataset->{'cleavage_loc'};
1159        $self->{signal_peptide_score} = $dataset->{'signal_peptide_score'};
1160        $self->{cello_location} = $dataset->{'cello_location'};
1161        $self->{cello_score} = $dataset->{'cello_score'};
1162        $self->{tmpred_score} = $dataset->{'tmpred_score'};
1163        $self->{tmpred_locations} = $dataset->{'tmpred_locations'};
1164    
1165        bless($self,$class);
1166        return $self;
1167    }
1168    
1169    sub display {
1170        my ($thing,$gd) = @_;
1171    
1172        my $fid = $thing->fig_id;
1173        my $fig= new FIG;
1174        my $length = length($fig->get_translation($fid));
1175    
1176        my $cleavage_prob;
1177        if($thing->cleavage_prob){$cleavage_prob = $thing->cleavage_prob;}
1178        my ($cleavage_loc_begin,$cleavage_loc_end) = split("-",$thing->cleavage_loc);
1179        my $signal_peptide_score = $thing->signal_peptide_score;
1180        my $cello_location = $thing->cello_location;
1181        my $cello_score = $thing->cello_score;
1182        my $tmpred_score = $thing->tmpred_score;
1183        my @tmpred_locations = split(",",$thing->tmpred_locations);
1184    
1185        my $lines = [];
1186        my $line_config = { 'title' => 'Localization Evidence',
1187                            'short_title' => 'Local',
1188                            'basepair_offset' => '1' };
1189    
1190        #color is
1191        my $color = "5";
1192    
1193        my $line_data = [];
1194    
1195        if($cello_location){
1196            my $cello_descriptions = [];
1197            my $description_cello_location = {"title" => 'Best Cello Location',
1198                                              "value" => $cello_location};
1199    
1200            push(@$cello_descriptions,$description_cello_location);
1201    
1202            my $description_cello_score = {"title" => 'Cello Score',
1203                                           "value" => $cello_score};
1204    
1205            push(@$cello_descriptions,$description_cello_score);
1206    
1207            my $element_hash = {
1208                "title" => "CELLO",
1209                "start" => "1",
1210                "end" =>  $length + 1,
1211                "color"=> $color,
1212                "type" => 'box',
1213                "zlayer" => '2',
1214                "description" => $cello_descriptions};
1215    
1216            push(@$line_data,$element_hash);
1217        }
1218    
1219        my $color = "6";
1220        if($tmpred_score){
1221            foreach my $tmpred (@tmpred_locations){
1222                my $descriptions = [];
1223                my ($begin,$end) =split("-",$tmpred);
1224                my $description_tmpred_score = {"title" => 'TMPRED score',
1225                                 "value" => $tmpred_score};
1226    
1227                push(@$descriptions,$description_tmpred_score);
1228    
1229                my $element_hash = {
1230                "title" => "transmembrane location",
1231                "start" => $begin + 1,
1232                "end" =>  $end + 1,
1233                "color"=> $color,
1234                "zlayer" => '5',
1235                "type" => 'smallbox',
1236                "description" => $descriptions};
1237    
1238                push(@$line_data,$element_hash);
1239            }
1240        }
1241    
1242        my $color = "1";
1243        if($signal_peptide_score){
1244            my $descriptions = [];
1245            my $description_signal_peptide_score = {"title" => 'signal peptide score',
1246                                                    "value" => $signal_peptide_score};
1247    
1248            push(@$descriptions,$description_signal_peptide_score);
1249    
1250            my $description_cleavage_prob = {"title" => 'cleavage site probability',
1251                                             "value" => $cleavage_prob};
1252    
1253            push(@$descriptions,$description_cleavage_prob);
1254    
1255            my $element_hash = {
1256                "title" => "SignalP",
1257                "start" => $cleavage_loc_begin - 2,
1258                "end" =>  $cleavage_loc_end + 3,
1259                "type" => 'bigbox',
1260                "color"=> $color,
1261                "zlayer" => '10',
1262                "description" => $descriptions};
1263    
1264            push(@$line_data,$element_hash);
1265        }
1266    
1267        $gd->add_line($line_data, $line_config);
1268    
1269        return ($gd);
1270    
1271    }
1272    
1273    sub cleavage_loc {
1274      my ($self) = @_;
1275    
1276      return $self->{cleavage_loc};
1277    }
1278    
1279    sub cleavage_prob {
1280      my ($self) = @_;
1281    
1282      return $self->{cleavage_prob};
1283    }
1284    
1285    sub signal_peptide_score {
1286      my ($self) = @_;
1287    
1288      return $self->{signal_peptide_score};
1289    }
1290    
1291    sub tmpred_score {
1292      my ($self) = @_;
1293    
1294      return $self->{tmpred_score};
1295    }
1296    
1297    sub tmpred_locations {
1298      my ($self) = @_;
1299    
1300      return $self->{tmpred_locations};
1301    }
1302    
1303    sub cello_location {
1304      my ($self) = @_;
1305    
1306      return $self->{cello_location};
1307    }
1308    
1309    sub cello_score {
1310      my ($self) = @_;
1311    
1312      return $self->{cello_score};
1313    }
1314    
1315    
1316    #########################################
1317    #########################################
1318  package Observation::Sims;  package Observation::Sims;
1319    
1320  use base qw(Observation);  use base qw(Observation);
# Line 1051  Line 1323 
1323    
1324      my ($class,$dataset) = @_;      my ($class,$dataset) = @_;
1325      my $self = $class->SUPER::new($dataset);      my $self = $class->SUPER::new($dataset);
1326        $self->{identity} = $dataset->{'identity'};
1327      $self->{acc} = $dataset->{'acc'};      $self->{acc} = $dataset->{'acc'};
1328      $self->{evalue} = $dataset->{'evalue'};      $self->{evalue} = $dataset->{'evalue'};
1329      $self->{start} = $dataset->{'start'};      $self->{qstart} = $dataset->{'qstart'};
1330      $self->{stop} = $dataset->{'stop'};      $self->{qstop} = $dataset->{'qstop'};
1331        $self->{hstart} = $dataset->{'hstart'};
1332        $self->{hstop} = $dataset->{'hstop'};
1333        $self->{database} = $dataset->{'database'};
1334        $self->{organism} = $dataset->{'organism'};
1335        $self->{function} = $dataset->{'function'};
1336        $self->{qlength} = $dataset->{'qlength'};
1337        $self->{hlength} = $dataset->{'hlength'};
1338    
1339      bless($self,$class);      bless($self,$class);
1340      return $self;      return $self;
# Line 1062  Line 1342 
1342    
1343  =head3 display()  =head3 display()
1344    
1345    If available use the function specified here to display a graphical observation.
1346    This code will display a graphical view of the similarities using the genome drawer object
1347    
1348    =cut
1349    
1350    sub display {
1351        my ($self,$gd) = @_;
1352    
1353        my $fig = new FIG;
1354        my $peg = $self->acc;
1355    
1356        my $organism = $self->organism;
1357        my $function = $self->function;
1358        my $abbrev_name = $fig->abbrev($organism);
1359        my $align_start = $self->qstart;
1360        my $align_stop = $self->qstop;
1361        my $hit_start = $self->hstart;
1362        my $hit_stop = $self->hstop;
1363    
1364        my $line_config = { 'title' => "$organism",
1365                            'short_title' => "$abbrev_name",
1366                            'basepair_offset' => '0'
1367                            };
1368    
1369        my $line_data = [];
1370    
1371        my $element_hash;
1372        my $links_list = [];
1373        my $descriptions = [];
1374    
1375        # get subsystem information
1376        my $url_link = "http://seed-viewer.theseed.org/index.cgi?action=ShowAnnotation&prot=".$peg;
1377    
1378        my $link;
1379        $link = {"link_title" => $peg,
1380                 "link" => $url_link};
1381        push(@$links_list,$link);
1382    
1383        my @subsystems = $fig->peg_to_subsystems($peg);
1384        foreach my $subsystem (@subsystems){
1385            my $link;
1386            $link = {"link" => "http://seed-viewer.theseed.org/index.cgi?action=ShowSubsystem&subsystem_name=$subsystem",
1387                     "link_title" => $subsystem};
1388            push(@$links_list,$link);
1389        }
1390    
1391        my $description_function;
1392        $description_function = {"title" => "function",
1393                                 "value" => $function};
1394        push(@$descriptions,$description_function);
1395    
1396        my ($description_ss, $ss_string);
1397        $ss_string = join (",", @subsystems);
1398        $description_ss = {"title" => "subsystems",
1399                           "value" => $ss_string};
1400        push(@$descriptions,$description_ss);
1401    
1402        my $description_loc;
1403        $description_loc = {"title" => "location start",
1404                            "value" => $hit_start};
1405        push(@$descriptions, $description_loc);
1406    
1407        $description_loc = {"title" => "location stop",
1408                            "value" => $hit_stop};
1409        push(@$descriptions, $description_loc);
1410    
1411        my $evalue = $self->evalue;
1412        while ($evalue =~ /-0/)
1413        {
1414            my ($chunk1, $chunk2) = split(/-/, $evalue);
1415            $chunk2 = substr($chunk2,1);
1416            $evalue = $chunk1 . "-" . $chunk2;
1417        }
1418    
1419        my $color = &color($evalue);
1420    
1421        my $description_eval = {"title" => "E-Value",
1422                                "value" => $evalue};
1423        push(@$descriptions, $description_eval);
1424    
1425        my $identity = $self->identity;
1426        my $description_identity = {"title" => "Identity",
1427                                    "value" => $identity};
1428        push(@$descriptions, $description_identity);
1429    
1430        $element_hash = {
1431            "title" => $peg,
1432            "start" => $align_start,
1433            "end" =>  $align_stop,
1434            "type"=> 'box',
1435            "color"=> $color,
1436            "zlayer" => "2",
1437            "links_list" => $links_list,
1438            "description" => $descriptions
1439            };
1440        push(@$line_data,$element_hash);
1441        $gd->add_line($line_data, $line_config);
1442    
1443        return ($gd);
1444    
1445    }
1446    
1447    =head3 display_table()
1448    
1449  If available use the function specified here to display the "raw" observation.  If available use the function specified here to display the "raw" observation.
1450  This code will display a table for the similarities protein  This code will display a table for the similarities protein
1451    
# Line 1069  Line 1453 
1453    
1454  =cut  =cut
1455    
1456  sub display {  sub display_table {
1457      my ($self,$cgi,$dataset) = @_;      my ($self,$dataset) = @_;
1458    
1459      my $data = [];      my $data = [];
1460      my $count = 0;      my $count = 0;
1461      my $content;      my $content;
1462        my $fig = new FIG;
1463        my $cgi = new CGI;
1464      foreach my $thing (@$dataset) {      foreach my $thing (@$dataset) {
1465          my $single_domain = [];          my $single_domain = [];
1466          next if ($thing->class ne "SIM");          next if ($thing->class ne "SIM");
1467          $count++;          $count++;
1468    
1469          push(@$single_domain,&HTML::set_prot_links($cgi,$thing->acc));          my $id = $thing->acc;
1470          push(@$single_domain,$thing->start);  
1471          push(@$single_domain,$thing->stop);          # add the subsystem information
1472            my @in_sub  = $fig->peg_to_subsystems($id);
1473            my $in_sub;
1474    
1475            if (@in_sub > 0) {
1476                $in_sub = @in_sub;
1477    
1478                # RAE: add a javascript popup with all the subsystems
1479                my $ss_list=join "<br>", map { my $g = $_; $g =~ s/\_/ /g; $_ = $g } sort {$a cmp $b} @in_sub;
1480                $in_sub = $cgi->a( {id=>"subsystems", onMouseover=>"javascript:if(!this.tooltip) this.tooltip=new Popup_Tooltip(this, 'Subsystems', '$ss_list', ''); this.tooltip.addHandler(); return false;"}, $in_sub);
1481            } else {
1482                $in_sub = "&nbsp;";
1483            }
1484    
1485            # add evidence code with tool tip
1486            my $ev_codes=" &nbsp; ";
1487            my @ev_codes = "";
1488            if ($id =~ /^fig\|\d+\.\d+\.peg\.\d+$/) {
1489                my @codes = grep { $_->[1] =~ /^evidence_code/i } $fig->get_attributes($id);
1490                @ev_codes = ();
1491                foreach my $code (@codes) {
1492                    my $pretty_code = $code->[2];
1493                    if ($pretty_code =~ /;/) {
1494                        my ($cd, $ss) = split(";", $code->[2]);
1495                        $ss =~ s/_/ /g;
1496                        $pretty_code = $cd;# . " in " . $ss;
1497                    }
1498                    push(@ev_codes, $pretty_code);
1499                }
1500            }
1501    
1502            if (scalar(@ev_codes) && $ev_codes[0]) {
1503                my $ev_code_help=join("<br />", map {&HTML::evidence_codes_explain($_)} @ev_codes);
1504                $ev_codes = $cgi->a(
1505                                    {
1506                                        id=>"evidence_codes", onMouseover=>"javascript:if(!this.tooltip) this.tooltip=new Popup_Tooltip(this, 'Evidence Codes', '$ev_code_help', ''); this.tooltip.addHandler(); return false;"}, join("<br />", @ev_codes));
1507            }
1508    
1509            my $iden    = $thing->identity;
1510            my $ln1     = $thing->qlength;
1511            my $ln2     = $thing->hlength;
1512            my $b1      = $thing->qstart;
1513            my $e1      = $thing->qstop;
1514            my $b2      = $thing->hstart;
1515            my $e2      = $thing->hstop;
1516            my $d1      = abs($e1 - $b1) + 1;
1517            my $d2      = abs($e2 - $b2) + 1;
1518            my $reg1    = "$b1-$e1 (<b>$d1/$ln1</b>)";
1519            my $reg2    = "$b2-$e2 (<b>$d2/$ln2</b>)";
1520    
1521            my $name = $thing->acc;
1522            my $field_name = "tables_" . $name;
1523            my $pair_name = "visual_" . $name;
1524    
1525            my $checkbox_col = qq(<input type=checkbox name=seq value="$name" id="$field_name" onClick="VisualCheckPair('$field_name', '$pair_name');">);
1526            my $acc_col .= &HTML::set_prot_links($cgi,$thing->acc);
1527    
1528            push(@$single_domain,$checkbox_col);
1529            push(@$single_domain,$thing->database);
1530            push(@$single_domain,$acc_col);
1531          push(@$single_domain,$thing->evalue);          push(@$single_domain,$thing->evalue);
1532            push(@$single_domain,"$iden\%");
1533            push(@$single_domain,$reg1);
1534            push(@$single_domain,$reg2);
1535            push(@$single_domain,$in_sub);
1536            push(@$single_domain,$ev_codes);
1537            push(@$single_domain,$thing->organism);
1538            push(@$single_domain,$thing->function);
1539          push(@$data,$single_domain);          push(@$data,$single_domain);
1540    
1541      }      }
1542    
1543      if ($count >0){      if ($count >0){
1544          $content = $data;          $content = $data;
1545      }      }
1546      else      else{
     {  
1547          $content = "<p>This PEG does not have any similarities</p>";          $content = "<p>This PEG does not have any similarities</p>";
1548      }      }
1549      return ($content);      return ($content);
1550  }  }
1551    
1552    sub html_enc { $_ = $_[0]; s/\&/&amp;/g; s/\>/&gt;/g; s/\</&lt;/g; $_ }
1553    
1554    sub color {
1555        my ($evalue) = @_;
1556    
1557        my $color;
1558        if ($evalue <= 1e-100){
1559            $color = 1;
1560        }
1561        elsif (($evalue <= 1e-70) && ($evalue > 1e-100)){
1562            $color = 2;
1563        }
1564        elsif (($evalue <= 1e-20) && ($evalue > 1e-70)){
1565            $color = 3;
1566        }
1567        elsif (($evalue <= 1e-10) && ($evalue > 1e-20)){
1568            $color = 4;
1569        }
1570        elsif (($evalue <= 1e-4) && ($evalue > 1e-1)){
1571            $color = 5;
1572        }
1573        else{
1574            $color = 6;
1575        }
1576        return ($color);
1577    }
1578    
1579    
1580    ############################
1581    package Observation::Cluster;
1582    
1583    use base qw(Observation);
1584    
1585    sub new {
1586    
1587        my ($class,$dataset) = @_;
1588        my $self = $class->SUPER::new($dataset);
1589        $self->{context} = $dataset->{'context'};
1590        bless($self,$class);
1591        return $self;
1592    }
1593    
1594    sub display {
1595        my ($self,$gd) = @_;
1596    
1597        my $fid = $self->fig_id;
1598        my $compare_or_coupling = $self->context;
1599        my $gd_window_size = $gd->window_size;
1600        my $fig = new FIG;
1601        my $all_regions = [];
1602    
1603        #get the organism genome
1604        my $target_genome = $fig->genome_of($fid);
1605    
1606        # get location of the gene
1607        my $data = $fig->feature_location($fid);
1608        my ($contig, $beg, $end);
1609        my %reverse_flag;
1610    
1611        if ($data =~ /(.*)_(\d+)_(\d+)$/){
1612            $contig = $1;
1613            $beg = $2;
1614            $end = $3;
1615        }
1616    
1617        my $offset;
1618        my ($region_start, $region_end);
1619        if ($beg < $end)
1620        {
1621            $region_start = $beg - 4000;
1622            $region_end = $end+4000;
1623            $offset = ($2+(($3-$2)/2))-($gd_window_size/2);
1624        }
1625        else
1626        {
1627            $region_start = $end-4000;
1628            $region_end = $beg+4000;
1629            $offset = ($3+(($2-$3)/2))-($gd_window_size/2);
1630            $reverse_flag{$target_genome} = $fid;
1631        }
1632    
1633        # call genes in region
1634        my ($target_gene_features, $reg_beg, $reg_end) = $fig->genes_in_region($target_genome, $contig, $region_start, $region_end);
1635        push(@$all_regions,$target_gene_features);
1636        my (@start_array_region);
1637        push (@start_array_region, $offset);
1638    
1639        my %all_genes;
1640        my %all_genomes;
1641        foreach my $feature (@$target_gene_features){ $all_genes{$feature} = $fid;}
1642    
1643        if ($compare_or_coupling eq "diverse")
1644        {
1645            my @coup = grep { $_->[1]} $fig->coupling_and_evidence($fid,5000,1e-10,4,1);
1646    
1647            my $coup_count = 0;
1648    
1649            foreach my $pair (@{$coup[0]->[2]}) {
1650                #   last if ($coup_count > 10);
1651                my ($peg1,$peg2) = @$pair;
1652    
1653                my ($pair_contig,$pair_beg,$pair_end,$pair_region_start,$pair_region_stop,$pair_genome);
1654                $pair_genome = $fig->genome_of($peg1);
1655    
1656                my $location = $fig->feature_location($peg1);
1657                if($location =~/(.*)_(\d+)_(\d+)$/){
1658                    $pair_contig = $1;
1659                    $pair_beg = $2;
1660                    $pair_end = $3;
1661                    if ($pair_beg < $pair_end)
1662                    {
1663                        $pair_region_start = $pair_beg - 4000;
1664                        $pair_region_stop = $pair_end+4000;
1665                        $offset = ($2+(($3-$2)/2))-($gd_window_size/2);
1666                    }
1667                    else
1668                    {
1669                        $pair_region_start = $pair_end-4000;
1670                        $pair_region_stop = $pair_beg+4000;
1671                        $offset = ($3+(($2-$3)/2))-($gd_window_size/2);
1672                        $reverse_flag{$pair_genome} = $peg1;
1673                    }
1674    
1675                    push (@start_array_region, $offset);
1676    
1677                    $all_genomes{$pair_genome} = 1;
1678                    my ($pair_features) = $fig->genes_in_region($pair_genome, $pair_contig, $pair_region_start, $pair_region_stop);
1679                    push(@$all_regions,$pair_features);
1680                    foreach my $pair_feature (@$pair_features){ $all_genes{$pair_feature} = $peg1;}
1681                }
1682                $coup_count++;
1683            }
1684        }
1685    
1686        elsif ($compare_or_coupling eq "close")
1687        {
1688            # make a hash of genomes that are phylogenetically close
1689            #my $close_threshold = ".26";
1690            #my @genomes = $fig->genomes('complete');
1691            #my %close_genomes = ();
1692            #foreach my $compared_genome (@genomes)
1693            #{
1694            #    my $dist = $fig->crude_estimate_of_distance($target_genome,$compared_genome);
1695            #    #$close_genomes{$compared_genome} = $dist;
1696            #    if ($dist <= $close_threshold)
1697            #    {
1698            #       $all_genomes{$compared_genome} = 1;
1699            #    }
1700            #}
1701            $all_genomes{"216592.1"} = 1;
1702            $all_genomes{"79967.1"} = 1;
1703            $all_genomes{"199310.1"} = 1;
1704            $all_genomes{"216593.1"} = 1;
1705            $all_genomes{"155864.1"} = 1;
1706            $all_genomes{"83334.1"} = 1;
1707            $all_genomes{"316407.3"} = 1;
1708    
1709            foreach my $comp_genome (keys %all_genomes){
1710                my $return = $fig->bbh_list($comp_genome,[$fid]);
1711                my $feature_list = $return->{$fid};
1712                foreach my $peg1 (@$feature_list){
1713                    my $location = $fig->feature_location($peg1);
1714                    my ($pair_contig,$pair_beg,$pair_end,$pair_region_start,$pair_region_stop,$pair_genome);
1715                    $pair_genome = $fig->genome_of($peg1);
1716    
1717                    if($location =~/(.*)_(\d+)_(\d+)$/){
1718                        $pair_contig = $1;
1719                        $pair_beg = $2;
1720                        $pair_end = $3;
1721                        if ($pair_beg < $pair_end)
1722                        {
1723                            $pair_region_start = $pair_beg - 4000;
1724                            $pair_region_stop = $pair_end + 4000;
1725                            $offset = ($2+(($3-$2)/2))-($gd_window_size/2);
1726                        }
1727                        else
1728                        {
1729                            $pair_region_start = $pair_end-4000;
1730                            $pair_region_stop = $pair_beg+4000;
1731                            $offset = ($3+(($2-$3)/2))-($gd_window_size/2);
1732                            $reverse_flag{$pair_genome} = $peg1;
1733                        }
1734    
1735                        push (@start_array_region, $offset);
1736                        $all_genomes{$pair_genome} = 1;
1737                        my ($pair_features) = $fig->genes_in_region($pair_genome, $pair_contig, $pair_region_start, $pair_region_stop);
1738                        push(@$all_regions,$pair_features);
1739                        foreach my $pair_feature (@$pair_features){ $all_genes{$pair_feature} = $peg1;}
1740                    }
1741                }
1742            }
1743        }
1744    
1745        # get the PCH to each of the genes
1746        my $pch_sets = [];
1747        my %pch_already;
1748        foreach my $gene_peg (keys %all_genes)
1749        {
1750            if ($pch_already{$gene_peg}){next;};
1751            my $gene_set = [$gene_peg];
1752            foreach my $pch_peg ($fig->in_pch_pin_with($gene_peg)) {
1753                $pch_peg =~ s/,.*$//;
1754                my $pch_genome = $fig->genome_of($pch_peg);
1755                if ( ($gene_peg ne $pch_peg) && ($all_genomes{$pch_genome})) {
1756                    push(@$gene_set,$pch_peg);
1757                    $pch_already{$pch_peg}=1;
1758                }
1759                $pch_already{$gene_peg}=1;
1760            }
1761            push(@$pch_sets,$gene_set);
1762        }
1763    
1764        #create a rank of the pch's
1765        my %pch_set_rank;
1766        my $order = 0;
1767        foreach my $set (@$pch_sets){
1768            my $count = scalar(@$set);
1769            $pch_set_rank{$order} = $count;
1770            $order++;
1771        }
1772    
1773        my %peg_rank;
1774        my $counter =  1;
1775        foreach my $pch_order (sort {$pch_set_rank{$b} <=> $pch_set_rank{$a}} keys %pch_set_rank){
1776            my $good_set = @$pch_sets[$pch_order];
1777            my $flag_set = 0;
1778            if (scalar (@$good_set) > 1)
1779            {
1780                foreach my $peg (@$good_set){
1781                    if ((!$peg_rank{$peg})){
1782                        $peg_rank{$peg} = $counter;
1783                        $flag_set = 1;
1784                    }
1785                }
1786                $counter++ if ($flag_set == 1);
1787            }
1788            else
1789            {
1790                foreach my $peg (@$good_set){
1791                    $peg_rank{$peg} = "20";
1792                }
1793            }
1794        }
1795    
1796    
1797    #    my $bbh_sets = [];
1798    #    my %already;
1799    #    foreach my $gene_key (keys(%all_genes)){
1800    #       if($already{$gene_key}){next;}
1801    #       my $gene_set = [$gene_key];
1802    #
1803    #       my $gene_key_genome = $fig->genome_of($gene_key);
1804    #
1805    #       foreach my $genome_key (keys(%all_genomes)){
1806    #           #next if ($gene_key_genome eq $genome_key);
1807    #           my $return = $fig->bbh_list($genome_key,[$gene_key]);
1808    #
1809    #           my $feature_list = $return->{$gene_key};
1810    #           foreach my $fl (@$feature_list){
1811    #               push(@$gene_set,$fl);
1812    #           }
1813    #       }
1814    #       $already{$gene_key} = 1;
1815    #       push(@$bbh_sets,$gene_set);
1816    #    }
1817    #
1818    #    my %bbh_set_rank;
1819    #    my $order = 0;
1820    #    foreach my $set (@$bbh_sets){
1821    #       my $count = scalar(@$set);
1822    #       $bbh_set_rank{$order} = $count;
1823    #       $order++;
1824    #    }
1825    #
1826    #    my %peg_rank;
1827    #    my $counter =  1;
1828    #    foreach my $bbh_order (sort {$bbh_set_rank{$b} <=> $bbh_set_rank{$a}} keys %bbh_set_rank){
1829    #       my $good_set = @$bbh_sets[$bbh_order];
1830    #       my $flag_set = 0;
1831    #       if (scalar (@$good_set) > 1)
1832    #       {
1833    #           foreach my $peg (@$good_set){
1834    #               if ((!$peg_rank{$peg})){
1835    #                   $peg_rank{$peg} = $counter;
1836    #                   $flag_set = 1;
1837    #               }
1838    #           }
1839    #           $counter++ if ($flag_set == 1);
1840    #       }
1841    #       else
1842    #       {
1843    #           foreach my $peg (@$good_set){
1844    #               $peg_rank{$peg} = "20";
1845    #           }
1846    #       }
1847    #    }
1848    
1849        foreach my $region (@$all_regions){
1850            my $sample_peg = @$region[0];
1851            my $region_genome = $fig->genome_of($sample_peg);
1852            my $region_gs = $fig->genus_species($region_genome);
1853            my $abbrev_name = $fig->abbrev($region_gs);
1854            my $line_config = { 'title' => $region_gs,
1855                                'short_title' => $abbrev_name,
1856                                'basepair_offset' => '0'
1857                                };
1858    
1859            my $offsetting = shift @start_array_region;
1860    
1861            my $second_line_config = { 'title' => "$region_gs",
1862                                       'short_title' => "",
1863                                       'basepair_offset' => '0'
1864                                       };
1865    
1866            my $line_data = [];
1867            my $second_line_data = [];
1868    
1869            # initialize variables to check for overlap in genes
1870            my ($prev_start, $prev_stop, $prev_fig, $second_line_flag);
1871            my $major_line_flag = 0;
1872            my $prev_second_flag = 0;
1873    
1874            foreach my $fid1 (@$region){
1875                $second_line_flag = 0;
1876                my $element_hash;
1877                my $links_list = [];
1878                my $descriptions = [];
1879    
1880                my $color = $peg_rank{$fid1};
1881    
1882                # get subsystem information
1883                my $function = $fig->function_of($fid1);
1884                my $url_link = "http://seed-viewer.theseed.org/index.cgi?action=ShowAnnotation&prot=".$fid1;
1885    
1886                my $link;
1887                $link = {"link_title" => $fid1,
1888                         "link" => $url_link};
1889                push(@$links_list,$link);
1890    
1891                my @subsystems = $fig->peg_to_subsystems($fid1);
1892                foreach my $subsystem (@subsystems){
1893                    my $link;
1894                    $link = {"link" => "http://seed-viewer.theseed.org/index.cgi?action=ShowSubsystem&subsystem_name=$subsystem",
1895                             "link_title" => $subsystem};
1896                    push(@$links_list,$link);
1897                }
1898    
1899                my $description_function;
1900                $description_function = {"title" => "function",
1901                                         "value" => $function};
1902                push(@$descriptions,$description_function);
1903    
1904                my $description_ss;
1905                my $ss_string = join (",", @subsystems);
1906                $description_ss = {"title" => "subsystems",
1907                                   "value" => $ss_string};
1908                push(@$descriptions,$description_ss);
1909    
1910    
1911                my $fid_location = $fig->feature_location($fid1);
1912                if($fid_location =~/(.*)_(\d+)_(\d+)$/){
1913                    my($start,$stop);
1914                    $start = $2 - $offsetting;
1915                    $stop = $3 - $offsetting;
1916    
1917                    if ( (($prev_start) && ($prev_stop) ) &&
1918                         ( ($start < $prev_start) || ($start < $prev_stop) ||
1919                           ($stop < $prev_start) || ($stop < $prev_stop) )){
1920                        if (($second_line_flag == 0) && ($prev_second_flag == 0)) {
1921                            $second_line_flag = 1;
1922                            $major_line_flag = 1;
1923                        }
1924                    }
1925                    $prev_start = $start;
1926                    $prev_stop = $stop;
1927                    $prev_fig = $fid1;
1928    
1929                    if ((defined($reverse_flag{$region_genome})) && ($reverse_flag{$region_genome} eq $all_genes{$fid1})){
1930                        $start = $gd_window_size - $start;
1931                        $stop = $gd_window_size - $stop;
1932                    }
1933    
1934                    $element_hash = {
1935                        "title" => $fid1,
1936                        "start" => $start,
1937                        "end" =>  $stop,
1938                        "type"=> 'arrow',
1939                        "color"=> $color,
1940                        "zlayer" => "2",
1941                        "links_list" => $links_list,
1942                        "description" => $descriptions
1943                    };
1944    
1945                    # if there is an overlap, put into second line
1946                    if ($second_line_flag == 1){ push(@$second_line_data,$element_hash); $prev_second_flag = 1;}
1947                    else{ push(@$line_data,$element_hash); $prev_second_flag = 0;}
1948    
1949                }
1950            }
1951            $gd->add_line($line_data, $line_config);
1952            $gd->add_line($second_line_data, $second_line_config) if ($major_line_flag == 1);
1953        }
1954        return $gd;
1955    }
1956    
1957    

Legend:
Removed from v.1.10  
changed lines
  Added in v.1.27

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3