~ubuntu-branches/ubuntu/raring/bioperl/raring

« back to all changes in this revision

Viewing changes to Bio/Location/Fuzzy.pm

  • Committer: Bazaar Package Importer
  • Author(s): Charles Plessy
  • Date: 2008-03-18 14:44:57 UTC
  • mfrom: (4 hardy)
  • mto: This revision was merged to the branch mainline in revision 6.
  • Revision ID: james.westby@ubuntu.com-20080318144457-1jjoztrvqwf0gruk
* debian/control:
  - Removed MIA Matt Hope (dopey) from the Uploaders field.
    Thank you for your work, Matt. I hope you are doing well.
  - Downgraded some recommended package to the 'Suggests' priority,
    according to the following discussion on Upstream's mail list.
    http://bioperl.org/pipermail/bioperl-l/2008-March/027379.html
    (Closes: #448890)
* debian/copyright converted to machine-readable format.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# $Id: Fuzzy.pm,v 1.26 2003/09/24 13:46:02 jason Exp $
 
1
# $Id: Fuzzy.pm,v 1.33.4.2 2006/10/02 23:10:21 sendu Exp $
2
2
#
3
3
# BioPerl module for Bio::Location::Fuzzy
4
4
# Cared for by Jason Stajich <jason@bioperl.org>
16
16
=head1 SYNOPSIS
17
17
 
18
18
    use Bio::Location::Fuzzy;
19
 
    my $fuzzylocation = new Bio::Location::Fuzzy(-start => '<30',
20
 
                                                 -end   => 90,
21
 
                                                 -location_type => '..');
 
19
    my $fuzzylocation = new Bio::Location::Fuzzy(
 
20
                                                 -start => '<30',
 
21
                                                 -end   => 90,
 
22
                                                 -location_type => '..');
22
23
 
23
24
    print "location string is ", $fuzzylocation->to_FTstring(), "\n";
24
25
    print "location is of the type ", $fuzzylocation->location_type, "\n";
32
33
E<lt>100..300 meaning it starts somewhere before 100.  Advanced
33
34
implementations of this interface may be able to handle the necessary
34
35
logic of overlaps/intersection/contains/union.  It was constructed to
35
 
handle fuzzy locations that can be represented in Genbank/EMBL.
 
36
handle fuzzy locations that can be represented in Genbank/EMBL and
 
37
Swissprot.
36
38
 
37
39
=head1 FEEDBACK
38
40
 
40
42
Bioperl modules. Send your comments and suggestions preferably to one
41
43
of the Bioperl mailing lists.  Your participation is much appreciated.
42
44
 
43
 
  bioperl-l@bioperl.org             - General discussion
44
 
  http://bio.perl.org/MailList.html - About the mailing lists
 
45
  bioperl-l@bioperl.org                  - General discussion
 
46
  http://bioperl.org/wiki/Mailing_lists  - About the mailing lists
45
47
 
46
48
=head2 Reporting Bugs
47
49
 
48
50
Report bugs to the Bioperl bug tracking system to help us keep track
49
 
the bugs and their resolution.  Bug reports can be submitted via email
50
 
or the web:
 
51
the bugs and their resolution.  Bug reports can be submitted via the
 
52
web:
51
53
 
52
 
  bioperl-bugs@bio.perl.org
53
 
  http://bugzilla.bioperl.org/
 
54
  http://bugzilla.open-bio.org/
54
55
 
55
56
=head1 AUTHOR - Jason Stajich
56
57
 
57
 
Email jason@bioperl.org
 
58
Email jason-at-bioperl-dot-org
58
59
 
59
60
=head1 APPENDIX
60
61
 
66
67
# Let the code begin...
67
68
 
68
69
package Bio::Location::Fuzzy;
69
 
use vars qw(@ISA );
70
70
use strict;
71
71
 
72
 
use Bio::Location::FuzzyLocationI;
73
 
use Bio::Location::Atomic;
74
 
 
75
 
@ISA = qw(Bio::Location::Atomic Bio::Location::FuzzyLocationI );
76
 
 
77
 
BEGIN {
78
 
    use vars qw( %FUZZYCODES %FUZZYPOINTENCODE %FUZZYRANGEENCODE 
79
 
                 @LOCATIONCODESBSANE );
80
 
 
81
 
    @LOCATIONCODESBSANE = (undef, 'EXACT', 'WITHIN', 'BETWEEN',
82
 
                        'BEFORE', 'AFTER');
83
 
 
84
 
    %FUZZYCODES = ( 'EXACT' => '..', # Position is 'exact
 
72
use base qw(Bio::Location::Atomic Bio::Location::FuzzyLocationI);
 
73
 
 
74
our @LOCATIONCODESBSANE = (undef, 'EXACT', 'WITHIN', 'BETWEEN', 'UNCERTAIN',
 
75
            'BEFORE', 'AFTER');
 
76
 
 
77
our %FUZZYCODES = ( 'EXACT' => '..', # Position is 'exact
85
78
   # Exact position is unknown, but is within the range specified, ((1.2)..100)
86
 
                    'WITHIN' => '.', 
87
 
                    # 1^2
88
 
                    'BETWEEN' => '^',
89
 
                    # <100
90
 
                    'BEFORE'  => '<',
91
 
                    # >10
92
 
                    'AFTER'   => '>');   
 
79
            'WITHIN' => '.', 
 
80
            # 1^2
 
81
            'BETWEEN'    => '^',
 
82
            'IN-BETWEEN' => '^',
 
83
            'UNCERTAIN'  => '?',
 
84
            # <100
 
85
            'BEFORE'  => '<',
 
86
            # >10
 
87
            'AFTER'   => '>');   
93
88
   
94
89
    # The following regular expressions map to fuzzy location types. Every
95
90
    # expression must match the complete encoded point string, and must
96
91
    # contain two groups identifying min and max. Empty matches are automatic.
97
92
    # converted to undef, except for 'EXACT', for which max is set to equal
98
93
    # min.
99
 
    %FUZZYPOINTENCODE = ( 
100
 
                          '\>(\d+)(.{0})' => 'AFTER',
101
 
                          '\<(.{0})(\d+)' => 'BEFORE',
102
 
                          '(\d+)'  => 'EXACT',
103
 
                          '(\d+)(.{0})\>' => 'AFTER',
104
 
                          '(.{0})(\d+)\<' => 'BEFORE',
105
 
                          '(\d+)\.(\d+)' => 'WITHIN',
106
 
                          '(\d+)\^(\d+)' => 'BETWEEN',
107
 
                     );
108
 
    
109
 
    %FUZZYRANGEENCODE  = ( '\.' => 'WITHIN',
110
 
                           '\.\.' => 'EXACT',
111
 
                           '\^' => 'BETWEEN' );
112
 
 
113
 
}
 
94
    
 
95
our %FUZZYPOINTENCODE = ( 
 
96
    '\>(\d+)(.{0})' => 'AFTER',
 
97
    '\<(.{0})(\d+)' => 'BEFORE',
 
98
    '(\d+)'         => 'EXACT',
 
99
    '\?(\d*)'       => 'UNCERTAIN',
 
100
    '(\d+)(.{0})\>' => 'AFTER',
 
101
    '(.{0})(\d+)\<' => 'BEFORE',
 
102
    '(\d+)\.(\d+)'  => 'WITHIN',
 
103
    '(\d+)\^(\d+)'  => 'BETWEEN',
 
104
   );
 
105
    
 
106
our %FUZZYRANGEENCODE  = (  '\.'   => 'WITHIN',
 
107
                            '\.\.' => 'EXACT',
 
108
                            '\^'   => 'IN-BETWEEN' );
114
109
 
115
110
=head2 new
116
111
 
121
116
 Args    : -start    => value for start  (initialize by superclass)
122
117
           -end      => value for end    (initialize by superclass)
123
118
           -strand   => value for strand (initialize by superclass)
124
 
           -location_type => either ('EXACT', 'WITHIN', 'BETWEEN') OR
125
 
                               ( 1,2,3)
 
119
           -location_type => either ('EXACT','WITHIN','IN-BETWEEN',
 
120
                             'UNCERTAIN') OR ( 1,2,3,4)
126
121
           -start_ext=> extension for start - defaults to 0, 
127
122
           -start_fuz=  fuzzy code for start can be 
128
 
                      ( 'EXACT', 'WITHIN', 'BETWEEN', 'BEFORE', 'AFTER') OR
 
123
                      ('EXACT','WITHIN','BETWEEN','BEFORE','AFTER',
 
124
                       'UNCERTAIN' ) OR
129
125
                      a value 1 - 5 corresponding to index+1 above
130
126
           -end_ext=> extension for end - defaults to 0, 
131
127
           -end_fuz=  fuzzy code for end can be 
132
 
                      ( 'EXACT', 'WITHIN', 'BETWEEN', 'BEFORE', 'AFTER') OR
 
128
                      ('EXACT','WITHIN','BETWEEN','BEFORE','AFTER',
 
129
                       'UNCERTAIN') OR
133
130
                      a value 1 - 5 corresponding to index+1 above
134
131
 
135
132
=cut
138
135
    my ($class, @args) = @_;
139
136
    my $self = $class->SUPER::new(@args);
140
137
    my ($location_type, $start_ext, $start_fuz, $end_ext, $end_fuz) = 
141
 
        $self->_rearrange([ qw(LOCATION_TYPE START_EXT START_FUZ 
142
 
                               END_EXT END_FUZ )
143
 
                            ], @args);
 
138
        $self->_rearrange([ qw(LOCATION_TYPE START_EXT START_FUZ 
 
139
                   END_EXT END_FUZ )
 
140
                ], @args);
144
141
 
145
142
    $location_type  && $self->location_type($location_type);
146
143
    $start_ext && $self->max_start($self->min_start + $start_ext);
156
153
  Title   : location_type
157
154
  Usage   : my $location_type = $location->location_type();
158
155
  Function: Get location type encoded as text
159
 
  Returns : string ('EXACT', 'WITHIN', 'BETWEEN')
 
156
  Returns : string ('EXACT', 'WITHIN', 'IN-BETWEEN', 'UNCERTAIN')
160
157
  Args    : none
161
158
 
162
159
=cut
164
161
sub location_type {
165
162
    my ($self,$value) = @_;
166
163
    if( defined $value || ! defined $self->{'_location_type'} ) {
167
 
        $value = 'EXACT' unless defined $value;
168
 
        if(! defined $FUZZYCODES{$value})  {
169
 
            $value = uc($value);
170
 
            if( $value =~ /\.\./ ) {
171
 
                $value = 'EXACT';
172
 
            } elsif( $value =~ /^\.$/ ) {
173
 
                $value = 'WITHIN';
174
 
            } elsif( $value =~ /\^/ ) {
175
 
                $value = 'BETWEEN';
176
 
 
177
 
 
178
 
                $self->throw("Use Bio::Location::Simple for IN-BETWEEN locations [". $self->start. "] and [". $self->end. "]")
179
 
                    if defined $self->start && defined $self->end && ($self->end - 1 == $self->start);
180
 
 
181
 
 
182
 
            } elsif( $value ne 'EXACT' && $value ne 'WITHIN' && 
183
 
                     $value ne 'BETWEEN' ) {
184
 
                $self->throw("Did not specify a valid location type");
185
 
            }
186
 
        }
187
 
        $self->{'_location_type'} = $value;
 
164
        $value = 'EXACT' unless defined $value;
 
165
        if(! defined $FUZZYCODES{$value} )  {
 
166
            $value = uc($value);
 
167
            if( $value =~ /\.\./ ) {
 
168
                $value = 'EXACT';
 
169
            } elsif( $value =~ /^\.$/ ) {
 
170
                $value = 'WITHIN';
 
171
            } elsif( $value =~ /\^/ ) {
 
172
                $value = 'IN-BETWEEN';
 
173
                $self->throw("Use Bio::Location::Simple for IN-BETWEEN locations [".
 
174
                             $self->start. "] and [". $self->end. "]")
 
175
                  if defined $self->start && defined $self->end &&
 
176
                            ($self->end - 1 == $self->start);
 
177
            } elsif( $value =~ /\?/ ) {
 
178
                $value = 'UNCERTAIN';
 
179
            } elsif( $value ne 'EXACT' && $value ne 'WITHIN' && 
 
180
                        $value ne 'IN-BETWEEN' ) {
 
181
                $self->throw("Did not specify a valid location type");
 
182
            }
 
183
        }
 
184
        $self->{'_location_type'} = $value;
188
185
    }
189
186
    return $self->{'_location_type'};
190
187
}
226
223
sub start {
227
224
    my($self,$value) = @_;
228
225
    if( defined $value ) {
229
 
        my ($encode,$min,$max) = $self->_fuzzypointdecode($value);
230
 
        $self->start_pos_type($encode);
231
 
        $self->min_start($min);
232
 
        $self->max_start($max);
 
226
    my ($encode,$min,$max) = $self->_fuzzypointdecode($value);
 
227
    $self->start_pos_type($encode);
 
228
    $self->min_start($min);
 
229
    $self->max_start($max);
233
230
    }
234
231
 
235
 
    $self->throw("Use Bio::Location::Simple for IN-BETWEEN locations [". $self->SUPER::start. "] and [". $self->SUPER::end. "]")
236
 
        if $self->location_type eq 'BETWEEN'  && defined $self->SUPER::end && ($self->SUPER::end - 1 == $self->SUPER::start);
 
232
    $self->throw("Use Bio::Location::Simple for IN-BETWEEN locations ["
 
233
                 . $self->SUPER::start. "] and [". $self->SUPER::end. "]")
 
234
    if $self->location_type eq 'IN-BETWEEN'  && defined $self->SUPER::end &&
 
235
                  ($self->SUPER::end - 1 == $self->SUPER::start);
237
236
 
238
237
    return $self->SUPER::start();
239
238
}
251
250
sub end {
252
251
    my($self,$value) = @_;
253
252
    if( defined $value ) {
254
 
        my ($encode,$min,$max) = $self->_fuzzypointdecode($value);
255
 
        $self->end_pos_type($encode);
256
 
        $self->min_end($min);
257
 
        $self->max_end($max);
 
253
    my ($encode,$min,$max) = $self->_fuzzypointdecode($value);
 
254
    $self->end_pos_type($encode);
 
255
    $self->min_end($min);
 
256
    $self->max_end($max);
258
257
    }
259
258
 
260
 
    $self->throw("Use Bio::Location::Simple for IN-BETWEEN locations [". $self->SUPER::start. "] and [". $self->SUPER::end. "]")
261
 
        if $self->location_type eq 'BETWEEN' && defined $self->SUPER::start && ($self->SUPER::end - 1 == $self->SUPER::start);
 
259
    $self->throw("Use Bio::Location::Simple for IN-BETWEEN locations [".
 
260
                 $self->SUPER::start. "] and [". $self->SUPER::end. "]")
 
261
    if $self->location_type eq 'IN-BETWEEN' && defined $self->SUPER::start &&
 
262
                ($self->SUPER::end - 1 == $self->SUPER::start);
262
263
 
263
264
    return $self->SUPER::end();
264
265
}
277
278
    my ($self,@args) = @_;
278
279
 
279
280
    if(@args) {
280
 
        $self->{'_min_start'} = $args[0]; # the value may be undef!
 
281
    $self->{'_min_start'} = $args[0]; # the value may be undef!
281
282
    }
282
283
    return $self->{'_min_start'};
283
284
}
296
297
    my ($self,@args) = @_;
