opencloning 0.4.5__tar.gz → 0.4.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {opencloning-0.4.5 → opencloning-0.4.7}/PKG-INFO +1 -1
- {opencloning-0.4.5 → opencloning-0.4.7}/pyproject.toml +1 -1
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/ebic/primer_design.py +9 -15
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/endpoints/primer_design.py +48 -53
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/http_client.py +0 -1
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/ncbi_requests.py +7 -1
- opencloning-0.4.7/src/opencloning/primer3_functions.py +109 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/primer_design.py +8 -9
- opencloning-0.4.5/src/opencloning/batch_cloning/EBIC/barcode.gb +0 -23
- opencloning-0.4.5/src/opencloning/batch_cloning/EBIC/common_plasmid.gb +0 -218
- opencloning-0.4.5/src/opencloning/batch_cloning/EBIC/example.py +0 -180
- opencloning-0.4.5/src/opencloning/batch_cloning/EBIC/primer_design_settings.py +0 -38
- opencloning-0.4.5/src/opencloning/ebic/__init__.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/LICENSE +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/README.md +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/__init__.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/_version.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/api_config_utils.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/app_settings.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/__init__.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/index.html +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/pombe/__init__.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/pombe/index.html +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/pombe/pombe_clone.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/pombe/pombe_gather.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/pombe/pombe_get_primers.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/pombe/pombe_summary.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/ziqiang_et_al2024/__init__.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/ziqiang_et_al2024/index.html +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/ziqiang_et_al2024/ziqiang_et_al2024.json +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/bug_fixing/README.md +0 -0
- {opencloning-0.4.5/src/opencloning/batch_cloning/EBIC → opencloning-0.4.7/src/opencloning/bug_fixing}/__init__.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/bug_fixing/backend_v0_3.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/cre_lox.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/dna_functions.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/dna_utils.py +0 -0
- {opencloning-0.4.5/src/opencloning/bug_fixing → opencloning-0.4.7/src/opencloning/ebic}/__init__.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/ebic/primer_design_settings.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/endpoints/annotation.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/endpoints/assembly.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/endpoints/external_import.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/endpoints/no_assembly.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/endpoints/no_input.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/endpoints/other.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/gateway.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/get_router.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/main.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/pydantic_models.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/request_examples.py +0 -0
- {opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/utils.py +0 -0
|
@@ -8,7 +8,7 @@ authors = ["Manuel Lera-Ramirez <manulera14@gmail.com>"]
|
|
|
8
8
|
description = "Backend of OpenCloning, a web application to generate molecular cloning strategies in json format, and share them with others."
|
|
9
9
|
license = "MIT"
|
|
10
10
|
name = "opencloning"
|
|
11
|
-
version = "0.4.
|
|
11
|
+
version = "0.4.7"
|
|
12
12
|
package-mode = true
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
repository = "https://github.com/manulera/OpenCloning_backend"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from pydna.dseqrecord import Dseqrecord
|
|
2
2
|
from Bio.SeqFeature import SimpleLocation
|
|
3
|
-
from
|
|
3
|
+
from ..primer3_functions import primer3_design_primers
|
|
4
4
|
|
|
5
5
|
from ..pydantic_models import PrimerModel
|
|
6
6
|
from .primer_design_settings import amanda_settings
|
|
@@ -13,23 +13,13 @@ adapter_right_fwd = 'ataGGTCTCtGCTT'
|
|
|
13
13
|
adapter_right_rvs = 'ataGGTCTCtAGCG'
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def call_primer3(seq: str, seq_args: dict):
|
|
17
|
-
report = bindings.design_primers(
|
|
18
|
-
seq_args={
|
|
19
|
-
'SEQUENCE_ID': 'MH1000',
|
|
20
|
-
'SEQUENCE_TEMPLATE': seq,
|
|
21
|
-
**seq_args,
|
|
22
|
-
},
|
|
23
|
-
global_args=amanda_settings,
|
|
24
|
-
)
|
|
25
|
-
return report
|
|
26
|
-
|
|
27
|
-
|
|
28
16
|
def ebic_primers(
|
|
29
17
|
input_seq: Dseqrecord,
|
|
30
18
|
location: SimpleLocation,
|
|
31
19
|
max_inside: int,
|
|
32
20
|
max_outside: int,
|
|
21
|
+
target_tm: float,
|
|
22
|
+
target_tm_tolerance: float,
|
|
33
23
|
) -> tuple[PrimerModel, PrimerModel, PrimerModel, PrimerModel]:
|
|
34
24
|
"""Design primers for EBIC"""
|
|
35
25
|
|
|
@@ -53,9 +43,13 @@ def ebic_primers(
|
|
|
53
43
|
'SEQUENCE_PRIMER_PAIR_OK_REGION_LIST': f'0,{max_outside + max_inside},{len(right_template) - int(padding/2)},{int(padding/2)}',
|
|
54
44
|
}
|
|
55
45
|
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
global_args = amanda_settings.copy()
|
|
47
|
+
global_args['PRIMER_OPT_TM'] = target_tm
|
|
48
|
+
global_args['PRIMER_MIN_TM'] = target_tm - target_tm_tolerance
|
|
49
|
+
global_args['PRIMER_MAX_TM'] = target_tm + target_tm_tolerance
|
|
58
50
|
|
|
51
|
+
report_left = primer3_design_primers(left_template, seq_args_left, global_args)
|
|
52
|
+
report_right = primer3_design_primers(right_template, seq_args_right, global_args)
|
|
59
53
|
primer_names = ['left_fwd', 'left_rvs', 'right_fwd', 'right_rvs']
|
|
60
54
|
primer_seqs = [
|
|
61
55
|
adapter_left_fwd + report_left['PRIMER_LEFT'][0]['SEQUENCE'],
|
|
@@ -3,8 +3,6 @@ from pydantic import create_model
|
|
|
3
3
|
import re
|
|
4
4
|
from Bio.Restriction import RestrictionBatch
|
|
5
5
|
from Bio.SeqUtils import gc_fraction
|
|
6
|
-
from primer3 import bindings
|
|
7
|
-
from itertools import product
|
|
8
6
|
|
|
9
7
|
from ..dna_functions import get_invalid_enzyme_names
|
|
10
8
|
from ..pydantic_models import PrimerModel, PrimerDesignQuery
|
|
@@ -14,6 +12,14 @@ from ..primer_design import (
|
|
|
14
12
|
gibson_assembly_primers,
|
|
15
13
|
simple_pair_primers,
|
|
16
14
|
)
|
|
15
|
+
from ..primer3_functions import (
|
|
16
|
+
primer3_calc_tm,
|
|
17
|
+
PrimerDesignSettings,
|
|
18
|
+
primer3_calc_homodimer,
|
|
19
|
+
primer3_calc_hairpin,
|
|
20
|
+
primer3_calc_heterodimer,
|
|
21
|
+
ThermodynamicResult,
|
|
22
|
+
)
|
|
17
23
|
from ..get_router import get_router
|
|
18
24
|
from ..ebic.primer_design import ebic_primers
|
|
19
25
|
from pydantic import BaseModel
|
|
@@ -45,6 +51,9 @@ def validate_spacers(spacers: list[str] | None, nb_templates: int, circular: boo
|
|
|
45
51
|
async def primer_design_homologous_recombination(
|
|
46
52
|
pcr_template: PrimerDesignQuery,
|
|
47
53
|
homologous_recombination_target: PrimerDesignQuery,
|
|
54
|
+
settings: PrimerDesignSettings = Body(
|
|
55
|
+
..., description='Primer design settings.', default_factory=PrimerDesignSettings
|
|
56
|
+
),
|
|
48
57
|
spacers: list[str] | None = Body(
|
|
49
58
|
None,
|
|
50
59
|
description='Spacers to add at the left and right side of the insertion.',
|
|
@@ -80,6 +89,7 @@ async def primer_design_homologous_recombination(
|
|
|
80
89
|
insert_forward,
|
|
81
90
|
target_tm,
|
|
82
91
|
spacers,
|
|
92
|
+
tm_func=lambda x: primer3_calc_tm(x, settings),
|
|
83
93
|
)
|
|
84
94
|
except ValueError as e:
|
|
85
95
|
raise HTTPException(400, *e.args)
|
|
@@ -93,6 +103,9 @@ async def primer_design_homologous_recombination(
|
|
|
93
103
|
@router.post('/primer_design/gibson_assembly', response_model=PrimerDesignResponse)
|
|
94
104
|
async def primer_design_gibson_assembly(
|
|
95
105
|
pcr_templates: list[PrimerDesignQuery],
|
|
106
|
+
settings: PrimerDesignSettings = Body(
|
|
107
|
+
..., description='Primer design settings.', default_factory=PrimerDesignSettings
|
|
108
|
+
),
|
|
96
109
|
spacers: list[str] | None = Body(
|
|
97
110
|
None,
|
|
98
111
|
description='Spacers to add between the restriction site and the 5\' end of the primer footprint (the part that binds the DNA).',
|
|
@@ -122,7 +135,13 @@ async def primer_design_gibson_assembly(
|
|
|
122
135
|
templates.append(template)
|
|
123
136
|
try:
|
|
124
137
|
primers = gibson_assembly_primers(
|
|
125
|
-
templates,
|
|
138
|
+
templates,
|
|
139
|
+
homology_length,
|
|
140
|
+
minimal_hybridization_length,
|
|
141
|
+
target_tm,
|
|
142
|
+
circular,
|
|
143
|
+
spacers,
|
|
144
|
+
tm_func=lambda x: primer3_calc_tm(x, settings),
|
|
126
145
|
)
|
|
127
146
|
except ValueError as e:
|
|
128
147
|
raise HTTPException(400, *e.args)
|
|
@@ -137,6 +156,9 @@ async def primer_design_simple_pair(
|
|
|
137
156
|
None,
|
|
138
157
|
description='Spacers to add between the restriction site and the 5\' end of the primer footprint (the part that binds the DNA).',
|
|
139
158
|
),
|
|
159
|
+
settings: PrimerDesignSettings = Body(
|
|
160
|
+
..., description='Primer design settings.', default_factory=PrimerDesignSettings
|
|
161
|
+
),
|
|
140
162
|
minimal_hybridization_length: int = Query(
|
|
141
163
|
..., description='The minimal length of the hybridization region in bps.'
|
|
142
164
|
),
|
|
@@ -186,6 +208,7 @@ async def primer_design_simple_pair(
|
|
|
186
208
|
spacers,
|
|
187
209
|
left_enzyme_inverted,
|
|
188
210
|
right_enzyme_inverted,
|
|
211
|
+
tm_func=lambda x: primer3_calc_tm(x, settings),
|
|
189
212
|
)
|
|
190
213
|
except ValueError as e:
|
|
191
214
|
raise HTTPException(400, *e.args)
|
|
@@ -198,11 +221,17 @@ async def primer_design_ebic(
|
|
|
198
221
|
template: PrimerDesignQuery,
|
|
199
222
|
max_inside: int = Query(..., description='The maximum length of the inside edge of the EBIC primer.'),
|
|
200
223
|
max_outside: int = Query(..., description='The maximum length of the outside edge of the EBIC primer.'),
|
|
224
|
+
target_tm: float = Query(
|
|
225
|
+
..., description='The desired melting temperature for the hybridization part of the primer.'
|
|
226
|
+
),
|
|
227
|
+
target_tm_tolerance: float = Query(
|
|
228
|
+
3, description='The tolerance for the desired melting temperature for the hybridization part of the primer.'
|
|
229
|
+
),
|
|
201
230
|
):
|
|
202
231
|
"""Design primers for EBIC"""
|
|
203
232
|
dseqr = read_dsrecord_from_json(template.sequence)
|
|
204
233
|
location = template.location.to_biopython_location()
|
|
205
|
-
return {'primers': ebic_primers(dseqr, location, max_inside, max_outside)}
|
|
234
|
+
return {'primers': ebic_primers(dseqr, location, max_inside, max_outside, target_tm, target_tm_tolerance)}
|
|
206
235
|
|
|
207
236
|
|
|
208
237
|
# @router.post('/primer_design/gateway_attB', response_model=PrimerDesignResponse)
|
|
@@ -240,32 +269,6 @@ async def primer_design_ebic(
|
|
|
240
269
|
# return {'primers': primers}
|
|
241
270
|
|
|
242
271
|
|
|
243
|
-
class ThermodynamicResult(BaseModel):
|
|
244
|
-
melting_temperature: float
|
|
245
|
-
deltaG: float
|
|
246
|
-
figure: str | None
|
|
247
|
-
|
|
248
|
-
@classmethod
|
|
249
|
-
def from_binding(cls, result):
|
|
250
|
-
return cls(
|
|
251
|
-
melting_temperature=result.tm,
|
|
252
|
-
deltaG=result.dg,
|
|
253
|
-
figure='\n'.join(result.ascii_structure_lines),
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
def get_sequence_thermodynamic_result(sequences: list[str], method: callable) -> ThermodynamicResult | None:
|
|
258
|
-
"""Get the thermodynamic result for a sequence, if the sequence is longer than primer3 60bp limit, it will be split into two
|
|
259
|
-
and the result with the lowest deltaG will be returned."""
|
|
260
|
-
results = [method(seq, output_structure=True) for seq in sequences]
|
|
261
|
-
results = [r for r in results if r.structure_found]
|
|
262
|
-
if len(results) == 0:
|
|
263
|
-
return None
|
|
264
|
-
|
|
265
|
-
result = min(results, key=lambda r: r.dg)
|
|
266
|
-
return ThermodynamicResult.from_binding(result)
|
|
267
|
-
|
|
268
|
-
|
|
269
272
|
class PrimerDetailsResponse(BaseModel):
|
|
270
273
|
melting_temperature: float
|
|
271
274
|
gc_content: float
|
|
@@ -273,20 +276,20 @@ class PrimerDetailsResponse(BaseModel):
|
|
|
273
276
|
hairpin: ThermodynamicResult | None
|
|
274
277
|
|
|
275
278
|
|
|
276
|
-
@router.
|
|
279
|
+
@router.post('/primer_details', response_model=PrimerDetailsResponse)
|
|
277
280
|
async def primer_details(
|
|
278
|
-
sequence: str =
|
|
281
|
+
sequence: str = Body(..., description='Primer sequence', pattern=r'^[ACGTacgt]+$'),
|
|
282
|
+
settings: PrimerDesignSettings = Body(
|
|
283
|
+
..., description='Primer design settings.', default_factory=PrimerDesignSettings
|
|
284
|
+
),
|
|
279
285
|
):
|
|
280
286
|
"""Get information about a primer"""
|
|
281
287
|
sequence = sequence.upper()
|
|
282
|
-
tm =
|
|
288
|
+
tm = primer3_calc_tm(sequence, settings)
|
|
283
289
|
gc_content = gc_fraction(sequence)
|
|
284
290
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
thermodynamic_sequences = [sequence[:60], sequence[-60:]]
|
|
288
|
-
homodimer = get_sequence_thermodynamic_result(thermodynamic_sequences, bindings.calc_homodimer)
|
|
289
|
-
hairpin = get_sequence_thermodynamic_result(thermodynamic_sequences, bindings.calc_hairpin)
|
|
291
|
+
homodimer = primer3_calc_homodimer(sequence, settings)
|
|
292
|
+
hairpin = primer3_calc_hairpin(sequence, settings)
|
|
290
293
|
|
|
291
294
|
return {
|
|
292
295
|
'melting_temperature': tm,
|
|
@@ -296,22 +299,14 @@ async def primer_details(
|
|
|
296
299
|
}
|
|
297
300
|
|
|
298
301
|
|
|
299
|
-
@router.
|
|
302
|
+
@router.post('/primer_heterodimer', response_model=ThermodynamicResult | None)
|
|
300
303
|
async def primer_heterodimer(
|
|
301
|
-
sequence1: str =
|
|
302
|
-
sequence2: str =
|
|
304
|
+
sequence1: str = Body(..., description='First primer sequence', pattern=r'^[ACGTacgt]+$'),
|
|
305
|
+
sequence2: str = Body(..., description='Second primer sequence', pattern=r'^[ACGTacgt]+$'),
|
|
306
|
+
settings: PrimerDesignSettings = Body(
|
|
307
|
+
..., description='Primer design settings.', default_factory=PrimerDesignSettings
|
|
308
|
+
),
|
|
303
309
|
):
|
|
304
310
|
"""Get information about a primer pair"""
|
|
305
311
|
|
|
306
|
-
|
|
307
|
-
sequence_pairs = [(sequence1, sequence2)]
|
|
308
|
-
else:
|
|
309
|
-
sequence_pairs = list(product((sequence1[:60], sequence1[-60:]), (sequence2[:60], sequence2[-60:])))
|
|
310
|
-
|
|
311
|
-
results = [bindings.calc_heterodimer(s1, s2, output_structure=True) for s1, s2 in sequence_pairs]
|
|
312
|
-
results = [r for r in results if r.structure_found]
|
|
313
|
-
if len(results) == 0:
|
|
314
|
-
return None
|
|
315
|
-
|
|
316
|
-
result = min(results, key=lambda r: r.dg)
|
|
317
|
-
return ThermodynamicResult.from_binding(result)
|
|
312
|
+
return primer3_calc_heterodimer(sequence1, sequence2, settings)
|
|
@@ -22,7 +22,6 @@ class AllowedExternalUrlsTransport(AsyncHTTPTransport):
|
|
|
22
22
|
async def handle_async_request(self, request: Request) -> Response:
|
|
23
23
|
if any(str(request.url).startswith(url) for url in allowed_external_urls):
|
|
24
24
|
return await super().handle_async_request(request)
|
|
25
|
-
print('>>>', request.url)
|
|
26
25
|
raise HTTPError(request.url, 403, f'Request to {request.url} is not allowed', None, None)
|
|
27
26
|
|
|
28
27
|
|
|
@@ -110,7 +110,13 @@ async def get_genbank_sequence(sequence_accession, start=None, end=None, strand=
|
|
|
110
110
|
|
|
111
111
|
resp = await async_get(url, headers=headers, params=params)
|
|
112
112
|
if resp.status_code == 200:
|
|
113
|
-
|
|
113
|
+
try:
|
|
114
|
+
return pydna_parse(resp.text)[0]
|
|
115
|
+
except Exception:
|
|
116
|
+
# Now the ncbi returns something like this:
|
|
117
|
+
# Example: https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=nuccore&id=blah&rettype=gbwithparts&retmode=text
|
|
118
|
+
# 'Error: F a i l e d t o u n d e r s t a n d i d : b l a h '
|
|
119
|
+
raise HTTPException(404, 'wrong sequence accession')
|
|
114
120
|
elif resp.status_code == 400:
|
|
115
121
|
raise HTTPException(404, 'wrong sequence accession')
|
|
116
122
|
elif resp.status_code == 503:
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Functions to calculate primer melting temperature using primer3.
|
|
3
|
+
primer3 should not be imported anywhere else.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
from itertools import product
|
|
8
|
+
from primer3.bindings import (
|
|
9
|
+
calc_tm as _calc_tm,
|
|
10
|
+
design_primers as _design_primers,
|
|
11
|
+
calc_homodimer as _calc_homodimer,
|
|
12
|
+
calc_hairpin as _calc_hairpin,
|
|
13
|
+
calc_heterodimer as _calc_heterodimer,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PrimerDesignSettings(BaseModel):
|
|
18
|
+
primer_dna_conc: float = Field(50, description='The DNA concentration in the primer solution (nM).')
|
|
19
|
+
primer_salt_monovalent: float = Field(
|
|
20
|
+
50, description='The monovalent salt concentration in the primer solution (mM).'
|
|
21
|
+
)
|
|
22
|
+
primer_salt_divalent: float = Field(
|
|
23
|
+
1.5, description='The divalent salt concentration in the primer solution (mM).'
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def to_primer3_args(self) -> dict:
|
|
27
|
+
"""Convert the settings to primer3 arguments."""
|
|
28
|
+
return {
|
|
29
|
+
'dna_conc': self.primer_dna_conc,
|
|
30
|
+
'mv_conc': self.primer_salt_monovalent,
|
|
31
|
+
'dv_conc': self.primer_salt_divalent,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def primer3_calc_tm(seq: str, settings: PrimerDesignSettings) -> float:
|
|
36
|
+
return _calc_tm(seq.upper(), **settings.to_primer3_args())
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def primer3_design_primers(seq: str, seq_args: dict, global_args: dict):
|
|
40
|
+
report = _design_primers(
|
|
41
|
+
seq_args={
|
|
42
|
+
'SEQUENCE_ID': 'MH1000',
|
|
43
|
+
'SEQUENCE_TEMPLATE': seq,
|
|
44
|
+
**seq_args,
|
|
45
|
+
},
|
|
46
|
+
global_args=global_args,
|
|
47
|
+
)
|
|
48
|
+
return report
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ThermodynamicResult(BaseModel):
|
|
52
|
+
melting_temperature: float
|
|
53
|
+
deltaG: float
|
|
54
|
+
figure: str | None
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def from_binding(cls, result):
|
|
58
|
+
return cls(
|
|
59
|
+
melting_temperature=result.tm,
|
|
60
|
+
deltaG=result.dg,
|
|
61
|
+
figure='\n'.join(result.ascii_structure_lines),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def get_sequence_thermodynamic_result(sequence: str, method: callable) -> ThermodynamicResult | None:
|
|
66
|
+
"""Get the thermodynamic result for a sequence, if the sequence is longer than primer3 60bp limit, it will be split into two
|
|
67
|
+
and the result with the lowest deltaG will be returned."""
|
|
68
|
+
sequence = sequence.upper()
|
|
69
|
+
if len(sequence) <= 60:
|
|
70
|
+
sequences = [sequence]
|
|
71
|
+
else:
|
|
72
|
+
sequences = [sequence[:60], sequence[-60:]]
|
|
73
|
+
|
|
74
|
+
results = [method(seq) for seq in sequences]
|
|
75
|
+
results = [r for r in results if r.structure_found]
|
|
76
|
+
if len(results) == 0:
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
result = min(results, key=lambda r: r.dg)
|
|
80
|
+
return ThermodynamicResult.from_binding(result)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def primer3_calc_homodimer(seq: str, settings: PrimerDesignSettings) -> ThermodynamicResult:
|
|
84
|
+
return get_sequence_thermodynamic_result(
|
|
85
|
+
seq, lambda x: _calc_homodimer(x, output_structure=True, **settings.to_primer3_args())
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def primer3_calc_hairpin(seq: str, settings: PrimerDesignSettings) -> ThermodynamicResult:
|
|
90
|
+
return get_sequence_thermodynamic_result(
|
|
91
|
+
seq, lambda x: _calc_hairpin(x, output_structure=True, **settings.to_primer3_args())
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def primer3_calc_heterodimer(seq1: str, seq2: str, settings: PrimerDesignSettings) -> ThermodynamicResult:
|
|
96
|
+
if len(seq1) <= 60 or len(seq2) <= 60:
|
|
97
|
+
sequence_pairs = [(seq1, seq2)]
|
|
98
|
+
else:
|
|
99
|
+
sequence_pairs = list(product((seq1[:60], seq1[-60:]), (seq2[:60], seq2[-60:])))
|
|
100
|
+
|
|
101
|
+
results = [
|
|
102
|
+
_calc_heterodimer(s1, s2, output_structure=True, **settings.to_primer3_args()) for s1, s2 in sequence_pairs
|
|
103
|
+
]
|
|
104
|
+
results = [r for r in results if r.structure_found]
|
|
105
|
+
if len(results) == 0:
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
result = min(results, key=lambda r: r.dg)
|
|
109
|
+
return ThermodynamicResult.from_binding(result)
|
|
@@ -7,13 +7,8 @@ from .pydantic_models import PrimerModel
|
|
|
7
7
|
from Bio.Seq import reverse_complement
|
|
8
8
|
from Bio.Restriction.Restriction import RestrictionType
|
|
9
9
|
from Bio.Data.IUPACData import ambiguous_dna_values as _ambiguous_dna_values
|
|
10
|
-
from primer3.bindings import calc_tm as _calc_tm
|
|
11
10
|
from typing import Callable
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def primer3_calc_tm(seq: str) -> float:
|
|
15
|
-
return _calc_tm(seq.upper())
|
|
16
|
-
|
|
11
|
+
from .primer3_functions import primer3_calc_tm, PrimerDesignSettings
|
|
17
12
|
|
|
18
13
|
ambiguous_dna_values = _ambiguous_dna_values.copy()
|
|
19
14
|
# Remove acgt
|
|
@@ -21,6 +16,10 @@ for base in 'ACGT':
|
|
|
21
16
|
del ambiguous_dna_values[base]
|
|
22
17
|
|
|
23
18
|
|
|
19
|
+
def default_tm_func(sequence: str) -> float:
|
|
20
|
+
return primer3_calc_tm(sequence, PrimerDesignSettings())
|
|
21
|
+
|
|
22
|
+
|
|
24
23
|
def homologous_recombination_primers(
|
|
25
24
|
pcr_seq: Dseqrecord,
|
|
26
25
|
pcr_loc: SimpleLocation,
|
|
@@ -31,7 +30,7 @@ def homologous_recombination_primers(
|
|
|
31
30
|
insert_forward: bool,
|
|
32
31
|
target_tm: float,
|
|
33
32
|
spacers: list[str] | None = None,
|
|
34
|
-
tm_func: Callable[[str], float] =
|
|
33
|
+
tm_func: Callable[[str], float] = default_tm_func,
|
|
35
34
|
estimate_function: Callable[[str], float] | None = None,
|
|
36
35
|
) -> tuple[str, str]:
|
|
37
36
|
|
|
@@ -91,7 +90,7 @@ def gibson_assembly_primers(
|
|
|
91
90
|
target_tm: float,
|
|
92
91
|
circular: bool,
|
|
93
92
|
spacers: list[str] | None = None,
|
|
94
|
-
tm_func: Callable[[str], float] =
|
|
93
|
+
tm_func: Callable[[str], float] = default_tm_func,
|
|
95
94
|
estimate_function: Callable[[str], float] | None = None,
|
|
96
95
|
) -> list[PrimerModel]:
|
|
97
96
|
|
|
@@ -157,7 +156,7 @@ def simple_pair_primers(
|
|
|
157
156
|
spacers: list[str] | None = None,
|
|
158
157
|
left_enzyme_inverted: bool = False,
|
|
159
158
|
right_enzyme_inverted: bool = False,
|
|
160
|
-
tm_func: Callable[[str], float] =
|
|
159
|
+
tm_func: Callable[[str], float] = default_tm_func,
|
|
161
160
|
estimate_function: Callable[[str], float] | None = None,
|
|
162
161
|
) -> tuple[PrimerModel, PrimerModel]:
|
|
163
162
|
"""
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
LOCUS barcode 151 bp DNA linear UNA 15-SEP-2024
|
|
2
|
-
DEFINITION natural linear DNA
|
|
3
|
-
ACCESSION .
|
|
4
|
-
VERSION .
|
|
5
|
-
KEYWORDS .
|
|
6
|
-
SOURCE natural DNA sequence
|
|
7
|
-
ORGANISM unspecified
|
|
8
|
-
REFERENCE 1 (bases 1 to 151)
|
|
9
|
-
AUTHORS SnapGene License
|
|
10
|
-
TITLE Direct Submission
|
|
11
|
-
JOURNAL Exported Dec 20, 2024 from SnapGene 7.2.1
|
|
12
|
-
https://www.snapgene.com
|
|
13
|
-
FEATURES Location/Qualifiers
|
|
14
|
-
source 1..151
|
|
15
|
-
/mol_type="genomic DNA"
|
|
16
|
-
/organism="unspecified"
|
|
17
|
-
misc_feature 15..137
|
|
18
|
-
/label=CG_Barcode1
|
|
19
|
-
ORIGIN
|
|
20
|
-
1 ataggtctct aatggctctt attcgggaca tttacaatgc cacccactgg gagtgattat
|
|
21
|
-
61 gagtctcatt gagactgctc accacagcat gaattctctg gttcggtggc gcatagctat
|
|
22
|
-
121 cgctgttcct gccactggct tagagaccta t
|
|
23
|
-
//
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
LOCUS KanSacB+Scarlett 5747 bp DNA circular SYN 08-AUG-2024
|
|
2
|
-
DEFINITION synthetic circular DNA
|
|
3
|
-
ACCESSION .
|
|
4
|
-
VERSION .
|
|
5
|
-
KEYWORDS .
|
|
6
|
-
SOURCE synthetic DNA construct
|
|
7
|
-
ORGANISM recombinant plasmid
|
|
8
|
-
REFERENCE 1 (bases 1 to 5747)
|
|
9
|
-
AUTHORS SnapGene License
|
|
10
|
-
TITLE Direct Submission
|
|
11
|
-
JOURNAL Exported Dec 20, 2024 from SnapGene 7.2.1
|
|
12
|
-
https://www.snapgene.com
|
|
13
|
-
FEATURES Location/Qualifiers
|
|
14
|
-
source 1..5747
|
|
15
|
-
/mol_type="other DNA"
|
|
16
|
-
/organism="recombinant plasmid"
|
|
17
|
-
misc_feature 1..4
|
|
18
|
-
/label=AATG
|
|
19
|
-
/note="/color=#f7e8f7"
|
|
20
|
-
misc_feature 5..2586
|
|
21
|
-
/label=From pC0.026
|
|
22
|
-
/note="/color=white"
|
|
23
|
-
/note="/indicates_part=True"
|
|
24
|
-
/note="/source=pC0.026"
|
|
25
|
-
promoter 5..450
|
|
26
|
-
/gene="sacR"
|
|
27
|
-
/label=sacB promoter
|
|
28
|
-
/note="sacB promoter and control region"
|
|
29
|
-
CDS 451..1872
|
|
30
|
-
/codon_start=1
|
|
31
|
-
/gene="Bacillus subtilis sacB"
|
|
32
|
-
/product="secreted levansucrase that renders
|
|
33
|
-
bacterialgrowth sensitive to sucrose"
|
|
34
|
-
/label=SacB
|
|
35
|
-
/note="negative selection marker"
|
|
36
|
-
/translation="MNIKKFAKQATVLTFTTALLAGGATQAFAKETNQKPYKETYGISH
|
|
37
|
-
ITRHDMLQIPEQQKNEKYQVPEFDSSTIKNISSAKGLDVWDSWPLQNADGTVANYHGYH
|
|
38
|
-
IVFALAGDPKNADDTSIYMFYQKVGETSIDSWKNAGRVFKDSDKFDANDSILKDQTQEW
|
|
39
|
-
SGSATFTSDGKIRLFYTDFSGKHYGKQTLTTAQVNVSASDSSLNINGVEDYKSIFDGDG
|
|
40
|
-
KTYQNVQQFIDEGNYSSGDNHTLRDPHYVEDKGHKYLVFEANTGTEDGYQGEESLFNKA
|
|
41
|
-
YYGKSTSFFRQESQKLLQSDKKRTAELANGALGMIELNDDYTLKKVMKPLIASNTVTDE
|
|
42
|
-
IERANVFKMNGKWYLFTDSRGSKMTIDGITSNDIYMLGYVSNSLTGPYKPLNKTGLVLK
|
|
43
|
-
MDLDPNDVTFTYSHFAVPQAKGNNVVITSYMTNRGFYADKQSTFAPSFLLNIKGKKTSV
|
|
44
|
-
VKDSILEQGQLTVNK"
|
|
45
|
-
misc_feature 2587..2590
|
|
46
|
-
/label=AGGT
|
|
47
|
-
/note="/color=#f7e8f7"
|
|
48
|
-
misc_feature 2591..3800
|
|
49
|
-
/label=From pC0.027
|
|
50
|
-
/note="/color=white"
|
|
51
|
-
/note="/indicates_part=True"
|
|
52
|
-
/note="/source=pC0.027"
|
|
53
|
-
CDS complement(2875..3690)
|
|
54
|
-
/codon_start=1
|
|
55
|
-
/gene="aph(3')-Ia"
|
|
56
|
-
/product="aminoglycoside phosphotransferase"
|
|
57
|
-
/label=KanR
|
|
58
|
-
/note="confers resistance to kanamycin in bacteria or
|
|
59
|
-
G418(Geneticin(R)) in eukaryotes"
|
|
60
|
-
/translation="MSHIQRETSCSRPRLNSNMDADLYGYKWARDNVGQSGATIYRLYG
|
|
61
|
-
KPDAPELFLKHGKGSVANDVTDEMVRLNWLTEFMPLPTIKHFIRTPDDAWLLTTAIPGK
|
|
62
|
-
TAFQVLEEYPDSGENIVDALAVFLRRLHSIPVCNCPFNSDRVFRLAQAQSRMNNGLVDA
|
|
63
|
-
SDFDDERNGWPVEQVWKEMHKLLPFSPDSVVTHGDFSLDNLIFDEGKLIGCIDVGRVGI
|
|
64
|
-
ADRYQDLAILWNCLGEFSPSLQKRLFQKYGIDNPDMNKLQFHLMLDEFF"
|
|
65
|
-
misc_feature 3691..3800
|
|
66
|
-
/label=promoter
|
|
67
|
-
misc_feature 3801..3804
|
|
68
|
-
/label=GCTT
|
|
69
|
-
/note="/color=#f7e8f7"
|
|
70
|
-
misc_feature 3805..4682
|
|
71
|
-
/label=From gblock_OriTOriR
|
|
72
|
-
/note="/color=white"
|
|
73
|
-
/note="/indicates_part=True"
|
|
74
|
-
/note="/source=gblock_OriTOriR"
|
|
75
|
-
misc_feature 4675..4681
|
|
76
|
-
/label=SapI site
|
|
77
|
-
promoter 4713..4842
|
|
78
|
-
/label=BBa_J72163 GlpT Promoter
|
|
79
|
-
/note="label: BBa_J72163 GlpT Promoter"
|
|
80
|
-
primer_bind 4713..4732
|
|
81
|
-
/label=CG17
|
|
82
|
-
RBS 4843..4878
|
|
83
|
-
/label=RBS
|
|
84
|
-
/note="label: RBS"
|
|
85
|
-
RBS 4861..4872
|
|
86
|
-
/label=RBS
|
|
87
|
-
/note="note: strong bacterial ribosome binding site
|
|
88
|
-
(Elowitz and Leibler, 2000)"
|
|
89
|
-
CDS 4879..5577
|
|
90
|
-
/label=mScarlet
|
|
91
|
-
/note="codon_start: 1 label: mScarlet transl_table: 1
|
|
92
|
-
translation:
|
|
93
|
-
MVSKGEAVIKEFMRFKVHMEGSMNGHEFEIEGEGEGRPYEGTQTAKLKVTKGGPLPFSW
|
|
94
|
-
DILSPQFMYGSRAFTKHPADIPDYYKQSFPEGFKWERVMNFEDGGAVTVTQDTSLEDGT
|
|
95
|
-
LIYKVKLRGTNFPPDGPVMQKKTMGWEASTERLYPEDGVLKGDIKMALRLKDGGRYLAD
|
|
96
|
-
FKTTYKAKKPVQMPGAYNVDRKLDITSHNEDYTVVEQYERSEGRHSTGGMDELYK*"
|
|
97
|
-
terminator 5578..5706
|
|
98
|
-
/label=BBa_B0015 Terminator
|
|
99
|
-
/note="label: BBa_B0015 Terminator"
|
|
100
|
-
terminator 5586..5657
|
|
101
|
-
/label=rrnB T1 terminator
|
|
102
|
-
/note="label: rrnB T1 terminator note: pLannotate note:
|
|
103
|
-
/database=snapgene note: /fragment=False note:
|
|
104
|
-
/identity=100.0 note: /match_length=100.0 note:
|
|
105
|
-
/other=terminator"
|
|
106
|
-
terminator 5673..5700
|
|
107
|
-
/label=T7Te terminator
|
|
108
|
-
/note="label: T7Te terminator note: pLannotate note:
|
|
109
|
-
/database=snapgene note: /fragment=False note:
|
|
110
|
-
/identity=100.0 note: /match_length=100.0 note:
|
|
111
|
-
/other=terminator"
|
|
112
|
-
primer_bind complement(5685..5706)
|
|
113
|
-
/label=CG18
|
|
114
|
-
misc_feature 5734..5747
|
|
115
|
-
/label=From gblock_OriTOriR
|
|
116
|
-
/note="/color=white"
|
|
117
|
-
/note="/indicates_part=True"
|
|
118
|
-
/note="/source=gblock_OriTOriR"
|
|
119
|
-
misc_feature 5738..5744
|
|
120
|
-
/label=SapI site
|
|
121
|
-
ORIGIN
|
|
122
|
-
1 aatgcacata tacctgccgt tcactattat ttagtgaaat gagatattat gatattttct
|
|
123
|
-
61 gaattgtgat taaaaaggca actttatgcc catgcaacag aaactataaa aaatacagag
|
|
124
|
-
121 aatgaaaaga aacagataga ttttttagtt ctttaggccc gtagtctgca aatcctttta
|
|
125
|
-
181 tgattttcta tcaaacaaaa gaggaaaata gaccagttgc aatccaaacg agagtctaat
|
|
126
|
-
241 agaatgaggt cgaaaagtaa atcgcgcggg tttgttactg ataaagcagg caagacctaa
|
|
127
|
-
301 aatgtgtaaa gggcaaagtg tatactttgg cgtcacccct tacatatttt aggtcttttt
|
|
128
|
-
361 ttattgtgcg taactaactt gccatcttca aacaggaggg ctggaagaag cagaccgcta
|
|
129
|
-
421 acacagtaca taaaaaagga gacatgaacg atgaacatca aaaagtttgc aaaacaagca
|
|
130
|
-
481 acagtattaa cctttactac cgcactgctg gcaggaggcg caactcaagc gtttgcgaaa
|
|
131
|
-
541 gaaacgaacc aaaagccata taaggaaaca tacggcattt cccatattac acgccatgat
|
|
132
|
-
601 atgctgcaaa tccctgaaca gcaaaaaaat gaaaaatatc aagttcctga attcgattcg
|
|
133
|
-
661 tccacaatta aaaatatctc ttctgcaaaa ggcctggacg tttgggacag ctggccatta
|
|
134
|
-
721 caaaacgctg acggcactgt cgcaaactat cacggctacc acatcgtctt tgcattagcc
|
|
135
|
-
781 ggagatccta aaaatgcgga tgacacatcg atttacatgt tctatcaaaa agtcggcgaa
|
|
136
|
-
841 acttctattg acagctggaa aaacgctggc cgcgtcttta aagacagcga caaattcgat
|
|
137
|
-
901 gcaaatgatt ctatcctaaa agaccaaaca caagaatggt caggttcagc cacatttaca
|
|
138
|
-
961 tctgacggaa aaatccgttt attctacact gatttctccg gtaaacatta cggcaaacaa
|
|
139
|
-
1021 acactgacaa ctgcacaagt taacgtatca gcatcagaca gctctttgaa catcaacggt
|
|
140
|
-
1081 gtagaggatt ataaatcaat ctttgacggt gacggaaaaa cgtatcaaaa tgtacagcag
|
|
141
|
-
1141 ttcatcgatg aaggcaacta cagctcaggc gacaaccata cgctgagaga tcctcactac
|
|
142
|
-
1201 gtagaagata aaggccacaa atacttagta tttgaagcaa acactggaac tgaagatggc
|
|
143
|
-
1261 taccaaggcg aagaatcttt atttaacaaa gcatactatg gcaaaagcac atcattcttc
|
|
144
|
-
1321 cgtcaagaaa gtcaaaaact tctgcaaagc gataaaaaac gcacggctga gttagcaaac
|
|
145
|
-
1381 ggcgctctcg gtatgattga gctaaacgat gattacacac tgaaaaaagt gatgaaaccg
|
|
146
|
-
1441 ctgattgcat ctaacacagt aacagatgaa attgaacgcg cgaacgtctt taaaatgaac
|
|
147
|
-
1501 ggcaaatggt acctgttcac tgactcccgc ggatcaaaaa tgacgattga cggcattacg
|
|
148
|
-
1561 tctaacgata tttacatgct tggttatgtt tctaattctt taactggccc atacaagccg
|
|
149
|
-
1621 ctgaacaaaa ctggccttgt gttaaaaatg gatcttgatc ctaacgatgt aacctttact
|
|
150
|
-
1681 tactcacact tcgctgtacc tcaagcgaaa ggaaacaatg tcgtgattac aagctatatg
|
|
151
|
-
1741 acaaacagag gattctacgc agacaaacaa tcaacgtttg cgccaagctt cctgctgaac
|
|
152
|
-
1801 atcaaaggca agaaaacatc tgttgtcaaa gacagcatcc ttgaacaagg acaattaaca
|
|
153
|
-
1861 gttaacaaat aaaaacgcaa aagaaaatgc cgatatccta ttggcatttt cttttatttc
|
|
154
|
-
1921 ttatcaacat aaaggtgaat cccatatgaa ctatataaaa gcaggcaaat ggctaaccgt
|
|
155
|
-
1981 attcctaacc ttttggtaat gactccaact tattgatagt gttttatgtt cagataatgc
|
|
156
|
-
2041 ccgatgactt tgtcatgcag ctccaccgat tttgagaacg acagcgactt ccgtcccagc
|
|
157
|
-
2101 cgtgccaggt gctgcctcag attcaggtta tgccgctcaa ttcgctgcgt atatcgcttg
|
|
158
|
-
2161 ctgattacgt gcagctttcc cttcaggcgg gattcataca gcggccagcc atccgtcatc
|
|
159
|
-
2221 catatcacca cgtcaaaggg tgacagcagg ctcataagac gccccagcgt cgccatagtg
|
|
160
|
-
2281 cgttcaccga atacgtgcgc aacaaccgtc taccggagac tgtcatacgc gtaaaacagc
|
|
161
|
-
2341 cagcgctggc gcgatttagc cccgacatag ccccactgtt cgtccatttc cgcgcagacg
|
|
162
|
-
2401 atgacgtcac tgcccggctg tatgcgcgag gttaccgact gcggcctgag ttttttaagt
|
|
163
|
-
2461 gacgtaaaat cgtgttgagg ccaacgccca taatgcgggc tgttgcccgg catccaacgc
|
|
164
|
-
2521 cattcatggc catatcaatg attttctggt gcgtaccggg ttgagaagcg gtgtaagtga
|
|
165
|
-
2581 actgcaaggt ctgaggtctg cctcgtgaag aaggtgttgc tgactcatac caggcctgaa
|
|
166
|
-
2641 tcgccccatc atccagccag aaagtgaggg agccacggtt gatgagagct ttgttgtagg
|
|
167
|
-
2701 tggaccagtt ggtgattttg aacttttgct ttgccacgga acggtctgcg ttgtcgggaa
|
|
168
|
-
2761 gatgcgtgat ctgatccttc aactcagcaa aagttcgatt tattcaacaa agccgccgtc
|
|
169
|
-
2821 ccgtcaagtc agcgtaatgc tctgccagtg ttacaaccaa ttaaccaatt ctgattagaa
|
|
170
|
-
2881 aaactcatcg agcatcaaat gaaactgcaa tttattcata tcaggattat caataccata
|
|
171
|
-
2941 tttttgaaaa agccgtttct gtaatgaagg agaaaactca ccgaggcagt tccataggat
|
|
172
|
-
3001 ggcaagatcc tggtatcggt ctgcgattcc gactcgtcca acatcaatac aacctattaa
|
|
173
|
-
3061 tttcccctcg tcaaaaataa ggttatcaag tgagaaatca ccatgagtga cgactgaatc
|
|
174
|
-
3121 cggtgagaat ggcaaaagct tatgcatttc tttccagact tgttcaacag gccagccatt
|
|
175
|
-
3181 acgctcgtca tcaaaatcac tcgcatcaac caaaccgtta ttcattcgtg attgcgcctg
|
|
176
|
-
3241 agcgagacga aatacgcgat cgctgttaaa aggacaatta caaacaggaa tcgaatgcaa
|
|
177
|
-
3301 ccggcgcagg aacactgcca gcgcatcaac aatattttca cctgaatcag gatattcttc
|
|
178
|
-
3361 taatacctgg aatgctgttt tcccggggat cgcagtggtg agtaaccatg catcatcagg
|
|
179
|
-
3421 agtacggata aaatgcttga tggtcggaag aggcataaat tccgtcagcc agtttagtct
|
|
180
|
-
3481 gaccatctca tctgtaacat cattggcaac gctacctttg ccatgtttca gaaacaactc
|
|
181
|
-
3541 tggcgcatcg ggcttcccat acaatcgata gattgtcgca cctgattgcc cgacattatc
|
|
182
|
-
3601 gcgagcccat ttatacccat ataaatcagc atccatgttg gaatttaatc gcggcctcga
|
|
183
|
-
3661 gcaagacgtt tcccgttgaa tatggctcat aacacccctt gtattactgt ttatgtaagc
|
|
184
|
-
3721 agacagtttt attgttcatg atgatatatt tttatcttgt gcaatgtaac atcagagatt
|
|
185
|
-
3781 ttgagacaca acgtggcttt gcttgtacac cttgataggt gggctgccct tcctggttgg
|
|
186
|
-
3841 cttggtttca tcagccatcc gcttgccctc atctgttacg ccggcggtag ccggccagcc
|
|
187
|
-
3901 tcgcagagca ggattcccgt tgagcaccgc caggtgcgaa taagggacag tgaagaagga
|
|
188
|
-
3961 acacccgctc gcgggtgggc ctacttcacc tatcctgccc ggctgacgcc gttggataca
|
|
189
|
-
4021 ccaaggaaag tctacacgaa ccctttggca aaatatcaaa ggatcttctt gagatccttt
|
|
190
|
-
4081 ttttctgcgc gtaatctgct gcttgcaaac aaaaaaacca ccgctaccag cggtggtttg
|
|
191
|
-
4141 tttgccggat caagagctac caactctttt tccgaaggta actggcttca gcagagcgca
|
|
192
|
-
4201 gataccaaat actgttcttc tagtgtagcc gtagttaggc caccacttca agaactctgt
|
|
193
|
-
4261 agcaccgcct acatacctcg ctctgctaat cctgttacca gtggctgctg ccagtggcga
|
|
194
|
-
4321 taagtcgtgt cttaccgggt tggactcaag acgatagtta ccggataagg cgcagcggtc
|
|
195
|
-
4381 gggctgaacg gggggttcgt gcacacagcc cagcttggag cgaacgacct acaccgaact
|
|
196
|
-
4441 gagataccta cagcgtgagc tatgagaaag cgccacgctt cccgaaggga gaaaggcgga
|
|
197
|
-
4501 caggtatccg gtaagcggca gggtcggaac aggagagcgc acgagggagc ttccaggggg
|
|
198
|
-
4561 aaacgcctgg tatctttata gtcctgtcgg gtttcgccac ctctgacttg agcgtcgatt
|
|
199
|
-
4621 tttgtgatgc tcgtcagggg ggcggagcct atggaaaaac gccagcaacg cggcgctctt
|
|
200
|
-
4681 catgctcgga gagagacctt tgccttgtct tcgaaagtga aacgtgattt catgcgtcat
|
|
201
|
-
4741 tttgaacatt ttgtaaatct tatttaataa tgtgtgcggc aattcacatt taatttatga
|
|
202
|
-
4801 atgttttctt aacatcgcgg caactcaaga aacggcaggt tcggatctta gctactagag
|
|
203
|
-
4861 aaagaggaga aatactagat ggttagcaaa ggcgaggcgg ttatcaagga gtttatgcgt
|
|
204
|
-
4921 tttaaggttc acatggaggg tagcatgaac ggtcacgagt tcgagatcga gggtgaaggc
|
|
205
|
-
4981 gagggtcgtc cgtacgaagg cacccagacc gcgaagctga aagtgaccaa gggtggcccg
|
|
206
|
-
5041 ctgccgttca gctgggacat cctgagcccg cagttcatgt atggcagccg tgcgtttacc
|
|
207
|
-
5101 aaacacccgg cggacattcc ggattactat aagcaaagct tcccggaagg ttttaaatgg
|
|
208
|
-
5161 gagcgtgtta tgaacttcga agatggtggc gcggtgaccg ttacccagga caccagcctg
|
|
209
|
-
5221 gaggatggca ccctgattta caaggtgaaa ctgcgtggca ccaactttcc gccggatggt
|
|
210
|
-
5281 ccggttatgc agaagaaaac gatgggttgg gaagcgagca ccgagcgtct gtatccggaa
|
|
211
|
-
5341 gatggcgtgc tgaagggtga tatcaaaatg gcgctgcgtc tgaaggacgg tggccgttac
|
|
212
|
-
5401 ctggcggatt ttaagaccac ctataaagcg aagaaaccgg tgcaaatgcc gggtgcgtac
|
|
213
|
-
5461 aacgttgacc gtaaactgga tattaccagc cacaacgagg attataccgt ggttgagcaa
|
|
214
|
-
5521 tatgagcgta gcgagggtcg ccacagcacc ggcggcatgg acgaactgta taagtgacca
|
|
215
|
-
5581 ggcatcaaat aaaacgaaag gctcagtcga aagactgggc ctttcgtttt atctgttgtt
|
|
216
|
-
5641 tgtcggtgaa cgctctctac tagagtcaca ctggctcacc ttcgggtggg cctttctgcg
|
|
217
|
-
5701 tttatagaag acaagggaaa ggtctctcgc tgagatagaa gagcacg
|
|
218
|
-
//
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import os
|
|
3
|
-
from primer3 import bindings
|
|
4
|
-
import json
|
|
5
|
-
from fastapi import UploadFile, Response
|
|
6
|
-
|
|
7
|
-
from opencloning.pydantic_models import (
|
|
8
|
-
GenomeCoordinatesSource,
|
|
9
|
-
TextFileSequence,
|
|
10
|
-
PrimerModel,
|
|
11
|
-
PCRSource,
|
|
12
|
-
RestrictionAndLigationSource,
|
|
13
|
-
BaseCloningStrategy,
|
|
14
|
-
HomologousRecombinationSource,
|
|
15
|
-
)
|
|
16
|
-
from opencloning.batch_cloning.EBIC.primer_design_settings import amanda_settings
|
|
17
|
-
from opencloning.endpoints.external_import import genome_coordinates, read_from_file
|
|
18
|
-
from opencloning.endpoints.assembly import pcr, restriction_and_ligation, homologous_recombination
|
|
19
|
-
from opencloning.dna_functions import read_dsrecord_from_json
|
|
20
|
-
|
|
21
|
-
# Settings for design
|
|
22
|
-
padding = 1000
|
|
23
|
-
max_inside = 20
|
|
24
|
-
max_outside = 70
|
|
25
|
-
outside_edge = padding - max_outside
|
|
26
|
-
inside_edge = padding + max_inside
|
|
27
|
-
|
|
28
|
-
adapter_left_fwd = 'ataGGTCTCtGGAG'
|
|
29
|
-
adapter_left_rvs = 'ataGGTCTCtCATT'
|
|
30
|
-
adapter_right_fwd = 'ataGGTCTCtGCTT'
|
|
31
|
-
adapter_right_rvs = 'ataGGTCTCtAGCG'
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def design_primers_ebic(seq: str, seq_args: dict):
|
|
35
|
-
|
|
36
|
-
report = bindings.design_primers(
|
|
37
|
-
seq_args={
|
|
38
|
-
'SEQUENCE_ID': 'MH1000',
|
|
39
|
-
'SEQUENCE_TEMPLATE': seq,
|
|
40
|
-
**seq_args,
|
|
41
|
-
},
|
|
42
|
-
global_args=amanda_settings,
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
return report
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
async def main():
|
|
49
|
-
cloning_strategy = BaseCloningStrategy(
|
|
50
|
-
sequences=[],
|
|
51
|
-
sources=[],
|
|
52
|
-
primers=[],
|
|
53
|
-
description='EBIC cloning strategy',
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
initial_source = GenomeCoordinatesSource(
|
|
57
|
-
id=0,
|
|
58
|
-
assembly_accession='GCF_002847425.1',
|
|
59
|
-
sequence_accession='NZ_CP025534.1',
|
|
60
|
-
start=2700777 - padding,
|
|
61
|
-
end=2701295 + padding,
|
|
62
|
-
strand=1,
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
if os.path.exists('cached_response.json'):
|
|
66
|
-
with open('cached_response.json', 'r') as f:
|
|
67
|
-
locus = json.load(f)
|
|
68
|
-
locus['sequences'][0] = TextFileSequence.model_validate(locus['sequences'][0])
|
|
69
|
-
locus['sources'][0] = GenomeCoordinatesSource.model_validate(locus['sources'][0])
|
|
70
|
-
else:
|
|
71
|
-
print('No cached response found, fetching from server')
|
|
72
|
-
locus = await genome_coordinates(initial_source)
|
|
73
|
-
with open('cached_response.json', 'w') as f:
|
|
74
|
-
json.dump(
|
|
75
|
-
{
|
|
76
|
-
'sequences': [locus['sequences'][0].model_dump()],
|
|
77
|
-
'sources': [locus['sources'][0].model_dump()],
|
|
78
|
-
},
|
|
79
|
-
f,
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
locus_seq: TextFileSequence = locus['sequences'][0]
|
|
83
|
-
locus_source: GenomeCoordinatesSource = locus['sources'][0]
|
|
84
|
-
locus_dseqr = read_dsrecord_from_json(locus_seq)
|
|
85
|
-
|
|
86
|
-
cloning_strategy.add_source_and_sequence(locus_source, locus_seq)
|
|
87
|
-
|
|
88
|
-
left_template = locus_dseqr[:inside_edge]
|
|
89
|
-
right_template = locus_dseqr[-inside_edge:]
|
|
90
|
-
|
|
91
|
-
seq_args_left = {
|
|
92
|
-
'SEQUENCE_PRIMER_PAIR_OK_REGION_LIST': f'0,{int(padding/2)},{outside_edge},{max_outside + max_inside}',
|
|
93
|
-
}
|
|
94
|
-
seq_args_right = {
|
|
95
|
-
'SEQUENCE_PRIMER_PAIR_OK_REGION_LIST': f'0,{max_outside + max_inside},{len(right_template) - int(padding/2)},{int(padding/2)}',
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
report_left = design_primers_ebic(str(left_template.seq), seq_args_left)
|
|
99
|
-
report_right = design_primers_ebic(str(right_template.seq), seq_args_right)
|
|
100
|
-
|
|
101
|
-
primer_names = ['left_fwd', 'left_rvs', 'right_fwd', 'right_rvs']
|
|
102
|
-
primer_seqs = [
|
|
103
|
-
adapter_left_fwd + report_left['PRIMER_LEFT'][0]['SEQUENCE'],
|
|
104
|
-
adapter_left_rvs + report_left['PRIMER_RIGHT'][0]['SEQUENCE'],
|
|
105
|
-
adapter_right_fwd + report_right['PRIMER_LEFT'][0]['SEQUENCE'],
|
|
106
|
-
adapter_right_rvs + report_right['PRIMER_RIGHT'][0]['SEQUENCE'],
|
|
107
|
-
]
|
|
108
|
-
primers = [PrimerModel(id=0, name=primer_names[i], sequence=primer_seqs[i]) for i in range(4)]
|
|
109
|
-
for primer in primers:
|
|
110
|
-
cloning_strategy.add_primer(primer)
|
|
111
|
-
|
|
112
|
-
pcr_left_source = PCRSource(id=0, output_name='left_homology_arm')
|
|
113
|
-
resp = await pcr(pcr_left_source, [locus_seq], [primers[0], primers[1]], 17, 0)
|
|
114
|
-
pcr_product_left: TextFileSequence = resp['sequences'][0]
|
|
115
|
-
pcr_left_source: PCRSource = resp['sources'][0]
|
|
116
|
-
cloning_strategy.add_source_and_sequence(pcr_left_source, pcr_product_left)
|
|
117
|
-
|
|
118
|
-
pcr_right_source = PCRSource(id=0, output_name='right_homology_arm')
|
|
119
|
-
resp = await pcr(pcr_right_source, [locus_seq], [primers[2], primers[3]], 17, 0)
|
|
120
|
-
pcr_product_right: TextFileSequence = resp['sequences'][0]
|
|
121
|
-
pcr_right_source: PCRSource = resp['sources'][0]
|
|
122
|
-
cloning_strategy.add_source_and_sequence(pcr_right_source, pcr_product_right)
|
|
123
|
-
|
|
124
|
-
with open(os.path.join(os.path.dirname(__file__), 'barcode.gb'), 'rb') as f:
|
|
125
|
-
dummy_resp = Response()
|
|
126
|
-
resp = await read_from_file(
|
|
127
|
-
dummy_resp, UploadFile(file=f, filename='barcode.gb'), None, None, True, 'barcode', None, None
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
barcode_source = resp['sources'][0]
|
|
131
|
-
barcode_seq: TextFileSequence = resp['sequences'][0]
|
|
132
|
-
cloning_strategy.add_source_and_sequence(barcode_source, barcode_seq)
|
|
133
|
-
|
|
134
|
-
with open(os.path.join(os.path.dirname(__file__), 'common_plasmid.gb'), 'rb') as f:
|
|
135
|
-
dummy_resp = Response()
|
|
136
|
-
resp = await read_from_file(
|
|
137
|
-
dummy_resp,
|
|
138
|
-
UploadFile(file=f, filename='common_plasmid.gb'),
|
|
139
|
-
None,
|
|
140
|
-
None,
|
|
141
|
-
True,
|
|
142
|
-
'common_plasmid',
|
|
143
|
-
None,
|
|
144
|
-
None,
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
common_plasmid_source = resp['sources'][0]
|
|
148
|
-
common_plasmid_seq: TextFileSequence = resp['sequences'][0]
|
|
149
|
-
cloning_strategy.add_source_and_sequence(common_plasmid_source, common_plasmid_seq)
|
|
150
|
-
|
|
151
|
-
golgen_gate = RestrictionAndLigationSource(id=0, output_name='golgen_gate', restriction_enzymes=['BsaI'])
|
|
152
|
-
resp = await restriction_and_ligation(
|
|
153
|
-
golgen_gate, [pcr_product_left, pcr_product_right, barcode_seq, common_plasmid_seq], False, True
|
|
154
|
-
)
|
|
155
|
-
golgen_gate_product: TextFileSequence = resp['sequences'][0]
|
|
156
|
-
golgen_gate_source: RestrictionAndLigationSource = resp['sources'][0]
|
|
157
|
-
cloning_strategy.add_source_and_sequence(golgen_gate_source, golgen_gate_product)
|
|
158
|
-
|
|
159
|
-
homologous_recombination_source = HomologousRecombinationSource(id=0, output_name='engineered_allele')
|
|
160
|
-
resp = await homologous_recombination(homologous_recombination_source, [locus_seq, golgen_gate_product], 17)
|
|
161
|
-
|
|
162
|
-
multi_site_sources = [
|
|
163
|
-
i for i, s in enumerate(resp['sources']) if all(join.left_location != join.right_location for join in s.input)
|
|
164
|
-
]
|
|
165
|
-
if len(multi_site_sources) > 1:
|
|
166
|
-
raise ValueError('Multiple insertions possible')
|
|
167
|
-
|
|
168
|
-
possible_sources = [resp['sources'][i] for i in multi_site_sources]
|
|
169
|
-
possible_sequences = [resp['sequences'][i] for i in multi_site_sources]
|
|
170
|
-
homologous_recombination_product: TextFileSequence = possible_sequences[0]
|
|
171
|
-
homologous_recombination_source: HomologousRecombinationSource = possible_sources[0]
|
|
172
|
-
cloning_strategy.add_source_and_sequence(homologous_recombination_source, homologous_recombination_product)
|
|
173
|
-
|
|
174
|
-
# Save cloning strategy to JSON file
|
|
175
|
-
with open('cloning_strategy.json', 'w') as f:
|
|
176
|
-
json.dump(cloning_strategy.model_dump(), f, indent=2)
|
|
177
|
-
return cloning_strategy
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
asyncio.run(main())
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
amanda_settings = {
|
|
2
|
-
# Tm: Optimal 60-62°C, but this can be extended to 58-64°C if necessary.
|
|
3
|
-
# All primers need to ideally be within 5°C to ensure they can be run on the same plate for high-throughput.
|
|
4
|
-
'PRIMER_OPT_TM': 61, # Optimal Tm
|
|
5
|
-
'PRIMER_MIN_TM': 58, # Minimum Tm
|
|
6
|
-
'PRIMER_MAX_TM': 64, # Maximum Tm
|
|
7
|
-
'PRIMER_PAIR_MAX_DIFF_TM': 5, # Maximum Tm difference within a pair
|
|
8
|
-
# Salt concentration: 50mM NaCl, 1.5mM MgCl2
|
|
9
|
-
'PRIMER_SALT_MONOVALENT': 50.0,
|
|
10
|
-
'PRIMER_SALT_DIVALENT': 1.5,
|
|
11
|
-
# 500 nM primer concentration
|
|
12
|
-
'PRIMER_DNA_CONC': 500.0,
|
|
13
|
-
# Primer size: 17-30nt.
|
|
14
|
-
'PRIMER_MIN_SIZE': 17, # Minimum primer length
|
|
15
|
-
'PRIMER_MAX_SIZE': 30, # Maximum primer length
|
|
16
|
-
'PRIMER_OPT_SIZE': 22, # Typical optimal size (can be adjusted)
|
|
17
|
-
# GC content: between 35 and 65%.
|
|
18
|
-
'PRIMER_MIN_GC': 35, # Minimum GC content percentage
|
|
19
|
-
'PRIMER_MAX_GC': 65, # Maximum GC content percentage
|
|
20
|
-
# A 1 or 2nt GC clamp at the 3’ end of the primer helps with PCR efficiency.
|
|
21
|
-
'PRIMER_GC_CLAMP': 1, # Number of GC bases required at the 3’ end
|
|
22
|
-
# Product size: ~950bp homologous arms, though this can be shortened if necessary.
|
|
23
|
-
'PRIMER_PRODUCT_SIZE_RANGE': [[800, 1000]], # Product size range in base pairs
|
|
24
|
-
# Avoid primers with long repetitions of nucleotides in a row (e.g., TTTTT).
|
|
25
|
-
'PRIMER_MAX_POLY_X': 4, # Maximum allowable repetitions of a single nucleotide
|
|
26
|
-
# Dimer and hairpin structure considerations:
|
|
27
|
-
# Self-dimers – avoid ΔG below -10
|
|
28
|
-
# Heterodimers – avoid ΔG below -10
|
|
29
|
-
# Hairpin loops - avoid ΔG below -5
|
|
30
|
-
'PRIMER_MAX_SELF_ANY': 47,
|
|
31
|
-
'PRIMER_MAX_SELF_END': 47,
|
|
32
|
-
'PRIMER_MAX_HAIRPIN': 47,
|
|
33
|
-
# Return only one primer pair
|
|
34
|
-
'PRIMER_NUM_RETURN': 1,
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
# Avoid primers with homology to other sites in the genome.
|
|
38
|
-
# This can be checked using external tools like BLAST for specificity.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/pombe/pombe_get_primers.py
RENAMED
|
File without changes
|
{opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/pombe/pombe_summary.py
RENAMED
|
File without changes
|
{opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/ziqiang_et_al2024/__init__.py
RENAMED
|
File without changes
|
{opencloning-0.4.5 → opencloning-0.4.7}/src/opencloning/batch_cloning/ziqiang_et_al2024/index.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opencloning-0.4.5/src/opencloning/bug_fixing → opencloning-0.4.7/src/opencloning/ebic}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|