File Coverage

blib/lib/Bio/DB/Das/Chado/Segment.pm
Criterion Covered Total %
statement 33 686 4.8
branch 0 340 0.0
condition 0 202 0.0
subroutine 11 40 27.5
pod 26 27 96.3
total 70 1295 5.4


line stmt bran cond sub pod time code
1             # $Id: Segment.pm,v 1.5 2009-06-04 15:33:30 scottcain Exp $
2              
3             =head1 NAME
4              
5             Bio::DB::Das::Chado::Segment - DAS-style access to a chado database
6              
7             =head1 SYNOPSIS
8              
9             # Get a Bio::Das::SegmentI object from a Bio::DB::Das::Chado database...
10              
11             $segment = $das->segment(-name => 'Landmark',
12             -start=> $start,
13             -stop => $stop);
14              
15             @features = $segment->overlapping_features(-type=>['type1','type2']);
16             # each feature is a Bio::SeqFeatureI-compliant object
17              
18             @features = $segment->contained_features(-type=>['type1','type2']);
19              
20             @features = $segment->contained_in(-type=>['type1','type2']);
21              
22             $stream = $segment->get_feature_stream(-type=>['type1','type2','type3'];
23             while (my $feature = $stream->next_seq) {
24             # do something with feature
25             }
26              
27             $count = $segment->features_callback(-type=>['type1','type2','type3'],
28             -callback => sub { ... { }
29             );
30              
31             =head1 DESCRIPTION
32              
33             Bio::DB::Das::Chado::Segment is a simplified alternative interface to
34             sequence annotation databases used by the distributed annotation
35             system. In this scheme, the genome is represented as a series of
36             landmarks. Each Bio::DB::Das::Chado::Segment object ("segment") corresponds
37             to a genomic region defined by a landmark and a start and end position
38             relative to that landmark. A segment is created using the Bio::DasI
39             segment() method.
40              
41             Features can be filtered by the following attributes:
42              
43             1) their location relative to the segment (whether overlapping,
44             contained within, or completely containing)
45              
46             2) their type
47              
48             3) other attributes using tag/value semantics
49              
50             Access to the feature list uses three distinct APIs:
51              
52             1) fetching entire list of features at a time
53              
54             2) fetching an iterator across features
55              
56             3) a callback
57              
58             =head1 FEEDBACK
59              
60             =head2 Mailing Lists
61              
62             User feedback is an integral part of the evolution of this and other
63             Bioperl modules. Send your comments and suggestions preferably to one
64             of the Bioperl mailing lists. Your participation is much appreciated.
65              
66             bioperl-l@bio.perl.org
67              
68             =head2 Reporting Bugs
69              
70             Report bugs to the Bioperl bug tracking system to help us keep track
71             the bugs and their resolution. Bug reports can be submitted via email
72             or the web:
73              
74             bioperl-bugs@bio.perl.org
75             http://bio.perl.org/bioperl-bugs/
76              
77             =head1 AUTHOR - Scott Cain
78              
79             Email cain@cshl.org
80              
81             =head1 APPENDIX
82              
83             The rest of the documentation details each of the object
84             methods. Internal methods are usually preceded with a _
85              
86             =cut
87              
88             package Bio::DB::Das::Chado::Segment;
89              
90 1     1   5 use strict;
  1         1  
  1         87  
91 1     1   11 use Carp qw(carp croak cluck confess);
  1         2  
  1         107  
92 1     1   7061 use Bio::Root::Root;
  1         119076  
  1         40  
93 1     1   941 use Bio::SeqI;
  1         33972  
  1         36  
94 1     1   889 use Bio::Das::SegmentI;
  1         802  
  1         27  
95 1     1   7 use Bio::DB::Das::Chado;
  1         2  
  1         24  
96 1     1   862 use Bio::DB::Das::Chado::Segment::Feature;
  1         3  
  1         45  
97 1     1   987 use Bio::DB::GFF::Typename;
  1         3337  
  1         38  
98 1     1   9 use Data::Dumper;
  1         1  
  1         69  
99             #dgg;not working# use Bio::Species;
100              
101 1     1   7 use constant DEBUG => 0;
  1         2  
  1         66  
102              
103 1     1   6 use vars qw(@ISA $VERSION);
  1         1  
  1         10626  
