These documents are For the HEAD of the CVS repository on July 19, 2007 Api docs for previous releases

Modware

Feature

Summary Included libraries Package variables Synopsis Description General documentation Methods

Summary
   Modware::Feature - Base class for all Modware::Feature::* classes.  Probably the most important class in Modware!
Package variables top
Privates (from my definitions)
$feat_ids = {}
Included modulestop
Bio::SeqIO
Chado::AutoDBI
Data::Dumper
IO::String
List::Compare
Modware::Config
Modware::Constant
Modware::Has_synonyms
Modware::Protein_info
Modware::Root
Inherit top
Modware::Has_synonyms Modware::Root
Synopsistop
  #
# The following code shows how to use the object.

# USE CASE: retreive a feature and print its type, then all of its qualifiers
my $feature = new Modware::Feature( -primary_id => 'DDB0191090' );
print $feature->type()."\n";
foreach my $qualifier ( @{$feature->qualifiers()} ) {
print "\t".$qualifier."\n";
}

# USE CASE: print primary_id of all ESTs whose alignment overlap this feature
my $feature = new Modware::Feature( -primary_id => 'DDB0191090' );
my @ests = grep{ $_->type() eq 'EST' } $feature->overlapping_aligned();
foreach my $est (@ests) {
print $est->primary_id()."\n";
}
Descriptiontop
   Creating features in this way automatically returns the proper subclass appropriate
for that gene. In other words if the primary_id passed in is a contig, you'll get a
Modware::Feature::CONTIG object, if its an mRNA youll get a Modware::Feature::MRNA object.

YOU SHOULD NOT CALL new Modware::Feature::CONTIG( -dicytbasid => DDBXXXXXX )
OR new Modware::Feature::MRNA( -dicytbasid => DDBXXXXXX ), ONLY USE THE Modware::Feature
object to create new features.

An error will be thrown for a nonexistent primary_id

A feature object is initially pretty bare, it only contains information contained in
the feature table and the dbxref table linked by dbxref_id in the feature table. The object
is popuplated with more data only as needed: most data attached to a feature is 'lazy evaluated'

two constructors new and _new

_new is private, only other packages (not client scripts) can call.
it is used for creating new objects from scratch
(not from feature_id or primary_id).
Methodstop
_database_objectDescriptionCode
_delete_featurepropDescriptionCode
_featurelocDescriptionCode
_formatted_seqDescriptionCode
_get_bioperlDescriptionCode
_get_derived_fromDescriptionCode
_get_external_idsDescriptionCode
_get_featurepropDescriptionCode
_get_featureprops_of_typeDescriptionCode
_get_geneDescriptionCode
_get_qualifiersDescriptionCode
_get_reference_featureDescriptionCode
_get_sourceDescriptionCode
_get_strandNo descriptionCode
_get_supported_byDescriptionCode
_get_synonymsDescriptionCode
_initDescriptionCode
_insert_featureDescriptionCode
_insert_featurelocDescriptionCode
_insert_or_update_featurepropDescriptionCode
_insert_or_update_subfeatureDescriptionCode
_insert_sourceDescriptionCode
_insert_subfeatureDescriptionCode
_relationship_objectsDescriptionCode
_relationship_subjectsDescriptionCode
_subfeature_uniquenameDescriptionCode
_update_external_idsDescriptionCode
_update_featureDescriptionCode
_update_featurelocDescriptionCode
_update_gene_associationDescriptionCode
_update_multivalue_featurepropDescriptionCode
_update_qualifiersDescriptionCode
_update_synonymsDescriptionCode
add_derived_fromDescriptionCode
add_external_idDescriptionCode
add_qualifierDescriptionCode
add_supported_byDescriptionCode
bioperlDescriptionCode
cached_sequencesDescriptionCode
chromosomeDescriptionCode
contigDescriptionCode
delete_from_cacheDescriptionCode
derived_fromDescriptionCode
descriptionDescriptionCode
display_typeDescriptionCode
endDescriptionCode
external_idsDescriptionCode
feature_idDescriptionCode
geneDescriptionCode
has_qualifierDescriptionCode
insertDescriptionCode
is_deletedDescriptionCode
nameDescriptionCode
newNo descriptionCode
organism_nameDescriptionCode
overlapping_alignedDescriptionCode
overlapping_cdsDescriptionCode
primary_idDescriptionCode
qualifiersDescriptionCode
reference_featureDescriptionCode
remove_derived_fromDescriptionCode
remove_external_idDescriptionCode
remove_qualifierDescriptionCode
remove_supported_byDescriptionCode
replaced_byDescriptionCode
sequenceDescriptionCode
sourceDescriptionCode
startDescriptionCode
strandDescriptionCode
subfeaturesDescriptionCode
supported_byDescriptionCode
typeDescriptionCode
updateDescriptionCode

Methods description

_database_objectcodetopprevnext
 Title    : _database_object
Usage : my $ids = $self->_database_object($database_object);
Function : gets/sets the Modware::Dbtable::Feature object
used to read/write from the database
Returns : Modware::Dbtable::Feature object
Args : optional: reference to a Modware::Dbtable::Feature
_delete_featurepropcodetopprevnext
 Title    : _delete_featureprop
Usage : my $descriptions = $feature->_delete_featureprop( 'some property' );
Function : deletes a record from featureprop
NOTE : THIS IS ONLY FOR SINGLE VALUED FEATUREPROPS!!!!!!!!!
Returns : nothing
Args : property to delete
_featureloccodetopprevnext
 Title    : _featureloc
Usage : to update the start position in the database:
: $self->_featureloc->fmin( 100 );
: this object is PRIVATE
Function : gets the FEATURELOC representing position on chromosome
Returns : Chado::Featureloc object
Args : nothing
_formatted_seqcodetopprevnext
 Title    : _formatted_seq
Function : given a sequence, header, and a header, will write a sequence in a given format
Returns : string
Args : ref to sequence, format
_get_bioperlcodetopprevnext
 Title    : _get_bioperl
Usage : Interface mehtod
Function : requires subclasses to implement this method
Returns : nothing
Args : none
_get_derived_fromcodetopprevnext
 Title    : _get_derived_from
Usage : $gene->_get_derived_from();
Function : gets array of supported by evideince
Returns : nothing
Args : none
_get_external_idscodetopprevnext
 Title    : _get_external_ids
Usage : $feature->_get_external_ids();
Function : gets the external_ids object for this feature (called from external_ids)
Returns : nothing
Args : none
_get_featurepropcodetopprevnext
 Title    : _get_featureprop
Usage : my $descriptions = $feature->_get_featureprop( 'description' );
Function : returns a single valued featureprop
NOTE : THIS IS ONLY FOR SINGLE VALUED FEATUREPROPS!!!!!!!!!
Returns : featureprop value
Args : property requested
_get_featureprops_of_typecodetopprevnext
 Title    : _get_featureprops_of_type
Usage : $gene->_get_featureprops_of_type('supported by');
Function : gets array of feature qualifiers ( currently modeled as strings)
Returns : arrayref of strings
Args : featureprop type
_get_genecodetopprevnext
 Title    : _get_gene
Usage : $feature->_get_gene();
Function : gets the gene object for this feature (called from gene)
: gets features which are the 'object' of a 'part_of'
Returns : nothing
Args : none
_get_qualifierscodetopprevnext
 Title    : _get_qualifiers
Usage : $gene->_get_qualifiers();
Function : gets array of feature qualifiers ( currently modeled as strings)
Returns : nothing
Args : none
_get_reference_featurecodetopprevnext
 Title    : _get_reference_feature
Usage : $feature->_get_reference_feature();
Function : gets the reference_feature object for this feature (called from reference_feature)
Returns : nothing
Args : none
_get_sourcecodetopprevnext
 Title    : _get_source
Usage : $feature->_get_source();
Function : gets the source from the dbxref table
NOTE : THIS SHOULD ONLY BE CALLED BY internally
Returns : source
Args : nothing
_get_supported_bycodetopprevnext
 Title    : _get_supported_by
Usage : $gene->_get_supported_by();
Function : gets array of supported by evdidnece
Returns : nothing
Args : none
_get_synonymscodetopprevnext
 Title    : _get_synonyms
Usage : $gene->_get_synonyms();
Function : gets the synonyms for this gene ( arrayref of strings )
Returns : nothing
Args : none
_initcodetopprevnext
 Title    : _init
