Skip to content

Commit

Permalink
Feature/melting temp (#19)
Browse files Browse the repository at this point in the history
* MeltingTemperatureMode enum added

* Melting Temperature basic calculations added to Primer

* add warning message of not-supported methods for melting temperature calculation

* tests for basic melting temperature calculations added

* `CHANGELOG.md` updated

* autopep8.sh applied

* feedback applied

* feedback applied

* feedback applied
  • Loading branch information
AHReccese authored Oct 8, 2024
1 parent a36ced3 commit a058118
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Changed
## [0.1] - 2024-06-05
### Added
- MeltingTemperature enum
- Basic melting temperature calculation
- `addition` and `multipication` operators overload
- `len` magic overload
- `Primer` class
Expand Down
2 changes: 2 additions & 0 deletions opr/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@

PRIMER_ADDITION_ERROR = "You can only add two Primer objects."
PRIMER_MULTIPICATION_ERROR = "The primer sequence can only be multiplied by an integer."

PRIMER_SUPPORTED_MELTING_TEMPERATURE_CALCULATIONS = "This version currently supports only the Basic calculation for Melting Temperature."
54 changes: 52 additions & 2 deletions opr/primer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
"""OPR primer."""
from enum import Enum
from warnings import warn
from .errors import OPRBaseError
from .params import VALID_BASES
Expand All @@ -9,6 +10,15 @@
from .params import A_WEIGHT, T_WEIGHT, C_WEIGHT, G_WEIGHT, ANHYDROUS_MOLECULAR_WEIGHT_CONSTANT
from .params import DNA_COMPLEMENT_MAP
from .params import PRIMER_ADDITION_ERROR, PRIMER_MULTIPICATION_ERROR
from .params import PRIMER_SUPPORTED_MELTING_TEMPERATURE_CALCULATIONS


class MeltingTemperature(Enum):
"""Mode used to calculate the Melting Temperature of the Primer accordingly."""

BASIC = 1
SALT_ADJUSTED = 2
NEAREST_NEIGHBOR = 3


class Primer:
Expand All @@ -30,6 +40,11 @@ def __init__(self, primer_sequence):
self._sequence = Primer.validate_primer(primer_sequence)
self._molecular_weight = None
self._gc_content = None
self._melting_temperature = {
MeltingTemperature.BASIC: None,
MeltingTemperature.SALT_ADJUSTED: None,
MeltingTemperature.NEAREST_NEIGHBOR: None,
}

def __len__(self):
"""
Expand Down Expand Up @@ -144,8 +159,8 @@ def molecular_weight(self):
c_count = self._sequence.count('C')
g_count = self._sequence.count('G')
# Anhydrous Molecular Weight = (An x 313.21) + (Tn x 304.2) + (Cn x 289.18) + (Gn x 329.21) - 61.96
self._molecular_weight = (a_count * A_WEIGHT) + (t_count * T_WEIGHT) + (c_count * \
C_WEIGHT) + (g_count * G_WEIGHT) - ANHYDROUS_MOLECULAR_WEIGHT_CONSTANT
self._molecular_weight = (a_count * A_WEIGHT) + (t_count * T_WEIGHT) + (c_count *
C_WEIGHT) + (g_count * G_WEIGHT) - ANHYDROUS_MOLECULAR_WEIGHT_CONSTANT
return self._molecular_weight

@molecular_weight.setter
Expand Down Expand Up @@ -177,3 +192,38 @@ def gc_content(self, _):
@gc_content.deleter
def gc_content(self, _):
raise OPRBaseError(PRIMER_NOT_REMOVABLE_ATTRIBUTE_ERROR)

def melting_temperature(self, method=MeltingTemperature.BASIC):
"""
Calculate(if needed) the melting temperature.
:param method: requested calculation mode for melting temperature
:type method: MeltingTemperature
:return: approximated melting temperature
"""
if self._melting_temperature[method] != None:
return self._melting_temperature[method]
a_count = self._sequence.count('A')
t_count = self._sequence.count('T')
c_count = self._sequence.count('C')
g_count = self._sequence.count('G')
if method == MeltingTemperature.BASIC:
if len(self) <= 13:
# 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
# [PubMed]).
self._melting_temperature[MeltingTemperature.BASIC] = (
a_count + t_count) * 2 + (g_count + c_count) * 4
else:
# 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)
self._melting_temperature[MeltingTemperature.BASIC] = 64.9 + 41 * \
((g_count + c_count - 16.4) / (a_count + t_count + g_count + c_count))
else:
raise(NotImplementedError(PRIMER_SUPPORTED_MELTING_TEMPERATURE_CALCULATIONS))
return self._melting_temperature[method]
13 changes: 11 additions & 2 deletions tests/test_calculations.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
from opr import Primer
from opr.primer import MeltingTemperature

TEST_CASE_NAME = "Calculations tests"

def test_mwc():
oprimer = Primer("ATCGATCGATCGATCGAT")
assert round(oprimer.molecular_weight, 1) == 5498.7


def test_gc_content_1(): #Reference: https://jamiemcgowan.ie/bioinf/gc_content.html
oprimer = Primer("ATCG")
assert oprimer.gc_content == 0.5


def test_gc_content_2(): #Reference: https://jamiemcgowan.ie/bioinf/gc_content.html
oprimer = Primer("ATTCG")
assert oprimer.gc_content == 0.4

def test_gc_content_3(): #Reference: https://jamiemcgowan.ie/bioinf/gc_content.html
oprimer = Primer("ATTTTTT")
assert oprimer.gc_content == 0

def test_melt_temp_1(): #Reference: http://biotools.nubic.northwestern.edu/OligoCalc.html
oprimer = Primer("ATCGATCGATCGATCGATCG")
basic_melt_temp = oprimer.melting_temperature(MeltingTemperature.BASIC)
assert round(basic_melt_temp,1) == 51.8

def test_melt_temp_2(): #Reference: http://biotools.nubic.northwestern.edu/OligoCalc.html
oprimer = Primer("ATCG")
basic_melt_temp = oprimer.melting_temperature(method=MeltingTemperature.BASIC)
assert round(basic_melt_temp,1) == 12

0 comments on commit a058118

Please sign in to comment.