<jupyter_start><jupyter_text>State of the art for PCR primer melting temperature (tm) calculationThis document was prepared to gather information about what might be the latest most modern and accurate ways to calculate PCR primermelting temperature (tm) in late 2019. I am the developer of the python package pydna and my main motivation is to provide an up to date method for the pydna package.There are meta studies in the literature, notably:Panjkovich, A., & Melo, F. (2005). Comparison of different melting temperature calculation methods for short DNA sequences. Bioinformatics , 21(6), 711–722. http://melolab.org/dnaMATEbut this paper is already almost fifteen years old and may not contain the latest developments.A google search came up with [this exchange](https://www.researchgate.net/post/Formula_for_calculating_Tm_of_primers2) on and [this](https://www.researchgate.net/post/How_do_I_calculate_the_annealing_temperature_of_my_PCR_reaction) researchgate.Several ad-hoc methods are suggested in the thread, but the suggestion of <NAME> of the [primer inspector](http://www.molbiotools.com/primerinspector.php) app seemed constructive to me.The methods in pydna are based on biopython code in the [Bio.SeqUtils.MeltingTemp](https://biopython.org/docs/1.74/api/Bio.SeqUtils.MeltingTemp.html) module. This code seems up to date, originally written by <NAME> and updated by <NAME> in 2018 according to copyright in the source code. PCR Primer InspectorA superficial inspection of PCR Primer Inspector reveals that the methods are relatively well documented compared to many other online tools. Clicking on the question mark next to each argument displays a page of text regarding the calculation.The objective of this analysis is to find out if PCR Primer Inspector and biopython (both being modern tools) calculate the same value for Tm of primers.This comparison was done on November 5, 2019, Biopython version used was 1.74 on linux mint. The example case is described below:The PCR reaction is a version of this [standard](https://www.neb.com/protocols/0001/01/01/taq-dna-polymerase-with-standard-taq-buffer-m0273) protocol:- 1X Taq Buffer with (NH4)2SO4- 0.2 mM of each dNTP- 2 mM MgCl2- 1 µM Primer I - 1 µM Primer II - Template DNAThe example buffer has this composition:[10X Taq Buffer with (NH4)2SO4](https://www.thermofisher.com/order/catalog/product/B33?SID=srch-srp-B33/B33?SID=srch-srp-B33) (B33) includes:- 750 mM Tris-HCl (pH 8.8 at 25°C)- 200 mM (NH4)2SO4- 0.1% (v/v) Tween 20This means that the final PCR reaction has: - 75 mM Tris-HCl- 40 mM NH4+ - 20 mM SO42-- 2  mM Mg2+- 4  mM Cl-The text below was copied from PCR Primer Inspector    The total concentration of monovalent cations is expectedly a sum of concentrations of sodium, potassium and ammonium cations     (not all of them have to be present in a PCR reaction mix). It is also advised to add the concentration of the dissociated     fraction of Tris in the PCR reaction mix (a half of the total Tris concentration may be a good approximation).     The Tm prediction may be less accurate in high concentrations (above 100 mM) of monovalent ions capable to form hydrogen bonds     (ammonium, Tris) and for bulkier monovalent ions (tetramethylammonium).Hence, "Cations" concentration should be 75/2 (half of Tris-HCl) + 40 (NH4+) = 77.5 mM .There should be very little of the other monovalent cations.The list of arguments is:- Primer concentration (nM): 1000 - Total monovalent cation concentration (mM): 77.5 - Mg2+concentration (mM): 2 - Total dNTPs concentration (mM): 0.8This values above were added to the input form of PCR Primer Inspector:![](page1.png)The result is 54.4°C for "Owczarzy 2008" and 54.9°C for "von Ahsen 2001". The use of these  references is described below. The text below was copied from PCR Primer Inspector:    MELTING TEMPERATURE CALCULATION    All the melting temperature calculations provided here are based on the     nearest neighbor method with parameters described in references [1] and [4].     Results of two different algorithms (references [2] and [3]) for monovalent     and magnesium cation correction are offered.    1.  A unified view of polymer, dumbbell, and oligonucleotide DNA nearest-neighbor thermodynamics        SantaLucia J. Jr. Proc Natl Acad Sci U S A. 1998;95(4):1460-5.    2.  Oligonucleotide melting temperatures under PCR conditions: nearest-neighbor corrections for Mg(2+),         deoxynucleotide triphosphate, and dimethyl sulfoxide concentrations with comparison to alternative         empirical formulas        <NAME>., <NAME>., <NAME>.        Clin Chem. 2001;47(11):1956-61.    3.  Predicting stability of DNA duplexes in solutions containing magnesium and monovalent cations        <NAME>., <NAME>., <NAME>., <NAME>., <NAME>.        Biochemistry. 2008;47(19):5336-53.    4.  The thermodynamics of DNA structural motifs        <NAME>., <NAME>.        Annu Rev Biophys Biomol Struct. 2004;33:415-40.                From above can be deduced that:1. Parameters used are described in references [1] and [4]2. The salt correction formulas from Owczarzy 2008 or von Ahsen 2001 are used.The first statement is somewhat ambiguous as the data in 1 and 4 is different (see below)although indeed very similar. Reference [1] (Table 1)![](sl_and_hicks_2004_table1.png) Reference [4] (Table 2)![](sl_1998_table2.png)As can be observed by comparing the two tables above, they only differ for the AA/TT entry (first line)and for Initiation / Init. w term. GC and Terminal AT penalty / Init. w term. AT.The ref 4 refers to Allawi 1997 for the data, and upon closer inspection, [Table 1](allawi_1997_table1.png) of Allawi 2997 is identical to table 2 of SantaLucia 1998.    <NAME>., & <NAME>. (1997). Thermodynamics and NMR of internal G.T mismatches in DNA. Biochemistry, 36(34), 10581–10594. BiopythonFrom Biopython [docs](https://biopython.org/DIST/docs/api/Bio.SeqUtils.MeltingTemp-module.html):table: Thermodynamic NN values, eight tables are implemented: For DNA/DNA hybridizations:- DNA_NN1: values from Breslauer et al. (1986)- DNA_NN2: values from Sugimoto et al. (1996)- DNA_NN3: values from Allawi & SantaLucia (1997) (default)- DNA_NN4: values from SantaLucia & Hicks (2004)                   <====<<<I choose the DNA_NN4 as the SantaLucia 1998 data from PCR Primer Inspector does not seem to be available.On closer inspection, Allawi & SantaLucia (1997) table 1 seem identical to SantaLucia J. Jr., Hicks D. 2004 Table 2.The salt correction method from Owczarzy et al. (2008) was chosen since this was what was used for PCR Primer Inspector.[7](https://biopython.org/DIST/docs/api/Bio.SeqUtils.MeltingTemp-module.htmlsalt_correction) = Complex formula with decision tree and 7 empirical constants. Mg2+ is corrected for dNTPs binding (if present) (Owczarzy et al. (2008), Biochemistry 47: 5336-5353)<jupyter_code>import Bio
Bio.__version__
from Bio.SeqUtils import MeltingTemp as mt<jupyter_output><empty_output><jupyter_text>The primer sequence is identical to the one used for the PCR Primer Inspector<jupyter_code>print( mt.Tm_NN("ATGGCAGTTGAGAAGA", 
       nn_table=mt.DNA_NN4,
       Na=40,
       Tris=75.0,
       Mg=2.0, 
       dnac1=1000, 
       dnac2=0, 
       dNTPs=0.8, 
       saltcorr=7) )<jupyter_output>57.794407437364214<jupyter_text>The biopython module reports 57.79°C while the PCR Primer Inspector reported 54.4°C.The difference is about 3.4 °C.This is a greater difference that I expected with care taken to use the same thermodynamic data. I contacted <NAME> by email:My email:Hi, I have tried to replicate theresults from <EMAIL> <EMAIL>with biopython using the same parameters and the same dataas far as I could tell. I still have a difference of about 3C.I compiled the comparison in this notebook:https://github.com/BjornFJohansson/tm/blob/master/tm.ipynbWould you care to have a look at it? to see if there is something obviously wrong?Is the code used by PCR Primer Inspector available for comparison?All the best,<NAME>Response:I tried to figure this out, but as I didn't see the python code I can only guess.PCR Primer Inspector uses the parameters from [1], but changing them to [4] gives only 0.1°C difference.What is probably the source of the discordant results is different understanding and implementation of this (from SantaLucia 1998):    "For self-complementary oligonucleotide duplexes, the Tm is calculated from the predicted dH° and dS° and the total oligonucleotide strand concentration CT, by using the equation ...[3]... For non-selfcomplementary molecules, CT in Eq. 3 is replaced by CT/4 if the strands are in equal concentration or by (CA - CB/2) if the strands are at different concentrations, where CA and CB are the concentrations of the more concentrated and less concentrated strands, respectively."That sounds like it should be CT for PCR conditions where C(primer)>>C(template) and CT/4 for an equimolar mix of complementary oligos. However, when checking the available code of Primer3, I found they use CT/4 for PCR conditions. I decided to be compliant with Primer3 (also Primer BLAST).If I change the algorithm to CT instead of CT/4, it gives 57.0 for half the Tris concentration and 57.9 for the whole Tris counted as monovalent cations.So it may be that there is a mistake in Primer3 (and hence also in PCR Primer Inspector), which is a kind of "gold standard" in the field....Best regards,<NAME>This means that the PCR Primer Inspector, Primer3 and other widely used tools implements the primer concentrationin a way not intended by the original author. The question is how to correctly emulate this using Biopython.Fortunately the documentation explains this nicely:[![](dnac1_2.png)](https://biopython.org/DIST/docs/api/Bio.SeqUtils.MeltingTemp-pysrc.htmlTm_NN)If I instead assign dnac1 and dnac2 to half of the total primer concentration according to the biopyton docs,the result become rather similar, especially if I also switch to the mt.DNA_NN3 table.PCR Primer Inspector gave 54.4 while biopython below gave 0.8 C or 0.01 C higher tm.<jupyter_code>from Bio.SeqUtils import MeltingTemp as mt