Usage : called from new
Function : interface method to be implemented in subclasses
: purpose is add specific initialization to subclasses
Returns : nothing
Args : nothing
_insert_featurecodetopprevnext
 Title    : _insert_feature
Function : inserts into feature table, gives primary_id as dbxrefid, name, and uniquename
Returns : nothing
Args : none
_insert_featureloccodetopprevnext
 Title    : _insert_featureloc
Function : inserts entry into the featureloc table for this feature
:
Returns : nothing
Args : none
_insert_or_update_featurepropcodetopprevnext
 Title    : _insert_or_update_featureprop
Usage : $feature->_insert_or_update_featureprop( 'created by', $ENV{'USER'} );
Function : creates ( or updates ) featureprop
NOTE : THIS IS ONLY FOR SINGLE VALUED FEATUREPROPS!!!!!!!!!
Returns : nothing
Args : property type, property value
_insert_or_update_subfeaturecodetopprevnext
 Title    : _insert_or_update_subfeature
Function : attempts to resolve a subfeature
: to an object in the database
:
Returns : nothing
Args : location object (start, end, strand), SO type of subfeature
_insert_sourcecodetopprevnext
 Title    : _insert_source
Usage : $feature->_insert_source();
Function : inserts the source into the dbxref table
NOTE : THIS SHOULD ONLY BE CALLED BY 'insert' method internally
Returns : nothing
Args : nothing
_insert_subfeaturecodetopprevnext
 Title    : _insert_subfeature
Function : inserts an exon and the appropriate feature relationship into the database
:
Returns : feature_id of subfeature
Args : SO type of subfeature
_relationship_objectscodetopprevnext
 Title    : relationship_objects
Usage : my @features = $feature->relationship_objects('part_of');
Function : gets features which are the 'object' of a specified relationship type
: relationship with this feature as the 'subject'
Returns : array of Chado::Feature objects
Args : relationship type
_relationship_subjectscodetopprevnext
 Title    : relationship_subjects
Usage : my @features = $feature->relationship_subjects('part_of');
Function : gets features which are the 'subject' of a specified relationship type
: relationship with this feature as the 'object'
Returns : array of Chado::Feature objects
Args : relationship type
_subfeature_uniquenamecodetopprevnext
 Title    : _subfeature_uniquename
Function : creates a unique name (goes in feature table column)
: for an subfeature ( copied wholesale from gmod_load_gff3.pl )
:
Returns : unique name for exon (string )
Args : exon location object
_update_external_idscodetopprevnext
 Title    : _update_external_ids
Function : loops through external ids associated feature
: if an external id exists for this source for a given feature, update it
: otherwise, insert it
Returns : nothing
Args : none
_update_featurecodetopprevnext
 Title    : update_feature
Function : updates feature table
Returns : nothing
Args : none
_update_featureloccodetopprevnext
 Title    : _update_featureloc
Function : updates the featureloc table with start and stop of feature
:
Returns : nothing
Args : none
_update_gene_associationcodetopprevnext
 Title    : _update_gene_association
Usage :
Function : associates this feature with a particular gene
:
Returns : nothing
Args : nothing
_update_multivalue_featurepropcodetopprevnext
 Title    : _update_multivalue_featureprop
:
Function : some of the things stored in featureprop can have more than one value
: for example, the 'supported by' array holds strings describing
: the evidence supporting a curated model
:
: These are typically modeled as arrays of strings ( the database identifiers are
: irrelevant ) and contain discreet values. This method is not used for
: something like 'notes' which does not contain discreet values and do have
: a database identifier passed around with them.
:
: This method takes care of updating these types of values and keeping their order
:
Usage : $self->_update_multivalue_featureprop( 'supported by', $self->supported_by() );
:
Returns : nothing
Args : none
_update_qualifierscodetopprevnext
 Title    : _update_qualifiers
Function : updates all 'qualifiers'
: compares list from database to current qualifier list, inserts/deletes as necessary
Returns : nothing
Args : none
_update_synonymscodetopprevnext
 Title    : _update_synonyms
Function : adds/links/unlinks synonyms from this gene
: compares list from database to current gene product list, inserts/deletes as necessary
Returns : nothing
Args : none
add_derived_fromcodetopprevnext
 Title    : add_derived_from
Usage : $feature->add_derived_from( 'Pseudogene' );
Function : adds a derived_from to the derived_from array
: does nothing if derived_from already exists
Returns : nothing
Args : name of derived_from to remove ( string )
add_external_idcodetopprevnext
 Title    : add_external_id
Usage : $feature->add_external_id( -source => 'Accession Number', -id => '122345' );
Function : adds an external id to the external_ids hash
Returns : nothing
Args : named:
: -source => the name of the db_xref
: -id => the ID From the external database
add_qualifiercodetopprevnext
 Title    : add_qualifier
Usage : $feature->add_qualifier( 'Pseudogene' );
Function : adds a qualifier to the qualifier array
: does nothing if qualifier already exists
Returns : nothing
Args : name of qualifier to remove ( string )
add_supported_bycodetopprevnext
 Title    : add_supported_by
Usage : $feature->add_supported_by( 'Pseudogene' );
Function : adds a supported_by to the supported_by array
: does nothing if supported_by already exists
Returns : nothing
Args : name of supported_by to remove ( string )
bioperlcodetopprevnext
 Title    : bioperl
Note : Fetches the bioperl object associated with this feature
: This is lazy evaluated
: each feature type will have its own _get_bioperl method
Usage : To print the bioperl name of the bioperl that this feature belongs to
: print $self->bioperl->bioperl_name();
Function : gets/sets the bioperl attribute of the feature
Returns : a Bio::SeqFeatureI implementing object
Args : optional: bioperl object
cached_sequencescodetopprevnext
 Title    : cached_sequences
Note : Fetches cached_sequences ( i.e. transcript, genomic, cds ) for this feature
: This is lazy evaluated
Usage : To print a list of sequneces:
: foreach my $seq_type ( keys %{$self->cached_sequences} ) {
: print $seq_type."\t".$self->cached_sequences->{$seq_type}."\n";
: }
Function : Calculates all available sequences and stores in a hash.
: Useful for comparing state of feature before and after a genome change
: so you could call cached_sequences(), then apply some change
: then compare the sequences in cached_sequences vs. the sequences
: calculated by caluculate_SOME_seq().
Returns : cached_sequences object ( hashref keyed on source)
Args : none
chromosomecodetopprevnext
 Title    : chromosome
Note : DEPRECATED
Function : defers to reference_feature method
Returns : Modware::Feature::Reference_feature
Args : optional: Modware::Feature::Reference_feature object
contigcodetopprevnext
 Title    : contig
Function : gets contig that this feature is enclosed on
Returns : Modware::Feature::CONTIG feature
Args : none
delete_from_cachecodetopprevnext
 Title    : delete_from_cache
Function : Some features types (i.e. chromosomes) are singletons -- they are cached and
: the cached obect is returned when 'new' is called. Sometimes this behavior is not
: desireable. This method deletes the cache.
Returns : nothing
Args : none
derived_fromcodetopprevnext
 Title    : derived_from
Note : derived_from are additional descriptors for a feature
: a feature can have 0..* derived_from ( deleted, dubious, questionable etc. )
Usage : my @derived_from = @{ $self->derived_from() };
: or
: $self->derived_from( \@array_of_derived_from)
Function : returns reference to array of feature derived_from
Returns : reference to array of feature types
Args : reference to array of feature types ( optional )
descriptioncodetopprevnext
 Title    : description
Note : Brief description of feature
Function : gets the description of the feature
Returns : string
Args : optional: description string
display_typecodetopprevnext
 Title    : display_type
Note : while SO is useful for describing the type of feature
: sometimes it is useful to be more descriptive:
: ie. 'Curated Model' and 'Gene Prediction From Sequencing Center'
:
: IF THEERE IS NO DISPLAY_TYPE WILL RETURN uppercased $SELF->TYPE!!!!!!!!!!!!!!
:
Function : gets/sets the display_type of the feature
Returns : string
Args : string (optional)
endcodetopprevnext
 Title    : end
Usage : Interface method, different subclasses will have different
: methods for determining 'end'. Aligned (blasted) features will look at
: the bioperl_alignment coordinates, cdss will look at the bioperl object
Function : requires subclasses to implement this method
Returns : nothing
Args : none
external_idscodetopprevnext
 Title    : external_ids
