File Coverage

blib/lib/GenOO/Data/File/FASTA.pm
Criterion Covered Total %
statement 45 48 93.7
branch 16 20 80.0
condition 2 3 66.6
subroutine 11 11 100.0
pod 0 1 0.0
total 74 83 89.1


line stmt bran cond sub pod time code
1             # POD documentation - main docs before the code
2              
3             =head1 NAME
4              
5             GenOO::Data::File::FASTA - Object implementing methods for accessing fasta formatted files (http://genome.ucsc.edu/FAQ/FAQformat#format1)
6              
7             =head1 SYNOPSIS
8              
9             # Object that manages a fasta file.
10              
11             # To initialize
12             my $fasta_parser = GenOO::Data::File::FASTA->new(
13             file => undef,
14             );
15              
16             =head1 DESCRIPTION
17              
18             This object offers methods to read a fasta file line by line.
19              
20             =head1 EXAMPLES
21              
22             # Create object
23             my $fasta_parser = GenOO::Data::File::FASTA->new(
24             file => 't/sample_data/sample.fasta.gz'
25             );
26              
27             # Read one record at a time
28             my $record = $fasta_parser->next_record;
29              
30             # Get the number of records read
31             my $count = $fasta_parser->records_read_count;
32              
33             =cut
34              
35             # Let the code begin...
36              
37             package GenOO::Data::File::FASTA;
38             $GenOO::Data::File::FASTA::VERSION = '1.5.1';
39              
40             #######################################################################
41             ####################### Load External modules #####################
42             #######################################################################
43 1     1   4001 use Modern::Perl;
  1         2  
  1         12  
44 1     1   161 use autodie;
  1         3  
  1         11  
45 1     1   3058 use Moose;
  1         1  
  1         12  
46 1     1   5525 use namespace::autoclean;
  1         1  
  1         14  
47              
48              
49             #######################################################################
50             ######################### Load GenOO modules ######################
51             #######################################################################
52 1     1   507 use GenOO::Data::File::FASTA::Record;
  1         2  
  1         601  
53              
54              
55             #######################################################################
56             ####################### Interface attributes ######################
57             #######################################################################
58             has 'file' => (
59             isa => 'Maybe[Str]',
60             is => 'rw',
61             required => 1
62             );
63              
64             has 'records_read_count' => (
65             is => 'rw',
66             default => 0,
67             init_arg => undef,
68             );
69              
70             has '_filehandle' => (
71             is => 'ro',
72             builder => '_open_filehandle',
73             init_arg => undef,
74             lazy => 1,
75             );
76              
77             has '_stored_record_header' => (
78             is => 'rw',
79             clearer => '_clear_stored_record_header',
80             predicate => '_has_stored_record_header',
81             init_arg => undef,
82             );
83              
84             has '_stored_record_sequence_parts' => (
85             traits => ['Array'],
86             is => 'rw',
87             isa => 'ArrayRef[Str]',
88             default => sub { [] },
89             handles => {
90             _all_record_sequence_parts => 'elements',
91             _add_record_sequence_part => 'push',
92             _join_record_sequence_parts => 'join',
93             _clear_record_sequence_parts => 'clear',
94             },
95             );
96              
97             has '_eof' => (
98             is => 'rw',
99             predicate => '_reached_eof',
100             init_arg => undef
101             );
102              
103              
104             #######################################################################
105             ######################## Interface Methods ########################
106             #######################################################################
107             sub next_record {
108 24     24 0 1187 my ($self) = @_;
109              
110 24 100       889 return undef if ($self->_reached_eof);
111              
112 22         687 while (my $line = $self->_filehandle->getline) {
113 78         2937 chomp $line;
114 78 100       149 if (_line_looks_like_record_header($line)) {
    100          
115 23 100       889 if ($self->_has_stored_record_header) {
116 20         51 my $record = $self->_create_record;
117 20         609 $self->_stored_record_header($line);
118 20         227 return $record;
119             }
120             else {
121 3         82 $self->_stored_record_header($line);
122             }
123             }
124             elsif (_line_looks_like_sequence($line)) {
125 44         2009 $self->_add_record_sequence_part($line);
126             }
127             }
128 2         95 $self->_eof(1);
129 2 50       69 if ($self->_has_stored_record_header) {
130 2         6 return $self->_create_record;
131             }
132 0         0 return undef;
133             }
134              
135             #######################################################################
136             ######################### Private methods ##########################
137             #######################################################################
138             sub _open_filehandle {
139 3     3   7 my ($self) = @_;
140              
141 3         8 my $read_mode;
142             my $HANDLE;
143 3 50       126 if (!defined $self->file) {
    50          
144 0         0 open ($HANDLE, '<-', $self->file);
145             }
146             elsif ($self->file =~ /\.gz$/) {
147 3 50       95 die 'Cannot open file ' . $self->file . "\n" if ! -e $self->file;
148 3         128 open($HANDLE, 'gzip -dc ' . $self->file . ' |');
149             }
150             else {
151 0         0 open ($HANDLE, '<', $self->file);
152             }
153              
154 3         22975 return $HANDLE;
155             }
156              
157             sub _increment_records_read_count {
158 22     22   28 my ($self) = @_;
159 22         737 $self->records_read_count($self->records_read_count+1);
160             }
161              
162             sub _create_record {
163 22     22   39 my ($self) = @_;
164              
165 22         724 my $record = GenOO::Data::File::FASTA::Record->new(
166             header => $self->_stored_record_header,
167             sequence => $self->_join_record_sequence_parts(''),
168             );
169 22         925 $self->_clear_stored_record_header;
170 22         955 $self->_clear_record_sequence_parts;
171 22         59 $self->_increment_records_read_count;
172              
173 22         36 return $record;
174             }
175              
176              
177             #######################################################################
178             ####################### Private subroutines ########################
179             #######################################################################
180             sub _line_looks_like_record_header {
181 133 100   133   1180 return ($_[0] =~ /^>/) ? 1 : 0;
182             }
183              
184             sub _line_looks_like_sequence {
185 55 100 66 55   89 return ((!_line_looks_like_record_header($_[0])) and ($_[0] =~ /\S/)) ? 1 : 0;
186             }
187              
188              
189             #######################################################################
190             ############################ Finalize #############################
191             #######################################################################
192             __PACKAGE__->meta->make_immutable;
193              
194             1;