opencloning 0.4.7__tar.gz → 0.4.8__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.
Files changed (45) hide show
  1. {opencloning-0.4.7 → opencloning-0.4.8}/PKG-INFO +1 -1
  2. {opencloning-0.4.7 → opencloning-0.4.8}/pyproject.toml +1 -1
  3. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/ebic/primer_design.py +23 -13
  4. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/endpoints/primer_design.py +21 -16
  5. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/primer3_functions.py +3 -3
  6. {opencloning-0.4.7 → opencloning-0.4.8}/LICENSE +0 -0
  7. {opencloning-0.4.7 → opencloning-0.4.8}/README.md +0 -0
  8. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/__init__.py +0 -0
  9. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/_version.py +0 -0
  10. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/api_config_utils.py +0 -0
  11. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/app_settings.py +0 -0
  12. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/__init__.py +0 -0
  13. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/index.html +0 -0
  14. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/pombe/__init__.py +0 -0
  15. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/pombe/index.html +0 -0
  16. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/pombe/pombe_clone.py +0 -0
  17. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/pombe/pombe_gather.py +0 -0
  18. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/pombe/pombe_get_primers.py +0 -0
  19. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/pombe/pombe_summary.py +0 -0
  20. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/ziqiang_et_al2024/__init__.py +0 -0
  21. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/ziqiang_et_al2024/index.html +0 -0
  22. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/batch_cloning/ziqiang_et_al2024/ziqiang_et_al2024.json +0 -0
  23. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/bug_fixing/README.md +0 -0
  24. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/bug_fixing/__init__.py +0 -0
  25. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/bug_fixing/backend_v0_3.py +0 -0
  26. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/cre_lox.py +0 -0
  27. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/dna_functions.py +0 -0
  28. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/dna_utils.py +0 -0
  29. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/ebic/__init__.py +0 -0
  30. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/ebic/primer_design_settings.py +0 -0
  31. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/endpoints/annotation.py +0 -0
  32. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/endpoints/assembly.py +0 -0
  33. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/endpoints/external_import.py +0 -0
  34. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/endpoints/no_assembly.py +0 -0
  35. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/endpoints/no_input.py +0 -0
  36. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/endpoints/other.py +0 -0
  37. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/gateway.py +0 -0
  38. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/get_router.py +0 -0
  39. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/http_client.py +0 -0
  40. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/main.py +0 -0
  41. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/ncbi_requests.py +0 -0
  42. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/primer_design.py +0 -0
  43. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/pydantic_models.py +0 -0
  44. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/request_examples.py +0 -0
  45. {opencloning-0.4.7 → opencloning-0.4.8}/src/opencloning/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencloning
3
- Version: 0.4.7
3
+ Version: 0.4.8
4
4
  Summary: Backend of OpenCloning, a web application to generate molecular cloning strategies in json format, and share them with others.
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -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.7"
11
+ version = "0.4.8"
12
12
  package-mode = true
13
13
  readme = "README.md"
14
14
  repository = "https://github.com/manulera/OpenCloning_backend"
@@ -1,16 +1,15 @@
1
1
  from pydna.dseqrecord import Dseqrecord
2
2
  from Bio.SeqFeature import SimpleLocation
3
- from ..primer3_functions import primer3_design_primers
3
+ from ..primer3_functions import PrimerDesignSettings, primer3_design_primers
4
4
 
5
5
  from ..pydantic_models import PrimerModel
6
6
  from .primer_design_settings import amanda_settings
7
7
 
8
- padding = 1000
9
-
10
8
  adapter_left_fwd = 'ataGGTCTCtGGAG'
11
9
  adapter_left_rvs = 'ataGGTCTCtCATT'
12
10
  adapter_right_fwd = 'ataGGTCTCtGCTT'
13
11
  adapter_right_rvs = 'ataGGTCTCtAGCG'
12
+ default_settings = PrimerDesignSettings()
14
13
 
15
14
 
