annotate cpt_intersect_adj/intersect_and_adjacent.py @ 2:7e393668b4b9 draft default tip

Uploaded
author cpt
date Fri, 20 May 2022 08:54:26 +0000
parents 4c72b6accdee
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
4c72b6accdee Uploaded
cpt
parents:
diff changeset
1 #!/usr/bin/env python
4c72b6accdee Uploaded
cpt
parents:
diff changeset
2 import logging
4c72b6accdee Uploaded
cpt
parents:
diff changeset
3 import argparse
4c72b6accdee Uploaded
cpt
parents:
diff changeset
4 from intervaltree import IntervalTree, Interval
4c72b6accdee Uploaded
cpt
parents:
diff changeset
5 from CPT_GFFParser import gffParse, gffWrite
4c72b6accdee Uploaded
cpt
parents:
diff changeset
6 from Bio.SeqRecord import SeqRecord
4c72b6accdee Uploaded
cpt
parents:
diff changeset
7 from Bio.Seq import Seq
4c72b6accdee Uploaded
cpt
parents:
diff changeset
8
4c72b6accdee Uploaded
cpt
parents:
diff changeset
9 logging.basicConfig(level=logging.INFO)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
10 log = logging.getLogger(__name__)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
11
4c72b6accdee Uploaded
cpt
parents:
diff changeset
12 def validFeat(rec):
4c72b6accdee Uploaded
cpt
parents:
diff changeset
13 for feat in rec.features:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
14 if feat.type != 'remark' and feat.type != 'annotation':
4c72b6accdee Uploaded
cpt
parents:
diff changeset
15 return True
4c72b6accdee Uploaded
cpt
parents:
diff changeset
16 return False
4c72b6accdee Uploaded
cpt
parents:
diff changeset
17
4c72b6accdee Uploaded
cpt
parents:
diff changeset
18 def treeFeatures(features, window):
4c72b6accdee Uploaded
cpt
parents:
diff changeset
19 for feat in features:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
20 # Interval(begin, end, data)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
21 yield Interval(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
22 int(feat.location.start) - int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
23 int(feat.location.end) + int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
24 feat.id,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
25 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
26 def treeFeatures_noRem(features, window):
4c72b6accdee Uploaded
cpt
parents:
diff changeset
27 for feat in features:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
28 if feat.type == 'remark' or feat.type == 'annotation':
4c72b6accdee Uploaded
cpt
parents:
diff changeset
29 continue
4c72b6accdee Uploaded
cpt
parents:
diff changeset
30 # Interval(begin, end, data)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
31 yield Interval(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
32 int(feat.location.start) - int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
33 int(feat.location.end) + int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
34 feat.id,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
35 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
36
4c72b6accdee Uploaded
cpt
parents:
diff changeset
37
4c72b6accdee Uploaded
cpt
parents:
diff changeset
38 def intersect(a, b, window, stranding):
4c72b6accdee Uploaded
cpt
parents:
diff changeset
39 rec_a = list(gffParse(a))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
40 rec_b = list(gffParse(b))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
41 rec_a_out = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
42 rec_b_out = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
43 maxLen = min(len(rec_a), len(rec_b))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
44 iterate = 0
4c72b6accdee Uploaded
cpt
parents:
diff changeset
45
4c72b6accdee Uploaded
cpt
parents:
diff changeset
46
4c72b6accdee Uploaded
cpt
parents:
diff changeset
47 if maxLen > 0:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
48 while iterate < maxLen:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
49 rec_a_i = rec_a[iterate]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
50 rec_b_i = rec_b[iterate]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
51
4c72b6accdee Uploaded
cpt
parents:
diff changeset
52 if (not validFeat(rec_a_i)) or (not validFeat(rec_b_i)):
4c72b6accdee Uploaded
cpt
parents:
diff changeset
53 rec_a_out.append(SeqRecord(rec_a[iterate].seq, rec_a[iterate].id, rec_a[iterate].name, rec_a[iterate].description, rec_a[iterate].dbxrefs, [], rec_a[iterate].annotations))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
54 rec_b_out.append(SeqRecord(rec_b[iterate].seq, rec_b[iterate].id, rec_b[iterate].name, rec_b[iterate].description, rec_b[iterate].dbxrefs, [], rec_b[iterate].annotations))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
55 iterate += 1
4c72b6accdee Uploaded
cpt
parents:
diff changeset
56 continue
4c72b6accdee Uploaded
cpt
parents:
diff changeset
57
4c72b6accdee Uploaded
cpt
parents:
diff changeset
58 a_neg = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
59 a_pos = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
60 b_neg = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
61 b_pos = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
62 tree_a = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
63 tree_b = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
64 if stranding == True:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
65 for feat in rec_a_i.features:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
66 if feat.type == 'remark' or feat.type == 'annotation':
4c72b6accdee Uploaded
cpt
parents:
diff changeset
67 continue
4c72b6accdee Uploaded
cpt
parents:
diff changeset
68 if feat.strand > 0:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
69 a_pos.append(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
70 Interval(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
71 int(feat.location.start) - int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
72 int(feat.location.end) + int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
73 feat.id,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
74 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
75 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
76 else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
77 a_neg.append(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
78 Interval(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
79 int(feat.location.start) - int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
80 int(feat.location.end) + int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
81 feat.id,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
82 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
83 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
84
4c72b6accdee Uploaded
cpt
parents:
diff changeset
85 for feat in rec_b_i.features:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
86 if feat.type == 'remark' or feat.type == 'annotation':
4c72b6accdee Uploaded
cpt
parents:
diff changeset
87 continue
4c72b6accdee Uploaded
cpt
parents:
diff changeset
88 if feat.strand > 0:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
89 b_pos.append(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
90 Interval(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
91 int(feat.location.start) - int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
92 int(feat.location.end) + int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
93 feat.id,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
94 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
95 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
96 else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
97 b_neg.append(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
98 Interval(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
99 int(feat.location.start) - int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
100 int(feat.location.end) + int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
101 feat.id,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
102 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
103 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
104
4c72b6accdee Uploaded
cpt
parents:
diff changeset
105 else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
106 for feat in rec_a_i.features:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
107 if feat.type == 'remark' or feat.type == 'annotation':
4c72b6accdee Uploaded
cpt
parents:
diff changeset
108 continue
4c72b6accdee Uploaded
cpt
parents:
diff changeset
109 tree_a.append(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
110 Interval(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
111 int(feat.location.start) - int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
112 int(feat.location.end) + int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
113 feat.id,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
114 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
115 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
116 for feat in rec_b_i.features:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
117 if feat.type == 'remark' or feat.type == 'annotation':
4c72b6accdee Uploaded
cpt
parents:
diff changeset
118 continue
4c72b6accdee Uploaded
cpt
parents:
diff changeset
119 tree_b.append(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
120 Interval(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
121 int(feat.location.start) - int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
122 int(feat.location.end) + int(window),
4c72b6accdee Uploaded
cpt
parents:
diff changeset
123 feat.id,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
124 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
125 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
126 if stranding:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
127 # builds interval tree from Interval objects of form (start, end, id) for each feature
4c72b6accdee Uploaded
cpt
parents:
diff changeset
128 # tree_a = IntervalTree(list(treeFeatures_noRem(rec_a_i.features, window)))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
129 #tree_b = IntervalTree(list(treeFeatures_noRem(rec_b_i.features, window)))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
130 #else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
131 tree_a_pos = IntervalTree(a_pos)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
132 tree_a_neg = IntervalTree(a_neg)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
133 tree_b_pos = IntervalTree(b_pos)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
134 tree_b_neg = IntervalTree(b_neg)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
135 else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
136 tree_a = IntervalTree(tree_a)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
137 tree_b = IntervalTree(tree_b)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
138
4c72b6accdee Uploaded
cpt
parents:
diff changeset
139
4c72b6accdee Uploaded
cpt
parents:
diff changeset
140 # Used to map ids back to features later
4c72b6accdee Uploaded
cpt
parents:
diff changeset
141 rec_a_map = {f.id: f for f in rec_a_i.features}
4c72b6accdee Uploaded
cpt
parents:
diff changeset
142 rec_b_map = {f.id: f for f in rec_b_i.features}
4c72b6accdee Uploaded
cpt
parents:
diff changeset
143
4c72b6accdee Uploaded
cpt
parents:
diff changeset
144 rec_a_hits_in_b = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
145 rec_b_hits_in_a = []
4c72b6accdee Uploaded
cpt
parents:
diff changeset
146
4c72b6accdee Uploaded
cpt
parents:
diff changeset
147 for feature in rec_a_i.features:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
148 # Save each feature in rec_a that overlaps a feature in rec_b
4c72b6accdee Uploaded
cpt
parents:
diff changeset
149 # hits = tree_b.find_range((int(feature.location.start), int(feature.location.end)))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
150
4c72b6accdee Uploaded
cpt
parents:
diff changeset
151 if feature.type == "remark" or feature.type == "annotation":
4c72b6accdee Uploaded
cpt
parents:
diff changeset
152 continue
4c72b6accdee Uploaded
cpt
parents:
diff changeset
153
4c72b6accdee Uploaded
cpt
parents:
diff changeset
154 if stranding == False:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
155 hits = tree_b[int(feature.location.start) : int(feature.location.end)]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
156
4c72b6accdee Uploaded
cpt
parents:
diff changeset
157
4c72b6accdee Uploaded
cpt
parents:
diff changeset
158 # feature id is saved in interval result.data, use map to get full feature
4c72b6accdee Uploaded
cpt
parents:
diff changeset
159 for hit in hits:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
160 rec_a_hits_in_b.append(rec_b_map[hit.data])
4c72b6accdee Uploaded
cpt
parents:
diff changeset
161
4c72b6accdee Uploaded
cpt
parents:
diff changeset
162 else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
163 if feature.strand > 0:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
164 hits_pos = tree_b_pos[
4c72b6accdee Uploaded
cpt
parents:
diff changeset
165 int(feature.location.start) : int(feature.location.end)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
166 ]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
167 for hit in hits_pos:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
168 rec_a_hits_in_b.append(rec_b_map[hit.data])
4c72b6accdee Uploaded
cpt
parents:
diff changeset
169 else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
170 hits_neg = tree_b_neg[
4c72b6accdee Uploaded
cpt
parents:
diff changeset
171 int(feature.location.start) : int(feature.location.end)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
172 ]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
173 for hit in hits_neg:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
174 rec_a_hits_in_b.append(rec_b_map[hit.data])
4c72b6accdee Uploaded
cpt
parents:
diff changeset
175
4c72b6accdee Uploaded
cpt
parents:
diff changeset
176 for feature in rec_b_i.features:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
177 if feature.type == "remark" or feature.type == "annotation":
4c72b6accdee Uploaded
cpt
parents:
diff changeset
178 continue
4c72b6accdee Uploaded
cpt
parents:
diff changeset
179
4c72b6accdee Uploaded
cpt
parents:
diff changeset
180 if stranding == False:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
181 hits = tree_a[int(feature.location.start) : int(feature.location.end)]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
182
4c72b6accdee Uploaded
cpt
parents:
diff changeset
183 # feature id is saved in interval result.data, use map to get full feature
4c72b6accdee Uploaded
cpt
parents:
diff changeset
184 for hit in hits:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
185 rec_b_hits_in_a.append(rec_a_map[hit.data])
4c72b6accdee Uploaded
cpt
parents:
diff changeset
186
4c72b6accdee Uploaded
cpt
parents:
diff changeset
187 else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
188 if feature.strand > 0:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
189 hits_pos = tree_a_pos[
4c72b6accdee Uploaded
cpt
parents:
diff changeset
190 int(feature.location.start) : int(feature.location.end)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
191 ]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
192 for hit in hits_pos:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
193 rec_b_hits_in_a.append(rec_a_map[hit.data])
4c72b6accdee Uploaded
cpt
parents:
diff changeset
194 else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
195 hits_neg = tree_a_neg[
4c72b6accdee Uploaded
cpt
parents:
diff changeset
196 int(feature.location.start) : int(feature.location.end)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
197 ]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
198 for hit in hits_neg:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
199 rec_b_hits_in_a.append(rec_a_map[hit.data])
4c72b6accdee Uploaded
cpt
parents:
diff changeset
200
4c72b6accdee Uploaded
cpt
parents:
diff changeset
201 # Remove duplicate features using sets
4c72b6accdee Uploaded
cpt
parents:
diff changeset
202 rec_a_out.append(SeqRecord(rec_a[iterate].seq, rec_a[iterate].id, rec_a[iterate].name, rec_a[iterate].description, rec_a[iterate].dbxrefs, sorted(set(rec_a_hits_in_b), key=lambda feat: feat.location.start), rec_a[iterate].annotations))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
203 rec_b_out.append(SeqRecord(rec_b[iterate].seq, rec_b[iterate].id, rec_b[iterate].name, rec_b[iterate].description, rec_b[iterate].dbxrefs, sorted(set(rec_b_hits_in_a), key=lambda feat: feat.location.start), rec_b[iterate].annotations))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
204 iterate += 1
4c72b6accdee Uploaded
cpt
parents:
diff changeset
205
4c72b6accdee Uploaded
cpt
parents:
diff changeset
206 else:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
207 # If one input is empty, output two empty result files.
4c72b6accdee Uploaded
cpt
parents:
diff changeset
208 rec_a_out = [SeqRecord(Seq(""), "none")]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
209 rec_b_out = [SeqRecord(Seq(""), "none")]
4c72b6accdee Uploaded
cpt
parents:
diff changeset
210 return rec_a_out, rec_b_out
4c72b6accdee Uploaded
cpt
parents:
diff changeset
211
4c72b6accdee Uploaded
cpt
parents:
diff changeset
212
4c72b6accdee Uploaded
cpt
parents:
diff changeset
213 if __name__ == "__main__":
4c72b6accdee Uploaded
cpt
parents:
diff changeset
214 parser = argparse.ArgumentParser(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
215 description="rebase gff3 features against parent locations", epilog=""
4c72b6accdee Uploaded
cpt
parents:
diff changeset
216 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
217 parser.add_argument("a", type=argparse.FileType("r"))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
218 parser.add_argument("b", type=argparse.FileType("r"))
4c72b6accdee Uploaded
cpt
parents:
diff changeset
219 parser.add_argument(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
220 "window",
4c72b6accdee Uploaded
cpt
parents:
diff changeset
221 type=int,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
222 default=50,
4c72b6accdee Uploaded
cpt
parents:
diff changeset
223 help="Allows features this far away to still be considered 'adjacent'",
4c72b6accdee Uploaded
cpt
parents:
diff changeset
224 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
225 parser.add_argument(
4c72b6accdee Uploaded
cpt
parents:
diff changeset
226 "-stranding",
4c72b6accdee Uploaded
cpt
parents:
diff changeset
227 action="store_true",
4c72b6accdee Uploaded
cpt
parents:
diff changeset
228 help="Only allow adjacency for same-strand features",
4c72b6accdee Uploaded
cpt
parents:
diff changeset
229 )
4c72b6accdee Uploaded
cpt
parents:
diff changeset
230 parser.add_argument("--oa", type=str, default="a_hits_near_b.gff")
4c72b6accdee Uploaded
cpt
parents:
diff changeset
231 parser.add_argument("--ob", type=str, default="b_hits_near_a.gff")
4c72b6accdee Uploaded
cpt
parents:
diff changeset
232 args = parser.parse_args()
4c72b6accdee Uploaded
cpt
parents:
diff changeset
233
4c72b6accdee Uploaded
cpt
parents:
diff changeset
234 b, a = intersect(args.a, args.b, args.window, args.stranding)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
235
4c72b6accdee Uploaded
cpt
parents:
diff changeset
236 with open(args.oa, "w") as handle:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
237 for rec in a:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
238 gffWrite([rec], handle)
4c72b6accdee Uploaded
cpt
parents:
diff changeset
239
4c72b6accdee Uploaded
cpt
parents:
diff changeset
240 with open(args.ob, "w") as handle:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
241 for rec in b:
4c72b6accdee Uploaded
cpt
parents:
diff changeset
242 gffWrite([rec], handle)