File Coverage

blib/lib/GenOO/GeneCollection/Factory/GTF.pm
Criterion Covered Total %
statement 83 94 88.3
branch 25 32 78.1
condition n/a
subroutine 10 10 100.0
pod 0 1 0.0
total 118 137 86.1


line stmt bran cond sub pod time code
1             # POD documentation - main docs before the code
2              
3             =head1 NAME
4              
5             GenOO::GeneCollection::Factory::GTF - Factory to create GeneCollection from a GTF file
6              
7             =head1 SYNOPSIS
8              
9             Creates GenOO::GeneCollection containing genes from a GTF file
10             Preferably use it through the generic GenOO::GeneCollection::Factory
11              
12             my $factory = GenOO::GeneCollection::Factory->new('GTF',{
13             file => 'sample.gtf'
14             });
15              
16             =head1 DESCRIPTION
17              
18             An instance of this class is a concrete factory for the creation of a
19             L<GenOO::GeneCollection> containing genes from a GTF file. It offers the method
20             "read_collection" (as the consumed role requires) which returns the actual
21             L<GenOO::GeneCollection> object in the form of
22             L<GenOO::RegionCollection::Type::DoubleHashArray>. The latter is the implementation
23             of the L<GenOO::RegionCollection> class based on the complex data structure
24             L<GenOO::Data::Structure::DoubleHashArray>.
25              
26             =head1 EXAMPLES
27              
28             # Create a concrete factory
29             my $factory_implementation = GenOO::GeneCollection::Factory->new('GTF',{
30             file => 'sample.gtf'
31             });
32            
33             # Return the actual GenOO::GeneCollection object
34             my $collection = $factory_implementation->read_collection;
35             print ref($collection) # GenOO::GeneCollection::Type::DoubleHashArray
36              
37             =cut
38              
39             # Let the code begin...
40              
41             package GenOO::GeneCollection::Factory::GTF;
42             $GenOO::GeneCollection::Factory::GTF::VERSION = '1.4.6';
43              
44             #######################################################################
45             ####################### Load External modules #####################
46             #######################################################################
47 1     1   2306 use Modern::Perl;
  1         2  
  1         10  
48 1     1   250 use autodie;
  1         2  
  1         12  
49 1     1   3784 use Moose;
  1         3  
  1         9  
50 1     1   6491 use namespace::autoclean;
  1         2  
  1         11  
51              
52              
53             #######################################################################
54             ####################### Load GenOO modules #####################
55             #######################################################################
56 1     1   88 use GenOO::RegionCollection::Factory;
  1         2  
  1         36  
57 1     1   4 use GenOO::Transcript;
  1         2  
  1         26  
58 1     1   6 use GenOO::Gene;
  1         1  
  1         19  
59 1     1   9 use GenOO::Data::File::GFF;
  1         3  
  1         1025  
