[Bioperl-l] Bio::SeqFeature::Primer Calculating the Primer TM

Barry Moore barry.moore at genetics.utah.edu
Tue Feb 17 19:23:01 EST 2004


John, Rob and others,

Well I certainly am not a Tm guru, but I'll reply none the less.  I have 
written a Tm calculator that uses thermodynamic parameters rather than 
"rule of thumb" calculations.  Mine follows the formula (and  
modifications) described by Integrated DNA Technologies on their web 
site 
(http://www.idtdna.com/program/techbulletins/Calculating_Tm_(melting_temperature).asp 
<http://www.idtdna.com/program/techbulletins/Calculating_Tm_%28melting_temperature%29.asp>).  
This code uses the equation: Tm = (dH / (dS +R * ln(C)) - 273.15  found 
in Breslauer (1986) and apparently used by GCG and the Python guys where 
R is the molar gas constant, and C is the molar concentration of the 
oligo.  It adds to that an adjustment of Na+ concentration as per Santa 
Lucia (1996) with some additional tweaking as described on the IDT web 
page above to give: Tm = (dH / (dS +R * ln(C)) - 273.15 + 12.0 * 
log[Na+] .  It uses the nearest-neighbor thermodynamic parameter set of 
Allawi and SantaLucia (1997), but it looks like maybe it should be 
updated to the SantaLucia (1998) parameter set.

I haven't read all the papers discussed in the various posts today, only 
the couple that my code is based on (and had plenty of trouble 
understanding all that was in those!), so I don't want to imply that the 
equations that I use are based on a thorough review of oligo 
thermodynamics literature, but the code seems to work, and it gives good 
Tm values. Theoretically I should get the exact same values as IDT's web 
calculator, but I don't.  My values are always very close, but off by a 
fraction to a couple degrees.  It may be due to a difference in 
parameter sets, although I'm using the same one that IDT references on 
their site.

Rob, I morphed my code into your Primer Tm method, and tried it out.  It 
seems to work fine.  It requires one extra parameter (oligo 
concentration) that I just defaulted.  If you want to use the code as is 
(or as a starting point) it is yours to do with as you see fit.  I can 
update the "thermodynamic parameters" hash to the SantaLucia (1998) 
values if this code looks promising and there is general agreement those 
values are the better.  I don't have CVS access, so I'll just post the 
modified method code at the very end of this message.

I did a quick and dirty test to see how Tm values differ between your 
Primer Tm method, my code, and IDT's web calculator.  They tend towards 
Tm(Rob) > Tm(IDT) > Tm(Barry).  Here's the result:

Oligo 	Primer.pm (Rob) 	Primer.pm (Barry) 	IDT
ACCGATACCG 	34.49709793 	29.41129054 	31.3
ACCCGATCTAGTAGA 	49.03043126 	41.9210458 	43.3
CATGGAGAGGGTGCAAATCC 	62.44709793 	55.72210633 	56.8
AAAGTAACCGAGAGAATCTGGAACA 	62.29709793 	56.7940798 	57.7
GGCTTTTGAAGTGGCAGAAAGACTGGGGGT 	71.76376459 	67.19994018 	68
CACTCGCCTGCTGGATGCAGAAGATGTGGATGTGC 	76.18281221 	70.5586708 	71.2
CTCTCCAGATGAAAAGTCTGTAATCACTTATGTGTCTTCG 	71.29709793 	63.54486627 	64.1
ATTTATGATGCCTTCCCTAAAGTTCCTGAGGGTGGAGAAGGGATC 	75.69709793 	69.5961597 
70.1
AGTGCTACGGAAGTGGACTCCAGGTGGCAAGAATACCAAAGCCGAGTGGA 	80.03709793 
75.41693338 	75.9


Here are the papers I've referenced:

    * Breslauer, K.J., Frank, R., Blocker, H., Marky, L.A. (1986)
      "Predicting DNA duplex stability from the base sequence."
      Proc.Natl. Acad. Sci. USA 83:3746-3750
    * SantaLucia, Jr., J.S, Allawi, H.T., Seneviratne, P.A. (1996)
      "Improved nearest-neighbor parameters for predicting DNA duplex
      stability" Biochemistry 35:3555-3562.
    * Allawi, H.T., SantaLucia, J. Jr. (1997) "Thermodynamics and NMR of
      internal G.T mismatches in DNA." Biochemistry 36: 10581-10594
    * SantaLucia J. Jr. (1998) "A unified view of polymer, dumbbell, and
      oligonucleotide DNA nearest-neighbor thermodynamics" PNAS 95:
      1460-1465.


Here is the new Tm method code:

=head2 Tm()

 Title   : Tm()
 Usage   : $tm = $primer->Tm(-salt=>'0.05')
 Function: Calculates and returns the Tm (melting temperature) of the primer
 Returns : A scalar containing the Tm.
 Args    : -salt set the Na+ concentration on which to base the calculation.
           (A parameter should be added to allow the oligo concentration 
to be set.)
 Notes   : Calculation of Tm as per Allawi et. al Biochemistry 1997 
36:10581-10594.  Also see
           documentation at http://biotools.idtdna.com/analyzer/ as they 
use this formula and
           have a couple nice help pages.  These Tm values will be about 
are about 0.5-3 degrees
           off from those of the idtdna web tool.  I don't know why.
=cut

sub Tm  {
    my ($self, %args) = @_;
    my $salt_conc = 0.05; #salt concentration (molar units)
    my $oligo_conc = 0.00000025; #oligo concentration (molar units)
    if ($args{'-salt'}) {$salt_conc = $args{'-salt'}} #accept object 
defined salt concentration
    #if ($args{'-oligo'}) {$oligo_conc = $args{'-oligo'}} #accept object 
defined oligo concentration
    my $seqobj = $self->seq();
    my $length = $seqobj->length();
    my $sequence = uc $seqobj->seq();
    my @dinucleotides;
    my $enthalpy;
    my $entropy;
    #Break sequence string into an array of all possible dinucleotides
    while ($sequence =~ /(.)(?=(.))/g) {
        push @dinucleotides, $1.$2;
    }
    #Build a hash with the thermodynamic values
    my %thermo_values = ('AA' => {'enthalpy' => -7.9,
                                  'entropy'  => -22.2},
                         'AC' => {'enthalpy' => -8.4,
                                  'entropy'  => -22.4},
                         'AG' => {'enthalpy' => -7.8,
                                  'entropy'  => -21},
                         'AT' => {'enthalpy' => -7.2,
                                  'entropy'  => -20.4},
                         'CA' => {'enthalpy' => -8.5,
                                  'entropy'  => -22.7},
                         'CC' => {'enthalpy' => -8,
                                  'entropy'  => -19.9},
                         'CG' => {'enthalpy' => -10.6,
                                  'entropy'  => -27.2},
                         'CT' => {'enthalpy' => -7.8,
                                  'entropy'  => -21},
                         'GA' => {'enthalpy' => -8.2,
                                  'entropy'  => -22.2},
                         'GC' => {'enthalpy' => -9.8,
                                  'entropy'  => -24.4},
                         'GG' => {'enthalpy' => -8,
                                  'entropy'  => -19.9},
                         'GT' => {'enthalpy' => -8.4,
                                  'entropy'  => -22.4},
                         'TA' => {'enthalpy' => -7.2,
                                  'entropy'  => -21.3},
                         'TC' => {'enthalpy' => -8.2,
                                  'entropy'  => -22.2},
                         'TG' => {'enthalpy' => -8.5,
                                  'entropy'  => -22.7},
                         'TT' => {'enthalpy' => -7.9,
                                  'entropy'  => -22.2},
                         'A' =>  {'enthalpy' => 2.3,
                                  'entropy'  => 4.1},
                         'C' =>  {'enthalpy' => 0.1,
                                  'entropy'  => -2.8},
                         'G' =>  {'enthalpy' => 0.1,
                                  'entropy'  => -2.8},
                         'T' =>  {'enthalpy' => 2.3,
                                  'entropy'  => 4.1}
                        );
    #Loop through dinucleotides and calculate cumulative enthalpy and 
entropy values
    for (@dinucleotides) {
       $enthalpy += $thermo_values{$_}{enthalpy};
       $entropy += $thermo_values{$_}{entropy};
    }
    #Account for initiation parameters
    $enthalpy += $thermo_values{substr($sequence, 0, 1)}{enthalpy};
    $entropy += $thermo_values{substr($sequence, 0, 1)}{entropy};
    $enthalpy += $thermo_values{substr($sequence, -1, 1)}{enthalpy};
    $entropy += $thermo_values{substr($sequence, -1, 1)}{entropy};
    #Symmetry correction
    $entropy -= 1.4;
    my $r = 1.987; #molar gas constant
    my $tm = ($enthalpy * 1000 / ($entropy + ($r * log($oligo_conc))) - 
273.15 + (12* (log($salt_conc)/log(10))));
    $self->{'Tm'}=$tm;
    return $tm;
}



More information about the Bioperl-l mailing list