Repository: biopython/biopython

Issue:
formulas in biopython/Bio/SeqUtils/MeltingTemp.py  source code line 736-760 don't correspond to line 795-818
Hello,

I found formulas in the source code line 736-760 are as follows,

1. Tm = 69.3 + 0.41(%GC) - 650/N
   (Marmur & Doty 1962, J Mol Biol 5: 109-118; Chester & Marshak 1993),
   Anal Biochem 209: 284-290)

   **_No salt correction_**

2. Tm = 81.5 + 0.41(%GC) - 675/N - %mismatch
   'QuikChange' formula. Recommended (by the manufacturer) for the
   design of primers for QuikChange mutagenesis.

   **_No salt correction_**

3. Tm = 81.5 + 0.41(%GC) - 675/N + 16.6 x log[Na+]
   (Marmur & Doty 1962, J Mol Biol 5: 109-118; Schildkraut & Lifson
   1965, Biopolymers 3: 195-208)

   **_salt correction method 1_**

4. Tm = 81.5 + 0.41(%GC) - 500/N + 16.6 x log([Na+]/(1.0 + 0.7 x[Na+])) - %mismatch
   (Wetmur 1991, Crit Rev Biochem Mol Biol 126: 227-259). This is the
   standard formula in approximative mode of MELTING 4.3.

   **_salt correction method 2_**

5. Tm = 78 + 0.7(%GC) - 500/N + 16.6 x log([Na+]/(1.0 + 0.7 x [Na+])) - %mismatch
   (Wetmur 1991, Crit Rev Biochem Mol Biol 126: 227-259). For RNA.

   **_salt correction method 2_**

6. Tm = 67 + 0.8(%GC) - 500/N + 16.6 x log([Na+]/(1.0 + 0.7 x [Na+])) - %mismatch
   (Wetmur 1991, Crit Rev Biochem Mol Biol 126: 227-259). For RNA/DNA
   hybrids.

   **_salt correction method 2_**

7. Tm = 81.5 + 0.41(%GC) - 600/N + 16.6 x log[Na+]
   Used by Primer3Plus to calculate the product Tm. Default set.

   **_salt correction method 1_**

8. Tm = 77.1 + 0.41(%GC) - 528/N + 11.7 x log[Na+]
   (von Ahsen et al. 2001, Clin Chem 47: 1956-1961). Recommended 'as a
   tradeoff between accuracy and ease of use'.
   
   **_salt correction method 4_**


While formulas in the source code line 795-818 don't correspond to the above one,

```
        if valueset == 1:
            A, B, C, D = (69.3, 0.41, 650, 1)
            saltcorr = 0
        if valueset == 2:
            A, B, C, D = (81.5, 0.41, 675, 1)
            saltcorr = 0
        if valueset == 3:
            A, B, C, D = (81.5, 0.41, 675, 1)
            saltcorr = 2
        if valueset == 4:
            A, B, C, D = (81.5, 0.41, 500, 1)
            saltcorr = 3
        if valueset == 5:
            A, B, C, D = (78.0, 0.7, 500, 1)
            saltcorr = 3
        if valueset == 6:
            A, B, C, D = (67.0, 0.8, 500, 1)
            saltcorr = 3
        if valueset == 7:
            A, B, C, D = (81.5, 0.41, 600, 1)
            saltcorr = 2
        if valueset == 8:
            A, B, C, D = (77.1, 0.41, 528, 1)
            saltcorr = 4
```

should the `saltcorr` parameters be like this?

```
        if valueset == 1:
            A, B, C, D = (69.3, 0.41, 650, 1)
            saltcorr = 0
        if valueset == 2:
            A, B, C, D = (81.5, 0.41, 675, 1)
            saltcorr = 0
        if valueset == 3:
            A, B, C, D = (81.5, 0.41, 675, 1)
            saltcorr = 1
        if valueset == 4:
            A, B, C, D = (81.5, 0.41, 500, 1)
            saltcorr = 2
        if valueset == 5:
            A, B, C, D = (78.0, 0.7, 500, 1)
            saltcorr = 2
        if valueset == 6:
            A, B, C, D = (67.0, 0.8, 500, 1)
            saltcorr = 2
        if valueset == 7:
            A, B, C, D = (81.5, 0.41, 600, 1)
            saltcorr = 1
        if valueset == 8:
            A, B, C, D = (77.1, 0.41, 528, 1)
            saltcorr = 4
```





Discussion:
The constants A, B, C, and D look the same to me - you think some of the ``saltcorr`` values are wrong? It does look odd that ``saltcorr = 1`` is never used despite the text.

Those magic numbers might deserve to be named constants in the Python code, that should improve the code readability too.
@JunhuiLi1017 Thanks, I'll have a look into it.
> Those magic numbers might deserve to be named constants in the Python code, that should improve the code
> readability too.

You mean the `valuesets` or the salt-correction methods? I guess you mean the latter. What do you have in mind, something like 'author-abbreviation_year', e.g., `SCHILDKR_65 = 1` 
I meant the salt-correction methods, but you may be right there is no obvious naming as they are not unique to any one author.
@MarkusPiotrowski @peterjc Thanks! I meant the `saltcorr` methods. From the formulas in source code line 736-760, the `saltcorr` parameter in line 795-818 seems to be saltcorr=0,0,1,2,2,2,1,4 instead of saltcorr=0,0,2,3,3,3,2,4.


Resolving patch:
diff --git a/Bio/SeqUtils/MeltingTemp.py b/Bio/SeqUtils/MeltingTemp.py
--- a/Bio/SeqUtils/MeltingTemp.py
+++ b/Bio/SeqUtils/MeltingTemp.py
@@ -62,7 +62,7 @@
     >>> print('%0.2f' % mt.Tm_Wallace(myseq))
     84.00
     >>> print('%0.2f' % mt.Tm_GC(myseq))
-    58.73
+    58.97
     >>> print('%0.2f' % mt.Tm_NN(myseq))
     60.32
 
@@ -766,7 +766,7 @@ def Tm_GC(
        concentration is calculated and used for salt correction (von Ahsen et
        al., 2001).
      - saltcorr: Type of salt correction (see method salt_correction).
-       Default=5. 0 or None means no salt correction.
+       Default=0. 0 or None means no salt correction.
      - mismatch: If 'True' (default) every 'X' in the sequence is counted as
        mismatch.
 
@@ -800,19 +800,19 @@ def Tm_GC(
             saltcorr = 0
         if valueset == 3:
             A, B, C, D = (81.5, 0.41, 675, 1)
-            saltcorr = 2
+            saltcorr = 1
         if valueset == 4:
             A, B, C, D = (81.5, 0.41, 500, 1)
-            saltcorr = 3
+            saltcorr = 2
         if valueset == 5:
             A, B, C, D = (78.0, 0.7, 500, 1)
-            saltcorr = 3
+            saltcorr = 2
         if valueset == 6:
             A, B, C, D = (67.0, 0.8, 500, 1)
-            saltcorr = 3
+            saltcorr = 2
         if valueset == 7:
             A, B, C, D = (81.5, 0.41, 600, 1)
-            saltcorr = 2
+            saltcorr = 1
         if valueset == 8:
             A, B, C, D = (77.1, 0.41, 528, 1)
             saltcorr = 4


Test patch: