File Coverage

blib/lib/Bio/Gonzales/Seq/IO.pm
Criterion Covered Total %
statement 46 102 45.1
branch 8 48 16.6
condition n/a
subroutine 11 16 68.7
pod 5 6 83.3
total 70 172 40.7


line stmt bran cond sub pod time code
1             package Bio::Gonzales::Seq::IO;
2              
3 8     8   356418 use warnings;
  8         48  
  8         322  
4 8     8   47 use strict;
  8         22  
  8         204  
5 8     8   42 use Carp qw/cluck confess croak carp/;
  8         16  
  8         557  
6              
7 8     8   3680 use Bio::Gonzales::Seq::IO::Fasta;
  8         24  
  8         335  
8              
9 8     8   62 use Data::Dumper;
  8         27  
  8         458  
10 8     8   54 use Bio::Gonzales::Util::File qw/open_on_demand/;
  8         17  
  8         424  
11 8     8   1452 use Bio::Gonzales::Util qw/flatten/;
  8         19  
  8         833  
12 8     8   59 use Bio::Gonzales::Seq;
  8         25  
  8         233  
13              
14 8     8   48 use base 'Exporter';
  8         14  
  8         9622  
15             our ( @EXPORT, @EXPORT_OK, %EXPORT_TAGS );
16             our $VERSION = '0.083'; # VERSION
17              
18             @EXPORT = qw(faslurp faspew fasubseq faiterate);
19             %EXPORT_TAGS = ();
20             @EXPORT_OK = qw(fahash);
21              
22             our $WIDTH = $Bio::Gonzales::Seq::WIDTH;
23              
24             our $SEQ_FORMAT = 'all';
25              
26             sub faslurp {
27 5     5 1 23400 my ($src) = @_;
28              
29 5         13 my @fa;
30              
31 5         35 my ( $fh, $fh_was_open ) = open_on_demand( $src, '<' );
32              
33 5         111 my $fasta = Bio::Gonzales::Seq::IO::Fasta->new($fh);
34 5         26 while ( my $entry = $fasta->next_seq ) {
35 55 50       134 confess unless ($entry);
36 55         242 push @fa, $entry;
37             }
38              
39 5 50       39 $fh->close unless ($fh_was_open);
40              
41 5 100       110 return wantarray ? @fa : \@fa;
42             }
43              
44             sub fasubseq {
45 0     0 1 0 my ( $src, $ids_with_ranges, $c ) = @_;
46              
47 0         0 my $ids;
48 0 0       0 if ( ref $ids_with_ranges eq 'ARRAY' ) {
49 0 0       0 return unless (@$ids_with_ranges);
50              
51 0 0       0 if ( ref $ids_with_ranges->[0] eq 'ARRAY' ) {
52             #array of array with id and range
53 0         0 $ids = {};
54              
55 0         0 for my $idrange (@$ids_with_ranges) {
56 0         0 my ( $id, @range ) = @$idrange;
57 0 0       0 $ids->{$id} = [] unless defined $ids->{$id};
58 0         0 push @{ $ids->{$id} }, \@range;
  0         0  
59             }
60              
61             } else {
62             #just plain ids
63 0         0 $ids = { map { $_ => [] } @$ids_with_ranges };
  0         0  
64             }
65             }
66              
67 0         0 my ( $fh, $fh_was_open ) = open_on_demand( $src, '<' );
68              
69 0         0 my $fasta = Bio::Gonzales::Seq::IO::Fasta->new($fh);
70 0         0 my @fa;
71 0         0 while ( my $entry = $fasta->next_seq ) {
72 0 0       0 if ( exists( $ids->{ $entry->id } ) ) {
73 0         0 my $ranges = $ids->{ $entry->id };
74 0         0 for my $range (@$ranges) {
75              
76 0         0 eval { push @fa, $entry->subseq( $range, $c ) };
  0         0  
77 0 0       0 if ($@) {
78 0         0 carp Dumper $entry->clone_empty;
79 0         0 croak $@;
80             }
81             }
82              
83             #empty ranges array
84 0 0       0 push @fa, $entry unless (@$ranges);
85             }
86             }
87 0 0       0 $fh->close unless ($fh_was_open);
88              
89 0 0       0 return wantarray ? @fa : \@fa;
90             }
91              
92             sub fahash {
93 0     0 1 0 my $faraw = faslurp(@_);
94 0         0 my %fa;
95 0         0 for my $s (@$faraw) {
96 0 0       0 confess "Dupicate entry: " . $s->id if ( exists( $fa{ $s->id } ) );
97 0         0 $fa{ $s->id } = $s;
98             }
99 0 0       0 return wantarray ? %fa : \%fa;
100             }
101              
102             sub faiterate {
103 0     0 1 0 my @srcs = flatten(@_);
104              
105 0 0       0 confess "no arguments supplied" unless ( @srcs > 0 );
106 0         0 my ( $fh, $fh_was_open ) = open_on_demand( shift(@srcs), '<' );
107 0         0 my $fasta = Bio::Gonzales::Seq::IO::Fasta->new($fh);
108              
109             return sub {
110 0     0   0 my $entry = $fasta->next_seq;
111 0 0       0 unless ( defined($entry) ) {
112 0 0       0 $fh->close unless ($fh_was_open);
113              
114 0 0       0 if ( my $src = shift @srcs ) {
115 0         0 ( $fh, $fh_was_open ) = open_on_demand( $src, '<' );
116 0         0 $fasta = Bio::Gonzales::Seq::IO::Fasta->new($fh);
117             } else {
118 0         0 return;
119             }
120             }
121 0         0 return $entry;
122 0         0 };
123             }
124              
125             sub faspew {
126 1     1 1 7 my ( $dest, @data ) = @_;
127              
128             #open destination, if necessary
129 1         3 my ( $fh, $fh_was_open ) = open_on_demand( $dest, '>' );
130              
131 1 50       12 carp "no sequences supplied" unless ( @data > 0 );
132             # take appropriate steps for the sequence objects
133 1         4 for my $d (@data) {
134 1 50       8 if ( ref $d eq 'HASH' ) {
    50          
    0          
135 0         0 for my $e ( values %{$d} ) {
  0         0  
136 0         0 print $fh $e->$SEQ_FORMAT;
137             }
138             } elsif ( ref $d eq 'ARRAY' ) {
139 1         3 for my $e ( @{$d} ) {
  1         3  
140 1         6 print $fh $e->$SEQ_FORMAT;
141             }
142             } elsif ( ref($d) eq 'Bio::Gonzales::Seq' ) {
143 0         0 print $fh $d->$SEQ_FORMAT;
144             } else {
145 0 0       0 unless ($d) {
146 0         0 cluck "Undefined argument supplied";
147 0         0 next;
148             }
149 0         0 confess "error";
150             }
151             }
152             $fh->close
153 1 50       9 unless ($fh_was_open);
154 1         58 return;
155             }
156              
157              
158 0     0 0   sub format_seq_string {return Bio::Gonzales::Seq::Format_seq_string($_[0], $WIDTH); }
159              
160             1;
161             __END__
162              
163             =head1 NAME
164              
165             Bio::Gonzales::Seq::IO - fast utility functions for sequence IO
166              
167             =head1 SYNOPSIS
168              
169             use Bio::Gonzales::Seq::IO qw( faslurp faspew fahash fasubseq faiterate )
170              
171             =head1 DESCRIPTION
172              
173             =head1 SUBROUTINES
174              
175             =over 4
176              
177             =item B<< @seqs = faslurp(@filenames) >>
178              
179             =item B<< $seqsref = faslurp(@filenames) >>
180              
181             C<faslurp> reads in all sequences from C<@filenames> and returns an array in
182             list or an arrayref in scalar context of the read sequences. The sequences are
183             stored as FAlite2::Entry objects.
184              
185             =item B<< $iterator = faiterate($filename) >>
186              
187             Allows you to create an iterator for the fasta file C<$filename>. This
188             iterator can be used to loop over the sequence file w/o reading in all content
189             at once. Iterator usage:
190              
191             while(my $sequence_object = $iterator->()) {
192             #do something with the sequence object
193             }
194              
195              
196             =item B<< $seqs = fasubseq($file, \@ids_with_locations, \%c) >>
197              
198             =item B<< $seqs = fasubseq($file, \@id_list, \%c) >>
199              
200             #ARRAY OF ARRAYS
201             @ids_with_locations = (
202             [ $id, $begin, $end, $strand ],
203             ...
204             );
205              
206             Config options can be:
207              
208             %c = (
209             keep_id => 1, # keeps the original id of the sequence
210             wrap => 1, # see further down
211             relaxed_range => 1, # substitute 0 or undef for $begin with '^' and for $end with '$'
212             );
213              
214              
215             There are several possibilities for C<$begin> and C<$end>:
216              
217             GGCAAAGGA ATGATGGTGT GCAGGCTTGG CATGGGAGAC
218             ^..........^ (1,11) OR ('^', 11)
219             ^.....................................^ (4,'$')
220             ^..............^ (21,35) { with wrap on: OR (-19,35) OR (-19, -5) }
221             ^..................^ (21,35) { with wrap on: OR (-19,'$') }
222            
223             C<wrap>: The default is to limit all negative
224             values to the sequence boundaries, so a negative begin would be equal to 1 or
225             '^' and a negative end would be equal to '$'.
226              
227             =item B<< $sref = fahash(@filenames) >>
228              
229             =item B<< %seqs = fahash(@filenames) >>
230              
231             Does the same as L<faslurp>, but returns an hash with the sequence ids as keys
232             and the sequence objects as values.
233              
234             =item B<< faspew($file, $seq1, $seq2, ...) >>
235              
236             "spew" out the given sequences to a file. Every C<$seqN> argument can be an
237             hash reference with L<FAlite2::Entry> objects as values or an array reference
238             of L<FAlite2::Entry> objects or just plain L<FAlite2::Entry> objects.
239            
240             =item B<< $iterator = faspew_iterate($filename) >>
241              
242             =item B<< $iterator = faspew_iterate($fh) >>
243              
244             Creates an iterator that writes the sequences to the given C<$filename> or C<$fh>.
245              
246             for my $sequence_object (@sequences) {
247             $iterator->($sequence_object)
248             }
249             #DO NOT FORGET THIS, THIS CALL WILL CLOSE THE FILEHANDLE
250             $iterator->();
251              
252             #this is equal to:
253              
254             $iterator->(@sequences);
255             $iterator->();
256             #or
257             $iterator->(\@sequences);
258             $iterator->();
259              
260              
261             #DO NOT DO THIS:
262              
263             $iterator->();
264              
265             The filehandle will not be closed in case one supplies not a C<$filename> but a C<$fh> handle.
266              
267             =back
268              
269             =head1 ADVANCED
270              
271             =over 4
272              
273             =item B<< change the output format >>
274              
275             $Bio::Gonzales::Seq::IO::WIDTH = 60; #sequence width in fasta output
276              
277             #but only if set to 'all_pretty' ('all' is default)
278             $Bio::Gonzales::Seq::IO::SEQ_FORMAT = 'all_pretty';
279              
280             =back
281              
282             =head1 SEE ALSO
283              
284             =head1 AUTHOR
285              
286             jw bargsten, C<< <joachim.bargsten at wur.nl> >>
287              
288             =cut