16
15
  def ebic_primers(
@@ -20,36 +19,47 @@ def ebic_primers(
20
19
  max_outside: int,
21
20
  target_tm: float,
22
21
  target_tm_tolerance: float,
22
+ padding_left: int = 1000,
23
+ padding_right: int = 1000,
24
+ settings: PrimerDesignSettings = default_settings,
23
25
  ) -> tuple[PrimerModel, PrimerModel, PrimerModel, PrimerModel]:
24
26
  """Design primers for EBIC"""
25
27
 
26
28
  # First, we keep only the part within the padding
27
- edge_left = location.start - padding
28
- edge_right = location.end + padding
29
+ edge_left = location.start - padding_left
30
+ edge_right = location.end + padding_right
29
31
  if edge_left < 0 or edge_right > len(input_seq):
30
32
  raise ValueError('The template is too short for the padding.')
31
33
 
32
34
  template_seq = str(input_seq.seq[edge_left:edge_right])
33
- inside_edge = padding + max_inside
34
- outside_edge = padding - max_outside
35
+ inside_edge_left = padding_left + max_inside
36
+ inside_edge_right = padding_right + max_inside
37
+ outside_edge_left = padding_left - max_outside
35
38
 
36
- left_template = template_seq[:inside_edge]
37
- right_template = template_seq[-inside_edge:]
39
+ left_template = template_seq[:inside_edge_left]
40
+ right_template = template_seq[-inside_edge_right:]
38
41
 
39
42
  seq_args_left = {
40
- 'SEQUENCE_PRIMER_PAIR_OK_REGION_LIST': f'0,{int(padding/2)},{outside_edge},{max_outside + max_inside}',
43
+ 'SEQUENCE_PRIMER_PAIR_OK_REGION_LIST': f'0,{int(padding_left/2)},{outside_edge_left},{max_outside + max_inside}',
41
44
  }
42
45
  seq_args_right = {
43
- 'SEQUENCE_PRIMER_PAIR_OK_REGION_LIST': f'0,{max_outside + max_inside},{len(right_template) - int(padding/2)},{int(padding/2)}',
46
+ 'SEQUENCE_PRIMER_PAIR_OK_REGION_LIST': f'0,{max_outside + max_inside},{len(right_template) - int(padding_right/2)},{int(padding_right/2)}',
44
47
  }
45
48
 
46
49
  global_args = amanda_settings.copy()
47
50
  global_args['PRIMER_OPT_TM'] = target_tm
48
51
  global_args['PRIMER_MIN_TM'] = target_tm - target_tm_tolerance
49
52
  global_args['PRIMER_MAX_TM'] = target_tm + target_tm_tolerance
53
+ global_args['PRIMER_SALT_MONOVALENT'] = settings.primer_salt_monovalent
54
+ global_args['PRIMER_SALT_DIVALENT'] = settings.primer_salt_divalent
55
+ global_args['PRIMER_DNA_CONC'] = settings.primer_dna_conc
56
+ global_args_left = global_args.copy()
57
+ global_args_right = global_args.copy()
58
+ global_args_left['PRIMER_PRODUCT_SIZE_RANGE'] = [[max(100, padding_left - 100), padding_left]]
59
+ global_args_right['PRIMER_PRODUCT_SIZE_RANGE'] = [[max(100, padding_right - 100), padding_right]]
50
60
 
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)
61
+ report_left = primer3_design_primers(left_template, seq_args_left, global_args_left)
62
+ report_right = primer3_design_primers(right_template, seq_args_right, global_args_right)
53
63
  primer_names = ['left_fwd', 'left_rvs', 'right_fwd', 'right_rvs']
