pydna 5.5.1__py3-none-any.whl → 5.5.2__py3-none-any.whl

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.
pydna/myprimers.py DELETED
@@ -1,219 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # Copyright 2013-2023 by Björn Johansson. All rights reserved.
4
- # This code is part of the Python-dna distribution and governed by its
5
- # license. Please see the LICENSE.txt file that should have been included
6
- # as part of this package.
7
- """
8
- Provides a practical way to access a list of primer sequences in a text file.
9
-
10
- The path of a text file can be specified in the pydna.ini file or by the
11
- ´pydna_primers´ environment variable.
12
-
13
- The file is expected to contain sequences in FASTA, Genbank or EMBL formats or
14
- any format readable by the parse_primers function.
15
-
16
- The primer list is expected to follow the convension below. The primer name is
17
- expected to begin with the number.
18
-
19
- can have the format below for example:
20
-
21
- ::
22
-
23
- >2_third_primer
24
- tgagtagtcgtagtcgtcgtat
25
-
26
- >1_second_primer
27
- tgatcgtcatgctgactatactat
28
-
29
- >0_first_primer
30
- ctaggatcgtagatctagctg
31
- ...
32
-
33
- The primerlist funtion returns a list of :class:`pydna.primer.Primer` objects
34
- primerdict returns a dict where the key is the id of the object.
35
- """
36
-
37
- import os as _os
38
- import re as _re
39
- from typing import Iterable
40
- from pathlib import Path
41
- import copy as _copy
42
- from keyword import iskeyword as _iskeyword
43
- from pydna.parsers import parse_primers as _parse_primers
44
- from pydna._pretty import pretty_str as _pretty_str
45
- from collections import UserList as _UserList
46
- from pydna.utils import open_folder as _open_folder
47
- from builtins import __dict__ as _kw
48
-
49
-
50
- class PrimerList(_UserList):
51
- """Read a text file with primers.
52
-
53
- The primers can be of any format readable by the parse_primers
54
- function. Lines beginning with # are ignored. Path defaults to
55
- the path given by the pydna_primers environment variable.
56
-
57
- The primer list does not accept new primers. Use the
58
- assign_numbers_to_new_primers method and paste the new
59
- primers at the top of the list.
60
-
61
- The primer list remembers the numbers of accessed primers.
62
- The indices of accessed primers are stored in the .accessed
63
- property.
64
- """
65
-
66
- def __init__(
67
- self,
68
- initlist: Iterable = None,
69
- path: (str, Path) = None,
70
- *args,
71
- identifier: str = "p",
72
- **kwargs,
73
- ):
74
- if initlist:
75
- self.data = initlist
76
- self.path = None
77
- else:
78
- self.path = Path(path or _os.environ["pydna_primers"])
79
- self.path.parent.mkdir(parents=True, exist_ok=True)
80
- self.data = _parse_primers(self.path.read_text())[::-1]
81
- # super().__init__(*args, **kwargs)
82
- self.accessed_indices = []
83
- if identifier.isidentifier() and not _iskeyword(identifier) and identifier not in _kw:
84
- self.identifier = identifier
85
- else:
86
- raise ValueError(f"{identifier} is not a valid identifier.")
87
-
88
- def __getitem__(self, i):
89
- """Save indices of accessed items."""
90
- if isinstance(i, slice):
91
- result = self.__class__(self.data[i])
92
- for ind in range(i.start, i.stop, i.step or 1):
93
- if ind not in self.accessed_indices:
94
- self.accessed_indices.append(ind)
95
- else:
96
- try:
97
- result = self.data[i]
98
- except IndexError as e:
99
- raise (e)
100
- else:
101
- if i not in self.accessed_indices:
102
- self.accessed_indices.append(i)
103
- return result
104
-
105
- def __setitem__(self, i, item):
106
- """Items already present can be set to the same value."""
107
- if abs(i) > len(self):
108
- raise IndexError(f"index {i} does not exist.")
109
- else:
110
- if str(item.seq).lower() != str(self.data[i].seq).lower():
111
- raise ValueError("Cannot change existing primer.")
112
- if i not in self.accessed_indices:
113
- self.accessed_indices.append(i)
114
-
115
- @property
116
- def accessed(self):
117
- """docstring."""
118
- return [self.data[i] for i in self.accessed_indices]
119
-
120
- def assign_numbers(self, lst: list):
121
- """Find new primers in lst.
122
-
123
- Returns a string containing new primers with their assigned
124
- numbers. This string can be copied and pasted to the primer
125
- text file.
126
- """
127
- new = []
128
- found = []
129
- oldstrs = [str(p.seq).upper() for p in self.data]
130
- # no = len(oldstrs)
131
- no, *rest = self.data[-1].name.split("_")
132
- no = int(no) + 1
133
- for p in lst[::-1]:
134
- try:
135
- i = oldstrs.index(str(p.seq).upper())
136
- except ValueError:
137
- i = no + len(new)
138
- # suffix = p.id.removeprefix(f"{str(i)}_") # use this after removing python 3.8
139
- suffix = p.id[len(f"{str(i)}_") :] if p.id.startswith(f"{str(i)}_") else p.id
140
- # suffix.lstrip("_")
141
- newprimer = _copy.copy(p)
142
- newprimer.id = f"{i}_{suffix}"
143
- new.append(newprimer)
144
- else:
145
- found.append(self[i])
146
- new = new[::-1]
147
- newold = new + found
148
- return _pretty_str("\n".join([p.format("primer") for p in newold]))
149
-
150
- def pydna_code_from_list(self, lst: list):
151
- """Pydna code for a list of primer objects."""
152
- indices = []
153
- prstrs = [str(p.seq).upper() for p in self.data]
154
- err = None
155
- for p in lst:
156
- try:
157
- prstrs.index(str(p.seq).upper())
158
- except ValueError as e:
159
- print(f"{p.format('primer')}")
160
- err = e
161
- else:
162
- indices.append(self.data.index(p))
163
- if err:
164
- raise ValueError("At least one primer not in list.")
165
-
166
- curly = "{}"
167
- msg = "from pydna.parsers import parse_primers\n\n"
168
- msg += f"{self.identifier} = {curly}\n\n"
169
- msg += ", ".join(f"{self.identifier}[{i}]" for i in indices)
170
- msg += " = parse_primers('''\n\n"
171
- msg += "\n".join(self[i].format("primer") for i in indices)
172
- msg += "\n''')"
173
- return _pretty_str(msg)
174
-
175
- def open_folder(self):
176
- """Open folder where primer file is located."""
177
- if self.path:
178
- _open_folder(self.path.parent)
179
- else:
180
- raise ValueError("path property not set.")
181
-
182
- code = pydna_code_from_list
183
-
184
-
185
- def check_primer_numbers(pl: list = None):
186
- """Find primers whose number do not match position in list."""
187
- if not pl:
188
- pl = PrimerList()
189
- primers_with_wrong_number = []
190
- for i, p in enumerate(pl):
191
- if not p.name.startswith(str(i)):
192
- primers_with_wrong_number.append(p)
193
- return primers_with_wrong_number
194
-
195
-
196
- def undefined_sequence(pl: list = None):
197
- """Primers in list with N or n instead of a sequence."""
198
- if not pl:
199
- pl = PrimerList()
200
- return [p for p in pl if _re.match("N+", str(p.seq.upper()))]
201
-
202
-
203
- def find_duplicate_primers(pl: list = None):
204
- """Find a list of lists with duplicated primer sequences."""
205
- if not pl:
206
- pl = PrimerList()
207
- pg = {}
208
- for p in pl:
209
- pg.setdefault(str(p.seq).upper(), []).append(p)
210
- return [pl for ps, pl in pg.items() if len(pl) > 1]
211
-
212
-
213
- if __name__ == "__main__":
214
- cache = _os.getenv("pydna_cache")
215
- _os.environ["pydna_cache"] = "nocache"
216
- import doctest
217
-
218
- doctest.testmod(verbose=True, optionflags=doctest.ELLIPSIS)
219
- _os.environ["pydna_cache"] = cache
@@ -1,44 +0,0 @@
1
- pydna/__init__.py,sha256=_BLqB7eQOWvmMql1-tqh-BSkXMYerYFDdAYpwAAxWEw,13391
2
- pydna/_pretty.py,sha256=eMjYTy19AUTA-nntiYEql3FPVe4WzTLSZ4f0Jd6SLfo,1172
3
- pydna/_thermodynamic_data.py,sha256=9_w-97DpkbsWbJGHVijscMvUS_SFt7GxzrxspMRPZSg,10903
4
- pydna/all.py,sha256=i2dR9cAccr3AdtAMMeH4jazpVjxWjfvu8LB3LD9hwgY,2099
5
- pydna/amplicon.py,sha256=09_R_-LNFydsTR9GxNtcFDVjypglp28mbWpnrOJEcq0,5466
6
- pydna/amplify.py,sha256=fjj0GU9Hx7_fzCaqrb1n5T2gQ7mvm5frraQ7b64zdFA,18965
7
- pydna/assembly.py,sha256=Rewf15nWeeUeMwJl5Laxm4nms_UC3zXI7qMtEbBGRpE,19532
8
- pydna/codon.py,sha256=Nxa_03n2wxXKACkzi55bUN1t5xUU_DBRRwh_ZLIb9_o,2568
9
- pydna/common_sub_strings.py,sha256=JD0gXGMymcQCsQtq1OlKuI4QIykKXbo5-OJ8N9XAuuE,11841
10
- pydna/conftest.py,sha256=T5-WmHWLZH3U3ifxnbxd_oOiIFibIrkYpwNacCHlvsY,999
11
- pydna/contig.py,sha256=aNKtXGaHY0c70tEEMHk_9lDMk9DQzjFRO6LK-GPtdwc,7991
12
- pydna/crispr.py,sha256=VbOe_nDVmdhlnYvnnmukJJhRMZr1gk1UK6qOJCCs988,3824
13
- pydna/design.py,sha256=IE04UXQqAkpX1leTZN8KPJjdd9gj1Es_4HNcTZML5Dw,28781
14
- pydna/download.py,sha256=uFoAvWYXr1C30071p9OweMdemvKO-1F2pB5CHo2k31U,1307
15
- pydna/dseq.py,sha256=-iOK3uHplIgYfwbImHzJA2aZ8uXsBwXZbWwkO01-IMM,53601
16
- pydna/dseqrecord.py,sha256=qVWbAWT672TNYAx_R_TDqbTnlxbL2mN-c-I14PyetR0,47238
17
- pydna/editor.py,sha256=Au3kZ5DYqa6MYB3kXJePHOJOioSJ5w7jtlZ8kfHvKm8,3471
18
- pydna/fakeseq.py,sha256=eGeivoppQ8vSPQqggxFXARmUhU6oEBfdnIkGDR_v9UQ,1449
19
- pydna/fusionpcr.py,sha256=uRuHbwmZ2H5SThDUYW-KwxMB1DwqA2Khof7KXiMdxN8,2783
20
- pydna/gateway.py,sha256=bZUASiC93WKwofnqBmG6cKahxXHnXHA26K64BAf8HMM,8447
21
- pydna/gel.py,sha256=yCPXNlF-3HzPVjQxa_NZjpC9UXTPfZBzCmW9m5kWkHo,3554
22
- pydna/genbank.py,sha256=mPtictXh-oOEdj2H6MtDYP2eaJK7vnap-QS33pEMRIk,8933
23
- pydna/genbankfile.py,sha256=wpCBYTysYqFwrGBIN8ean2MAAocdA_7OJ9avHEho9fw,1652
24
- pydna/genbankfixer.py,sha256=D2-I30fIPMndyefNzOaeAYbu6LGHC_SnOyjxJhhMfYw,20695
25
- pydna/genbankrecord.py,sha256=EWRQ9EB7xzIAVqk7ico0bL_JSjR92LXt0UTSQ0HztEI,5771
26
- pydna/goldengate.py,sha256=Fmkbb4kkau9h1o6I-MiQZ0rNHwmD4-1IK0BJaL1MblI,1774
27
- pydna/ladders.py,sha256=2SaTq7_Y8XLvEBK0UqgkB9aWePzG0g84cPiNtJfggx0,3574
28
- pydna/ligate.py,sha256=41YYBcZxGl1PzABZoi-zkRlRcR6sYCzT4rp5HE45A9Q,2205
29
- pydna/myenzymes.py,sha256=v9e9JnykCw6lqoZ4zNcW6cH3DGtGxl0O1WXzJkyhhyk,1834
30
- pydna/myprimers.py,sha256=JtpdejRP6MkKplLv-p5NCMzxBTepYN0CVHSxxP3ms3Q,7362
31
- pydna/parsers.py,sha256=UlG5xh4EsNNPaPK4SoEE6KL52YxkQfLvKJiDm3DB5s4,6927
32
- pydna/primer.py,sha256=7AYWIhr1YbjG0Gak94bU6bTlsRUgWCIbKTndgsgWZ2M,2533
33
- pydna/readers.py,sha256=dsihpjRopxWeeab1bRAK4TRHMBLYK_SpK1j2llHrHk0,1850
34
- pydna/seq.py,sha256=Qwbx1uo-JIYXIuySXevNtxoDgohENHTTTCjPMnn4yjo,7703
35
- pydna/seqrecord.py,sha256=oz2YZR3_tkNj7YgdWmJr0MyREJZvCgvmq1g8hzuzNyQ,23530
36
- pydna/sequence_picker.py,sha256=jYbGUparKyIhDD30BzT2x-olnPpDjv-xvyaeIk6_V4E,1659
37
- pydna/threading_timer_decorator_exit.py,sha256=D91kqjKSavWDnXyc1Fo-CwPYtbmR2DjTXnBYSRXKmSA,2793
38
- pydna/tm.py,sha256=YVXgDMB_AxNyzPR9fYT1YWlfy80paKTl2r0bkLFNxU8,11330
39
- pydna/user_cloning.py,sha256=VSpYX1tdbcD_PzEt69Jz6Lud-yAkYMVXnzVd4v2usnE,692
40
- pydna/utils.py,sha256=7CQ8tkVcTcNY_k1eBbP242ax3X2MMZGZ1cPhHcDY8y4,22084
41
- pydna-5.5.1.dist-info/LICENSE.txt,sha256=u8QfcsnNXZM0UCexerK_MvyA2lPWgeGyUtSYXvLG6Oc,6119
42
- pydna-5.5.1.dist-info/METADATA,sha256=mJGG_H_ccfb97ELbilQYUxFvjIVBNYt7X2Tdwe2Pp0Y,24485
43
- pydna-5.5.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
44
- pydna-5.5.1.dist-info/RECORD,,
File without changes