297
298
 
298
299
    if(@args) {
299
 
        $self->{'_max_start'} = $args[0]; # the value may be undef!
 
300
        $self->{'_max_start'} = $args[0]; # the value may be undef!
300
301
    }
301
302
    return $self->{'_max_start'};
302
303
}
307
308
  Usage   : my $start_pos_type = $location->start_pos_type();
308
309
  Function: Get/set start position type.
309
310
  Returns : type of position coded as text 
310
 
            ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
 
311
            ('BEFORE','AFTER','EXACT','WITHIN','BETWEEN','UNCERTAIN')
311
312
  Args    : a string on set
312
313
 
313
314
=cut
315
316
sub start_pos_type {
316
317
    my ($self,$value) = @_;
317
318
    if(defined $value &&  $value =~ /^\d+$/ ) {
318
 
        if( $value == 0 ) { $value = 'EXACT'; }
319
 
        else { 
320
 
            my $v = $LOCATIONCODESBSANE[$value];
321
 
            if( ! defined $v ) {
322
 
                $self->warn("Provided value $value which I don't understand, reverting to 'EXACT'");
323
 
                $v = 'EXACT';
324
 
            }
325
 
            $value = $v;
326
 
        }
 
319
        if( $value == 0 ) { $value = 'EXACT'; }
 
320
        else { 
 
321
            my $v = $LOCATIONCODESBSANE[$value];
 
322
            if( ! defined $v ) {
 
323
                $self->warn("Provided value $value which I don't understand,".
 
324
                            " reverting to 'EXACT'");
 
325
                $v = 'EXACT';
 
326
            }
 
327
            $value = $v;
 
328
        }
327
329
    }
328
330
    if(defined($value)) {
329
 
        $self->{'_start_pos_type'} = $value;
 
331
        $self->{'_start_pos_type'} = $value;
330
332
    }
331
333
    return $self->{'_start_pos_type'};
332
334
}
345
347
    my ($self,@args) = @_;
