Fast-HInt-ppi 0.1.0__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.
- Fast_HInt/File_proteins.py +780 -0
- Fast_HInt/HInt.py +244 -0
- Fast_HInt/Scoring_HInt.py +954 -0
- Fast_HInt/Utils_HInt.py +1313 -0
- Fast_HInt/__init__.py +1 -0
- Fast_HInt/get_good_inter_pae.py +340 -0
- fast_hint_ppi-0.1.0.dist-info/METADATA +33 -0
- fast_hint_ppi-0.1.0.dist-info/RECORD +11 -0
- fast_hint_ppi-0.1.0.dist-info/WHEEL +5 -0
- fast_hint_ppi-0.1.0.dist-info/entry_points.txt +2 -0
- fast_hint_ppi-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
""" Create File_proteins object
|
|
2
|
+
|
|
3
|
+
Author: Quentin Rouger
|
|
4
|
+
"""
|
|
5
|
+
import urllib.request
|
|
6
|
+
import re
|
|
7
|
+
from .Utils_HInt import *
|
|
8
|
+
import os
|
|
9
|
+
import copy
|
|
10
|
+
from rdkit import Chem,RDLogger
|
|
11
|
+
|
|
12
|
+
RDLogger.DisableLog('rdApp.*') #Disable RDKit warnings for SMILES parsing
|
|
13
|
+
|
|
14
|
+
class File_proteins() :
|
|
15
|
+
"""
|
|
16
|
+
Manipulate and save the file that contains all proteins.
|
|
17
|
+
"""
|
|
18
|
+
def __init__ (self, path_txt_file, baits, AF_version) :
|
|
19
|
+
"""
|
|
20
|
+
Constructor :
|
|
21
|
+
Set attributes for a single entry file.
|
|
22
|
+
|
|
23
|
+
Parameters:
|
|
24
|
+
-----------
|
|
25
|
+
path_txt_file : string
|
|
26
|
+
baits : list
|
|
27
|
+
AF_version : string (2 or 3)
|
|
28
|
+
"""
|
|
29
|
+
self.set_all_att(path_txt_file, baits, AF_version)
|
|
30
|
+
|
|
31
|
+
def set_proteins_sequence_SP (self, new_protein_sequence) :
|
|
32
|
+
"""
|
|
33
|
+
Sets a dict of all sequences with Signal peptide.
|
|
34
|
+
|
|
35
|
+
Parameters:
|
|
36
|
+
----------
|
|
37
|
+
new_protein_sequence = dictionary
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
----------
|
|
41
|
+
"""
|
|
42
|
+
self.protein_sequence_SP = new_protein_sequence
|
|
43
|
+
|
|
44
|
+
def set_proteins_sequence_no_SP (self, new_protein_sequence) :
|
|
45
|
+
"""
|
|
46
|
+
Sets a dict of all sequences without Signal peptide and set a lenght dict.
|
|
47
|
+
|
|
48
|
+
Parameters:
|
|
49
|
+
----------
|
|
50
|
+
new_protein_sequence = dictionary
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
----------
|
|
54
|
+
"""
|
|
55
|
+
self.protein_sequence_no_SP = new_protein_sequence
|
|
56
|
+
self.find_prot_lenght(new_protein_sequence)
|
|
57
|
+
|
|
58
|
+
def set_proteins (self, new_protein) :
|
|
59
|
+
"""
|
|
60
|
+
Sets a list of all proteins.
|
|
61
|
+
|
|
62
|
+
Parameters:
|
|
63
|
+
----------
|
|
64
|
+
new_protein = list
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
----------
|
|
68
|
+
"""
|
|
69
|
+
self.protein = new_protein
|
|
70
|
+
|
|
71
|
+
def set_file_name (self, filename) :
|
|
72
|
+
"""
|
|
73
|
+
Sets new filename for the txt file.
|
|
74
|
+
|
|
75
|
+
Parameters:
|
|
76
|
+
----------
|
|
77
|
+
filename = string
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
----------
|
|
81
|
+
"""
|
|
82
|
+
self.file_name = filename
|
|
83
|
+
|
|
84
|
+
def set_lenght_prot (self, lenght_prot) :
|
|
85
|
+
"""
|
|
86
|
+
Sets lenght of all proteins.
|
|
87
|
+
|
|
88
|
+
Parameters:
|
|
89
|
+
----------
|
|
90
|
+
lenght_prot = dictionary
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
----------
|
|
94
|
+
"""
|
|
95
|
+
self.lenght_prot = lenght_prot
|
|
96
|
+
|
|
97
|
+
def set_result_dict (self, result_dict) :
|
|
98
|
+
"""
|
|
99
|
+
Sets dict who will contains all results.
|
|
100
|
+
|
|
101
|
+
Parameters:
|
|
102
|
+
----------
|
|
103
|
+
result_dict = dict
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
----------
|
|
107
|
+
"""
|
|
108
|
+
self.result_dict = result_dict
|
|
109
|
+
|
|
110
|
+
def set_possible_prey (self, possible_prey) :
|
|
111
|
+
"""
|
|
112
|
+
Sets list of all possible prey.
|
|
113
|
+
|
|
114
|
+
Parameters:
|
|
115
|
+
----------
|
|
116
|
+
possible_prey : list
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
----------
|
|
120
|
+
"""
|
|
121
|
+
self.possible_prey = possible_prey
|
|
122
|
+
|
|
123
|
+
def set_deeploc (self, deeploc) :
|
|
124
|
+
"""
|
|
125
|
+
Sets a dict of all DeepLoc results.
|
|
126
|
+
|
|
127
|
+
Parameters:
|
|
128
|
+
----------
|
|
129
|
+
deeploc : dictionary
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
----------
|
|
133
|
+
"""
|
|
134
|
+
self.deeploc = deeploc
|
|
135
|
+
|
|
136
|
+
def set_int_score (self, int_score) :
|
|
137
|
+
"""
|
|
138
|
+
Sets a dict of interaction score.
|
|
139
|
+
|
|
140
|
+
Parameters:
|
|
141
|
+
----------
|
|
142
|
+
int_score : dictionary
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
----------
|
|
146
|
+
"""
|
|
147
|
+
self.int_score = int_score
|
|
148
|
+
|
|
149
|
+
def set_homo_score (self, homo_score) :
|
|
150
|
+
"""
|
|
151
|
+
Sets a dict of homo-oligomer score.
|
|
152
|
+
|
|
153
|
+
Parameters:
|
|
154
|
+
----------
|
|
155
|
+
homo_score : dictionary
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
----------
|
|
159
|
+
"""
|
|
160
|
+
self.homo_score = homo_score
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def set_prot_SP (self, dict_SP) :
|
|
164
|
+
"""
|
|
165
|
+
Sets a dict indicating whether each protein has a signal peptide (SP) or not.
|
|
166
|
+
|
|
167
|
+
Parameters:
|
|
168
|
+
----------
|
|
169
|
+
int_score : dictionary
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
----------
|
|
173
|
+
"""
|
|
174
|
+
self.prot_SP = dict_SP
|
|
175
|
+
|
|
176
|
+
def set_uniprot_prot (self, list_uniprot) :
|
|
177
|
+
"""
|
|
178
|
+
Sets a list of protein set with uniprotID.
|
|
179
|
+
|
|
180
|
+
Parameters:
|
|
181
|
+
----------
|
|
182
|
+
list_uniprot : list
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
----------
|
|
186
|
+
"""
|
|
187
|
+
self.list_uniprot = list_uniprot
|
|
188
|
+
|
|
189
|
+
def set_compounds (self, compounds) :
|
|
190
|
+
"""
|
|
191
|
+
Set a dict of compounds. Key of the dict is name of the compound and the value is the smile.
|
|
192
|
+
|
|
193
|
+
Parameters:
|
|
194
|
+
----------
|
|
195
|
+
compounds : dict
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
----------
|
|
199
|
+
"""
|
|
200
|
+
self.compounds = compounds
|
|
201
|
+
|
|
202
|
+
def set_time_dict (self, time_dict) :
|
|
203
|
+
"""
|
|
204
|
+
Set a dict of differents step timing. Key of the dict is step and the value list of number of prey and time.
|
|
205
|
+
|
|
206
|
+
Parameters:
|
|
207
|
+
----------
|
|
208
|
+
time_dict : dict
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
----------
|
|
212
|
+
"""
|
|
213
|
+
self.time_dict = time_dict
|
|
214
|
+
|
|
215
|
+
def get_proteins_sequence_SP (self) :
|
|
216
|
+
"""
|
|
217
|
+
Return the new amino acid sequence dictionary with SP.
|
|
218
|
+
|
|
219
|
+
Parameters:
|
|
220
|
+
----------
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
----------
|
|
224
|
+
proteins_sequence : dictionary
|
|
225
|
+
"""
|
|
226
|
+
return self.protein_sequence_SP
|
|
227
|
+
|
|
228
|
+
def get_proteins_sequence_no_SP (self) :
|
|
229
|
+
"""
|
|
230
|
+
Return the new amino acid sequence dictionary without SP.
|
|
231
|
+
|
|
232
|
+
Parameters:
|
|
233
|
+
----------
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
----------
|
|
237
|
+
proteins_sequence : dictionary
|
|
238
|
+
"""
|
|
239
|
+
return self.protein_sequence_no_SP
|
|
240
|
+
|
|
241
|
+
def get_proteins (self) :
|
|
242
|
+
"""
|
|
243
|
+
Return the new proteins name list.
|
|
244
|
+
|
|
245
|
+
Parameters:
|
|
246
|
+
----------
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
----------
|
|
250
|
+
protein : list
|
|
251
|
+
"""
|
|
252
|
+
return self.protein
|
|
253
|
+
|
|
254
|
+
def get_file_name (self) :
|
|
255
|
+
"""
|
|
256
|
+
Return the name of the file.
|
|
257
|
+
|
|
258
|
+
Parameters:
|
|
259
|
+
----------
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
----------
|
|
263
|
+
file_name : string
|
|
264
|
+
"""
|
|
265
|
+
return self.file_name
|
|
266
|
+
|
|
267
|
+
def get_lenght_prot (self) :
|
|
268
|
+
"""
|
|
269
|
+
Return the lenght of proteins.
|
|
270
|
+
|
|
271
|
+
Parameters:
|
|
272
|
+
----------
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
----------
|
|
276
|
+
lenght_prot : dictionary
|
|
277
|
+
"""
|
|
278
|
+
return self.lenght_prot
|
|
279
|
+
|
|
280
|
+
def get_result_dict (self) :
|
|
281
|
+
"""
|
|
282
|
+
Return new result dict.
|
|
283
|
+
|
|
284
|
+
Parameters:
|
|
285
|
+
----------
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
----------
|
|
289
|
+
result_dict : dict
|
|
290
|
+
"""
|
|
291
|
+
return self.result_dict
|
|
292
|
+
|
|
293
|
+
def get_possible_prey (self) :
|
|
294
|
+
"""
|
|
295
|
+
Return list of all possible prey.
|
|
296
|
+
|
|
297
|
+
Parameters:
|
|
298
|
+
----------
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
----------
|
|
302
|
+
possible_prey : list
|
|
303
|
+
"""
|
|
304
|
+
return self.possible_prey
|
|
305
|
+
|
|
306
|
+
def get_deeploc (self) :
|
|
307
|
+
"""
|
|
308
|
+
Return the DeepLoc result dict.
|
|
309
|
+
|
|
310
|
+
Parameters:
|
|
311
|
+
----------
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
----------
|
|
315
|
+
deeploc : dictionary
|
|
316
|
+
"""
|
|
317
|
+
return self.deeploc
|
|
318
|
+
|
|
319
|
+
def get_int_score (self) :
|
|
320
|
+
"""
|
|
321
|
+
Return the interaction result dict.
|
|
322
|
+
|
|
323
|
+
Parameters:
|
|
324
|
+
----------
|
|
325
|
+
|
|
326
|
+
Returns:
|
|
327
|
+
----------
|
|
328
|
+
int_score : dictionary
|
|
329
|
+
"""
|
|
330
|
+
return self.int_score
|
|
331
|
+
|
|
332
|
+
def get_homo_score (self) :
|
|
333
|
+
"""
|
|
334
|
+
Return the homo-oligomer result dict.
|
|
335
|
+
|
|
336
|
+
Parameters:
|
|
337
|
+
----------
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
----------
|
|
341
|
+
homo_score : dictionary
|
|
342
|
+
"""
|
|
343
|
+
return self.homo_score
|
|
344
|
+
|
|
345
|
+
def get_prot_SP (self) :
|
|
346
|
+
"""
|
|
347
|
+
Return a dict indicating whether each protein has a signal peptide (SP) or not.
|
|
348
|
+
|
|
349
|
+
Parameters:
|
|
350
|
+
----------
|
|
351
|
+
|
|
352
|
+
Returns:
|
|
353
|
+
----------
|
|
354
|
+
int_score : dictionary
|
|
355
|
+
"""
|
|
356
|
+
return self.prot_SP
|
|
357
|
+
|
|
358
|
+
def get_uniprot_prot (self) :
|
|
359
|
+
"""
|
|
360
|
+
Return a list of protein set with uniprotID.
|
|
361
|
+
|
|
362
|
+
Parameters:
|
|
363
|
+
----------
|
|
364
|
+
|
|
365
|
+
Returns:
|
|
366
|
+
----------
|
|
367
|
+
list_uniprot : list
|
|
368
|
+
"""
|
|
369
|
+
return self.list_uniprot
|
|
370
|
+
|
|
371
|
+
def get_compounds (self) :
|
|
372
|
+
"""
|
|
373
|
+
Return a dict of compounds.
|
|
374
|
+
|
|
375
|
+
Parameters:
|
|
376
|
+
----------
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
----------
|
|
380
|
+
compounds : dict
|
|
381
|
+
"""
|
|
382
|
+
return self.compounds
|
|
383
|
+
|
|
384
|
+
def get_time_dict (self) :
|
|
385
|
+
"""
|
|
386
|
+
Return a dict of timings.
|
|
387
|
+
|
|
388
|
+
Parameters:
|
|
389
|
+
----------
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
----------
|
|
393
|
+
time_dict : dict
|
|
394
|
+
"""
|
|
395
|
+
return self.time_dict
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
### Generating of features and pre-file to run multimer
|
|
400
|
+
|
|
401
|
+
def set_all_att (self, path_txt, baits, AF_version) :
|
|
402
|
+
"""
|
|
403
|
+
Initialize and populate all attributes from a protein input text file.
|
|
404
|
+
|
|
405
|
+
This method parses a text file containing protein identifiers and/or FASTA sequences, cleans NCBI-formatted headers, validates protein uniqueness,
|
|
406
|
+
checks sequence validity, and initializes all internal data structures required for downstream analyses.
|
|
407
|
+
|
|
408
|
+
The input file may contain :
|
|
409
|
+
- Comma-separated protein identifiers
|
|
410
|
+
- FASTA-formatted protein sequences
|
|
411
|
+
- NCBI-style headers, which are automatically cleaned and normalized
|
|
412
|
+
|
|
413
|
+
Parameters :
|
|
414
|
+
----------
|
|
415
|
+
path_txt : string
|
|
416
|
+
baits : list
|
|
417
|
+
AF_version : string (2 or 3)
|
|
418
|
+
|
|
419
|
+
Notes :
|
|
420
|
+
----------
|
|
421
|
+
- Protein identifiers are converted to uppercase for consistency.
|
|
422
|
+
- FASTA headers are simplified by extracting protein identifiers from NCBI annotations.
|
|
423
|
+
- Sequences containing non-standard amino acids are rejected to ensure compatibility with MSA generation and peptid signal.
|
|
424
|
+
"""
|
|
425
|
+
new_proteins = list()
|
|
426
|
+
new_compounds = dict()
|
|
427
|
+
uniprot_prot = list()
|
|
428
|
+
sequence_SP = dict()
|
|
429
|
+
result_dict = dict()
|
|
430
|
+
prot_SP = dict()
|
|
431
|
+
already_fasta = dict()
|
|
432
|
+
int_score = dict()
|
|
433
|
+
homo_score = dict()
|
|
434
|
+
time_dict = dict()
|
|
435
|
+
save_prot = ""
|
|
436
|
+
list_new_prot_name = list()
|
|
437
|
+
with open(path_txt,"r") as check_f : #clean ncbi file
|
|
438
|
+
new_fasta = str()
|
|
439
|
+
for line in check_f :
|
|
440
|
+
if line[0] == ">" and "[protein_id=" in line or "[locus_tag=" in line or "[gbkey=" in line : #clean ncbi file
|
|
441
|
+
scrap_name = line.split(" ")[1].split("=")[1][0:len(line.split(" ")[1].split("=")[1])-1]
|
|
442
|
+
if scrap_name in list_new_prot_name :
|
|
443
|
+
for i in range(1,100) :
|
|
444
|
+
new_name = scrap_name + "_" + str(i)
|
|
445
|
+
if new_name not in list_new_prot_name :
|
|
446
|
+
scrap_name = new_name
|
|
447
|
+
break
|
|
448
|
+
new_fasta += ">" + scrap_name + "\n"
|
|
449
|
+
list_new_prot_name.append(scrap_name)
|
|
450
|
+
elif line[0] == ">" and " "in line :
|
|
451
|
+
scrap_name = line.split(" ")[0][1:]
|
|
452
|
+
new_fasta += ">" + scrap_name + "\n"
|
|
453
|
+
list_new_prot_name.append(scrap_name)
|
|
454
|
+
else :
|
|
455
|
+
new_fasta += line.replace("*", "")
|
|
456
|
+
with open(path_txt,"w") as w_file :
|
|
457
|
+
w_file.write(new_fasta)
|
|
458
|
+
with open(path_txt,"r") as in_file :
|
|
459
|
+
for line in in_file :
|
|
460
|
+
if "," in str(line) or (line[0] != ">" and save_prot == "" and line.strip() != "") :
|
|
461
|
+
save_prot = ""
|
|
462
|
+
new_line = (line.strip().split(","))
|
|
463
|
+
for prot in new_line :
|
|
464
|
+
clean_prot = prot.upper().strip()
|
|
465
|
+
compound_name = ""
|
|
466
|
+
mol = None
|
|
467
|
+
if ":" in clean_prot : #compounds set up
|
|
468
|
+
compound_name = clean_prot.split(":")[0]
|
|
469
|
+
smile = clean_prot.split(":")[1]
|
|
470
|
+
smile = smile.replace("CL","Cl")
|
|
471
|
+
smile = smile.replace("BR","Br")
|
|
472
|
+
smile = smile.replace("FL","Fl") #Clean smile
|
|
473
|
+
mol = Chem.MolFromSmiles(smile) #check if the line is a SMILES code
|
|
474
|
+
if clean_prot in new_proteins or compound_name in new_compounds.values() :
|
|
475
|
+
raise ValueError(f"Protein {clean_prot} is duplicated in the input file.")
|
|
476
|
+
else :
|
|
477
|
+
if mol is not None :
|
|
478
|
+
if ":" not in clean_prot :
|
|
479
|
+
raise ValueError(f"Missing compound name for {clean_prot}. Compounds should be in the format 'CompoundName:SMILES'.")
|
|
480
|
+
else :
|
|
481
|
+
mol_with_H = Chem.AddHs(mol) #Add explicit hydrogens to the molecule to ensure accurate SMILES representation
|
|
482
|
+
smiles_H = Chem.MolToSmiles(mol_with_H)
|
|
483
|
+
new_compounds[compound_name] = smiles_H
|
|
484
|
+
result_dict[compound_name] = dict()
|
|
485
|
+
int_score[compound_name] = dict()
|
|
486
|
+
else :
|
|
487
|
+
new_proteins.append(clean_prot)
|
|
488
|
+
uniprot_prot.append(clean_prot)
|
|
489
|
+
result_dict[clean_prot] = dict()
|
|
490
|
+
int_score[clean_prot] = dict()
|
|
491
|
+
homo_score[clean_prot] = dict()
|
|
492
|
+
elif line[0] == ">" :
|
|
493
|
+
save_prot = line[1:len(line)].strip("\n").strip(" ")
|
|
494
|
+
if save_prot in new_proteins :
|
|
495
|
+
raise ValueError(f"Protein {save_prot} is duplicated in the input file.")
|
|
496
|
+
else :
|
|
497
|
+
new_proteins.append(save_prot)
|
|
498
|
+
already_fasta[save_prot] = str()
|
|
499
|
+
sequence_SP[save_prot] = ""
|
|
500
|
+
result_dict[save_prot] = dict()
|
|
501
|
+
int_score[save_prot] = dict()
|
|
502
|
+
homo_score[save_prot] = dict()
|
|
503
|
+
elif len(line) > 1 and save_prot != "" :
|
|
504
|
+
sequence_SP[save_prot] = sequence_SP[save_prot] + line.strip("\n").strip("\t").replace(" ","").replace("-","")
|
|
505
|
+
for aa in ["O", "B", "Z", "J", "X", "U"] :
|
|
506
|
+
if aa in line.strip("\n") :
|
|
507
|
+
raise ValueError(f"Sequence {save_prot} contains {aa}.")
|
|
508
|
+
if new_compounds != {} :
|
|
509
|
+
if AF_version != "3" :
|
|
510
|
+
raise ValueError("Compounds screening need AlphaFold3.")
|
|
511
|
+
for protein in new_proteins :
|
|
512
|
+
if protein not in baits :
|
|
513
|
+
raise ValueError("HInt doesn't allow to screen compounds and proteins. Please remove no bait protein from the input file.")
|
|
514
|
+
self.set_time_dict(time_dict)
|
|
515
|
+
self.set_compounds(new_compounds)
|
|
516
|
+
self.set_uniprot_prot(uniprot_prot)
|
|
517
|
+
self.set_file_name(path_txt)
|
|
518
|
+
self.set_proteins(new_proteins)
|
|
519
|
+
self.set_possible_prey(new_proteins)
|
|
520
|
+
self.set_proteins_sequence_SP(sequence_SP)
|
|
521
|
+
self.set_int_score(int_score)
|
|
522
|
+
self.set_homo_score(homo_score)
|
|
523
|
+
self.set_result_dict(result_dict)
|
|
524
|
+
self.set_prot_SP(prot_SP)
|
|
525
|
+
|
|
526
|
+
def check_save_dict (self, Path_Pickle_Feature) :
|
|
527
|
+
"""
|
|
528
|
+
Inspect previously saved computation states and determine missing features for each protein.
|
|
529
|
+
|
|
530
|
+
This method compares the current protein set and sequences with the persistent save dictionary (save_dict.pkl) in order to identify which
|
|
531
|
+
computational steps must be recomputed. It verifies the presence and consistency of :
|
|
532
|
+
- Multiple sequence alignments (MSA, .a3m files)
|
|
533
|
+
- Feature pickle files (.pkl)
|
|
534
|
+
- DeepLoc subcellular localization predictions
|
|
535
|
+
- Signal peptide annotations
|
|
536
|
+
- Interaction scores
|
|
537
|
+
|
|
538
|
+
Parameters :
|
|
539
|
+
----------
|
|
540
|
+
Path_Pickle_Feature : str
|
|
541
|
+
|
|
542
|
+
Returns :
|
|
543
|
+
----------
|
|
544
|
+
need_msa : list
|
|
545
|
+
need_pkl : list
|
|
546
|
+
need_DeepLoc : list
|
|
547
|
+
|
|
548
|
+
Notes :
|
|
549
|
+
----------
|
|
550
|
+
- Sequence mismatches between MSAs and cached data trigger a full reset for the affected protein.
|
|
551
|
+
- Interaction scores are invalidated if the corresponding structural models are missing.
|
|
552
|
+
- UniProt sequences are retrieved using the API and cleaned to remove formatting artifacts.
|
|
553
|
+
- The save dictionary is always updated at the end of the procedure.
|
|
554
|
+
"""
|
|
555
|
+
need_msa = list()
|
|
556
|
+
need_pkl = list()
|
|
557
|
+
need_DeepLoc = list()
|
|
558
|
+
protein_sequence_no_SP = dict()
|
|
559
|
+
deeploc_prot = dict()
|
|
560
|
+
prot_SP = dict()
|
|
561
|
+
int_score = self.get_int_score()
|
|
562
|
+
homo_score = self.get_homo_score()
|
|
563
|
+
result_dict = self.get_result_dict()
|
|
564
|
+
pattern = r"SQ SEQUENCE .* .*\n([\s\S]*)"
|
|
565
|
+
del_car = ["\n"," ","//"]
|
|
566
|
+
|
|
567
|
+
sequences_SP = self.get_proteins_sequence_SP()
|
|
568
|
+
proteins = self.get_proteins()
|
|
569
|
+
|
|
570
|
+
if os.path.isfile('log_file/save_dict.pkl') == True :
|
|
571
|
+
with open('log_file/save_dict.pkl', 'rb') as save_dict :
|
|
572
|
+
all_info = pickle.load(save_dict)
|
|
573
|
+
deeploc_prot = copy.deepcopy(all_info["deeploc"])
|
|
574
|
+
protein_sequence_no_SP = copy.deepcopy(all_info["sequence_no_SP"])
|
|
575
|
+
int_score.update(copy.deepcopy(all_info["int_score"]))
|
|
576
|
+
homo_score.update(copy.deepcopy(all_info["homo_score"]))
|
|
577
|
+
prot_SP = copy.deepcopy(all_info["Signal_peptide"])
|
|
578
|
+
for protein in proteins :
|
|
579
|
+
result_dict[protein] = dict()
|
|
580
|
+
if protein in deeploc_prot.keys() : #if protein in deeploc of save dict
|
|
581
|
+
result_dict[protein]["DeepLoc"] = deeploc_prot[protein]
|
|
582
|
+
if protein in prot_SP.keys() : #if protein in SP of save dict
|
|
583
|
+
result_dict[protein]["Signal_peptide"] = prot_SP[protein]
|
|
584
|
+
if protein in all_info["sequence_SP"].keys() : #if protein in sequence_SP of save dict
|
|
585
|
+
if protein in sequences_SP.keys() : #check if two sequence match
|
|
586
|
+
if sequences_SP[protein] != all_info["sequence_SP"][protein] : #if not match, remove MSA files and start at zero
|
|
587
|
+
cmd = f"rm -rf {Path_Pickle_Feature}/*{protein}*"
|
|
588
|
+
cmd2 = f"rm -rf ./result_PPI_int/*{protein}*"
|
|
589
|
+
cmd3 = f"rm -rf ./result_homo_int/*{protein}*"
|
|
590
|
+
os.system(cmd)
|
|
591
|
+
os.system(cmd2)
|
|
592
|
+
os.system(cmd3)
|
|
593
|
+
need_msa.append(protein)
|
|
594
|
+
need_DeepLoc.append(protein)
|
|
595
|
+
int_score[protein] = dict() #remove int score
|
|
596
|
+
homo_score[protein] = dict()
|
|
597
|
+
else : #sequences match, set all arguments
|
|
598
|
+
sequences_SP[protein] = all_info["sequence_SP"][protein]
|
|
599
|
+
if protein not in all_info["sequence_no_SP"].keys() :
|
|
600
|
+
need_msa.append(protein)
|
|
601
|
+
if protein not in all_info["deeploc"].keys() :
|
|
602
|
+
need_DeepLoc.append(protein)
|
|
603
|
+
|
|
604
|
+
else : #protein not in fasta format, so UniprotID is good
|
|
605
|
+
if protein in all_info["sequence_SP"].keys() :
|
|
606
|
+
sequences_SP[protein] = all_info["sequence_SP"][protein]
|
|
607
|
+
if protein not in all_info["sequence_no_SP"].keys() :
|
|
608
|
+
need_msa.append(protein)
|
|
609
|
+
if protein not in all_info["deeploc"].keys() :
|
|
610
|
+
need_DeepLoc.append(protein)
|
|
611
|
+
if protein not in all_info["sequence_SP"].keys() :
|
|
612
|
+
if protein not in sequences_SP.keys() : #if protein need sequence in Uniprot
|
|
613
|
+
logger.info("Search sequence for " + protein)
|
|
614
|
+
try:
|
|
615
|
+
urllib.request.urlretrieve("https://rest.uniprot.org/uniprotkb/"+protein+".txt","log_file/temp_file.txt")
|
|
616
|
+
except Exception as e :
|
|
617
|
+
raise Exception(f"{protein} is not a compliant UniprotID")
|
|
618
|
+
|
|
619
|
+
with open("log_file/temp_file.txt","r") as in_file:
|
|
620
|
+
for seq in re.finditer(pattern, in_file.read()) :
|
|
621
|
+
sequences_SP[protein] = seq.group(1)
|
|
622
|
+
# with open("temp_file.txt","r") as in_file:
|
|
623
|
+
# for name in re.finditer(pattern2, in_file.read()) :
|
|
624
|
+
# names[protein] = name.group(1)
|
|
625
|
+
for car in del_car :
|
|
626
|
+
sequences_SP[protein] = sequences_SP[protein].replace(car,"")
|
|
627
|
+
os.remove("log_file/temp_file.txt")
|
|
628
|
+
need_DeepLoc.append(protein) #add of new protein in txt file
|
|
629
|
+
need_msa.append(protein)
|
|
630
|
+
else : #protein in fasta format, who don't have sequence without SP and DeepLoc
|
|
631
|
+
need_DeepLoc.append(protein)
|
|
632
|
+
need_msa.append(protein)
|
|
633
|
+
if os.path.isfile(f"{Path_Pickle_Feature}/{protein}.a3m") == False and protein not in need_msa : #proteins without msa
|
|
634
|
+
need_msa.append(protein)
|
|
635
|
+
cmd = f"rm -rf {Path_Pickle_Feature}/*{protein}*" #remove residue files
|
|
636
|
+
os.system(cmd)
|
|
637
|
+
int_score[protein] = dict() #remove int score
|
|
638
|
+
homo_score[protein] = dict()
|
|
639
|
+
if os.path.isfile(f"{Path_Pickle_Feature}/{protein}.pkl") == False and os.path.isfile(f"{Path_Pickle_Feature}/{protein}.a3m") == True : #proteins with msa without pkl file
|
|
640
|
+
need_pkl.append(protein)
|
|
641
|
+
if os.path.isfile(f"{Path_Pickle_Feature}/{protein}.a3m") == True and protein not in need_msa : #check sequence in msa file match with save dict
|
|
642
|
+
with open(f"{Path_Pickle_Feature}/{protein}.a3m","r") as msa_file :
|
|
643
|
+
index = 0
|
|
644
|
+
for line in msa_file :
|
|
645
|
+
if index == 1 :
|
|
646
|
+
msa_seq = line.strip("\n")
|
|
647
|
+
break
|
|
648
|
+
if line[0] == ">" :
|
|
649
|
+
index += 1
|
|
650
|
+
if index == 0 : #empty msa file, so remove it and start at zero
|
|
651
|
+
cmd = f"rm -rf {Path_Pickle_Feature}/*{protein}*"
|
|
652
|
+
os.system(cmd)
|
|
653
|
+
need_msa.append(protein)
|
|
654
|
+
int_score[protein] = dict() #remove int score
|
|
655
|
+
elif msa_seq != all_info["sequence_no_SP"][protein] and index == 1 : #if not match, remove pkl file and start at zero
|
|
656
|
+
cmd = f"rm -rf {Path_Pickle_Feature}/*{protein}*"
|
|
657
|
+
os.system(cmd)
|
|
658
|
+
need_msa.append(protein)
|
|
659
|
+
need_DeepLoc.append(protein)
|
|
660
|
+
int_score[protein] = dict() #remove int score
|
|
661
|
+
|
|
662
|
+
#Check is save score interaction are still valid or delete it
|
|
663
|
+
for protein in all_info["int_score"].keys() :
|
|
664
|
+
for key in all_info["int_score"][protein].keys() :
|
|
665
|
+
bait = key.split(f"iQ_score_vs_")[1]
|
|
666
|
+
if not glob.glob(f"./result_PPI_int/{bait}_and_{protein}/ranked_0*") and not glob.glob(f"./result_PPI_int/{protein}_and_{bait}/ranked_0*") : #if no model for this interaction, remove score
|
|
667
|
+
if f"iQ_score_vs_{bait}" in int_score[protein].keys() :
|
|
668
|
+
del int_score[protein][f"iQ_score_vs_{bait}"]
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
#Check is save homo score interaction are valid
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
else : #no save dict, so check if protein have MSA or pkl
|
|
675
|
+
for protein in proteins :
|
|
676
|
+
if protein not in sequences_SP.keys() : #if protein need sequence in Uniprot
|
|
677
|
+
print("Search sequence for " + protein)
|
|
678
|
+
urllib.request.urlretrieve("https://rest.uniprot.org/uniprotkb/"+protein+".txt","log_file/temp_file.txt")
|
|
679
|
+
if os.path.getsize("log_file/temp_file.txt") == 0 :
|
|
680
|
+
logger.error(f"{protein} is not a compliant UniprotID")
|
|
681
|
+
with open("log_file/temp_file.txt","r") as in_file :
|
|
682
|
+
for seq in re.finditer(pattern, in_file.read()):
|
|
683
|
+
sequences_SP[protein] = seq.group(1)
|
|
684
|
+
# with open("temp_file.txt","r") as in_file :
|
|
685
|
+
# for name in re.finditer(pattern2, in_file.read()) :
|
|
686
|
+
# names[protein] = name.group(1)
|
|
687
|
+
for car in del_car :
|
|
688
|
+
sequences_SP[protein] = sequences_SP[protein].replace(car,"")
|
|
689
|
+
|
|
690
|
+
os.remove("log_file/temp_file.txt")
|
|
691
|
+
if os.path.isfile(f"{Path_Pickle_Feature}/{protein}.a3m") == False : #proteins without msa
|
|
692
|
+
cmd = f"rm -rf {Path_Pickle_Feature}/*{protein}*" #remove residue files
|
|
693
|
+
os.system(cmd)
|
|
694
|
+
if os.path.isfile(f"{Path_Pickle_Feature}/{protein}.pkl") == False and os.path.isfile(f"{Path_Pickle_Feature}/{protein}.a3m") == True : #proteins with msa without pkl file
|
|
695
|
+
need_pkl.append(protein)
|
|
696
|
+
|
|
697
|
+
need_msa.append(protein) #make SignalP and DeepLoc for all proteins, too create the save dict
|
|
698
|
+
need_DeepLoc.append(protein)
|
|
699
|
+
|
|
700
|
+
self.set_prot_SP(prot_SP)
|
|
701
|
+
self.set_result_dict(result_dict)
|
|
702
|
+
self.set_deeploc(deeploc_prot)
|
|
703
|
+
self.set_proteins_sequence_no_SP(protein_sequence_no_SP)
|
|
704
|
+
self.set_proteins_sequence_SP(sequences_SP)
|
|
705
|
+
self.set_int_score(int_score)
|
|
706
|
+
self.set_homo_score(homo_score)
|
|
707
|
+
self.Make_save_dict() #Save modification of the save dict
|
|
708
|
+
return need_msa, need_pkl, need_DeepLoc
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
def Make_save_dict (self) :
|
|
712
|
+
"""
|
|
713
|
+
Save all relevant intermediate results into a pickle file in order to avoid recomputing completed steps in future runs.
|
|
714
|
+
"""
|
|
715
|
+
pkl_dict = dict()
|
|
716
|
+
pkl_dict["sequence_SP"] = self.get_proteins_sequence_SP()
|
|
717
|
+
pkl_dict["sequence_no_SP"] = self.get_proteins_sequence_no_SP()
|
|
718
|
+
pkl_dict["deeploc"] = self.get_deeploc()
|
|
719
|
+
pkl_dict["int_score"] = self.get_int_score()
|
|
720
|
+
pkl_dict["homo_score"] = self.get_homo_score()
|
|
721
|
+
pkl_dict["Signal_peptide"] = self.get_prot_SP()
|
|
722
|
+
with open('log_file/save_dict.pkl', 'wb') as out_file :
|
|
723
|
+
pickle.dump(pkl_dict, out_file)
|
|
724
|
+
|
|
725
|
+
def find_prot_lenght (self, prot_dict = None) :
|
|
726
|
+
"""
|
|
727
|
+
Compute and store the length (number of amino acids) of each protein based on sequences without signal peptides.
|
|
728
|
+
|
|
729
|
+
Parameters :
|
|
730
|
+
----------
|
|
731
|
+
prot_dict = dict or None
|
|
732
|
+
"""
|
|
733
|
+
if prot_dict == None :
|
|
734
|
+
proteins = self.get_proteins()
|
|
735
|
+
else :
|
|
736
|
+
proteins = prot_dict
|
|
737
|
+
sequences = self.get_proteins_sequence_no_SP()
|
|
738
|
+
lenght_prot = dict()
|
|
739
|
+
for protein in proteins :
|
|
740
|
+
lenght_prot[protein] = len(sequences[protein])
|
|
741
|
+
self.set_lenght_prot(lenght_prot)
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
def create_fasta_file (self, with_SP, need_msa=[], need_pkl=[]) :
|
|
745
|
+
"""
|
|
746
|
+
Generate FASTA files for proteins requiring MSA or pkl generation.
|
|
747
|
+
|
|
748
|
+
Parameters :
|
|
749
|
+
----------
|
|
750
|
+
with_SP : boolean
|
|
751
|
+
need_msa : list
|
|
752
|
+
need_pkl : list
|
|
753
|
+
"""
|
|
754
|
+
line_msa = str()
|
|
755
|
+
sequences_SP = self.get_proteins_sequence_SP()
|
|
756
|
+
sequences_no_SP = self.get_proteins_sequence_no_SP()
|
|
757
|
+
file_name = self.get_file_name().split("/")[-1]
|
|
758
|
+
ext_f = "." + file_name.split(".")[-1]
|
|
759
|
+
file_msa = file_name.replace(ext_f,"_msa.fasta")
|
|
760
|
+
file_pkl = file_name.replace(ext_f,"_pkl.fasta")
|
|
761
|
+
if os.path.isfile(f"log_file/{file_msa}") == True :
|
|
762
|
+
os.remove(f"log_file/{file_msa}")
|
|
763
|
+
if os.path.isfile(f"log_file/{file_pkl}") == True :
|
|
764
|
+
os.remove(f"log_file/{file_pkl}")
|
|
765
|
+
if len(need_msa) != 0 :
|
|
766
|
+
if with_SP == True :
|
|
767
|
+
sequences = sequences_SP
|
|
768
|
+
if with_SP == False :
|
|
769
|
+
sequences = sequences_no_SP
|
|
770
|
+
for protein in need_msa :
|
|
771
|
+
line_msa += ">" + protein + "\n" + sequences[protein] + "\n"
|
|
772
|
+
with open(f"log_file/{file_msa}","w") as f_msa :
|
|
773
|
+
f_msa.write(line_msa)
|
|
774
|
+
line_pkl = str()
|
|
775
|
+
if len(need_pkl) != 0 :
|
|
776
|
+
for protein in need_pkl :
|
|
777
|
+
line_pkl += ">" + protein + "\n" + sequences_no_SP[protein] + "\n"
|
|
778
|
+
with open(f"log_file/{file_pkl}","w") as f_pkl :
|
|
779
|
+
f_pkl.write(line_pkl)
|
|
780
|
+
|