Note : Fetches the external_ids object associated with this feature
: the external ids object is currently a hasref keyed on
: the external_id's source
: This is lazy evaluated
Usage : To print a list of external_id's:
: foreach my $source ( keys %{$self->external_ids} ) {
: print $source."\t".$self->external_ids->{$source}."\n";
: }
Function : gets/sets the external_ids attribute of the feature
Returns : external_ids object ( hashref keyed on source)
Args : optional: external_ids object ( hashref keyed on source)
feature_idcodetopprevnext
 Title    : feature_id
Usage : $self->feature_id( $some_feature_id );
: or
: print $self->feature_id();
Function : gets/sets feature_id ALSO sets the _database_object to that row in the database
Returns : feature_id string
Args : feature_id ( optional )
genecodetopprevnext
 Title    : gene
Note : Fetches the gene object associated with this feature
: This is lazy evaluated so as to avoid an infinite loop
: of creating a gene which gets a feature which gets its gene
: which gets it feature .....
: May make feature and loci singletons, then use circular refs and 'weaken'
Usage : To print the gene name of the gene that this feature belongs to
: print $self->gene->gene_name();
Function : gets/sets the gene attribute of the feature
Returns : string
Args : optional: gene object
has_qualifiercodetopprevnext
 Title    : has_qualifier
Usage : print "Pseudogene" if $feature->has_qualifier( 'Pseudogene' );
Function : returns true if the feature has this qualifier in its qualifier array
Returns : boolean
Args : name of qualifier ( string )
insertcodetopprevnext
 Title    : insert
Function : inserts into feature table and associated tables in database
Returns : nothing
Args : none
is_deletedcodetopprevnext
 Title    : is_deleted
Note :
Usage : print "THIS IS DELETED" if $self->is_deleted();
Function : returns is_deleted attribute of the feature
Returns : boolean
Args : none
namecodetopprevnext
 Title    : name
Function : the 'name' of the feature. Could be an ID, an aceesion, or a systematic name
Returns : value of 'name' the default (here) being the datbaseID, override if you want another value
Args : none
organism_namecodetopprevnext
 Title    : organism_name
Function : returns the name of the organims that the feature is associated with
:
Returns : nothing
Args : none
overlapping_alignedcodetopprevnext
 Title    : overlapping_aligned
Note : don't like the way that this uses the Dbtable object for chromosome, will have to change this
Usage : To print primary_ids of aligned overlapping this feature :
: map { print $_->primary_id()."\n" } grep { $_->type eq "EST" } $feature->overlapping_aligned()
Function : returns an array of gene models ( curated and sequencing center ) which overlap this feature
Returns : array of features
Args : none
overlapping_cdscodetopprevnext
 Title    : overlapping_cds
Note : don't like the way that this uses the Dbtable object for chromosome, will have to change this
Usage : To print primary_ids of CDSS overlapping this feature :
: map { print $_->primary_id()."\n" } $feature->overlapping_cds()
Function : returns an array of gene models ( curated and sequencing center ) which overlap this feature
Returns : array of features
Args : none
primary_idcodetopprevnext
 Title    : primary_id
Usage : my $primary_id = $self->primary_id();
Function : returns primary_id for this object
Returns : primary_id string
Args : none
qualifierscodetopprevnext
 Title    : qualifiers
Note : qualifiers are additional descriptors for a feature
: a feature can have 0..* qualifiers ( deleted, dubious, questionable etc. )
Usage : my @qualifiers = @{ $self->qualifiers() };
: or
: $self->qualifiers( \@array_of_qualifiers)
Function : returns reference to array of feature qualifiers
Returns : reference to array of feature types
Args : reference to array of feature types ( optional )
reference_featurecodetopprevnext
 Title    : reference_feature
Note : Fetches the reference_feature object associated with this feature
: This is lazy evaluated
Usage : to print reference_feature name
: print $feature->reference_feature->name();
Function : gets/sets the reference_feature attribute of the feature
Returns : Modware::Feature::reference_feature
Args : optional: Modware::Feature::reference_feature object
remove_derived_fromcodetopprevnext
 Title    : remove_derived_from
Usage : $feature->remove_derived_from( 'Corrupted' );
Function : removes a derived_from from the derived_from array
: does nothing if derived_from does not already exist
Returns : nothing
Args : name of derived_from to remove ( string )
remove_external_idcodetopprevnext
 Title    : remove_external_id
Usage : $feature->add_external_id( -source => 'Accession Number' );
Function : removes an external id from the external_ids hash
Returns : nothing
Args : named:
: -source => the name of the db_xref
remove_qualifiercodetopprevnext
 Title    : remove_qualifier
Usage : $feature->remove_qualifier( 'Corrupted' );
Function : removes a qualifier from the qualifier array
: does nothing if qualifier does not already exist
Returns : nothing
Args : name of qualifier to remove ( string )
remove_supported_bycodetopprevnext
 Title    : remove_supported_by
Usage : $feature->remove_supported_by( 'Corrupted' );
Function : removes a supported_by from the supported_by array
: does nothing if supported_by does not already exist
Returns : nothing
Args : name of supported_by to remove ( string )
replaced_bycodetopprevnext
 Title    : replaced_by
Note :
Usage : my $new_feature = new Modware::Feature(
-primary_id => $feature->is_replaced_by()
) if $feature->is_deleted() and $feature->is_replaced_by();
Function : returns primary_id of feature that replaces this one
Returns : primary_id
Args : none
sequencecodetopprevnext
 Title    : sequence
Function : returns sequence of a given type and formats in a given way
Returns : formatted sequence
Args : named arguments
:
: -type => type of sequence ( in display_seq_type )
: -format => string (used by Bio::SeqIO) optional
:
sourcecodetopprevnext
 Title    : source
Note : source is where the feauture came from
: some examples are: Genbank, Sequencing Center, Other Prediction, Curator
Usage : $self->source( 'Sequencing Center' );
: or
: print $self->source();
Function : gets/sets the source attribute of the feature
Returns : string
Args : optional: source string
startcodetopprevnext
 Title    : start
Usage : Interface method, different subclasses will have different
: methods for determining 'start'. Aligned (blasted) features will look at
: the bioperl_alignment coordinates, cdss will look at the bioperl object
Function : requires subclasses to implement this method
Returns : nothing
Args : none
strandcodetopprevnext
 Title    : strand
Function : gets/sets the strand that this feature is on
Returns : (1, -1, undef)
Args : optional (1, -1)
subfeaturescodetopprevnext
 Title    : subfeatures
Usage : my @features = $feature->subfeatures();
Function : gets features which are the 'subject' of a 'part of'
: relationship with this feature as the 'object'
Returns : array of Chado::Feature objects
Args : nothing
supported_bycodetopprevnext
 Title    : supported_by
Note : supported_by are additional descriptors for a feature
: a feature can have 0..* supported_by ( deleted, dubious, questionable etc. )
Usage : my @supported_by = @{ $self->supported_by() };
: or
: $self->supported_by( \@array_of_supported_by)
Function : returns reference to array of feature supported_by
Returns : reference to array of feature types
Args : reference to array of feature types ( optional )
typecodetopprevnext
 Title    : type
Note : Eventually will be a Sequnce ontology (SO) mapped type
: for now just our own types.
: Examples: mRNA, EST, Gene Model
Usage : $self->type( 'mRNA' );
: or
: print $self->type();
Function : gets/sets the type attribute of the feature
Returns : string
Args : optional: type string
updatecodetopprevnext
 Title    : update
Function : updates feature table and associated tables in database
Returns : nothing
Args : none

Methods code

