~ubuntu-branches/ubuntu/trusty/bioperl/trusty

« back to all changes in this revision

Viewing changes to Bio/DB/Flat/BinarySearch.pm

  • Committer: Package Import Robot
  • Author(s): Charles Plessy
  • Date: 2013-09-22 13:39:48 UTC
  • mfrom: (3.1.11 sid)
  • Revision ID: package-import@ubuntu.com-20130922133948-c6z62zegjyp7ztou
Tags: 1.6.922-1
* New upstream release.
* Replaces and Breaks grinder (<< 0.5.3-3~) because of overlaping contents.
  Closes: #722910
* Stop Replacing and Breaking bioperl ( << 1.6.9 ): not needed anymore. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#
2
2
# BioPerl module for Bio::DB::Flat::BinarySearch
3
3
#
4
 
# Please direct questions and support issues to <bioperl-l@bioperl.org> 
 
4
# Please direct questions and support issues to <bioperl-l@bioperl.org>
5
5
#
6
6
# Cared for by Michele Clamp <michele@sanger.ac.uk>>
7
7
#
44
44
A string also has to be entered to defined what the primary key
45
45
(primary_namespace) is called.
46
46
 
47
 
The index can now be created using 
 
47
The index can now be created using
48
48
 
49
49
    my $index = Bio::DB::Flat::BinarySearch->new(
50
50
             -directory         => "/home/max/",
51
51
             -dbname            => "mydb",
52
 
                  -start_pattern     => $start_pattern,
53
 
                  -primary_pattern   => $primary_pattern,
 
52
              -start_pattern     => $start_pattern,
 
53
              -primary_pattern   => $primary_pattern,
54
54
             -primary_namespace => "ID",
55
 
                  -format            => "fasta" );
 
55
              -format            => "fasta" );
56
56
 
57
57
    my @files = ("file1","file2","file3");
58
58
 
71
71
instance you may want to retrieve sequences from swissprot using
72
72
their accessions as well as their ids.
73
73
 
74
 
To be able to do this when creating your index you need to pass in 
 
74
To be able to do this when creating your index you need to pass in
75
75
a hash of secondary_patterns which have their namespaces as the keys
76
76
to the hash.
77
77
 
102
102
 
103
103
    my $index = Bio::DB::Flat::BinarySearch->new(
104
104
                -directory          => $index_directory,
105
 
                          -dbname             => "ppp",
106
 
                          -write_flag         => 1,
 
105
                  -dbname             => "ppp",
 
106
                  -write_flag         => 1,
107
107
                -verbose            => 1,
108
108
                -start_pattern      => $start_pattern,
109
109
                -primary_pattern    => $primary_pattern,
117
117
 
118
118
=head2 Index reading
119
119
 
120
 
To fetch sequences using an existing index first of all create your sequence 
121
 
object 
 
120
To fetch sequences using an existing index first of all create your sequence
 
121
object
122
122
 
123
123
    my $index = Bio::DB::Flat::BinarySearch->new(
124
124
                  -directory => $index_directory);
139
139
into objects.
140
140
 
141
141
    my $seq = Bio::SeqIO->new(-fh     => $fh,
142
 
                                            -format => 'fasta');
 
142
                                -format => 'fasta');
143
143
 
144
144
The last way is to retrieve a sequence directly.  This is the
145
145
slowest way of extracting as the sequence objects need to be made.
170
170
  bioperl-l@bioperl.org                  - General discussion
171
171
  http://bioperl.org/wiki/Mailing_lists  - About the mailing lists
172
172
 
173
 
=head2 Support 
 
173
=head2 Support
174
174
 
175
175
Please direct usage questions or support issues to the mailing list:
176
176
 
177
177
I<bioperl-l@bioperl.org>
178
178
 
179
 
rather than to the module maintainer directly. Many experienced and 
180
 
reponsive experts will be able look at the problem and quickly 
181
 
address it. Please include a thorough description of the problem 
 
179
rather than to the module maintainer directly. Many experienced and
 
180
reponsive experts will be able look at the problem and quickly
 
181
address it. Please include a thorough description of the problem
182
182
with code and data examples if at all possible.
183
183
 
184
184
=head2 Reporting Bugs
209
209
use strict;
210
210
 
211
211
use Fcntl qw(SEEK_END SEEK_CUR);
 
212
 
212
213
# rather than using tell which might be buffered
213
 
sub systell{ sysseek($_[0], 0, SEEK_CUR) }
214
 
sub syseof{ sysseek($_[0], 0, SEEK_END) }
 
214
sub systell { sysseek( $_[0], 0, SEEK_CUR ) }
 
215
sub syseof  { sysseek( $_[0], 0, SEEK_END ) }
215
216
 
216
217
use File::Spec;
217
218
use Bio::Root::RootI;
224
225
use constant HEADER_SIZE      => 4;
225
226
use constant DEFAULT_FORMAT   => 'fasta';
226
227
 
227
 
my @formats = ['FASTA','SWISSPROT','EMBL'];
 
228
my @formats = [ 'FASTA', 'SWISSPROT', 'EMBL' ];
228
229
 
229
230
=head2 new
230
231
 
231
232
 Title   : new
232
 
 Usage   : For reading 
 
233
 Usage   : For reading
233
234
             my $index = Bio::DB::Flat::BinarySearch->new(
234
235
                     -directory => '/Users/michele/indices/dbest',
235
 
                     -dbname    => 'mydb',
 
236
             -dbname    => 'mydb',
236
237
                     -format    => 'fasta');
237
238
 
238
 
           For writing 
 
239
           For writing
239
240
 
240
241
             my %secondary_patterns = {"ACC" => "^>\\S+ +(\\S+)"}
241
242
             my $index = Bio::DB::Flat::BinarySearch->new(
242
 
                     -directory          => '/Users/michele/indices',
 
243
             -directory          => '/Users/michele/indices',
243
244
                     -dbname             => 'mydb',
244
 
                     -primary_pattern    => "^>(\\S+)",
 
245
             -primary_pattern    => "^>(\\S+)",
245
246
                     -secondary_patterns => \%secondary_patterns,
246
 
                     -primary_namespace  => "ID");
 
247
             -primary_namespace  => "ID");
247
248
 
248
249
             my @files = ('file1','file2','file3');
249
250
 
253
254
 Function: create a new Bio::DB::Flat::BinarySearch object
254
255
 Returns : new Bio::DB::Flat::BinarySearch
255
256
 Args    : -directory          Root directory for index files
256
 
           -dbname             Name of subdirectory containing indices 
 
257
           -dbname             Name of subdirectory containing indices
257
258
                               for named database
258
259
           -write_flag         Allow building index
259
260
           -primary_pattern    Regexp defining the primary id
267
268
=cut
268
269
 
