Mercurial > repos > jjohnson > crest
view GeneModel.pm @ 0:acc8d8bfeb9a
Uploaded
author | jjohnson |
---|---|
date | Wed, 08 Feb 2012 16:59:24 -0500 |
parents | |
children |
line wrap: on
line source
package GeneModel; use strict; use Carp; use Data::Dumper; use Tree::Interval; use Tree::DAG_Node; use English; use Gene; sub new { my $class = shift; my $obj = {}; $obj->{FMODEL} = {}; $obj->{RMODEL} = {}; if (@_) { my %arg = @_; $obj->{FMODEL} = $arg{-FMODEL} if($arg{-FMODEL}); $obj->{RMODEL} = $arg{-RMODEL} if($arg{-RMODEL}); } return bless $obj, $class; } sub get_all_chr { my $self = shift; return keys %{$self->{FMODEL}}; } sub add_gene { my ($self, $gene) = @_; if($gene->strand eq '+') { $self->{FMODEL}->{$gene->chr}->insert([$gene->start, $gene->end], $gene); } else { $self->{FMODEL}->{$gene->chr}->insert([$gene->start, $gene->end], $gene); } } sub remove_gene { my $self = shift; my $gene = shift; if($gene->strand eq '+') { $self->{FMODEL}->{$gene->chr}->remove([$gene->start, $gene->end], $gene); } else { $self->{RMODEL}->{$gene->chr}->remove([$gene->start, $gene->end], $gene); } } sub n_genes { my $self = shift; my $n = 0; foreach my $c (keys %{$self->{FMODEL}}) { $n += $self->{FMODEL}->{$c}->size; } foreach my $c (keys %{$self->{RMODEL}}) { $n += $self->{RMODEL}->{$c}->size; } return $n; } sub sub_model { my ($self, $chr, $strand) = @_; if($strand eq '+' ) { return $self->{FMODEL}->{$chr}; } else { return $self->{RMODEL}->{$chr}; } } sub look_up_gene { my ($self, $chr, $gene) = @_; if($gene->isa('Gene')) { if($gene->strand eq '+') { return $self->{FMODEL}->{$chr}->lookup([$gene->start, $gene->end]); } else { return $self->{RMODEL}->{$chr}->lookup([$gene->start, $gene->end]); } } elsif(ref($gene) eq 'ARRAY') { return ( $self->{FMODEL}->{$chr}->lookup([$gene->start, $gene->end]), $self->{RMODEL}->{$chr}->lookup([$gene->start, $gene->end]) ); } else { croak "Not implemented look_up_gene for $gene"; } } sub overlap_genes { my ($self, $chr, $fea, $ort) = @_; my @genes; if(ref($fea) eq 'ARRAY') { @genes = $self->_overlap_array($chr, $fea, $ort); } elsif($fea->isa('Transcript')) { foreach my $e (@{$fea->exons}) { push @genes, $self->_overlap_array($chr, $e, $fea->strand ? $fea->strand : undef); } } else { croak "Not implemented overlap for $fea"; } my @rtn; foreach my $g (@genes) { push @rtn, $g if($g->overlap($fea)); } return @rtn; } sub _overlap_array { my($self, $chr, $a, $ort) = @_; if($ort) { return $ort == '+' ? $self->{FMODEL}->{$chr}->intersect($a) : $self->{RMODEL}->{$chr}->intersect($a); } else { return ($self->{FMODEL}->{$chr}->intersect($a), $self->{RMODEL}->{$chr}->intersect($a)); } } sub model { my ($self, $chr, $strand, $val) = @_; croak "Please specify chr and strand for GeneModel" unless $chr && $strand; my $model = $strand eq '+' ? $self->{FMODEL} : $self->{RMODEL}; if($val) { croak "The model for each chrom must be a Tree::Interval" unless $val->isa('Tree::Interval'); $model->{$chr} = $val; } return $model->{$chr}; } sub from_file { my ($self, $file, $format) = @_; croak "$format is not implemented yet!" unless uc($format) eq "REFFLAT"; print STDERR "Processing gene model file, please wait ... "; my $transcripts = _refFlat2Transcripts($file); my $model = _Transcript2GeneModel($transcripts); foreach my $c (keys %{$model}) { foreach my $s (keys %{$model->{$c}}) { if($s eq '+') { $self->{FMODEL}->{$c} = $model->{$c}{$s}; } else { $self->{RMODEL}->{$c} = $model->{$c}{$s}; } } } print STDERR "Done.\n"; } sub _refFlat2Transcripts { my $file = shift; my %transcripts; open my $FILE, "<$file" or croak "Can't open $file: $OS_ERROR"; while( my $line = <$FILE> ) { next if($line =~ /^#/); #annotation line my ($name, $refseq_id, $chr, $strand, $txStart, $txEnd, $cdsStart, $cdsEnd, $exonCount, $exonStarts, $exonEnds) = split(/\s+/, $line); my $type = $cdsEnd == $cdsStart ? "NR" : "NM"; my @starts = split /,/, $exonStarts; my @ends = split /,/, $exonEnds; if(scalar @starts != scalar @ends) { warn "Number of exon starts is not same as exon ends!"; next; } $transcripts{$chr} = {} unless (exists $transcripts{$chr}); $transcripts{$chr}->{$strand} = [] unless (exists $transcripts{$chr}->{$strand}); my @exons; for( my $i = 0; $i < $exonCount; $i++) { push @exons, [$starts[$i], $ends[$i]]; } my $t = Transcript->new(-START => $starts[0], -END => $ends[$#ends], -CHR => $chr, -STRAND => $strand eq '+' ? 1 : -1, -NAME => $name, -REFSEQ_ID => $refseq_id, -EXONS => \@exons, -TYPE => $type); push @{$transcripts{$chr}->{$strand}}, $t; } #sort the list of transcripts foreach my $c (keys %transcripts) { foreach my $s (keys %{$transcripts{$c}}) { my @tmp = @{$transcripts{$c}->{$s}}; @tmp = sort { $a->start <=> $b->start || $a->end <=> $b->end } @tmp; $transcripts{$c}->{$s} = \@tmp; } } return \%transcripts; } sub _Transcript2GeneModel { my $transcripts = shift; my %genemodel; foreach my $c (keys %{$transcripts}) { $genemodel{$c} = {}; foreach my $s (keys %{$transcripts->{$c}}) { my $tree = $genemodel{$c}->{$s} = Tree::Interval->new(); foreach my $t (@{$transcripts->{$c}{$s}}) { my @ol = $tree->intersect([$t->start, $t->end]); if(scalar @ol == 0 ) { my $gene = Gene->new(); $gene->add_transcript($t); $tree->insert([$t->start, $t->end], $gene); next; } my @real_ol; foreach my $g (@ol) { push @real_ol, $g->val if($g->val->overlap($t)); } if(scalar @real_ol == 0) { #gene in gene? # print STDERR "Gene in Gene: ", $t->name, " in ", $ol[0]->val->name, " \n"; my $gene = Gene->new(); $gene->add_transcript($t); $tree->insert([$t->start, $t->end], $gene); next; } if(scalar @real_ol == 1 ) { # transcript belongs to gene my $g = $real_ol[0]; # print STDERR "Same Gene group: ", $t->name, " in ", $real_ol[0]->name, " \n"; if($t->start < $g->start || $t->end > $g->end) { $tree->delete([$g->start, $g->end], $g); $g->add_transcript($t); $tree->insert([$g->start, $g->end], $g); next; } $g->add_transcript($t); next; } # a transcript make more genes same # print STDERR "Join Gene group: ", $t->name, " join ", $real_ol[0]->name, "and", $real_ol[1]->name, " \n"; my $gene = Gene->new(); $gene->add_transcript($t); foreach my $g (@real_ol) { $tree->delete([$g->start, $g->end], $g); foreach my $tp (@{$g->transcripts}) { $gene->add_transcript($tp); } } $tree->insert([$gene->start, $gene->end], $gene); } } } return \%genemodel; } sub _print_tree { return; my $tree = shift; my $t = Tree::DAG_Node->lol_to_tree($tree->root->as_lol); local $, = "\n"; print @{$t->draw_ascii_tree}, "\n"; } 1;