Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GC Clamp Property Added to Primer Class #32

Merged
merged 8 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Added
- `equality` operator overload
- `gc_clamp` property
## [0.1] - 2024-11-27
### Added
- `MeltingTemperature` enum
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@
>>> primer1.gc_content
0.5217391304347826
```
#### GC clamp
```pycon
>>> primer1.gc_clamp
1
```
#### Melting temperature
```pycon
>>> primer1.melting_temperature()
Expand Down
16 changes: 16 additions & 0 deletions opr/functions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
"""OPR functions."""
from .params import A_WEIGHT, T_WEIGHT, C_WEIGHT, G_WEIGHT, ANHYDROUS_MOLECULAR_WEIGHT_CONSTANT
from .params import PRIMER_SEQUENCE_VALID_RANGE_FOR_GC_CLAMP_WARNING
from warnings import warn
sepandhaghighi marked this conversation as resolved.
Show resolved Hide resolved


def molecular_weight_calc(sequence):
Expand Down Expand Up @@ -36,3 +38,17 @@ def basic_melting_temperature_calc(sequence):
else:
melting_temperature = 64.9 + 41 * ((g_count + c_count - 16.4) / (a_count + t_count + g_count + c_count))
return melting_temperature


def gc_clamp_calc(sequence):
"""
Calculate GC clamp.

:param sequence: primer nucleotides sequence
sepandhaghighi marked this conversation as resolved.
Show resolved Hide resolved
:type sequence: str
:return: Number of guanine (G) or cytosine (C) bases in the last 5 bases of a primer.
sepandhaghighi marked this conversation as resolved.
Show resolved Hide resolved
"""
if len(sequence) < 5:
warn(PRIMER_SEQUENCE_VALID_RANGE_FOR_GC_CLAMP_WARNING, RuntimeWarning)
sepandhaghighi marked this conversation as resolved.
Show resolved Hide resolved
return 0
return sequence[-5:].count('G') + sequence[-5:].count('C')
1 change: 1 addition & 0 deletions opr/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
PRIMER_SEQUENCE_LENGTH_WARNING = "The recommended range for primer length is between 18 and 30."
PRIMER_SEQUENCE_VALID_BASES_ERROR = "Primer sequence should only contain the nucleotide bases A, T, C, and G."
PRIMER_SEQUENCE_VALID_GC_CONTENT_RANGE_WARNING = "The recommended range for GC content is between 30% and 80%."
PRIMER_SEQUENCE_VALID_RANGE_FOR_GC_CLAMP_WARNING = "The primer sequence should have at least 5 bases. GC clamp is set to 0."
PRIMER_READ_ONLY_ATTRIBUTE_ERROR = "This attribute is read-only."
PRIMER_NOT_REMOVABLE_ATTRIBUTE_ERROR = "This attribute is not removable."

Expand Down
22 changes: 21 additions & 1 deletion opr/primer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .params import DNA_COMPLEMENT_MAP
from .params import PRIMER_ADDITION_ERROR, PRIMER_MULTIPLICATION_ERROR
from .params import PRIMER_MELTING_TEMPERATURE_NOT_IMPLEMENTED_ERROR
from .functions import molecular_weight_calc, basic_melting_temperature_calc
from .functions import molecular_weight_calc, basic_melting_temperature_calc, gc_clamp_calc


class MeltingTemperature(Enum):
Expand Down Expand Up @@ -40,6 +40,7 @@ def __init__(self, sequence):
self._sequence = Primer.validate_primer(sequence)
self._molecular_weight = None
self._gc_content = None
self._gc_clamp = None
self._melting_temperature = {
MeltingTemperature.BASIC: None,
MeltingTemperature.SALT_ADJUSTED: None,
Expand Down Expand Up @@ -197,6 +198,25 @@ def gc_content(self, _):
def gc_content(self, _):
raise OPRBaseError(PRIMER_NOT_REMOVABLE_ATTRIBUTE_ERROR)

@property
def gc_clamp(self):
"""
Calculate GC clamp of the primer.

:return: GC clamp of the primer
"""
if self._gc_clamp is None:
self._gc_clamp = gc_clamp_calc(self._sequence)
return self._gc_clamp

@gc_clamp.setter
def gc_clamp(self, _):
raise OPRBaseError(PRIMER_READ_ONLY_ATTRIBUTE_ERROR)

@gc_clamp.deleter
def gc_clamp(self, _):
raise OPRBaseError(PRIMER_NOT_REMOVABLE_ATTRIBUTE_ERROR)

def melting_temperature(self, method=MeltingTemperature.BASIC):
"""
Calculate(if needed) the melting temperature.
Expand Down
8 changes: 8 additions & 0 deletions tests/test_calculations.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ def test_gc_content_3(): #Reference: https://jamiemcgowan.ie/bioinf/gc_content.h
oprimer = Primer("ATTTTTT")
assert oprimer.gc_content == 0

def test_gc_clamp_1(): #Reference: https://www.oligoevaluator.com/OligoCalcServlet
oprimer = Primer("ATCGATCGATCGATCGATCG")
sepandhaghighi marked this conversation as resolved.
Show resolved Hide resolved
assert oprimer.gc_clamp == 2

def test_gc_clamp_2(): #Reference: https://www.oligoevaluator.com/OligoCalcServlet
sepandhaghighi marked this conversation as resolved.
Show resolved Hide resolved
oprimer = Primer("ATCG")
assert oprimer.gc_clamp == 0

sepandhaghighi marked this conversation as resolved.
Show resolved Hide resolved
def test_melt_temp_1(): #Reference: http://biotools.nubic.northwestern.edu/OligoCalc.html
oprimer = Primer("ATCGATCGATCGATCGATCG")
basic_melt_temp = oprimer.melting_temperature(MeltingTemperature.BASIC)
Expand Down
Loading