_database_objectdescriptiontopprevnext
sub _database_object {
   my ($self, $obj) = @_;
   if($obj) {
      $self->{_database_object} = $obj;
   }
   return $self->{_database_object};
}
_delete_featurepropdescriptiontopprevnext
sub _delete_featureprop {
   my ($self, $prop) = @_;

   my ($featureprop_term)    = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Feature_property_cv_id(),
      name  => $prop
   );
   my $prop_row = Chado::Featureprop->get_single_row(
      type_id     => $featureprop_term->cvterm_id,
      feature_id  => $self->feature_id
   );

   warn( "deleting $prop for ".$self->feature_id ) if $prop_row && DEBUG;

   $prop_row ? $prop_row->delete() : $self->warn("trying to delete non existent featureprop: $prop.");
}
_featurelocdescriptiontopprevnext
sub _featureloc {
   my ($self, $obj) = @_;

   if ( ! exists $self->{_featureloc} ) {
      $self->{_featureloc} = Chado::Featureloc->get_single_row( feature_id => $self->feature_id );
   }

   return $self->{_featureloc};
}
_formatted_seqdescriptiontopprevnext
sub _formatted_seq {
   my ($self, $sequence, $header, $format) = @_;

   my $str = IO::String->new;
   my $seqobj;
   my $out;

   eval{
      $seqobj      = Bio::Seq->new(
                                  -display_id => $self->primary_id,
                                  -desc       => $header,
                                  -seq        => $$sequence
                     );


      $out = Bio::SeqIO->new( '-format' => $format, -fh =>$str  );
      $out->write_seq( $seqobj );
   };
   if ($@) {
      $self->throw("Eror writing $format sequence for ".$self->primary_id."\n".
                    "header: $header\n$@");
   }

   return  ${ $str->string_ref };
}
_get_bioperldescriptiontopprevnext
sub _get_bioperl {
   my ($self) = @_;
   $self->warn_not_implemented();
}
_get_derived_fromdescriptiontopprevnext
sub _get_derived_from {
   my ($self) = @_;

   $self->derived_from( $self->_get_featureprops_of_type('derived from' ) );
}
_get_external_idsdescriptiontopprevnext
sub _get_external_ids {
   my ($self) = @_;

   my $id_hash = {};

   my @dbxref_rows = Chado::Feature_Dbxref->search(
      feature_id => $self->feature_id
   );

   foreach my $dbxref_row (@dbxref_rows) {

     my $source = $dbxref_row->dbxref->db->name;
     my $id     = $dbxref_row->dbxref->accession;

    #
# the GFF loader adds 'DB:' to the beginning of dbxrefs
#
$source =~ s/^DB://; #
# filter out 'GFF_source' which is stored in dbXref
#
next if $source eq "GFF_source"; $id_hash->{ $source } = $id; } $self->external_ids( $id_hash );
}
_get_featurepropdescriptiontopprevnext
sub _get_featureprop {
   my ($self, $prop) = @_;

   warn( "getting ".$prop." for ".$self->feature_id ) if DEBUG;

   # First check if the property term exists in feature_property cv
# then, check auto_cv (where we put featureprops that don't exist
# in feature_property cv)
my ($prop_term) = Chado::Cvterm->get_single_row( cv_id => Modware::Constant->Feature_property_cv_id(), name => $prop ) || Chado::Cvterm->get_single_row( cv_id => Modware::Constant->Auto_cv_id(), name => $prop ); return undef if !$prop_term; my $prop_row = Chado::Featureprop->get_single_row( type_id => $prop_term->cvterm_id, feature_id => $self->feature_id ); warn( "got ".$prop_row->value() ) if $prop_row && DEBUG; return $prop_row ? $prop_row->value() : undef;
}
_get_featureprops_of_typedescriptiontopprevnext
sub _get_featureprops_of_type {
   my ($self, $type) = @_;


   my ($qualifier_term)    = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Feature_property_cv_id(),
      name  => $type
   );

   my @rows = Chado::Featureprop->search(
     type_id     => $qualifier_term->cvterm_id,
     feature_id => $self->feature_id
   );

   my @values   = map { $_->value } sort { $a->rank() <=> $b->rank() } @rows;

   return\@ values;
}
_get_genedescriptiontopprevnext
sub _get_gene {
   my ($self) = @_;

   return if !$self->_database_object;

   my @superfeatures = $self->_relationship_objects( 'part_of' );

   if ( scalar @superfeatures == 1 && $superfeatures[0]->type_id->name eq 'gene' ) {
      $gene = new Modware::Feature( -feature_id => $superfeatures[0]->feature_id );
      $self->gene( $gene );
   }
}
_get_qualifiersdescriptiontopprevnext
sub _get_qualifiers {
   my ($self) = @_;

   $self->qualifiers( $self->_get_featureprops_of_type('qualifier' ) );
}
_get_reference_featuredescriptiontopprevnext
sub _get_reference_feature {
   my ($self) = @_;

   my $location = $self->_featureloc();

   if ( $location && $location->srcfeature() ) {

      my $ref_object = new Modware::Feature( -feature_id => $location->srcfeature->feature_id );

      $self->reference_feature( $ref_object );

   }
}
_get_sourcedescriptiontopprevnext
sub _get_source {
   my ($self) = @_;

   my $results = Chado::Dbxref->search_source_for_feature( $self->feature_id )->next;

   return $results ? $results->accession() : undef;
}
_get_stranddescriptiontopprevnext
sub _get_strand {
   my ($self, $obj) = @_;



   $self->strand( $self->_featureloc() ? $self->_featureloc()   : undef    ) ;
}
_get_supported_bydescriptiontopprevnext
sub _get_supported_by {
   my ($self) = @_;

   $self->supported_by( $self->_get_featureprops_of_type('supported by' ) );
}
_get_synonymsdescriptiontopprevnext
sub _get_synonyms {
   my ($self) = @_;

   if ( $self->feature_id() ){  # only get from database if gene has been inserted into database
my @feature_synonyms = $self->_database_object()->feature_synonym_feature_id(); my @synonyms = grep { $_ ne $self->name() } map { $_->synonym()->name() } @feature_synonyms; $self->synonyms(\@ synonyms ); } else { # otherwise initialize with empty array
$self->synonyms( [] ); }
}
_initdescriptiontopprevnext
sub _init {
   my ($self, @args) = @_;

   $self->throw_not_implemented();
}
_insert_featuredescriptiontopprevnext
sub _insert_feature {
   my ($self, @args) = @_;

   my $id_dbxref = Modware::DBH->get_public_id();
   $self->primary_id( $id_dbxref->accession );

   my ($cvterm) = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Sequence_ontology_id(),
      name  => $self->type
   );

   $self->throw( "cannot insert a feature with out a valid SO type. (got ".$self->type() .")") if !$cvterm;

   my $type_id    = $cvterm->cvterm_id;

   my $feautre_row = Chado::Feature->create({
     organism_id => Modware::Constant->Organism_id(),
     dbxref_id   => $id_dbxref->dbxref_id,
     name        => $self->name(),
     uniquename  => $id_dbxref->accession,
     type_id     => $type_id,
     is_obsolete => $self->is_deleted() || 0
   });

   $self->feature_id( $feautre_row->feature_id );
}
_insert_featurelocdescriptiontopprevnext
sub _insert_featureloc {
   my ($self, @args) = @_;

   die "Cannot insert featureloc without feature id." if !$self->feature_id();
   $self->warn("Inserting featureloc") if DEBUG;

   my $fmin          = $self->start - 1;    # chado is interbase coordinates
my $fmax = $self->end; my $srcfeature_id = $self->reference_feature() ? $self->reference_feature() : undef; $self->{_featureloc} = Chado::Featureloc->create({ feature_id => $self->feature_id, srcfeature_id => $srcfeature_id, strand => $self->strand(), fmin => $fmin, fmax => $fmax });
}
_insert_or_update_featurepropdescriptiontopprevnext
sub _insert_or_update_featureprop {
   my ($self, $prop, $value) = @_;

   # First check if the property term exists in feature_property cv
# then, check auto_cv (where we put featureprops that don't exist
# in feature_property cv)
my ($prop_term) = Chado::Cvterm->get_single_row( cv_id => Modware::Constant->Feature_property_cv_id(), name => $prop ) || Chado::Cvterm->get_single_row( cv_id => Modware::Constant->Auto_cv_id(), name => $prop ); if ( !$prop_term ) { $self->warn("$prop is not a recognized feature prop, inserting into cv table"); # add the term to the autocreated CV
$prop_term = Chado::Cvterm->create({ cv_id => Modware::Constant->Auto_cv_id(), name => $prop }); } my $record = Chado::Featureprop->get_single_row( type_id => $prop_term->cvterm_id, feature_id => $self->feature_id ); if ( $record && $value ) { eval { $record->value( $value ); $record->update(); }; if ($@) { $self->throw( "error inserting Featureprop with ". Dumper( type_id => $prop_term->cvterm_id, feature_id => $self->feature_id, value => $value, ).$@ ); } } elsif ( $record && !$value ) { $record->delete(); } elsif ($value) { eval { my $record = Chado::Featureprop->create({ type_id => $prop_term->cvterm_id, feature_id => $self->feature_id, value => $value }); warn "inserted $prop : $value for ".$self->feature_id if DEBUG; warn "feautreprop_id = ".$record->featureprop_id if DEBUG; }; if ($@) { $self->throw( "error inserting Featureprop with ". Dumper( type_id => $prop_term->cvterm_id, feature_id => $self->feature_id, value => $value, ).$@ ); } } else { # $self->warn( "Cannot insert a feature prop without a property AND a value. (received prop: $prop and value: $value)") if ( !defined $prop || !defined $value );
}
}
_insert_or_update_subfeaturedescriptiontopprevnext
sub _insert_or_update_subfeature {
   my ($self, $subfeature, $type ) = @_;

   my $location = $subfeature->location();

   my ($cvterm) = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Sequence_ontology_id(),
      name  => $type
   );

   my ($partof_term)    = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Relationship_cv_id(),
      name  => 'part_of'
   );

   $self->throw( "cannot insert a feature with out a valid SO type.") if !$cvterm;

   my $fmin    = $location->start - 1;    # chado is interbase coordinates
