forked from arq5x/gemini
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgemini_stats.py
More file actions
executable file
·301 lines (258 loc) · 9.06 KB
/
Copy pathgemini_stats.py
File metadata and controls
executable file
·301 lines (258 loc) · 9.06 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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
#!/usr/bin/env python
import sqlite3
import os
import numpy as np
import cPickle
import zlib
import collections
from collections import Counter
import gemini_utils as util
from gemini_constants import *
import GeminiQuery
def get_tstv(c, args):
"""
Report the transition / transversion ratio.
"""
ts_cmd = "SELECT count(1) \
FROM variants \
WHERE type = \'snp\' \
AND sub_type = \'ts\'"
tv_cmd = "SELECT count(1) \
FROM variants v \
WHERE type = \'snp\' \
AND sub_type = \'tv\'"
# get the number of transitions
c.execute(ts_cmd)
ts = c.fetchone()[0]
# get the number of transversions
c.execute(tv_cmd)
tv = c.fetchone()[0]
# report the transitions, transversions, and the ts/tv ratio
print "ts" + '\t' + \
"tv" + '\t' + "ts/tv"
print str(ts) + '\t' + \
str(tv) + '\t' + \
str(tstv(ts,tv))
def get_tstv_coding(c, args):
"""
Report the transition / transversion ratio in coding regions.
"""
ts_cmd = "SELECT count(1) \
FROM variants v \
WHERE v.type = \'snp\' \
AND v.sub_type = \'ts\' \
AND v.is_coding = 1"
tv_cmd = "SELECT count(1) \
FROM variants v \
WHERE v.type = \'snp\' \
AND v.sub_type = \'tv\' \
AND v.is_coding = 1"
# get the number of transitions
c.execute(ts_cmd)
ts = c.fetchone()[0]
# get the number of transversions
c.execute(tv_cmd)
tv = c.fetchone()[0]
# report the transitions, transversions, and the ts/tv ratio
print "ts" + '\t' + \
"tv" + '\t' + "ts/tv"
print str(ts) + '\t' + \
str(tv) + '\t' + \
str(tstv(ts,tv))
def get_tstv_noncoding(c, args):
"""
Report the transition / transversion ratio in non-coding regions.
"""
ts_cmd = "SELECT count(1) \
FROM variants v \
WHERE v.type = \'snp\' \
AND v.sub_type = \'ts\' \
AND v.is_coding = 0"
tv_cmd = "SELECT count(1) \
FROM variants v \
WHERE v.type = \'snp\' \
AND v.sub_type = \'tv\' \
AND v.is_coding = 0"
# get the number of transitions
c.execute(ts_cmd)
ts = c.fetchone()[0]
# get the number of transversions
c.execute(tv_cmd)
tv = c.fetchone()[0]
# report the transitions, transversions, and the ts/tv ratio
print "ts" + '\t' + \
"tv" + '\t' + "ts/tv"
print str(ts) + '\t' + \
str(tv) + '\t' + \
str(tstv(ts,tv))
def tstv(ts, tv):
"""
Calculate ts/tv, and avoid division by zero error
"""
try:
return round(float(ts) / float(tv), 4)
except ZeroDivisionError:
return 0
def get_snpcounts(c, args):
"""
Report the count of each type of SNP.
"""
query = "SELECT ref, alt, count(1) \
FROM variants \
WHERE type = \'snp\' \
GROUP BY ref, alt"
# get the ref and alt alleles for all snps.
c.execute(query)
print '\t'.join(['type', 'count'])
for row in c:
print '\t'.join([str(row['ref']) + "->" + str(row['alt']),
str(row['count(1)'])])
def get_sfs(c, args):
"""
Report the site frequency spectrum
"""
precision = 3
query = "SELECT round(aaf," + str(precision) + "), count(1) \
FROM variants \
GROUP BY round(aaf," + str(precision) + ")"
c.execute(query)
print '\t'.join(['aaf', 'count'])
for row in c:
print '\t'.join([str(row[0]), str(row[1])])
def get_mds(c, args):
"""
Compute the pairwise genetic distance between each sample.
"""
idx_to_sample = {}
c.execute("select sample_id, name from samples")
for row in c:
idx_to_sample[int(row['sample_id']) - 1] = row['name']
query = "SELECT DISTINCT v.variant_id, v.gt_types\
FROM variants v\
WHERE v.type = 'snp'"
c.execute(query)
# keep a list of numeric genotype values
# for each sample
genotypes = collections.defaultdict(list)
for row in c:
gt_types = np.array(cPickle.loads(zlib.decompress(row['gt_types'])))
# at this point, gt_types is a numpy array
# idx: 0 1 2 3 4 5 6 .. #samples
# type [0 1 2 1 2 0 0 .. ]
for idx, gt_type in enumerate(gt_types):
sample = idx_to_sample[idx]
genotypes[sample].append(gt_type)
mds = collections.defaultdict(float)
# convert the genotype list for each sample
# to a numpy array for performance.
# masks stores an array of T/F indicating which genotypes are
# known (True, [0,1,2]) and unknown (False [-1]).
masks = {}
for s in genotypes:
sample = str(s)
x = np.array(genotypes[sample])
genotypes[sample] = x
masks[sample] = \
np.ma.masked_where(genotypes[sample] != UNKNOWN,
genotypes[sample]).mask
# compute the euclidean distance for each s1/s2 combination
# using numpy's vectorized sum() and square() operations.
# we use the mask arrays to identify the indices of known genotypes
# for each sample. by doing a bitwise AND of the mask arrays for the
# two samples, we have a mask array of variants where __both__ samples
# were called.
for sample1 in genotypes:
for sample2 in genotypes:
pair = (sample1, sample2)
# which variants have known genotypes for both samples?
both_mask = masks[str(sample1)] & masks[str(sample2)]
genotype1 = genotypes[sample1]
genotype2 = genotypes[sample2]
# distance between s1 and s2:
eucl_dist = float(np.sum(np.square((genotype1 - genotype2)[both_mask]))) \
/ \
float(np.sum(both_mask))
mds[pair] = eucl_dist
# report the pairwise MDS for each sample pair.
print "sample1\tsample2\tdistance"
for pair in mds:
print "\t".join([str(pair[0]), str(pair[1]), str(round(mds[pair], 4))])
def get_variants_by_sample(c, args):
"""
Report the number of variants observed for each sample
where the sample had a non-ref genotype
"""
idx_to_sample = util.map_indices_to_samples(c)
# report.
print '\t'.join(['sample', 'total'])
query = "SELECT sample_id, \
(num_het + num_hom_alt) as total \
FROM sample_genotype_counts"
c.execute(query)
for row in c:
sample = idx_to_sample[row['sample_id']]
print "\t".join(str(s) for s in [sample,
row['total']])
def get_gtcounts_by_sample(c, args):
"""
Report the count of each genotype class
observed for each sample.
"""
idx_to_sample = util.map_indices_to_samples(c)
# report.
print '\t'.join(['sample', 'num_hom_ref', 'num_het',
'num_hom_alt', 'num_unknown', 'total'])
query = "SELECT *, \
(num_hom_ref + num_het + num_hom_alt + num_unknown) as total \
FROM sample_genotype_counts"
c.execute(query)
# count the number of each genotype type obs. for each sample.
for row in c:
sample = idx_to_sample[row['sample_id']]
print "\t".join(str(s) for s in [sample,
row['num_hom_ref'],
row['num_het'],
row['num_hom_alt'],
row['num_unknown'],
row['total']])
def summarize_query_by_sample(args):
gq = GeminiQuery.GeminiQuery(args.db)
gq.run(args.query, show_variant_samples=True, gt_filter=args.gt_filter)
total_counts = Counter()
het_counts = Counter()
hom_alt_counts = Counter()
hom_ref_counts = Counter()
print "\t".join(["sample", "total", "num_het", "num_hom_alt", "num_hom_ref"])
for row in gq:
total_counts.update(row["variant_samples"])
het_counts.update(row["HET_samples"])
hom_alt_counts.update(row["HOM_ALT_samples"])
hom_ref_counts.update(row["HOM_REF_samples"])
for key in total_counts.keys():
count_row = [key, total_counts.get(key, 0), het_counts.get(key, 0),
hom_alt_counts.get(key, 0), hom_ref_counts.get(key, 0)]
print "\t".join(map(str, count_row))
def stats(parser, args):
if os.path.exists(args.db):
conn = sqlite3.connect(args.db)
conn.isolation_level = None
conn.row_factory = sqlite3.Row
c = conn.cursor()
if args.tstv:
get_tstv(c, args)
elif args.tstv_coding:
get_tstv_coding(c, args)
elif args.tstv_noncoding:
get_tstv_noncoding(c, args)
elif args.snp_counts:
get_snpcounts(c, args)
elif args.sfs:
get_sfs(c, args)
elif args.variants_by_sample:
get_variants_by_sample(c, args)
elif args.genotypes_by_sample:
get_gtcounts_by_sample(c, args)
elif args.mds:
get_mds(c, args)
elif args.query:
summarize_query_by_sample(args)