346
348
 
347
349
    if(@args) {
348
 
        $self->{'_min_end'} = $args[0]; # the value may be undef!
 
350
        $self->{'_min_end'} = $args[0]; # the value may be undef!
349
351
    }
350
352
    return $self->{'_min_end'};
351
353
}
364
366
    my ($self,@args) = @_;
365
367
 
366
368
    if(@args) {
367
 
        $self->{'_max_end'} = $args[0]; # the value may be undef!
 
369
        $self->{'_max_end'} = $args[0]; # the value may be undef!
368
370
    }
369
371
    return $self->{'_max_end'};
370
372
}
375
377
  Usage   : my $end_pos_type = $location->end_pos_type();
376
378
  Function: Get/set end position type.
377
379
  Returns : type of position coded as text 
378
 
            ('BEFORE', 'AFTER', 'EXACT','WITHIN', 'BETWEEN')
 
380
            ('BEFORE','AFTER','EXACT','WITHIN','BETWEEN','UNCERTAIN')
379
381
  Args    : a string on set
380
382
 
381
383
=cut
383
385
sub end_pos_type {
384
386
    my ($self,$value) = @_;
385
387
    if( defined $value && $value =~ /^\d+$/ ) {
386
 
        if( $value == 0 ) { $value = 'EXACT'; }
387
 
        else { 
388
 
            my $v = $LOCATIONCODESBSANE[$value];
389
 
            if( ! defined $v ) {
390
 
                $self->warn("Provided value $value which I don't understand, reverting to 'EXACT'");
391
 
                $v = 'EXACT';
392
 
            }
393
 
            $value = $v;
394
 
        }
 
388
        if( $value == 0 ) { $value = 'EXACT'; }
 
389
        else { 
 
390
            my $v = $LOCATIONCODESBSANE[$value];
 
391
            if( ! defined $v ) {
 
392
                $self->warn("Provided value $value which I don't understand,".
 
393
                            " reverting to 'EXACT'");
 
394
                $v = 'EXACT';
 
395
            }
 
396
            $value = $v;
 
397
        }
395
398
    }
396
399
 
397
400
    if(defined($value)) {
398
 
        $self->{'_end_pos_type'} = $value;
 
401
        $self->{'_end_pos_type'} = $value;
399
402
    }
400
403
    return $self->{'_end_pos_type'};
401
404
}
413
416
=head2 coordinate_policy
414
417
 