my $fmax = $location->end; my $strand = $location->strand; # should return single object
# this might be easier in the future with a
# view that joins featureloc and feature
my @same_location_objs = Chado::Featureloc->search( srcfeature_id => $self->reference_feature->feature_id, strand => $strand, fmin => $fmin, fmax => $fmax ); # should only be one if you are sharing exons
my ($identical_subfeat) = grep{ $_->feature()->type_id() eq $cvterm->cvterm_id() } @same_location_objs; # don't need to do anything,
# just make sure it's correctly linked
# to the current feature and return.
if ($identical_subfeat) { #warn "found $type for ".Dumper($self->gene()->name(),$location)."\n";
Chado::Feature_Relationship->find_or_create({ object_id => $self->feature_id, type_id => $partof_term->cvterm_id, subject_id => $identical_subfeat->feature_id }); # store feature_id for later use
# Modware does not have an exon object so
# use BioPerl's tag system to keep track of it
$subfeature->add_tag_value( 'feature_id', $identical_subfeat->feature_id() ); } else { $self->_insert_subfeature( $subfeature, $type ); }
}
_insert_sourcedescriptiontopprevnext
sub _insert_source {
   my ($self) = @_;

   $self->throw("Need a 'source' to insert a feature.") if !$self->source();

   $gff_source_db = Chado::Db->get_single_row({
      name  => 'GFF_source'
   });

   my $source_xref = Chado::Dbxref->find_or_create({
     db_id     => $gff_source_db->id,
     accession => $self->source(),
   });

   my $feature_dbxref = Chado::Feature_Dbxref->find_or_create({
      feature_id => $self->feature_id,
      dbxref_id  => $source_xref->id
   });
}
_insert_subfeaturedescriptiontopprevnext
sub _insert_subfeature {
   my ($self, $subfeature, $type ) = @_;
   my $location = $subfeature->location();

   my ($cvterm) = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Sequence_ontology_id(),
      name  => $type
   );

   $self->throw( "cannot insert a feature with out a valid SO type.") if !$cvterm;

   my $type_id    = $cvterm->cvterm_id;

   my $uniquename = $self->_subfeature_uniquename( $location, $type );

   my $subfeat_row = Chado::Feature->create({
     organism_id => Modware::Constant->Organism_id(),
     uniquename  => $uniquename,
     seqlen      => $location->length(),
     type_id     => $type_id
   });

   my ($partof_term)    = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Relationship_cv_id(),
      name  => 'part_of'
   );

   Chado::Feature_Relationship->create({
      object_id  => $self->feature_id,
      type_id    => $partof_term->cvterm_id,
      subject_id => $subfeat_row->feature_id
   });

   my $fmin    = $location->start - 1;    # chado is interbase coordinates
