Repository navigation
Expand file tree
/
Copy pathseqdb.py
More file actions
135 lines (111 loc) · 2.77 KB
/
Copy pathseqdb.py
File metadata and controls
135 lines (111 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from bidict import *
import os.path, os
import sys
class SeqDB():
def __init__(self, fn):
self.fn = fn
self = self.load_db()
def load_db(self):
# Initialize empty SeqDB
self.db = bidict({})
# Load existing SeqDB (if exists)
if os.path.exists(self.fn):
for line in open(self.fn):
[sid, seq] = line.rstrip().split()
self.db[int(sid)] = seq
return self
def add_seq(self, seq):
# Add new sequence to SeqDB
if seq not in ~self.db:
# If SeqDB is empty, set OTU = 1
if len(self.db) == 0:
otu = 1
# Otherwise, increment to get next OTU
else:
otu = max(self.db) + 1
self.db[:seq] = otu
return otu
def merge_db(self, x, keep=0):
# Merge SeqDB with another database
# If keep == 0, use ids in self
if keep == 0:
for seq in ~x.db:
self.add_seq(seq)
return self
# If keep == 0, use ids in x
elif keep == 1:
for seq in ~self.db:
x.add_seq(seq)
return x
def get_seq(self, otu):
# Get sequence associated with OTU id
try:
seq = self.db[otu]
return seq
except:
quit('error: otu "%s "not in database' %(otu))
def get_otu(self, seq):
# Get OTU id associated with sequence
# If sequence in SeqDB, get OTU id
if seq in ~self.db:
otu = self.db[:seq]
# Otherwise, create new SeqDB entry
else:
otu = self.add_seq(seq)
# Return OTU id
return otu
def trim_db(self, l, keep_all=False):
# Trim sequences in SeqDB to length l
for seq in ~self.db:
new_seq = seq[:l]
self.add_seq(new_seq)
# Remove other sequences from SeqDB (unless keep_all==True)
if keep_all == False:
if len(seq) != l:
del self.db[:seq]
return self
def validate(self, fn):
# Load file as SeqDB
x = SeqDB(fn)
# Test for equality
if self.db == x.db:
return True
else:
return False
def write(self, out_fn=None, overwrite=False):
# If no outfile, use infile
if out_fn is None:
out_fn = self.fn
while overwrite == False and os.path.exists(out_fn):
out_fn += '.bk'
# Write SeqDB to tempfile
tmp_fn = '%s.tmp' %(out_fn)
tmp = open(tmp_fn, 'w')
for otu in self.db:
seq = self.db[otu]
tmp.write('%d\t%s\n' %(otu, seq))
tmp.close()
# Validate and move to final destination
if self.validate(tmp_fn):
cmd = 'mv %s %s' %(tmp_fn, out_fn)
os.system(cmd)
return self
def map_db(self, x, reverse=False):
# Map OTUs in self to OTUs in another SeqDB
if reverse == False:
m = {}
for seq in ~self.db:
otu1 = self.get_otu(seq)
otu2 = x.get_otu(seq)
m[otu1] = otu2
# Or map OTUs in another SeqDB to self
elif reverse == True:
m = {}
for seq in ~self.x:
otu1 = x.get_otu(seq)
otu2 = self.get_otu(seq)
m[otu1] = otu2
# Otherwise, throw error
else:
quit('error: invalid argument in map_to_db()')
return m