415
418
  Title   : coordinate_policy
 
419
 
416
420
  Usage   : $policy = $location->coordinate_policy();
417
421
            $location->coordinate_policy($mypolicy); # set may not be possible
418
422
  Function: Get the coordinate computing policy employed by this object.
435
439
  Returns : A Bio::Location::CoordinatePolicyI implementing object.
436
440
  Args    : On set, a Bio::Location::CoordinatePolicyI implementing object.
437
441
 
 
442
See L<Bio::Location::CoordinatePolicyI>
 
443
 
438
444
=cut
439
445
 
440
446
=head2 to_FTstring
448
454
=cut
449
455
 
450
456
sub to_FTstring {
451
 
    my ($self) = @_;
 
457
    my ($self) = @_;    
452
458
    my (%vals) = ( 'start' => $self->start,
453
 
                   'min_start' => $self->min_start,
454
 
                   'max_start' => $self->max_start,
455
 
                   'start_code' => $self->start_pos_type,
456
 
                   'end' => $self->end,
457
 
                   'min_end' => $self->min_end,
458
 
                   'max_end' => $self->max_end,
459
 
                   'end_code' => $self->end_pos_type );
460
 
    
 
459
           'min_start' => $self->min_start,
 
460
           'max_start' => $self->max_start,
 
461
           'start_code' => $self->start_pos_type,
 
462
           'end' => $self->end,
 
463
           'min_end' => $self->min_end,
 
464
           'max_end' => $self->max_end,
 
465
           'end_code' => $self->end_pos_type );
 
