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

Diff of /FigKernelPackages/FIGO.pm

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

revision 1.6, Thu Feb 22 13:43:18 2007 UTC revision 1.26, Wed Sep 26 04:03:48 2007 UTC
# Line 1  Line 1 
1    ########################################################################
2  #  #
3  # Copyright (c) 2003-2006 University of Chicago and Fellowship  # Copyright (c) 2003-2006 University of Chicago and Fellowship
4  # for Interpretations of Genomes. All Rights Reserved.  # for Interpretations of Genomes. All Rights Reserved.
# Line 14  Line 15 
15  # Genomes at veronika@thefig.info or download a copy from  # Genomes at veronika@thefig.info or download a copy from
16  # http://www.theseed.org/LICENSE.TXT.  # http://www.theseed.org/LICENSE.TXT.
17  #  #
18    ########################################################################
19    
20  package FIGO;  =head1 Overview
21    
22    This module is a set of packages encapsulating the SEED's core methods
23    using an "OOP-like" style.
24    
25    There are several modules clearly related to "individual genomes:"
26    FIGO, GenomeO, ContigO, FeatureO (and I<maybe> AnnotationO).
27    
28    There are also modules that deal with complex relationships between
29    pairs or sets of features in one, two, or more genomes,
30    rather than any particular single genome:
31    BBHO, CouplingO, SubsystemO, FunctionalRoleO, FigFamO.
32    
33    Finally, the methods in "Attribute" might in principle attach
34    "atributes" to any type of object.
35    (Likewise, in principle one might like to attach an "annotation"
36    to any type of object
37    
38    The four modules dealing with "genomes" have a reasonable clear
39    "implied heirarchy:"
40    
41    =over 4
42    
43        FIGO > GenomeO > ContigO > FeatureO
44    
45    =back
46    
47    However, inheritance is B<NOT> implemented using the C<@ISA> mechanism,
48    because some methods deal with "pairwise" or "setwise" relations between objects
49    or other more complex relationships that do not naturally fit into any heirarchy ---
50    which would get us into the whole quagmire of "multiple inheritance."
51    
52    We have chosen to in many cases sidestep the entire issue of inheritance
53    via an I<ad hoc> mechanism:
54    If a "child" object needs access to its "ancestors'" methods,
55    we will explicitly pass it references to its "ancestors,"
56    as subroutine arguments.
57    This is admittedly ugly, clumsy, and potentially error-prone ---
58    but it has the advantage that, unlike multiple inheritance,
59    we understand how to do it...
60    
61    MODULE DEPENDENCIES: FIG, FIG_Config, FigFams, SFXlate, SproutFIG, Tracer,
62        gjoparseblast, Data::Dumper.
63    
64    =cut
65    
66    ########################################################################
67    package FIGO;
68    ########################################################################
69  use strict;  use strict;
70  use FIG;  use FIG;
71  use FIG_Config;  use FIG_Config;
# Line 24  Line 73 
73  use SproutFIG;  use SproutFIG;
74  use Tracer;  use Tracer;
75  use Data::Dumper;  use Data::Dumper;
76    use Carp;
77  use FigFams;  use FigFams;
78  use gjoparseblast;  use gjoparseblast;
79    
80  =head1 FIGO Methods  =head1 FIGO
81    
82    The effective "base class" containing a few "top-level" methods.
83    
84    =cut
85    
86    
87  =head3 new  =head3 new
88    
# Line 64  Line 119 
119      return bless $self, $class;      return bless $self, $class;
120  }  }
121    
122    sub function_of {
123        my($self,$id) = @_;
124    
125        my $fig  = $self->{_fig};
126        my $func = $fig->function_of($id);
127    
128        return ($func ? $func : "");
129    }
130    
131  =head3 genomes  =head3 genomes
132    
# Line 80  Line 142 
142  C<< my @tax_ids = $figo->genomes( @constraints ); >>  C<< my @tax_ids = $figo->genomes( @constraints ); >>
143    
144  =item @constraints  =item @constraints
145    
146  One or more element of: complete, prokaryotic, eukaryotic, bacterial, archaeal, nmpdr.  One or more element of: complete, prokaryotic, eukaryotic, bacterial, archaeal, nmpdr.
147    
148  =item RETURNS: List of Tax-IDs.  =item RETURNS: List of Tax-IDs.
149    
150  =item EXAMPLE: L<Display all complete, prokaryotic genomes>  =item EXAMPLE:
151    
152    L<Display all complete, prokaryotic genomes>
153    
154  =back  =back
155    
# Line 141  Line 206 
206  =over4  =over4
207    
208  =item RETURNS:  =item RETURNS:
209    
210  List of all subsystems.  List of all subsystems.
211    
212  =item EXAMPLE: L<Accessing Subsystem data>  =item EXAMPLE:
213    
214    L<Accessing Subsystem data>
215    
216  =back  =back
217    
# Line 188  Line 256 
256    
257  =over4  =over4
258    
259  =item USAGE:  C<< foreach $fam ($figO->all_figfams) { #...Do something } >>  =item USAGE:
260    
261    C<< foreach $fam ($figO->all_figfams) { #...Do something } >>
262    
263    =item RETURNS:
264    
265        List of FIGfam Objects
266    
267  =item RETURNS: List of FIGfam Objects  =item EXAMPLE:
268    
269  =item EXAMPLE: L<Accessing FIGfams>  L<Accessing FIGfams>
270    
271  =back  =back
272    
# Line 211  Line 285 
285    
286  =over4  =over4
287    
288  =item USAGE:   C<< my ($fam, $sims) = $figO->family_containing($seq); >>  =item USAGE:
289    
290    C<< my ($fam, $sims) = $figO->family_containing($seq); >>
291    
292  =item $seq:    A protein translation string.  =item $seq:
293    
294        A protein translation string.
295    
296  =item RETURNS:  =item RETURNS:
297    
298        $fam:  A FIGfam Object.        $fam:  A FIGfam Object.
299    
300        $sims: A set of similarity objects.        $sims: A set of similarity objects.
301    
302  =item EXAMPLE: L<Placing a sequence into a FIGfam>  =item EXAMPLE: L<Placing a sequence into a FIGfam>
# Line 241  Line 321 
321      }      }
322  }  }
323    
324    =head3 figfam
325    
326    =over 4
327    
328    =item USAGE:
329    
330    C<< my $fam = $figO->figfam($family_id); >>
331    
332    =item $family_id;
333    
334        A FigFam ID
335    
336    =item RETURNS:
337    
338          $fam:  A FIGfam Object.
339    
340    =back
341    
342    =cut
343    
344    sub figfam {
345        my($self,$fam_id) = @_;
346    
347        return &FigFamO::new('FigFamO',$self,$fam_id);
348    }
349    
350    
351  ########################################################################  ########################################################################
352  package GenomeO;  package GenomeO;
# Line 251  Line 357 
357    
358  =cut  =cut
359    
360    
361  =head3 new  =head3 new
362    
363  Constructor of GenomeO objects.  Constructor of GenomeO objects.
# Line 258  Line 365 
365  =over4  =over4
366    
367  =item USAGE:  =item USAGE:
 C<< my $org = GenomeO->new($figo, $tax_id); >>  