104             @ISA = qw(Bio::Root::Root Bio::SeqI Bio::Das::SegmentI Bio::DB::Das::Chado);
105             $VERSION = 0.34;
106              
107             #use overload '""' => 'asString';
108              
109             # construct a virtual segment that works in a lazy way
110             sub new {
111             #validate that the name/accession is valid, and start and end are valid,
112             #then return a new segment
113              
114 0     0 1   my $self = {};
115 0           my $class_type = shift;
116              
117 0           my ( $name,$factory,$base_start,$stop,$db_id,$target,$feature_id,$srcf_id ) = @_;
118              
119 0   0       bless $self, ref $class_type || $class_type;
120 0           $self->{'factory'} = $factory;
121 0           $self->{'name'} = $name;
122              
123 0 0         $self->feature_id($feature_id) if $feature_id;
124              
125 0   0       $target ||=0;
126 0           my $strand;
127              
128              
129 0           warn "na:$name, id:$db_id, $factory\n" if DEBUG;
130 0           warn "base_start = $base_start, stop = $stop\n" if DEBUG;
131             # clicking on the help in gbrowse calls this constructor without a
132             # name. return to avoid performances issues
133 0 0         if (! defined ($name)) {
134 0           return;
135             }
136             # $self->Bio::Root::Root->throw("start value less than 1\n")
137             # if ( defined $base_start && $base_start < 1 );
138 0 0         $base_start = $base_start ? int($base_start) : 1;
139 0           my $interbase_start = $base_start - 1;
140              
141 0           my $quoted_name = $factory->dbh->quote( lc $name );
142              
143 0           warn "quoted name:$quoted_name\n" if DEBUG;
144              
145             # need to change this query to allow for Target queries
146              
147             ##URGI - Changed the request to be sure we are getting the srcfeature_id of type 'reference class'
148             ##from gbrowse configuration file
149             ##We also check if we are not in the recursive call from feactory->segment, in this case we already set the ref feature_id
150             ##for reference class feature.
151              
152             ##minor change: calling name2term with no arg returna a hashref (as documented)
153             ##so if $factory->default_class() is empty, you would get a hashref in $refclass
154              
155 0 0         my $refclass = $factory->default_class()
156             ? $factory->name2term($factory->default_class())
157             : undef;
158              
159 0   0       my $ref_feature_id = $factory->refclass_feature_id() || undef;
160              
161 0 0         my $where_part = " and rank = $target " if(defined($target));
162              
163 0 0         if(defined($ref_feature_id)){
164 0           $where_part .= " and fl.srcfeature_id = $ref_feature_id ";
165             }
166             else{
167 0 0         $where_part .= " and srcf.type_id = $refclass " if(defined($refclass));
168             }
169              
170 0 0         $where_part .= " and srcf.is_obsolete = false " unless $self->factory->allow_obsolete;
171              
172 0 0         $where_part .= " and srcf.organism_id = ".$self->factory->organism_id
173             if $self->factory->organism_id;
174              
175 0           warn $where_part if DEBUG;
176              
177 0           my $srcfeature_query = $factory->dbh->prepare( "
178             select srcfeature_id from featureloc fl
179             join feature srcf on (fl.srcfeature_id = srcf.feature_id)
180             where fl.feature_id = ? " . $where_part
181             );
182              
183             #my $srcfeature_query = $factory->dbh->prepare( "
184             # select srcfeature_id from featureloc
185             # where feature_id = ? and rank = $target
186             # " );
187              
188 0           my $landmark_is_src_query = $factory->dbh->prepare( "
189             select f.name,f.feature_id,f.seqlen,f.type_id,f.is_obsolete
190             from feature f
191             where f.feature_id = ?
192             " );
193              
194             #not used any more
195             #my $feature_query = $factory->dbh->prepare( "
196             # select f.name,f.feature_id,f.seqlen,f.type_id,fl.fmin,fl.fmax,fl.strand
197             # from feature f, featureloc fl,f.is_obsolete
198             # where fl.feature_id = ? and
199             # ? = f.feature_id
200             # " );
201              
202 0           my $fetch_uniquename_query = $factory->dbh->prepare( "
203             select f.name,fl.fmin,fl.fmax,f.uniquename,f.is_obsolete,fl.srcfeature_id,fl.strand
204             from feature f, featureloc fl
205             where f.feature_id = ? and
206             f.feature_id = fl.feature_id
207             ");
208              
209 0           my $ref = $self->_search_by_name( $factory, $quoted_name, $db_id, $feature_id );
210              
211             #returns either a feature_id scalar (if there is only one result)
212             #or an arrayref (of feature_ids) if there is more than one result
213             #or nothing if there is no result
214              
215 0 0         if ( ref $ref eq 'ARRAY' ) { #more than one result returned
    0          
216              
217 0           warn "\n\n@$ref\n\n";
218              
219 0           my @segments;
220              
221 0           foreach my $feature_id (@$ref) {
222              
223 0 0         $fetch_uniquename_query->execute($feature_id )
224             or Bio::Root::Root->throw("fetching uniquename from feature_id failed") ;
225              
226 0           my $hashref = $fetch_uniquename_query->fetchrow_hashref;
227              
228 0 0 0       next if ($$hashref{'is_obsolete'} and !$self->factory->allow_obsolete);
229              
230 0           warn "$base_start, $stop\n" if DEBUG;
231              
232 0           warn "Looping through feature_ids in constructor:\n"
233             .Dumper($hashref) if DEBUG;
234              
235 0 0         $base_start = $base_start ? $base_start : $$hashref{fmin} + 1;
236 0 0         $stop = $stop ? $stop : $$hashref{fmax};
237 0           $db_id = $$hashref{uniquename};
238 0           $srcf_id = $$hashref{srcfeature_id};
239 0           $name = $$hashref{name};
240              
241 0 0 0       next if (!defined ($base_start) or !defined($stop) or !defined($db_id));
      0        
242              
243 0           warn "calling factory->segment with name:$name, start:$base_start, stop:$stop, db_id:$db_id, srcfeature_id:$srcf_id\n" if DEBUG;
244 0           push @segments, $factory->segment(-name=>$name,-start=>$base_start,-stop=>$stop,-db_id=>$db_id,-feature_id=>$feature_id,-srcfeature_id=>$srcf_id);
245              
246 0           warn "segments array in constructor:@segments" if DEBUG;
247              
248             #reset these variables so subsequent passes through the loop wont be confused
249 0           $base_start ='';
250 0           $stop ='';
251 0           $db_id ='';
252 0           $strand ='';
253 0           $srcf_id ='';
254             }
255              
256 0           $landmark_is_src_query->finish;
257 0           $fetch_uniquename_query->finish;
258 0           $srcfeature_query->finish;
259 0 0         if (@segments < 2) {
    0          
260 0           return $segments[0]; #I don't think this should ever happen
261             }
262             elsif (wantarray) {
263 0           return @segments;
264             }
265             else {
266 0           warn "The query for $name returned multiple segments\nPlease call in a list context to get them all";
267 0           Bio::Root::Root->throw("multiple segment exception") ;
268             }
269             }
270             elsif ( ref $ref eq 'SCALAR' ) { #one result returned
271              
272 0           my $landmark_feature_id = $$ref;
273              
274 0           warn "landmark feature_id:$landmark_feature_id" if DEBUG;
275              
276 0 0         $srcfeature_query->execute($landmark_feature_id)
277             or Bio::Root::Root->throw("finding srcfeature_id failed");
278              
279 0           my $hash_ref = $srcfeature_query->fetchrow_hashref;
280 0 0         my $srcfeature_id =
281             $$hash_ref{'srcfeature_id'}
282             ? $$hash_ref{'srcfeature_id'}
283             : $landmark_feature_id;
284              
285 0           warn "srcfeature_id:$srcfeature_id" if DEBUG;
286              
287             ###URGI Is it the right place to set it?
288             #but don't set it if creating a feature for a hit object
289 0 0         $factory->refclass_feature_id($srcfeature_id)
290             unless defined($target);
291              
292 0 0         if ( $landmark_feature_id == $srcfeature_id ) {
293              
294 0 0         $landmark_is_src_query->execute($landmark_feature_id)
295             or Bio::Root::Root->throw("something else failed");
296 0           $hash_ref = $landmark_is_src_query->fetchrow_hashref;
297              
298 0           warn "skipping feature_id $$hash_ref{feature_id}"
299             if (DEBUG and
300             $$hash_ref{'is_obsolete'} and
301             !$self->factory->allow_obsolete);
302 0 0 0       next if ($$hash_ref{'is_obsolete'} and !$self->factory->allow_obsolete);
303              
304 0           $name = $$hash_ref{'name'};
305              
306 0           my $length = $$hash_ref{'seqlen'};
307 0           my $type = $factory->term2name( $$hash_ref{'type_id'} );
308              
309 0 0         if ( $$hash_ref{'fmin'} ) {
310 0           $interbase_start = $$hash_ref{'fmin'};
311 0           $base_start = $interbase_start + 1;
312 0           $stop = $$hash_ref{'fmax'};
313 0           $strand = $$hash_ref{'strand'};
314             }
315              
316 0           warn "base_start:$base_start, stop:$stop, length:$length" if DEBUG;
317              
318 0 0 0       if( defined($interbase_start) and $interbase_start < 0) {
319 0           $self->warn("start value ($interbase_start) less than zero,"
320             ." resetting to zero") if DEBUG;
321 0           $base_start = 1;
322 0           $interbase_start = 0;
323             }
324              
325 0 0 0       if( defined($stop) and defined($length) and $stop > $length ){
      0        
326 0           $self->warn("end value ($stop) greater than length ($length),"
327             ." truncating to $length") if DEBUG;
328 0           $stop = $length;
329             }
330 0 0         $stop = $stop ? int($stop) : $length;
331 0           $length = $stop - $interbase_start;
332              
333 0           warn "base_start:$base_start, stop:$stop, length:$length" if DEBUG;
334              
335 0           $self->feature_id($landmark_feature_id);
336 0           $self->start($base_start);
337 0           $self->end($stop);
338 0           $self->{'length'} = $length;
339             # cluck "i'm in new";
340             # $self->srcfeature_id($srcfeature_id);
341 0           $self->{'srcfeature_id'} = $srcfeature_id;
342 0           $self->class($type);
343 0           $self->name($name);
344 0           $self->strand($strand);
345              
346 0           my $source = $self->source();
347 0           my $type_obj = Bio::DB::GFF::Typename->new(
348             $type,
349             $source);
350              
351 0           $self->type($type_obj);
352              
353             # warn $self, ref $self, Dumper($self) if DEBUG;
354            
355 0           $fetch_uniquename_query->finish;
356 0           $srcfeature_query->finish;
357 0           $landmark_is_src_query->finish;
358 0           return $self;
359             }
360              
361             else { #return a Feature object for the feature_id
362 0           warn $landmark_feature_id if DEBUG;
363 0           warn $factory,$base_start,$stop,$strand if DEBUG;
364              
365             #unless ($landmark_feature_id && $base_start && $stop) {
366 0           $fetch_uniquename_query->execute($landmark_feature_id);
367 0           my $resultref = $fetch_uniquename_query->fetchrow_hashref;
368 0           warn Dumper($resultref) if DEBUG;
369 0           $base_start = $$resultref{'fmin'} +1;
370 0           $stop = $$resultref{'fmax'};
371 0           $strand = $$resultref{'strand'};
372 0           warn "after fetching coord info: $base_start, $stop, $strand"
373             if DEBUG;
374             #}
375              
376 0           my ($feat) = $self->features(
377             -feature_id => $landmark_feature_id,
378             -factory => $factory,
379             -start => $base_start,
380             -stop => $stop,
381             -strand => $strand, );
382 0           $fetch_uniquename_query->finish;
383 0           $srcfeature_query->finish;
384 0           $landmark_is_src_query->finish;
385 0           return $feat;
386             }
387             }
388             else {
389 0           $fetch_uniquename_query->finish;
390 0           $landmark_is_src_query->finish;
391 0           $srcfeature_query->finish;
392 0           warn "no segment found" if DEBUG;
393 0           return; #nothing returned
394             }
395             }
396              
397             =head2 name
398              
399             Title : name
400             Usage : $segname = $seg->name();
401             Function: Returns the name of the segment
402             Returns : see above
403             Args : none
404             Status : public
405              
406             =cut
407              
408             sub name {
409 0     0 1   my $self = shift;
410 0 0         return undef unless ref $self;
411 0           return $self->{'name'}
412             }
413              
414             =head2 feature_id()
415              
416             Title : feature_id
417             Usage : $obj->feature_id($newval)
418             Function: holds feature.feature_id
419             Returns : value of feature_id (a scalar)
420             Args : on set, new value (a scalar or undef, optional)
421              
422              
423             =cut
424              
425             sub feature_id {
426 0     0 1   my $self = shift;
427              
428 0 0         return $self->{'feature_id'} = shift if @_;
429 0 0         return $self->{'feature_id'} if $self->{'feature_id'};
430              
431 0           my $dbh = $self->factory->dbh;
432              
433 0           warn $self->name;
434 0           warn $self->type;
435 0           $self->factory->name2term($self->type);
436              
437 0           my $name = $self->name;
438 0           my $org_id = $self->factory->organism_id;
439 0           my $type_id = $self->factory->name2term($self->type);
440              
441 0           my $query = "SELECT feature_id FROM feature WHERE (name = ? OR uniquename = ?)
442             AND type_id = ? ";
443              
444 0           my @args = ($name,$name,$type_id);
445 0 0         if ($org_id) {
446 0           $query .= " AND organism_id = ?";
447 0           push @args, $org_id;
448             }
449 0           my $sth = $dbh->prepare($query);
450 0           $sth->execute(@args);
451 0 0         return if $sth->rows > 1;
452            
453 0           my ($feature_id) = $sth->fetchrow_array;
454 0           $self->{'feature_id'} = $feature_id;
455 0           return $self->{'feature_id'};
456             }
457              
458             *primary_id = \&feature_id;
459              
460             =head2 strand()
461              
462             Title : strand
463             Usage : $obj->strand()
464             Function: Returns the strand of the feature. Unlike the other
465             methods, the strand cannot be changed once the object is
466             created (due to coordinate considerations).
467             corresponds to featureloc.strand
468             Returns : -1, 0, or 1
469             Args : on set, new value (a scalar or undef, optional)
470              
471              
472             =cut
473              
474             sub strand {
475 0     0 1   my $self = shift;
476              
477 0 0         return $self->{'strand'} = shift if @_;
478 0   0       return $self->{'strand'} || 0;
479             }
480              
481             *abs_strand = \&strand;
482              
483             =head2 attributes
484              
485             Title : attributes
486             Usage : @attributes = $obj->attributes;
487             Function: get the "attributes" of this segment
488             Returns : An array of strings
489             Args : None
490              
491             This is a object-specific wrapper on the more generic attributes
492             method in Bio::DB::Das::Chado.
493              
494             =cut
495              
496              
497             sub attributes {
498 0     0 1   my $self = shift;
499 0           my $factory = $self->factory;
500 0 0         defined(my $id = $self->id) or return;
501 0           $factory->attributes($id,@_);
502             }
503              
504              
505             =head2 _search_by_name
506              
507             Title : _search_by_name
508             Usage : _search_by_name($name);
509             Function: Searches for segments based on a name
510             Returns : Either a scalar (a feature_id) or an arrary ref (containing feature_ids)
511             Args : A string (name)
512             Status : private (used by new)
513              
514             =cut
515              
516             sub _search_by_name {
517 0     0     my $self = shift;
518 0           my ($factory,$quoted_name,$db_id,$feature_id) = @_;
519              
520 0           my $fulltext = $factory->fulltext;
521              
522 0           warn "_search_by_name args:@_" if DEBUG;
523              
524 0           my $obsolete_part = "";
525 0 0         $obsolete_part = " and is_obsolete = false " unless $self->factory->allow_obsolete;
526              
527 0 0         $obsolete_part .= " and organism_id = ".$self->factory->organism_id
528             if $self->factory->organism_id;
529              
530 0           my $sth;
531 0 0         if ($feature_id) {
    0          
532 0           $sth = $factory->dbh->prepare("
533             select name,feature_id,seqlen from feature
534             where feature_id = $feature_id $obsolete_part");
535             }
536             elsif ($db_id) {
537 0           $sth = $factory->dbh->prepare ("
538             select name,feature_id,seqlen from feature
539             where uniquename = \'$db_id\' $obsolete_part ");
540              
541             }
542             else {
543             #can't use FTS here as exact names are required
544 0           $sth = $factory->dbh->prepare ("
545             select name,feature_id,seqlen from feature
546             where lower(name) = $quoted_name $obsolete_part ");
547             }
548            
549 0 0         $sth->execute or Bio::Root::Root->throw("unable to validate name/length");
550            
551 0           my $where_part = '';
552 0 0         $where_part = " and f.organism_id = ".$self->factory->organism_id
553             if $self->factory->organism_id;
554 0 0         $where_part .= " and f.is_obsolete = 'false' "
555             unless $self->factory->allow_obsolete;
556            
557 0           my $rows_returned = $sth->rows;
558 0 0         if ($rows_returned == 0) { #look in synonym for an exact match
    0          
559 0           warn "looking for a synonym to $quoted_name" if DEBUG;
560 0           my $isth;
561 0 0         if ($self->factory->use_all_feature_names()) {
562              
563 0           my $optional_full_text;
564 0 0         if ($fulltext) {
565 0           $optional_full_text
566             = "afn.searchable_name @@ plainto_tsquery($quoted_name) $where_part";
567             }
568             else {
569 0           $optional_full_text
570             = "lower(afn.name) = $quoted_name $where_part";
571             }
572              
573 0           $isth = $factory->dbh->prepare ("
574             select afn.feature_id from all_feature_names afn, feature f
575             where afn.feature_id = f.feature_id and
576             f.is_obsolete = 'false' and
577             $optional_full_text
578             ");
579              
580             }
581             else {
582 0           my $full_text_options;
583 0 0         if ($fulltext) {
584 0           $full_text_options
585             = "s.searchable_synonym_sgml @@ plainto_tsquery($quoted_name) $where_part";
586             }
587             else {
588 0           $full_text_options
589             = "lower(s.synonym_sgml) = $quoted_name $where_part";
590             }
591 0           $isth = $factory->dbh->prepare ("
592             select fs.feature_id from feature_synonym fs, synonym s, feature f
593             where fs.synonym_id = s.synonym_id and
594             f.feature_id = fs.feature_id and
595             f.is_obsolete = 'false' and
596             $full_text_options
597             ");
598             }
599 0 0         $isth->execute or Bio::Root::Root->throw("query for name in synonym failed");
600 0           $rows_returned = $isth->rows;
601              
602 0 0         if ($rows_returned == 0) { #look in dbxref for accession number match
    0          
603 0           warn "looking in dbxref for $quoted_name" if DEBUG;
604              
605 0           my $full_text_option;
606 0 0         if ($fulltext) {
607 0           $full_text_option = "d.searchable_accession @@ plainto_tsquery($quoted_name) $where_part";
608             }
609             else {
610 0           $full_text_option = "lower(d.accession) = $quoted_name $where_part";
611             }
612              
613 0           $isth = $factory->dbh->prepare ("
614             select fd.feature_id from feature_dbxref fd, dbxref d, feature f
615             where fd.dbxref_id = d.dbxref_id and
616             f.feature_id = fd.feature_id and
617             f.is_obsolete = 'false' and
618             $full_text_option");
619 0 0         $isth->execute or Bio::Root::Root->throw("query for accession failed");
620 0           $rows_returned = $isth->rows;
621              
622 0           $sth->finish;
623 0           $isth->finish;
624 0 0         return if $rows_returned == 0;
625              
626 0 0         if ($rows_returned == 1) {
627 0           my $hashref = $isth->fetchrow_hashref;
628 0           my $feature_id = $$hashref{'feature_id'};
629 0           $sth->finish;
630 0           $isth->finish;
631 0           return \$feature_id;
632             } else {
633 0           my @feature_ids;
634 0           while (my $hashref = $isth->fetchrow_hashref) {
635 0           push @feature_ids, $$hashref{'feature_id'};
636             }
637 0           $sth->finish;
638 0           $isth->finish;
639 0           return \@feature_ids;
640             }
641              
642             } elsif ($rows_returned == 1) {
643 0           my $hashref = $isth->fetchrow_hashref;
644 0           my $feature_id = $$hashref{'feature_id'};
645 0           warn "found $feature_id in feature_synonym" if DEBUG;
646 0           $sth->finish;
647 0           $isth->finish;
648 0           return \$feature_id;
649             } else {
650 0           my @feature_ids;
651 0           while (my $hashref = $isth->fetchrow_hashref) {
652 0           push @feature_ids, $$hashref{'feature_id'};
653             }
654 0           $sth->finish;
655 0           $isth->finish;
656 0           return \@feature_ids;
657             }
658              
659             } elsif ($rows_returned == 1) {
660 0           my $hashref = $sth->fetchrow_hashref;
661 0           my $feature_id = $$hashref{'feature_id'};
662 0           warn "feature_id in _search_by_name:$feature_id" if DEBUG;
663 0           $sth->finish;
664 0           return \$feature_id;
665             } else {
666 0           my @feature_ids;
667 0           while (my $hashref = $sth->fetchrow_hashref) {
668 0           warn "feature_ids in _search_by_name$$hashref{'feature_id'}" if DEBUG;
669 0           push @feature_ids, $$hashref{'feature_id'};
670             }
671 0           $sth->finish;
672 0           return \@feature_ids;
673             }
674             }
675              
676             =head2 class
677              
678             Needed for backward compatability; always returns 'Sequence'.
679              
680             =cut
681              
682             sub class {
683 0     0 1   return 'Sequence';
684             }
685              
686             =head2 type
687              
688             Title : type
689             Usage : $obj->type($newval)
690             Function: used to be alias of class() for backward compatibility,
691             now behaves the same as Bio::DB::Das::Chado::Segment::Feature->type
692             Returns : A Bio::DB::GFF::Typename object
693             Args : on set, new value: Bio::DB::GFF::Typename object
694              
695             =cut
696              
697             sub type {
698 0     0 1   my $self = shift;
699              
700 0 0         return $self->{'type'} = shift if @_;
701 0           return $self->{'type'};
702             }
703              
704              
705             #*type = \&class;
706              
707             =head2 seq_id
708              
709             Title : seq_id
710             Usage : $ref = $s->seq_id
711             Function: return the ID of the landmark, aliased to name() for backward compatibility
712             Returns : a string
713             Args : none
714             Status : Public
715              
716             =cut
717              
718             *seq_id = \&name;
719              
720             =head2 start
721              
722             Title : start
723             Usage : $s->start
724             Function: start of segment
725             Returns : integer
726             Args : none
727             Status : Public
728              
729             =cut
730              
731             sub start {
732 0     0 1   my $self = shift;
733 0 0         return undef unless ref $self;
734 0 0         return $self->{'start'} = shift if @_;
735 0 0         return $self->{'start'} if $self->{'start'};
736 0           return undef;
737              
738             }
739              
740             =head2 low
741              
742             Title : low
743             Usage : $s->low
744             Function: start of segment
745             Returns : integer
746             Args : none
747             Status : Public
748              
749             Alias of start for backward compatibility
750              
751             =cut
752              
753             *low = \&start;
754              
755             =head2 end
756              
757             Title : end
758             Usage : $s->end
759             Function: end of segment
760             Returns : integer
761             Args : none
762             Status : Public
763              
764             =cut
765              
766             sub end {
767 0     0 1   my $self = shift;
768 0 0         return undef unless ref $self;
769 0 0         return $self->{'end'} = shift if @_;
770 0 0         return $self->{'end'} if $self->{'end'};
771 0           return undef;
772             }
773              
774             =head2 high
775              
776             Title : high
777             Usage : $s->high
778             Function: end of segment
779             Returns : integer
780             Args : none
781             Status : Public
782              
783             Alias of end for backward compatiblity
784              
785             =cut
786              
787             *high = \&end;
788              
789             =head2 stop
790              
791             Title : stop
792             Usage : $s->stop
793             Function: end of segment
794             Returns : integer
795             Args : none
796             Status : Public
797              
798             Alias of end for backward compatiblity
799              
800             =cut
801              
802             *stop = \&end;
803              
804             =head2 length
805              
806             Title : length
807             Usage : $s->length
808             Function: length of segment
809             Returns : integer
810             Args : none
811             Status : Public
812              
813             Returns the length of the segment. Always a positive number.
814              
815             =cut
816              
817 0     0 1   sub length { shift->{length} }
818              
819             =head2 features
820              
821             Title : features
822             Usage : @features = $s->features(@args)
823             Function: get features that overlap this segment
824             Returns : a list of Bio::SeqFeatureI objects
825             Args : see below
826             Status : Public
827              
828             This method will find all features that intersect the segment in a
829             variety of ways and return a list of Bio::SeqFeatureI objects. The
830             feature locations will use coordinates relative to the reference
831             sequence in effect at the time that features() was called.
832              
833             The returned list can be limited to certain types, attributes or
834             range intersection modes. Types of range intersection are one of:
835              
836             "overlaps" the default
837             "contains" return features completely contained within the segment
838             "contained_in" return features that completely contain the segment
839              
840             Two types of argument lists are accepted. In the positional argument
841             form, the arguments are treated as a list of feature types. In the
842             named parameter form, the arguments are a series of -name=E<gt>value
843             pairs.
844              
845             Argument Description
846             -------- ------------
847              
848             -types An array reference to type names in the format
849             "method:source"
850              
851             -attributes A hashref containing a set of attributes to match
852              
853             -rangetype One of "overlaps", "contains", or "contained_in".
854              
855             -iterator Return an iterator across the features.
856              
857             -callback A callback to invoke on each feature
858              
859             The -attributes argument is a hashref containing one or more
860             attributes to match against:
861              
862             -attributes => { Gene => 'abc-1',
863             Note => 'confirmed' }
864              
865             Attribute matching is simple string matching, and multiple attributes
866             are ANDed together. More complex filtering can be performed using the
867             -callback option (see below).
868              
869             If -iterator is true, then the method returns an object reference that
870             implements the next_seq() method. Each call to next_seq() returns a
871             new Bio::SeqFeatureI object.
872              
873             If -callback is passed a code reference, the code reference will be
874             invoked on each feature returned. The code will be passed two
875             arguments consisting of the current feature and the segment object
876             itself, and must return a true value. If the code returns a false
877             value, feature retrieval will be aborted.
878              
879             -callback and -iterator are mutually exclusive options. If -iterator
880             is defined, then -callback is ignored.
881              
882             =cut
883              
884             sub features {
885 0     0 1   my $self = shift;
886              
887 0           warn "Segment->features() args:@_" if DEBUG;
888              
889 0           my @sub_args = @_;
890              
891             # In some cases (url search : ?name=foo) $self isn't a hash ref ie
892             # object but a simple scalar ie string. So we need to get the
893             # factory the right way before accessing it
894 0           my ($factory,$feature_id);
895 0 0 0       if (ref ($self) && $self->factory->do2Level) {
896 0           return $self->_features2level(@sub_args);
897             }# should put an else here to try to get the factory from @_
898             else {
899 0 0 0       if ($sub_args[0] and $sub_args[0] =~ /^-/) {
900 0           my %args = @_;
901 0 0         $factory = $args{-factory} if ($args{-factory});
902 0 0         $feature_id = $args{-feature_id} if ($args{-feature_id});
903             }
904             }
905              
906 0           my ($types,$type_placeholder,$attributes,$rangetype,$iterator,$callback,$base_start,$stop,$seq_id,$end);
907 0 0 0       if (ref($self) and $sub_args[0] and $sub_args[0] =~ /^-/) {
    0 0        
      0        
      0        
908 0           ($types,$type_placeholder,$attributes,$rangetype,$iterator,$callback,$base_start,$stop,$seq_id,$end) =
909             $self->_rearrange([qw(TYPES
910             TYPE
911             ATTRIBUTES
912             RANGETYPE
913             ITERATOR
914             CALLBACK
915             START
916             STOP
917             SEQ_ID
918             END )],@sub_args);
919 0           warn "type and types after calling _rearrange:$type_placeholder,$types" if DEBUG;
920             }
921             elsif (defined $factory and $sub_args[0] and $sub_args[0] =~ /^-/) {
922 0           ($types,$type_placeholder,$attributes,$rangetype,$iterator,$callback,$base_start,$stop,$seq_id,$end) =
923             $factory->_rearrange([qw(TYPES
924             TYPE
925             ATTRIBUTES
926             RANGETYPE
927             ITERATOR
928             CALLBACK
929             START
930             STOP
931             SEQ_ID
932             END )],@sub_args);
933 0           warn "type and types after calling factory->_rearrange:$type_placeholder,$types" if DEBUG;
934            
935             }
936             else {
937 0           warn "didn't call rearrange" if DEBUG;
938 0           $types = \@sub_args;
939             }
940              
941             #UGG, allow both -types and -type to be used in the args
942 0 0 0       if ($type_placeholder and !$types) {
943 0 0         if (ref $type_placeholder eq 'ARRAY') {
944 0           $types = $type_placeholder;
945             }
946             else {
947 0           $$types[0] = $type_placeholder;
948             }
949 0           warn "what sort of thing is type_placeholder?:".ref $type_placeholder if DEBUG;
950             }
951              
952 0 0 0       warn "@$types\n" if (defined $types and DEBUG);
953 0           warn $factory if DEBUG;
954              
955 0   0       $factory ||=$self->factory();
956 0           my $feat = Bio::DB::Das::Chado::Segment::Feature->new();
957 0           my @features;
958              
959              
960 0           my ($interbase_start,$rend,$srcfeature_id,$sql_types);
961 0 0         if (!$feature_id) {
962 0   0       $rangetype ||='overlaps';
963              
964             # set range variable
965              
966 0 0         $base_start = defined $base_start ? $base_start : $self->start;
967 0           $interbase_start = $base_start -1;
968 0   0       $end ||= $stop;
969 0 0         $rend = defined $end ? $end : $self->end;
970             # my $sql_range;
971             # if ($rangetype eq 'contains') {
972             #
973             # $sql_range = " fl.fmin >= $interbase_start and fl.fmax <= $rend ";
974             #
975             # } elsif ($rangetype eq 'contained_in') {
976             #
977             # $sql_range = " fl.fmin <= $interbase_start and fl.fmax >= $rend ";
978             #
979             # } else { #overlaps is the default
980             #
981             # $sql_range = " fl.fmin <= $rend and fl.fmax >= $interbase_start ";
982            
983             # }
984              
985             # set type variable
986              
987             #$sql_types = '';
988              
989 0           my $valid_type = undef;
990 0 0 0       if ($types && scalar @$types != 0) {
991              
992 0           warn "first type:$$types[0]\n" if DEBUG;
993              
994 0 0         if (ref $$types[0] eq 'ARRAY') {
995 0           @$types = @{$$types[0]};
  0            
996 0           warn "first type after deref:$$types[0]\n" if DEBUG;
997             }
998              
999 0           my $temp_type = $$types[0];
1000 0           my $temp_source = '';
1001 0 0         if ($$types[0] =~ /(.*):(.*)/) {
1002 0           $temp_type = $1;
1003 0           $temp_source = $2;
1004             }
1005              
1006 0           $valid_type = $factory->name2term($temp_type);
1007 0 0         $self->throw("feature type: '$temp_type' is not recognized") unless $valid_type;
1008              
1009 0           my $temp_dbxref = $factory->source2dbxref($temp_source);
1010 0 0 0       if ($temp_source && $temp_dbxref) {
1011 0           $sql_types .= "((f.type_id = $valid_type and fd.dbxref_id = $temp_dbxref)";
1012             } else {
1013 0           $sql_types .= "((f.type_id = $valid_type)";
1014             }
1015              
1016 0 0         if (scalar @$types > 1) {
1017 0           for(my $i=1;$i<(scalar @$types);$i++) {
1018              
1019 0           $temp_type = $$types[$i];
1020 0           $temp_source = '';
1021 0 0         if ($$types[$i] =~ /(.*):(.*)/) {
1022 0           $temp_type = $1;
1023 0           $temp_source = $2;
1024             }
1025 0           warn "more types:$$types[$i]\n" if DEBUG;
1026              
1027 0           $valid_type = $factory->name2term($temp_type);
1028 0 0         $self->throw("feature type: '$temp_type' is not recognized") unless $valid_type;
1029              
1030 0           $temp_dbxref=$factory->source2dbxref($temp_source);
1031 0 0 0       if ($temp_source && $temp_dbxref) {
1032 0           $sql_types .= " OR \n (f.type_id = $valid_type and fd.dbxref_id = $temp_dbxref)";
1033             } else {
1034 0           $sql_types .= " OR \n (f.type_id = $valid_type)";
1035             }
1036             }
1037             }
1038 0           $sql_types .= ") ";
1039             }
1040              
1041             # $factory->dbh->trace(1) if DEBUG;
1042              
1043 0 0         $srcfeature_id = $self->{srcfeature_id} if ref $self;
1044 0 0 0       if (!$srcfeature_id && defined($seq_id)) {
1045             #if the seq_id arg was passed in, we should only look on that feature
1046 0           my $srcfeature_query = "SELECT feature_id FROM feature where lower(uniquename) = ? ";
1047 0 0         $srcfeature_query .= "and organism_id = ".$factory->organism_id
1048             if $factory->organism_id;
1049 0           my $srcf_query_handle= $factory->dbh->prepare($srcfeature_query);
1050 0           $srcf_query_handle->execute(lc($seq_id));
1051 0           ($srcfeature_id) = $srcf_query_handle->fetchrow_array;
1052 0           warn "found srcfeature_id:$srcfeature_id" if DEBUG;
1053             }
1054              
1055              
1056             }
1057 0           my $select_part = "select distinct f.name,fl.fmin,fl.fmax,fl.strand,fl.phase,"
1058             ."fl.locgroup,fl.srcfeature_id,f.type_id,f.uniquename,"
1059             ."f.feature_id, af.significance as score, "
1060             ."fd.dbxref_id,f.is_obsolete ";
1061              
1062 0           my $order_by = "order by f.type_id,fl.fmin ";
1063              
1064 0           warn $feature_id if DEBUG;
1065              
1066 0           my $where_part;
1067             my $from_part;
1068 0 0         if ($feature_id) {
1069 0           $from_part = "from (feature f join featureloc fl ON (f.feature_id = fl.feature_id)) "
1070             ."left join feature_dbxref fd ON (f.feature_id = fd.feature_id
1071             AND fd.dbxref_id in (select dbxref_id from dbxref where db_id=".$factory->gff_source_db_id.")) "
1072             ."left join analysisfeature af ON (f.feature_id = af.feature_id)";
1073              
1074 0           $where_part = "where f.feature_id = $feature_id and fl.rank=0 ";
1075              
1076             ##URGI Added a sub request to get the refclass srcfeature id to map all the features from this reference region.
1077             ##We then filter and are sure that we are getting the features located on the reference feature with the good
1078             ##coordinates.
1079 0           my $refclass = $factory->name2term($factory->default_class());
1080 0   0       my $refclass_feature_id = $factory->refclass_feature_id() || undef;
1081              
1082             #In case we already have the reference class feature_id
1083 0 0 0       if(defined($refclass_feature_id) and defined($srcfeature_id)){
    0          
1084 0           $where_part .= " and fl.srcfeature_id = $refclass_feature_id ";
1085             }
1086             elsif($refclass){
1087             #From the type_id of the reference class and the feature_id we are working with
1088             #we get the srcfeature_id of the reference class feature
1089 0           my $srcquery = "select srcfeature_id ";
1090 0           $srcquery .= "from featureloc fl join feature f on (fl.srcfeature_id = f.feature_id) ";
1091 0           $srcquery .= "where fl.feature_id = ? and f.type_id = ?";
1092              
1093 0           my $sth = $factory->dbh->prepare($srcquery);
1094 0 0         $sth->execute($feature_id,$refclass) or $self->throw("refclass_srcfeature query failed");
1095 0           my $hashref = $sth->fetchrow_hashref();
1096 0   0       my $srcfeature_id = $hashref->{srcfeature_id} || undef;
1097 0 0         $where_part .= " and fl.srcfeature_id = $srcfeature_id " if(defined($srcfeature_id));
1098 0           $sth->finish;
1099             }
1100              
1101             } else {
1102 0           my ($featureslice,$morewhere);
1103 0 0 0       if ($factory->srcfeatureslice
    0 0        
      0        
      0        
1104             && $srcfeature_id
1105             && defined $interbase_start
1106             && defined $rend){
1107 0           $featureslice = "featureloc_slice($srcfeature_id,$interbase_start, $rend)";
1108 0           warn "using featureloc_slice" if DEBUG;
1109             }elsif (defined $interbase_start && defined $rend){
1110 0           $featureslice = "featureslice($interbase_start, $rend)";
1111             }else {
1112 0           $featureslice = "featureloc";
1113 0 0         $morewhere = " and fl.srcfeature_id = $srcfeature_id " if defined($srcfeature_id);
1114             }
1115 0           $from_part = "from (feature f left join $featureslice fl ON (f.feature_id = fl.feature_id)) "
1116             ."left join feature_dbxref fd ON (f.feature_id = fd.feature_id
1117             AND fd.dbxref_id in (select dbxref_id from dbxref where db_id=".$factory->gff_source_db_id.")) "
1118             ."left join analysisfeature af ON (f.feature_id = af.feature_id)";
1119              
1120 0           $where_part = "where fl.rank=0 ";
1121 0 0         $where_part .= " and $sql_types "
1122             if defined ($sql_types);
1123 0 0         $where_part .= $morewhere if $morewhere;
1124             }
1125              
1126             #the ref $self check had to be added here to make gbrowse_details work
1127             #The good news is that gbrowse_details should always be calling with the
1128             #feature_id, so this won't be needed anyway.
1129 0 0 0       $where_part .= " and f.organism_id = ".$self->factory->organism_id
1130             if (ref $self && $self->factory->organism_id);
1131              
1132 0           my $query = "$select_part\n$from_part\n$where_part\n$order_by\n";
1133              
1134             #Recursive Mapping
1135             # Construct a query that recursively maps clone's features on
1136             # the underlying chromosome
1137 0 0 0       if ($factory->recursivMapping && ! $feature_id){
1138 0           my $qFrom=$from_part;
1139 0           $qFrom =~ s/featureslice/recurs_featureslice/g;
1140 0           $query="$select_part\n$from_part\n$where_part\nUNION\n$select_part\n$qFrom\n$where_part\norder by type_id, fmin";
1141             }
1142 0           $query =~ s/\s+/ /gs if DEBUG;
1143 0           warn $query if DEBUG;
1144             #END Recursive Mapping
1145              
1146              
1147 0           $factory->dbh->do("set enable_seqscan=0");
1148             # $factory->dbh->do("set enable_hashjoin=0");
1149              
1150 0           warn "Segement->features query:$query" if DEBUG;
1151              
1152 0           my $feature_query = $factory->dbh->prepare($query);
1153              
1154 0 0         $feature_query->execute or $self->throw("feature query failed");
1155             # $factory->dbh->do("set enable_hashjoin=1");
1156 0           $factory->dbh->do("set enable_seqscan=1");
1157              
1158 0 0 0       if ($feature_query->rows < 1
      0        
      0        
1159             and $sql_types
1160             and !defined($interbase_start)
1161             and !defined($rend)) {
1162             #standard feature query failed to find anything
1163             #try looking for srcfeatures:
1164 0           my $srcfeature_query = "SELECT f.name,f.type_id,f.uniquename,f.feature_id, fd.dbxref_id,f.is_obsolete,f.seqlen FROM feature f left join feature_dbxref fd ON (f.feature_id = fd.feature_id AND fd.dbxref_id in (select dbxref_id from dbxref where db_id=2)) WHERE $sql_types order by f.type_id";
1165 0           warn "srcfeature_query:$srcfeature_query" if DEBUG;
1166              
1167 0           $feature_query = $factory->dbh->prepare($srcfeature_query);
1168 0 0         $feature_query->execute or $self->throw("srcfeature query failed");
1169             }
1170              
1171             # Old query (doesn't use RTree index):
1172             #
1173             # select distinct f.name,fl.fmin,fl.fmax,fl.strand,f.type_id,f.feature_id
1174             # from feature f, featureloc fl
1175             # where
1176             # $sql_types
1177             # fl.srcfeature_id = $srcfeature_id and
1178             # f.feature_id = fl.feature_id and
1179             # $sql_range
1180             # order by type_id
1181              
1182              
1183              
1184              
1185             #$factory->dbh->trace(0);
1186             #take these results and create a list of Bio::SeqFeatureI objects
1187             #
1188              
1189             # my $sth_srcfeature_id_to_name = $self->factory->dbh->prepare("
1190             # select name from feature where feature_id = ?;");
1191              
1192 0           while (my $hashref = $feature_query->fetchrow_hashref) {
1193              
1194 0           warn "dbstart:$$hashref{fmim}, dbstop:$$hashref{fmax}" if DEBUG;
1195 0           warn "start:$base_start, stop:$stop\n" if DEBUG;
1196              
1197 0           warn "skipping feature_id $$hashref{feature_id} because it is obsolete"
1198             if (DEBUG and
1199             $$hashref{is_obsolete} and !$self->factory->allow_obsolete);
1200 0 0 0       next if ($$hashref{is_obsolete} and !$self->factory->allow_obsolete);
1201              
1202 0 0 0       if ($feature_id &&
    0 0        
1203             defined($stop) && $stop != $$hashref{fmax} ) {
1204 0           $stop = $$hashref{fmin} + $stop + 1;
1205             } elsif (defined($$hashref{seqlen})) {
1206 0           $stop = $$hashref{seqlen};
1207             } else {
1208 0           $stop = $$hashref{fmax};
1209             }
1210              
1211 0 0 0       if ($feature_id &&
    0 0        
      0        
1212             defined($base_start) && defined($$hashref{fmin}) && $base_start != ($$hashref{fmin}+1) ) {
1213 0           my $interbase_start = $$hashref{fmin} + $base_start - 1;
1214 0           $base_start = $interbase_start + 1;
1215             } elsif (defined($$hashref{seqlen})) {
1216 0           $base_start = 1;
1217             } else {
1218 0           my $interbase_start = $$hashref{fmin};
1219 0           $base_start = $interbase_start +1;
1220             }
1221 0           warn "base_start:$base_start, end:$stop" if DEBUG;
1222              
1223 0   0       my $source = $factory->dbxref2source($$hashref{dbxref_id}) || "" ;
1224 0           my $type = Bio::DB::GFF::Typename->new(
1225             $factory->term2name($$hashref{type_id}),
1226             $source);
1227              
1228 0 0         if (defined $$hashref{seqlen}) { #this is a srcfeature
1229 0           $feat = Bio::DB::Das::Chado::Segment::Feature->new(
1230             $factory,
1231             undef,
1232             undef,
1233             $base_start,$stop,
1234             $type,
1235             undef,
1236             undef,
1237             undef,
1238             $$hashref{name},
1239             $$hashref{uniquename},
1240             $$hashref{feature_id}
1241             );
1242             }
1243             else {
1244 0 0         $feat = Bio::DB::Das::Chado::Segment::Feature->new(
    0          
1245             $factory,
1246             $feature_id? undef :$self, #only give the segment as the
1247             # parent if the feature_id wasn't
1248             # provided
1249             $feature_id ?
1250             $factory->srcfeature2name($$hashref{'srcfeature_id'})
1251             :$self->seq_id,
1252              
1253             $base_start,$stop,
1254             $type,
1255             $$hashref{score},
1256             $$hashref{strand},
1257             $$hashref{phase},
1258             $$hashref{name},
1259             $$hashref{uniquename},$$hashref{feature_id});
1260             }
1261              
1262 0           push @features, $feat;
1263              
1264 0           my $fstart = $feat->start() if DEBUG;
1265 0           my $fend = $feat->end() if DEBUG;
1266             # warn "$feat->{annotation}, $$hashref{nbeg}, $fstart, $$hashref{nend}, $fend\n" if DEBUG;
1267             }
1268              
1269 0           warn "returning @features\n" if DEBUG;
1270              
1271 0           $feature_query->finish;
1272 0 0         if ($iterator) {
    0          
    0          
1273 0           warn "using Bio::DB::Das::ChadoIterator\n" if DEBUG;
1274 0 0         return Bio::DB::Das::ChadoIterator->new(\@features) if @features;
1275             } elsif (wantarray) {
1276 0           return @features;
1277             } elsif (@features >0) {
1278 0           return \@features;
1279             } else {
1280 0           return;
1281             }
1282             }
1283              
1284             =head2 _features2level
1285              
1286             See: features
1287              
1288             Its a crude copy past from feature + additionnal code to handle
1289             prefetching of 2 levels features. The generated query is ~ as
1290             performant as the one generated by features, and the calls to
1291             Bio::DB::Das::Chado::Segment->sub_SeqFeatures are avoided, but this
1292             doesn't lead to a huge performace boost.
1293              
1294             If a further development increases the performances provided by this 2
1295             level prefetch, we will need to refactor features and _features2level
1296             to avoid code duplication
1297              
1298             =cut
1299              
1300             sub _features2level(){
1301 0     0     my $self = shift;
1302              
1303 0           warn "Segment->_features2level() args:@_\n" if DEBUG;
1304              
1305 0           my ($types,$type_placeholder,$attributes,$rangetype,$iterator,$callback,$base_start,$stop,$feature_id,$factory);
1306 0 0 0       if ($_[0] and $_[0] =~ /^-/) {
1307 0           ($types,$type_placeholder,$attributes,$rangetype,$iterator,$callback,$base_start,$stop,$feature_id,$factory) =
1308             $self->_rearrange([qw(TYPES
1309             TYPE
1310             ATTRIBUTES
1311             RANGETYPE
1312             ITERATOR
1313             CALLBACK
1314             START
1315             STOP
1316             FEATURE_ID
1317             FACTORY)],@_);
1318 0           warn "$types\n" if DEBUG;
1319             } else {
1320 0           $types = \@_;
1321             }
1322              
1323             #UGG, allow both -types and -type to be used in the args
1324 0 0 0       if ($type_placeholder and !$types) {
1325 0           $types = $type_placeholder;
1326             }
1327              
1328 0 0 0       warn "@$types\n" if (defined $types and DEBUG);
1329              
1330 0   0       $factory ||=$self->factory();
1331 0           my $feat = Bio::DB::Das::Chado::Segment::Feature->new();
1332 0           my @features;
1333              
1334              
1335 0           my ($interbase_start,$rend,$srcfeature_id,$sql_types);
1336 0 0         unless ($feature_id) {
1337 0   0       $rangetype ||='overlaps';
1338              
1339             # set range variable
1340              
1341 0           $base_start = $self->start;
1342 0           $interbase_start = $base_start -1;
1343 0           $rend = $self->end;
1344              
1345 0           $sql_types = '';
1346              
1347 0           my $valid_type = undef;
1348 0 0         if (scalar @$types != 0) {
1349              
1350 0           warn "first type:$$types[0]\n" if DEBUG;
1351              
1352 0           my $temp_type = $$types[0];
1353 0           my $temp_source = '';
1354 0 0         if ($$types[0] =~ /(.*):(.*)/) {
1355 0           $temp_type = $1;
1356 0           $temp_source = $2;
1357             }
1358              
1359 0           $valid_type = $factory->name2term($temp_type);
1360 0 0         $self->throw("feature type: '$temp_type' is not recognized") unless $valid_type;
1361              
1362 0           my $temp_dbxref = $factory->source2dbxref($temp_source);
1363 0 0 0       if ($temp_source && $temp_dbxref) {
1364 0           $sql_types .= "((f.type_id = $valid_type and fd.dbxref_id = $temp_dbxref)";
1365             } else {
1366 0           $sql_types .= "((f.type_id = $valid_type)";
1367             }
1368              
1369 0 0         if (scalar @$types > 1) {
1370 0           for (my $i=1;$i<(scalar @$types);$i++) {
1371            
1372 0           $temp_type = $$types[$i];
1373 0           $temp_source = '';
1374 0 0         if ($$types[$i] =~ /(.*):(.*)/) {
1375 0           $temp_type = $1;
1376 0           $temp_source = $2;
1377             }
1378 0           warn "more types:$$types[$i]\n" if DEBUG;
1379              
1380 0           $valid_type = $factory->name2term($temp_type);
1381 0 0         $self->throw("feature type: '$temp_type' is not recognized") unless $valid_type;
1382              
1383 0           $temp_dbxref=$factory->source2dbxref($temp_source);
1384 0 0 0       if ($temp_source && $temp_dbxref) {
1385 0           $sql_types .= " OR \n (f.type_id = $valid_type and fd.dbxref_id = $temp_dbxref)";
1386             } else {
1387 0           $sql_types .= " OR \n (f.type_id = $valid_type)";
1388             }
1389             }
1390             }
1391 0           $sql_types .= ") ";
1392             }
1393              
1394             # $factory->dbh->trace(1) if DEBUG;
1395              
1396 0           $srcfeature_id = $self->{srcfeature_id};
1397              
1398             }
1399 0           my $select_part = "select distinct f.name,fl.fmin,fl.fmax,fl.strand,fl.phase,"
1400             ."fl.locgroup,fl.srcfeature_id,f.type_id,f.uniquename,"
1401             ."f.feature_id, af.significance as score, "
1402             ."fd.dbxref_id,f.is_obsolete ";
1403              
1404 0           my $order_by = "order by f.type_id,fl.fmin ";
1405              
1406 0           my $where_part;
1407             my $from_part;
1408 0 0         if ($feature_id) {
1409 0           $from_part = "from (feature f join featureloc fl ON (f.feature_id = fl.feature_id)) "
1410             ."left join feature_dbxref fd ON
1411             (f.feature_id = fd.feature_id
1412             AND fd.dbxref_id in (select dbxref_id from dbxref where db_id=".$factory->gff_source_db_id.")) "
1413             ."left join analysisfeature af ON (af.feature_id = f.feature_id) ";
1414              
1415 0           $where_part = " where f.feature_id = $feature_id and fl.rank=0 ";
1416 0 0         $where_part .= " and f.organism_id = ".$self->factory->organism_id
1417             if $self->factory->organism_id;
1418              
1419             ##URGI Added a sub request to get the refclass srcfeature id to map all the features from this reference region.
1420             ##We then filter and are sure that we are getting the features located on the reference feature with the good
1421             ##coordinates.
1422 0           my $refclass = $factory->name2term($factory->default_class());
1423 0   0       my $refclass_feature_id = $factory->refclass_feature_id() || undef;
1424              
1425             #In case we already have the reference class feature_id
1426 0 0         if(defined($refclass_feature_id)){
    0          
1427 0           $where_part .= " and fl.srcfeature_id = $refclass_feature_id ";
1428             }
1429             elsif($refclass){
1430             #From the type_id of the reference class and the feature_id we are working with
1431             #we get the srcfeature_id of the reference class feature
1432 0           my $srcquery = "select srcfeature_id ";
1433 0           $srcquery .= "from featureloc fl join feature f on (fl.srcfeature_id = f.feature_id) ";
1434 0           $srcquery .= "where fl.feature_id = ? and f.type_id = ?";
1435              
1436 0           my $sth = $factory->dbh->prepare($srcquery,$refclass);
1437 0 0         $sth->execute($feature_id) or $self->throw("refclass_srcfeature query failed");
1438 0           my $hashref = $sth->fetchrow_hashref();
1439 0   0       my $srcfeature_id = $hashref->{srcfeature_id} || undef;
1440 0 0         $where_part .= " and fl.srcfeature_id = $srcfeature_id " if(defined($srcfeature_id));
1441 0           $sth->finish;
1442             }
1443              
1444             } else {
1445 0           my $featureslice;
1446 0 0         if ($factory->srcfeatureslice){
1447 0           $featureslice = "featureloc_slice($srcfeature_id,$interbase_start, $rend)";
1448             }else{
1449 0           $featureslice = "featureslice($interbase_start, $rend)";
1450             }
1451 0           $from_part = "from ((feature f join $featureslice fl ON (f.feature_id = fl.feature_id)) "
1452             ."left join feature_dbxref fd ON
1453             (f.feature_id = fd.feature_id
1454             AND fd.dbxref_id in (select dbxref_id from dbxref where db_id=".$factory->gff_source_db_id.")) "
1455             ."left join analysisfeature af ON (af.feature_id = f.feature_id)) "
1456             .'left join feature_relationship fr on (f.feature_id = fr.object_id) left join feature sub_f on (sub_f.feature_id = fr.subject_id) left join featureloc sub_fl on (sub_f.feature_id=sub_fl.feature_id) ';
1457              
1458 0           $where_part = "where $sql_types "
1459             ." and fl.srcfeature_id = $srcfeature_id and fl.rank=0 "
1460             .' AND (fl.locgroup=sub_fl.locgroup OR sub_fl.locgroup is null) ';
1461             }
1462              
1463            
1464              
1465 0           $select_part .= ', sub_f.name as sname,sub_fl.fmin as sfmin,sub_fl.fmax as sfmax,sub_fl.strand as sstrand,sub_fl.phase as sphase,sub_fl.locgroup as slocgroup,sub_f.type_id as stype_id,sub_f.uniquename as suniquename,sub_f.feature_id as sfeature_id';
1466 0           my $query = "$select_part\n $from_part\n$where_part\n$order_by\n";
1467              
1468              
1469              
1470              
1471 0           $query =~ s/\s+/ /gs if DEBUG;
1472 0           warn $query if DEBUG;
1473              
1474 0           warn "Segement->features query:$query" if DEBUG;
1475              
1476 0           my $sth = $factory->dbh->prepare($query);
1477              
1478 0 0         $sth->execute or $self->throw("feature query failed");
1479             # $factory->dbh->do("set enable_hashjoin=1");
1480              
1481              
1482             #2Level Optimisation
1483             #each feature is spaned over several tuples, each of which store a different SUBfeature (only one tuple if no subfeat of course)
1484              
1485 0           while (my $hashref = $sth->fetchrow_hashref) {
1486              
1487 0           warn "dbstart:$$hashref{fmim}, dbstop:$$hashref{fmax}" if DEBUG;
1488 0           warn "start:$base_start, stop:$stop\n" if DEBUG;
1489              
1490 0 0 0       next if ($$hashref{is_obsolete} and !$self->factory->allow_obsolete);
1491              
1492 0 0 0       if ( !defined ($feat->feature_id) || $feat->feature_id != $$hashref{feature_id}) {
1493             #either first feature or new feature
1494 0 0 0       if (defined ($feat->feature_id) && $feat->feature_id != $$hashref{feature_id}) {
1495             # not the first feat , adding the previous feat
1496 0           push @features, $feat;
1497              
1498             }
1499 0 0 0       if ($feature_id &&
      0        
1500             defined($stop) && $stop != $$hashref{fmax} ) {
1501 0           $stop = $$hashref{fmin} + $stop + 1;
1502             } else {
1503 0           $stop = $$hashref{fmax};
1504             }
1505 0 0 0       if ($feature_id &&
      0        
1506             defined($base_start) && $base_start != ($$hashref{fmin}+1) ) {
1507 0           my $interbase_start = $$hashref{fmin} + $base_start - 1;
1508 0           $base_start = $interbase_start + 1;
1509             } else {
1510 0           my $interbase_start = $$hashref{fmin};
1511 0           $base_start = $interbase_start +1;
1512             }
1513 0           warn "base_start:$base_start, end:$stop" if DEBUG;
1514              
1515 0   0       my $source = $factory->dbxref2source($$hashref{dbxref_id}) || "" ;
1516 0           my $type = Bio::DB::GFF::Typename->new(
1517             $factory->term2name($$hashref{type_id}),
1518             $source);
1519              
1520 0 0         $feat = Bio::DB::Das::Chado::Segment::Feature->new(
    0          
1521             $factory,
1522             $feature_id? undef :$self, #only give the segment as the
1523             # parent if the feature_id wasn't
1524             # provided
1525             $feature_id ?
1526             $factory->srcfeature2name($$hashref{'srcfeature_id'})
1527             :$self->seq_id,
1528              
1529             $base_start,$stop,
1530             $type,
1531             $$hashref{score},
1532             $$hashref{strand},
1533             $$hashref{phase},
1534             $$hashref{name},
1535             $$hashref{uniquename},
1536             $$hashref{feature_id});
1537 0           print STDERR "Created Feature obj $$hashref{name}][[$$hashref{feature_id}][$$hashref{'srcfeature_id'}]\n" if DEBUG;
1538             }
1539             #handling sub feat, if any
1540 0 0         if ($$hashref{sfeature_id}) {
1541 0 0 0       if ($feature_id &&
      0        
1542             defined($stop) && $stop != $$hashref{sfmax} ) {
1543 0           $stop = $$hashref{sfmin} + $stop + 1;
1544             } else {
1545 0           $stop = $$hashref{fmax};
1546             }
1547 0 0 0       if ($feature_id &&
      0        
1548             defined($base_start) && $base_start != ($$hashref{sfmin}+1) ) {
1549 0           my $interbase_start = $$hashref{sfmin} + $base_start - 1;
1550 0           $base_start = $interbase_start + 1;
1551             } else {
1552 0           my $interbase_start = $$hashref{sfmin};
1553 0           $base_start = $interbase_start +1;
1554             }
1555 0           warn "base_start:$base_start, end:$stop" if DEBUG;
1556              
1557 0   0       my $source = $factory->dbxref2source($$hashref{dbxref_id}) || "" ;
1558 0           my $type = Bio::DB::GFF::Typename->new(
1559             $factory->term2name($$hashref{stype_id}),
1560             $source);
1561              
1562 0 0         my $subFeat = Bio::DB::Das::Chado::Segment::Feature->new(
1563             $factory,
1564             $feat,
1565             $feature_id ? $factory->srcfeature2name($$hashref{'srcfeature_id'}):$self->seq_id,
1566             #$base_start,$stop,
1567             $$hashref{sfmin} + 1, $$hashref{sfmax},
1568             $type,
1569             $$hashref{score}, #TODO : add the subfeat score, not the feat
1570             $$hashref{sstrand},
1571             $$hashref{sphase},
1572             $$hashref{sname},
1573             $$hashref{suniquename},$$hashref{sfeature_id});
1574              
1575             #adding the subfeat to its parent, ie $feat
1576             # $feat->subfeatures($subFeat);
1577 0           $feat->add_subfeature($subFeat);
1578             #warn $feat->feature_id . ":".$feat->start ."..".$feat->end ." base_start:$base_start, end:$stop";
1579             } #end of the subfeat handling
1580            
1581              
1582 0           my $fstart = $feat->start() if DEBUG;
1583 0           my $fend = $feat->end() if DEBUG;
1584             # warn "$feat->{annotation}, $$hashref{nbeg}, $fstart, $$hashref{nend}, $fend\n" if DEBUG;
1585              
1586             } #end while hashref loop
1587              
1588             #We check if the last feature creatd is the same as the last pushed in the array
1589 0 0 0       if(@features > 0 && $features[-1]->feature_id() ne $feat->feature_id()){
1590 0           push @features, $feat;
1591             }
1592              
1593 0           $sth->finish;
1594 0 0         if ($iterator) {
    0          
1595 0           warn "using Bio::DB::Das::ChadoIterator\n" if DEBUG;
1596 0 0         return Bio::DB::Das::ChadoIterator->new(\@features) if @features;
1597             } elsif (wantarray) {
1598 0           return @features;
1599             } else {
1600 0           return \@features;
1601             }
1602             }
1603              
1604              
1605             =head2 get_all_SeqFeature, get_SeqFeatures, top_SeqFeatures, all_SeqFeatures
1606              
1607             Title : get_all_SeqFeature, get_SeqFeatures, top_SeqFeatures, all_SeqFeatures
1608             Usage : $s->get_all_SeqFeature()
1609             Function: get the sequence string for this segment
1610             Returns : a string
1611             Args : none
1612             Status : Public
1613              
1614             Several aliases of features() for backward compatibility
1615              
1616             =cut
1617              
1618             *get_all_SeqFeature = *top_SeqFeatures = *all_SeqFeatures = \&features;
1619              
1620 0     0 1   sub get_SeqFeatures {return}
1621              
1622             =head2 dna
1623              
1624             Title : dna
1625             Usage : $s->dna
1626             Function: get the dna string this segment
1627             Returns : a string
1628             Args : none
1629             Status : Public
1630              
1631             Returns the sequence for this segment as a string.
1632              
1633             =cut
1634              
1635             sub dna {
1636 0     0 1   my $self = shift;
1637 0           my %arg = @_;
1638 0           my ($ref,$class,$base_start,$stop,$strand)
1639 0           = @{$self}{qw(sourceseq class start end strand)};
1640              
1641 0           warn "ref:$ref, class:$class, $base_start..$stop, ($strand)\n" if DEBUG;
1642              
1643 0 0         if($arg{self}){
1644 0           my $r_id = $self->feature_id;
1645            
1646 0 0         $self->warn("FIXME: incomplete implementation of alternate sequence selection") if $self->verbose;
1647            
1648 0           my $sth = $self->factory->dbh->prepare("
1649             select residues from feature
1650             where feature_id = ?");
1651              
1652 0 0         $sth->execute($r_id) or $self->throw("seq query failed");
1653            
1654 0           my $array_ref = $sth->fetchrow_arrayref;
1655 0           my $seq = $$array_ref[0];
1656              
1657 0           $sth->finish;
1658 0           return $seq;
1659             }
1660              
1661 0           my $feat_id = $self->{srcfeature_id};
1662              
1663 0           my $has_start = defined $base_start;
1664 0           my $has_stop = defined $stop;
1665              
1666 0           my $reversed;
1667 0 0 0       if ($has_start && $has_stop && $base_start > $stop) {
    0 0        
      0        
1668 0           $reversed++;
1669 0           ($base_start,$stop) = ($stop,$base_start);
1670             } elsif ($strand && $strand < 0 ) {
1671 0           $reversed++;
1672             }
1673              
1674 0           my $sth;
1675 0 0 0       if (!$has_start and !$has_stop) {
    0          
    0          
1676 0           $sth = $self->factory->dbh->prepare("
1677             select residues from feature
1678             where feature_id = $feat_id ");
1679             } elsif (!$has_start) {
1680 0           $sth = $self->factory->dbh->prepare("
1681             select substring(residues for $stop) from feature
1682             where feature_id = $feat_id ");
1683             } elsif (!$has_stop) {
1684 0           $sth = $self->factory->dbh->prepare("
1685             select substring(residues from $base_start) from feature
1686             where feature_id = $feat_id ");
1687             } else { #has both start and stop
1688 0           my $sslen = $stop-$base_start+1;
1689 0           $sth = $self->factory->dbh->prepare("
1690             select substring(residues from $base_start for $sslen) from feature
1691             where feature_id = $feat_id ");
1692             }
1693              
1694 0 0         $sth->execute or $self->throw("seq query failed");
1695            
1696 0           my $array_ref = $sth->fetchrow_arrayref;
1697 0           my $seq = $$array_ref[0];
1698 0           $sth->finish;
1699              
1700 0 0         if ($reversed) {
1701 0           $seq = reverse $seq;
1702 0           $seq =~ tr/gatcGATC/ctagCTAG/;
1703             }
1704              
1705 0           return $seq;
1706             }
1707              
1708             sub subseq {
1709 0     0 1   my $self = shift;
1710 0           my ($start, $stop) = @_;
1711 0           $start--;
1712              
1713 0           my $dna = $self->dna;
1714 0           my $length = $stop - $start + 1;
1715              
1716 0           my $substr = substr($dna, $start, $length);
1717              
1718 0           my $subseqobj = Bio::Seq->new( -display_id => $self->seq_id,
1719             -seq => $substr);
1720              
1721 0           return $subseqobj;
1722             }
1723              
1724             =head2 seq
1725              
1726             Title : seq
1727             Usage : $s->seq
1728             Function: get a Bio::Seq object for this segment
1729             Returns : a Bio::Seq object
1730             Args : none
1731             Status : Public
1732              
1733             Returns the sequence for this segment as a Bio::Seq object.
1734              
1735             =cut
1736              
1737             sub seq {
1738 0     0 1   my $self = shift;
1739              
1740 0           my $seqobj = Bio::Seq->new(
1741             -display_id => $self->seq_id
1742             .":".$self->start
1743             ."..".$self->end,
1744             -seq => $self->dna,
1745             );
1746              
1747 0           return $seqobj;
1748             }
1749              
1750             *protein = \&dna;
1751              
1752             =head2 factory
1753              
1754             Title : factory
1755             Usage : $factory = $s->factory
1756             Function: return the segment factory
1757             Returns : a Bio::DasI object
1758             Args : see below
1759             Status : Public
1760              
1761             This method returns a Bio::DasI object that can be used to fetch
1762             more segments. This is typically the Bio::DasI object from which
1763             the segment was originally generated.
1764              
1765             =cut
1766              
1767 0     0 1   sub factory {my $self = shift;
1768 0 0         confess "self is not an object" unless ref $self;
1769 0           return $self->{factory} }
1770              
1771             =head2 srcfeature_id
1772              
1773             Title : srcfeature_id
1774             Usage : $obj->srcfeature_id($newval)
1775             Function: undocumented method by Scott Cain
1776             Returns : value of srcfeature_id (a scalar)
1777             Args : on set, new value (a scalar or undef, optional)
1778              
1779              
1780             =cut
1781              
1782             sub srcfeature_id {
1783 0     0 1   my $self = shift;
1784              
1785 0 0         return $self->{'srcfeature_id'} = shift if @_;
1786            
1787 0           confess "how did I get into srcfeature_id method" if (DEBUG and !ref $self);
1788 0           return $self->{'srcfeature_id'};
1789             }
1790              
1791             =head2 source
1792              
1793             Title : source
1794             Usage : $obj->source($newval)
1795             Function: Returns the source; sets with an argument
1796             Returns : A string that is the source
1797             Args : A string to set the source
1798              
1799             =cut
1800              
1801             sub source {
1802 0     0 1   my $self = shift;
1803 0           my $source;
1804              
1805 0 0         return $self->{'source'} = shift if @_;
1806 0 0         return $self->{'source'} if defined ($self->{'source'});
1807            
1808             #fine, not set, get by query
1809              
1810 0           my $query = "SELECT dbx.accession FROM feature_dbxref fd
1811             JOIN dbxref dbx USING (dbxref_id)
1812             WHERE fd.feature_id = ?
1813             AND dbx.db_id = ?";
1814 0           my $sth = $self->factory->dbh->prepare($query);
1815 0 0         $sth->execute($self->feature_id, $self->factory->gff_source_db_id)
1816             or $self->throw("failed to get source via query");
1817              
1818 0           ($source) = $sth->fetchrow_array;
1819              
1820 0           $sth->finish;
1821 0           return $source;
1822             }
1823              
1824             =head2 source_tag
1825              
1826             Title : source_tag
1827             Function: aliased to source() for Bio::SeqFeatureI compatibility
1828              
1829             =cut
1830              
1831             *source_tag = \&source;
1832              
1833             =head2 alphabet
1834              
1835             Title : alphabet
1836             Usage : $obj->alphabet($newval)
1837             Function: Returns the sequence "type", ie, dna
1838             Returns : scalar 'dna'
1839             Args : None
1840              
1841              
1842             =cut
1843              
1844             sub alphabet {
1845 0     0 1   return 'dna';
1846             }
1847              
1848             =head2 display_id, display_name, accession_number, desc
1849              
1850             Title : display_id, display_name, accession_number, desc
1851             Usage : $s->display_name()
1852             Function: Alias of name()
1853             Returns : string
1854             Args : none
1855              
1856             Several aliases for name; it may be that these could do something better than
1857             just giving back the name.
1858              
1859             =cut
1860              
1861             *display_id = *display_name = *accession_number = \&name;
1862             # *desc =
1863              
1864             #dgg patch for SeqI.desc -- use ref segment Note property for description
1865             sub desc {
1866 0     0 1   my $self= shift;
1867 0 0         return $self->{'desc'} if defined $self->{'desc'};
1868              
1869 0           my $sth = $self->factory->dbh->prepare( "select value from featureprop
1870             where feature_id = ? and type_id in (select cvterm_id from cvterm where name = 'Note') ");
1871 0           $sth->execute( $self->feature_id );
1872 0           my $hashref = $sth->fetchrow_hashref();
1873              
1874 0           $sth->finish;
1875 0           return $self->{'desc'}= $hashref->{value};
1876             }
1877              
1878             #dgg patch for SeqI -- Bio::SeqI::species
1879             sub species {
1880 0     0 1   my $self= shift;
1881 0 0         return $self->{'species'} if defined $self->{'species'};
1882              
1883 0           my $sth = $self->factory->dbh->prepare( "select genus,species from organism
1884             where organism_id = (select organism_id from feature where feature_id = ?) ");
1885 0           cluck "i'm in species";
1886 0           $sth->execute( $self->srcfeature_id );
1887 0           my $hashref = $sth->fetchrow_hashref();
1888 0           $sth->finish;
1889            
1890             ## this is dying; why? dgg
1891             # my $spp= Bio::Species->new( -classification => [ $hashref->{species}, $hashref->{genus} ] );
1892            
1893 0           my $spp= $hashref->{genus}.' '.$hashref->{species}; # works for display uses
1894 0           return $self->{'species'}= $spp;
1895             }
1896              
1897              
1898             =head2 primary_seq
1899              
1900             Title : primary_seq
1901             Usage : $s->primary_seq()
1902             Function: Get a Bio::PrimarySeqI compliant object
1903             Returns : Bio::PrimarySeqI
1904             Args : none
1905              
1906             =cut
1907              
1908             sub primary_seq {
1909 0     0 1   my $self = shift;
1910              
1911 0           return Bio::PrimarySeq->new(
1912             -seq => $self->seq->seq,
1913             -display_id => $self->display_id,
1914             -accession_number => $self->accession_number,
1915             -primary_id => $self->primary_id,
1916             -desc => $self->desc,
1917             );
1918             }
1919              
1920              
1921             =head2 get_feature_stream
1922              
1923             Title : get_feature_stream
1924             Usage : $db->get_feature_stream(@args)
1925             Function: creates a feature iterator
1926             Returns : A Bio::DB::Das::ChadoIterator object
1927             Args : The same arguments as the feature method
1928              
1929             get_feature_stream has an alias called get_seq_stream for backward
1930             compatability.
1931              
1932             =cut
1933              
1934             sub get_feature_stream {
1935 0     0 1   my $self = shift;
1936 0           my @args = @_;
1937 0           warn "get_feature_stream args: @_\n" if DEBUG;
1938 0           my $features = $self->features(@args);
1939 0           warn "using get_feature_stream\n" if DEBUG;
1940 0           warn "feature array: $features\n" if DEBUG;
1941 0           warn "first feature: $$features[0]\n" if DEBUG;
1942 0 0         return Bio::DB::Das::ChadoIterator->new($features) if $features;
1943 0           return Bio::DB::Das::ChadoIterator->new([]);
1944             }
1945              
1946             #dgg patch for DasI need
1947             *get_seq_stream = \&get_feature_stream;
1948              
1949             =head2 clone
1950              
1951             Title : clone
1952             Usage : $copy = $s->clone
1953             Function: make a copy of this segment
1954             Returns : a Bio::DB::GFF::Segment object
1955             Args : none
1956             Status : Public
1957              
1958             =cut
1959              
1960             # deep copy of the thing
1961             sub clone {
1962 0     0 1   my $self = shift;
1963 0           my %h = %$self;
1964 0           return bless \%h,ref($self);
1965             }
1966              
1967             =head2 sourceseq
1968              
1969             Title : sourceseq
1970             Usage : $obj->sourceseq($newval)
1971             Function: undocumented method by Scott Cain
1972             Returns : value of sourceseq (a scalar)
1973             Args : on set, new value (a scalar or undef, optional)
1974              
1975              
1976             =cut
1977              
1978             sub sourceseq {
1979 0     0 1   my $self = shift;
1980              
1981 0 0         return $self->{'sourceseq'} if $self->{'sourceseq'};
1982              
1983 0           my $dbh = $self->factory->dbh;
1984 0           my $sourceseq_query = $dbh->prepare("
1985             select name from feature where feature_id = ?");
1986              
1987 0 0         $sourceseq_query->execute($self->srcfeature_id)
1988             or $self->throw("getting sourceseq name query failed");
1989              
1990 0 0         return if $sourceseq_query->rows < 1;
1991 0           my $hashref = $sourceseq_query->fetchrow_hashref;
1992            
1993 0           $sourceseq_query->finish;
1994 0           $self->{'sourceseq'} = $$hashref{'name'};
1995 0           return $self->{'sourceseq'};
1996             }
1997              
1998             =head2 refseq
1999              
2000             Title : refseq
2001             Usage : $s->refseq
2002             Function: get or set the reference sequence
2003             Returns : a string
2004             Args : none
2005             Status : Public
2006              
2007             Examine or change the reference sequence. This is an alias to
2008             sourceseq(), provided here for API compatibility with
2009             Bio::DB::GFF::RelSegment.
2010              
2011             =cut
2012              
2013             *refseq = \&sourceseq;
2014              
2015             =head2 abs_ref
2016              
2017             Title : abs_ref
2018             Usage : $obj->abs_ref()
2019             Function: Alias of sourceseq
2020             Returns : value of sourceseq (a scalar)
2021             Args : none
2022              
2023             Alias of sourceseq for backward compatibility
2024              
2025             =cut
2026              
2027             *abs_ref = \&sourceseq;
2028              
2029             =head2 abs_start
2030              
2031             Title : abs_start
2032             Usage : $obj->abs_start()
2033             Function: Alias of start
2034             Returns : value of start (a scalar)
2035             Args : none
2036              
2037             =cut
2038              
2039             *abs_start = \&start;
2040              
2041             =head2 abs_end
2042              
2043             Title : abs_end
2044             Usage : $obj->abs_end()
2045             Function: Alias of end
2046             Returns : value of end (a scalar)
2047             Args : none
2048              
2049             =cut
2050              
2051             *abs_end = \&end;
2052              
2053             =head2 asString
2054              
2055             Title : asString
2056             Usage : $s->asString
2057             Function: human-readable string for segment
2058             Returns : a string
2059             Args : none
2060             Status : Public
2061              
2062             Returns a human-readable string representing this sequence. Format
2063             is:
2064              
2065             sourceseq:start,stop
2066              
2067             =cut
2068              
2069             sub asString {
2070 0     0 1   my $self = shift;
2071 0 0         unless (ref $self) {
2072 0           warn "in asString with no self";
2073 0 0         return unless ref $self;
2074             }
2075 0           my $label = $self->refseq;
2076 0           my $start = $self->start;
2077 0           my $stop = $self->stop;
2078 0           return "$label:$start,$stop";
2079             }
2080              
2081             sub rel2abs {
2082 0     0 0   shift;
2083 0           return @_;
2084             }
2085              
2086              
2087             1;