466
 
461
467
    my (%strs) = ( 'start' => '',
462
 
                   'end'   => '');
 
468
           'end'   => '');
463
469
    my ($delimiter) = $FUZZYCODES{$self->location_type};
 
470
    $delimiter = $FUZZYCODES{'EXACT'} if ($self->location_type eq 'UNCERTAIN');
 
471
    
 
472
    my $policy = ref($self->coordinate_policy);
 
473
    
464
474
    # I'm lazy, lets do this in a loop since behaviour will be the same for 
465
475
    # start and end
 
476
    # The CoordinatePolicy now dictates start/end data here (bug 992) - cjf
466
477
    foreach my $point ( qw(start end) ) {
467
 
        if( $vals{$point."_code"} ne 'EXACT' ) {
468
 
            
469
 
            if( (!defined $vals{"min_$point"} ||
470
 
                 !defined $vals{"max_$point"})
471
 
                && ( $vals{$point."_code"} eq 'WITHIN' || 
472
 
                     $vals{$point."_code"} eq 'BETWEEN')
473
 
                     ) {
474
 
                $vals{"min_$point"} = '' unless defined $vals{"min_$point"};
475
 
                $vals{"max_$point"} = '' unless defined $vals{"max_$point"};
476
 
                
477
 
                $self->warn("Fuzzy codes for start are in a strange state, (".
478
 
                            join(",", ($vals{"min_$point"}, 
479
 
                                       $vals{"max_$point"},
480
 
                                       $vals{$point."_code"})). ")");
481
 
                return '';
482
 
            }
483
 
            if( defined $vals{$point."_code"} && 
484
 
                ($vals{$point."_code"} eq 'BEFORE' ||
485
 
                 $vals{$point."_code"} eq 'AFTER')
486
 
                ) {
487
 
                $strs{$point} .= $FUZZYCODES{$vals{$point."_code"}};
488
 
            } 
489
 
            if( defined $vals{"min_$point"} ) {
490
 
                $strs{$point} .= $vals{"min_$point"};
491
 
            }
492
 
            if( defined $vals{$point."_code"} && 
493
 
                ($vals{$point."_code"} eq 'WITHIN' ||
494
 
                 $vals{$point."_code"} eq 'BETWEEN')
495
 
                ) {
496
 
                $strs{$point} .= $FUZZYCODES{$vals{$point."_code"}};
497
 
            }
498
 
            if( defined $vals{"max_$point"} ) {
499
 
                $strs{$point} .= $vals{"max_$point"};
500
 
            }
501
 
            if(($vals{$point."_code"} eq 'WITHIN') || 
502
 
               ($vals{$point."_code"} eq 'BETWEEN')) {
503
 
                $strs{$point} = "(".$strs{$point}.")";
504
 
            }
505
 
        } else { 
506
 
            $strs{$point} = $vals{$point};
507
 
        }
508
 
        
 
478
        if( ($vals{$point."_code"} ne 'EXACT') &&
 
479
            ($vals{$point."_code"} ne 'UNCERTAIN') ) {
 
480
            
 
481
            # must have max and min defined to use 'WITHIN', 'BETWEEN'
 
482
            if ((!defined $vals{"min_$point"} ||
 
483
                 !defined $vals{"max_$point"}) && 
 
484
                ( $vals{$point."_code"} eq 'WITHIN' || 
 
485
                  $vals{$point."_code"} eq 'BETWEEN'))
 
486
            {
 
487
                $vals{"min_$point"} = '' unless defined $vals{"min_$point"};
 
488
                $vals{"max_$point"} = '' unless defined $vals{"max_$point"};
 
489
                
 
490
                $self->warn("Fuzzy codes for start are in a strange state, (".
 
491
                        join(",", ($vals{"min_$point"}, 
 
492
                               $vals{"max_$point"},
 
493
                               $vals{$point."_code"})). ")");
 
494
                return '';
 
495
            }
 
496
            
 
497
            if (defined $vals{$point."_code"} && 
 
498
               ($vals{$point."_code"} eq 'BEFORE' ||
 
499
                $vals{$point."_code"} eq 'AFTER'))
 
500
            {
 
501
                $strs{$point} .= $FUZZYCODES{$vals{$point."_code"}};
 
502
                $strs{$point} .= $vals{"$point"};
 
503
            }
 
504
 
 
505
            if( defined $vals{$point."_code"} && 
 
506
              ($vals{$point."_code"} eq 'WITHIN' ||
 
507
               $vals{$point."_code"} eq 'BETWEEN'))
 
508
            {
 
509
                # Expect odd results with anything but WidestCoordPolicy for now
 
510
                $strs{$point} .= ($point eq 'start') ?
 
511
                        $vals{"$point"}.
 
512
                        $FUZZYCODES{$vals{$point."_code"}}.
 
513
                        $vals{'max_'.$point}
 
514
                        :
 
515
                        $vals{'min_'.$point}.
 
516
                        $FUZZYCODES{$vals{$point."_code"}}.
 
517
                        $vals{"$point"};
 
518
                $strs{$point} = "(".$strs{$point}.")";
 
519
            }
 
520
            
 
521
        } elsif ($vals{$point."_code"} eq 'UNCERTAIN') {
 
522
            $strs{$point}  = $FUZZYCODES{$vals{$point."_code"}};
 
523
            $strs{$point} .= $vals{$point} if defined $vals{$point};
 
524
        } else {
 
525
            $strs{$point} = $vals{$point};
 
526
        }
509
527
    }
 
