Bioperl Training Exercise 9
- add getTm() method to BITS::Training::Primer that calculates the Tm for primer less than 14.
- Tm= (wA+xT) * 2 + (yG+zC) * 4
- where w,x,y,z are the number of the bases A,T,G,C in the sequence, respectively (from Marmur,J., and Doty,P. (1962) J Mol Biol 5:109-118
BITS::Training::Primer - getTm() method |
---|
Add the following to the BITS::Training::Primer module: sub getTm { my $self = shift; my $Tm = ( $self->numberOf('A') + $self->numberOf('T') ) * 2 + ( $self->numberOf('G') + $self->numberOf('C') ) * 4; return $Tm; } |
- create LongPrimer class that inherits from BITS::Training::Primer.
- Check perldoc base ! Do you understand why it is important to use modules with a single package AND have the same name ?
- Edit primer.pl so that the appropriate primer object is created depending on the length of the sequence.
BITS::Training::LongPrimer |
---|
Create the module LongPrimer.pm and save the file in the BITS/Training folder: package BITS::Training::LongPrimer; use strict; use base 'BITS::Training::Primer'; 1; |
At this moment the BITS::Training::LongPrimer class is not very useful: all methods (including the constructor) are inherited from the parental BITS::Training::Primer class. In other words, you can perfectly create objects of the BITS::Training::LongPrimer class, but they will currently behave exactly the same as BITS::Training::Primer objects.
primer.pl snippet |
---|
use BITS::Training::Primer; use BITS::Training::LongPrimer; # fill container while (<DATA>) { chomp; next if /^$/; # create primer object and add to container push @primers, ($_ > 14 ? BITS::Training::LongPrimer->new($_) : BITS::Training::Primer->new($_)); } |
- Now, add some BITS::Training::LongPrimer specific functionality by overriding the getTm() method. In OOP this is known as polymorphism, a method with the same name can have different behaviors depending to what class the object belongs.
- For sequences longer than 13 nucleotides, the equation used is
- Tm= 64.9 +41*(yG+zC-16.4)/(wA+xT+yG+zC)
- See Wallace,R.B., Shaffer,J., Murphy,R.F., Bonner,J., Hirose,T., and Itakura,K. (1979) Nucleic Acids Res 6:3543-3557 (Abstract) and Sambrook,J., and Russell,D.W. (2001) Molecular Cloning: A Laboratory Manual. Cold Spring Harbor Laboratory Press; Cold Spring Harbor, NY. (CHSL Press)
BITS::Training::LongPrimer - overriding the getTm() method |
---|
Create the module LongPrimer.pm and save the file in the BITS/Training folder: package BITS::Training::LongPrimer; use strict; use base 'BITS::Training::Primer'; sub getTm { my $self = shift; return 64.9 + 41 * ( $self->numberOf('G') + $self->numberOf('C') - 16.4 ) / ( $self->numberOf('A') + $self->numberOf('T') + $self->numberOf('G') + $self->numberOf('C') ); } 1; At this moment the BITS::Training::LongPrimer class is not very useful: all methods (including the constructor) are inherited from the parental BITS::Training::Primer class. In other words, you can perfectly create objects of the BITS::Training::LongPrimer class, but they will currently behave exactly the same as BITS::Training::Primer objects. |
- Make the proper improvements so that the Tm is calculated only once, e.g. not at every call to getTm().
Melting temperature calculated only once |
---|
One solution is to calculate the Tm at construction time and store the value as an attribute. But we want the code to be lazy here: calculate only when the information is needed. A way to achieve this is to check if the Tm attribute is set or not. If set, simply return that value. If not set, calculate the Tm, save the attribute for later use and return the value. BITS::Training::Primer: sub getTm { my $self =shift; # if called the first time # _tm attribute is not set # so, calculate and set the attribute first unless (defined $self->{_tm}) { $self->_calculateTm(); } return $self->{_tm}; } sub _calculateTm { my $self = shift; $self->{_tm} = ( $self->numberOf('A') + $self->numberOf('T') ) * 2 + ( $self->numberOf('G') + $self->numberOf('C') ) * 4; }
sub _calculateTm { my $self = shift; $self->{_tm} = 64.9 + 41 * ( $self->numberOf('G') + $self->numberOf('C') - 16.4 ) / ( $self->numberOf('A') + $self->numberOf('T') + $self->numberOf('G') + $self->numberOf('C') ); } |
- Advanced (try out at home). Now the primer object class consumer has to decide which primer class to use, depending on the primer length. This is a job that perfectly can be done with a so called builder pattern.