tabtk 1.0.0__tar.gz → 1.0.2__tar.gz
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.
- {tabtk-1.0.0 → tabtk-1.0.2}/PKG-INFO +1 -1
- {tabtk-1.0.0 → tabtk-1.0.2}/tabtk/__init__.py +1 -1
- {tabtk-1.0.0 → tabtk-1.0.2}/tabtk/tabtk.py +142 -17
- {tabtk-1.0.0 → tabtk-1.0.2}/tabtk.egg-info/PKG-INFO +1 -1
- {tabtk-1.0.0 → tabtk-1.0.2}/LICENSE +0 -0
- {tabtk-1.0.0 → tabtk-1.0.2}/README.md +0 -0
- {tabtk-1.0.0 → tabtk-1.0.2}/pyproject.toml +0 -0
- {tabtk-1.0.0 → tabtk-1.0.2}/setup.cfg +0 -0
- {tabtk-1.0.0 → tabtk-1.0.2}/tabtk/__main__.py +0 -0
- {tabtk-1.0.0 → tabtk-1.0.2}/tabtk.egg-info/SOURCES.txt +0 -0
- {tabtk-1.0.0 → tabtk-1.0.2}/tabtk.egg-info/dependency_links.txt +0 -0
- {tabtk-1.0.0 → tabtk-1.0.2}/tabtk.egg-info/entry_points.txt +0 -0
- {tabtk-1.0.0 → tabtk-1.0.2}/tabtk.egg-info/requires.txt +0 -0
- {tabtk-1.0.0 → tabtk-1.0.2}/tabtk.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tabtk
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: tabtk: A toolkit for sequence similarity analysis based on tabular data
|
|
5
5
|
Author-email: Chrispin Chaguza <chrispin.chaguza@gmail.com>
|
|
6
6
|
Maintainer-email: Chrispin Chaguza <chrispin.chaguza@gmail.com>
|
|
@@ -16,6 +16,8 @@ import pandas as pd
|
|
|
16
16
|
import networkx as nx
|
|
17
17
|
import math
|
|
18
18
|
import datetime
|
|
19
|
+
import statistics
|
|
20
|
+
import glob
|
|
19
21
|
from .__init__ import __version__
|
|
20
22
|
|
|
21
23
|
def pairwiseSimilarity(firstRecord,secondRecord):
|
|
@@ -55,7 +57,7 @@ def pairwiseSimilarity(firstRecord,secondRecord):
|
|
|
55
57
|
return(similarityData)
|
|
56
58
|
|
|
57
59
|
|
|
58
|
-
def alignmentSimilarity(
|
|
60
|
+
def alignmentSimilarity(i,j):
|
|
59
61
|
seqMatch=0
|
|
60
62
|
seqMisMatch=0
|
|
61
63
|
|
|
@@ -87,6 +89,11 @@ def mashSimilarity(cmdValues):
|
|
|
87
89
|
else:
|
|
88
90
|
pass
|
|
89
91
|
|
|
92
|
+
if int(cmdValues["length"])>=16:
|
|
93
|
+
print("Note: use shorter k-mers ≤16 when working diverse sequences")
|
|
94
|
+
else:
|
|
95
|
+
pass
|
|
96
|
+
|
|
90
97
|
tmpOut = f"mash.{str(datetime.datetime.now()).replace(" ","").replace("-",".").replace(":",".")}"
|
|
91
98
|
tmpOutR = f"mash.{str(datetime.datetime.now()).replace(" ","").replace("-",".").replace(":",".")}"
|
|
92
99
|
|
|
@@ -122,6 +129,98 @@ def mashSimilarity(cmdValues):
|
|
|
122
129
|
|
|
123
130
|
return(mashResults)
|
|
124
131
|
|
|
132
|
+
def blastSimilarity(cmdValues):
|
|
133
|
+
if not shutil.which("blastn"):
|
|
134
|
+
print("Install BLAST and try again... exiting...")
|
|
135
|
+
sys.exit()
|
|
136
|
+
|
|
137
|
+
else:
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
tmpFileNames = []
|
|
141
|
+
fileNames = []
|
|
142
|
+
|
|
143
|
+
tmpCmd="wc -l "+str(cmdValues["data"])+" | awk '{print $1}'"
|
|
144
|
+
dataFileLines=subprocess.Popen(tmpCmd,shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
|
|
145
|
+
dataLines = int(dataFileLines.communicate()[0])
|
|
146
|
+
dataFileLines.kill()
|
|
147
|
+
|
|
148
|
+
bar = ChargingBar("Loading data", max=int(dataLines))
|
|
149
|
+
for fileName in open(cmdValues["data"],"r"):
|
|
150
|
+
fileNames.append(str(fileName).strip())
|
|
151
|
+
|
|
152
|
+
bar.next()
|
|
153
|
+
bar.finish()
|
|
154
|
+
|
|
155
|
+
for i in fileNames:
|
|
156
|
+
tmpFileNames.append(f"{Path(i).stem}.tmpfna")
|
|
157
|
+
|
|
158
|
+
with open(f"{Path(i).stem}.tmpfna","w") as fh:
|
|
159
|
+
for j in SeqIO.parse(i,"fasta"):
|
|
160
|
+
fh.write(f">{Path(os.path.basename(i)).stem}\n{j.seq}\n")
|
|
161
|
+
|
|
162
|
+
tmpOut = f"blast.{str(datetime.datetime.now()).replace(" ","").replace("-",".").replace(":",".")}"
|
|
163
|
+
|
|
164
|
+
Cmd1 = f"cat {" ".join(tmpFileNames)} > {tmpOut}"
|
|
165
|
+
Cmd2 = f"makeblastdb -in {tmpOut} -dbtype nucl"
|
|
166
|
+
|
|
167
|
+
subprocess.call(Cmd1,shell=True,stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
|
168
|
+
subprocess.call(Cmd2,shell=True,stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
|
169
|
+
|
|
170
|
+
print("Calculating percent similarity... may take longer... be patient...")
|
|
171
|
+
|
|
172
|
+
tmpOut1 = f"blast.{str(datetime.datetime.now()).replace(" ","").replace("-",".").replace(":",".")}"
|
|
173
|
+
tmpOut2 = f"blast.{str(datetime.datetime.now()).replace(" ","").replace("-",".").replace(":",".")}"
|
|
174
|
+
|
|
175
|
+
blastCmd1 = f"echo \'qseqid sseqid length pident qcovs\' | tr \' \' \'\\t\' > {tmpOut2}"
|
|
176
|
+
blastCmd2 = f"blastn -db {tmpOut} -query {tmpOut} -word_size {cmdValues["length"]} -num_threads {cmdValues["threads"]} -outfmt \'6 qseqid sseqid length pident qcovs\' -evalue 0.001 >> {tmpOut2}"
|
|
177
|
+
|
|
178
|
+
subprocess.call(blastCmd1,shell=True,stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
|
179
|
+
subprocess.call(blastCmd2,shell=True,stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
|
180
|
+
|
|
181
|
+
blastData = pd.read_csv(tmpOut2,delimiter="\t",dtype={'pident': float,'qcovs': float})
|
|
182
|
+
blastData["tmp"] = blastData.apply(lambda x: (x["qcovs"] * x["pident"])/100,axis=1)
|
|
183
|
+
|
|
184
|
+
blastData["qseqidR"] = blastData.apply(lambda x: x["qseqid"] if x["qseqid"] > x["sseqid"] else x["sseqid"],axis=1)
|
|
185
|
+
blastData["sseqidR"] = blastData.apply(lambda x: x["qseqid"] if x["qseqid"] < x["sseqid"] else x["sseqid"],axis=1)
|
|
186
|
+
|
|
187
|
+
blastData["qseqid"] = blastData["qseqidR"]
|
|
188
|
+
blastData["sseqid"] = blastData["sseqidR"]
|
|
189
|
+
|
|
190
|
+
blastData["cov"] = blastData[["qseqid","sseqid","tmp"]].groupby(["qseqid","sseqid"])["tmp"].transform(lambda x: statistics.mean(x))
|
|
191
|
+
blastDataR = blastData.groupby(["qseqid","sseqid"]).first().reset_index()
|
|
192
|
+
|
|
193
|
+
blastData = blastDataR.drop(columns=["tmp","length","pident","qseqidR","sseqidR"])
|
|
194
|
+
blastDataFinal = blastData[["sseqid","qseqid","cov"]].rename(columns={"sseqid":"seq1","qseqid":"seq2","cov":"pid"}).values.tolist()
|
|
195
|
+
|
|
196
|
+
bar = ChargingBar("Cleaning temporary files", max=len(fileNames))
|
|
197
|
+
for fileName in tmpFileNames:
|
|
198
|
+
if os.path.exists(fileName):
|
|
199
|
+
os.remove(fileName)
|
|
200
|
+
else:
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
bar.next()
|
|
204
|
+
bar.finish()
|
|
205
|
+
|
|
206
|
+
if os.path.exists(tmpOut1):
|
|
207
|
+
os.remove(tmpOut1)
|
|
208
|
+
else:
|
|
209
|
+
pass
|
|
210
|
+
|
|
211
|
+
if os.path.exists(tmpOut2):
|
|
212
|
+
os.remove(tmpOut2)
|
|
213
|
+
else:
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
for file in glob.glob(f"{tmpOut}*"):
|
|
217
|
+
if os.path.exists(file):
|
|
218
|
+
os.remove(file)
|
|
219
|
+
else:
|
|
220
|
+
pass
|
|
221
|
+
|
|
222
|
+
return(blastDataFinal)
|
|
223
|
+
|
|
125
224
|
|
|
126
225
|
def fastaniSimilarity(cmdValues):
|
|
127
226
|
if not shutil.which("fastANI"):
|
|
@@ -131,6 +230,11 @@ def fastaniSimilarity(cmdValues):
|
|
|
131
230
|
else:
|
|
132
231
|
pass
|
|
133
232
|
|
|
233
|
+
if int(cmdValues["length"])>=16:
|
|
234
|
+
print("Note: use shorter k-mers ≤16 when working diverse sequences")
|
|
235
|
+
else:
|
|
236
|
+
pass
|
|
237
|
+
|
|
134
238
|
tmpOut = f"mash.{str(datetime.datetime.now()).replace(" ","").replace("-",".").replace(":",".")}"
|
|
135
239
|
|
|
136
240
|
fastaniCmd = f"fastANI --rl {cmdValues["data"]} --ql {cmdValues["data"]} -k {cmdValues["length"]} --matrix --fragLen {cmdValues["fragment"]} --minFraction {cmdValues["fraction"]} --output {tmpOut} -t {cmdValues["threads"]}"
|
|
@@ -143,11 +247,8 @@ def fastaniSimilarity(cmdValues):
|
|
|
143
247
|
|
|
144
248
|
with open(tmpOut,"r") as fastaniFile:
|
|
145
249
|
for itemPos,fastaniOutput in enumerate(fastaniFile):
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
else:
|
|
149
|
-
item = fastaniOutput.strip().split("\t")
|
|
150
|
-
fastaniResults.append(f"{Path(item[0]).stem}\t{Path(item[1]).stem}\t{float(item[2])}")
|
|
250
|
+
item = fastaniOutput.strip().split("\t")
|
|
251
|
+
fastaniResults.append(f"{Path(item[0]).stem}\t{Path(item[1]).stem}\t{float(item[2])}")
|
|
151
252
|
|
|
152
253
|
if os.path.exists(tmpOut):
|
|
153
254
|
os.remove(tmpOut)
|
|
@@ -170,7 +271,7 @@ def similarity(cmdValues):
|
|
|
170
271
|
else:
|
|
171
272
|
pass
|
|
172
273
|
|
|
173
|
-
if (not cmdValues["aln"]) and (not cmdValues["mash"]) and (not cmdValues["fastani"]):
|
|
274
|
+
if (not cmdValues["blast"]) and (not cmdValues["aln"]) and (not cmdValues["mash"]) and (not cmdValues["fastani"]):
|
|
174
275
|
dataMatrixDF = loadDataTable(cmdValues)
|
|
175
276
|
|
|
176
277
|
itemPairs = itertools.permutations([item for pos,item in enumerate(dataMatrixDF.keys()) if pos>0], r=2)
|
|
@@ -192,7 +293,7 @@ def similarity(cmdValues):
|
|
|
192
293
|
bar.next()
|
|
193
294
|
bar.finish()
|
|
194
295
|
|
|
195
|
-
elif (not cmdValues["aln"]) and (cmdValues["mash"]) and (not cmdValues["fastani"]):
|
|
296
|
+
elif (not cmdValues["blast"]) and (not cmdValues["aln"]) and (cmdValues["mash"]) and (not cmdValues["fastani"]):
|
|
196
297
|
similarityResults = mashSimilarity(cmdValues)
|
|
197
298
|
|
|
198
299
|
with open(cmdValues["output"],"w") as simData:
|
|
@@ -205,7 +306,7 @@ def similarity(cmdValues):
|
|
|
205
306
|
bar.next()
|
|
206
307
|
bar.finish()
|
|
207
308
|
|
|
208
|
-
elif (not cmdValues["aln"]) and (not cmdValues["mash"]) and (cmdValues["fastani"]):
|
|
309
|
+
elif (not cmdValues["blast"]) and (not cmdValues["aln"]) and (not cmdValues["mash"]) and (cmdValues["fastani"]):
|
|
209
310
|
similarityResults = fastaniSimilarity(cmdValues)
|
|
210
311
|
|
|
211
312
|
with open(cmdValues["output"],"w") as simData:
|
|
@@ -218,14 +319,13 @@ def similarity(cmdValues):
|
|
|
218
319
|
bar.next()
|
|
219
320
|
bar.finish()
|
|
220
321
|
|
|
221
|
-
elif (cmdValues["aln"]) and (not cmdValues["mash"]) and (not cmdValues["fastani"]):
|
|
322
|
+
elif (not cmdValues["blast"]) and (cmdValues["aln"]) and (not cmdValues["mash"]) and (not cmdValues["fastani"]):
|
|
222
323
|
alignment={}
|
|
223
324
|
|
|
224
325
|
for i in SeqIO.parse(cmdValues['data'],"fasta"):
|
|
225
326
|
alignment[i.id]=i
|
|
226
327
|
|
|
227
328
|
fhandle=open(str(cmdValues['outputFile']),"w")
|
|
228
|
-
|
|
229
329
|
fhandle.write("seq1\tseq2\tpid\n")
|
|
230
330
|
|
|
231
331
|
tmpList = sorted(map(sorted, combinations(set([i for i in alignment.keys()]), 2)))
|
|
@@ -234,6 +334,19 @@ def similarity(cmdValues):
|
|
|
234
334
|
args=[(alignment[m],alignment[n]) for m,n in tmpList]
|
|
235
335
|
results=pool.starmap(alignmentSimilarity, args)
|
|
236
336
|
|
|
337
|
+
elif (cmdValues["blast"]) and (not cmdValues["aln"]) and (not cmdValues["mash"]) and (not cmdValues["fastani"]):
|
|
338
|
+
similarityResults = blastSimilarity(cmdValues)
|
|
339
|
+
|
|
340
|
+
with open(cmdValues["output"],"w") as simData:
|
|
341
|
+
simData.write("seq1\tseq2\tpid\n")
|
|
342
|
+
|
|
343
|
+
bar = ChargingBar('Writing similarity values', max=len(similarityResults))
|
|
344
|
+
for itemPair in similarityResults:
|
|
345
|
+
simData.write(f"{"\t".join([str(r) for r in itemPair])}\n")
|
|
346
|
+
|
|
347
|
+
bar.next()
|
|
348
|
+
bar.finish()
|
|
349
|
+
|
|
237
350
|
else:
|
|
238
351
|
pass
|
|
239
352
|
|
|
@@ -258,6 +371,7 @@ def transpose(cmdValues):
|
|
|
258
371
|
def lineages1Levels(cmdValues):
|
|
259
372
|
np.random.rand(1)
|
|
260
373
|
|
|
374
|
+
print(cmdValues["thresholds"][0])
|
|
261
375
|
snpDistDF = pd.read_csv(cmdValues["data"],delimiter="\t",header=0)
|
|
262
376
|
|
|
263
377
|
Graph = nx.Graph()
|
|
@@ -857,15 +971,19 @@ def gwas(cmdValues):
|
|
|
857
971
|
bar.finish()
|
|
858
972
|
|
|
859
973
|
|
|
860
|
-
def queryKmers(seqNum,seqFile,kmerFile):
|
|
974
|
+
def queryKmers(seqNum,seqFile,kmerFile,cmdValues):
|
|
861
975
|
seqFileName = Path(os.path.basename(seqFile)).stem
|
|
862
976
|
tmpOutFileA = f"bifrost.{str(datetime.datetime.now()).replace(" ","").replace("-",".").replace(":",".")}"
|
|
863
977
|
|
|
864
978
|
tmpCmd1 = f"Bifrost build -t 3 -k 31 -i -d -r {seqFile} -o {tmpOutFileA}.graph"
|
|
865
979
|
subprocess.call(tmpCmd1,shell=True,stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
|
866
980
|
|
|
867
|
-
|
|
868
|
-
|
|
981
|
+
if cmdValues["approximate"]:
|
|
982
|
+
tmpCmd2 = f"Bifrost query -a -t 5 -e 1 -q {kmerFile} -g {tmpOutFileA}.graph.gfa.gz -o {tmpOutFileA}"
|
|
983
|
+
subprocess.call(tmpCmd2,shell=True,stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
|
984
|
+
else:
|
|
985
|
+
tmpCmd2 = f"Bifrost query -t 5 -e 1 -q {kmerFile} -g {tmpOutFileA}.graph.gfa.gz -o {tmpOutFileA}"
|
|
986
|
+
subprocess.call(tmpCmd2,shell=True,stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
|
869
987
|
|
|
870
988
|
tmpCmd3 = f"echo {seqFileName} > {tmpOutFileA}.out.tsv"
|
|
871
989
|
subprocess.call(tmpCmd3,shell=True,stdout=subprocess.DEVNULL,stderr=subprocess.STDOUT)
|
|
@@ -1096,10 +1214,10 @@ def table(cmdValues):
|
|
|
1096
1214
|
print("Query k-mers against sequences... may take longer... be patient...")
|
|
1097
1215
|
|
|
1098
1216
|
with multiprocessing.Pool(processes=cmdValues["threads"]) as pool:
|
|
1099
|
-
args = [(seqFileNum,seqFileName,kmersFile) for seqFileNum,seqFileName in seqFileDF]
|
|
1217
|
+
args = [(seqFileNum,seqFileName,kmersFile,cmdValues) for seqFileNum,seqFileName in seqFileDF]
|
|
1100
1218
|
kmerResults = pool.starmap(queryKmers, args)
|
|
1101
1219
|
|
|
1102
|
-
with open(f"{
|
|
1220
|
+
with open(f"{cmdValues["output"]}","w") as kmerData:
|
|
1103
1221
|
kmerFiles = []
|
|
1104
1222
|
kmerHeaderFiles = []
|
|
1105
1223
|
|
|
@@ -1217,6 +1335,8 @@ def tabtkMain():
|
|
|
1217
1335
|
dest='mash',help='Calculate similarity using MASH')
|
|
1218
1336
|
similarityOptions.add_argument('--fastani','-n',action='store_true',default=False,
|
|
1219
1337
|
dest='fastani',help='Calculate similarity using fastANI')
|
|
1338
|
+
similarityOptions.add_argument('--blast','-b',action='store_true',default=False,
|
|
1339
|
+
dest='blast',help='Calculate similarity using BLAST')
|
|
1220
1340
|
similarityOptions.add_argument('--aln','-a',action='store_true',default=False,
|
|
1221
1341
|
dest='aln',help='Calculate similarity based on a given sequence alignment')
|
|
1222
1342
|
similarityOptions.add_argument('--fraction','-c',action='store',required=False,nargs=1,
|
|
@@ -1403,7 +1523,7 @@ def tabtkMain():
|
|
|
1403
1523
|
help='K-mer length (default: 31)')
|
|
1404
1524
|
kmerMatrixOptions.add_argument('--min','-m',action='store',required=False,nargs=1,
|
|
1405
1525
|
metavar='minabundance',dest='minabundance',default=1,type=int,
|
|
1406
|
-
help='Minimum k-mer abundance (
|
|
1526
|
+
help='Minimum k-mer abundance (default: 1)')
|
|
1407
1527
|
kmerMatrixOptions.add_argument('--maxmem','-x',action='store',required=False,nargs=1,
|
|
1408
1528
|
metavar='maxmemory',dest='maxmemory',default=31,type=int,
|
|
1409
1529
|
help='Maximum memory (default: 5000)')
|
|
@@ -1414,6 +1534,9 @@ def tabtkMain():
|
|
|
1414
1534
|
kmerMatrixOptions.add_argument('--kmers','-k',action='store',required=False,nargs=1,
|
|
1415
1535
|
metavar='kmers',dest='kmers',default="",
|
|
1416
1536
|
help='Only query input sequence against a given k-mer database')
|
|
1537
|
+
kmerMatrixOptions.add_argument('--approx','-a',action='store_true',required=False,
|
|
1538
|
+
dest='approximate',default=False,
|
|
1539
|
+
help='Search inexact k-mers (default: False)')
|
|
1417
1540
|
kmerMatrixOptions.add_argument('--threads','-t',action='store',required=False,nargs=1,
|
|
1418
1541
|
metavar='threads',dest='threads',default=5,type=int,
|
|
1419
1542
|
help='Number of threads (default: 5)')
|
|
@@ -1445,6 +1568,7 @@ def tabtkMain():
|
|
|
1445
1568
|
'size': int(options.size[0:][0]) if isinstance(options.size,list) else int(options.size),
|
|
1446
1569
|
'mash': options.mash,
|
|
1447
1570
|
'fastani': options.fastani,
|
|
1571
|
+
'blast': options.blast,
|
|
1448
1572
|
'aln': options.aln,
|
|
1449
1573
|
'threads': int(options.threads[0:][0]) if isinstance(options.threads,list) else int(options.threads)
|
|
1450
1574
|
}
|
|
@@ -1537,6 +1661,7 @@ def tabtkMain():
|
|
|
1537
1661
|
'maxmemory': int(options.maxmemory[0:][0]) if isinstance(options.maxmemory,list) else int(options.maxmemory),
|
|
1538
1662
|
'length': int(options.length[0:][0]) if isinstance(options.length,list) else int(options.length),
|
|
1539
1663
|
'kmers': options.kmers[0:][0] if isinstance(options.kmers,list) else options.kmers,
|
|
1664
|
+
'approximate': options.approximate,
|
|
1540
1665
|
'threads': int(options.threads[0:][0]) if isinstance(options.threads,list) else int(options.threads)
|
|
1541
1666
|
}
|
|
1542
1667
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tabtk
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: tabtk: A toolkit for sequence similarity analysis based on tabular data
|
|
5
5
|
Author-email: Chrispin Chaguza <chrispin.chaguza@gmail.com>
|
|
6
6
|
Maintainer-email: Chrispin Chaguza <chrispin.chaguza@gmail.com>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|