54
64
  primer_seqs = [
55
65
  adapter_left_fwd + report_left['PRIMER_LEFT'][0]['SEQUENCE'],
@@ -51,9 +51,7 @@ def validate_spacers(spacers: list[str] | None, nb_templates: int, circular: boo
51
51
  async def primer_design_homologous_recombination(
52
52
  pcr_template: PrimerDesignQuery,
53
53
  homologous_recombination_target: PrimerDesignQuery,
54
- settings: PrimerDesignSettings = Body(
55
- ..., description='Primer design settings.', default_factory=PrimerDesignSettings
56
- ),
54
+ settings: PrimerDesignSettings = Body(description='Primer design settings.', default_factory=PrimerDesignSettings),
57
55
  spacers: list[str] | None = Body(
58
56
  None,
59
57
  description='Spacers to add at the left and right side of the insertion.',
@@ -103,9 +101,7 @@ async def primer_design_homologous_recombination(
103
101
  @router.post('/primer_design/gibson_assembly', response_model=PrimerDesignResponse)
104
102
  async def primer_design_gibson_assembly(
105
103
  pcr_templates: list[PrimerDesignQuery],
106
- settings: PrimerDesignSettings = Body(
107
- ..., description='Primer design settings.', default_factory=PrimerDesignSettings
108
- ),
104
+ settings: PrimerDesignSettings = Body(description='Primer design settings.', default_factory=PrimerDesignSettings),
109
105
  spacers: list[str] | None = Body(
110
106
  None,
111
107
  description='Spacers to add between the restriction site and the 5\' end of the primer footprint (the part that binds the DNA).',
@@ -156,9 +152,7 @@ async def primer_design_simple_pair(
156
152
  None,
157
153
  description='Spacers to add between the restriction site and the 5\' end of the primer footprint (the part that binds the DNA).',
158
154
  ),
159
- settings: PrimerDesignSettings = Body(
160
- ..., description='Primer design settings.', default_factory=PrimerDesignSettings
161
- ),
155
+ settings: PrimerDesignSettings = Body(description='Primer design settings.', default_factory=PrimerDesignSettings),
162
156
  minimal_hybridization_length: int = Query(
163
157
  ..., description='The minimal length of the hybridization region in bps.'
164
158
  ),
@@ -219,6 +213,7 @@ async def primer_design_simple_pair(
219
213
  @router.post('/primer_design/ebic', response_model=PrimerDesignResponse)
220
214
  async def primer_design_ebic(
221
215
  template: PrimerDesignQuery,
216
+ settings: PrimerDesignSettings = Body(description='Primer design settings.', default_factory=PrimerDesignSettings),
222
217
  max_inside: int = Query(..., description='The maximum length of the inside edge of the EBIC primer.'),
223
218
  max_outside: int = Query(..., description='The maximum length of the outside edge of the EBIC primer.'),
224
219
  target_tm: float = Query(
@@ -227,11 +222,25 @@ async def primer_design_ebic(
227
222
  target_tm_tolerance: float = Query(
228
223
  3, description='The tolerance for the desired melting temperature for the hybridization part of the primer.'
229
224
  ),
225
+ padding_left: int = Query(..., description='The padding length on the left side of the template.'),
226
+ padding_right: int = Query(..., description='The padding length on the right side of the template.'),
230
227
  ):
231
228
  """Design primers for EBIC"""
232
229
  dseqr = read_dsrecord_from_json(template.sequence)
233
230
  location = template.location.to_biopython_location()
234
- return {'primers': ebic_primers(dseqr, location, max_inside, max_outside, target_tm, target_tm_tolerance)}
231
+ return {
232
+ 'primers': ebic_primers(
233
+ dseqr,
234
+ location,
235
+ max_inside,
236
+ max_outside,
237
+ target_tm,
238
+ target_tm_tolerance,
239
+ padding_left,
240
+ padding_right,
241
+ settings,
242
+ )
243
+ }
235
244
 
236
245
 
237
246
  # @router.post('/primer_design/gateway_attB', response_model=PrimerDesignResponse)
@@ -279,9 +288,7 @@ class PrimerDetailsResponse(BaseModel):
279
288
  @router.post('/primer_details', response_model=PrimerDetailsResponse)
280
289
  async def primer_details(
281
290
  sequence: str = Body(..., description='Primer sequence', pattern=r'^[ACGTacgt]+$'),
282
- settings: PrimerDesignSettings = Body(
283
- ..., description='Primer design settings.', default_factory=PrimerDesignSettings
284
- ),
291
+ settings: PrimerDesignSettings = Body(description='Primer design settings.', default_factory=PrimerDesignSettings),
285
292
  ):
286
293
  """Get information about a primer"""
287
294
  sequence = sequence.upper()
@@ -303,9 +310,7 @@ async def primer_details(
303
310
  async def primer_heterodimer(
304
311
  sequence1: str = Body(..., description='First primer sequence', pattern=r'^[ACGTacgt]+$'),
305
312
  sequence2: str = Body(..., description='Second primer sequence', pattern=r'^[ACGTacgt]+$'),
306
- settings: PrimerDesignSettings = Body(
307
- ..., description='Primer design settings.', default_factory=PrimerDesignSettings
308
- ),
313
+ settings: PrimerDesignSettings = Body(description='Primer design settings.', default_factory=PrimerDesignSettings),
309
314
  ):
310
315
  """Get information about a primer pair"""
311
316
 
@@ -62,7 +62,7 @@ class ThermodynamicResult(BaseModel):
62
62
  )
63
63
 
64
64
 
65
- def get_sequence_thermodynamic_result(sequence: str, method: callable) -> ThermodynamicResult | None:
65
+ def get_sequence_thermodynamic_result(sequence: str, method: callable):
66
66
  """Get the thermodynamic result for a sequence, if the sequence is longer than primer3 60bp limit, it will be split into two
67
67
  and the result with the lowest deltaG will be returned."""
68
68
  sequence = sequence.upper()
@@ -80,13 +80,13 @@ def get_sequence_thermodynamic_result(sequence: str, method: callable) -> Thermo
80
80
  return ThermodynamicResult.from_binding(result)
81
81
 
82
82
 
83
- def primer3_calc_homodimer(seq: str, settings: PrimerDesignSettings) -> ThermodynamicResult:
83
+ def primer3_calc_homodimer(seq: str, settings: PrimerDesignSettings):
84
84
  return get_sequence_thermodynamic_result(
85
85
  seq, lambda x: _calc_homodimer(x, output_structure=True, **settings.to_primer3_args())
86
86
  )
87
87
 
88
88
 
89
- def primer3_calc_hairpin(seq: str, settings: PrimerDesignSettings) -> ThermodynamicResult:
89
+ def primer3_calc_hairpin(seq: str, settings: PrimerDesignSettings):
90
90
  return get_sequence_thermodynamic_result(
91
91
  seq, lambda x: _calc_hairpin(x, output_structure=True, **settings.to_primer3_args())
92
92
  )
File without changes
File without changes