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/HInt.py ADDED
@@ -0,0 +1,244 @@
1
+ """
2
+ Main entry point of HInt
3
+
4
+ Author: Quentin Rouger
5
+
6
+ This script orchestrates the full HInt pipeline, from input parsing to final results generation.
7
+ """
8
+
9
+ import sys
10
+ import logging
11
+ import argparse
12
+ import os
13
+ import threading
14
+
15
+ # ------------------------------------------------------------------
16
+ # Logging configuration
17
+ # ------------------------------------------------------------------
18
+
19
+ log_filename = "./log_file/HInt.log"
20
+
21
+ # Create log directory if it does not exist
22
+ if not os.path.exists("log_file") :
23
+ os.system("mkdir log_file")
24
+
25
+ from .Utils_HInt import *
26
+ from .File_proteins import *
27
+ from .Scoring_HInt import Score_interaction, Resume_file, Create_figures
28
+
29
+ # Reset existing handlers to avoid duplicated logs
30
+ logging.getLogger().handlers.clear()
31
+ logger = logging.getLogger()
32
+ logger.setLevel(logging.INFO)
33
+ formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
34
+ file_handler = logging.FileHandler(log_filename, mode='w')
35
+ file_handler.setFormatter(formatter)
36
+ stream_handler = logging.StreamHandler(sys.stdout)
37
+ stream_handler.setFormatter(formatter)
38
+ logger.addHandler(file_handler)
39
+ logger.addHandler(stream_handler)
40
+
41
+
42
+ # ------------------------------------------------------------------
43
+ # Argument parsing
44
+ # ------------------------------------------------------------------
45
+
46
+ def add_arguments(parser) :
47
+ """
48
+ Define command-line arguments.
49
+
50
+ Parameters
51
+ ----------
52
+ parser : argparse.ArgumentParser
53
+ """
54
+ parser.add_argument("--gpu", help="Comma-separated list of GPUs available for computation (default: 0)", required=False, default="0")
55
+
56
+ N_CPU = multiprocessing.cpu_count()
57
+ default_cpu = N_CPU // 2 # by default, use half of the available CPUs
58
+ parser.add_argument("--cpu", help="Number of CPUs available for computation (default: half of the CPUs)", required=False, default=default_cpu, type=int)
59
+ parser.add_argument("--multi_job_per_gpu", help="Allow multiple jobs to run on the same GPU if VRAM allows it (default: True)", required=False, default="True")
60
+ parser.add_argument("--multi_scoring", help="Score all models of each interactions (default: False)", required=False, default="False")
61
+
62
+ # ------------------------------------------------------------------
63
+ # Main execution
64
+ # ------------------------------------------------------------------
65
+
66
+ def main() :
67
+
68
+ parser = argparse.ArgumentParser()
69
+ add_arguments(parser)
70
+ args = parser.parse_args()
71
+
72
+ GPU = [gpu for gpu in args.gpu.split(",")]
73
+ CPU = args.cpu
74
+ if CPU > multiprocessing.cpu_count() :
75
+ raise ValueError(f"Number of CPUs specified ({CPU}) exceeds the number of available CPUs ({multiprocessing.cpu_count()}).")
76
+ multi_job_per_gpu = args.multi_job_per_gpu
77
+ if multi_job_per_gpu not in ["True", "False"] :
78
+ raise ValueError("Invalid value for --multi_job_per_gpu. Need True or False.")
79
+ multi_scoring = args.multi_scoring
80
+ if multi_scoring not in ["True", "False"] :
81
+ raise ValueError("Invalid value for --multi_scoring. Need True or False.")
82
+ Informations_dict = Define_informations()
83
+
84
+ # --------------------------------------------------------------
85
+ # Initialize protein container
86
+ # --------------------------------------------------------------
87
+
88
+ HInt_object = File_proteins(Informations_dict["Path_Uniprot_ID"], Informations_dict["Interact_with"], Informations_dict["AlphaFold"])
89
+
90
+ logger.info("GPUs set to: %s", GPU)
91
+ logger.info("Number of CPUs set to: %s", CPU)
92
+
93
+
94
+
95
+ for bait in Informations_dict["Interact_with"] : # Check that all bait proteins exist in the protein list
96
+ if bait not in HInt_object.get_proteins() and bait != "" :
97
+ raise Exception(f"Bait {bait} not found in the protein list {Informations_dict['Path_Uniprot_ID']}")
98
+
99
+ # --------------------------------------------------------------
100
+ # Checkpointing: determine which features need to be computed
101
+ # --------------------------------------------------------------
102
+
103
+ # need_msa also includes proteins that only require signal peptide information
104
+ need_msa, need_pkl, need_DeepLoc = HInt_object.check_save_dict(Informations_dict["Path_Pickle_Feature"])
105
+
106
+ # Remove bait proteins from the prey list
107
+ HInt_object.set_possible_prey([protein for protein in HInt_object.get_possible_prey() if protein not in Informations_dict["Interact_with"]])
108
+
109
+ # --------------------------------------------------------------
110
+ # Length-based filtering
111
+ # --------------------------------------------------------------
112
+
113
+ # Filter proteins based on sequence length
114
+ # (default: remove proteins shorter than 20 AA)
115
+ need_msa, need_pkl, need_DeepLoc = filter_lenght(HInt_object, Informations_dict, need_msa, need_pkl, need_DeepLoc)
116
+
117
+ # --------------------------------------------------------------
118
+ # DeepLoc filtering
119
+ # --------------------------------------------------------------
120
+
121
+
122
+ if Informations_dict["Organism"] == "None" :
123
+ HInt_object.set_proteins_sequence_no_SP(HInt_object.get_proteins_sequence_SP()) #don't remove signal peptide
124
+ need_DeepLoc = []
125
+
126
+ if len(need_DeepLoc) > 0 : # Run DeepLoc only for proteins without localization information
127
+ run_deeploc(HInt_object, Informations_dict["Organism"], need_DeepLoc, GPU)
128
+
129
+
130
+ if Informations_dict["DeepLoc"].split(",") != ["None"] : # Apply DeepLoc-based filtering if enabled
131
+ need_msa, need_pkl = filter_deeploc(HInt_object, Informations_dict, need_msa, need_pkl)
132
+
133
+ HInt_object.Make_save_dict() # Save DeepLoc results
134
+
135
+ # --------------------------------------------------------------
136
+ # Signal peptide processing
137
+ # --------------------------------------------------------------
138
+
139
+ need_SP = list()
140
+ for protein in need_msa :
141
+ if protein not in HInt_object.get_proteins_sequence_no_SP().keys() or protein not in HInt_object.get_prot_SP().keys() : #protein need MSA but can already have sequence without SP
142
+ need_SP.append(protein)
143
+
144
+
145
+ if Informations_dict["Organism"] == "None" : # Run SignalP only if the organism is specified
146
+ need_SP = []
147
+ if len(need_SP) > 0 : # Run SignalP for proteins without signal peptide annotation
148
+ need_msa = run_SP(HInt_object, Informations_dict, need_SP, need_msa)
149
+
150
+ need_msa = check_exist_MSA(HInt_object, Informations_dict, need_msa) # Check for existing MSA files after SignalP processing
151
+ HInt_object.Make_save_dict() # Save sequences without signal peptides
152
+
153
+ for bait in Informations_dict["Interact_with"] : # Adjust bait protein lengths if specific regions are defined
154
+ if Informations_dict["Regions"][bait] != "0-0" :
155
+ dict_lenght = HInt_object.get_lenght_prot()
156
+ start = int(Informations_dict["Regions"][bait].split("-")[0])
157
+ end = int(Informations_dict["Regions"][bait].split("-")[1])
158
+ dict_lenght[bait] = end - start + 1
159
+ HInt_object.set_lenght_prot(dict_lenght)
160
+
161
+
162
+ # Filter proteins based on signal peptide criteria
163
+ need_msa, need_pkl = filter_signalP(HInt_object, Informations_dict, need_msa, need_pkl)
164
+
165
+ HInt_object.Make_save_dict()
166
+
167
+ # --------------------------------------------------------------
168
+ # Feature generation (MSA + pickle files)
169
+ # --------------------------------------------------------------
170
+
171
+
172
+ #Create batch just for loop on
173
+ job_with_vram_length = Generate_scripts(HInt_object, Informations_dict, "PPI_int", bait)
174
+ first_need_msa = []
175
+ first_need_pkl = []
176
+ First_batch = Generate_first_batch(job_with_vram_length, GPU, multi_job_per_gpu) #correspond to the first batch of proteins to process, based on the number of available GPUs and CPUs
177
+ if First_batch != None :
178
+ First_batch[0].append(bait) #add bait to the first batch, to make sure it is processed first
179
+ for prot in First_batch[0] :
180
+ if prot in need_msa :
181
+ first_need_msa.append(prot)
182
+ need_msa.remove(prot)
183
+ if prot in need_pkl :
184
+ first_need_pkl.append(prot)
185
+ need_pkl.remove(prot)
186
+
187
+ create_feature(HInt_object, Informations_dict, GPU, CPU, first_need_msa, first_need_pkl)
188
+
189
+ HInt_object.Make_save_dict()
190
+ prio_list_MSA = prioritize_by_vram_fit(job_with_vram_length, GPU)
191
+ batch_MSA = []
192
+ if prio_list_MSA != [] :
193
+ prio_list_MSA.pop(0) #remove first batch
194
+ for batch in prio_list_MSA :
195
+ new_prio_list = []
196
+ for prot in batch :
197
+ if prot in need_msa :
198
+ new_prio_list.append(prot)
199
+ if prot in need_pkl :
200
+ new_prio_list.append(prot)
201
+ batch_MSA.append(new_prio_list)
202
+
203
+ if len(first_need_msa) > 0 :
204
+ logger.info("Generating MSA depth figures")
205
+ Make_all_MSA_coverage(HInt_object, Informations_dict["Path_Pickle_Feature"], Informations_dict["Interact_with"], first_need_msa)
206
+ if Informations_dict["Interact_with"] != [''] :
207
+ for bait in Informations_dict["Multimer_bait"] :
208
+ if HInt_object.get_compounds() != {} :
209
+ gpu_thread = threading.Thread(
210
+ target=Generate_3D_model, args=(HInt_object, CPU, multi_scoring, Informations_dict, "PPI_int", job_with_vram_length, GPU, multi_job_per_gpu))
211
+ gpu_thread.start()
212
+ for batch in batch_MSA :
213
+ create_feature(HInt_object, Informations_dict, GPU, CPU, batch, [])
214
+ gpu_thread.join()
215
+ else :
216
+ gpu_thread = threading.Thread(target=Generate_3D_model, args=(HInt_object, CPU, multi_scoring, Informations_dict, "PPI_int", job_with_vram_length, GPU, multi_job_per_gpu))
217
+ gpu_thread.start()
218
+ for batch in batch_MSA :
219
+ create_feature(HInt_object, Informations_dict, GPU, CPU, batch, [])
220
+ gpu_thread.join()
221
+ Score_interaction(HInt_object, Informations_dict, CPU, "PPI_int", "", multi_scoring, bait) #if score is not done in Generate_3D_model, do it here
222
+ HInt_object.Make_save_dict()
223
+ # --------------------------------------------------------------
224
+ # Homo-oligomer modeling
225
+ # --------------------------------------------------------------
226
+
227
+ if int(Informations_dict["Homo-oligomer"]) > 1 :
228
+ #job_with_vram_length = Generate_scripts(HInt_object, Informations_dict, "homo_int", "")
229
+ Generate_3D_model(Informations_dict, "homo_int", job_with_vram_length, GPU, multi_job_per_gpu)
230
+
231
+
232
+
233
+ # --------------------------------------------------------------
234
+ # Final summary and figures
235
+ # --------------------------------------------------------------
236
+
237
+
238
+ sorted_protein = Resume_file(HInt_object, Informations_dict)
239
+
240
+ if Informations_dict["Interact_with"] != [''] :
241
+
242
+ Create_figures(HInt_object, Informations_dict, Informations_dict["AlphaFold"], sorted_protein, CPU)
243
+
244
+