528
    
510
529
    my $str = $strs{'start'} . $delimiter . $strs{'end'};
511
530
    if($self->is_remote() && $self->seq_id()) {
512
 
        $str = $self->seq_id() . ":" . $str;
 
531
    $str = $self->seq_id() . ":" . $str;
513
532
    }
514
533
    if( defined $self->strand && 
515
 
        $self->strand == -1 ) {
516
 
        $str = "complement(" . $str . ")";
 
534
    $self->strand == -1 &&
 
535
    $self->location_type() ne "UNCERTAIN") {
 
536
    $str = "complement(" . $str . ")";
517
537
    } elsif($self->location_type() eq "WITHIN") {
518
 
        $str = "(".$str.")";
 
538
    $str = "(".$str.")";
519
539
    }
520
540
    return $str;
521
541
}
540
560
    # strip off leading and trailing space
541
561
    $string =~ s/^\s*(\S+)\s*/$1/;
542
562
    foreach my $pattern ( keys %FUZZYPOINTENCODE ) {
543
 
        if( $string =~ /^$pattern$/ ) {
544
 
            my ($min,$max) = ($1,$2);
545
 
            if($FUZZYPOINTENCODE{$pattern} eq 'EXACT') {
546
 
                $max = $min;
547
 
            } else {
548
 
                $max = undef if(length($max) == 0);
549
 
                $min = undef if(length($min) == 0);
550
 
            }
551
 
            return ($FUZZYPOINTENCODE{$pattern},$min,$max);
552
 
        }
 
563
        if( $string =~ /^$pattern$/ ) {
 
564
            my ($min,$max) = ($1,$2) unless (($1 eq '') && (!defined $2));
 
565
            if( ($FUZZYPOINTENCODE{$pattern} eq 'EXACT') ||
 
566
                 ($FUZZYPOINTENCODE{$pattern} eq 'UNCERTAIN')
 
567
              ) {
 
568
                $max = $min;
 
569
            } else {
 
570
                $max = undef if((defined $max) && (length($max) == 0));
 
571
                $min = undef if((defined $min) && (length($min) == 0));
 
572
            }
 
573
            return ($FUZZYPOINTENCODE{$pattern},$min,$max);
 
574
        }
553
575
    }
554
576
    if( $self->verbose >= 1 ) {
555
 
        $self->warn("could not find a valid fuzzy encoding for $string");
 
577
        $self->warn("could not find a valid fuzzy encoding for $string");
556
578
    }
557
579
    return ();
558
580
}
559
581
 
560
582
1;
561