File Coverage

blib/lib/TIGR/FASTA/Iterator.pm
Criterion Covered Total %
statement 19 217 8.7
branch 0 104 0.0
condition 0 66 0.0
subroutine 7 17 41.1
pod 6 6 100.0
total 32 410 7.8


line stmt bran cond sub pod time code
1             # $Id: FASTAiterator.pm,v 1.1 2004/04/28 15:03:43 aphillip Exp $
2              
3             package TIGR::FASTA::Iterator;
4             {
5              
6             =head1 NAME
7              
8             TIGR::FASTA::Iterator - TIGR::FASTA::Iterator class for parsing and navigating
9             FASTA format files and streams. An object of this class can parse FASTA
10             records from STDIN and from a pipe.
11              
12             =head1 SYNOPSIS
13              
14             use TIGR::FASTA::Iterator;
15             my $obj_instance = new TIGR::FASTA::Iterator ($foundation_obj_ref,
16             $error_array_ref,
17             $fasta_file_name);
18              
19             =head1 DESCRIPTION
20              
21             This module iterates over a FASTA formatted file stream. It provides
22             data extraction and simple analysis routines. This module utilizes
23             acceptance validation of FASTA formatted files via the TIGR::FASTA::Grammar
24             module.
25              
26             =cut
27              
28             BEGIN {
29 1     1   1816 require 5.006_00;
30             }
31              
32 1     1   5 use strict;
  1         2  
  1         24  
33 1     1   358 use IO::File;
  1         1700  
  1         93  
34 1     1   7 use TIGR::Foundation;
  1         2  
  1         65  
35 1     1   5 use TIGR::FASTA::Grammar ':public';
  1         2  
  1         135  
36 1     1   9 use TIGR::FASTA::Grammar ':private';
  1         2  
  1         122  
37 1     1   7 use TIGR::FASTA::Record;
  1         1  
  1         2041  
38              
39              
40             ## internal variables and identifiers
41              
42             our $REVISION = (qw$Revision: 1.1 $)[-1];
43             our $VERSION = '1.11';
44             our $VERSION_STRING = "$VERSION (Build $REVISION)";
45             our @DEPEND =
46             (
47             "TIGR::Foundation",
48             "TIGR::FASTA::Grammar",
49             "TIGR::FASTA::Record",
50             );
51              
52             my $SYS_ERR = 0; # this flag specifies non-user related error
53             my $USR_ERR = 1; # this flag specifies user related error
54              
55             ## external variables
56              
57             my $UNBOUND_FASTA_SEPARATOR = $TIGR::FASTA::Grammar::UNBOUND_FASTA_SEPARATOR;
58            
59             # debugging scheme
60             #
61             # Debugging via the TIGR Foundation uses increasing log levels based on
62             # nesting. 'MAIN' starts at level 1. Every nest increments the level by
63             # 1.
64             # Subroutines always start nesting at level 2. As debugging levels
65             # increase, logging is more verbose. This makes sense as you log at
66             # greater depth (ie. deeper branching).
67             #
68             # The following definitions help emphasize the debugging in the program.
69             #
70             my $DEBUG_LEVEL_1 = 1;
71             my $DEBUG_LEVEL_2 = 2;
72             my $DEBUG_LEVEL_3 = 3;
73             my $DEBUG_LEVEL_4 = 4;
74             my $DEBUG_LEVEL_5 = 5;
75             my $DEBUG_LEVEL_6 = 6;
76             my $DEBUG_LEVEL_7 = 7;
77             my $DEBUG_LEVEL_8 = 8;
78             my $DEBUG_LEVEL_9 = 9;
79              
80             ## prototypes
81              
82             sub new(;$$$);
83             sub open($);
84             sub close();
85             sub hasNext();
86             sub next();
87             sub get();
88             sub _initialize();
89             sub _parse();
90             sub _nullRecordHandler($);
91             sub _errorHandler($$$);
92              
93              
94             ## implementation
95              
96             =over
97              
98             =item $obj_instance = new TIGR::FASTA::Iterator ($foundation_object,
99             $error_array_ref, $db_file);
100              
101             This method returns a new instance of a TIGR::FASTA::Iterator object. It takes
102             three optional parameters: a TIGR::Foundation object (C<$foundation_object>),
103             a reference to an array for logging user error messages (C<$error_array_ref>),
104             and a FASTA file (C<$db_file>) or stream. The filename "-" describes stdin.
105             The new instance is returned on success. If the file supplied cannot be
106             opened or is invalid, this method returns undefined. This method also returns
107             undefined if the parameters supplied are invalid. Errors in parsing are written
108             to the array C<$error_array_ref>, the error file and the log file.
109              
110             =cut
111              
112              
113             sub new(;$$$) {
114 0     0 1   my $pkg = shift;
115 0           my @method_args = @_;
116              
117 0           my $error_condition = 0;
118 0           my $self = {};
119 0           bless $self, $pkg;
120 0           $self->_initialize(); # set up internal variables;
121              
122 0 0 0       if ( ( scalar (@method_args) > 0 ) &&
123             ( ( ref ($method_args[0]) ) =~ /foundation/i ) ) {
124 0           $self->{foundation} = shift @method_args;
125 0           $self->_errorHandler("Got TIGR::Foundation in new()", $DEBUG_LEVEL_3,
126             $SYS_ERR);
127             }
128             else {
129 0           $self->{foundation} = undef;
130 0           $self->_errorHandler("No TIGR::Foundation in new()", $DEBUG_LEVEL_3,
131             $SYS_ERR);
132             }
133              
134 0 0 0       if ( ( scalar (@method_args) > 0 ) &&
135             ( ( ref ($method_args[0]) ) =~ /array/i ) ) {
136 0           $self->{error_ref} = shift @method_args;
137 0           $self->_errorHandler("Got Error ARRAY in new()", $DEBUG_LEVEL_3,
138             $SYS_ERR);
139             }
140             else {
141 0           $self->{error_ref} = undef;
142 0           $self->_errorHandler("No Error ARRAY in new()", $DEBUG_LEVEL_3,
143             $SYS_ERR);
144             }
145              
146 0 0 0       if ( ( scalar (@method_args) > 0 ) &&
147             ( ! ref ($method_args[0]) ) ) {
148 0           my $filename = shift @method_args;
149 0 0         if(defined($filename)) {
150 0           $self->{db_file_name} = $filename ;
151 0           $self->_errorHandler("Got file name in new()", $DEBUG_LEVEL_4,
152             $SYS_ERR);
153             }
154             else {
155 0           $self->_errorHandler("undef passed as filename", $DEBUG_LEVEL_4,
156             $USR_ERR);
157             }
158             }
159             else {
160 0           $self->{db_file_name} = undef;
161 0           $self->_errorHandler("No file name in new()", $DEBUG_LEVEL_3,
162             $SYS_ERR);
163             }
164              
165             # check for invocation errors
166 0 0 0       if ( ( scalar (@method_args) > 0 ) ) {
    0          
167 0           $error_condition = 1;
168 0           $self->_errorHandler("Too many parameters passed to new() method",
169             $DEBUG_LEVEL_3, $SYS_ERR);
170             }
171             elsif ( defined ( $self->{db_file_name} ) &&
172             ! defined ( $self->open($self->{db_file_name}) ) ) {
173             # the error message is logged via the open() routine
174 0           $self = undef;
175             }
176 0 0         return ( $error_condition == 0 ) ? $self : undef;
177             }
178              
179              
180             =item $result = $obj_instance->open($file_name);
181              
182             This method opens a FASTA file or pipe for reading. It takes in the filename to
183             be opened. If the file name is "-" the input is taken from stdin. On success,
184             this method returns 1. If the file cannot be opened or parsing fails, this
185             method returns undefined.
186              
187             =cut
188              
189              
190             sub open($) {
191 0     0 1   my $self = shift;
192 0           my $db_file_name = shift;
193            
194 0           my $error_condition = 0;
195              
196             # close a previously open file
197 0 0         if ( defined ($self->{db_handle}) ) {
198 0           $self->_errorHandler("Closing old handle in open()", $DEBUG_LEVEL_3,
199             $SYS_ERR);
200 0           $self->close();
201             }
202 0           my $name = $self->{db_file_name};
203            
204 0 0 0       if (!(
    0          
205             ( defined ( $db_file_name ) ) &&
206             ( $self->{db_file_name} = $db_file_name ) &&
207             ( defined ( $self->{db_file_name} ))
208             ) ) {
209            
210 0           $error_condition = 1;
211 0           $self->_errorHandler(
212             "File name does not exist", $DEBUG_LEVEL_3, $USR_ERR);
213             }
214             elsif(!defined ( $self->{db_handle} =
215             new IO::File $self->{db_file_name})) {
216 0           $error_condition = 1;
217 0           $self->_errorHandler(
218             "Cannot open file \'$self->{db_file_name}\'", $DEBUG_LEVEL_3,
219             $USR_ERR);
220             }
221            
222            
223 0 0         if ( $error_condition == 1 ) {
224 0           $self->_initialize(); # reset object state
225             }
226            
227 0 0         return ($error_condition == 1) ? undef : 1;
228             }
229              
230              
231             =item $result = $obj_instance->close();
232              
233             This method closes the object file stream and resets all internal data
234             structures. The result of the operation is returned. If the file stream
235             is closed successfully, this object returns true (1), otherwise false
236             (undefined).
237              
238             =cut
239              
240              
241             sub close() {
242 0     0 1   my $self = shift;
243 0           my $return_val = undef;
244              
245 0 0         if ( defined ( $self->{db_handle} ) ) {
246 0           $return_val = $self->{db_handle}->close();
247 0 0         if (!$return_val) {
248 0           $return_val = undef;
249 0           $self->_errorHandler(
250             "Error closing FASTA file: $self->{db_file_name}",
251             $DEBUG_LEVEL_4, $USR_ERR);
252             }
253             }
254 0           $self->_initialize();
255 0           return $return_val;
256             }
257            
258              
259             =item $result = $obj_instance->hasNext();
260              
261             This method returns true (1) if there are more elements beyond the current
262             element in the filestream. If not, this method returns false (undefined).
263              
264             =cut
265              
266             sub hasNext() {
267 0     0 1   my $self = shift;
268 0           my $next_header = $self->{rec_header};
269 0           $self->_errorHandler(
270             "Checking to see if the header of the next record is set",
271             $DEBUG_LEVEL_2, $SYS_ERR);
272 0           my $result = undef;
273 0           my $newline = undef;
274 0           my $line_number = $self->{line_number};
275 0 0         if ($line_number == 0) {
276 0           $self->_errorHandler(
277             "No record has been parsed",
278             $DEBUG_LEVEL_3, $SYS_ERR);
279             my $db_handle = defined ( $self->{db_handle} ) ?
280 0 0         $self->{db_handle} : undef;
281            
282 0 0         if(defined $db_handle) {
283 0           $newline = <$db_handle>;
284             }
285             #reading the first line from a file.
286 0 0         if(defined($newline)) {
287 0           $line_number++;
288 0           $self->{line_number} = $line_number;
289 0           $next_header = $newline;
290 0           $self->_errorHandler(
291             "Assigned the header of the next record",
292             $DEBUG_LEVEL_4, $SYS_ERR);
293 0           $self->{rec_header} = $next_header;
294 0           $result = 1;
295             }
296             }
297            
298 0 0 0       if((defined ($next_header)) && (($next_header) ne "")) {
299 0           $result = 1;
300             }
301 0           return $result;
302             }
303              
304              
305             =item $result = $obj_instance->next();
306              
307             This method selects the next record in the file stream for parsing. If the
308             record parses, it is returned, else the method returns undefined. If there is
309             no record in the file stream, the method returns undefined.
310              
311             =cut
312              
313             sub next() {
314 0     0 1   my $self = shift;
315 0           my $record = undef;
316 0 0         if(($self->_parse()) == 1) {
317 0           $self->_errorHandler(
318             "The record parsed",
319             $DEBUG_LEVEL_3, $SYS_ERR);
320             #obtaining the stored record.
321 0           my $recordarray_ref = $self->{recordinfo};
322            
323 0 0 0       if( (defined $recordarray_ref) &&
324             (( ref ($recordarray_ref) ) =~ /array/i) ) {
325            
326 0           my @recordarray = @$recordarray_ref;
327 0           my $array_length = 0;
328              
329 0 0 0       if((defined $recordarray_ref) &&
      0        
330             ($array_length = @recordarray) &&
331             ($array_length > 0)) {
332            
333 0           my $header = shift @recordarray;
334 0           $self->_errorHandler(
335             "Got the record header",
336             $DEBUG_LEVEL_5, $SYS_ERR);
337 0           my $data = undef;
338 0 0         if ( scalar(@recordarray) > 0 ) {
339 0           $data = join "", @recordarray;
340 0           $data =~ s/\n//g; # extract new lines from scalar data
341             }
342             $self->_errorHandler(
343 0           "Got the record data",
344             $DEBUG_LEVEL_5, $SYS_ERR);
345 0           $record = new TIGR::FASTA::Record ($header, $data);
346            
347 0 0         if(defined($record)) {
348 0           $self->_errorHandler(
349             "Created new record",
350             $DEBUG_LEVEL_6, $SYS_ERR);
351             }
352             }
353             }
354             }
355 0           return $record;
356             }
357              
358              
359             =item $record_contents = $obj_instance->get();
360              
361             This method returns the current TIGR::FASTA::Record object (active record). If
362             the current object (active record) is undefined, this method returns undefined.
363              
364             =cut
365            
366             sub get() {
367 0     0 1   my $self = shift;
368 0           my $record = undef;
369             #obtaining the stored record information.
370 0           my $recordarray_ref = $self->{recordinfo};
371 0 0 0       if( (defined $recordarray_ref) &&
372             (( ref ($recordarray_ref) ) =~ /array/i) ) {
373 0           my @recordarray = @$recordarray_ref;
374 0           my $array_length = 0;
375              
376 0 0 0       if((defined $recordarray_ref) &&
      0        
377             ($array_length = @recordarray) &&
378             ($array_length > 0)) {
379            
380 0           my $header = shift @recordarray;
381 0           $self->_errorHandler(
382             "Got the record header",
383             $DEBUG_LEVEL_4, $SYS_ERR);
384 0           my $data = undef;
385 0 0         if ( scalar(@recordarray) > 0 ) {
386 0           $data = join "", @recordarray;
387 0           $data =~ s/\n//g; # extract new lines from scalar data
388             }
389             $self->_errorHandler(
390 0           "Got the record data",
391             $DEBUG_LEVEL_4, $SYS_ERR);
392 0           $record = new TIGR::FASTA::Record ($header, $data);
393 0 0         if(defined($record)) {
394 0           $self->_errorHandler(
395             "Created new record",
396             $DEBUG_LEVEL_5, $SYS_ERR);
397             }
398            
399             }
400             }
401 0           return $record;
402             }
403              
404              
405             # $obj_instance->_initialize();
406              
407             #This method resets the object to its initial state. Internal data structures
408             #are reset. This method does not return.
409              
410              
411             sub _initialize() {
412 0     0     my $self = shift;
413             # look up methods for records here
414 0           $self->{error_cnt} = 0; # parse error tabulator
415 0           $self->{db_file_name} = "";
416 0           $self->{db_handle} = undef;
417 0           $self->{rec_header} = undef; # the next record header
418 0           $self->{recordinfo} = undef; # reference to the record contents
419 0           $self->{line_number} = 0; # the line number in the FASTA file.
420             }
421              
422             # $obj_instance->_parse();
423              
424             #This method parses a FASTA record from the file stream.
425             #All the parsing errors for this record are recorded in
426             #the logfile. If the record parses correctly, the method returns 1, else it
427             #returns 0.
428            
429            
430             sub _parse() {
431            
432 0     0     my $self = shift;
433 0           my $last_line_length_lt_std_flag = 0;
434 0           my $record_identifier = "";
435 0           my $preceding_header_flag = 0;
436 0           my $first_data_line_length = 0;
437 0           my @recarray;
438 0           my $preceding_record_flag = 0;
439              
440 0           my $line_number = $self->{line_number};
441            
442 0           $self->{error_cnt} = 0;
443             my $db_handle = defined ( $self->{db_handle} ) ?
444 0 0         $self->{db_handle} : undef;
445            
446             # check for FASTA header of next record
447 0           my $header = $self->{rec_header};
448            
449             #when in the beginning and end of the filestream.
450 0 0         if(!defined ($header)) {
451 0           my $newline = <$db_handle>;
452 0 0 0       if((defined($newline)) && ($newline ne "")) {
453 0           $line_number++;
454 0           $header = $newline;
455             }
456             }
457             #parsing the header
458 0 0         if ( ( isValidFASTAheader($header) ) != 0 ) {
459             # set up the variables for parsing a new record
460 0           $last_line_length_lt_std_flag = 0;
461 0           $preceding_header_flag = 1;
462 0           $preceding_record_flag = 1;
463 0           $self->{rec_header} = undef;
464              
465             # if it's a valid FASTA header, then don't need to check again
466             # extract the record IDENTIFIER
467 0           $record_identifier = _headerToIdentifier($header);
468 0           push @recarray,$header;
469             }
470             else { #the header is not valid.
471 0 0 0       if((defined $header) && (defined $line_number)) {
472 0           $self->_errorHandler("Expected: record header " .
473             "information in FASTA record header. Got: \'$header\' ".
474             "at line $line_number.", $DEBUG_LEVEL_3, $USR_ERR);
475             }
476 0           $preceding_record_flag = 1;
477 0           $self->{rec_header} = undef;
478             }
479            
480 0   0       while ( ( defined ( $db_handle ) ) &&
      0        
481             ( defined ( my $line = <$db_handle> )) &&
482             (++$line_number)) {
483 0           chomp $line;
484            
485             # check FASTA data
486 0 0 0       if ( ( defined ( $record_identifier ) ) &&
    0 0        
487             ( $record_identifier !~ // ) &&
488             ( ( isValidFASTAdata($line) ) != 0 ) ) {
489            
490 0           push @recarray,$line;
491 0 0         if($preceding_header_flag == 1) {
492 0           $first_data_line_length = setValidFASTAlineLength($line);
493             }
494            
495             # check $last_line_length_lt_std_flag for an error on
496             # previous line
497 0 0         if(defined ($first_data_line_length)) {
498 0 0         if ( $last_line_length_lt_std_flag == 1 ) {
499 0           $self->{error_cnt}++;
500 0           $self->_errorHandler("Expected: FASTA data ".
501             "definition lines should be ".
502             "$first_data_line_length bases (characters) ".
503             "across. Only the last line of a sequence ".
504             "data definition may be less than " .
505             "$first_data_line_length bases (characters) " .
506             "across, if applicable. See line " .
507             ($line_number - 1) . '.', $DEBUG_LEVEL_6, $USR_ERR);
508             }
509 0           $last_line_length_lt_std_flag = 0;
510            
511             # check current line for over-length problem
512 0 0         if ( length($line) > $first_data_line_length ) {
    0          
513 0           $self->{error_cnt}++;
514 0           $self->_errorHandler("Expected: FASTA data ".
515             "definition lines should be $first_data_line_length ".
516             "bases (characters) across. Only the last line of a ".
517             "sequence data definition may be less than " .
518             "$first_data_line_length bases (characters) ".
519             "across, if applicable. See line " . $line_number .
520             '.',
521             $DEBUG_LEVEL_6,$USR_ERR);
522             }
523            
524             #check current line for under-length problem;
525             #report only if not
526             #the last line in the data definition
527             elsif ( length($line) < $first_data_line_length ) {
528 0           $last_line_length_lt_std_flag = 1;
529             }
530             }
531 0           $preceding_header_flag = 0;
532             }
533             elsif($line =~ /^>/) { #the next header
534 0 0         if ($preceding_record_flag == 1) { #its the next record.
535 0           $self->{rec_header} = $line;
536 0           $self->_errorHandler(
537             "Assigned the header of the next record",
538             $DEBUG_LEVEL_5, $SYS_ERR);
539 0           last;
540             }
541             }
542             # handle data error types
543             else {
544 0           $self->{error_cnt}++;
545              
546             # line has a separator token in it, so it may be header
547 0 0 0       if ( $line =~ /$UNBOUND_FASTA_SEPARATOR/ ) {
    0          
    0          
548 0           $self->_errorHandler("Expected: record header " .
549             "information in FASTA record header. Got: \'$line\' ".
550             "at line $line_number.", $DEBUG_LEVEL_6, $USR_ERR);
551 0           $last_line_length_lt_std_flag = 0;
552             }
553             # if last data line was small, expect this to be a header too
554             elsif ( $last_line_length_lt_std_flag == 1 ) {
555 0           $self->_errorHandler("Expected: FASTA record header " .
556             "beginning with \'>\'. Got: \'$line\' at line ".
557             "$line_number.",$DEBUG_LEVEL_6, $USR_ERR);
558 0           $last_line_length_lt_std_flag = 0;
559             }
560             elsif ( ( defined ( $record_identifier ) ) &&
561             ( $record_identifier !~ // ) ) {
562 0           $self->_errorHandler("Expected: valid FASTA data " .
563             "definition for record identifier ".
564             "\'$record_identifier\' Check sequence content at line ".
565             "$line_number for invalid bases ".
566             "(data type: invalid data).", $DEBUG_LEVEL_6, $USR_ERR);
567             }
568             else {
569 0           $self->_errorHandler("Expected: FASTA record header " .
570             "followed by definition of sequence. Invalid input at " .
571             "line $line_number.", $DEBUG_LEVEL_6, $USR_ERR);
572             }
573             }
574             } # end while
575              
576             # check terminal case data definition
577 0 0         if ( $preceding_header_flag == 1 ) {
578 0           $self->_nullRecordHandler($line_number);
579             }
580 0           $self->{recordinfo} = \@recarray;
581 0           $self->{line_number} = $line_number;
582 0 0         return ( $self->{error_cnt} == 0 ) ? 1 : 0;
583             }
584              
585              
586             # $obj_instance->_nullRecordHandler($);
587              
588             #This method handles the case of a null or equivalently empty record
589             #encountered during parsing. It logs the appropriate message to the
590             #TIGR Foundation object. The only argument is the line number.
591              
592              
593             sub _nullRecordHandler($) {
594 0     0     my $self = shift;
595 0           my $line_number = shift;
596            
597 0 0         if ( ! defined ($line_number) ) {
598 0           $line_number = "";
599             }
600              
601 0           $self->{error_cnt}++;
602 0 0         if ( $self->{db_handle}->eof() == 1 ) {
603 0           $self->_errorHandler("Expected: FASTA record header " .
604             "followed by definition of sequence. " .
605             "Got end of file after line " .
606             ($line_number) . ".", $DEBUG_LEVEL_5, $USR_ERR);
607             }
608             else {
609 0           $self->_errorHandler("Expected: FASTA record header " .
610             "followed by definition of sequence " .
611             "Got FASTA header at line " .
612             ($line_number-1) . ".", $DEBUG_LEVEL_5, $USR_ERR);
613             }
614             }
615              
616              
617              
618             # $message = $obj_instance->_errorHandler($message, $tf_level,
619             # $internal_log_flag);
620              
621             #This method handles logging to the TIGR::Foundation module and
622             #internal error record reference array. The C<$message> argument is logged
623             #to the appropriate service. The C<$tf_level> parameter specifies the
624             #logging level for TIGR::Foundation, while the C<$internal_log_flag> parameter
625             #specifies if C<$message> should be written to the internal array reference
626             #specified in C. If a TIGR::Foundation instance does not exist,
627             #no logging to that facility occurs. This method returns C<$message>.
628              
629              
630             sub _errorHandler($$$) {
631            
632 0     0     my $self = shift;
633              
634 0           my ( $message, $tf_level, $log_facility ) = @_;
635              
636 0 0 0       if ( defined ($message) &&
      0        
637             defined ($tf_level) &&
638             defined ($log_facility) ) {
639              
640 0 0         if ( defined ($self->{foundation}) ) {
641 0 0         if ( $log_facility != $USR_ERR ) { # all user errors go to .error
642 0           $self->{foundation}->logLocal($message, $tf_level);
643             }
644             else {
645 0           $self->{foundation}->logError($message);
646             }
647             }
648            
649 0 0 0       if ( ( defined ($self->{error_ref}) ) &&
650             ( $log_facility == $USR_ERR ) ) {
651 0           push @{$self->{error_ref}}, $message;
  0            
652             }
653             }
654 0           return $message;
655             }
656              
657             =head1 USAGE
658              
659             To use this module, load the C package via the
660             C function. Then, create a new instance of the object via the
661             C method, as shown below. There are several invocations possible
662             for this method since all parameters to C are optional.
663              
664             To access records from the C instance, the
665             C package must be loaded via the C function.
666              
667             An example script using this module follows. The C
668             module is included for completeness but does not have to be used.
669              
670             #!/usr/local/bin/perl -w
671              
672             # This script accepts FASTA files with the '-i' option
673             # on the command line and validates every record in the file.
674             # Parse errors for each record are collected to the
675             # '@errors_list' array and written to the .error file.
676             # This program concatenates all of the correct records together to
677             # one output file specified with the '-o' option.
678             # NOTE: The '-i' option must be specified before every input file.
679            
680              
681             use strict;
682             use TIGR::FASTA::Iterator;
683             use TIGR::FASTA::Record;
684              
685             MAIN:
686             {
687             my $tf_object = new TIGR::Foundation;
688             my @errors_list = ();
689             my @input_files = ();
690             my $output_file = undef;
691              
692             # Capture the return code from the TIGR::Foundation method
693             my $result = $tf_object->TIGR_GetOptions('i=s' => \@input_files,
694             'o=s' => \$output_file);
695             if ( $result != 1 ) {
696             $tf_object->bail("Invalid command line options.");
697             }
698              
699             # Create a TIGR::FASTA::Iterator instance using TIGR::Foundation and
700             # an error message list.
701             my $fasta_iterator = new TIGR::FASTA::Iterator $tf_object, \@errors_list;
702              
703             if ( !( defined ( $output_file ) &&
704             open OUTFILE, ">$output_file" ) ) {
705             $tf_object->bail("Cannot open output file for writing.");
706             }
707              
708             foreach my $in_file ( @input_files ) {
709             $fasta_iterator->open($in_file) or
710             $tf_object->logLocal("Cannot open or read file $in_file", 2);
711              
712             if ( scalar(@errors_list) > 0 ) { # are there parse errors?
713             while ( @errors_list ) { # get the messages from the list
714             my $message = shift @errors_list;
715             print STDERR $message, "\n";
716             }
717             }
718             #
719             while ( $fasta_iterator->hasNext() ) {
720             # print each record to OUTFILE
721             my $record = $fasta_iterator->next();
722              
723             # print each record to OUTFILE
724             if(defined $record) {
725             print OUTFILE $record->toString();
726             }
727             }
728             }
729             }
730              
731             =cut
732              
733             }
734              
735             1;