print( mt.Tm_NN("ATGGCAGTTGAGAAGA", 
       nn_table=mt.DNA_NN4,
       Na=40,
       Tris=75.0,
       Mg=2.0, 
       dnac1=1000/2, 
       dnac2=1000/2, 
       dNTPs=0.8, 
       saltcorr=7) )
print( mt.Tm_NN("ATGGCAGTTGAGAAGA", 
       nn_table=mt.DNA_NN3,
       Na=40,
       Tris=75.0,
       Mg=2.0, 
       dnac1=1000/2, 
       dnac2=1000/2, 
       dNTPs=0.8, 
       saltcorr=7) )<jupyter_output>55.24658512819792
54.49960170791479<jupyter_text>As per the email exchange above, PCR Primer Inspector follow the implementation of Primer3 with respect to the DNA concentration.  [Primer3 - PCR primer design tool](https://github.com/primer3-org) is an old but widely usead and continuously updated program.Primer3 is a c-program that I would like to avoid installing for now. Fortunately, there are several Primer3 instances available on the net.A google search resulted in this primer3 instance: http://www.bioinformatics.nl/cgi-bin/primer3plus/primer3plus.cgiI tried to emulate the settings used for PCR Primer Inspector as closely as possible. The Owczarzy 2008 salt correction is not available so Owczarzy 2004 was chosen.![](primer3_settings2.png)Monovalent and divalent cations, dNTPs and Annealing oligo concentrations were selected to reflect previous settings.![](primer3_settings1.png)The resulting Tm is 57C![](primer3_result.png)This is almost identical to the same settings in biopython:<jupyter_code>print( mt.Tm_NN("ATGGCAGTTGAGAAGA", 
       nn_table=mt.DNA_NN3,
       Na=40,
       Tris=75.0,
       Mg=2.0, 
       dnac1=1000/2, 
       dnac2=1000/2, 
       dNTPs=0.8, 
       saltcorr=6) )
import pydna
pydna.__version__
from pydna.tm import tm_default
tm_default("ATGGCAGTTGAGAAGA")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0728744939271255, 'fraction_numerical': 0.04436572199730095, 'mean_word_length': 4.221047996477322, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 37, 'https://': 10, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '439080', 'license': 'BSD-2-Clause', 'n_tokens_mistral': 3988, 'n_tokens_neox': 3315, 'n_words': 1502, 'path': 'tm.ipynb', 'repo_name': 'BjornFJohansson/tm', 'size': '11994'}