FunVIP 0.3.20__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.
src/modeltest.py ADDED
@@ -0,0 +1,443 @@
1
+ from funvip.src import ext
2
+ import os, shutil, copy
3
+ import logging
4
+
5
+ cmd_translator_modeltestng_fasttree = {
6
+ "JC": "",
7
+ "GTR": "-gtr",
8
+ "JC+G4": "-gamma",
9
+ "GTR+G4": "-gtr -gamma",
10
+ }
11
+ cmd_translator_modelfinder_fasttree = {
12
+ "JC": "",
13
+ "GTR": "-gtr",
14
+ "JC+G4": "-gamma",
15
+ "GTR+G4": "-gtr -gamma",
16
+ }
17
+ cmd_translator_modelfinder_raxml = {
18
+ "JC": "-m JC",
19
+ "JC+G4": "-m JC",
20
+ "JC+I": "-m JC",
21
+ "JC+G4+I": "-m JC",
22
+ "HKY": "-m HKY85",
23
+ "HKY+G4": "-m HKY85",
24
+ "HKY+I": "-m HKY85",
25
+ "HKY+G4+I": "-m HKY85",
26
+ "K80": "-m K80",
27
+ "K80+G4": "-m K80",
28
+ "TrNef": "-m GTRCAT",
29
+ "TrNef+G4": "-m GTRGAMMA",
30
+ "TrNef+I": "-m GTRCATI",
31
+ "TrNef+G4+I": "-m GTRGAMMAI",
32
+ "TPM1": "-m GTRCAT",
33
+ "TPM1+G4": "-m GTRGAMMA",
34
+ "TPM1+I": "-m GTRCATI",
35
+ "TPM1+G4+I": "-m GTRGAMMAI",
36
+ "TPM2": "-m GTRCAT",
37
+ "TPM2+G4": "-m GTRGAMMA",
38
+ "TPM2+I": "-m GTRCATI",
39
+ "TPM2+G4+I": "-m GTRGAMMAI",
40
+ "TPM3": "-m GTRCAT",
41
+ "TPM3+G4": "-m GTRGAMMA",
42
+ "TPM3+I": "-m GTRCATI",
43
+ "TPM3+G4+I": "-m GTRGAMMAI",
44
+ "TIM1": "-m GTRCAT",
45
+ "TIM1+G4": "-m GTRGAMMA",
46
+ "TIM1+I": "-m GTRCATI",
47
+ "TIM1+G4+I": "-m GTRGAMMAI",
48
+ "TIM2": "-m GTRCAT",
49
+ "TIM2+G4": "-m GTRGAMMA",
50
+ "TIM2+I": "-m GTRCATI",
51
+ "TIM2+G4+I": "-m GTRGAMMAI",
52
+ "TIM3": "-m GTRCAT",
53
+ "TIM3+G4": "-m GTRGAMMA",
54
+ "TIM3+I": "-m GTRCATI",
55
+ "TIM3+G4+I": "-m GTRGAMMAI",
56
+ "TVMef": "-m GTRCAT",
57
+ "TVMef+G4": "-m GTRGAMMA",
58
+ "TVMef+I": "-m GTRCATI",
59
+ "TVMef+G4+I": "-m GTRGAMMAI",
60
+ "SYM": "-m GTRCAT",
61
+ "SYM+G4": "-m GTRGAMMA",
62
+ "SYM+I": "-m GTRCATI",
63
+ "SYM+G4+I": "-m GTRGAMMAI",
64
+ "F81+FO": "-m GTRCATX",
65
+ "F81+FO+G4": "-m GTRGAMMAX",
66
+ "F81+FO+I": "-m GTRCATIX",
67
+ "F81+FO+G4+I": "-m GTRGAMMAIX",
68
+ "TrN+FO": "-m GTRCATX",
69
+ "TrN+FO+G4": "-m GTRGAMMAX",
70
+ "TrN+FO+I": "-m GTRCATIX",
71
+ "TrN+FO+G4+I": "-m GTRGAMMAIX",
72
+ "TPM1uf+FO": "-m GTRCATX",
73
+ "TPM1uf+FO+G4": "-m GTRGAMMAX",
74
+ "TPM1uf+FO+I": "-m GTRCATIX",
75
+ "TPM1uf+FO+G4+I": "-m GTRGAMMAIX",
76
+ "TPM2uf+FO": "-m GTRCATX",
77
+ "TPM2uf+FO+G4": "-m GTRGAMMAX",
78
+ "TPM2uf+FO+I": "-m GTRCATIX",
79
+ "TPM2uf+FO+G4+I": "-m GTRGAMMAIX",
80
+ "TPM3uf+FO": "-m GTRCATX",
81
+ "TPM3uf+FO+G4": "-m GTRGAMMAX",
82
+ "TPM3uf+FO+I": "-m GTRCATIX",
83
+ "TPM3uf+FO+G4+I": "-m GTRGAMMAIX",
84
+ "TIM1uf+FO": "-m GTRCATX",
85
+ "TIM1uf+FO+G4": "-m GTRGAMMAX",
86
+ "TIM1uf+FO+I": "-m GTRCATIX",
87
+ "TIM1uf+FO+G4+I": "-m GTRGAMMAIX",
88
+ "TIM2uf+FO": "-m GTRCATX",
89
+ "TIM2uf+FO+G4": "-m GTRGAMMAX",
90
+ "TIM2uf+FO+I": "-m GTRCATIX",
91
+ "TIM2uf+FO+G4+I": "-m GTRGAMMAIX",
92
+ "TIM3uf+FO": "-m GTRCATX",
93
+ "TIM3uf+FO+G4": "-m GTRGAMMAX",
94
+ "TIM3uf+FO+I": "-m GTRCATIX",
95
+ "TIM3uf+FO+G4+I": "-m GTRGAMMAIX",
96
+ "TVM+FO": "-m GTRCATX",
97
+ "TVM+FO+G4": "-m GTRGAMMAX",
98
+ "TVM+FO+I": "-m GTRCATIX",
99
+ "TVM+FO+G4+I": "-m GTRGAMMAIX",
100
+ "GTR+FO": "-m GTRCATX",
101
+ "GTR+FO+G4": "-m GTRGAMMAX",
102
+ "GTR+FO+I": "-m GTRCATIX",
103
+ "GTR+FO+G4+I": "-m GTRGAMMAIX",
104
+ "F81": "-m GTRCATX",
105
+ "F81+G4": "-m GTRGAMMAX",
106
+ "F81+I": "-m GTRCATIX",
107
+ "F81+G4+I": "-m GTRGAMMAIX",
108
+ "TrN": "-m GTRCAT",
109
+ "TrN+G4": "-m GTRGAMMA",
110
+ "TrN+I": "-m GTRCATI",
111
+ "TrN+G4+I": "-m GTRGAMMAI",
112
+ "TPM1uf": "-m GTRCAT",
113
+ "TPM1uf+G4": "-m GTRGAMMA",
114
+ "TPM1uf+I": "-m GTRCATI",
115
+ "TPM1uf+G4+I": "-m GTRGAMMAI",
116
+ "TPM2uf": "-m GTRCAT",
117
+ "TPM2uf+G4": "-m GTRGAMMA",
118
+ "TPM2uf+I": "-m GTRCATI",
119
+ "TPM2uf+G4+I": "-m GTRGAMMAI",
120
+ "TPM3uf": "-m GTRCAT",
121
+ "TPM3uf+G4": "-m GTRGAMMA",
122
+ "TPM3uf+I": "-m GTRCATI",
123
+ "TPM3uf+G4+I": "-m GTRGAMMAI",
124
+ "TIM1uf": "-m GTRCAT",
125
+ "TIM1uf+G4": "-m GTRGAMMA",
126
+ "TIM1uf+I": "-m GTRCATI",
127
+ "TIM1uf+G4+I": "-m GTRGAMMAI",
128
+ "TIM2uf": "-m GTRCAT",
129
+ "TIM2uf+G4": "-m GTRGAMMA",
130
+ "TIM2uf+I": "-m GTRCATI",
131
+ "TIM2uf+G4+I": "-m GTRGAMMAI",
132
+ "TIM3uf": "-m GTRCAT",
133
+ "TIM3uf+G4": "-m GTRGAMMA",
134
+ "TIM3uf+I": "-m GTRCATI",
135
+ "TIM3uf+G4+I": "-m GTRGAMMAI",
136
+ "TVM": "-m GTRCAT",
137
+ "TVM+G4": "-m GTRGAMMA",
138
+ "TVM+I": "-m GTRCATI",
139
+ "TVM+G4+I": "-m GTRGAMMAI",
140
+ "GTR": "-m GTRCAT",
141
+ "GTR+G4": "-m GTRGAMMA",
142
+ "GTR+I": "-m GTRCATI",
143
+ "GTR+G4+I": "-m GTRGAMMAI",
144
+ "F81+F": "-m GTRCAT",
145
+ "F81+F+G4": "-m GTRGAMMA",
146
+ "F81+F+I": "-m GTRCATI",
147
+ "F81+F+G4+I": "-m GTRGAMMAI",
148
+ "TrN+F": "-m GTRCAT",
149
+ "TrN+F+G4": "-m GTRGAMMA",
150
+ "TrN+F+I": "-m GTRCATI",
151
+ "TrN+F+G4+I": "-m GTRGAMMAI",
152
+ "TPM1uf+F": "-m GTRCAT",
153
+ "TPM1uf+F+G4": "-m GTRGAMMA",
154
+ "TPM1uf+F+I": "-m GTRCATI",
155
+ "TPM1uf+F+G4+I": "-m GTRGAMMAI",
156
+ "TPM2uf+F": "-m GTRCAT",
157
+ "TPM2uf+F+G4": "-m GTRGAMMA",
158
+ "TPM2uf+F+I": "-m GTRCATI",
159
+ "TPM2uf+F+G4+I": "-m GTRGAMMAI",
160
+ "TPM3uf+F": "-m GTRCAT",
161
+ "TPM3uf+F+G4": "-m GTRGAMMA",
162
+ "TPM3uf+F+I": "-m GTRCATI",
163
+ "TPM3uf+F+G4+I": "-m GTRGAMMAI",
164
+ "TIM1uf+F": "-m GTRCAT",
165
+ "TIM1uf+F+G4": "-m GTRGAMMA",
166
+ "TIM1uf+F+I": "-m GTRCATI",
167
+ "TIM1uf+F+G4+I": "-m GTRGAMMAI",
168
+ "TIM2uf+F": "-m GTRCAT",
169
+ "TIM2uf+F+G4": "-m GTRGAMMA",
170
+ "TIM2uf+F+I": "-m GTRCATI",
171
+ "TIM2uf+F+G4+I": "-m GTRGAMMAI",
172
+ "TIM3uf+F": "-m GTRCAT",
173
+ "TIM3uf+F+G4": "-m GTRGAMMA",
174
+ "TIM3uf+F+I": "-m GTRCATI",
175
+ "TIM3uf+F+G4+I": "-m GTRGAMMAI",
176
+ "TVM+F": "-m GTRCAT",
177
+ "TVM+F+G4": "-m GTRGAMMA",
178
+ "TVM+F+I": "-m GTRCATI",
179
+ "TVM+F+G4+I": "-m GTRGAMMAI",
180
+ "GTR+F": "-m GTRCAT",
181
+ "GTR+F+G4": "-m GTRGAMMA",
182
+ "GTR+F+I": "-m GTRCATI",
183
+ "GTR+F+G4+I": "-m GTRGAMMAI",
184
+ }
185
+
186
+
187
+ def parse_model(modeltest_file, opt, path):
188
+ model_list = []
189
+ model_cmd = "no model found"
190
+
191
+ if opt.method.modeltest == "iqtree":
192
+ # Check iqtree - iqtree pair has misentered here
193
+ if opt.method.tree == "iqtree":
194
+ logging.error(
195
+ f"DEVELOPMENTAL ERROR. MODELTEST {opt.method.modeltest} entered while {opt.method.tree} selected"
196
+ )
197
+ raise Exception
198
+
199
+ # read modeltest result file
200
+ print(modeltest_file)
201
+ try:
202
+ with open(modeltest_file, "r", encoding="UTF-8") as f:
203
+ lines = f.readlines()
204
+ logging.info(f"Successfully parsed {modeltest_file}")
205
+ except:
206
+ logging.error(f"Cannot parse modeltest file for {modeltest_file}")
207
+ raise Exception
208
+
209
+ # Parse modeltest file
210
+ flag = 0
211
+ for line in lines:
212
+ # finish parsing from new line break
213
+ if line == "\n" and flag == 1:
214
+ break
215
+ # parse when modeltest result existing region
216
+ if flag == 1:
217
+ model_list.append(line.split(" ")[0])
218
+
219
+ # indicing modeltest result start
220
+ if (
221
+ "Model LogL AIC w-AIC AICc w-AICc BIC w-BIC"
222
+ in line
223
+ ):
224
+ # parsing flag
225
+ flag = 1
226
+
227
+ # Designate modeltest method by tree method
228
+ if opt.method.tree == "fasttree":
229
+ for model in model_list:
230
+ # if model is available model for tree method take it
231
+ if model in cmd_translator_modelfinder_fasttree:
232
+ # convert to commands
233
+ model_cmd = cmd_translator_modelfinder_fasttree[model]
234
+ break
235
+
236
+ if model_cmd == "no model found":
237
+ logging.error(f"DEVELOPMENTAL ERROR. FAILED PARSING APPROPRIATE MODEL")
238
+ logging.error(f"{model_list}")
239
+ raise Exception
240
+
241
+ elif opt.method.tree == "raxml":
242
+ for model in model_list:
243
+ # if model is available model for tree method take it
244
+ if model in cmd_translator_modelfinder_raxml:
245
+ # convert to commands
246
+ model_cmd = cmd_translator_modelfinder_raxml[model]
247
+ break
248
+
249
+ if model_cmd == "no model found":
250
+ logging.error(f"DEVELOPMENTAL ERROR. FAILED PARSING APPROPRIATE MODEL")
251
+ logging.error(f"{model_list}")
252
+ raise Exception
253
+
254
+ else:
255
+ logging.error(
256
+ f"DEVELOPMENTAL ERROR. INAPPROPRIATE TREE METHOD {opt.method.tree} selected"
257
+ )
258
+ raise Exception
259
+
260
+ elif opt.method.modeltest == "modeltest-ng":
261
+ ### Testing block ###
262
+ # Parse files
263
+
264
+ try:
265
+ with open(modeltest_file, "r", encoding="UTF-8") as f:
266
+ lines = f.readlines()
267
+ status = None
268
+
269
+ # Fasttree needs converter
270
+ if opt.method.tree == "fasttree":
271
+ flag = 0 # 1 : Criterion found, 2: --- line found 1st time(while parsing), 0 : parsing ended
272
+ cnt = 1 # line count
273
+ for line in lines:
274
+ print(f"flag {flag} / [line]: {line}")
275
+
276
+ if (
277
+ "model K lnL score delta weight"
278
+ in line
279
+ ):
280
+ # Check if the right chunk selected
281
+ if "AICc" in line and opt.criterion == "AICc":
282
+ flag = 1
283
+ elif "AIC" in line and opt.criterion == "AIC":
284
+ flag = 1
285
+ elif "BIC" in line and opt.criterion == "BIC":
286
+ flag = 1
287
+
288
+ elif flag == 1 and "--------" in line:
289
+ # Skipping one line
290
+ flag = 2
291
+ elif flag == 2 and not ("------" in line):
292
+ logging.info(f"[line]")
293
+ logging.info(line)
294
+ # Parsing objects
295
+ model_list.append(line.split(f"{cnt} ")[1].split(" ")[0])
296
+ if cnt < 10:
297
+ cnt += 1
298
+ else:
299
+ cnt = 1
300
+ # Finish all 10 parsed
301
+ break
302
+ elif flag == 2 and "------" in line:
303
+ # reset block
304
+ flag = 0
305
+
306
+ # get commands with available model
307
+ for model in model_list:
308
+ if model in cmd_translator_modeltestng_fasttree:
309
+ model_cmd = cmd_translator_modeltestng_fasttree[model]
310
+ break
311
+
312
+ # For IQTREE and RAxML, just easily parse commands
313
+ else:
314
+ for line in lines:
315
+ # Check current criterion
316
+ if "AICc" in line:
317
+ status = "AICc"
318
+ elif "AIC" in line and not "AICc" in line:
319
+ status = "AIC"
320
+ elif "BIC" in line:
321
+ status = "BIC"
322
+
323
+ if status == opt.criterion:
324
+ if line.strip().startswith(">"):
325
+ if opt.method.tree == "fasttree":
326
+ logging.error(
327
+ f"DEVELOPMENTAL ERROR. MODELTEST-NG COMMAND PARSING STEP entered while {opt.method.tree} selected"
328
+ )
329
+ elif opt.method.tree == "iqtree":
330
+ if "iqtree" in line:
331
+ model_cmd = f'-m {line.split("-m ")[1]}'
332
+ break
333
+ elif opt.method.tree == "raxml":
334
+ if "raxmlHPC-SSE3" in line:
335
+ model_cmd = (
336
+ f'-m {line.split("-m ")[1].split(" -n ")[0]}'
337
+ )
338
+ break
339
+
340
+ # Currently using BIC model
341
+ model_cmd = model_dict["BIC"]
342
+
343
+ except:
344
+ logging.warning(f"Cannot parse modeltest file for {modeltest_file}")
345
+
346
+ else:
347
+ logging.error(
348
+ f"DEVELOPMENTAL ERROR. INAPPROPRIATE MODELTEST METHOD {opt.method.modeltest} selected"
349
+ )
350
+ raise Exception
351
+
352
+ return model_cmd
353
+
354
+
355
+ def cleanup(modeltest_file):
356
+ pass
357
+
358
+
359
+ # main function
360
+ def modeltest(V, path, opt) -> dict:
361
+ group_dict = V.dict_dataset
362
+ model_dict = copy.deepcopy(group_dict)
363
+
364
+ # By group and by gene
365
+ for group in group_dict:
366
+ for gene in group_dict[group]:
367
+ if opt.method.modeltest.lower() == "modeltest-ng":
368
+ # As modeltest-ng shows only top 10 results,
369
+ # we should reduce number of models to prevent none of the model fits
370
+ if opt.method.tree == "fasttree":
371
+ models = "-m JC,GTR -h ug"
372
+ else:
373
+ models = ""
374
+
375
+ # run modeltest-ng
376
+ ext.Modeltest_ng(
377
+ fasta=f"{path.out_alignment}/{opt.runname}_trimmed_{group}_{gene}.fasta",
378
+ models=models,
379
+ out=f"{path.out_modeltest}/{opt.runname}_{group}_{gene}",
380
+ thread=opt.thread,
381
+ )
382
+
383
+ # Change result name
384
+ try:
385
+ shutil.move(
386
+ f"{path.out_modeltest}/{opt.runname}_{group}_{gene}.out",
387
+ f"{path.out_modeltest}/{opt.runname}_{group}_{gene}.modeltest",
388
+ )
389
+ except:
390
+ logging.warning(
391
+ f"Cannot parse modeltest file for {path.out_modeltest}/{opt.runname}_{group}_{gene}.out. Running with default option"
392
+ )
393
+
394
+ # parse model from modeltest-ng result
395
+ model_dict[group][gene] = parse_model(
396
+ modeltest_file=f"{path.out_modeltest}/{opt.runname}_{group}_{gene}.modeltest",
397
+ path=path,
398
+ opt=opt,
399
+ )
400
+ elif opt.method.modeltest.lower() == "iqtree":
401
+ if not (opt.method.tree == "iqtree"):
402
+ # Run IQTREE ModelFinder
403
+ ext.ModelFinder(
404
+ fasta=f"{path.out_alignment}/{opt.runname}_trimmed_{group}_{gene}.fasta",
405
+ opt=opt,
406
+ path=path,
407
+ thread=opt.thread,
408
+ )
409
+
410
+ # Move modeltest result to appropriate location
411
+ try:
412
+ shutil.move(
413
+ f"{path.out_alignment}/{opt.runname}_trimmed_{group}_{gene}.fasta.iqtree",
414
+ f"{path.out_modeltest}/{opt.runname}_{group}_{gene}.modeltest",
415
+ )
416
+ except:
417
+ logging.warning(
418
+ f"Cannot parse modeltest file for {path.out_alignment}/{opt.runname}_trimmed_{group}_{gene}.fasta.iqtree. Running with default option"
419
+ )
420
+
421
+ # parse model from IQTREE ModelFinder result
422
+ model_dict[group][gene] = parse_model(
423
+ modeltest_file=f"{path.out_modeltest}/{opt.runname}_{group}_{gene}.modeltest",
424
+ path=path,
425
+ opt=opt,
426
+ )
427
+ else:
428
+ logging.info(
429
+ "IQTREE will perform ModelFinder internally in tree construction step, skipping in modeltest step"
430
+ )
431
+ model_dict[group][gene] = "skip"
432
+
433
+ else: # including opt.model_method.lower() == "none":
434
+ if opt.method.tree == "raxml":
435
+ logging.info("Skipping modeltest. Using GTRGAMMA as default")
436
+ model_dict[group][gene] = "-m GTRGAMMA"
437
+ else:
438
+ logging.info("Skipping modeltest.")
439
+ model_dict[group][gene] = "skip"
440
+
441
+ logging.info(model_dict)
442
+
443
+ return model_dict
src/ncbi.py ADDED
@@ -0,0 +1,160 @@
1
+ from Bio import Entrez
2
+ from Bio import SeqIO
3
+ from Bio.Blast.Applications import NcbiblastnCommandline
4
+ from Bio.Blast import NCBIXML
5
+ from Bio.Seq import Seq
6
+ import time
7
+ from time import sleep
8
+ import pickle
9
+ import json
10
+ import re
11
+ import logging
12
+ from datetime import datetime
13
+ from itertools import repeat
14
+ import xmltodict
15
+ import os, sys, subprocess
16
+ import random
17
+ import pickle
18
+ import pandas as pd
19
+ import shutil
20
+
21
+ # from .logger import Mes
22
+
23
+
24
+ def Downloadbyacclist(Email, list_ID, out):
25
+ if len(list_ID) == 0:
26
+ return []
27
+
28
+ path_tmp = "tmp_download"
29
+
30
+ # print(list_ID)
31
+
32
+ def xml2dict(record):
33
+ dict_type = xmltodict.parse(record)
34
+ json_type = json.dumps(dict_type, indent=4)
35
+ dict2_type = json.loads(json_type)
36
+ return dict2_type
37
+
38
+ Entrez.email = Email
39
+
40
+ logging.info(f"Number of IDs: {len(list_ID)}")
41
+
42
+ # Parse
43
+ cnt = 0
44
+ cut = 50 # parse by 50 sequences
45
+ cnt_all = len(list_ID)
46
+
47
+ start_time = time.time()
48
+
49
+ record_list = []
50
+
51
+ for i in range(int((len(list_ID) - 1) / cut) + 1):
52
+ # last chunk
53
+ if i * cut + cut > len(list_ID):
54
+ # Mes(i)
55
+ ID_string = ",".join(list_ID[i * cut :])
56
+ sleep(0.3)
57
+ cnt += len(list_ID[i * cut :])
58
+ logging.info(
59
+ f"{cnt}/{cnt_all} {100*cnt/cnt_all}% {time.time()-start_time}s"
60
+ )
61
+
62
+ try:
63
+ print(ID_string)
64
+ handle = Entrez.efetch(
65
+ db="nucleotide", id=ID_string, rettype="gb", retmode="xml"
66
+ )
67
+ except: # Retry
68
+ logging.info("Requesting again...")
69
+ try:
70
+ sleep(10)
71
+ handle = Entrez.efetch(
72
+ db="nucleotide", id=ID_string, rettype="gb", retmode="xml"
73
+ )
74
+ except:
75
+ sleep(100)
76
+ handle = Entrez.efetch(
77
+ db="nucleotide", id=ID_string, rettype="gb", retmode="xml"
78
+ )
79
+
80
+ pre_record = handle.read()
81
+ json_record = xml2dict(pre_record)
82
+ tmp_record_list = []
83
+
84
+ # If only one result available
85
+ if type(json_record["GBSet"]["GBSeq"]) is dict:
86
+ json_record["GBSet"]["GBSeq"] = [json_record["GBSet"]["GBSeq"]]
87
+
88
+ if len(list_ID[i * cut :]) != 1:
89
+ for record in json_record["GBSet"]["GBSeq"]:
90
+ print(record)
91
+ record_list.append(record)
92
+ tmp_record_list.append(record)
93
+ else:
94
+ record = json_record["GBSet"]["GBSeq"]
95
+ record_list.append(record)
96
+ tmp_record_list.append(record)
97
+
98
+ try:
99
+ with open(f"./{path_tmp}/{i}", "wb") as f:
100
+ pickle.dump(tmp_record_list, f)
101
+ except:
102
+ logging.error("Saving Error")
103
+ raise Exception
104
+
105
+ # non last chunk
106
+ else:
107
+ # Mes(i)
108
+ ID_string = ",".join(list_ID[i * cut : i * cut + cut])
109
+ sleep(0.3)
110
+ cnt += cut
111
+ logging.info(
112
+ f"{cnt}/{cnt_all} {100*cnt/cnt_all}% {time.time()-start_time}s"
113
+ )
114
+
115
+ try:
116
+ handle = Entrez.efetch(
117
+ db="nucleotide", id=ID_string, rettype="gb", retmode="xml"
118
+ )
119
+ except: # Retry
120
+ logging.info("Requesting again...")
121
+ try:
122
+ sleep(10)
123
+ handle = Entrez.efetch(
124
+ db="nucleotide", id=ID_string, rettype="gb", retmode="xml"
125
+ )
126
+ except:
127
+ sleep(100)
128
+ handle = Entrez.efetch(
129
+ db="nucleotide", id=ID_string, rettype="gb", retmode="xml"
130
+ )
131
+
132
+ pre_record = handle.read()
133
+ json_record = xml2dict(pre_record)
134
+ tmp_record_list = []
135
+
136
+ if len(list_ID[i * cut :]) != 1:
137
+ for record in json_record["GBSet"]["GBSeq"]:
138
+ record_list.append(record)
139
+ tmp_record_list.append(record)
140
+ else:
141
+ record = json_record["GBSet"]["GBSeq"]
142
+ record_list.append(record)
143
+ tmp_record_list.append(record)
144
+
145
+ try:
146
+ with open(f"./{path_tmp}/{i}", "wb") as f:
147
+ pickle.dump(tmp_record_list, f)
148
+ except:
149
+ logging.error("Saving Error")
150
+ raise Exception
151
+
152
+ with open(out, "w") as fp:
153
+ json_term = json.dump(record_list, fp, indent=4)
154
+
155
+ # If success, remove tmp files
156
+ tmp_file_list = [file for file in os.listdir(f"./{path_tmp}/")]
157
+ for file in tmp_file_list:
158
+ os.remove(f"./{path_tmp}/{file}")
159
+
160
+ return record_list
src/opt_generator.py ADDED
@@ -0,0 +1,72 @@
1
+ # Option generator for multiprocessing starmap
2
+ import logging
3
+ import os
4
+
5
+
6
+ def opt_generator(V, opt, path, step, thread=None):
7
+ list_opt = []
8
+
9
+ if thread is None:
10
+ thread = opt.thread
11
+
12
+ ## alignment options generator
13
+ if step == "alignment":
14
+ for group in V.dict_dataset:
15
+ for gene in V.dict_dataset[group]:
16
+ # For concatenated gene matrix, alignment should be done by each gene matrix and then concatenated
17
+ if gene != "concatenated":
18
+ # double checking path
19
+ if os.path.isfile(
20
+ f"{path.out_adjusted}/{opt.runname}_Adjusted_{group}_{gene}.fasta"
21
+ ):
22
+ list_opt.append(
23
+ (
24
+ f"{path.out_adjusted}/{opt.runname}_Adjusted_{group}_{gene}.fasta",
25
+ f"{path.out_alignment}/{opt.runname}_MAFFT_{group}_{gene}.fasta",
26
+ path,
27
+ thread,
28
+ opt.mafft.algorithm,
29
+ "adjustdirection",
30
+ opt.mafft.op,
31
+ opt.mafft.ep,
32
+ )
33
+ )
34
+
35
+ elif step == "trimming":
36
+ # Generate trimming opts for multiprocessing
37
+ for group in V.dict_dataset:
38
+ for gene in V.dict_dataset[group]:
39
+ if not (gene == "concatenated"):
40
+ if opt.method.trim.lower() == "gblocks":
41
+ list_opt.append(
42
+ (
43
+ f"{path.out_alignment}/{opt.runname}_MAFFT_{group}_{gene}.fasta",
44
+ f"{path.out_alignment}/{opt.runname}_trimmed_{group}_{gene}.fasta",
45
+ path,
46
+ opt,
47
+ )
48
+ )
49
+ elif opt.method.trim.lower() == "trimal":
50
+ list_opt.append(
51
+ (
52
+ f"{path.out_alignment}/{opt.runname}_MAFFT_{group}_{gene}.fasta",
53
+ f"{path.out_alignment}/{opt.runname}_trimmed_{group}_{gene}.fasta",
54
+ path,
55
+ opt,
56
+ )
57
+ )
58
+ else: # for just copy
59
+ list_opt.append(
60
+ (
61
+ f"{path.out_alignment}/{opt.runname}_MAFFT_{group}_{gene}.fasta",
62
+ f"{path.out_alignment}/{opt.runname}_trimmed_{group}_{gene}.fasta",
63
+ path,
64
+ opt,
65
+ )
66
+ )
67
+
68
+ else:
69
+ logging.error(f"[Error] Unexpected step {step} given for opt_generator")
70
+ raise Exception
71
+
72
+ return list_opt