PyamilySeq 0.3.0__py3-none-any.whl → 0.5.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.
- PyamilySeq/Constants.py +1 -14
- PyamilySeq/PyamilySeq.py +237 -0
- PyamilySeq/PyamilySeq_Genus.py +659 -0
- PyamilySeq/PyamilySeq_Species.py +33 -110
- PyamilySeq/Seq_Combiner.py +44 -0
- PyamilySeq/utils.py +136 -0
- PyamilySeq-0.5.0.dist-info/METADATA +163 -0
- PyamilySeq-0.5.0.dist-info/RECORD +14 -0
- {PyamilySeq-0.3.0.dist-info → PyamilySeq-0.5.0.dist-info}/WHEEL +1 -1
- PyamilySeq-0.5.0.dist-info/entry_points.txt +3 -0
- PyamilySeq/combine_FASTA_with_genome_IDs.py +0 -49
- PyamilySeq-0.3.0.dist-info/METADATA +0 -103
- PyamilySeq-0.3.0.dist-info/RECORD +0 -11
- PyamilySeq-0.3.0.dist-info/entry_points.txt +0 -2
- {PyamilySeq-0.3.0.dist-info → PyamilySeq-0.5.0.dist-info}/LICENSE +0 -0
- {PyamilySeq-0.3.0.dist-info → PyamilySeq-0.5.0.dist-info}/top_level.txt +0 -0
PyamilySeq/Constants.py
CHANGED
|
@@ -1,15 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
PyamilySeq_Version = 'v0.5.0'
|
|
2
2
|
|
|
3
|
-
PyamilySeq_Version = 'v0.3.0'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def is_tool_installed(tool_name):
|
|
8
|
-
"""Check if a tool is installed and available in PATH."""
|
|
9
|
-
try:
|
|
10
|
-
subprocess.run([tool_name, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
|
|
11
|
-
return True
|
|
12
|
-
except subprocess.CalledProcessError:
|
|
13
|
-
return False
|
|
14
|
-
except FileNotFoundError:
|
|
15
|
-
return False
|
PyamilySeq/PyamilySeq.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import collections
|
|
3
|
+
import os
|
|
4
|
+
import glob
|
|
5
|
+
import subprocess
|
|
6
|
+
from PyamilySeq_Species import *
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from .PyamilySeq_Species import cluster
|
|
11
|
+
from .Constants import *
|
|
12
|
+
from .utils import *
|
|
13
|
+
except (ModuleNotFoundError, ImportError, NameError, TypeError) as error:
|
|
14
|
+
from PyamilySeq_Species import cluster
|
|
15
|
+
from Constants import *
|
|
16
|
+
from utils import *
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def run_cd_hit(input_file, clustering_output, options):
|
|
22
|
+
cdhit_command = [
|
|
23
|
+
'cd-hit-est',
|
|
24
|
+
'-i', input_file,
|
|
25
|
+
'-o', clustering_output,
|
|
26
|
+
'-c', str(options.pident),
|
|
27
|
+
'-s', str(options.len_diff),
|
|
28
|
+
'-T', "20",
|
|
29
|
+
'-d', "0",
|
|
30
|
+
'-sc', "1",
|
|
31
|
+
'-sf', "1"
|
|
32
|
+
]
|
|
33
|
+
if options.verbose == True:
|
|
34
|
+
subprocess.run(cdhit_command)
|
|
35
|
+
else:
|
|
36
|
+
subprocess.run(cdhit_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def main():
|
|
40
|
+
parser = argparse.ArgumentParser(description='PyamilySeq ' + PyamilySeq_Version + ': PyamilySeq Run Parameters.')
|
|
41
|
+
### Required Arguments
|
|
42
|
+
required = parser.add_argument_group('Required Arguments')
|
|
43
|
+
required.add_argument('-run_mode', action='store', dest='run_mode', choices=['Full','Partial'],
|
|
44
|
+
help='Run Mode: Should PyamilySeq be run in "Full" or "Partial" mode?',
|
|
45
|
+
required=True)
|
|
46
|
+
required.add_argument('-group_mode', action='store', dest='group_type', choices=['Species','Genus'],
|
|
47
|
+
help='Group Mode: Should PyamilySeq be run in "Species" or "Genus" mode?',
|
|
48
|
+
required=True)
|
|
49
|
+
required.add_argument("-clust_tool", action="store", dest="clust_tool", choices=['CD-HIT'],
|
|
50
|
+
help="Clustering tool to use: CD-HIT, DIAMOND, BLAST or MMseqs2.",
|
|
51
|
+
required=True)
|
|
52
|
+
required.add_argument("-output_dir", action="store", dest="output_dir",
|
|
53
|
+
help="Directory for all output files.",
|
|
54
|
+
required=True)
|
|
55
|
+
### Full-Mode Arguments
|
|
56
|
+
full_mode_args = parser.add_argument_group('Full-Mode Arguments - Required when "-run_mode Full" is used')
|
|
57
|
+
full_mode_args.add_argument("-input_type", action="store", dest="input_type", choices=['separate', 'combined'],
|
|
58
|
+
help="Type of input files: 'separate' for separate FASTA and GFF files,"
|
|
59
|
+
" 'combined' for GFF files with embedded FASTA sequences.",
|
|
60
|
+
required=False)
|
|
61
|
+
full_mode_args.add_argument("-input_dir", action="store", dest="input_dir",
|
|
62
|
+
help="Directory containing GFF/FASTA files.",
|
|
63
|
+
required=False)
|
|
64
|
+
full_mode_args.add_argument("-name_split", action="store", dest="name_split",
|
|
65
|
+
help="substring used to split the filename and extract the genome name ('_combined.gff3' or '.gff').",
|
|
66
|
+
required=False)
|
|
67
|
+
full_mode_args.add_argument("-pid", action="store", dest="pident", type=float, default=0.95,
|
|
68
|
+
help="Default 0.95: Pident threshold for clustering.",
|
|
69
|
+
required=False)
|
|
70
|
+
full_mode_args.add_argument("-len_diff", action="store", dest="len_diff", type=float, default=0.80,
|
|
71
|
+
help="Default 0.80: Minimum length difference between clustered sequences - (-s) threshold for CD-HIT clustering.",
|
|
72
|
+
required=False)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
###Partial-Mode Arguments
|
|
76
|
+
partial_mode_args = parser.add_argument_group('Partial-Mode Arguments - Required when "-run_mode Partial" is used')
|
|
77
|
+
partial_mode_args.add_argument('-cluster_file', action='store', dest='cluster_file',
|
|
78
|
+
help='Clustering output file containing CD-HIT, TSV or CSV Edge List',
|
|
79
|
+
required=False)
|
|
80
|
+
|
|
81
|
+
###Grouping Arguments
|
|
82
|
+
grouping_args = parser.add_argument_group('Grouping Arguments - Use to fine-tune grouping of genes after clustering')
|
|
83
|
+
grouping_args.add_argument('-reclustered', action='store', dest='reclustered', help='Clustering output file from secondary round of clustering',
|
|
84
|
+
required=False)
|
|
85
|
+
grouping_args.add_argument('-seq_tag', action='store', dest='sequence_tag', default='StORF',
|
|
86
|
+
help='Default - "StORF": Unique identifier to be used to distinguish the second of two rounds of clustered sequences',
|
|
87
|
+
required=False)
|
|
88
|
+
grouping_args.add_argument('-groups', action="store", dest='core_groups', default="99,95,15",
|
|
89
|
+
help='Default - (\'99,95,15\'): Gene family groups to use',
|
|
90
|
+
required=False)
|
|
91
|
+
|
|
92
|
+
###Output Arguments
|
|
93
|
+
output_args = parser.add_argument_group('Output Parameters')
|
|
94
|
+
output_args.add_argument('-w', action="store", dest='write_families', default=None,
|
|
95
|
+
help='Default - No output: Output sequences of identified families (provide levels at which to output "-w 99,95"'
|
|
96
|
+
' - Must provide FASTA file with -fasta',
|
|
97
|
+
required=False)
|
|
98
|
+
output_args.add_argument('-con', action="store", dest='con_core', default=None,
|
|
99
|
+
help='Default - No output: Output aligned and concatinated sequences of identified families - used for MSA (provide levels at which to output "-w 99,95"'
|
|
100
|
+
' - Must provide FASTA file with -fasta',
|
|
101
|
+
required=False)
|
|
102
|
+
output_args.add_argument('-original_fasta', action='store', dest='original_fasta',
|
|
103
|
+
help='FASTA file to use in conjunction with "-w" or "-con" when running in Partial Mode.',
|
|
104
|
+
required=False)
|
|
105
|
+
output_args.add_argument('-gpa', action='store', dest='gene_presence_absence_out', help='Default - False: If selected, a Roary formatted gene_presence_absence.csv will be created - Required for Coinfinder and other downstream tools',
|
|
106
|
+
required=False)
|
|
107
|
+
|
|
108
|
+
### Misc Arguments
|
|
109
|
+
misc = parser.add_argument_group('Misc')
|
|
110
|
+
misc.add_argument('-verbose', action='store', dest='verbose', default=False, type=eval, choices=[True, False],
|
|
111
|
+
help='Default - False: Print out runtime messages',
|
|
112
|
+
required = False)
|
|
113
|
+
misc.add_argument('-v', action='store_true', dest='version',
|
|
114
|
+
help='Default - False: Print out version number and exit',
|
|
115
|
+
required=False)
|
|
116
|
+
|
|
117
|
+
options = parser.parse_args()
|
|
118
|
+
|
|
119
|
+
### Checking all required parameters are provided by user
|
|
120
|
+
if options.run_mode == 'Full':
|
|
121
|
+
required_full_mode = [options.input_type, options.input_dir, options.name_split, options.clust_tool,
|
|
122
|
+
options.pident, options.len_diff]
|
|
123
|
+
if all(required_full_mode):
|
|
124
|
+
# Proceed with the Full mode
|
|
125
|
+
pass
|
|
126
|
+
else:
|
|
127
|
+
missing_options = [opt for opt in
|
|
128
|
+
['input_type', 'input_dir', 'name_split', 'clust_tool', 'pident', 'len_diff'] if
|
|
129
|
+
not options.__dict__[opt]]
|
|
130
|
+
print(f"Missing required options for Full mode: {', '.join(missing_options)}")
|
|
131
|
+
elif options.run_mode == 'Partial':
|
|
132
|
+
required_partial_mode = [options.cluster_file, ]
|
|
133
|
+
if all(required_partial_mode):
|
|
134
|
+
# Proceed with the Partial mode
|
|
135
|
+
pass
|
|
136
|
+
else:
|
|
137
|
+
missing_options = [opt for opt in
|
|
138
|
+
['cluster_file',] if
|
|
139
|
+
not options.__dict__[opt]]
|
|
140
|
+
print(f"Missing required options for Partial mode: {', '.join(missing_options)}")
|
|
141
|
+
|
|
142
|
+
if options.clust_tool == 'CD-HIT':
|
|
143
|
+
clust_affix = '.clstr'
|
|
144
|
+
elif options.clust_tool == 'TSV':
|
|
145
|
+
clust_affix = '.tsv'
|
|
146
|
+
elif options.clust_tool == 'CSV':
|
|
147
|
+
clust_affix = '.csv'
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
###External tool checks:
|
|
152
|
+
##MAFFT
|
|
153
|
+
if options.con_core == True:
|
|
154
|
+
if is_tool_installed('mafft'):
|
|
155
|
+
if options.verbose == True:
|
|
156
|
+
print("mafft is installed. Proceeding with alignment.")
|
|
157
|
+
else:
|
|
158
|
+
exit("mafft is not installed. Please install mafft to proceed.")
|
|
159
|
+
##CD-HIT
|
|
160
|
+
if options.clust_tool == 'CD-HIT':
|
|
161
|
+
if is_tool_installed('cd-hit'):
|
|
162
|
+
if options.verbose == True:
|
|
163
|
+
print("cd-hit is installed. Proceeding with clustering.")
|
|
164
|
+
else:
|
|
165
|
+
exit("cd-hit is not installed. Please install cd-hit to proceed.")
|
|
166
|
+
|
|
167
|
+
if options.write_families != None and options.original_fasta == False:
|
|
168
|
+
exit("-fasta must br provided if -w is used")
|
|
169
|
+
|
|
170
|
+
options.core_groups = options.core_groups + ',0'
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
if options.cluster_file:
|
|
174
|
+
options.cluster_file = fix_path(options.cluster_file)
|
|
175
|
+
if options.reclustered:
|
|
176
|
+
options.reclustered = fix_path(options.reclustered)
|
|
177
|
+
if options.input_dir:
|
|
178
|
+
options.input_dir = fix_path(options.input_dir)
|
|
179
|
+
if options.output_dir:
|
|
180
|
+
options.output_dir = fix_path(options.output_dir)
|
|
181
|
+
|
|
182
|
+
output_path = os.path.abspath(options.output_dir)
|
|
183
|
+
combined_out_file = os.path.join(output_path, "combined_sequences.fasta")
|
|
184
|
+
clustering_output = os.path.join(output_path, 'clustering_' + options.clust_tool)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
if options.run_mode == 'Full':
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
if options.input_type == 'separate':
|
|
192
|
+
read_separate_files(options.input_dir, options.name_split, combined_out_file)
|
|
193
|
+
else:
|
|
194
|
+
read_combined_files(options.input_dir, options.name_split, combined_out_file)
|
|
195
|
+
|
|
196
|
+
run_cd_hit(combined_out_file, clustering_output, options)
|
|
197
|
+
class clustering_options:
|
|
198
|
+
def __init__(self):
|
|
199
|
+
self.cluster_format = options.clust_tool
|
|
200
|
+
self.reclustered = options.reclustered
|
|
201
|
+
self.sequence_tag = options.sequence_tag
|
|
202
|
+
self.core_groups = '99,95,15,0'
|
|
203
|
+
self.clusters = clustering_output + clust_affix
|
|
204
|
+
self.gene_presence_absence_out = options.gene_presence_absence_out
|
|
205
|
+
self.write_families = options.write_families
|
|
206
|
+
self.con_core = options.con_core
|
|
207
|
+
self.fasta = combined_out_file
|
|
208
|
+
self.verbose = options.verbose
|
|
209
|
+
|
|
210
|
+
clustering_options = clustering_options()
|
|
211
|
+
|
|
212
|
+
elif options.run_mode == 'Partial':
|
|
213
|
+
class clustering_options:
|
|
214
|
+
def __init__(self):
|
|
215
|
+
self.cluster_format = options.clust_tool
|
|
216
|
+
self.reclustered = options.reclustered
|
|
217
|
+
self.sequence_tag = options.sequence_tag
|
|
218
|
+
self.core_groups = '99,95,15,0'
|
|
219
|
+
self.clusters = options.cluster_file
|
|
220
|
+
self.gene_presence_absence_out = options.gene_presence_absence_out
|
|
221
|
+
self.write_families = options.write_families
|
|
222
|
+
self.con_core = options.con_core
|
|
223
|
+
self.fasta = options.original_fasta
|
|
224
|
+
self.verbose = options.verbose
|
|
225
|
+
|
|
226
|
+
clustering_options = clustering_options()
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
cluster(clustering_options)
|
|
232
|
+
|
|
233
|
+
print("Thank you for using PyamilySeq -- A detailed user manual can be found at https://github.com/NickJD/PyamilySeq\n"
|
|
234
|
+
"Please report any issues to: https://github.com/NickJD/PyamilySeq/issues\n#####")
|
|
235
|
+
|
|
236
|
+
if __name__ == "__main__":
|
|
237
|
+
main()
|