269
270
sub new {
270
 
    my($class, @args) = @_;
 
271
    my ( $class, @args ) = @_;
271
272
 
272
273
    my $self = $class->SUPER::new(@args);
273
274
 
274
275
    bless $self, $class;
275
276
 
276
 
    my ($index_dir,$dbname,$format,$write_flag,$primary_pattern,
277
 
        $primary_namespace,$start_pattern,$secondary_patterns) =
278
 
            $self->_rearrange([qw(DIRECTORY
279
 
                                  DBNAME
280
 
                                  FORMAT
281
 
                                  WRITE_FLAG
282
 
                                  PRIMARY_PATTERN
283
 
                                  PRIMARY_NAMESPACE
284
 
                                  START_PATTERN
285
 
                                  SECONDARY_PATTERNS)], @args);
 
277
    my ( $index_dir, $dbname, $format, $write_flag, $primary_pattern,
 
278
        $primary_namespace, $start_pattern, $secondary_patterns )
 
279
      = $self->_rearrange(
 
280
        [
 
281
            qw(DIRECTORY
 
282
              DBNAME
 
283
              FORMAT
 
284
              WRITE_FLAG
 
285
              PRIMARY_PATTERN
 
286
              PRIMARY_NAMESPACE
 
287
              START_PATTERN
 
288
              SECONDARY_PATTERNS)
 
289
        ],
 
290
        @args
 
291
      );
286
292
 
287
293
    $self->index_directory($index_dir);
288
294
    $self->dbname($dbname);
289
295
 
290
 
    if ($self->index_directory && $self->read_config_file) {
291
 
        
292
 
        my $fh = $self->primary_index_filehandle;
 
296
    if ( $self->index_directory && $self->read_config_file ) {
 
297
 
 
298
        my $fh           = $self->primary_index_filehandle;
293
299
        my $record_width = $self->read_header($fh);
294
300
        $self->record_size($record_width);
295
301
    }
296
302
    $format ||= DEFAULT_FORMAT;
297
 
    $self->format            ($format);
298
 
    $self->write_flag        ($write_flag);
 
303
    $self->format($format);
 
304
    $self->write_flag($write_flag);
299
305
 
300
 
    if ($self->write_flag && ! $primary_namespace) {
301
 
      ($primary_namespace,$primary_pattern,
302
 
       $start_pattern,$secondary_patterns) =
303
 
        $self->_guess_patterns($self->format);
 
306
    if ( $self->write_flag && !$primary_namespace ) {
 
307
        (
 
308
            $primary_namespace, $primary_pattern,
 
309
            $start_pattern,     $secondary_patterns
 
310
        ) = $self->_guess_patterns( $self->format );
304
311
    }
305
312
 
306
 
    $self->primary_pattern   ($primary_pattern);
307
 
    $self->primary_namespace ($primary_namespace);
308
 
    $self->start_pattern     ($start_pattern);
 
313
    $self->primary_pattern($primary_pattern);
 
314
    $self->primary_namespace($primary_namespace);
 
315
    $self->start_pattern($start_pattern);
309
316
    $self->secondary_patterns($secondary_patterns);
310
317
 
311
318
    return $self;
312
319
}
313
320
 
314
321
sub new_from_registry {
315
 
    my ($self,%config) =  @_;
316
 
   
 
322
    my ( $self, %config ) = @_;
 
323
 
317
324
    my $dbname   = $config{'dbname'};
318
325
    my $location = $config{'location'};
319
 
    
320
 
    my $index =  Bio::DB::Flat::BinarySearch->new(-dbname    => $dbname,
321
 
                                                 -index_dir => $location,
322
 
                                                 );
 
326
 
 
327
    my $index = Bio::DB::Flat::BinarySearch->new(
 
328
        -dbname    => $dbname,
 
329
        -index_dir => $location,
 
330
    );
323
331
}
324
332
 
325
333
=head2 get_Seq_by_id
326
334
 
327
335
 Title   : get_Seq_by_id
328
336
 Usage   : $obj->get_Seq_by_id($newval)
329
 
 Function: 
330
 
 Example : 
 
337
 Function:
 
338
 Example :
331
339
 Returns : value of get_Seq_by_id
332
340
 Args    : newvalue (optional)
333
341
 
334
342
=cut
335
343
 
336
344
sub get_Seq_by_id {
337
 
    my ($self,$id) = @_;
 
345
    my ( $self, $id ) = @_;
338
346
 
339
347
    # too many uninit variables...
340
348
    local $^W = 0;
341
349
 
342
 
    my ($fh,$length) = $self->get_stream_by_id($id);
 
350
    my ( $fh, $length ) = $self->get_stream_by_id($id);
343
351
 
344
 
    unless (defined($self->format)) {
345
 
        $self->throw("Can't create sequence - format is not defined");
 
352
    unless ( defined( $self->format ) ) {
 
353
        $self->throw("Can't create sequence - format is not defined");
346
354
    }
347
355
 
348
356
    return unless $fh;
349
357
 
350
 
    unless ( defined($self->{_seqio}) ) {
 
358
    unless ( defined( $self->{_seqio} ) ) {
351
359
 
352
 
        $self->{_seqio} = Bio::SeqIO->new(-fh => $fh,
353
 
                                         -format => $self->format);
354
 
    } else {
355
 
        $self->{_seqio}->fh($fh);
 
360
        $self->{_seqio} = Bio::SeqIO->new(
 
361
            -fh     => $fh,
 
362
            -format => $self->format
 
363
        );
 
364
    }
 
365
    else {
 
366
        $self->{_seqio}->fh($fh);
356
367
    }
357
368
 
358
369
    return $self->{_seqio}->next_seq;
370
381
=cut
371
382
 
372
383
sub get_entry_by_id {
373
 
    my ($self,$id) = @_;
 
384
    my ( $self, $id ) = @_;
374
385
 
375
 
    my ($fh,$length) = $self->get_stream_by_id($id);
 
386
    my ( $fh, $length ) = $self->get_stream_by_id($id);
376
387
 
377
388
    my $entry;
378
389
 
379
 
    sysread($fh,$entry,$length);
 
390
    sysread( $fh, $entry, $length );
380
391
 
381
392
    return $entry;
382
393
}
383
394
 
384
 
 
385
395
=head2 get_stream_by_id
386
396
 
387
397
 Title   : get_stream_by_id
394
404
=cut
395
405
 
396
406
sub get_stream_by_id {
397
 
    my ($self,$id) = @_;
398
 
 
399
 
    unless( $self->record_size ) {
400
 
        if ($self->index_directory && $self->read_config_file) {
401
 
            
402
 
            my $fh = $self->primary_index_filehandle;
403
 
            my $record_width = $self->read_header($fh);
404
 
            $self->record_size($record_width);
405
 
        }
 
407
    my ( $self, $id ) = @_;
 
408
 
 
409
    unless ( $self->record_size ) {
 
410
        if ( $self->index_directory && $self->read_config_file ) {
 
411
 
 
412
            my $fh           = $self->primary_index_filehandle;
 
413
            my $record_width = $self->read_header($fh);
 
414
            $self->record_size($record_width);
 
415
        }
406
416
    }
407
417
    my $indexfh = $self->primary_index_filehandle;
408
 
    syseof ($indexfh);
 
418
    syseof($indexfh);
409
419
 
410
420
    my $filesize = systell($indexfh);
411
 
    
412
 
    $self->throw("file was not parsed properly, record size is empty") 
413
 
        unless $self->record_size;
414
 
    
415
 
    my $end = ($filesize - $self->{'_start_pos'}) / $self->record_size;
416
 
    my ($newid,$rest,$fhpos) = $self->find_entry($indexfh,0,$end,$id,$self->record_size);
417
 
 
418
 
    
419
 
    my ($fileid,$pos,$length) = split(/\t/,$rest);
420
 
 
421
 
    #print STDERR "BinarySearch Found id entry $newid $fileid $pos $length:$rest\n";
422
 
 
423
 
    if (!$newid) {
424
 
      return;
 
421
 
 
422
    $self->throw("file was not parsed properly, record size is empty")
 
423
      unless $self->record_size;
 
424
 
 
425
    my $end = ( $filesize - $self->{'_start_pos'} ) / $self->record_size;
 
426
    my ( $newid, $rest, $fhpos ) =
 
427
      $self->find_entry( $indexfh, 0, $end, $id, $self->record_size );
 
428
 
 
429
    my ( $fileid, $pos, $length ) = split( /\t/, $rest );
 
430
 
 
431
#print STDERR "BinarySearch Found id entry $newid $fileid $pos $length:$rest\n";
 
432
 
 
433
    if ( !$newid ) {
 
434
        return;
425
435
    }
426
436
 
427
437
    my $file = $self->{_file}{$fileid};
428
438
 
429
 
    open (my $IN,"<$file");
 
439
    open( my $IN, "<$file" );
430
440
 
431
441
    my $entry;
432
 
    
433
 
    sysseek($IN,$pos,0);
434
 
 
435
 
    return ($IN,$length);
 
442
 
 
443
    sysseek( $IN, $pos, 0 );
 
444
 
 
445
    return ( $IN, $length );
436
446
}
437
447
 
438
448
=head2 get_Seq_by_acc
447
457
=cut
448
458
 
449
459
sub get_Seq_by_acc {
450
 
    my ($self,$acc) = @_;
 
460
    my ( $self, $acc ) = @_;
451
461
 
452
462
    # too many uninit variables...
453
463
    local $^W = 0;
454
464
 
455
 
    if ($self->primary_namespace eq "ACC") {
456
 
       return $self->get_Seq_by_id($acc);
457
 
    } else {
458
 
      return $self->get_Seq_by_secondary("ACC",$acc);
 
465
    if ( $self->primary_namespace eq "ACC" ) {
 
466
        return $self->get_Seq_by_id($acc);
 
467
    }
 
468
    else {
 
469
        return $self->get_Seq_by_secondary( "ACC", $acc );
459
470
    }
460
471
}
461
472
 
471
482
=cut
472
483
 
473
484
sub get_Seq_by_version {
474
 
    my ($self,$acc) = @_;
 
485
    my ( $self, $acc ) = @_;
475
486
 
476
487
    # too many uninit variables...
477
488
    local $^W = 0;
478
489
 
479
 
    if ($self->primary_namespace eq "VERSION") {
480
 
       return $self->get_Seq_by_id($acc);
481
 
    } else {
482
 
      return $self->get_Seq_by_secondary("VERSION",$acc);
 
490
    if ( $self->primary_namespace eq "VERSION" ) {
 
491
        return $self->get_Seq_by_id($acc);
 
492
    }
 
493
    else {
 
494
        return $self->get_Seq_by_secondary( "VERSION", $acc );
483
495
    }
484
496
}
485
497
 
495
507
=cut
496
508
 
497
509
sub get_Seq_by_secondary {
498
 
    my ($self,$name,$id) = @_;
 
510
    my ( $self, $name, $id ) = @_;
499
511
 
500
512
    my @names = $self->secondary_namespaces;
501
513
 
502
514
    my $found = 0;
503
515
    foreach my $tmpname (@names) {
504
 
        if ($name eq $tmpname) {
505
 
            $found = 1;
506
 
        }
 
516
        if ( $name eq $tmpname ) {
 
517
            $found = 1;
 
518
        }
507
519
    }
508
520
 
509
 
    if ($found == 0) {
510
 
        $self->throw("Secondary index for $name doesn't exist\n");
 
521
    if ( $found == 0 ) {
 
522
        $self->throw("Secondary index for $name doesn't exist\n");
511
523
    }
512
524
 
513
525
    my $fh = $self->open_secondary_index($name);
514
526
 
515
 
    syseof ($fh);
 
527
    syseof($fh);
516
528
 
517
529
    my $filesize = systell($fh);
518
530
 
519
531
    my $recsize = $self->{'_secondary_record_size'}{$name};
520
 
#    print "Name " . $recsize . "\n";
521
 
 
522
 
    my $end = ($filesize - $self->{'_start_pos'})/$recsize;
523
 
 
524
 
#    print "End $end $filesize\n";
525
 
    my ($newid,$primary_id,$pos) = $self->find_entry($fh,0,$end,$id,$recsize);
526
 
 
527
 
    sysseek($fh,$pos,0);
528
 
 
529
 
#    print "Found new id $newid $primary_id\n";    
 
532
 
 
533
    #    print "Name " . $recsize . "\n";
 
534
 
 
535
    my $end = ( $filesize - $self->{'_start_pos'} ) / $recsize;
 
536
 
 
537
    #    print "End $end $filesize\n";
 
538
    my ( $newid, $primary_id, $pos ) =
 
539
      $self->find_entry( $fh, 0, $end, $id, $recsize );
 
540
 
 
541
    sysseek( $fh, $pos, 0 );
 
542
 
 
543
    #    print "Found new id $newid $primary_id\n";
530
544
    # We now need to shuffle up the index file to find the top secondary entry
531
545
 
532
546
    my $record = $newid;
533
547
 
534
 
    while ($record =~ /^$newid/ && $pos >= 0) {
535
 
 
536
 
        $record = $self->read_record($fh,$pos,$recsize);
537
 
        $pos = $pos - $recsize;
538
 
#       print "Up record = $record:$newid\n";
 
548
    while ( $record =~ /^$newid/ && $pos >= 0 ) {
 
549
 
 
550
        $record = $self->read_record( $fh, $pos, $recsize );
 
551
        $pos = $pos - $recsize;
 
552
 
 
553
        #       print "Up record = $record:$newid\n";
539
554
    }
540
555
 
541
556
    $pos += $recsize;
542
557
 
543
 
#    print "Top position is $pos\n";
 
558
    #    print "Top position is $pos\n";
544
559
 
545
560
    # Now we have to shuffle back down again to read all the secondary entries
546
561
 
549
564
 
550
565
    $primary_id{$primary_id} = 1;
551
566
 
552
 
    while ($current_id eq $newid) {
553
 
        $record = $self->read_record($fh,$pos,$recsize);
554
 
        # print "Record is :$record:\n";
555
 
        my ($secid,$primary_id) = split(/\t/,$record,2);
556
 
        $current_id = $secid;
557
 
 
558
 
        if ($current_id eq $newid) {
559
 
            $primary_id =~ s/ //g;
560
 
        #    print "Primary $primary_id\n";
561
 
            $primary_id{$primary_id} = 1;
562
 
 
563
 
            $pos = $pos + $recsize;
564
 
         #   print "Down record = $record\n";
565
 
        }
 
567
    while ( $current_id eq $newid ) {
 
568
        $record = $self->read_record( $fh, $pos, $recsize );
 
569
 
 
570
        # print "Record is :$record:\n";
 
571
        my ( $secid, $primary_id ) = split( /\t/, $record, 2 );
 
572
        $current_id = $secid;
 
573
 
 
574
        if ( $current_id eq $newid ) {
 
575
            $primary_id =~ s/ //g;
 
576
 
 
577
            #    print "Primary $primary_id\n";
 
578
            $primary_id{$primary_id} = 1;
 
579
 
 
580
            $pos = $pos + $recsize;
 
581
 
 
582
            #   print "Down record = $record\n";
 
583
        }
566
584
    }
567
585
 
568
 
    if (!defined($newid)) {
569
 
      return;
 
586
    if ( !defined($newid) ) {
 
587
        return;
570
588
    }
571
589
 
572
590
    my @entry;
573
591
 
574
 
    foreach my $id (keys %primary_id) {
575
 
      push @entry,$self->get_Seq_by_id($id);
 
592
    foreach my $id ( keys %primary_id ) {
 
593
        push @entry, $self->get_Seq_by_id($id);
576
594
    }
577
595
    return wantarray ? @entry : $entry[0];
578
596
 
590
608
=cut
591
609
 
592
610
sub read_header {
593
 
    my ($self,$fh) = @_;
 
611
    my ( $self, $fh ) = @_;
594
612
 
595
613
    my $record_width;
596
614
 
597
 
    sysread($fh,$record_width,HEADER_SIZE);
 
615
    sysread( $fh, $record_width, HEADER_SIZE );
598
616
 
599
617
    $self->{'_start_pos'} = HEADER_SIZE;
600
618
    $record_width =~ s/ //g;
615
633
=cut
616
634
 
617
635
sub read_record {
618
 
  my ($self,$fh,$pos,$len) = @_;
619
 
 
620
 
  sysseek($fh,$pos,0);
621
 
 
622
 
  my $record;
623
 
    
624
 
  sysread($fh,$record,$len);
625
 
 
626
 
  return $record;
 
636
    my ( $self, $fh, $pos, $len ) = @_;
 
637
 
 
638
    sysseek( $fh, $pos, 0 );
 
639
 
 
640
    my $record;
 
641
 
 
642
    sysread( $fh, $record, $len );
 
643
 
 
644
    return $record;
627
645
 
628
646
}
629
647
 
639
657
=cut
640
658
 
641
659
sub get_all_primary_ids {
642
 
  my $self = shift;
643
 
 
644
 
  my $fh = $self->primary_index_filehandle;
645
 
  syseof($fh);
646
 
  my $filesize = systell($fh);
647
 
  my $recsize  = $self->record_size;
648
 
  my $end = $filesize;
649
 
 
650
 
  my @ids;
651
 
  for (my $pos=$self->{'_start_pos'}; $pos < $end; $pos += $recsize) {
652
 
    my $record = $self->read_record($fh,$pos,$recsize);
653
 
    my ($entryid)  = split(/\t/,$record);
654
 
    push @ids,$entryid;
655
 
  }
656
 
  @ids;
 
660
    my $self = shift;
 
661
 
 
662
    my $fh = $self->primary_index_filehandle;
 
663
    syseof($fh);
 
664
    my $filesize = systell($fh);
 
665
    my $recsize  = $self->record_size;
 
666
    my $end      = $filesize;
 
667
 
 
668
    my @ids;
 
669
    for ( my $pos = $self->{'_start_pos'} ; $pos < $end ; $pos += $recsize ) {
 
670
        my $record = $self->read_record( $fh, $pos, $recsize );
 
671
        my ($entryid) = split( /\t/, $record );
 
672
        push @ids, $entryid;
 
673
    }
 
674
    @ids;
657
675
}
658
676
 
659
 
 
660
677
=head2 find_entry
661
678
 
662
679
 Title   : find_entry
669
686
=cut
670
687
 
671
688
sub find_entry {
672
 
    my ($self,$fh,$start,$end,$id,$recsize) = @_;
673
 
    
674
 
    my $mid = int( ($end+1+$start) / 2);
675
 
    my $pos = ($mid-1)*$recsize + $self->{'_start_pos'};
676
 
    
677
 
    my ($record) = $self->read_record($fh,$pos,$recsize);
678
 
    my ($entryid,$rest)  = split(/\t/,$record,2);
 
689
    my ( $self, $fh, $start, $end, $id, $recsize ) = @_;
 
690
 
 
691
    my $mid = int( ( $end + 1 + $start ) / 2 );
 
692
    my $pos = ( $mid - 1 ) * $recsize + $self->{'_start_pos'};
 
693
 
 
694
    my ($record) = $self->read_record( $fh, $pos, $recsize );
 
695
    my ( $entryid, $rest ) = split( /\t/, $record, 2 );
679
696
    $rest =~ s/\s+$//;
680
697
 
681
 
#    print "Mid $recsize $mid $pos:$entryid:$rest:$record\n";
682
 
#    print "Entry :$id:$entryid:$rest\n";
683
 
 
684
 
    my ($first,$second) = $id le $entryid ? ($id,$entryid) : ($entryid,$id);
685
 
 
686
 
    if ($id eq $entryid) {
687
 
 
688
 
      return ($id,$rest,$pos-$recsize);
689
 
 
690
 
    } elsif ($first eq $id) {
691
 
        
692
 
      if ($end-$start <= 1) {
693
 
        return;
694
 
      }
695
 
      my $end = $mid;
696
 
#      print "Moving up $entryid $id\n";
697
 
      $self->find_entry($fh,$start,$end,$id,$recsize);
698
 
 
699
 
    } elsif ($second eq $id ) {
700
 
#       print "Moving down $entryid $id\n";
701
 
      if ($end-$start <= 1) {
702
 
        return;
703
 
      }
704
 
 
705
 
      $start = $mid;
706
 
      
707
 
      $self->find_entry($fh,$start,$end,$id,$recsize);
708
 
    }
709
 
 
710
 
 }   
711
 
 
 
698
    #    print "Mid $recsize $mid $pos:$entryid:$rest:$record\n";
 
699
    #    print "Entry :$id:$entryid:$rest\n";
 
700
 
 
701
    my ( $first, $second ) =
 
702
      $id le $entryid ? ( $id, $entryid ) : ( $entryid, $id );
 
703
 
 
704
    if ( $id eq $entryid ) {
 
705
 
 
706
        return ( $id, $rest, $pos - $recsize );
 
707
 
 
708
    }
 
709
    elsif ( $first eq $id ) {
 
710
 
 
711
        if ( $end - $start <= 1 ) {
 
712
            return;
 
713
        }
 
714
        my $end = $mid;
 
715
 
 
716
        #      print "Moving up $entryid $id\n";
 
717
        $self->find_entry( $fh, $start, $end, $id, $recsize );
 
718
 
 
719
    }
 
720
    elsif ( $second eq $id ) {
 
721
 
 
722
        #       print "Moving down $entryid $id\n";
 
723
        if ( $end - $start <= 1 ) {
 
724
            return;
 
725
        }
 
726
 
 
727
        $start = $mid;
 
728
 
 
729
        $self->find_entry( $fh, $start, $end, $id, $recsize );
 
730
    }
 
731
 
 
732
}
712
733
 
713
734
=head2 build_index
714
735
 
722
743
=cut
723
744
 
724
745
sub build_index {
725
 
    my ($self,@files) = @_;
726
 
    $self->write_flag or 
727
 
        $self->throw('Cannot build index unless -write_flag is true');
 
746
    my ( $self, @files ) = @_;
 
747
    $self->write_flag
 
748
      or $self->throw('Cannot build index unless -write_flag is true');
728
749
 
729
750
    my $rootdir = $self->index_directory;
730
751
 
731
 
    if (!defined($rootdir)) {
732
 
        $self->throw("No index directory set - can't build indices");
733
 
    }
734
 
 
735
 
    if (! -d $rootdir) {
736
 
        $self->throw("Index directory [$rootdir] is not a directory. Cant' build indices");
737
 
    }
738
 
 
739
 
    my $dbpath = File::Spec->catfile($rootdir,$self->dbname);
740
 
    if (! -d $dbpath) {
741
 
      warn "Creating directory $dbpath\n";
742
 
      mkdir $dbpath,0777 or $self->throw("Couldn't create $dbpath: $!");
743
 
    }
744
 
 
745
 
    unless (@files ) {
746
 
        $self->throw("Must enter an array of filenames to index");
 
752
    if ( !defined($rootdir) ) {
 
753
        $self->throw("No index directory set - can't build indices");
 
754
    }
 
755
 
 
756
    if ( !-d $rootdir ) {
 
757
        $self->throw(
 
758
            "Index directory [$rootdir] is not a directory. Cant' build indices"
 
759
        );
 
760
    }
 
761
 
 
762
    my $dbpath = File::Spec->catfile( $rootdir, $self->dbname );
 
763
    if ( !-d $dbpath ) {
 
764
        warn "Creating directory $dbpath\n";
 
765
        mkdir $dbpath, 0777 or $self->throw("Couldn't create $dbpath: $!");
 
766
    }
 
767
 
 
768
    unless (@files) {
 
769
        $self->throw("Must enter an array of filenames to index");
747
770
    }
748
771
 
749
772
    foreach my $file (@files) {
750
 
        $file = File::Spec->rel2abs($file)
751
 
            unless File::Spec->file_name_is_absolute($file);
752
 
        unless ( -e $file) {
753
 
            $self->throw("Can't index file [$file] as it doesn't exist");
754
 
        }
 
773
        $file = File::Spec->rel2abs($file)
 
774
          unless File::Spec->file_name_is_absolute($file);
 
775
        unless ( -e $file ) {
 
776
            $self->throw("Can't index file [$file] as it doesn't exist");
 
777
        }
755
778
    }
756
 
    
757
 
    if (my $filehash = $self->{_dbfile}) {
758
 
      push @files,keys %$filehash;
 
779
 
 
780
    if ( my $filehash = $self->{_dbfile} ) {
 
781
        push @files, keys %$filehash;
759
782
    }
760
783
 
761
784
    my %seen;
762
 
    @files = grep {!$seen{$_}++} @files;
 
785
    @files = grep { !$seen{$_}++ } @files;
763
786
 
764
787
    # Lets index
765
 
    $self->make_config_file(\@files);
 
788
    $self->make_config_file( \@files );
766
789
    my $entries = 0;
767
790
    foreach my $file (@files) {
768
 
      $entries += $self->_index_file($file);
 
791
        $entries += $self->_index_file($file);
769
792
    }
770
793
 
771
794
    # update alphabet if necessary
772
 
    $self->make_config_file(\@files);
 
795
    $self->make_config_file( \@files );
773
796
 
774
797
    # And finally write out the indices
775
798
    $self->write_primary_index;
782
805
 
783
806
 Title   : _index_file
784
807
 Usage   : $obj->_index_file($newval)
785
 
 Function: 
786
 
 Example : 
 
808
 Function:
 
809
 Example :
787
810
 Returns : value of _index_file
788
811
 Args    : newvalue (optional)
789
812
 
790
 
 
791
813
=cut
792
814
 
793
815
sub _index_file {
794
 
        my ($self,$file) = @_;
795
 
        my $v = $self->verbose;
796
 
        open(my $FILE,"<", $file) || $self->throw("Can't open file [$file]");
797
 
 
798
 
        my $recstart = 0;
799
 
        my $fileid = $self->get_fileid_by_filename($file);
800
 
        my $found = 0;
801
 
        my $id;
802
 
        my $count = 0;
803
 
 
804
 
        my $primary       = $self->primary_pattern;
805
 
        my $start_pattern = $self->start_pattern;
806
 
 
807
 
        my $pos = 0;
808
 
 
809
 
        my $new_primary_entry;
810
 
 
811
 
        my $length;
812
 
 
813
 
        my $fh = $FILE;
814
 
 
815
 
        my $done = -1;
816
 
 
817
 
        my @secondary_names = $self->secondary_namespaces;
818
 
        my %secondary_id;
819
 
        my $last_one;
820
 
 
821
 
        while (<$fh>) {
822
 
      $last_one = $_;
823
 
      $self->{alphabet} ||= $self->guess_alphabet($_);          
824
 
      if ($_ =~ /$start_pattern/) {
825
 
                        if ($done == 0) {
826
 
                                $id = $new_primary_entry;
827
 
                                $self->{alphabet} ||= $self->guess_alphabet($_);
828
 
          
829
 
                                my $tmplen = (tell $fh) - length($_);
830
 
 
831
 
                                $length = $tmplen  - $pos;
832
 
                
833
 
                                unless( defined($id)) {
834
 
                                        $self->throw("No id defined for sequence");
835
 
                                }
836
 
                                unless( defined($fileid)) {
837
 
                                        $self->throw("No fileid defined for file $file");
838
 
                                }
839
 
                                unless( defined($pos)) {
840
 
                                        $self->throw("No position defined for " . $id . "\n");
841
 
                                }
842
 
                                unless( defined($length)) {
843
 
                                        $self->throw("No length defined for " . $id . "\n");
844
 
                                }
845
 
                                $self->_add_id_position($id,$pos,$fileid,$length,\%secondary_id);
846
 
 
847
 
                                $pos   = $tmplen;
848
 
                
849
 
                                if ($count > 0 && $count%1000 == 0) {
850
 
                                        $self->debug( "Indexed $count ids\n") if $v > 0;
851
 
                                }
852
 
            
853
 
                                $count++;
854
 
                        } else {
855
 
                                $done = 0;
856
 
                        }
857
 
      }
858
 
 
859
 
      if ($_ =~ /$primary/) {
860
 
                        $new_primary_entry = $1;    
861
 
      }
862
 
 
863
 
      my $secondary_patterns = $self->secondary_patterns;
864
 
 
865
 
      foreach my $sec (@secondary_names) {
866
 
                        my $pattern = $secondary_patterns->{$sec};
867
 
 
868
 
                        if ($_ =~ /$pattern/) {
869
 
                                $secondary_id{$sec} = $1;
870
 
                        }
871
 
      }
872
 
                
873
 
        }
874
 
 
875
 
        # Remember to add in the last one
876
 
 
877
 
        $id = $new_primary_entry;
878
 
        # my $tmplen = (tell $fh) - length($last_one);
879
 
        my $tmplen = (tell $fh);
880
 
 
881
 
        $length = $tmplen - $pos;
882
 
    
883
 
        if (!defined($id)) {
884
 
                $self->throw("No id defined for sequence");
885
 
        }
886
 
        if (!defined($fileid)) {
887
 
                $self->throw("No fileid defined for file $file");
888
 
        }
889
 
        if (!defined($pos)) {
890
 
                $self->throw("No position defined for " . $id . "\n");
891
 
        }
892
 
        if (!defined($length)) {
893
 
                $self->throw("No length defined for " . $id . "\n");
894
 
        }
895
 
    
896
 
        $self->_add_id_position($id,$pos,$fileid,$length,\%secondary_id);
897
 
        $count++;
898
 
    
899
 
        close($FILE);
900
 
        $count;
 
816
    my ( $self, $file ) = @_;
 
817
    my $v = $self->verbose;
 
818
    open( my $FILE, "<", $file ) || $self->throw("Can't open file [$file]");
 
819
 
 
820
    my $recstart = 0;
 
821
    my $fileid   = $self->get_fileid_by_filename($file);
 
822
    my $found    = 0;
 
823
    my $id;
 
824
    my $count = 0;
 
825
 
 
826
    my $primary       = $self->primary_pattern;
 
827
    my $start_pattern = $self->start_pattern;
 
828
 
 
829
    my $pos = 0;
 
830
 
 
831
    my $new_primary_entry;
 
832
 
 
833
    my $length;
 
834
 
 
835
    my $fh = $FILE;
 
836
 
 
837
    my $done = -1;
 
838
 
 
839
    my @secondary_names = $self->secondary_namespaces;
 
840
    my %secondary_id;
 
841
    my $last_one;
 
842
 
 
843
    while (<$fh>) {
 
844
        $last_one = $_;
 
845
        $self->{alphabet} ||= $self->guess_alphabet($_);
 
846
        if ( $_ =~ /$start_pattern/ ) {
 
847
            if ( $done == 0 ) {
 
848
                $id = $new_primary_entry;
 
849
                $self->{alphabet} ||= $self->guess_alphabet($_);
 
850
 
 
851
                my $tmplen = ( tell $fh ) - length($_);
 
852
 
 
853
                $length = $tmplen - $pos;
 
854
 
 
855
                unless ( defined($id) ) {
 
856
                    $self->throw("No id defined for sequence");
 
857
                }
 
858
                unless ( defined($fileid) ) {
 
859
                    $self->throw("No fileid defined for file $file");
 
860
                }
 
861
                unless ( defined($pos) ) {
 
862
                    $self->throw( "No position defined for " . $id . "\n" );
 
863
                }
 
864
                unless ( defined($length) ) {
 
865
                    $self->throw( "No length defined for " . $id . "\n" );
 
866
                }
 
867
                $self->_add_id_position( $id, $pos, $fileid, $length,
 
868
                    \%secondary_id );
 
869
 
 
870
                $pos = $tmplen;
 
871
 
 
872
                if ( $count > 0 && $count % 1000 == 0 ) {
 
873
                    $self->debug("Indexed $count ids\n") if $v > 0;
 
874
                }
 
875
 
 
876
                $count++;
 
877
            }
 
878
            else {
 
879
                $done = 0;
 
880
            }
 
881
        }
 
882
 
 
883
        if ( $_ =~ /$primary/ ) {
 
884
            $new_primary_entry = $1;
 
885
        }
 
886
 
 
887
        my $secondary_patterns = $self->secondary_patterns;
 
888
 
 
889
        foreach my $sec (@secondary_names) {
 
890
            my $pattern = $secondary_patterns->{$sec};
 
891
 
 
892
            if ( $_ =~ /$pattern/ ) {
 
893
                $secondary_id{$sec} = $1;
 
894
            }
 
895
        }
 
896
 
 
897
    }
 
898
 
 
899
    # Remember to add in the last one
 
900
 
 
901
    $id = $new_primary_entry;
 
902
 
 
903
    # my $tmplen = (tell $fh) - length($last_one);
 
904
    my $tmplen = ( tell $fh );
 
905
 
 
906
    $length = $tmplen - $pos;
 
907
 
 
908
    if ( !defined($id) ) {
 
909
        $self->throw("No id defined for sequence");
 
910
    }
 
911
    if ( !defined($fileid) ) {
 
912
        $self->throw("No fileid defined for file $file");
 
913
    }
 
914
    if ( !defined($pos) ) {
 
915
        $self->throw( "No position defined for " . $id . "\n" );
 
916
    }
 
917
    if ( !defined($length) ) {
 
918
        $self->throw( "No length defined for " . $id . "\n" );
 
919
    }
 
920
 
 
921
    $self->_add_id_position( $id, $pos, $fileid, $length, \%secondary_id );
 
922
    $count++;
 
923
 
 
924
    close($FILE);
 
925
    $count;
901
926
}
902
927
 
903
928
=head2 write_primary_index
904
929
 
905
930
 Title   : write_primary_index
906
931
 Usage   : $obj->write_primary_index($newval)
907
 
 Function: 
908
 
 Example : 
 
932
 Function:
 
933
 Example :
909
934
 Returns : value of write_primary_index
910
935
 Args    : newvalue (optional)
911
936
 
913
938
=cut
914
939
 
915
940
sub write_primary_index {
916
 
        my ($self) = @_;
917
 
 
918
 
        my @ids = keys %{$self->{_id}};
919
 
 
920
 
        @ids = sort {$a cmp $b} @ids;
921
 
 
922
 
        open (my $INDEX,">" . $self->primary_index_file) || 
923
 
          $self->throw("Can't open primary index file [" . 
924
 
                                                $self->primary_index_file . "]");
925
 
 
926
 
        my $recordlength = $self->{_maxidlength} +
927
 
                           $self->{_maxfileidlength} + 
928
 
                                $self->{_maxposlength} +
929
 
                                     $self->{_maxlengthlength} + 3;
930
 
    
931
 
        print $INDEX sprintf("%04d",$recordlength);
932
 
 
933
 
        foreach my $id (@ids) {
934
 
 
935
 
                if (!defined($self->{_id}{$id}{_fileid})) {
936
 
                        $self->throw("No fileid for $id\n");
937
 
                }
938
 
                if (!defined($self->{_id}{$id}{_pos})) {
939
 
                        $self->throw("No position for $id\n");
940
 
                }
941
 
                if (!defined($self->{_id}{$id}{_length})) {
942
 
                        $self->throw("No length for $id");
943
 
                }
944
 
 
945
 
                my $record =  $id              . "\t" . 
946
 
                  $self->{_id}{$id}{_fileid} . "\t" .
947
 
                         $self->{_id}{$id}{_pos}    . "\t" .
948
 
                                $self->{_id}{$id}{_length};
949
 
 
950
 
                print $INDEX sprintf("%-${recordlength}s",$record);
 
941
    my ($self) = @_;
 
942
 
 
943
    my @ids = keys %{ $self->{_id} };
 
944
 
 
945
    @ids = sort { $a cmp $b } @ids;
 
946
 
 
947
    open( my $INDEX, ">" . $self->primary_index_file )
 
948
      || $self->throw(
 
949
        "Can't open primary index file [" . $self->primary_index_file . "]" );
 
950
 
 
951
    my $recordlength =
 
952
      $self->{_maxidlength} +
 
953
      $self->{_maxfileidlength} +
 
954
      $self->{_maxposlength} +
 
955
      $self->{_maxlengthlength} + 3;
 
956
 
 
957
    print $INDEX sprintf( "%04d", $recordlength );
 
958
 
 
959
    foreach my $id (@ids) {
 
960
 
 
961
        if ( !defined( $self->{_id}{$id}{_fileid} ) ) {
 
962
            $self->throw("No fileid for $id\n");
 
963
        }
 
964
        if ( !defined( $self->{_id}{$id}{_pos} ) ) {
 
965
            $self->throw("No position for $id\n");
 
966
        }
 
967
        if ( !defined( $self->{_id}{$id}{_length} ) ) {
 
968
            $self->throw("No length for $id");
 
969
        }
 
970
 
 
971
        my $record =
 
972
            $id . "\t"
 
973
          . $self->{_id}{$id}{_fileid} . "\t"
 
974
          . $self->{_id}{$id}{_pos} . "\t"
 
975
          . $self->{_id}{$id}{_length};
 
976
 
 
977
        print $INDEX sprintf( "%-${recordlength}s", $record );
951
978
 
952
979
    }
953
980
}
956
983
 
957
984
 Title   : write_secondary_indices
958
985
 Usage   : $obj->write_secondary_indices($newval)
959
 
 Function: 
960
 
 Example : 
 
986
 Function:
 
987
 Example :
961
988
 Returns : value of write_secondary_indices
962
989
 Args    : newvalue (optional)
963
990
 
967
994
sub write_secondary_indices {
968
995
    my ($self) = @_;
969
996
 
970
 
    # These are the different 
971
 
    my @names = keys (%{$self->{_secondary_id}});
 
997
    # These are the different
 
998
    my @names = keys( %{ $self->{_secondary_id} } );
972
999
 
973
 
    
974
1000
    foreach my $name (@names) {
975
1001
 
976
 
        my @seconds = keys %{$self->{_secondary_id}{$name}};
977
 
 
978
 
        # First we need to loop over to get the longest record.
979
 
        my $length = 0;
980
 
 
981
 
        foreach my $second (@seconds) {
982
 
            my $tmplen = length($second) + 1;
983
 
            my @prims = keys %{$self->{_secondary_id}{$name}{$second}};
984
 
 
985
 
            foreach my $prim (@prims) {
986
 
                my $recordlen = $tmplen + length($prim);
987
 
            
988
 
                if ($recordlen > $length) {
989
 
                    $length = $recordlen;
990
 
                }
991
 
            }
992
 
        }
993
 
 
994
 
        # Now we can print the index
995
 
        
996
 
        my $fh = $self->new_secondary_filehandle($name);        
997
 
 
998
 
        print $fh sprintf("%04d",$length);
999
 
        @seconds = sort @seconds;
1000
 
        
1001
 
        foreach my $second (@seconds) {
1002
 
 
1003
 
            my @prims = keys %{$self->{_secondary_id}{$name}{$second}};
1004
 
            my $tmp = $second;
1005
 
 
1006
 
            foreach my $prim (@prims) {
1007
 
                my $record = $tmp . "\t" . $prim;
1008
 
                if (length($record) > $length) {
1009
 
                    $self->throw("Something has gone horribly wrong - length of record is more than we thought [$length]\n");
1010
 
                } else {
1011
 
                    print $fh sprintf("%-${length}s",$record);
1012
 
                    print $fh sprintf("%-${length}s",$record);
1013
 
                }
1014
 
            }
1015
 
        }
1016
 
                
1017
 
        close($fh);
 
1002
        my @seconds = keys %{ $self->{_secondary_id}{$name} };
 
1003
 
 
1004
        # First we need to loop over to get the longest record.
 
1005
        my $length = 0;
 
1006
 
 
1007
        foreach my $second (@seconds) {
 
1008
            my $tmplen = length($second) + 1;
 
1009
            my @prims  = keys %{ $self->{_secondary_id}{$name}{$second} };
 
1010
 
 
1011
            foreach my $prim (@prims) {
 
1012
                my $recordlen = $tmplen + length($prim);
 
1013
 
 
1014
                if ( $recordlen > $length ) {
 
1015
                    $length = $recordlen;
 
1016
                }
 
1017
            }
 
1018
        }
 
1019
 
 
1020
        # Now we can print the index
 
1021
 
 
1022
        my $fh = $self->new_secondary_filehandle($name);
 
1023
 
 
1024
        print $fh sprintf( "%04d", $length );
 
1025
        @seconds = sort @seconds;
 
1026
 
 
1027
        foreach my $second (@seconds) {
 
1028
 
 
1029
            my @prims = keys %{ $self->{_secondary_id}{$name}{$second} };
 
1030
            my $tmp   = $second;
 
1031
 
 
1032
            foreach my $prim (@prims) {
 
1033
                my $record = $tmp . "\t" . $prim;
 
1034
                if ( length($record) > $length ) {
 
1035
                    $self->throw(
 
1036
"Something has gone horribly wrong - length of record is more than we thought [$length]\n"
 
1037
                    );
 
1038
                }
 
1039
                else {
 
1040
                    print $fh sprintf( "%-${length}s", $record );
 
1041
                }
 
1042
            }
 
1043
        }
 
1044
 
 
1045
        close($fh);
1018
1046
    }
1019
1047
}
1020
1048
 
1022
1050
 
1023
1051
 Title   : new_secondary_filehandle
1024
1052
 Usage   : $obj->new_secondary_filehandle($newval)
1025
 
 Function: 
1026
 
 Example : 
 
1053
 Function:
 
1054
 Example :
1027
1055
 Returns : value of new_secondary_filehandle
1028
1056
 Args    : newvalue (optional)
1029
1057
 
1031
1059
=cut
1032
1060
 
1033
1061
sub new_secondary_filehandle {
1034
 
    my ($self,$name) = @_;
 
1062
    my ( $self, $name ) = @_;
1035
1063
 
1036
1064
    my $indexdir = $self->_config_path;
1037
1065
 
1038
 
    my $secindex = File::Spec->catfile($indexdir,"id_$name.index");
 
1066
    my $secindex = File::Spec->catfile( $indexdir, "id_$name.index" );
1039
1067
 
1040
 
    open(my $fh,">", $secindex) || $self->throw($!);
 
1068
    open( my $fh, ">", $secindex ) || $self->throw($!);
1041
1069
    return $fh;
1042
1070
}
1043
1071
 
1045
1073
 
1046
1074
 Title   : open_secondary_index
1047
1075
 Usage   : $obj->open_secondary_index($newval)
1048
 
 Function: 
1049
 
 Example : 
 
1076
 Function:
 
1077
 Example :
1050
1078
 Returns : value of open_secondary_index
1051
1079
 Args    : newvalue (optional)
1052
1080
 
1054
1082
=cut
1055
1083
 
1056
1084
sub open_secondary_index {
1057
 
    my ($self,$name) = @_;
1058
 
 
1059
 
    if (!defined($self->{_secondary_filehandle}{$name})) {
1060
 
 
1061
 
        my $indexdir = $self->_config_path;
1062
 
        my $secindex = $indexdir . "/id_$name.index";
1063
 
        
1064
 
        if (! -e $secindex) {
1065
 
            $self->throw("Index is not present for namespace [$name]\n");
1066
 
        }
1067
 
 
1068
 
        open(my $newfh,"<", $secindex) || $self->throw($!);
1069
 
        my $reclen = $self->read_header($newfh);
1070
 
 
1071
 
        $self->{_secondary_filehandle} {$name} = $newfh;
1072
 
        $self->{_secondary_record_size}{$name} = $reclen;
 
1085
    my ( $self, $name ) = @_;
 
1086
 
 
1087
    if ( !defined( $self->{_secondary_filehandle}{$name} ) ) {
 
1088
 
 
1089
        my $indexdir = $self->_config_path;
 
1090
        my $secindex = $indexdir . "/id_$name.index";
 
1091
 
 
1092
        if ( !-e $secindex ) {
 
1093
            $self->throw("Index is not present for namespace [$name]\n");
 
1094
        }
 
1095
 
 
1096
        open( my $newfh, "<", $secindex ) || $self->throw($!);
 
1097
        my $reclen = $self->read_header($newfh);
 
1098
 
 
1099
        $self->{_secondary_filehandle}{$name}  = $newfh;
 
1100
        $self->{_secondary_record_size}{$name} = $reclen;
1073
1101
    }
1074
1102
 
1075
1103
    return $self->{_secondary_filehandle}{$name};
1080
1108
 
1081
1109
 Title   : _add_id_position
1082
1110
 Usage   : $obj->_add_id_position($newval)
1083
 
 Function: 
1084
 
 Example : 
 
1111
 Function:
 
1112
 Example :
1085
1113
 Returns : value of _add_id_position
1086
1114
 Args    : newvalue (optional)
1087
1115
 
1089
1117
=cut
1090
1118
 
1091
1119
sub _add_id_position {
1092
 
        my ($self,$id,$pos,$fileid,$length,$secondary_id) = @_;
1093
 
 
1094
 
        if (!defined($id)) {
1095
 
                $self->throw("No id defined. Can't add id position");
1096
 
        }
1097
 
        if (!defined($pos)) {
1098
 
                $self->throw("No position defined. Can't add id position");
1099
 
        }
1100
 
        if ( ! defined($fileid)) {
1101
 
                $self->throw("No fileid defined. Can't add id position");
1102
 
        }
1103
 
        if (! defined($length) || $length <= 0) {
1104
 
                $self->throw("No length defined or <= 0 [$length]. Can't add id position");
1105
 
        }
1106
 
 
1107
 
        $self->{_id}{$id}{_pos}    = $pos;
1108
 
        $self->{_id}{$id}{_length} = $length;
1109
 
        $self->{_id}{$id}{_fileid} = $fileid;
1110
 
 
1111
 
        # Now the secondary ids
1112
 
 
1113
 
        foreach my $sec (keys (%$secondary_id)) {
1114
 
                my $value = $secondary_id->{$sec};
1115
 
                $self->{_secondary_id}{$sec}{$value}{$id} = 1;
1116
 
        }
1117
 
 
1118
 
        $self->{_maxidlength} = length($id)
1119
 
          if !exists $self->{_maxidlength} or 
1120
 
                 length($id) >= $self->{_maxidlength};
1121
 
 
1122
 
        $self->{_maxfileidlength} = length($fileid)
1123
 
          if !exists $self->{_maxfileidlength} or 
1124
 
                 length($fileid) >= $self->{_maxfileidlength};
1125
 
 
1126
 
        $self->{_maxposlength} = length($pos)
1127
 
          if !exists $self->{_maxposlength} or 
1128
 
                 length($pos) >= $self->{_maxposlength};
1129
 
 
1130
 
        $self->{_maxlengthlength} = length($length)
1131
 
          if !exists $self->{_maxlengthlength} or 
1132
 
                 length($length) >= $self->{_maxlengthlength};
 
1120
    my ( $self, $id, $pos, $fileid, $length, $secondary_id ) = @_;
 
1121
 
 
1122
    if ( !defined($id) ) {
 
1123
        $self->throw("No id defined. Can't add id position");
 
1124
    }
 
1125
    if ( !defined($pos) ) {
 
1126
        $self->throw("No position defined. Can't add id position");
 
1127
    }
 
1128
    if ( !defined($fileid) ) {
 
1129
        $self->throw("No fileid defined. Can't add id position");
 
1130
    }
 
1131
    if ( !defined($length) || $length <= 0 ) {
 
1132
        $self->throw(
 
1133
            "No length defined or <= 0 [$length]. Can't add id position");
 
1134
    }
 
1135
 
 
1136
    $self->{_id}{$id}{_pos}    = $pos;
 
1137
    $self->{_id}{$id}{_length} = $length;
 
1138
    $self->{_id}{$id}{_fileid} = $fileid;
 
1139
 
 
1140
    # Now the secondary ids
 
1141
 
 
1142
    foreach my $sec ( keys(%$secondary_id) ) {
 
1143
        my $value = $secondary_id->{$sec};
 
1144
        $self->{_secondary_id}{$sec}{$value}{$id} = 1;
 
1145
    }
 
1146
 
 
1147
    $self->{_maxidlength} = length($id)
 
1148
      if !exists $self->{_maxidlength}
 
1149
          or length($id) >= $self->{_maxidlength};
 
1150
 
 
1151
    $self->{_maxfileidlength} = length($fileid)
 
1152
      if !exists $self->{_maxfileidlength}
 
1153
          or length($fileid) >= $self->{_maxfileidlength};
 
1154
 
 
1155
    $self->{_maxposlength} = length($pos)
 
1156
      if !exists $self->{_maxposlength}
 
1157
          or length($pos) >= $self->{_maxposlength};
 
1158
 
 
1159
    $self->{_maxlengthlength} = length($length)
 
1160
      if !exists $self->{_maxlengthlength}
 
1161
          or length($length) >= $self->{_maxlengthlength};
1133
1162
}
1134
1163
 
1135
1164
=head2 make_config_file
1136
1165
 
1137
1166
 Title   : make_config_file
1138
1167
 Usage   : $obj->make_config_file($newval)
1139
 
 Function: 
1140
 
 Example : 
 
1168
 Function:
 
1169
 Example :
1141
1170
 Returns : value of make_config_file
1142
1171
 Args    : newvalue (optional)
1143
1172
 
1144
1173
=cut
1145
1174
 
1146
1175
sub make_config_file {
1147
 
    my ($self,$files) = @_;
1148
 
    
 
1176
    my ( $self, $files ) = @_;
 
1177
 
1149
1178
    my @files = @$files;
1150
1179
 
1151
1180
    my $configfile = $self->_config_file;
1152
1181
 
1153
 
    open(my $CON,">", $configfile) || $self->throw("Can't create config file [$configfile]");
 
1182
    open( my $CON, ">", $configfile )
 
1183
      || $self->throw("Can't create config file [$configfile]");
1154
1184
 
1155
1185
    # First line must be the type of index - in this case flat
1156
1186
    print $CON "index\tflat/1\n";
1161
1191
 
1162
1192
    foreach my $file (@files) {
1163
1193
 
1164
 
        my $size = -s $file;
1165
 
 
1166
 
        print $CON "fileid_$count\t$file\t$size\n";
1167
 
 
1168
 
        my $fh;
1169
 
        open($fh,"<", $file) || $self->throw($!);
1170
 
        $self->{_file}  {$count}   = $file;
1171
 
        $self->{_dbfile}{$file}    = $count;
1172
 
        $self->{_size}{$count}     = $size; 
1173
 
        $count++;
 
1194
        my $size = -s $file;
 
1195
 
 
1196
        print $CON "fileid_$count\t$file\t$size\n";
 
1197
 
 
1198
        my $fh;
 
1199
        open( $fh, "<", $file ) || $self->throw($!);
 
1200
        $self->{_file}{$count}  = $file;
 
1201
        $self->{_dbfile}{$file} = $count;
 
1202
        $self->{_size}{$count}  = $size;
 
1203
        $count++;
1174
1204
    }
1175
1205
 
1176
1206
    # Now the namespaces
1177
1207
 
1178
 
    print $CON "primary_namespace\t" .$self->primary_namespace. "\n";
1179
 
    
 
1208
    print $CON "primary_namespace\t" . $self->primary_namespace . "\n";
 
1209
 
1180
1210
    # Needs fixing for the secondary stuff
1181
1211
 
1182
1212
    my $second_patterns = $self->secondary_patterns;
1183
1213
 
1184
1214
    my @second = keys %$second_patterns;
1185
1215
 
1186
 
    if ((@second))  {
1187
 
        print $CON "secondary_namespaces";
 
1216
    if ( (@second) ) {
 
1217
        print $CON "secondary_namespaces";
1188
1218
 
1189
 
        foreach my $second (@second) {
1190
 
            print $CON "\t$second";
1191
 
        }
 
1219
        foreach my $second (@second) {
 
1220
            print $CON "\t$second";
 
1221
        }
1192
1222
        print $CON "\n";
1193
1223
    }
1194
1224
 
1195
1225
    # Now the config format
1196
1226
 
1197
 
    unless (defined ($self->format) ) {
1198
 
        $self->throw("Format does not exist in module - can't write config file");
1199
 
    } else {
1200
 
        my $format = $self->format;
1201
 
        my $alphabet = $self->alphabet;
1202
 
        my $alpha    = $alphabet ? "/$alphabet" : '';
1203
 
        print $CON "format\t" . "$format\n";
1204
 
     }
 
1227
    unless ( defined( $self->format ) ) {
 
1228
        $self->throw(
 
1229
            "Format does not exist in module - can't write config file");
 
1230
    }
 
1231
    else {
 
1232
        my $format   = $self->format;
 
1233
        my $alphabet = $self->alphabet;
 
1234
        my $alpha    = $alphabet ? "/$alphabet" : '';
 
1235
        print $CON "format\t" . "$format\n";
 
1236
    }
1205
1237
    close($CON);
1206
1238
}
1207
1239
 
1209
1241
 
1210
1242
 Title   : read_config_file
1211
1243
 Usage   : $obj->read_config_file($newval)
1212
 
 Function: 
1213
 
 Example : 
 
1244
 Function:
 
1245
 Example :
1214
1246
 Returns : value of read_config_file
1215
1247
 Args    : newvalue (optional)
1216
1248
 
1217
1249
=cut
1218
1250
 
1219
1251
sub read_config_file {
1220
 
        my ($self) = @_;
1221
 
        my $configfile = $self->_config_file;
1222
 
        return unless -e $configfile;
1223
 
 
1224
 
        open(my $CON,"<", $configfile) || $self->throw("Can't open configfile [$configfile]");
1225
 
 
1226
 
        # First line must be type
1227
 
        my $line = <$CON>; 
1228
 
        chomp($line);
1229
 
        my $version;
1230
 
 
1231
 
        # This is hard coded as we only index flatfiles here
1232
 
        if ($line =~ m{index\tflat/(\d+)}) {
1233
 
                $version = $1;
1234
 
        } else {
1235
 
                $self->throw("First line not compatible with flat file index.  Should be something like\n\nindex\tflat/1");
1236
 
        }
1237
 
 
1238
 
        $self->index_type("flat");
1239
 
        $self->index_version($version);
1240
 
 
1241
 
        while (<$CON>) {
1242
 
                chomp;
1243
 
 
1244
 
                # Look for fileid lines
1245
 
                if ($_ =~ /^fileid_(\d+)\t(.+)\t(\d+)/) {
1246
 
                        my $fileid   = $1;
1247
 
                        my $filename = $2;
1248
 
                        my $filesize = $3;
1249
 
 
1250
 
                        if (! -e $filename) {
1251
 
                                $self->throw("File [$filename] does not exist!");
1252
 
                        }
1253
 
                        if (-s $filename != $filesize) {
1254
 
                                $self->throw("Flatfile size for $filename differs from what the index thinks it is. Real size [" . (-s $filename) . "] Index thinks it is [" . $filesize  . "]");
1255
 
                        }
1256
 
                
1257
 
                        my $fh;
1258
 
                        open($fh,"<", $filename) || $self->throw($!);
1259
 
                        $self->{_file}  {$fileid}   = $filename;
1260
 
                        $self->{_dbfile}{$filename} = $fileid;
1261
 
                        $self->{_size}  {$fileid}   = $filesize; 
1262
 
                }
1263
 
                
1264
 
                # Look for namespace lines
1265
 
                if ( /(.*)_namespaces?\t(.+)/ ) {
1266
 
              if ($1 eq "primary") {
1267
 
                       $self->primary_namespace($2);
1268
 
              } elsif ($1 eq "secondary") {
1269
 
                       $self->secondary_namespaces(split "\t",$2);
1270
 
              } else {
1271
 
                       $self->throw("Unknown namespace name in config file [$1");
1272
 
              }
1273
 
           }
1274
 
        
1275
 
           # Look for format lines
1276
 
           if ($_ =~ /format\t(\S+)/) {
1277
 
              # Check the format here?
1278
 
              my $format = $1;
1279
 
 
1280
 
              # handle LSID format
1281
 
              if ($format =~ /^URN:LSID:open-bio\.org:(\w+)(?:\/(\w+))?/) {
1282
 
                 $self->format($1);
1283
 
                 $self->alphabet($2);
1284
 
              } else {  # compatibility with older versions
1285
 
                 $self->format($1);
1286
 
              }
1287
 
            }
1288
 
    }
1289
 
    
 
1252
    my ($self) = @_;
 
1253
    my $configfile = $self->_config_file;
 
1254
    return unless -e $configfile;
 
1255
 
 
1256
    open( my $CON, "<", $configfile )
 
1257
      || $self->throw("Can't open configfile [$configfile]");
 
1258
 
 
1259
    # First line must be type
 
1260
    my $line = <$CON>;
 
1261
    chomp($line);
 
1262
    my $version;
 
1263
 
 
1264
    # This is hard coded as we only index flatfiles here
 
1265
    if ( $line =~ m{index\tflat/(\d+)} ) {
 
1266
        $version = $1;
 
1267
    }
 
1268
    else {
 
1269
        $self->throw(
 
1270
"First line not compatible with flat file index.  Should be something like\n\nindex\tflat/1"
 
1271
        );
 
1272
    }
 
1273
 
 
1274
    $self->index_type("flat");
 
1275
    $self->index_version($version);
 
1276
 
 
1277
    while (<$CON>) {
 
1278
        chomp;
 
1279
 
 
1280
        # Look for fileid lines
 
1281
        if ( $_ =~ /^fileid_(\d+)\t(.+)\t(\d+)/ ) {
 
1282
            my $fileid   = $1;
 
1283
            my $filename = $2;
 
1284
            my $filesize = $3;
 
1285
 
 
1286
            if ( !-e $filename ) {
 
1287
                $self->throw("File [$filename] does not exist!");
 
1288
            }
 
1289
            if ( -s $filename != $filesize ) {
 
1290
                $self->throw(
 
1291
"Flatfile size for $filename differs from what the index thinks it is. Real size ["
 
1292
                      . ( -s $filename )
 
1293
                      . "] Index thinks it is ["
 
1294
                      . $filesize
 
1295
                      . "]" );
 
1296
            }
 
1297
 
 
1298
            my $fh;
 
1299
            open( $fh, "<", $filename ) || $self->throw($!);
 
1300
            $self->{_file}{$fileid}     = $filename;
 
1301
            $self->{_dbfile}{$filename} = $fileid;
 
1302
            $self->{_size}{$fileid}     = $filesize;
 
1303
        }
 
1304
 
 
1305
        # Look for namespace lines
 
1306
        if (/(.*)_namespaces?\t(.+)/) {
 
1307
            if ( $1 eq "primary" ) {
 
1308
                $self->primary_namespace($2);
 
1309
            }
 
1310
            elsif ( $1 eq "secondary" ) {
 
1311
                $self->secondary_namespaces( split "\t", $2 );
 
1312
            }
 
1313
            else {
 
1314
                $self->throw("Unknown namespace name in config file [$1");
 
1315
            }
 
1316
        }
 
1317
 
 
1318
        # Look for format lines
 
1319
        if ( $_ =~ /format\t(\S+)/ ) {
 
1320
 
 
1321
            # Check the format here?
 
1322
            my $format = $1;
 
1323
 
 
1324
            # handle LSID format
 
1325
            if ( $format =~ /^URN:LSID:open-bio\.org:(\w+)(?:\/(\w+))?/ ) {
 
1326
                $self->format($1);
 
1327
                $self->alphabet($2);
 
1328
            }
 
1329
            else {    # compatibility with older versions
 
1330
                $self->format($1);
 
1331
            }
 
1332
        }
 
1333
    }
 
1334
 
1290
1335
    close($CON);
1291
1336
 
1292
1337
    # Now check we have all that we need
1293
1338
 
1294
 
    my @fileid_keys = keys (%{$self->{_file}});
1295
 
 
1296
 
    if (!(@fileid_keys)) {
1297
 
             $self->throw("No flatfile fileid files in config - check the index has been made correctly");
1298
 
    }
1299
 
 
1300
 
    if (!defined($self->primary_namespace)) {
1301
 
            $self->throw("No primary namespace exists");
1302
 
    }
1303
 
 
1304
 
    if (! -e $self->primary_index_file) {
1305
 
            $self->throw("Primary index file [" . $self->primary_index_file . "] doesn't exist");
 
1339
    my @fileid_keys = keys( %{ $self->{_file} } );
 
1340
 
 
1341
    if ( !(@fileid_keys) ) {
 
1342
        $self->throw(
 
1343
"No flatfile fileid files in config - check the index has been made correctly"
 
1344
        );
 
1345
    }
 
1346
 
 
1347
    if ( !defined( $self->primary_namespace ) ) {
 
1348
        $self->throw("No primary namespace exists");
 
1349
    }
 
1350
 
 
1351
    if ( !-e $self->primary_index_file ) {
 
1352
        $self->throw( "Primary index file ["
 
1353
              . $self->primary_index_file
 
1354
              . "] doesn't exist" );
1306
1355
    }
1307
1356
 
1308
1357
    1;
1312
1361
 
1313
1362
 Title   : get_fileid_by_filename
1314
1363
 Usage   : $obj->get_fileid_by_filename($newval)
1315
 
 Function: 
1316
 
 Example : 
 
1364
 Function:
 
1365
 Example :
1317
1366
 Returns : value of get_fileid_by_filename
1318
1367
 Args    : newvalue (optional)
1319
1368
 
1320
1369
=cut
1321
1370
 
1322
1371
sub get_fileid_by_filename {
1323
 
    my ($self,$file) = @_;
1324
 
    
1325
 
    if (!defined($self->{_dbfile})) {
1326
 
        $self->throw("No file to fileid mapping present.  Has the fileid file been read?");
 
1372
    my ( $self, $file ) = @_;
 
1373
 
 
1374
    if ( !defined( $self->{_dbfile} ) ) {
 
1375
        $self->throw(
 
1376
            "No file to fileid mapping present.  Has the fileid file been read?"
 
1377
        );
1327
1378
    }
1328
1379
 
1329
 
    
1330
1380
    return $self->{_dbfile}{$file};
1331
1381
}
1332
1382
 
1334
1384
 
1335
1385
 Title   : get_filehandle_by_fileid
1336
1386
 Usage   : $obj->get_filehandle_by_fileid($newval)
1337
 
 Function: 
1338
 
 Example : 
 
1387
 Function:
 
1388
 Example :
1339
1389
 Returns : value of get_filehandle_by_fileid
1340
1390
 Args    : newvalue (optional)
1341
1391
 
1342
1392
=cut
1343
1393
 
1344
1394
sub get_filehandle_by_fileid {
1345
 
    my ($self,$fileid) = @_;
 
1395
    my ( $self, $fileid ) = @_;
1346
1396
 
1347
 
    if (!defined($self->{_file}{$fileid})) {
1348
 
        $self->throw("ERROR: undefined fileid in index [$fileid]");
 
1397
    if ( !defined( $self->{_file}{$fileid} ) ) {
 
1398
        $self->throw("ERROR: undefined fileid in index [$fileid]");
1349
1399
    }
1350
 
   
1351
 
        my $fh;
1352
 
        open($fh,"<", $self->{_file}{$fileid}) || $self->throw($!);
 
1400
 
 
1401
    my $fh;
 
1402
    open( $fh, "<", $self->{_file}{$fileid} ) || $self->throw($!);
1353
1403
    return $fh;
1354
1404
}
1355
1405
 
1357
1407
 
1358
1408
 Title   : primary_index_file
1359
1409
 Usage   : $obj->primary_index_file($newval)
1360
 
 Function: 
1361
 
 Example : 
 
1410
 Function:
 
1411
 Example :
1362
1412
 Returns : value of primary_index_file
1363
1413
 Args    : newvalue (optional)
1364
1414
 
1368
1418
sub primary_index_file {
1369
1419
    my ($self) = @_;
1370
1420
 
1371
 
    return File::Spec->catfile($self->_config_path,"key_" . $self->primary_namespace . ".key");
 
1421
    return File::Spec->catfile( $self->_config_path,
 
1422
        "key_" . $self->primary_namespace . ".key" );
1372
1423
}
1373
1424
 
1374
1425
=head2 primary_index_filehandle
1375
1426
 
1376
1427
 Title   : primary_index_filehandle
1377
1428
 Usage   : $obj->primary_index_filehandle($newval)
1378
 
 Function: 
1379
 
 Example : 
 
1429
 Function:
 
1430
 Example :
1380
1431
 Returns : value of primary_index_filehandle
1381
1432
 Args    : newvalue (optional)
1382
1433
 
1386
1437
sub primary_index_filehandle {
1387
1438
    my ($self) = @_;
1388
1439
 
1389
 
    unless (defined ($self->{'_primary_index_handle'})) {
1390
 
        open($self->{'_primary_index_handle'}, "<" . $self->primary_index_file) || self->throw($@);
 
1440
    unless ( defined( $self->{'_primary_index_handle'} ) ) {
 
1441
        open( $self->{'_primary_index_handle'},
 
1442
            "<" . $self->primary_index_file )
 
1443
          || self->throw($@);
1391
1444
    }
1392
1445
    return $self->{'_primary_index_handle'};
1393
1446
}
1396
1449
 
1397
1450
 Title   : format
1398
1451
 Usage   : $obj->format($newval)
1399
 
 Function: 
1400
 
 Example : 
 
1452
 Function:
 
1453
 Example :
1401
1454
 Returns : value of format
1402
1455
 Args    : newvalue (optional)
1403
1456
 
1404
1457
 
1405
1458
=cut
1406
1459
 
1407
 
sub format{
1408
 
   my ($obj,$value) = @_;
1409
 
   if( defined $value) {
1410
 
      $obj->{'format'} = $value;
 
1460
sub format {
 
1461
    my ( $obj, $value ) = @_;
 
1462
    if ( defined $value ) {
 
1463
        $obj->{'format'} = $value;
1411
1464
    }
1412
1465
    return $obj->{'format'};
1413
1466
 
1414
1467
}
1415
1468
 
1416
 
sub alphabet{
1417
 
   my ($obj,$value) = @_;
1418
 
   if( defined $value) {
1419
 
      $obj->{alphabet} = $value;
 
1469
sub alphabet {
 
1470
    my ( $obj, $value ) = @_;
 
1471
    if ( defined $value ) {
 
1472
        $obj->{alphabet} = $value;
1420
1473
    }
1421
1474
    return $obj->{alphabet};
1422
1475
}
1425
1478
 
1426
1479
 Title   : write_flag
1427
1480
 Usage   : $obj->write_flag($newval)
1428
 
 Function: 
1429
 
 Example : 
 
1481
 Function:
 
1482
 Example :
1430
1483
 Returns : value of write_flag
1431
1484
 Args    : newvalue (optional)
1432
1485
 
1433
1486
 
1434
1487
=cut
1435
1488
 
1436
 
sub write_flag{
1437
 
   my ($obj,$value) = @_;
1438
 
   if( defined $value) {
1439
 
      $obj->{'write_flag'} = $value;
 
1489
sub write_flag {
 
1490
    my ( $obj, $value ) = @_;
 
1491
    if ( defined $value ) {
 
1492
        $obj->{'write_flag'} = $value;
1440
1493
    }
1441
1494
    return $obj->{'write_flag'};
1442
1495
 
1447
1500
 Title   : dbname
1448
1501
 Usage   : $obj->dbname($newval)
1449
1502
 Function: get/set database name
1450
 
 Example : 
 
1503
 Example :
1451
1504
 Returns : value of dbname
1452
1505
 Args    : newvalue (optional)
1453
1506
 
1454
1507
=cut
1455
1508
 
1456
1509
sub dbname {
1457
 
  my $self = shift;
1458
 
  my $d = $self->{flat_dbname};
1459
 
  $self->{flat_dbname} = shift if @_;
1460
 
  $d;
 
1510
    my $self = shift;
 
1511
    my $d    = $self->{flat_dbname};
 
1512
    $self->{flat_dbname} = shift if @_;
 
1513
    $d;
1461
1514
}
1462
1515
 
1463
1516
=head2 index_directory
1464
1517
 
1465
1518
 Title   : index_directory
1466
1519
 Usage   : $obj->index_directory($newval)
1467
 
 Function: 
1468
 
 Example : 
 
1520
 Function:
 
1521
 Example :
1469
1522
 Returns : value of index_directory
1470
1523
 Args    : newvalue (optional)
1471
1524
 
1473
1526
=cut
1474
1527
 
1475
1528
sub index_directory {
1476
 
    my ($self,$arg) = @_;
 
1529
    my ( $self, $arg ) = @_;
1477
1530
 
1478
 
    if (defined($arg)) {
1479
 
        if ($arg !~ m{/$}) {
1480
 
            $arg .= "/";
1481
 
        }
1482
 
        $self->{_index_directory} = $arg;
 
1531
    if ( defined($arg) ) {
 
1532
        if ( $arg !~ m{/$} ) {
 
1533
            $arg .= "/";
 
1534
        }
 
1535
        $self->{_index_directory} = $arg;
1483
1536
    }
1484
1537
    return $self->{_index_directory};
1485
1538
 
1486
1539
}
1487
1540
 
1488
1541
sub _config_path {
1489
 
  my $self = shift;
1490
 
  my $root = $self->index_directory;
1491
 
  my $dbname = $self->dbname;
1492
 
  File::Spec->catfile($root,$dbname);
 
1542
    my $self   = shift;
 
1543
    my $root   = $self->index_directory;
 
1544
    my $dbname = $self->dbname;
 
1545
    File::Spec->catfile( $root, $dbname );
1493
1546
}
1494
1547
 
1495
1548
sub _config_file {
1496
 
  my $self = shift;
1497
 
  my $path = $self->_config_path;
1498
 
  File::Spec->catfile($path,CONFIG_FILE_NAME);
 
1549
    my $self = shift;
 
1550
    my $path = $self->_config_path;
 
1551
    File::Spec->catfile( $path, CONFIG_FILE_NAME );
1499
1552
}
1500
1553
 
1501
1554
=head2 record_size
1502
1555
 
1503
1556
 Title   : record_size
1504
1557
 Usage   : $obj->record_size($newval)
1505
 
 Function: 
1506
 
 Example : 
 
1558
 Function:
 
1559
 Example :
1507
1560
 Returns : value of record_size
1508
1561
 Args    : newvalue (optional)
1509
1562
 
1520
1573
 
1521
1574
 Title   : primary_namespace
1522
1575
 Usage   : $obj->primary_namespace($newval)
1523
 
 Function: 
1524
 
 Example : 
 
1576
 Function:
 
1577
 Example :
1525
1578
 Returns : value of primary_namespace
1526
1579
 Args    : newvalue (optional)
1527
1580
 
1529
1582
 
1530
1583
sub primary_namespace {
1531
1584
    my $self = shift;
1532
 
    $self->{_primary_namespace} =  shift if @_;
 
1585
    $self->{_primary_namespace} = shift if @_;
1533
1586
    return $self->{_primary_namespace};
1534
1587
}
1535
1588
 
1537
1590
 
1538
1591
 Title   : index_type
1539
1592
 Usage   : $obj->index_type($newval)
1540
 
 Function: 
1541
 
 Example : 
 
1593
 Function:
 
1594
 Example :
1542
1595
 Returns : value of index_type
1543
1596
 Args    : newvalue (optional)
1544
1597
 
1555
1608
 
1556
1609
 Title   : index_version
1557
1610
 Usage   : $obj->index_version($newval)
1558
 
 Function: 
1559
 
 Example : 
 
1611
 Function:
 
1612
 Example :
1560
1613
 Returns : value of index_version
1561
1614
 Args    : newvalue (optional)
1562
1615
 
1573
1626
 
1574
1627
 Title   : primary_pattern
1575
1628
 Usage   : $obj->primary_pattern($newval)
1576
 
 Function: 
1577
 
 Example : 
 
1629
 Function:
 
1630
 Example :
1578
1631
 Returns : value of primary_pattern
1579
1632
 Args    : newvalue (optional)
1580
1633
 
1581
1634
 
1582
1635
=cut
1583
1636
 
1584
 
sub primary_pattern{
 
1637
sub primary_pattern {
1585
1638
    my $obj = shift;
1586
1639
    $obj->{'primary_pattern'} = shift if @_;
1587
1640
    return $obj->{'primary_pattern'};
1591
1644
 
1592
1645
 Title   : start_pattern
1593
1646
 Usage   : $obj->start_pattern($newval)
1594
 
 Function: 
1595
 
 Example : 
 
1647
 Function:
 
1648
 Example :
1596
1649
 Returns : value of start_pattern
1597
1650
 Args    : newvalue (optional)
1598
1651
 
1599
1652
 
1600
1653
=cut
1601
1654
 
1602
 
sub start_pattern{
 
1655
sub start_pattern {
1603
1656
    my $obj = shift;
1604
1657
    $obj->{'start_pattern'} = shift if @_;
1605
1658
    return $obj->{'start_pattern'};
1609
1662
 
1610
1663
 Title   : secondary_patterns
1611
1664
 Usage   : $obj->secondary_patterns($newval)
1612
 
 Function: 
1613
 
 Example : 
 
1665
 Function:
 
1666
 Example :
1614
1667
 Returns : value of secondary_patterns
1615
1668
 Args    : newvalue (optional)
1616
1669
 
1617
1670
 
1618
1671
=cut
1619
1672
 
1620
 
sub secondary_patterns{
1621
 
   my ($obj,$value) = @_;
1622
 
   if( defined $value) {
1623
 
      $obj->{'secondary_patterns'} = $value;
1624
 
 
1625
 
      my @names = keys %$value;
1626
 
 
1627
 
      foreach my $name (@names) {
1628
 
          $obj->secondary_namespaces($name);
1629
 
      }
 
1673
sub secondary_patterns {
 
1674
    my ( $obj, $value ) = @_;
 
1675
    if ( defined $value ) {
 
1676
        $obj->{'secondary_patterns'} = $value;
 
1677
 
 
1678
        my @names = keys %$value;
 
1679
 
 
1680
        foreach my $name (@names) {
 
1681
            $obj->secondary_namespaces($name);
 
1682
        }
1630
1683
    }
1631
1684
    return $obj->{'secondary_patterns'};
1632
1685
 
1636
1689
 
1637
1690
 Title   : secondary_namespaces
1638
1691
 Usage   : $obj->secondary_namespaces($newval)
1639
 
 Function: 
1640
 
 Example : 
 
1692
 Function:
 
1693
 Example :
1641
1694
 Returns : value of secondary_namespaces
1642
1695
 Args    : newvalue (optional)
1643
1696
 
1645
1698
=cut
1646
1699
 
1647
1700
sub secondary_namespaces {
1648
 
    my ($obj,@values) = @_;
 
1701
    my ( $obj, @values ) = @_;
1649
1702
 
1650
1703
    if (@values) {
1651
 
        push(@{$obj->{'secondary_namespaces'}},@values);
 
1704
        push( @{ $obj->{'secondary_namespaces'} }, @values );
1652
1705
    }
1653
 
    return @{$obj->{'secondary_namespaces'} || []};
 
1706
    return @{ $obj->{'secondary_namespaces'} || [] };
1654
1707
}
1655
1708
 
1656
 
 
1657
 
 
1658
1709
## These are indexing routines to index commonly used format - fasta
1659
1710
## swissprot and embl
1660
1711
 
1661
1712
sub new_SWISSPROT_index {
1662
 
    my ($self,$index_dir,@files) = @_;
 
1713
    my ( $self, $index_dir, @files ) = @_;
1663
1714
 
1664
1715
    my %secondary_patterns;
1665
1716
 
1666
 
    my $start_pattern = "^ID   (\\S+)";
 
1717
    my $start_pattern   = "^ID   (\\S+)";
1667
1718
    my $primary_pattern = "^AC   (\\S+)\\;";
1668
1719
 
1669
1720
    $secondary_patterns{"ID"} = $start_pattern;
1670
1721
 
1671
 
    my $index =  Bio::DB::Flat::BinarySearch->new
1672
 
        (-index_dir          => $index_dir,
1673
 
         -format             => 'swissprot',
1674
 
         -primary_pattern    => $primary_pattern,
1675
 
         -primary_namespace  => "ACC",
1676
 
         -start_pattern      => $start_pattern,
1677
 
         -secondary_patterns => \%secondary_patterns);
 
1722
    my $index = Bio::DB::Flat::BinarySearch->new(
 
1723
        -index_dir          => $index_dir,
 
1724
        -format             => 'swissprot',
 
1725
        -primary_pattern    => $primary_pattern,
 
1726
        -primary_namespace  => "ACC",
 
1727
        -start_pattern      => $start_pattern,
 
1728
        -secondary_patterns => \%secondary_patterns
 
1729
    );
1678
1730
 
1679
1731
    $index->build_index(@files);
1680
1732
}
1681
1733
 
1682
1734
sub new_EMBL_index {
1683
 
   my ($self,$index_dir,@files) = @_;
1684
 
 
1685
 
   my %secondary_patterns;
1686
 
 
1687
 
   my $start_pattern = "^ID   (\\S+)";
1688
 
   my $primary_pattern = "^AC   (\\S+)\\;";
1689
 
   my $primary_namespace = "ACC";
1690
 
 
1691
 
   $secondary_patterns{"ID"} = $start_pattern;
1692
 
 
1693
 
   my $index = Bio::DB::Flat::BinarySearch->new
1694
 
       (-index_dir          => $index_dir,
1695
 
        -format             => 'embl',
1696
 
        -primary_pattern    => $primary_pattern,
1697
 
        -primary_namespace  => "ACC",
1698
 
        -start_pattern      => $start_pattern,
1699
 
        -secondary_patterns => \%secondary_patterns);
 
1735
    my ( $self, $index_dir, @files ) = @_;
 
1736
 
 
1737
    my %secondary_patterns;
 
1738
 
 
1739
    my $start_pattern     = "^ID   (\\S+)";
 
1740
    my $primary_pattern   = "^AC   (\\S+)\\;";
 
1741
    my $primary_namespace = "ACC";
 
1742
 
 
1743
    $secondary_patterns{"ID"} = $start_pattern;
 
1744
 
 
1745
    my $index = Bio::DB::Flat::BinarySearch->new(
 
1746
        -index_dir          => $index_dir,
 
1747
        -format             => 'embl',
 
1748
        -primary_pattern    => $primary_pattern,
 
1749
        -primary_namespace  => "ACC",
 
1750
        -start_pattern      => $start_pattern,
 
1751
        -secondary_patterns => \%secondary_patterns
 
1752
    );
1700
1753
 
1701
1754
    $index->build_index(@files);
1702
1755
 
1703
 
   return $index;
 
1756
    return $index;
1704
1757
}
1705
1758
 
1706
1759
sub new_FASTA_index {
1707
 
   my ($self,$index_dir,@files) =  @_;
1708
 
 
1709
 
   my %secondary_patterns;
1710
 
 
1711
 
   my $start_pattern = "^>";
1712
 
   my $primary_pattern = "^>(\\S+)";
1713
 
   my $primary_namespace = "ACC"; 
1714
 
 
1715
 
   $secondary_patterns{"ID"} = "^>\\S+ +(\\S+)";
1716
 
 
1717
 
   my $index =  Bio::DB::Flat::BinarySearch->new
1718
 
       (-index_dir          => $index_dir,
1719
 
        -format             => 'fasta',
1720
 
        -primary_pattern    => $primary_pattern,
1721
 
        -primary_namespace  => "ACC",
1722
 
        -start_pattern      => $start_pattern,
1723
 
        -secondary_patterns => \%secondary_patterns);
1724
 
 
1725
 
   $index->build_index(@files);
1726
 
 
1727
 
   return $index;
 
1760
    my ( $self, $index_dir, @files ) = @_;
 
1761
 
 
1762
    my %secondary_patterns;
 
1763
 
 
1764
    my $start_pattern     = "^>";
 
1765
    my $primary_pattern   = "^>(\\S+)";
 
1766
    my $primary_namespace = "ACC";
 
1767
 
 
1768
    $secondary_patterns{"ID"} = "^>\\S+ +(\\S+)";
 
1769
 
 
1770
    my $index = Bio::DB::Flat::BinarySearch->new(
 
1771
        -index_dir          => $index_dir,
 
1772
        -format             => 'fasta',
 
1773
        -primary_pattern    => $primary_pattern,
 
1774
        -primary_namespace  => "ACC",
 
1775
        -start_pattern      => $start_pattern,
 
1776
        -secondary_patterns => \%secondary_patterns
 
1777
    );
 
1778
 
 
1779
    $index->build_index(@files);
 
1780
 
 
1781
    return $index;
1728
1782
}
1729
1783
 
1730
1784
# EVERYTHING THAT FOLLOWS THIS
1731
1785
# is an awful hack - in reality Michele's code needs to be rewritten
1732
1786
# to use Bio::SeqIO, but I have too little time to do this -- LS
1733
1787
sub guess_alphabet {
1734
 
  my $self = shift;
1735
 
  my $line = shift;
1736
 
 
1737
 
  my $format = $self->format;
1738
 
  return 'protein' if $format eq 'swissprot';
1739
 
 
1740
 
  if ($format eq 'genbank') {
1741
 
    return unless $line =~ /^LOCUS/;
1742
 
    return 'dna' if $line =~ /\s+\d+\s+bp/i;
1743
 
    return 'protein';
1744
 
  }
1745
 
 
1746
 
  if ($format eq 'embl') {
1747
 
    return unless $line =~ /^ID/;
1748
 
    return 'dna' if $line =~ / DNA;/i;
1749
 
    return 'rna' if $line =~ / RNA;/i;
1750
 
    return 'protein';
1751
 
  }
1752
 
 
1753
 
  return;
 
1788
    my $self = shift;
 
1789
    my $line = shift;
 
1790
 
 
1791
    my $format = $self->format;
 
1792
    return 'protein' if $format eq 'swissprot';
 
1793
 
 
1794
    if ( $format eq 'genbank' ) {
 
1795
        return unless $line =~ /^LOCUS/;
 
1796
        return 'dna' if $line =~ /\s+\d+\s+bp/i;
 
1797
        return 'protein';
 
1798
    }
 
1799
 
 
1800
    if ( $format eq 'embl' ) {
 
1801
        return unless $line =~ /^ID/;
 
1802
        return 'dna' if $line =~ / DNA;/i;
 
1803
        return 'rna' if $line =~ / RNA;/i;
 
1804
        return 'protein';
 
1805
    }
 
1806
 
 
1807
    return;
1754
1808
}
1755
1809
 
1756
1810
# return (namespace,primary_pattern,start_pattern,secondary_pattern)
1757
1811
sub _guess_patterns {
1758
 
  my $self = shift;
1759
 
  my $format = shift;
1760
 
  if ($format =~ /swiss(prot)?/i) {
1761
 
    return ('ID',
1762
 
            "^ID   (\\S+)",
1763
 
            "^ID   (\\S+)",
1764
 
            {
1765
 
             ACC  => "^AC   (\\S+);"
1766
 
            });
1767
 
  }
1768
 
 
1769
 
  if ($format =~ /embl/i) {
1770
 
    return ('ID',
1771
 
            "^ID   (\\S+)",
1772
 
            "^ID   (\\S+)",
1773
 
            {
1774
 
             ACC     => q/^AC   (\S+);/,
1775
 
             VERSION => q/^SV\s+(\S+)/
1776
 
            });
1777
 
  }
1778
 
 
1779
 
  if ($format =~ /genbank/i) {
1780
 
    return ('ID',
1781
 
            q/^LOCUS\s+(\S+)/,
1782
 
            q/^LOCUS/,
1783
 
            {
1784
 
             ACC     => q/^ACCESSION\s+(\S+)/,
1785
 
             VERSION => q/^VERSION\s+(\S+)/
1786
 
            });
1787
 
  }
1788
 
 
1789
 
  if ($format =~ /fasta/i) {
1790
 
    return ('ACC',
1791
 
            '^>(\S+)',
1792
 
            '^>(\S+)',
1793
 
           );
1794
 
  }
1795
 
 
1796
 
  $self->throw("I can't handle format $format");
 
1812
    my $self   = shift;
 
1813
    my $format = shift;
 
1814
    if ( $format =~ /swiss(prot)?/i ) {
 
1815
        return ( 'ID', "^ID   (\\S+)", "^ID   (\\S+)",
 
1816
            { ACC => "^AC   (\\S+);" } );
 
1817
    }
 
1818
 
 
1819
    if ($format =~ /embl/i) {
 
1820
        return ('ID',
 
1821
            "^ID   (\\S+[^; ])",
 
1822
            "^ID   (\\S+[^; ])",
 
1823
            {
 
1824
             ACC     => q/^AC   (\S+);/,
 
1825
             VERSION => q/^SV\s+(\S+)/
 
1826
            });
 
1827
     }
 
1828
 
 
1829
    if ( $format =~ /genbank/i ) {
 
1830
        return (
 
1831
            'ID',
 
1832
            q/^LOCUS\s+(\S+)/,
 
1833
            q/^LOCUS/,
 
1834
            {
 
1835
                ACC     => q/^ACCESSION\s+(\S+)/,
 
1836
                VERSION => q/^VERSION\s+(\S+)/
 
1837
            }
 
1838
        );
 
1839
    }
 
1840
 
 
1841
    if ( $format =~ /fasta/i ) {
 
1842
        return ( 'ACC', '^>(\S+)', '^>(\S+)', );
 
1843
    }
 
1844
 
 
1845
    $self->throw("I can't handle format $format");
1797
1846
 
1798
1847
}
1799
1848