60              
61              
62             #######################################################################
63             ####################### Interface attributes ######################
64             #######################################################################
65             has 'file' => (
66             isa => 'Str',
67             is => 'ro'
68             );
69              
70              
71             #######################################################################
72             ########################## Consumed Roles #########################
73             #######################################################################
74             with 'GenOO::RegionCollection::Factory::Requires';
75              
76              
77             #######################################################################
78             ######################## Interface Methods ########################
79             #######################################################################
80             sub read_collection {
81 6     6 0 12887 my ($self) = @_;
82            
83 6         204 my @genes = $self->_read_gtf($self->file);
84            
85 6         259 return GenOO::RegionCollection::Factory->create('RegionArray', {
86             array => \@genes
87             })->read_collection;
88             }
89              
90             #######################################################################
91             ######################### Private methods ##########################
92             #######################################################################
93             sub _read_gtf {
94 6     6   13 my ($self, $file)=@_;
95            
96 6         12 my %transcripts;
97             my %transcript_splice_starts;
98 0         0 my %transcript_splice_stops;
99 0         0 my %genes;
100            
101 6         193 my $gff = GenOO::Data::File::GFF->new(file => $file);
102            
103 6         50 while (my $record = $gff->next_record){
104              
105 5808 50       192073 my $transcript_id = $record->attribute('transcript_id') or die "transcript_id attribute must be defined\n";
106 5808 50       186697 my $gene_id = $record->attribute('gene_id') or die "gene_id attribute must be defined\n";
107            
108 5808 50       145565 if ($record->strand == 0){
109 0         0 warn "Skipping transcript $transcript_id: strand symbol". $record->strand_symbol." not accepted\n";
110 0         0 next;
111             }
112            
113             # Get transcript with id or create a new one. Update coordinates if required
114 5808         8551 my $transcript = $transcripts{$transcript_id};
115 5808 100       9944 if (not defined $transcript) {
116 348         9939 $transcript = GenOO::Transcript->new(
117             id => $transcript_id,
118             chromosome => $record->rname,
119             strand => $record->strand,
120             start => $record->start,
121             stop => $record->stop,
122             splice_starts => [$record->start], # will be re-written later
123             splice_stops => [$record->stop], # will be re-written later
124             );
125 348         1917 $transcripts{$transcript_id} = $transcript;
126 348         9232 my $uniq_gene_id = join("",($gene_id,$record->rname,$record->strand));
127 348 100       1239 if (!exists $genes{$uniq_gene_id}){
128 156         3877 my $gene = GenOO::Gene->new(name => $gene_id);
129 156         913 $genes{$uniq_gene_id}{'1'} = $gene;
130 156         4636 $transcript->gene($genes{$uniq_gene_id}{'1'});
131 156         620 $genes{$uniq_gene_id}{'1'}->add_transcript($transcript);
132 156         387 $transcript_splice_starts{$transcript_id} = [];
133 156         378 $transcript_splice_stops{$transcript_id} = [];
134             }
135             else{
136 192         366 my $found = 0;
137 192         375 my $i = 0;
138 192         321 foreach my $index (keys %{$genes{$uniq_gene_id}}){
  192         835  
139 192         335 $i = $index;
140 192         383 my $gene = $genes{$uniq_gene_id}{$index};
141 192 50       5233 if ($gene->contains_position($record->start,0)){
142 192         331 $found = 1;
143 192         4942 $transcript->gene($genes{$uniq_gene_id}{$index});
144 192         889 $genes{$uniq_gene_id}{$index}->add_transcript($transcript);
145 192         639 $transcript_splice_starts{$transcript_id} = [];
146 192         447 $transcript_splice_stops{$transcript_id} = [];
147 192         607 last;
148             }
149            
150             }
151 192 50       590 if ($found == 0){
152 0         0 my $index = $i+1;
153 0         0 my $gene = GenOO::Gene->new(name => $gene_id);
154 0         0 $genes{$uniq_gene_id}{$index} = $gene;
155 0         0 $transcript->gene($genes{$uniq_gene_id}{$index});
156 0         0 $genes{$uniq_gene_id}{$index}->add_transcript($transcript);
157 0         0 $transcript_splice_starts{$transcript_id} = [];
158 0         0 $transcript_splice_stops{$transcript_id} = [];
159             }
160             }
161            
162            
163             }
164             else {
165 5460 100       137832 if ($record->start < $transcript->start) {
166 180         4734 $transcript->start($record->start);
167             }
168 5460 100       134093 if ($record->stop > $transcript->stop) {
169 3342         79925 $transcript->stop($record->stop);
170             }
171             }
172            
173 5808 100       149415 if ($record->feature eq 'exon') {
    100          
    100          
174 2982         2557 push @{$transcript_splice_starts{$transcript_id}}, $record->start;
  2982         75515  
175 2982         2904 push @{$transcript_splice_stops{$transcript_id}}, $record->stop;
  2982         74112  
176             }
177             elsif ($record->feature eq 'start_codon') {
178 270 100       6834 if ($record->strand == 1) {
    50          
179 168         4364 $transcript->coding_start($record->start);
180             }
181             elsif ($record->strand == -1) {
182 102         2542 $transcript->coding_stop($record->stop);
183             }
184             }
185             elsif ($record->feature eq 'stop_codon') {
186 270 100       6722 if ($record->strand == 1) {
    50          
187 168         4421 $transcript->coding_stop($record->stop);
188             }
189             elsif ($record->strand == -1) {
190 102         2640 $transcript->coding_start($record->start);
191             }
192             }
193             }
194            
195 6         118 foreach my $transcript_id (keys %transcripts) {
196 348         1063 $transcripts{$transcript_id}->set_splice_starts_and_stops($transcript_splice_starts{$transcript_id}, $transcript_splice_stops{$transcript_id});
197             }
198            
199 6         49 my @outgenes;
200 6         67 foreach my $name (keys %genes){
201 156         105 foreach my $index (keys %{$genes{$name}}){
  156         276  
202 156         268 push @outgenes, $genes{$name}{$index};
203             }
204             }
205 6         282 return @outgenes;
206             }
207              
208             1;