Skip to content

Commit

Permalink
optimisation for #237
Browse files Browse the repository at this point in the history
  • Loading branch information
manulera authored and BjornFJohansson committed Aug 8, 2024
1 parent 8f30e8e commit 0cc98b0
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 16 deletions.
69 changes: 69 additions & 0 deletions example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
import requests
from pydna.design import primer_design
from pydna.dseqrecord import Dseqrecord
from pydna.tm import tm_default
import time


def primer_tm_neb(primer, conc=0.5, prodcode="q5-0"):
"""Calculates a single primers melting temp from NEB.
Parameters
----------
primer1 : str
conc : float
prodcode : str
find product codes on nebswebsite: https://tmapi.neb.com/docs/productcodes
Returns
-------
tm : int
primer melting temperature
"""

url = "https://tmapi.neb.com/tm"

params = {"seq1": primer, "conc": conc, "prodcode": prodcode}

# Mimic a browser request with this headers
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-US,en;q=0.5",
"Connection": "keep-alive",
"Referer": "https://example.com",
}
res = requests.get(url, params=params, headers=headers)
r = res.json()
print("making a request")
if r["success"]:
return r["data"]["tm1"]
else:
print("request failed")
print(r["error"][0])


start_time = time.time()
result = primer_design(
Dseqrecord("atgtcgtATGaaaccgttatcgatcatatgtGcgaaatgtcgcgcgtcatctacgtatcatcgatctactTAAacgtgta"),
limit=8,
target_tm=60,
estimate_function=tm_default,
tm_func=primer_tm_neb,
)
print("result", result.seq)
print("--- %s seconds ---" % (time.time() - start_time))


start_time = time.time()
result = primer_design(
Dseqrecord("atgtcgtATGaaaccgttatcgatcatatgtGcgaaatgtcgcgcgtcatctacgtatcatcgatctactTAAacgtgta"),
limit=8,
target_tm=60,
tm_func=primer_tm_neb,
)
print("result", result.seq)
print("--- %s seconds ---" % (time.time() - start_time))
54 changes: 38 additions & 16 deletions src/pydna/design.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,44 @@
from pydna.dseqrecord import Dseqrecord as _Dseqrecord
from pydna.primer import Primer as _Primer
import logging as _logging
import operator as _operator

_module_logger = _logging.getLogger("pydna." + __name__)


def primer_design(template, fp=None, rp=None, limit=13, target_tm=55.0, tm_func=_tm_default, **kwargs):
def get_tm_and_primer(target_tm, template, limit, tm_func, starting_temp=0) -> tuple[float, str]:
"""returns a string"""
tmp = starting_temp
length = limit
tlen = len(template)
p = str(template.seq[:length])

if starting_temp < target_tm:
condition = _operator.le
increment = 1
else:
condition = _operator.ge
increment = -1
while condition(tmp, target_tm):
length += increment
p = str(template.seq[:length])
tmp = tm_func(p)
if length >= tlen or length == 0:
break
ps = p[:-1]
tmps = tm_func(str(ps))
_module_logger.debug(((p, tmp), (ps, tmps)))
return min((abs(target_tm - tmp), p), (abs(target_tm - tmps), ps))


def get_tm_and_primer_with_estimate(target_tm, template, limit, tm_func, estimate_function):
first_temp, first_guess = get_tm_and_primer(target_tm, template, limit, estimate_function)
return get_tm_and_primer(target_tm, template, len(first_guess), tm_func, first_temp)


def primer_design(
template, fp=None, rp=None, limit=13, target_tm=55.0, tm_func=_tm_default, estimate_function=None, **kwargs
):
"""This function designs a forward primer and a reverse primer for PCR amplification
of a given template sequence.
Expand Down Expand Up @@ -118,21 +151,10 @@ def primer_design(template, fp=None, rp=None, limit=13, target_tm=55.0, tm_func=
"""

def design(target_tm, template):
"""returns a string"""
tmp = 0
length = limit
tlen = len(template)
p = str(template.seq[:length])
while tmp < target_tm:
length += 1
p = str(template.seq[:length])
tmp = tm_func(p)
if length >= tlen:
break
ps = p[:-1]
tmps = tm_func(str(ps))
_module_logger.debug(((p, tmp), (ps, tmps)))
return min((abs(target_tm - tmp), p), (abs(target_tm - tmps), ps))[1]
if estimate_function:
return get_tm_and_primer_with_estimate(target_tm, template, limit, tm_func, estimate_function)[1]
else:
return get_tm_and_primer(target_tm, template, limit, tm_func)[1]

if not fp and not rp:
_module_logger.debug("no primer given, design forward primer:")
Expand Down

0 comments on commit 0cc98b0

Please sign in to comment.