368    
369  =item RETURNS: A new GenomeO object.  C<< my $orgO = GenomeO->new($figO, $tax_id); >>
370    
371    =item RETURNS:
372    
373        A new "GenomeO" object.
374    
375  =back  =back
376    
# Line 281  Line 391 
391    
392  =over4  =over4
393    
394  =item USAGE:   C<< my $tax_id = $org->id(); >>  =item USAGE:
395    
396  =item RETURNS: Taxonomy-ID of GenomeO object.  C<< my $tax_id = $orgO->id(); >>
397    
398    =item RETURNS:
399    
400        Taxonomy-ID of "GenomeO" object.
401    
402  =back  =back
403    
# Line 301  Line 415 
415    
416  =over4  =over4
417    
418  =item USAGE:   C<< $gs = $genome->genus_species(); >>  =item USAGE:
419    
420  =item RETURNS: Genus-species-strain string  C<< $gs = $orgO->genus_species(); >>
421    
422    =item RETURNS:
423    
424        Genus-species-strain string
425    
426  =back  =back
427    
# Line 317  Line 435 
435  }  }
436    
437    
438    
439    
440    =head3 taxonomy_of
441    
442    =over 4
443    
444    =item FUNCTION:
445    
446    Return the TAXONOMY string of a "GenomeO" object.
447    
448    =item USAGE:
449    
450    C<< my $taxonomy = $orgO->taxonomy_of(); >>
451    
452    =item RETURNS:
453    
454    TAXONOMY string.
455    
456    =back
457    
458    =cut
459    
460    sub taxonomy_of {
461        my ($self) = @_;
462    
463        my $figO = $self->{_figO};
464        my $fig  = $figO->{_fig};
465    
466        return $fig->taxonomy_of($self->{_id});
467    }
468    
469    
470  =head3 contigs_of  =head3 contigs_of
471    
472  =over4  =over4
473    
474  =item RETURNS: List of C<contig> objects contained in a C<GenomeO> object.  =item RETURNS:
475    
476    List of C<contig> objects contained in a C<GenomeO> object.
477    
478    =item EXAMPLE:
479    
480  =item EXAMPLE: L<Show how to access contigs and extract sequence>  L<Show how to access contigs and extract sequence>
481    
482  =back  =back
483    
# Line 341  Line 495 
495    
496  =head3 features_of  =head3 features_of
497    
498    =over 4
499    
500    =item FUNCTION:
501    
502    Returns a list of "FeatureO" objects contained in a "GenomeO" object.
503    
504    =item USAGE:
505    
506    C<< my @featureOs = $orgO->features_of();        #...Fetch all features >>
507    
508    or
509    
510    C<< my @featureOs = $orgO->features_of('peg');   #...Fetch only PEGs >>
511    
512    =item RETURNS:
513    
514    List of "FeatureO" objects.
515    
516    =back
517    
518  =cut  =cut
519    
520  sub features_of {  sub features_of {
# Line 359  Line 533 
533    
534  =over4  =over4
535    
536  =item USAGE:   C<< $genome->display(); >>  =item USAGE:
537    
538  =item RETURNS: Null  C<< $genome->display(); >>
539    
540    =item RETURNS:
541    
542        (Void)
543    
544  =back  =back
545    
# Line 393  Line 571 
571  =over4  =over4
572    
573  =item USAGE:  =item USAGE:
574    
575  C<< $contig = ContigO->new( $figO, $genomeId, $contigId); >>  C<< $contig = ContigO->new( $figO, $genomeId, $contigId); >>
576    
577  =item $figO: A FIGO object.  =item $figO:
578    
579  =item $genomeId: Taxon-ID for the genome the contig is from.      Parent FIGO object.
580    
581  =item $contigId: Identifier for the contig  =item $genomeId:
582    
583  =item RETURNS: A "ContigO" object.      Taxon-ID for the genome the contig is from.
584    
585    =item $contigId:
586    
587        Identifier for the contig
588    
589    =item RETURNS:
590    
591        A "ContigO" object.
592    
593  =back  =back
594    
# Line 423  Line 610 
610    
611  =over4  =over4
612    
613  =item RETURNS: Sequence ID string of "ContigO" object  =item RETURNS:
614    
615        Sequence ID string of "ContigO" object
616    
617  =back  =back
618    
# Line 441  Line 630 
630  =over4  =over4
631    
632  =item USAGE:  =item USAGE:
     C<< my $tax_id = $contig->genome(); >>  
633    
634  =item RETURNS: GenomeO object containing the contig object.  C<< my $tax_id = $contig->genome->id(); >>
635    
636    =item RETURNS:
637    
638        Tax-ID of the GenomeO object containing the contig object.
639    
640  =back  =back
641    
# Line 452  Line 644 
644  sub genome {  sub genome {
645      my($self) = @_;      my($self) = @_;
646    
647      return $self->{_genome};      my $figO = $self->{_figO};
648        return new GenomeO($figO,$self->{_genome});
649  }  }
650    
651    
# Line 462  Line 655 
655  =over4  =over4
656    
657  =item USAGE:  =item USAGE:
658    
659      C<< my $len = $contig->contig_length(); >>      C<< my $len = $contig->contig_length(); >>
660    
661  =item RETURNS: Length of contig's DNA sequence.  =item RETURNS:
662    
663        Length of contig's DNA sequence.
664    
665  =back  =back
666    
# Line 474  Line 670 
670      my($self) = @_;      my($self) = @_;
671    
672      my $fig = $self->{_figO}->{_fig};      my $fig = $self->{_figO}->{_fig};
673      my $contig_lengths = $fig->contig_lengths($self->genome);      my $contig_lengths = $fig->contig_lengths($self->genome->id);
674      return $contig_lengths->{$self->id};      return $contig_lengths->{$self->id};
675  }  }
676    
# Line 484  Line 680 
680  =over4  =over4
681    
682  =item USAGE:  =item USAGE:
683    
684      C<< my $seq = $contig->dna_seq(beg, $end); >>      C<< my $seq = $contig->dna_seq(beg, $end); >>
685    
686  =item $beg: Begining point of DNA subsequence  =item $beg:
687    
688        Begining point of DNA subsequence
689    
690  =item $end: End point of DNA subsequence  =item $end:
691    
692  =item RETURNS: string of DNA sequence from $beg to $end      End point of DNA subsequence
693    
694    =item RETURNS:
695    
696        string of DNA sequence running from $beg to $end
697  (NOTE: if $beg > $end, returns reverse complement of DNA subsequence.)  (NOTE: if $beg > $end, returns reverse complement of DNA subsequence.)
698    
699  =back  =back
# Line 506  Line 708 
708      if (($beg && (&FIG::between(1,$beg,$max))) &&      if (($beg && (&FIG::between(1,$beg,$max))) &&
709          ($end && (&FIG::between(1,$end,$max))))          ($end && (&FIG::between(1,$end,$max))))
710      {      {
711          return $fig->dna_seq($self->genome,join("_",($self->id,$beg,$end)));          return $fig->dna_seq($self->genome->id,join("_",($self->id,$beg,$end)));
712      }      }
713      else      else
714      {      {
# Line 527  Line 729 
729    
730  =over4  =over4
731    
732  =item RETURNS: Nil  =item RETURNS:
733    
734        (Void)
735    
736  =back  =back
737    
# Line 536  Line 740 
740  sub display {  sub display {
741      my($self) = @_;      my($self) = @_;
742    
743      print join("ContigO",$self->genome,$self->id,$self->contig_length),"\n";      print join("ContigO",$self->genome->id,$self->id,$self->contig_length),"\n";
744    }
745    
746    sub features_in_region {
747        my($self,$beg,$end) = @_;
748        my $figO = $self->{_figO};
749        my $fig = $figO->{_fig};
750    
751        my($features) = $fig->genes_in_region($self->genome->id,$self->id,$beg,$end);
752        return map { new FeatureO($figO,$_) } @$features;
753  }  }
754    
755    
# Line 545  Line 758 
758  package FeatureO;  package FeatureO;
759  ########################################################################  ########################################################################
760  use Data::Dumper;  use Data::Dumper;
761    use Carp;
762    
763  =head1 FeatureO  =head1 FeatureO
764    
765    Methods for working with features on "ContigO" objects.
766    
767  =cut  =cut
768    
769    
770    =head3 new
771    
772    Constructor of new "FeatureO" objects
773    
774    =over 4
775    
776  =head1 new  =item USAGE:
777    
778  Constructor of "FeatureO" objects  C<< my $feature = FeatureO->new( $figO, $fid ); >>
779    
780    =item C<$figO>:
781    
782    "Base" FIGO object.
783    
784    =item C<$fid>:
785    
786    Feature-ID for new feature
787    
788    =item RETURNS:
789    
790    A newly created "FeatureO" object.
791    
792    =back
793    
794  =cut  =cut
795    
# Line 569  Line 804 
804  }  }
805    
806    
807    
808  =head3 id  =head3 id
809    
810    =over 4
811    
812    =item USAGE:
813    
814    C<< my $fid = $feature->id(); >>
815    
816    =item RETURNS:
817    
818    The FID (Feature ID) of a "FeatureO" object.
819    
820    =back
821    
822  =cut  =cut
823    
824  sub id {  sub id {
# Line 583  Line 831 
831    
832  =head3 genome  =head3 genome
833    
834    =over 4
835    
836    =item USAGE:
837    
838    C<< my $taxid = $feature->genome(); >>
839    
840    =item RETURNS:
841    
842    The Taxon-ID for the "GenomeO" object containing the feature.
843    
844    =back
845    
846  =cut  =cut
847    
848  sub genome {  sub genome {
849      my($self) = @_;      my($self) = @_;
850        my $figO = $self->{_figO};
851      $self->id =~ /^fig\|(\d+\.\d+)/;      $self->id =~ /^fig\|(\d+\.\d+)/;
852      return $1;      return new GenomeO($figO,$1);
853  }  }
854    
855    
856    
857  =head3 type  =head3 type
858    
859    =over 4
860    
861    =item USAGE:
862    
863    C<< my $feature_type = $feature->type(); >>
864    
865    =item RETURNS:
866    
867    The feature object's "type" (e.g., "peg," "rna," etc.)
868    
869    =back
870    
871  =cut  =cut
872    
873  sub type {  sub type {
# Line 607  Line 879 
879    
880    
881    
   
882  =head3 location  =head3 location
883    
884    =over 4
885    
886    =item USAGE:
887    
888    C<< my $loc = $feature->location(); >>
889    
890    =item RETURNS:
891    
892    A string representing the feature object's location on the genome's DNA,
893    in SEED "tbl format" (i.e., "contig_beging_end").
894    
895    =back
896    
897  =cut  =cut
898    
899  sub location {  sub location {
# Line 620  Line 904 
904  }  }
905    
906    
907    =head3 contig
908    
909    =over 4
910    
911    =item USAGE:
912    
913    C<< my $contig = $feature->contig(); >>
914    
915    =item RETURNS:
916    
917    A "ContigO" object to access the contig data
918    for the contig the feature is on.
919    
920    =back
921    
922    =cut
923    
924    sub contig {
925        my($self) = @_;
926    
927        my $figO = $self->{_figO};
928        my $loc      = $self->location;
929        my $genomeID = $self->genome->id;
930        return ($loc =~ /^(\S+)_\d+_\d+$/) ? new ContigO($figO,$genomeID,$1) : undef;
931    }
932    
933    
934    
935    =head3 begin
936    
937    =over 4
938    
939    =item USAGE:
940    
941    C<< my $beg = $feature->begin(); >>
942    
943    =item RETURNS:
944    
945    The numerical coordinate of the first base of the feature.
946    
947    =back
948    
949    =cut
950    
951    sub begin {
952        my($self) = @_;
953    
954        my $loc = $self->location;
955        return ($loc =~ /^\S+_(\d+)_\d+$/) ? $1 : undef;
956    }
957    
958    
959    
960    =head3 end
961    
962    =over 4
963    
964    =item USAGE:
965    
966    C<< my $end = $feature->end(); >>
967    
968    =item RETURNS:
969    
970    The numerical coordinate of the last base of the feature.
971    
972    =back
973    
974    =cut
975    
976    sub end {
977        my($self) = @_;
978    
979        my $loc = $self->location;
980        return ($loc =~ /^\S+_\d+_(\d+)$/) ? $1 : undef;
981    }
982    
983    
984    
985  =head3 dna_seq  =head3 dna_seq
986    
987    =over 4
988    
989    =item USAGE:
990    
991    C<< my $dna_seq = $feature->dna_seq(); >>
992    
993    =item RETURNS:
994    
995    A string contining the DNA subsequence of the contig
996    running from the first to the last base of the feature.
997    
998    If ($beg > $end), the reverse complement subsequence is returned.
999    
1000    =back
1001    
1002  =cut  =cut
1003    
1004  sub dna_seq {  sub dna_seq {
# Line 638  Line 1014 
1014    
1015  =head3 prot_seq  =head3 prot_seq
1016    
1017    =over 4
1018    
1019    =item USAGE:
1020    
1021    C<< my $dna_seq = $feature->prot_seq(); >>
1022    
1023    =item RETURNS:
1024    
1025    A string contining the protein translation of the feature (if it exists),
1026    or the "undef" value if the feature does not exist or is not a PEG.
1027    
1028    =back
1029    
1030  =cut  =cut
1031    
1032  sub prot_seq {  sub prot_seq {
# Line 653  Line 1042 
1042    
1043  =head3 function_of  =head3 function_of
1044    
1045    =over 4
1046    
1047    =item USAGE:
1048    
1049    C<< my $func = $feature->function_of(); >>
1050    
1051    =item RETURNS:
1052    
1053    A string containing the function assigned to the feature,
1054    or the "undef" value if no function has been assigned.
1055    
1056    =back
1057    
1058  =cut  =cut
1059    
1060  sub function_of {  sub function_of {
# Line 667  Line 1069 
1069    
1070  =head3 coupled_to  =head3 coupled_to
1071    
1072    =over 4
1073    
1074    =item USAGE:
1075    
1076    C<< my @coupled_features = $feature->coupled_to(); >>
1077    
1078    =item RETURNS:
1079    
1080    A list of "CouplingO" objects describing the evidence for functional coupling
1081    between this feature and other nearby features.
1082    
1083    =back
1084    
1085  =cut  =cut
1086    
1087  sub coupled_to {  sub coupled_to {
1088      my($self) = @_;      my($self) = @_;
1089    
1090      ($self->type eq "peg") || return undef;      ($self->type eq "peg") || return ();
1091      my $figO = $self->{_figO};      my $figO = $self->{_figO};
1092      my $fig  = $figO->{_fig};      my $fig  = $figO->{_fig};
1093      my $peg1 = $self->id;      my $peg1 = $self->id;
# Line 689  Line 1104 
1104    
1105  =head3 annotations  =head3 annotations
1106    
1107    =over 4
1108    
1109    =item USAGE:
1110    
1111    C<< my @annot_list = $feature->annotations(); >>
1112    
1113    =item RETURNS:
1114    
1115    A list of "AnnotationO" objects allowing access to the annotations for this feature.
1116    
1117    =back
1118    
1119  =cut  =cut
1120    
1121  sub annotations {  sub annotations {
# Line 700  Line 1127 
1127      return map { &AnnotationO::new('AnnotationO',@$_) } $fig->feature_annotations($self->id,1);      return map { &AnnotationO::new('AnnotationO',@$_) } $fig->feature_annotations($self->id,1);
1128  }  }
1129    
1130    
1131    =head3 in_subsystems
1132    
1133    =over 4
1134    
1135    =item USAGE:
1136    
1137    C<< my @subsys_list = $feature->in_subsystems(); >>
1138    
1139    =item RETURNS:
1140    
1141    A list of "SubsystemO" objects allowing access to the subsystems
1142    that this feature particupates in.
1143    
1144    =back
1145    
1146    =cut
1147    
1148  sub in_subsystems {  sub in_subsystems {
1149      my($self) = @_;      my($self) = @_;
1150      my $figO = $self->{_figO};      my $figO = $self->{_figO};
# Line 711  Line 1156 
1156    
1157  =head3 possibly_truncated  =head3 possibly_truncated
1158    
1159    =over 4
1160    
1161    =item USAGE:
1162    
1163    C<< my $trunc = $feature->possibly_truncated(); >>
1164    
1165    =item RETURNS:
1166    
1167    Boolean C<TRUE> if the feature may be truncated;
1168    boolean C<FALSE> otherwise.
1169    
1170    =back
1171    
1172  =cut  =cut
1173    
1174  sub possibly_truncated {  sub possibly_truncated {
# Line 725  Line 1183 
1183    
1184  =head3 possible_frameshift  =head3 possible_frameshift
1185    
1186    =over 4
1187    
1188    =item USAGE:
1189    
1190    C<< my $fs = $feature->possible_frameshift(); >>
1191    
1192    =item RETURNS:
1193    
1194    Boolean C<TRUE> if the feature may be a frameshifted fragment;
1195    boolean C<FALSE> otherwise.
1196    
1197    (NOTE: This is a crude prototype implementation,
1198    and is mostly as an example of how to code using FIGO.)
1199    
1200    =back
1201    
1202  =cut  =cut
1203    
1204  sub possible_frameshift {  sub possible_frameshift {
# Line 732  Line 1206 
1206      my $figO = $self->{_figO};      my $figO = $self->{_figO};
1207      my($tmp_dir) = $figO->{_tmp_dir};      my($tmp_dir) = $figO->{_tmp_dir};
1208    
1209        #...Skip tests and return '0' if truncated...
1210      if (! $self->possibly_truncated)      if (! $self->possibly_truncated)
1211      {      {
1212            #...Get best precomputed BLAST hit if E-value < 1.0e-50:
1213          my @sims = $self->sims( -max => 1, -cutoff => 1.0e-50);          my @sims = $self->sims( -max => 1, -cutoff => 1.0e-50);
1214    
1215            #...If a sim was returned:
1216          if (my $sim = shift @sims)          if (my $sim = shift @sims)
1217          {          {
1218                #...Get best hit FID and boundaries:
1219              my $peg2 = $sim->id2;              my $peg2 = $sim->id2;
1220              my $ln1  = $sim->ln1;              my $ln1  = $sim->ln1;
1221              my $ln2  = $sim->ln2;              my $ln2  = $sim->ln2;
1222              my $b2   = $sim->b2;              my $b2   = $sim->b2;
1223              my $e2   = $sim->e2;              my $e2   = $sim->e2;
1224    
1225                #...Convert from AA to BP, and pad out w/ 100 bp guard region:
1226              my $adjL = 100 + (($b2-1) * 3);              my $adjL = 100 + (($b2-1) * 3);
1227              my $adjR = 100 + (($ln2 - $e2) * 3);              my $adjR = 100 + (($ln2 - $e2) * 3);
1228    
1229                #...If hit is more than 20% longer than query:
1230              if ($ln2 > (1.2 * $ln1))              if ($ln2 > (1.2 * $ln1))
1231              {              {
1232                    #...Get and parse query location:
1233                  my $loc = $self->location;                  my $loc = $self->location;
1234                  if ($loc =~ /^(\S+)_(\d+)_(\d+)/)                  if ($loc =~ /^(\S+)_(\d+)_(\d+)/)
1235                  {                  {
1236                      my $contig = $1;                      my $contig = $1;
1237                      my $beg    = $2;                      my $beg    = $2;
1238                      my $end = $3;                      my $end = $3;
1239                      my $contigO = new ContigO($figO,$self->genome,$contig);  
1240                        #...Create new ContigO object:
1241                        my $contigO = new ContigO($figO, $self->genome->id, $contig);
1242    
1243                        #...Extract DNA subsequence, including guard regions:
1244                      my $begA = &max(1,$beg - $adjL);                      my $begA = &max(1,$beg - $adjL);
1245                      my $endA = &min($end+$adjR,$contigO->contig_length);                      my $endA = &min($end+$adjR,$contigO->contig_length);
1246                      my $dna  = $contigO->dna_seq($begA,$endA);                      my $dna  = $contigO->dna_seq($begA,$endA);
1247                      open(TMP,">$tmp_dir/tmp_dna") || die "couild not open tmp_dna";                      if (defined($dna) && (length($dna) > 90))
1248                        {
1249                            #...Open tmp-file and write FASTA containing DNA subregion to be BLASTed:
1250                            open( TMP, ">$tmp_dir/tmp_dna") || die "could not open tmp_dna";
1251                      print TMP ">dna\n$dna\n";                      print TMP ">dna\n$dna\n";
1252                      close(TMP);                      close(TMP);
1253    
1254                      my $peg2O = new FeatureO($figO,$peg2);                          #...Create new FeatureO object corresponding tp $peg2:
1255                      my $prot  = $peg2O->prot_seq;                          my $pegO2 = new FeatureO($figO,$peg2);
1256    
1257                            #...Fetch its translation, and print to tmp FASTA file for BLASTing:
1258                            my $prot  = $pegO2->prot_seq;
1259                            if (defined($prot) && (length($prot) > 30))
1260                            {
1261                      open(TMP,">$tmp_dir/tmp_prot") || die "could not open tmp_prot";                      open(TMP,">$tmp_dir/tmp_prot") || die "could not open tmp_prot";
1262                      print TMP ">tmp_prot\n$prot\n";                      print TMP ">tmp_prot\n$prot\n";
1263                      close(TMP);                      close(TMP);
1264    
1265                                #...Build BLAST nucleotide database for extracted DNA region,
1266                                #   and TBLASTN $peg2 against the DNA:
1267                      &run("formatdb -i $tmp_dir/tmp_dna -pF");                      &run("formatdb -i $tmp_dir/tmp_dna -pF");
1268                      open(BLAST,"blastall -i $tmp_dir/tmp_prot -d $tmp_dir/tmp_dna -p tblastn -FF -e 1.0e-50 |")                      open(BLAST,"blastall -i $tmp_dir/tmp_prot -d $tmp_dir/tmp_dna -p tblastn -FF -e 1.0e-50 |")
1269                          || die "could not blast";                          || die "could not blast";
1270    
1271                                #...Parse the TBLASTN output; find and sort HSPs by left boundary:
1272                      my $db_seq_out = &gjoparseblast::next_blast_subject(\*BLAST,1);                      my $db_seq_out = &gjoparseblast::next_blast_subject(\*BLAST,1);
1273                      my @hsps       = sort { $a->[0] <=> $b->[0] }                      my @hsps       = sort { $a->[0] <=> $b->[0] }
1274                                       map { [$_->[9],$_->[10],$_->[12],$_->[13]] }                                       map { [$_->[9],$_->[10],$_->[12],$_->[13]] }
1275                                       grep { $_->[1] < 1.0e-50 }                                       grep { $_->[1] < 1.0e-50 }
1276                                       @{$db_seq_out->[6]};                                       @{$db_seq_out->[6]};
1277    
1278                                #...Extract HSP boundary pairs:
1279                      my @prot = map { [$_->[0],$_->[1]] } @hsps;                      my @prot = map { [$_->[0],$_->[1]] } @hsps;
1280                      my @dna  = map { [$_->[2],$_->[3]] } @hsps;                      my @dna  = map { [$_->[2],$_->[3]] } @hsps;
1281                      if (&covers(\@prot,length($prot),3) && &covers(\@dna,3*length($prot),9))  
1282                                #...If the "cover" of the HSPs covers more than 90% of $peg2 w gaps < 3 AA,
1283                                #   and the "cover" of the HPSs cover more than 90% of the extracted DNA
1284                                #   w/ gaps < 9 bp (but not a multiple of 3), suspect a possible frameshift:
1285                                if (&covers(\@prot,length($prot),3,0) && &covers(\@dna,3*length($prot),9,1))
1286                      {                      {
1287                          return 1;                          return 1;
1288                      }                      }
# Line 784  Line 1290 
1290              }              }
1291          }          }
1292      }      }
1293            }
1294        }
1295      return 0;      return 0;
1296  }  }
1297    
# Line 791  Line 1299 
1299    
1300  =head3 run  =head3 run
1301    
1302    (Note: This function should be considered "PRIVATE")
1303    
1304    =over 4
1305    
1306    =item FUNCTION:
1307    
1308    Passes a string containing a command to be execture by the "system" shell command.
1309    
1310    =item USAGE:
1311    
1312    C<< $feature->run($cmd); >>
1313    
1314    =item RETURNS:
1315    
1316    Nil if the execution of C<$cmd> was successful;
1317    aborts with traceback if C<$cmd> fails.
1318    
1319    =back
1320    
1321  =cut  =cut
1322    
1323  sub run {  sub run {
1324      my($cmd) = @_;      my($cmd) = @_;
1325      (system($cmd) == 0) || Confess("FAILED: $cmd");      (system($cmd) == 0) || confess("FAILED: $cmd");
1326  }  }
1327    
1328    
1329    
1330  =head3 max  =head3 max
1331    
1332    (Note: This function should be considered "PRIVATE")
1333    
1334    =over 4
1335    
1336    =item USAGE:
1337    
1338    C<< my $max = $feature->max($x, $y); >>
1339    
1340    =item C<$x> and  C<$y>
1341    
1342    Numerical values.
1343    
1344    =item RETURNS:
1345    
1346    The larger of the two numerical values C<$x> and C<$y>.
1347    
1348    =back
1349    
1350  =cut  =cut
1351    
1352  sub max {  sub max {
# Line 813  Line 1358 
1358    
1359  =head3 min  =head3 min
1360    
1361    (Note: This function should be considered "PRIVATE")
1362    
1363    =over 4
1364    
1365    =item USAGE:
1366    
1367    C<< my $min = $feature->min($x, $y); >>
1368    
1369    =item C<$x> and C<$y>
1370    
1371    Numerical values.
1372    
1373    =item RETURNS:
1374    
1375    The smaller of the two numerical values C<$x> and C<$y>.
1376    
1377    =back
1378    
1379  =cut  =cut
1380    
1381  sub min {  sub min {
# Line 824  Line 1387 
1387    
1388  =head3 covers  =head3 covers
1389    
1390    (Question: Should this function be considered "PRIVATE" ???)
1391    
1392    USAGE:
1393        C<< if (&covers(\@hits, $len, $diff, $must_shift)) { #...Do stuff } >>
1394    
1395    Returns boolean C<TRUE> if a set of BLAST HSPs "cover" more than 90%
1396    of the database sequence(?).
1397    
1398  =cut  =cut
1399    
1400  sub covers {  sub covers {
1401      my($hsps,$ln,$diff) = @_;      my($hsps,$ln,$diff,$must_shift) = @_;
1402    
1403      my $hsp1 = shift @$hsps;      my $hsp1 = shift @$hsps;
1404      my $hsp2;      my $hsp2;
1405      while ($hsp1 && ($hsp2 = shift @$hsps) && ($hsp1 = &merge($hsp1,$hsp2,$diff))) {}      my $merged = 0;
1406      return ($hsp1 && (($hsp1->[1] - $hsp1->[0]) > (0.9 * $ln)));      while ($hsp1 && ($hsp2 = shift @$hsps) &&
1407               ($must_shift ? &diff_frames($hsp1,$hsp2) : 1) &&
1408               ($hsp1 = &merge($hsp1,$hsp2,$diff))) { $merged = 1 }
1409        return ($merged && $hsp1 && (($hsp1->[1] - $hsp1->[0]) > (0.9 * $ln)));
1410    }
1411    
1412    sub diff_frames {
1413        my($hsp1,$hsp2) = @_;
1414        return (($hsp1->[0] % 3) != ($hsp2->[0] % 3));
1415  }  }
1416    
1417    
1418    
1419  =head3 merge  =head3 merge
1420    
1421    Merge two HSPs unless their overlap or separation is too large.
1422    
1423    RETURNS: Merged boundaries if merger succeeds, and C<undef> if merger fails.
1424    
1425  =cut  =cut
1426    
1427  sub merge {  sub merge {
# Line 853  Line 1436 
1436    
1437  =head3 sims  =head3 sims
1438    
1439    =over 4
1440    
1441    =item FUNCTION:
1442    
1443    Returns precomputed "Sim.pm" objects from the SEED.
1444    
1445    =item USAGE:
1446    
1447    C<< my @sims = $pegO->sims( -all, -cutoff => 1.0e-10); >>
1448    
1449    C<< my @sims = $pegO->sims( -max => 50, -cutoff => 1.0e-10); >>
1450    
1451    =item RETURNS: List of sim objects.
1452    
1453    =back
1454    
1455  =cut  =cut
1456    
1457  use Sim;  use Sim;
# Line 863  Line 1462 
1462      my $fig  = $figO->{_fig};      my $fig  = $figO->{_fig};
1463    
1464      my $cutoff = $args{-cutoff} ? $args{-cutoff} : 1.0e-5;      my $cutoff = $args{-cutoff} ? $args{-cutoff} : 1.0e-5;
1465      my $all    = $args{-all}    ? $args{-all}    : "fig";      my $all    = $args{-all}    ? 'all'          : "fig";
1466      my $max    = $args{-max}    ? $args{-max}    : 10000;      my $max    = $args{-max}    ? $args{-max}    : 10000;
1467    
1468      return $fig->sims($self->id,$max,$cutoff,$all);      my @sims = $fig->sims($self->id,$max,$cutoff,$all);
1469    
1470        if (@sims) {
1471            my $peg1 = FeatureO->new($figO, $sims[0]->[0]);
1472    
1473            foreach my $sim (@sims) {
1474    #           $sim->[0] = $peg1;
1475    #           $sim->[1] = FeatureO->new($figO, $sim->[1]);
1476            }
1477        }
1478    
1479        return @sims;
1480  }  }
1481    
1482    
1483    
1484  =head3 bbhs  =head3 bbhs
1485    
1486    =over 4
1487    
1488    =item FUNCTION:
1489    
1490    Given a PEG-type "FeatureO" object, returns the list of BBHO objects
1491    corresponding to the pre-computed BBHs for that PEG.
1492    
1493    =item USAGE:
1494    
1495    C<< my @bbhs = $pegO->bbhs(); >>
1496    
1497    =item RETURNS:
1498    
1499    List of BBHO objects.
1500    
1501    =back
1502    
1503  =cut  =cut
1504    
1505  sub bbhs {  sub bbhs {
# Line 890  Line 1517 
1517                                                  },'BBHO') } @bbhs;                                                  },'BBHO') } @bbhs;
1518  }  }
1519    
1520    
1521  =head3 display  =head3 display
1522    
1523    =over 4
1524    
1525    =item FUNCTION:
1526    
1527    Prints info about a "FeatureO" object to STDOUT.
1528    
1529    =item USAGE:
1530    
1531    C<< $pegO->display(); >>
1532    
1533    =item RETURNS;
1534    
1535    (void)
1536    
1537    =back
1538    
1539  =cut  =cut
1540    
1541  sub display {  sub display {
# Line 910  Line 1554 
1554    
1555  =head1 BBHO  =head1 BBHO
1556    
1557    Methods for accessing "Bidirectiona Best Hits" (BBHs).
1558    
1559  =cut  =cut
1560    
1561    
1562  =head3 new  =head3 new
1563    
1564    Constructor of BBHO objects.
1565    
1566    (NOTE: The "average user" should never need to invoke this method.)
1567    
1568  =cut  =cut
1569    
1570  sub new {  sub new {
# Line 930  Line 1580 
1580  }  }
1581    
1582    
1583    
1584  =head3 peg1  =head3 peg1
1585    
1586    =over 4
1587    
1588    =item USAGE:
1589    
1590    C<< my $peg1 = $bbh->peg1(); >>
1591    
1592    =item RETURNS:
1593    
1594    A "FeatureO" object corresponding to the "query" sequence
1595    in a BBH pair.
1596    
1597    =back
1598    
1599  =cut  =cut
1600    
1601  sub peg1 {  sub peg1 {
# Line 943  Line 1607 
1607    
1608  =head3 peg2  =head3 peg2
1609    
1610    =over 4
1611    
1612    =item USAGE:
1613    
1614    C<< my $peg2 = $bbh->peg2(); >>
1615    
1616    =item RETURNS:
1617    
1618    A "FeatureO" object corresponding to the "database" sequence
1619    in a BBH pair.
1620    
1621    =back
1622    
1623  =cut  =cut
1624    
1625  sub peg2 {  sub peg2 {
# Line 956  Line 1633 
1633    
1634  =head3 psc  =head3 psc
1635    
1636    =over 4
1637    
1638    =item USAGE:
1639    
1640    C<< my $psc = $bbh->psc(); >>
1641    
1642    =item RETURNS:
1643    
1644    The numerical value of the BLAST E-value for the pair.
1645    
1646    =back
1647    
1648  =cut  =cut
1649    
1650  sub psc {  sub psc {
# Line 968  Line 1657 
1657    
1658  =head3 norm_bitscore  =head3 norm_bitscore
1659    
1660    
1661    =over 4
1662    
1663    =item USAGE:
1664    
1665    C<< my $bsc = $bbh->norm_bitscore(); >>
1666    
1667    =item RETURNS:
1668    
1669    The "BLAST bit-score per aligned character" for the pair.
1670    
1671    =back
1672    
1673  =cut  =cut
1674    
1675  sub norm_bitscore {  sub norm_bitscore {
# Line 984  Line 1686 
1686    
1687  =head1 AnnotationO  =head1 AnnotationO
1688    
1689    Methods for accessing SEED annotations.
1690    
1691  =cut  =cut
1692    
1693    
1694    
1695  =head3 new  =head3 new
1696    
1697    =over 4
1698    
1699    =item FUNCTION:
1700    
1701    Cronstruct a new "AnnotationO" object
1702    
1703    =item USAGE:
1704    
1705    C<< my $annotO = AnnotationO->new( $fid, $timestamp, $who, $text); >>
1706    
1707    =item C<$fid>
1708    
1709    A feature identifier.
1710    
1711    =item C<$timestamp>
1712    
1713    The C<UN*X> timestamp one wishes to associate with the annotation.
1714    
1715    =item C<$who>
1716    
1717    The annotator's user-name.
1718    
1719    =item C<$text>
1720    
1721    The textual content of the annotation.
1722    
1723    =item RETURNS:
1724    
1725    An "AnnotationO" object.
1726    
1727    =back
1728    
1729  =cut  =cut
1730    
1731  sub new {  sub new {
# Line 1007  Line 1743 
1743    
1744  =head3 fid  =head3 fid
1745    
1746    =over 4
1747    
1748    =item FUNCTION:
1749    
1750    Extract the feature-ID that was annotated.
1751    
1752    =item USAGE:
1753    
1754    C<< my $fid = $annotO->fid(); >>
1755    
1756    =item RETURNS;
1757    
1758    The feature-ID as a string.
1759    
1760    =back
1761    
1762  =cut  =cut
1763    
1764  sub fid {  sub fid {
# Line 1019  Line 1771 
1771    
1772  =head3 timestamp  =head3 timestamp
1773    
1774    =over 4
1775    
1776    =item FUNCTION:
1777    
1778    Extract the C<UN*X> timestamp of the annotation.
1779    
1780    =item USAGE:
1781    
1782    C<< my $fid = $annotO->timestamp(); >>
1783    
1784    =item RETURNS;
1785    
1786    The timestamp as a string.
1787    
1788    =back
1789    
1790  =cut  =cut
1791    
1792  sub timestamp {  sub timestamp {
# Line 1038  Line 1806 
1806    
1807  =head3 made_by  =head3 made_by
1808    
1809    =over 4
1810    
1811    =item FUNCTION:
1812    
1813    Extract the annotator's user-name.
1814    
1815    =item USAGE:
1816    
1817    C<< my $fid = $annotO->made_by(); >>
1818    
1819    =item RETURNS;
1820    
1821    The username of the annotator, as a string.
1822    
1823    =back
1824    
1825  =cut  =cut
1826    
1827  sub made_by {  sub made_by {
# Line 1052  Line 1836 
1836    
1837  =head3 text  =head3 text
1838    
1839    =over 4
1840    
1841    =item FUNCTION:
1842    
1843    Extract the text of the annotation.
1844    
1845    =item USGAE:
1846    
1847    C<< my $text = $annotO->text(); >>
1848    
1849    =item RETURNS:
1850    
1851    The text of the annotation, as a string.
1852    
1853    =back
1854    
1855  =cut  =cut
1856    
1857  sub text {  sub text {
# Line 1064  Line 1864 
1864    
1865  =head3 display  =head3 display
1866    
1867    =over 4
1868    
1869    =item FUNCTION:
1870    
1871    Print the contents of an "AnnotationO" object to B<STDOUT>
1872    in human-readable form.
1873    
1874    =item USAGE:
1875    
1876    C<< my $annotO->display(); >>
1877    
1878    =item RETURNS:
1879    
1880    (void)
1881    
1882    =back
1883    
1884  =cut  =cut
1885    
1886  sub display {  sub display {
# Line 1079  Line 1896 
1896  ########################################################################  ########################################################################
1897  use Data::Dumper;  use Data::Dumper;
1898    
1899    =head1 CouplingO
1900    
1901    Methods for accessing the "Functional coupling scores"
1902    of PEGs in close physical proximity to each other.
1903    
1904    =cut
1905    
1906    
1907    
1908  =head3 new  =head3 new
1909    
1910    =over 4
1911    
1912    =item FUNCTION:
1913    
1914    Construct a new "CouplingO" object
1915    encapsulating the "functional coupling" score
1916    between a pair of features in some genome.
1917    
1918    =item USAGE:
1919    
1920    C<< $couplingO = CouplingO->new($figO, $fid1, $fid2, $sc); >>
1921    
1922    =item C<$figO>
1923    
1924    Parent "FIGO" object.
1925    
1926    =item C<$fid1> and C<$fid2>
1927    
1928    A pair of feature-IDs.
1929    
1930    =item C<$sc>
1931    
1932    A functional-coupling score
1933    
1934    =item RETURNS:
1935    
1936    A "CouplingO" object.
1937    
1938    =back
1939    
1940  =cut  =cut
1941    
1942  sub new {  sub new {
# Line 1100  Line 1956 
1956    
1957  =head3 peg1  =head3 peg1
1958    
1959    =over 4
1960    
1961    =item FUNCTION:
1962    
1963    Returns a "FeatureO" object corresponding to the first FID in a coupled pair.
1964    
1965    =item USAGE:
1966    
1967    C<< my $peg1 = $couplingO->peg1(); >>
1968    
1969    =item RETURNS:
1970    
1971    A "FeatureO" object.
1972    
1973    =back
1974    
1975  =cut  =cut
1976    
1977  sub peg1 {  sub peg1 {
# Line 1111  Line 1983 
1983    
1984    
1985    
1986  =head3 peg1  =head3 peg2
1987    
1988    =over 4
1989    
1990    =item FUNCTION:
1991    
1992    Returns a "FeatureO" object corresponding to the second FID in a coupled pair.
1993    
1994    =item USAGE:
1995    
1996    C<< my $peg2 = $couplingO->peg2(); >>
1997    
1998    =item RETURNS:
1999    
2000    A "FeatureO" object.
2001    
2002    =back
2003    
2004  =cut  =cut
2005    
# Line 1126  Line 2014 
2014    
2015  =head3 sc  =head3 sc
2016    
2017    =over 4
2018    
2019    =item FUNCTION:
2020    
2021    Extracts the "functional coupling" score from a "CouplingO" object.
2022    
2023    =item USAGE:
2024    
2025    C<< my $sc = $couplingO->sc(); >>
2026    
2027    =item RETURNS:
2028    
2029    A scalar score.
2030    
2031    =back
2032    
2033  =cut  =cut
2034    
2035  sub sc {  sub sc {
# Line 1138  Line 2042 
2042    
2043  =head3 evidence  =head3 evidence
2044    
2045    =over 4
2046    
2047    =item FUNCTION:
2048    
2049    Fetch the evidence for a "functional coupling" between two close PEGs,
2050    in the form of a list of objects describing the "Pairs of Close Homologs" (PCHs)
2051    supporting the existence of a functional coupling between the two close PEGs.
2052    
2053    =item USAGE:
2054    
2055    C<< my $evidence = $couplingO->evidence(); >>
2056    
2057    =item RETURNS
2058    
2059    List of pairs of "FeatureO" objects.
2060    
2061    =back
2062    
2063  =cut  =cut
2064    
2065  sub evidence {  sub evidence {
# Line 1146  Line 2068 
2068      my $figO = $self->{_figO};      my $figO = $self->{_figO};
2069      my $fig  = $figO->{_fig};      my $fig  = $figO->{_fig};
2070      my @ev = ();      my @ev = ();
2071      foreach my $tuple ($fig->coupling_evidence($self->peg1,$self->peg2))      foreach my $tuple ($fig->coupling_evidence($self->peg1->id,$self->peg2->id))
2072      {      {
2073          my($peg3,$peg4,$rep) = @$tuple;          my($peg3,$peg4,$rep) = @$tuple;
2074          push(@ev,[&FeatureO::new('FeatureO',$figO,$peg3),          push(@ev,[&FeatureO::new('FeatureO',$figO,$peg3),
# Line 1160  Line 2082 
2082    
2083  =head3 display  =head3 display
2084    
2085    =over 4
2086    
2087    =item FUNCTION:
2088    
2089    Print the contents of a "CouplingO" object to B<STDOUT> in human-readable form.
2090    
2091    =item USAGE:
2092    
2093    C<< $couplingO->display(); >>
2094    
2095    =item RETURNS:
2096    
2097    (Void)
2098    
2099    =back
2100    
2101  =cut  =cut
2102    
2103  sub display {  sub display {
# Line 1212  Line 2150 
2150    
2151  =head3 usable  =head3 usable
2152    
2153    
2154  =cut  =cut
2155    
2156  sub usable {  sub usable {
# Line 1312  Line 2251 
2251    
2252  =head1 FunctionalRoleO  =head1 FunctionalRoleO
2253    
2254    Methods for accessing the functional roles of features.
2255    
2256  =cut  =cut
2257    
2258    
# Line 1408  Line 2349 
2349      my $famO = $self->{_famO};      my $famO = $self->{_famO};
2350      if (! $famO) { $famO = $self->{_famO} = &FigFam::new('FigFam',$fig,$self->id) }      if (! $famO) { $famO = $self->{_famO} = &FigFam::new('FigFam',$fig,$self->id) }
2351    
2352      return map { &FigFamO::new('FigFamO',$figO,$_) } $famO->list_members;      return map { &FeatureO::new('FeatureO',$figO,$_) } $famO->list_members;
2353  }  }
2354    
   
   
2355  =head3 rep_seqs  =head3 rep_seqs
2356    
2357  =cut  =cut
# Line 1464  Line 2403 
2403  ########################################################################  ########################################################################
2404  =head1 Attribute  =head1 Attribute
2405    
2406    (Note yet implemented.)
2407    
2408  =cut  =cut
2409    
2410  1;  1;

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.26

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3