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/trim.py ADDED
@@ -0,0 +1,118 @@
1
+ from funvip.src import ext
2
+ from funvip.src.opt_generator import opt_generator
3
+ from Bio import AlignIO
4
+ from Bio import SeqIO
5
+ from time import sleep
6
+ import multiprocessing as mp
7
+ import os
8
+ import logging
9
+ import shutil
10
+
11
+
12
+ ## Trimming function of FunVIP
13
+ # As most of the trimming functions affects inside of alignment
14
+ def trimming(alignment, out, path, opt):
15
+ logging.debug("Entered trimming module")
16
+ # Save alignment before running trimming
17
+ original_msa = AlignIO.read(alignment, "fasta")
18
+
19
+ # Running trimming
20
+ if opt.method.trim.lower() == "gblocks":
21
+ trimming_result = ext.Gblocks(fasta=alignment, out=out, path=path)
22
+ elif opt.method.trim.lower() == "trimal":
23
+ trimming_result = ext.Trimal(
24
+ fasta=alignment,
25
+ out=out,
26
+ path=path,
27
+ algorithm=opt.trimal.algorithm,
28
+ threshold=opt.trimal.gt,
29
+ )
30
+ else:
31
+ trimming_result = shutil.copy(alignment, out)
32
+
33
+ logging.debug(f"opt.allow_innertrimming: {opt.allow_innertrimming}")
34
+ logging.debug(f"opt.method.trim: {opt.method.trim}")
35
+ # Repair mid alignment
36
+ if not (opt.allow_innertrimming) and (
37
+ opt.method.trim.lower()
38
+ in (
39
+ "gblocks",
40
+ "trimal",
41
+ )
42
+ ):
43
+ # Check if trimming successed
44
+ if trimming_result is not ((-1, -1)):
45
+ # Repair trimmend alignment by analysis flanking region
46
+ trimmed_msa = AlignIO.read(out, "fasta")
47
+ logging.debug(f"Trimming region for {alignment} : {trimming_result}")
48
+
49
+ # trimming results are in 1 based positions, and start, end included
50
+ revived_msa = original_msa[:, trimming_result[0] - 1 : trimming_result[1]]
51
+ AlignIO.write(revived_msa, out, "fasta")
52
+ else:
53
+ logging.warning(
54
+ f"Trimming {alignment} failed. Check if the alignment includes invalid sequneces"
55
+ )
56
+
57
+ return trimming_result
58
+
59
+
60
+ # Trimming pipeline of FunVIP
61
+ def pipe_trimming(V, path, opt):
62
+ trimming_opt = opt_generator(V, opt, path, step="trimming")
63
+ # run multiprocessing start
64
+ if opt.verbose < 3:
65
+ p = mp.Pool(opt.thread)
66
+ trimming_result = p.starmap(trimming, trimming_opt)
67
+ p.close()
68
+ p.join()
69
+
70
+ else:
71
+ # non-multithreading mode for debugging
72
+ trimming_result = []
73
+ for option in trimming_opt:
74
+ trimming_result.append(trimming(*option))
75
+
76
+ # sleep(10)
77
+ # raise Exception
78
+
79
+ # Remove datasets if trimming results nothing
80
+ trim_fail = []
81
+ for group in V.dict_dataset:
82
+ for gene in V.dict_dataset[group]:
83
+ if not gene == "concatenated":
84
+ if os.path.isfile(
85
+ f"{path.out_alignment}/{opt.runname}_MAFFT_{group}_{gene}.fasta"
86
+ ):
87
+ if os.path.isfile(
88
+ f"{path.out_alignment}/{opt.runname}_trimmed_{group}_{gene}.fasta"
89
+ ):
90
+ seq_list = list(
91
+ SeqIO.parse(
92
+ f"{path.out_alignment}/{opt.runname}_trimmed_{group}_{gene}.fasta",
93
+ "fasta",
94
+ )
95
+ )
96
+ if len(seq_list[0].seq) == 0:
97
+ trim_fail.append((group, gene))
98
+ else:
99
+ pass
100
+ else:
101
+ pass
102
+
103
+ for fail in trim_fail:
104
+ group = fail[0]
105
+ gene = fail[1]
106
+ V.dict_dataset[group].pop(gene)
107
+ logging.warning(
108
+ f"Dataset {group} {gene} has removed during trimming because no sequence left. Please check alignment if database contains bad sequences."
109
+ )
110
+
111
+ # If non of the genes left for group except for concatenate, remove group
112
+ if len(V.dict_dataset[group]) == 1 and "concatenated" in V.dict_dataset[group]:
113
+ logging.warning(
114
+ f"Dataset {group} has removed because non of the genes are available"
115
+ )
116
+ V.dict_dataset.pop(group)
117
+
118
+ return V, path, opt