my $fmax = $location->end; my $strand = $location->strand; Chado::Featureloc->create({ feature_id => $subfeat_row->feature_id, srcfeature_id => $self->reference_feature->feature_id, strand => $strand, fmin => $fmin, fmax => $fmax }); # store feature_id for later use
# Modware does not have an exon object so
# use BioPerl's tag system to keep track of it
$subfeature->add_tag_value( 'feature_id', $subfeat_row->feature_id() ); return $subfeat_row->feature_id;
}
_relationship_objectsdescriptiontopprevnext
sub _relationship_objects {
   my ($self, $relationship_type) = @_;

   $self->throw("need to pass relationship type to relationship_objects method.") if !$relationship_type;

   my ($rel_type)    = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Relationship_cv_id(),
      name  => $relationship_type
   );

   $self->throw("relationship term $relationship_type not found in database.") if !$rel_type;

   my @feature_relations = Chado::Feature_Relationship->search(
      subject_id => $self->feature_id,
      type_id    => $rel_type->cvterm_id
   );

   my @features = map { $_->object_id  } @feature_relations;

   return @features;
}
_relationship_subjectsdescriptiontopprevnext
sub _relationship_subjects {
   my ($self, $relationship_type) = @_;

   $self->throw("need to pass relationship type to relationship_subjects method.") if !$relationship_type;

   my ($rel_type)    = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Relationship_cv_id(),
      name  => $relationship_type
   );

   $self->throw("relationship term $relationship_type not found in database.") if !$rel_type;

   my @feature_relations = Chado::Feature_Relationship->search(
      object_id => $self->feature_id,
      type_id   => $rel_type->cvterm_id
   );

   my @features = map { $_->subject_id  } @feature_relations;

   return @features;
}
_subfeature_uniquenamedescriptiontopprevnext
sub _subfeature_uniquename {
   my ($self, $location, $type) = @_;

   my $fmin = $location->start - 1;    # chado is interbase coordinates
my $fmax = $location->end; my $positionstr = ":$fmin..$fmax"; #
# took this from gmod_load_gff3
#
$self->throw("Can't find reference feature") if !$self->reference_feature(); my $uniquename = sprintf("_%s_%s_%s%s", $self->primary_id, $type, $self->reference_feature->primary_id, $positionstr ); return $uniquename;
}
_update_external_idsdescriptiontopprevnext
sub _update_external_ids {
   my ($self, @args) = @_;
  #
# create hash of existing Dbxref rows keyed on db name (source in modware-ese)
#
my $dbxref_hash = {}; my @fdbxref_rows = Chado::Feature_Dbxref->search( feature_id => $self->feature_id ); foreach my $fdbxref_row (@fdbxref_rows) { my $source = $fdbxref_row->dbxref->db->name; #
# the GFF loader adds 'DB:' to the beginning of dbxrefs
#
$source =~ s/^DB://; #
# filter out 'GFF_source' which is stored in dbXref
#
next if $source eq "GFF_source"; $dbxref_hash->{ $source } = $fdbxref_row->dbxref(); if (!exists $self->external_ids()->{$source} ) { $fdbxref_row->delete(); } } #
# eventually you will have to check if there are any
# feautre_dbxrefs to delete.
#
foreach my $source ( keys %{$self->external_ids} ) { #
# if a feature already has a dbxref, and it is different,
# just update that dbxref record
if ( $dbxref_hash->{ $source } ) { if ( $dbxref_hash->{ $source }->accession() ne $self->external_ids->{$source} ) { $dbxref_hash->{ $source }->accession($self->external_ids->{$source}); $dbxref_hash->{ $source }->update(); } } else { # find or create the db:
#
# the GFF loader adds 'DB:' to the beginning of dbxrefs,
# here, we prepend it to be consistent
#
my $db = Chado::Db->find_or_create( { name => "DB:".$source } ); # created the dbxref
my $dbxref = Chado::Dbxref->find_or_create( { db_id => $db->db_id, accession => $self->external_ids->{$source} }); # link it to the feature
my $f_dbxref = Chado::Feature_Dbxref->find_or_create( { feature_id => $self->feature_id(), dbxref_id => $dbxref->dbxref_id }); } }
}
_update_featuredescriptiontopprevnext
sub _update_feature {
   my ($self, @args) = @_;
   no warnings qw (uninitialized);
   die "Cannot update feature without feature_id" if !$self->feature_id();

   $self->_database_object( $self->is_deleted() );
   $self->_database_object( $self->name() );
   if ( $self->{bioperl} && $self->_database_object->seqlen ne $self->bioperl->length ) {
      $self->warn("Updating seqlen.") if DEBUG;
      $self->_database_object( $self->bioperl->length ) if $self->{bioperl};
   }

   $self->_database_object();
}
_update_featurelocdescriptiontopprevnext
sub _update_featureloc {
   my ($self, @args) = @_;
   no warnings qw( uninitialized );
   die "Cannot update feature without feature_id" if !$self->feature_id();

   my $fmin = $self->start - 1;    # chado is interbase coordinates
my $fmax = $self->end; my $srcfeature_id = $self->reference_feature() ? $self->reference_feature() : undef; #
# Has the location changed?
#
#
# if the location row does not exist, you have to create it here
#
if ( !$self->_featureloc() ) { $self->{_featureloc} = Chado::Featureloc->create( { feature_id => $self->feature_id, srcfeature_id => $srcfeature_id, fmin => $fmin, fmax => $fmax, strand => $self->strand() } ); } if ( $fmin ne $self->_featureloc() or $fmax ne $self->_featureloc() or $srcfeature_id ne $self->_featureloc() ) { warn "Updating feature location" if DEBUG; $self->_featureloc( $srcfeature_id ); $self->_featureloc( $fmin ); $self->_featureloc( $fmax ); } if ( $self->strand() ne $self->_featureloc() ) { warn "Updating feature strand setting to:".$self->strand() if DEBUG; $self->_featureloc( $self->strand() ); } $self->_featureloc();
}
_update_gene_associationdescriptiontopprevnext
sub _update_gene_association {
   my ($self) = @_;

   my ($partof_term)    = Chado::Cvterm->get_single_row(
      cv_id => Modware::Constant->Relationship_cv_id(),
      name  => 'part_of'
   );

   my $feat_relationship = Chado::Feature_Relationship->get_single_row(
      type_id    => $partof_term->cvterm_id,
      subject_id => $self->feature_id
   );

   if ( $self->gene ) {

      if ($feat_relationship) {
         $feat_relationship->object_id( $self->gene->feature_id );
         $feat_relationship->update();
      }
      else {

         Chado::Feature_Relationship->create({
            type_id    => $partof_term->cvterm_id,
            subject_id => $self->feature_id,
            object_id  => $self->gene->feature_id
         });
      }
   }
   else {
      $feature_relationship->delete();
   }
}
_update_multivalue_featurepropdescriptiontopprevnext
sub _update_multivalue_featureprop {
   my ($self, $fp_type, $arrayref ) = @_;

   no warnings qw( exiting ); # yeah, I KNOW I'm exiting an eval via 'exit'
my ($qualifier_term) = Chado::Cvterm->get_single_row( cv_id => Modware::Constant->Feature_property_cv_id(), name => $fp_type ); my $term_id = $qualifier_term->cvterm_id(); my $feature_id = $self->feature_id(); my @featureprop_rows = Chado::Featureprop->search( feature_id => $feature_id, type_id => $term_id ); foreach my $row (@featureprop_rows) { if ( ! grep { $row->value eq $_ } @{$arrayref} ) { warn "deleted $fp_type (featureprop: ".$row->featureprop_id().") for ".$self->feature_id."\n" if DEBUG;; $row->delete(); } } #
# The following is a gigantic kludge to get around the
# (feature_id, type_id, rank) unique key
#
# you can't just update the rank if the row is already there
# because the rank could conflict with another record
# residing in the database that already has that rank.
#
my @values = @{ $arrayref }; for (my $i=0;$i<=$#values;$i++) { my $value = $values[$i]; print uc($value)."\n" if DEBUG; eval { #
# first search for this particular rank
# and move it out of the way, by giving it a high rank like 1001
#
my $record = Chado::Featureprop->get_single_row( { type_id => $term_id,, feature_id => $feature_id, rank => $i }); if ( $record && $record->value eq $value ) { next; # if its all the same, then dont do anything
} #
# move current item of this rank out of the way
#
if ( $record ) { $record->rank( $i + 1000 ); $record->update(); } #
# now see if the value is already there
#
my $value_row = Chado::Featureprop->get_single_row( feature_id => $feature_id, type_id => $term_id, value => $value ); #
# if it is, give it this new rank
#
if ( $value_row ) { my $orig_row = $value_row->rank(); $value_row->rank( $i ); $value_row->update(); warn "updated rank of $fp_type $value from $orig_row to $i (featureprop: ".$value_row->featureprop_id().") for ".$self->feature_id."\n" if DEBUG; } #
# otherwise, create it.
#
else { my $new_record = Chado::Featureprop->create({ feature_id => $feature_id, type_id => $term_id, value => $value, rank => $i }); warn "Inserted $fp_type $value ( rank: $i ) (featureprop: ".$new_record->featureprop_id().") for ".$self->feature_id."\n" if DEBUG; } }; if ($@) { $self->throw("Error linking feature_type: $value to ".$self->feature_id."\n". $@); } }
}
_update_qualifiersdescriptiontopprevnext
sub _update_qualifiers {
   my ($self, @args) = @_;

   $self->_update_multivalue_featureprop( 'qualifier', $self->qualifiers );
}
_update_synonymsdescriptiontopprevnext
sub _update_synonyms {
   my ($self, @args) = @_;

   my $synonym_term = Chado::Cvterm->get_single_row( 
     name => 'synonym',
     cv_id => Modware::Constant->Null_cv_id()
   );
   my $null_pub = Chado::Pub->get_single_row(
      uniquename => 'null'
   );

   my @object_links;
   foreach my $synonym ( @{ $self->synonyms() } ) {
      my $syn_row = Chado::Synonym->find_or_create( 
         name         => $synonym,
         type_id      => $synonym_term->cvterm_id(),
         synonym_sgml => $synonym
      );
      push @object_links, $syn_row->synonym_id();
   }


   my @database_links  = map{ $_->synonym_id } $self->_database_object()->feature_synonym_feature_id();

   my $lc            = List::Compare->new(\@object_links,\@ database_links);
   my @insert        = $lc->get_Lonly;  # array of ids in object, but not in feature_synonym table
my @delete = $lc->get_Ronly; # array of ids in feature_synonym but not in object
foreach my $syn_id (@insert) { eval { Chado::Feature_Synonym->create({ feature_id => $self->feature_id(), synonym_id => $syn_id, pub_id => $null_pub }); }; if ($@) { $self->throw("Error linking synonym: $syn_id to ".$self->feature_id."\n". $@); } } foreach my $syn_id (@delete) { eval { my $feature_synonym = Chado::Feature_Synonym->get_single_row( feature_id => $self->feature_id(), synonym_id => $syn_id ); $feature_synonym->delete(); }; if ($@) { $self->throw("Error unlinking synonym: $syn_id to ".$self->feature_id."\n". $@); } }
}
add_derived_fromdescriptiontopprevnext
sub add_derived_from {
   my ($self, $derived_from_str) = @_;

   $self->throw( "need derived_from to add") if !$derived_from_str;

   $self->throw( "$derived_from_str is not an acceptable derived from value") if !grep{ $_ eq $derived_from_str } @derived_from_values;

   if ( !grep { $_ eq $derived_from_str } @{ $self->derived_from() } ) {
      push @{ $self->derived_from }, $derived_from_str;
   }
}
add_external_iddescriptiontopprevnext
sub add_external_id {
   my ($self, @args) = @_;

   my ( $source, $id ) =  $self->_rearrange([qw(SOURCE ID)], @args);


   $self->throw( "need -id and -source") if !( $source && $id );

   # I think we should change the way external IDs are stored by making an arrrya of hashes instead of justa Hash. This allows to store more than one external ID with the same source.
$self->external_ids->{$source} = $id;
}
add_qualifierdescriptiontopprevnext
sub add_qualifier {
   my ($self, $qualifier) = @_;

   $self->throw( "need qualifier to add") if !$qualifier;

   $self->throw( "$qualifier is not an acceptable qualifier value") if !grep{ $_ eq $qualifier } @allowed_qualifiers;

   if ( !grep { $_ eq $qualifier } @{ $self->qualifiers() } ) {
      push @{ $self->qualifiers }, $qualifier;
   }
}
add_supported_bydescriptiontopprevnext
sub add_supported_by {
   my ($self, $supported_by_str) = @_;

   $self->throw( "need supported_by to add") if !$supported_by_str;

   $self->throw( "$supported_by_str is not an acceptable supported by value") if !grep{ $_ eq $supported_by_str } @supported_by_values;

   if ( !grep { $_ eq $supported_by_str } @{ $self->supported_by() } ) {
      push @{ $self->supported_by }, $supported_by_str;
   }
}
bioperldescriptiontopprevnext
sub bioperl {
   my ($self, $obj) = @_;

  #
# fetches bioperl from database (_get_bioperl) if bioperl is not yet defined
# and the user is not attempting to set the bioperl
#
exists $self->{bioperl} || scalar @_ > 1 || $self->_get_bioperl(); if(scalar @_ > 1) { $self->{bioperl} = $obj; } return $self->{bioperl};
}
cached_sequencesdescriptiontopprevnext
sub cached_sequences {
   my ($self, $obj) = @_;

  #
# fetches cached_sequences from database (_get_cached_sequences) if cached_sequences is not yet defined
# and the user is not attempting to set the cached_sequences
#
exists $self->{cached_sequences} || scalar @_ > 1 || $self->_get_cached_sequences(); if(scalar @_ > 1) { $self->{cached_sequences} = $obj; } return $self->{cached_sequences};
}
chromosomedescriptiontopprevnext
sub chromosome {
   my ($self, @args) = @_;
   $self->warn("deprecated method Modware::Feature->chromosome() called.");
   $self->reference_feature( @args );
}
contigdescriptiontopprevnext
sub contig {
   my ($self,  @args) = @_;
   warn "Modware::Feature::contig method is deprecated\n";
   my ( $contig ) = grep{ $_->type eq 'Contig' } map{ new Modware::Feature(-feature_id => $_) } @{ $self->reference_feature( $self->start(), $self->end() ) };

   return $contig;
}
delete_from_cachedescriptiontopprevnext
sub delete_from_cache {
   my ($self) = @_;

   delete $feat_ids->{$self->primary_id()};
}
derived_fromdescriptiontopprevnext
sub derived_from {
   my ($self, $obj) = @_;

  #
# fetches derived_from from database (_get_derived_from) if derived_from is not yet defined
# and the user is not attempting to set the derived_from options
#
exists $self->{derived_from} || scalar @_ > 1 || $self->_get_derived_from(); if(scalar @_ > 1) { $self->{derived_from} = $obj; } return $self->{derived_from};
}
descriptiondescriptiontopprevnext
sub description {
   my ($self, $obj) = @_;

  #
# fetches description from database (_get_description) if description is not yet defined
# and the user is not attempting to set the description options
#
exists $self->{description} || scalar @_ > 1 || $self->description( $self->_get_featureprop( 'description' ) ); if(scalar @_ > 1) { $self->{description} = $obj; } return $self->{description};
}
display_typedescriptiontopprevnext
sub display_type {
   my ($self, $obj) = @_;
   if($obj) {
      $self->{display_type} = $obj;
   }
   return $self->{display_type} || ucfirst($self->type());
}
enddescriptiontopprevnext
sub end {
   my ($self) = @_;
   $self->throw_not_implemented();
}
external_idsdescriptiontopprevnext
sub external_ids {
   my ($self, $obj) = @_;

  #
# fetches external_ids from database (_get_external_ids) if external_ids is not yet defined
# and the user is not attempting to set the external_ids
#
exists $self->{external_ids} || scalar @_ > 1 || $self->_get_external_ids(); if(scalar @_ > 1) { $self->{external_ids} = $obj; } return $self->{external_ids};
}
feature_iddescriptiontopprevnext
sub feature_id {
   my ($self, $feature_id) = @_;

   if( $feature_id ) {
      $self->{feature_id} = $feature_id;

      my $database_obj = Chado::Feature->get_single_row( feature_id => $feature_id );

      if ( !$database_obj ) {
         $self->throw( "cannot find feature_id: $feature_id in the database ");
      }

      $self->_database_object( $database_obj );
   }

   return $self->{feature_id};
}
genedescriptiontopprevnext
sub gene {
   my ($self, $obj) = @_;

  #
# fetches gene from database (_get_gene) if gene is not yet defined
# and the user is not attempting to set the gene
#
exists $self->{gene} || scalar @_ > 1 || $self->_get_gene(); if(scalar @_ > 1) { $self->{gene} = $obj; } return $self->{gene};
}
has_qualifierdescriptiontopprevnext
sub has_qualifier {
   my ($self, $qualifier) = @_;

   $self->throw( "need qualifier to check") if !$qualifier;

   my @qualifiers = grep { $_ eq $qualifier } @{ $self->qualifiers() };

   scalar @qualifiers ? 1 : 0;
}
insertdescriptiontopprevnext
sub insert {
   my ($self, @args) = @_;

   $self->_insert_feature();
   $self->_insert_or_update_featureprop( 'description', $self->description ) if ($self->description());

   $self->_insert_source();
   $self->_update_external_ids() if exists $self->{'external_ids'};
   $self->_update_reference_links() if $self->{'references'};
   $self->_update_qualifiers();
   $self->_update_synonyms()         if exists $self->{synonyms};
}
is_deleteddescriptiontopprevnext
sub is_deleted {
   my ($self, $obj) = @_;

   if(scalar @_ > 1) {
      $self->{is_deleted} = $obj;
   }
   return $self->{is_deleted};
}
namedescriptiontopprevnext
sub name {
   my ($self, $obj) = @_;

   return $self->primary_id();
}
newdescriptiontopprevnext
sub new {
   my ($class, @args) = @_;

   my $self = {};
   bless $self, $class;

   my ( $feature_id, $primary_id, $type ) =  $self->_rearrange([qw(FEATURE_ID PRIMARY_ID TYPE)], @args);

   my $feature_object;

  #
# if passed -primary_id
#
if ( $primary_id ) { my $dbxref = Chado::Dbxref->get_single_row( accession => uc($primary_id), db_id => Modware::Constant->Application_db_id() ); my $feature; if (!$dbxref) { $feature = Chado::Feature->get_single_row( uniquename => $primary_id ); } else { $feature = Chado::Feature->get_single_row( dbxref_id => $dbxref->dbxref_id ); } if (!$feature) { $self->throw( "Cannot create feature for primary_id $primary_id, does not exist"); } if ( !$feature ) { $self->throw( "$primary_id is not a associated with a feature"); } $feature_id = $feature->feature_id; } #
# for subclasses which implment singletons,
# we cache the feature_id and if it exists
# return that object
#
if ( $feature_id && $feat_ids->{$feature_id} ) { return $feat_ids->{$feature_id}; } if ( $type ) { $self->throw("Cannont pass -type if you have passed -feature_id or -primary_id") if $feature_id; my $feat; eval{ my $uctype = uc( $type ); $uctype =~ s/ /_/; $module = "Modware::Feature::$uctype"; if ( $type =~ /[^m]RNA/i ) { $module = 'Modware::Feature::NCRNA'; } elsif ( $type eq 'contig_reference' ) { # there is no SO type 'contig_reference', it actually
# gets created as a contig, but the type contig_reference is
# used to signal that it should be blessed as a 'Modware::Feature::REFERENCE_FEATURE'
# instead of Modware::Feature::CONTIG (which has a location).
$type =~ s/_reference$//g; $module = 'Modware::Feature::REFERENCE_FEATURE'; } else { # The following logic makes sure that the 'type'
# maps to a class in Modware::Feature
# if there is no class for this type, then create a
# Modware::Feature::GENERIC object
eval "require $module"; if ( $@ =~ /^Can't locate Modware\/Feature\/$uctype/ ) { warn "creating GENERIC object for $type" if DEBUG; $module = 'Modware::Feature::GENERIC'; } elsif( $@ ) { die $@; } } $self->_load_module( $module ); $feat = $module->new( @args ); $feat->type( $type ); $feat->is_deleted( 0 ); $feat->_init(); }; if ( $@ ) { $self->throw( "$@" ); } return $feat; } #
# if passed -feature_id or $feature_id set by primary_id
#
if ( $feature_id ) { $self->feature_id( $feature_id ); } else { $self->throw( "Need one of three arguments: -type, -feature_id, -primary_id"); } bless $self, Modware::Feature; #
# NOT ALL FEATURES HAVE PRIMARY_IDS. Modware::Feature::GENE overrides this
# in its init method
#
$self->primary_id( $self->_database_object->dbxref->accession ) if $self->_database_object->dbxref; $self->type ( $self->_database_object->type_id->name ); $self->source ( $self->_get_source() ); $self->qualifiers(); $self->is_deleted ( $self->_database_object() ); if ( $self->type() eq "chromosome" ) { #
# this is a SINGLETON OBJECT ONLY ONE CHROMOSOME OF A GIVEN CHROMOSOME_NO
# CAN EXIST AT ONE TIME
#
$feat_ids->{$self->feature_id()} = $self; } my $module; if ( $self->type() =~ /[^m]RNA/ ) { $module = 'Modware::Feature::NCRNA'; } elsif ( $self->type() eq 'contig' && !$self->_featureloc() ){ $module = 'Modware::Feature::REFERENCE_FEATURE'; } else { # The following logic makes sure that the 'type'
# maps to a class in Modware::Feature
# if there is no class for this type, then create a
# Modware::Feature::GENERIC object
my $uctype = uc( $self->type() ); $uctype =~ s/ /_/; $module = "Modware::Feature::$uctype"; eval "require $module"; if ( $@ =~ /^Can't locate Modware\/Feature\/$uctype/ ) { warn "creating GENERIC object for $type" if DEBUG; $module = 'Modware::Feature::GENERIC'; } elsif( $@ ) { die $@; } } $self->_load_module( $module ); bless $self, $module; $self->_init(); return $self;
}
organism_namedescriptiontopprevnext
sub organism_name {
   my ($self, @args) = @_;

   my $organism = $self->_database_object();

   return $organism->genus()." ".$organism->species();
}
overlapping_aligneddescriptiontopprevnext
sub overlapping_aligned {
   my ($self, $obj) = @_;

   return Modware::Search::Feature->Search_overlapping_feats_by_range( $self->reference_feature->name, $self->start, $self->end, 'match' );
}
overlapping_cdsdescriptiontopprevnext
sub overlapping_cds {
   my ($self, $obj) = @_;

   return Modware::Search::Feature->Search_overlapping_feats_by_range( $self->reference_feature->name, $self->start, $self->end, 'mRNA' );
}
primary_iddescriptiontopprevnext
sub primary_id {
   my ($self, $obj) = @_;
   if($obj) {
      $self->{primary_id} = $obj;
   }
   return $self->{primary_id};
}
qualifiersdescriptiontopprevnext
sub qualifiers {
   my ($self, $obj) = @_;

  #
# fetches qualifiers from database (_get_qualifiers) if qualifiers is not yet defined
# and the user is not attempting to set the qualifiers options
#
exists $self->{qualifiers} || scalar @_ > 1 || $self->_get_qualifiers(); if(scalar @_ > 1) { $self->{qualifiers} = $obj; } return $self->{qualifiers};
}
reference_featuredescriptiontopprevnext
sub reference_feature {
   my ($self, $obj) = @_;

  #
# fetches reference_feature from database (_get_reference_feature) if reference_feature is not yet defined
# and the user is not attempting to set the reference_feature
#
exists $self->{reference_feature} || scalar @_ > 1 || $self->_get_reference_feature(); if(scalar @_ > 1) { $self->{reference_feature} = $obj; $self->bioperl( $obj->bioperl() ) if ( $obj && $self->{bioperl} && !$self->isa( 'Modware::Feature::Aligned' ) && !$self->isa( 'Modware::Feature::MATCH' ) ); } return $self->{reference_feature};
}
remove_derived_fromdescriptiontopprevnext
sub remove_derived_from {
   my ($self, $derived_from_str) = @_;

   $self->throw( "need derived_from to remove") if !$derived_from_str;

   my @derived_from = grep { $_ ne $derived_from_str } @{ $self->derived_from() };

   $self->derived_from (\@ derived_from );
}
remove_external_iddescriptiontopprevnext
sub remove_external_id {
   my ($self, @args) = @_;

   my ( $source ) =  $self->_rearrange([qw(SOURCE)], @args);

   $self->throw( "need -source named argument in remove_external_id") if !( $source );
   $self->warn("Trying to delete non-existent external_id: $source") if (!$self->external_ids->{$source});

   delete $self->external_ids->{$source};
}
remove_qualifierdescriptiontopprevnext
sub remove_qualifier {
   my ($self, $qualifier) = @_;

   $self->throw( "need qualifier to remove") if !$qualifier;

   my @qualifiers = grep { $_ ne $qualifier } @{ $self->qualifiers() };

   $self->qualifiers (\@ qualifiers );
}
remove_supported_bydescriptiontopprevnext
sub remove_supported_by {
   my ($self, $supported_by_str) = @_;

   $self->throw( "need supported_by to remove") if !$supported_by_str;

   my @supported_by = grep { $_ ne $supported_by_str } @{ $self->supported_by() };

   $self->supported_by (\@ supported_by );
}
replaced_bydescriptiontopprevnext
sub replaced_by {
   my ($self, $obj) = @_;

  #
# fetches replaced_by from database (_get_replaced_by) if replaced_by is not yet defined
# and the user is not attempting to set the replaced_by options
#
exists $self->{replaced_by} || scalar @_ > 1 || $self->replaced_by( $self->_get_featureprop( 'replaced by' ) ); if(scalar @_ > 1) { $self->{replaced_by} = $obj; } return $self->{replaced_by};
}
sequencedescriptiontopprevnext
sub sequence {
   my ($self,  @args) = @_;

   my ( $format, $display_seq_type ) =  $self->_rearrange([qw(FORMAT TYPE)], @args);

   my $seq = $self->cached_sequences->{'default'};

   $display_seq_type = $self->type()." Sequence";
   
   $self->throw(" no seqeunce of type: $display_seq_type exists for ". $self->primary_id) if ( !$seq );

   my $header;

   if ( !$format ) {
     return $seq;
   }

   $header .= "|".$display_seq_type."|";
   $header .= " gene: ".$self->gene->gene_name if $self->gene;

   return $self->_formatted_seq(\$ seq, $header, $format);
}
sourcedescriptiontopprevnext
sub source {
   my ($self, $obj) = @_;
   if($obj) {
      $self->{source} = $obj;
   }
   return $self->{source};
}
startdescriptiontopprevnext
sub start {
   my ($self) = @_;
   $self->throw_not_implemented();
}
stranddescriptiontopprevnext
sub strand {
   my ($self, $obj) = @_;

  #
# fetches strand from database (_get_strand) if strand is not yet defined
# and the user is not attempting to set the strand options
#
exists $self->{strand} || scalar @_ > 1 || $self->_get_strand(); if(scalar @_ > 1) { $self->{strand} = $obj; } return $self->{strand};
}
subfeaturesdescriptiontopprevnext
sub subfeatures {
   my ($self) = @_;

   return $self->_relationship_subjects( 'part_of' );
}
supported_bydescriptiontopprevnext
sub supported_by {
   my ($self, $obj) = @_;

  #
# fetches supported_by from database (_get_supported_by) if supported_by is not yet defined
# and the user is not attempting to set the supported_by options
#
exists $self->{supported_by} || scalar @_ > 1 || $self->_get_supported_by(); if(scalar @_ > 1) { $self->{supported_by} = $obj; } return $self->{supported_by};
}
typedescriptiontopprevnext
sub type {
   my ($self, $obj) = @_;
   if($obj) {
      $self->{type} = $obj;
   }
   return $self->{type};
}
updatedescriptiontopprevnext
sub update {
   my ($self, @args) = @_;

   $self->_update_feature();

   $self->_insert_or_update_featureprop( 'description', $self->description ) if exists $self->{description};
   $self->_update_external_ids() if exists $self->{'external_ids'};
   $self->_update_reference_links() if $self->{'references'};
   $self->_update_synonyms() if exists $self->{synonyms};;
   $self->_update_qualifiers();
   $self->_update_multivalue_featureprop( 'derived from', $self->derived_from() ) if exists $self->{derived_from};
   $self->_update_multivalue_featureprop( 'supported by', $self->supported_by() ) if exists $self->{supported_by};

   if ( $self->replaced_by() && $self->is_deleted() ) {
      $self->_insert_or_update_featureprop( 'replaced by', $self->replaced_by() );
   }
   elsif ( $self->_get_featureprop( 'replaced by' ) ) {
      $self->_delete_featureprop( 'replaced by' );
   }
}

General documentation

AUTHOR - Eric Just top
   Eric Just e-just@northwestern.edu
APPENDIX top
   The rest of the documentation details each of the object
methods. Internal methods are usually preceded with a _