From f098d487a231a0d9f2ad31ac61d6c1102147045b Mon Sep 17 00:00:00 2001 From: Patrick Meidl <pm2@sanger.ac.uk> Date: Thu, 31 Aug 2006 11:47:22 +0000 Subject: [PATCH] first (draft) version of new modules for ID mapping --- modules/Bio/EnsEMBL/IdMapping/Entry.pm | 78 +++++ .../Bio/EnsEMBL/IdMapping/ExonScoreBuilder.pm | 147 +++++++++ modules/Bio/EnsEMBL/IdMapping/ScoreBuilder.pm | 102 ++++++ .../EnsEMBL/IdMapping/ScoredMappingMatrix.pm | 305 ++++++++++++++++++ modules/Bio/EnsEMBL/IdMapping/TinyExon.pm | 205 ++++++++++++ modules/Bio/EnsEMBL/IdMapping/TinyGene.pm | 60 ++++ .../Bio/EnsEMBL/IdMapping/TinyTranscript.pm | 72 +++++ .../Bio/EnsEMBL/IdMapping/TinyTranslation.pm | 43 +++ 8 files changed, 1012 insertions(+) create mode 100644 modules/Bio/EnsEMBL/IdMapping/Entry.pm create mode 100644 modules/Bio/EnsEMBL/IdMapping/ExonScoreBuilder.pm create mode 100644 modules/Bio/EnsEMBL/IdMapping/ScoreBuilder.pm create mode 100644 modules/Bio/EnsEMBL/IdMapping/ScoredMappingMatrix.pm create mode 100644 modules/Bio/EnsEMBL/IdMapping/TinyExon.pm create mode 100644 modules/Bio/EnsEMBL/IdMapping/TinyGene.pm create mode 100644 modules/Bio/EnsEMBL/IdMapping/TinyTranscript.pm create mode 100644 modules/Bio/EnsEMBL/IdMapping/TinyTranslation.pm diff --git a/modules/Bio/EnsEMBL/IdMapping/Entry.pm b/modules/Bio/EnsEMBL/IdMapping/Entry.pm new file mode 100644 index 0000000000..41765bfff9 --- /dev/null +++ b/modules/Bio/EnsEMBL/IdMapping/Entry.pm @@ -0,0 +1,78 @@ +package Bio::EnsEMBL::IdMapping::Entry; + +=head1 NAME + + +=head1 SYNOPSIS + + +=head1 DESCRIPTION + + +=head1 METHODS + + +=head1 LICENCE + +This code is distributed under an Apache style licence. Please see +http://www.ensembl.org/info/about/code_licence.html for details. + +=head1 AUTHOR + +Patrick Meidl <meidl@ebi.ac.uk>, Ensembl core API team + +=head1 CONTACT + +Please post comments/questions to the Ensembl development list +<ensembl-dev@ebi.ac.uk> + +=cut + +use strict; +use warnings; +no warnings 'uninitialized'; + +use Bio::EnsEMBL::Utils::Exception qw(throw warning); + + +sub new { + my $caller = shift; + my $class = ref($caller) || $caller; + + my $self = []; + bless ($self, $class); + + return $self; +} + + +sub new_fast { + my $class = shift; + my $array_ref = shift; + return bless $array_ref, $class; +} + + +sub source { + my $self = shift; + $self->[0] = shift if (@_); + return $self->[0]; +} + + +sub target { + my $self = shift; + $self->[1] = shift if (@_); + return $self->[1]; +} + + +sub score { + my $self = shift; + $self->[2] = shift if (@_); + return $self->[2]; +} + + +1; + diff --git a/modules/Bio/EnsEMBL/IdMapping/ExonScoreBuilder.pm b/modules/Bio/EnsEMBL/IdMapping/ExonScoreBuilder.pm new file mode 100644 index 0000000000..0041bc6de8 --- /dev/null +++ b/modules/Bio/EnsEMBL/IdMapping/ExonScoreBuilder.pm @@ -0,0 +1,147 @@ +package Bio::EnsEMBL::IdMapping::ExonScoreBuilder; + +=head1 NAME + + +=head1 SYNOPSIS + + +=head1 DESCRIPTION + + +=head1 METHODS + + +=head1 LICENCE + +This code is distributed under an Apache style licence. Please see +http://www.ensembl.org/info/about/code_licence.html for details. + +=head1 AUTHOR + +Patrick Meidl <meidl@ebi.ac.uk>, Ensembl core API team + +=head1 CONTACT + +Please post comments/questions to the Ensembl development list +<ensembl-dev@ebi.ac.uk> + +=cut + + +use strict; +use warnings; +no warnings 'uninitialized'; + +use Bio::EnsEMBL::IdMapping::ScoreBuilder; +our @ISA = qw(Bio::EnsEMBL::IdMapping::ScoreBuilder); + +use Bio::EnsEMBL::Utils::Argument qw(rearrange); +use Bio::EnsEMBL::Utils::Exception qw(throw warning); +use Bio::EnsEMBL::Utils::ScriptUtils qw(parse_bytes); +use Bio::EnsEMBL::IdMapping::ScoredMappingMatrix; + + +sub score_exons { + my $self = shift; + + my $matrix = Bio::EnsEMBL::IdMapping::ScoredMappingMatrix->new( + -DUMP_PATH => $self->conf('dumppath') + ); + + my $cache_file = $matrix->cache_file; + + if (-s $cache_file) { + # read from file + $self->logger->log_stamped("Reading exon scoring matrix from file...\n"); + $self->logger->log("Cache file $cache_file.\n", 1); + $matrix->read_from_file; + $self->logger->log_stamped("Done.\n"); + } else { + # + # build scoring matrix + # + + # direct mapping (by overlap, if common coord_system exists) + if ($self->cache->highest_common_cs) { + $matrix = $self->build_overlap_scores($matrix); + } + + + # map the remaining exons using exonerate + + # dump exons to fasta files + my $dump_size = $self->cache->dump_filtered_exons; + + if ($dump_size) { + # run exonerate + my $exonerate_matrix; + + # merge matrices + $matrix->merge($exonerate_matrix); + } + + + # + # write scoring matrix to file + # + $matrix->write_to_file; + + return $matrix; + } + + return $matrix; +} + + +sub build_overlap_scores { + my $self = shift; + my $matrix = shift; + + unless ($matrix and + $matrix->isa('Bio::EnsEMBL::IdMapping::ScoredMappingMatrix')) { + throw('Need a Bio::EnsEMBL::IdMapping::ScoredMappingMatrix.'); + } + + my @s_exons = $self->sort_exons( + [values %{ $self->cache->get_by_name('exons_by_id', 'source') } + ); + my @t_exons = $self->sort_exons( + [values %{ $self->cache->get_by_name('exons_by_id', 'target') } + ); + + +} + + +# +# Return a list of exons, sorted by seq_region_name, then location (where +# location is either start-1 or end, so each exon is in the list twice) +# +# TODO: this implementation isn't good enough, since you'll need location later +# to compare source and target exons again. best add this as an instance +# variable to the TinyExon returned +# +sub sort_exons { + my $self = shift; + my $exons = shift; + + return + map { $_->[2] } + sort { $a->[0] cmp $b->[0] || $a->[1] <=> $b->[1] } + ( + map { [$_->common_name, $_->common_start - 1, $_] } @$exons, + map { [$_->common_name, $_->common_end, $_] } @$exons + ); + +} + + +sub compare_exons { + my $self = shift; + my $e1 = shift; + my $e2 = shift; + + return ( $e1-> +} + diff --git a/modules/Bio/EnsEMBL/IdMapping/ScoreBuilder.pm b/modules/Bio/EnsEMBL/IdMapping/ScoreBuilder.pm new file mode 100644 index 0000000000..3a249d46ed --- /dev/null +++ b/modules/Bio/EnsEMBL/IdMapping/ScoreBuilder.pm @@ -0,0 +1,102 @@ +package Bio::EnsEMBL::IdMapping::ScoreBuilder; + +=head1 NAME + + +=head1 SYNOPSIS + + +=head1 DESCRIPTION + + +=head1 METHODS + + +=head1 LICENCE + +This code is distributed under an Apache style licence. Please see +http://www.ensembl.org/info/about/code_licence.html for details. + +=head1 AUTHOR + +Patrick Meidl <meidl@ebi.ac.uk>, Ensembl core API team + +=head1 CONTACT + +Please post comments/questions to the Ensembl development list +<ensembl-dev@ebi.ac.uk> + +=cut + + +use strict; +use warnings; +no warnings 'uninitialized'; + +use Bio::EnsEMBL::Utils::Exception qw(throw warning); + + +=head2 new + + Arg[1] : + Example : + Description : constructor + Return type : + Exceptions : + Caller : general + +=cut + +sub new { + my $caller = shift; + my $class = ref($caller) || $caller; + + my ($logger, $conf, $cache) = rearrange(['LOGGER', 'CONF', 'CACHE'], @_); + + unless ($logger->isa('Bio::EnsEMBL::Utils::Logger')) { + throw("You must provide a Bio::EnsEMBL::Utils::Logger for logging."); + } + + unless ($conf->isa('Bio::EnsEMBL::Utils::ConfParser')) { + throw("You must provide configuration as a Bio::EnsEMBL::Utils::ConfParser object."); + } + + unless ($cache->isa('Bio::EnsEMBL::IdMapping::Cache')) { + throw("You must provide configuration as a Bio::EnsEMBL::IdMapping::Cache object."); + } + + my $self = {}; + bless ($self, $class); + + # initialise + $self->logger($logger); + $self->conf($conf); + $self->cache($cache); + + return $self; +} + + +sub logger { + my $self = shift; + $self->{'_logger'} = shift if (@_); + return $self->{'_logger'}; +} + + +sub conf { + my $self = shift; + $self->{'_conf'} = shift if (@_); + return $self->{'_conf'}; +} + + +sub cache { + my $self = shift; + $self->{'_cache'} = shift if (@_); + return $self->{'_cache'}; +} + + +1; + diff --git a/modules/Bio/EnsEMBL/IdMapping/ScoredMappingMatrix.pm b/modules/Bio/EnsEMBL/IdMapping/ScoredMappingMatrix.pm new file mode 100644 index 0000000000..4e2d1a7a4c --- /dev/null +++ b/modules/Bio/EnsEMBL/IdMapping/ScoredMappingMatrix.pm @@ -0,0 +1,305 @@ +package Bio::EnsEMBL::IdMapping::ScoredMappingMatrix; + +=head1 NAME + + +=head1 SYNOPSIS + + +=head1 DESCRIPTION + + +=head1 METHODS + + +=head1 LICENCE + +This code is distributed under an Apache style licence. Please see +http://www.ensembl.org/info/about/code_licence.html for details. + +=head1 AUTHOR + +Patrick Meidl <meidl@ebi.ac.uk>, Ensembl core API team + +=head1 CONTACT + +Please post comments/questions to the Ensembl development list +<ensembl-dev@ebi.ac.uk> + +=cut + + +use strict; +use warnings; +no warnings 'uninitialized'; + +use Bio::EnsEMBL::Utils::Argument qw(rearrange); +use Bio::EnsEMBL::Utils::Exception qw(throw warning); +use Bio::EnsEMBL::Utils::ScriptUtils qw(parse_bytes); +use Bio::EnsEMBL::IdMapping::Entry; + + +sub new { + my $caller = shift; + my $class = ref($caller) || $caller; + + my ($dump_path) = rearrange(['DUMP_PATH'], @_); + + throw("You must provide a dump path") unless ($dump_path); + + my $self = {}; + bless ($self, $class); + + # initialise internal datastructure + $self->{'matrix'} = {}; + $self->{'source_list'} = {}; + $self->{'target_list'} = {}; + $self->{'dump_path'} = $dump_path; + + return $self; +} + + +sub add_Entry { + my $self = shift; + my $entry = shift; + + unless ($entry and $entry->isa('Bio::EnsEMBL::IdMapping::Entry')) { + throw("Need a Bio::EnsEMBL::IdMapping::Entry"); + } + + return $self->add_score($entry->source, $entry->target, $entry->score); +} + + +sub remove_Entry { +} + + +sub add_score { + my $self = shift; + my $source = shift; + my $target = shift; + my $score = shift; + + # make sure you don't put duplicates on the source and target lists + unless (exists($self->{'matrix'}->{"$source:$target"})) { + push @{ $self->{'source_list'}->{$source} }, $target; + push @{ $self->{'target_list'}->{$target} }, $source; + } + + $self->{'matrix'}->{"$source:$target"} = $score; +} + + +sub get_Entry { + my $self = shift; + my $source = shift; + my $target = shift; + + if (exists($self->{'matrix'}->{"$source:$target"}) { + return Bio::EnsEMBL::IdMapping::Entry->new_fast( + [$source, $target, $self->{'matrix'}->{"$source:$target"}] + ); + } else { + return undef; + } +} + + +sub get_score { + my $self = shift; + my $source = shift; + my $target = shift; + + + if (exists($self->{'matrix'}->{"$source:$target"}) { + return $self->{'matrix'}->{"$source:$target"}; + } else { + return undef; + } +} + + +sub get_targets_for_source { + my $self = shift; + my $source = shift; + + return($self->{'source_list'}->{$source} || []); +} + + +sub get_sources_for_target { + my $self = shift; + my $target = shift; + + return($self->{'target_list'}->{$target} || []); +} + + +sub get_all_Entries { + my $self = shift; + + my @result = (); + + foreach my $key (keys %{ $self->{'matrix'} }) { + my ($source, $target) = split(/:/, $key); + push @result, Bio::EnsEMBL::IdMapping::Entry->new_fast( + [$source, $target, $self->{'matrix'}->{$key}] + ); + } + + return \@result; +} + + +sub get_all_sources { + return [keys %{ $_->{'source_list'} }]; +} + + +sub get_all_targets { + return [keys %{ $_->{'target_list'} }]; +} + + +sub get_entry_count { + return scalar(keys %{ $_->{'matrix'} }); +} + + +sub get_source_count { + return scalar(keys %{ $_->{'source_list'} }); +} + + +sub get_target_count { + return scalar(keys %{ $_->{'target_list'} }); +} + + +sub get_min_scores { + my $self = shift; + + my @keys = keys %{ $self->{'matrix'} }; + + return [undef, undef] unless (@keys); + + # initialise; this should make loop quicker + my $min = $self->{'matrix'}->{$keys[0]}; + my $max = $self->{'matrix'}->{$keys[0]}; + + foreach my $key (@keys) { + $min = $self->{'matrix'}->{$key} if ($min > $self->{'matrix'}->{$key}); + $max = $self->{'matrix'}->{$key} if ($max < $self->{'matrix'}->{$key}); + } + + return [$min, $max]; +} + + +sub get_average_score { + my $self = shift; + + my @keys = keys %{ $self->{'matrix'} }; + + return undef unless (@keys); + + my $total = 0; + + foreach my $key (@keys) { + $total += $self->{'matrix'}->{$key}; + } + + return $total/scalar(@keys); +} + + +sub write_to_file { +} + + +sub merge { + my $self = shift; + my $matrix = shift; + + unless ($matrix and + $matrix->isa('Bio::EnsEMBL::IdMapping::ScoredMappingMatrix')) { + throw('You must provide a Bio::EnsEMBL::IdMapping::ScoredMappingMatrix'); + } + + my $c = 0; + + foreach my $key (keys %{ $matrix->{'matrix'} }) { + if (!defined($self->{'matrix'}->{$key}) or + $self->{'matrix'}->{$key} < $matrix->{'matrix'}->{$key}) { + $self->{'matrix'}->{$key} = $matrix->{'matrix'}->{$key}; + $c++; + } + } + + return $c; +} + + +sub write_to_file { + my $self = shift; + + # create dump directory if it doesn't exist + if (my $dump_path = $self->dump_path) { + unless (-d $dump_path) { + system("mkdir -p $dump_path") == 0 or + throw("Unable to create directory $dump_path.\n"); + } + } + + my $cache_file = $self->cache_file; + + eval { nstore($self, $cache_file) }; + if ($@) { + throw("Unable to store $cache_file: $@\n"); + } + + my $size = -s $cache_file; + return parse_bytes($size); +} + + +sub read_from_file { + my $self = shift; + + my $cache_file = $self->cache_file; + + unless (-s $cache_file) { + throw("No valid cache file found at $cache_file."); + } + + eval { $self = retrieve($cache_file); }; + if ($@) { + throw("Unable to retrieve cache: $@"); + } + + return $self; +} + + +sub cache_file { + my $self = shift; + my $cache_file = ($self->dump_path || '.').'/exon_scoring_matrix.ser'; + return $cache_file; +} + + +# +# getter/setters +# + +sub dump_path { + my $self = shift; + $self->{'dump_path'} = shift if (@_); + return $self->{'dump_path'}; +} + + +1; + diff --git a/modules/Bio/EnsEMBL/IdMapping/TinyExon.pm b/modules/Bio/EnsEMBL/IdMapping/TinyExon.pm new file mode 100644 index 0000000000..ec7080b084 --- /dev/null +++ b/modules/Bio/EnsEMBL/IdMapping/TinyExon.pm @@ -0,0 +1,205 @@ +package Bio::EnsEMBL::IdMapping::TinyGene; + +=head1 NAME + + +=head1 SYNOPSIS + + +=head1 DESCRIPTION + + +=head1 METHODS + + +=head1 LICENCE + +This code is distributed under an Apache style licence. Please see +http://www.ensembl.org/info/about/code_licence.html for details. + +=head1 AUTHOR + +Patrick Meidl <meidl@ebi.ac.uk>, Ensembl core API team + +=head1 CONTACT + +Please post comments/questions to the Ensembl development list +<ensembl-dev@ebi.ac.uk> + +=cut + + +# internal data structure (array indices): +# +# 0 dbID +# 1 stable_id +# 2 start +# 3 end +# 4 strand +# 5 seq_region_name +# 6 coord_system_name +# 7 coord_system_version +# 8 seq +# 9 need_project +# 10 common_start +# 11 common_end +# 12 common_strand +# 13 common_sr_name + + +use strict; +use warnings; +no warnings 'uninitialized'; + +use Bio::EnsEMBL::IDMapping::TinyFeature; +our @ISA = qw(Bio::EnsEMBL::IDMapping::TinyFeature); + +use Bio::EnsEMBL::Utils::Exception qw(throw warning); + + +sub start { + my $self = shift; + $self->[2] = shift if (@_); + return $self->[2]; +} + + +sub end { + my $self = shift; + $self->[3] = shift if (@_); + return $self->[3]; +} + + +sub strand { + my $self = shift; + $self->[4] = shift if (@_); + return $self->[4]; +} + + +sub seq_region_name { + my $self = shift; + $self->[5] = shift if (@_); + return $self->[5]; +} + + +sub coord_system_name { + my $self = shift; + $self->[6] = shift if (@_); + return $self->[6]; +} + + +sub coord_system_version { + my $self = shift; + $self->[7] = shift if (@_); + return $self->[7]; +} + + +sub seq { + my $self = shift; + $self->[8] = shift if (@_); + return $self->[8]; +} + + +sub need_project { + my $self = shift; + $self->[9] = shift if (@_); + return $self->[9]; +} + + +sub common_start { + my $self = shift; + + # when used as a setter, always set a value + $self->[10] = shift if (@_); + + # when used as a getter + if (scalar(@$self > 9) { + # return value for common coord_system if available (but avoid + # autovivification gotcha!) + return $self->[10]; + } elsif ($self->need_project) { + # return undef if common value expected but not there (e.g. no projection + # found + return undef; + } else { + # return native value + return $self->start; + } +} + + +sub common_end { + my $self = shift; + + # when used as a setter, always set a value + $self->[11] = shift if (@_); + + # when used as a getter + if (scalar(@$self > 9) { + # return value for common coord_system if available (but avoid + # autovivification gotcha!) + return $self->[11]; + } elsif ($self->need_project) { + # return undef if common value expected but not there (e.g. no projection + # found + return undef; + } else { + # return native value + return $self->end; + } +} + + +sub common_strand { + my $self = shift; + + # when used as a setter, always set a value + $self->[12] = shift if (@_); + + # when used as a getter + if (scalar(@$self > 9) { + # return value for common coord_system if available (but avoid + # autovivification gotcha!) + return $self->[12]; + } elsif ($self->need_project) { + # return undef if common value expected but not there (e.g. no projection + # found + return undef; + } else { + # return native value + return $self->strand; + } +} + + +sub common_sr_name { + my $self = shift; + + # when used as a setter, always set a value + $self->[13] = shift if (@_); + + # when used as a getter + if (scalar(@$self > 9) { + # return value for common coord_system if available (but avoid + # autovivification gotcha!) + return $self->[13]; + } elsif ($self->need_project) { + # return undef if common value expected but not there (e.g. no projection + # found + return undef; + } else { + # return native value + return $self->seq_region_name; + } +} + + +1; + diff --git a/modules/Bio/EnsEMBL/IdMapping/TinyGene.pm b/modules/Bio/EnsEMBL/IdMapping/TinyGene.pm new file mode 100644 index 0000000000..0cd2d7ce72 --- /dev/null +++ b/modules/Bio/EnsEMBL/IdMapping/TinyGene.pm @@ -0,0 +1,60 @@ +package Bio::EnsEMBL::IdMapping::TinyGene; + +=head1 NAME + + +=head1 SYNOPSIS + + +=head1 DESCRIPTION + + +=head1 METHODS + + +=head1 LICENCE + +This code is distributed under an Apache style licence. Please see +http://www.ensembl.org/info/about/code_licence.html for details. + +=head1 AUTHOR + +Patrick Meidl <meidl@ebi.ac.uk>, Ensembl core API team + +=head1 CONTACT + +Please post comments/questions to the Ensembl development list +<ensembl-dev@ebi.ac.uk> + +=cut + + +use strict; +use warnings; +no warnings 'uninitialized'; + +use Bio::EnsEMBL::IDMapping::TinyFeature; +our @ISA = qw(Bio::EnsEMBL::IDMapping::TinyFeature); + +use Bio::EnsEMBL::Utils::Exception qw(throw warning); + + +sub add_Transcript { + my $self = shift; + my $tr = shift; + + unless ($tr && $tr->isa('Bio::EnsEMBL::IdMapping::TinyTranscript')) { + throw('Need a Bio::EnsEMBL::IdMapping::TinyTranscript.'); + } + + push @{ $self->[9] }, $tr; +} + + +sub get_all_Transcripts { + return $_->[9] || []; +} + + +1; + diff --git a/modules/Bio/EnsEMBL/IdMapping/TinyTranscript.pm b/modules/Bio/EnsEMBL/IdMapping/TinyTranscript.pm new file mode 100644 index 0000000000..a0fe549041 --- /dev/null +++ b/modules/Bio/EnsEMBL/IdMapping/TinyTranscript.pm @@ -0,0 +1,72 @@ +package Bio::EnsEMBL::IdMapping::TinyTranscript; + +=head1 NAME + + +=head1 SYNOPSIS + + +=head1 DESCRIPTION + + +=head1 METHODS + + +=head1 LICENCE + +This code is distributed under an Apache style licence. Please see +http://www.ensembl.org/info/about/code_licence.html for details. + +=head1 AUTHOR + +Patrick Meidl <meidl@ebi.ac.uk>, Ensembl core API team + +=head1 CONTACT + +Please post comments/questions to the Ensembl development list +<ensembl-dev@ebi.ac.uk> + +=cut + + +use strict; +use warnings; +no warnings 'uninitialized'; + +use Bio::EnsEMBL::IDMapping::TinyFeature; +our @ISA = qw(Bio::EnsEMBL::IDMapping::TinyFeature); + +use Bio::EnsEMBL::Utils::Exception qw(throw warning); + + +sub add_Translation { + my $self = shift; + my $tl = shift; + + unless ($self->[0] eq 'tr' and $tl->[0] eq 'tl') { + throw('You can only add a translation to a transcript.'); + } + + $self->[10] = $tl; +} + + +sub add_Exon { + my $self = shift; + my $exon = shift; + + unless ($exon && $exon->isa('Bio::EnsEMBL::IdMapping::TinyExon')) { + throw('Need a Bio::EnsEMBL::IdMapping::TinyExon.'); + } + + push @{ $self->[11] }, $exon; +} + + +sub get_all_Exons { + return $_->[11] || []; +} + + +1; + diff --git a/modules/Bio/EnsEMBL/IdMapping/TinyTranslation.pm b/modules/Bio/EnsEMBL/IdMapping/TinyTranslation.pm new file mode 100644 index 0000000000..9fdc7c64ac --- /dev/null +++ b/modules/Bio/EnsEMBL/IdMapping/TinyTranslation.pm @@ -0,0 +1,43 @@ +package Bio::EnsEMBL::IdMapping::TinyGene; + +=head1 NAME + + +=head1 SYNOPSIS + + +=head1 DESCRIPTION + + +=head1 METHODS + + +=head1 LICENCE + +This code is distributed under an Apache style licence. Please see +http://www.ensembl.org/info/about/code_licence.html for details. + +=head1 AUTHOR + +Patrick Meidl <meidl@ebi.ac.uk>, Ensembl core API team + +=head1 CONTACT + +Please post comments/questions to the Ensembl development list +<ensembl-dev@ebi.ac.uk> + +=cut + + +use strict; +use warnings; +no warnings 'uninitialized'; + +use Bio::EnsEMBL::IDMapping::TinyFeature; +our @ISA = qw(Bio::EnsEMBL::IDMapping::TinyFeature); + +use Bio::EnsEMBL::Utils::Exception qw(throw warning); + + +1; + -- GitLab