genop 0.1.0__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.
- genop-0.1.0/PKG-INFO +17 -0
- genop-0.1.0/genop/__init__.py +1 -0
- genop-0.1.0/genop/gene_optimizer.py +269 -0
- genop-0.1.0/genop/models/511145_cai.pkl +0 -0
- genop-0.1.0/genop/models/511145_cei.pkl +0 -0
- genop-0.1.0/genop/models/511145_sub.pkl +0 -0
- genop-0.1.0/genop.egg-info/PKG-INFO +17 -0
- genop-0.1.0/genop.egg-info/SOURCES.txt +10 -0
- genop-0.1.0/genop.egg-info/dependency_links.txt +1 -0
- genop-0.1.0/genop.egg-info/top_level.txt +1 -0
- genop-0.1.0/setup.cfg +4 -0
- genop-0.1.0/setup.py +19 -0
genop-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: genop
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Codon optimization tool
|
|
5
|
+
Home-page: https://github.com/conzaytsev/GeneOptimizer
|
|
6
|
+
Author: Konstantin Zaytsev
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Requires-Python: >3.9
|
|
10
|
+
Dynamic: author
|
|
11
|
+
Dynamic: classifier
|
|
12
|
+
Dynamic: description
|
|
13
|
+
Dynamic: home-page
|
|
14
|
+
Dynamic: requires-python
|
|
15
|
+
Dynamic: summary
|
|
16
|
+
|
|
17
|
+
Python module for codon optimization in genes to achieve specific expression levels.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .gene_optimizer import Optimizer
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
from random import randint, choices
|
|
2
|
+
from importlib.resources import files
|
|
3
|
+
import pickle
|
|
4
|
+
from . import models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def crossingover(sequence1, sequence2):
|
|
8
|
+
point1 = randint(0, len(sequence1))
|
|
9
|
+
point2 = randint(0, len(sequence1))
|
|
10
|
+
while point2 == point1:
|
|
11
|
+
point2 = randint(0, len(sequence1))
|
|
12
|
+
if point1 > point2:
|
|
13
|
+
point1, point2 = point2, point1
|
|
14
|
+
new_sequence1 = sequence1[: point1] + sequence2[point1: point2] + sequence1[point2:]
|
|
15
|
+
new_sequence2 = sequence2[: point1] + sequence1[point1: point2] + sequence2[point2:]
|
|
16
|
+
return new_sequence1, new_sequence2
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def randomize(encoded, codon_dictionary):
|
|
20
|
+
randomized = ''
|
|
21
|
+
for i in encoded:
|
|
22
|
+
randomized += codon_dictionary[i][randint(0, len(codon_dictionary[i]) - 1)]
|
|
23
|
+
return randomized
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def nonrandomize(encoded, triplet_encoded, sixplet_dictionary, sixplet_frequencies, codon_dictionary, codon_context):
|
|
27
|
+
randomized = choices(sixplet_dictionary[encoded[0]], sixplet_frequencies[encoded[0]])[0]
|
|
28
|
+
for i in triplet_encoded[2:]:
|
|
29
|
+
randomized += choices(codon_dictionary[i], codon_context[randomized[-3:]][i])[0]
|
|
30
|
+
return randomized
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def translate(aa_sequence):
|
|
34
|
+
dictionary = {'F': 'TTT', 'L': 'TTA', 'I': 'ATT', 'M': 'ATG', 'V': 'GTT', 'S': 'TCT', 'P': 'CCT', 'T': 'ACT',
|
|
35
|
+
'A': 'GCT', 'Y': 'TAT', 'H': 'CAT', 'Q': 'CAA', 'N': 'AAT', 'K': 'AAA', 'D': 'GAT', 'E': 'GAA',
|
|
36
|
+
'C': 'TGT', 'W': 'TGG', 'R': 'CGT', 'G': 'GGT'}
|
|
37
|
+
nuc_sequence = ''
|
|
38
|
+
for letter in aa_sequence:
|
|
39
|
+
nuc_sequence += dictionary[letter]
|
|
40
|
+
return nuc_sequence
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def read_file(filename):
|
|
44
|
+
genes = []
|
|
45
|
+
|
|
46
|
+
if filename.split('.')[-1] == 'csv':
|
|
47
|
+
with open(filename, 'r') as file:
|
|
48
|
+
data = file.readlines()
|
|
49
|
+
for i in range(len(data)):
|
|
50
|
+
if i > 0:
|
|
51
|
+
data_string = data[i].replace('\n', '').split(';')
|
|
52
|
+
genes.append(data_string[2])
|
|
53
|
+
|
|
54
|
+
elif filename.split('.')[-1] == 'txt':
|
|
55
|
+
with open(filename, 'r') as file:
|
|
56
|
+
for line in file:
|
|
57
|
+
if len(line[:-1]) % 3 == 0 and len(line[:-1]) == line.count('A') + line.count('T') + line.count(
|
|
58
|
+
'G') + line.count('C'):
|
|
59
|
+
genes.append(line[:-1])
|
|
60
|
+
|
|
61
|
+
else:
|
|
62
|
+
gene = ''
|
|
63
|
+
with open(filename, 'r') as file:
|
|
64
|
+
for line in file:
|
|
65
|
+
if line[0] == '>':
|
|
66
|
+
if gene != '' and len(gene) % 3 == 0 and len(gene) == gene.count('A') + gene.count(
|
|
67
|
+
'T') + gene.count('G') + gene.count('C'):
|
|
68
|
+
genes.append(gene)
|
|
69
|
+
gene = ''
|
|
70
|
+
else:
|
|
71
|
+
gene += line[:-1]
|
|
72
|
+
if gene != '' and len(gene) % 3 == 0 and len(gene) == gene.count('A') + gene.count('T') + gene.count(
|
|
73
|
+
'G') + gene.count('C'):
|
|
74
|
+
genes.append(gene)
|
|
75
|
+
return genes
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def gc_content(sequence):
|
|
79
|
+
return (sequence.count('G') + sequence.count('C')) / len(sequence)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def restriction_check(sequence, restriction_sites):
|
|
83
|
+
for site in restriction_sites:
|
|
84
|
+
if sequence.find(site) > -1:
|
|
85
|
+
return False
|
|
86
|
+
return True
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class Optimizer:
|
|
90
|
+
def __init__(self, input_sequence, sequence_type='nucleotide', expression_model='coli', subspace_model='coli', set_size=1000, expression_priority=1,
|
|
91
|
+
subspace_priority=0, center_priority=0, gc_priority=0, n_children=10, max_iterations=300, restriction_sites=''):
|
|
92
|
+
if expression_model == 'coli':
|
|
93
|
+
with open(files(models) / '511145_cei.pkl', 'rb') as file: self.expression_model = pickle.load(file)
|
|
94
|
+
else:
|
|
95
|
+
self.expression_model = expression_model
|
|
96
|
+
if subspace_model == 'coli':
|
|
97
|
+
with open(files(models) / '511145_sub.pkl', 'rb') as file: self.subspace_model = pickle.load(file)
|
|
98
|
+
else:
|
|
99
|
+
self.subspace_model = subspace_model
|
|
100
|
+
|
|
101
|
+
codon_dictionary = [['TTT', 'TTC'],
|
|
102
|
+
['TTA', 'TTG', 'CTT', 'CTC', 'CTA', 'CTG'],
|
|
103
|
+
['ATT', 'ATC', 'ATA'],
|
|
104
|
+
['ATG'],
|
|
105
|
+
['GTT', 'GTC', 'GTA', 'GTG'],
|
|
106
|
+
['TCT', 'TCC', 'TCA', 'TCG', 'AGT', 'AGC'],
|
|
107
|
+
['CCT', 'CCC', 'CCA', 'CCG'],
|
|
108
|
+
['ACT', 'ACC', 'ACA', 'ACG'],
|
|
109
|
+
['GCT', 'GCC', 'GCA', 'GCG'],
|
|
110
|
+
['TAT', 'TAC'],
|
|
111
|
+
['CAT', 'CAC'],
|
|
112
|
+
['CAA', 'CAG'],
|
|
113
|
+
['AAT', 'AAC'],
|
|
114
|
+
['AAA', 'AAG'],
|
|
115
|
+
['GAT', 'GAC'],
|
|
116
|
+
['GAA', 'GAG'],
|
|
117
|
+
['TGT', 'TGC'],
|
|
118
|
+
['TGG'],
|
|
119
|
+
['CGT', 'CGC', 'CGA', 'CGG', 'AGA', 'AGG'],
|
|
120
|
+
['GGT', 'GGC', 'GGA', 'GGG'],
|
|
121
|
+
['TAA', 'TAG', 'TGA']] # Stop
|
|
122
|
+
|
|
123
|
+
reverse_dictionary = {}
|
|
124
|
+
for i in range(len(codon_dictionary)):
|
|
125
|
+
for j in codon_dictionary[i]:
|
|
126
|
+
reverse_dictionary[j] = i
|
|
127
|
+
|
|
128
|
+
triplets = []
|
|
129
|
+
for item in codon_dictionary:
|
|
130
|
+
triplets.extend(item)
|
|
131
|
+
|
|
132
|
+
triplet_encoded = []
|
|
133
|
+
if sequence_type == 'protein':
|
|
134
|
+
for i in range(0, len(input_sequence)):
|
|
135
|
+
triplet_encoded.append(reverse_dictionary[translate(input_sequence)[i:i + 3]])
|
|
136
|
+
else:
|
|
137
|
+
for i in range(0, len(input_sequence), 3):
|
|
138
|
+
triplet_encoded.append(reverse_dictionary[input_sequence[i:i + 3]])
|
|
139
|
+
|
|
140
|
+
sequence_set = []
|
|
141
|
+
if subspace_priority == center_priority == 0:
|
|
142
|
+
while len(sequence_set) < set_size:
|
|
143
|
+
sequence_set.append(randomize(triplet_encoded, codon_dictionary))
|
|
144
|
+
else:
|
|
145
|
+
sixplet_dictionary = []
|
|
146
|
+
for first in codon_dictionary:
|
|
147
|
+
for second in codon_dictionary:
|
|
148
|
+
sixplet_dictionary.append([])
|
|
149
|
+
for first_codon in first:
|
|
150
|
+
for second_codon in second:
|
|
151
|
+
sixplet_dictionary[-1].append(first_codon + second_codon)
|
|
152
|
+
|
|
153
|
+
sixplet_reverse_dictionary = {}
|
|
154
|
+
for i in range(len(sixplet_dictionary)):
|
|
155
|
+
for j in sixplet_dictionary[i]:
|
|
156
|
+
sixplet_reverse_dictionary[j] = i
|
|
157
|
+
|
|
158
|
+
sixplets = []
|
|
159
|
+
for i in triplets:
|
|
160
|
+
for j in triplets:
|
|
161
|
+
sixplets.append(i + j)
|
|
162
|
+
|
|
163
|
+
distribution = self.subspace_model.distribution
|
|
164
|
+
|
|
165
|
+
sixplet_frequencies = []
|
|
166
|
+
for item in sixplet_dictionary:
|
|
167
|
+
sixplet_frequencies.append([])
|
|
168
|
+
for sixplet in item:
|
|
169
|
+
sixplet_frequencies[-1].append(distribution[sixplet])
|
|
170
|
+
|
|
171
|
+
codon_context = {}
|
|
172
|
+
for first_triplet in triplets:
|
|
173
|
+
codon_context[first_triplet] = []
|
|
174
|
+
for item in codon_dictionary:
|
|
175
|
+
codon_context[first_triplet].append(
|
|
176
|
+
[distribution[first_triplet + second_triplet] for second_triplet in item])
|
|
177
|
+
|
|
178
|
+
encoded = []
|
|
179
|
+
if sequence_type == 'protein':
|
|
180
|
+
for i in range(0, len(input_sequence) - 1):
|
|
181
|
+
encoded.append(sixplet_reverse_dictionary[translate(input_sequence)[i:i + 6]])
|
|
182
|
+
else:
|
|
183
|
+
for i in range(0, len(input_sequence) - 3, 3):
|
|
184
|
+
encoded.append(sixplet_reverse_dictionary[input_sequence[i:i + 6]])
|
|
185
|
+
|
|
186
|
+
while len(sequence_set) < set_size:
|
|
187
|
+
sequence = nonrandomize(encoded, triplet_encoded, sixplet_dictionary, sixplet_frequencies,
|
|
188
|
+
codon_dictionary, codon_context)
|
|
189
|
+
if restriction_check(sequence, restriction_sites):
|
|
190
|
+
sequence_set.append(sequence)
|
|
191
|
+
|
|
192
|
+
self.sequence_set = sequence_set
|
|
193
|
+
self.expression_priority = expression_priority
|
|
194
|
+
self.subspace_priority = subspace_priority
|
|
195
|
+
self.center_priority = center_priority
|
|
196
|
+
self.gc_priority = gc_priority
|
|
197
|
+
self.max_iterations = max_iterations
|
|
198
|
+
self.n_children = n_children
|
|
199
|
+
self.restriction_sites = restriction_sites
|
|
200
|
+
self.expression_weight = 0
|
|
201
|
+
self.subspace_weight = 0
|
|
202
|
+
self.center_weight = 0
|
|
203
|
+
self.gc_weight = 0
|
|
204
|
+
|
|
205
|
+
def score(self, sequence, target_score, target_distance, target_center, target_gc):
|
|
206
|
+
value = 0
|
|
207
|
+
if self.expression_priority > 0:
|
|
208
|
+
value += abs(self.expression_model.predict(sequence) - target_score) * self.expression_weight
|
|
209
|
+
if self.subspace_priority > 0:
|
|
210
|
+
value += abs(self.subspace_model.distance(sequence) - target_distance) * self.subspace_weight
|
|
211
|
+
if self.center_priority > 0:
|
|
212
|
+
value += abs(self.subspace_model.center_distance(sequence) - target_center) * self.center_weight
|
|
213
|
+
if self.gc_priority > 0:
|
|
214
|
+
value += abs(gc_content(sequence) - target_gc) * self.gc_weight
|
|
215
|
+
return 1 / value
|
|
216
|
+
|
|
217
|
+
def optimize(self, target_score=10, target_distance=0, target_center=0, target_gc=0):
|
|
218
|
+
self.expression_weight = 0.1 * self.expression_priority
|
|
219
|
+
|
|
220
|
+
distance_variation = sorted(self.subspace_model.distances)
|
|
221
|
+
self.subspace_weight = 1 / abs(distance_variation[int(len(distance_variation) * 0.001)] - distance_variation[
|
|
222
|
+
int(len(distance_variation) * 0.999)]) * self.subspace_priority
|
|
223
|
+
|
|
224
|
+
self.center_weight = 1 * self.center_priority
|
|
225
|
+
|
|
226
|
+
self.gc_weight = 1 * self.gc_priority
|
|
227
|
+
|
|
228
|
+
score_set = []
|
|
229
|
+
for sequence in self.sequence_set:
|
|
230
|
+
score_set.append(self.score(sequence, target_score, target_distance, target_center, target_gc))
|
|
231
|
+
|
|
232
|
+
sequence_set = [x for y, x in sorted(zip(score_set, self.sequence_set))]
|
|
233
|
+
score_set.sort()
|
|
234
|
+
|
|
235
|
+
counter = 0
|
|
236
|
+
best_score = 0
|
|
237
|
+
while counter < self.max_iterations:
|
|
238
|
+
counter += 1
|
|
239
|
+
children = []
|
|
240
|
+
while len(children) < self.n_children:
|
|
241
|
+
parent1 = choices(sequence_set, score_set)[0]
|
|
242
|
+
parent2 = choices(sequence_set, score_set)[0]
|
|
243
|
+
while parent2 == parent1:
|
|
244
|
+
parent2 = choices(sequence_set, score_set)[0]
|
|
245
|
+
child1, child2 = crossingover(parent1, parent2)
|
|
246
|
+
if child1 != parent1 and child1 != parent2:
|
|
247
|
+
if restriction_check(child1, self.restriction_sites):
|
|
248
|
+
children.append(child1)
|
|
249
|
+
if restriction_check(child2, self.restriction_sites):
|
|
250
|
+
children.append(child2)
|
|
251
|
+
|
|
252
|
+
children_score = []
|
|
253
|
+
for sequence in children:
|
|
254
|
+
children_score.append(self.score(sequence, target_score, target_distance, target_center, target_gc))
|
|
255
|
+
|
|
256
|
+
sequence_set.extend(children)
|
|
257
|
+
score_set.extend(children_score)
|
|
258
|
+
sequence_set = [x for y, x in sorted(zip(score_set, sequence_set))]
|
|
259
|
+
score_set.sort()
|
|
260
|
+
|
|
261
|
+
for i in range(len(children)):
|
|
262
|
+
sequence_set.pop(0)
|
|
263
|
+
score_set.pop(0)
|
|
264
|
+
|
|
265
|
+
if score_set[-1] > best_score:
|
|
266
|
+
best_score = score_set[-1]
|
|
267
|
+
counter = 0
|
|
268
|
+
|
|
269
|
+
return sequence_set[-1]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: genop
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Codon optimization tool
|
|
5
|
+
Home-page: https://github.com/conzaytsev/GeneOptimizer
|
|
6
|
+
Author: Konstantin Zaytsev
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Requires-Python: >3.9
|
|
10
|
+
Dynamic: author
|
|
11
|
+
Dynamic: classifier
|
|
12
|
+
Dynamic: description
|
|
13
|
+
Dynamic: home-page
|
|
14
|
+
Dynamic: requires-python
|
|
15
|
+
Dynamic: summary
|
|
16
|
+
|
|
17
|
+
Python module for codon optimization in genes to achieve specific expression levels.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
setup.py
|
|
2
|
+
genop/__init__.py
|
|
3
|
+
genop/gene_optimizer.py
|
|
4
|
+
genop.egg-info/PKG-INFO
|
|
5
|
+
genop.egg-info/SOURCES.txt
|
|
6
|
+
genop.egg-info/dependency_links.txt
|
|
7
|
+
genop.egg-info/top_level.txt
|
|
8
|
+
genop/models/511145_cai.pkl
|
|
9
|
+
genop/models/511145_cei.pkl
|
|
10
|
+
genop/models/511145_sub.pkl
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
genop
|
genop-0.1.0/setup.cfg
ADDED
genop-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
setup(
|
|
5
|
+
name="genop",
|
|
6
|
+
version='0.1.0',
|
|
7
|
+
author="Konstantin Zaytsev",
|
|
8
|
+
url='https://github.com/conzaytsev/GeneOptimizer',
|
|
9
|
+
description='Codon optimization tool',
|
|
10
|
+
long_description='Python module for codon optimization in genes to achieve specific expression levels.',
|
|
11
|
+
packages=['genop'],
|
|
12
|
+
install_requires=[],
|
|
13
|
+
python_requires='>3.9',
|
|
14
|
+
package_data={'genop': ['models/*.pkl']},
|
|
15
|
+
classifiers= [
|
|
16
|
+
'License :: OSI Approved :: MIT License',
|
|
17
|
+
'Programming Language :: Python :: 3'
|
|
18
|
+
]
|
|
19
|
+
)
|