annotate allele-counts.py @ 21:1fc7bef38c5f draft default tip

"planemo upload for repository https://github.com/galaxyproject/dunovo commit ac9577f0047ad984b307fe2c4b40e2eb45a0e6e2-dirty"
author nick
date Fri, 03 Apr 2020 19:47:34 +0000
parents 44c3abd1b767
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
1 #!/usr/bin/python3
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
2 """
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
3 Run with -h option or see DESCRIPTION for description.
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
4 This script's functionality is being obsoleted by the new, and much more sanely
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
5 written, nvc-filter.py.
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
6
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
7 New in this version:
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
8 - Calculate strand bias
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
9 - Rename MINOR.FREQ.PERC to MAF
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
10
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
11 Naive Variant Caller variant count parsing one-liner:
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
12 $ cat variants.vcf | grep -v '^#' | cut -f 10 | cut -d ':' -f 4 | tr ',=' '\t:'
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
13 """
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
14 import os
57e85db3f13c Uploaded script
nick
parents:
diff changeset
15 import sys
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
16 import errno
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
17 import random
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
18 from optparse import OptionParser
57e85db3f13c Uploaded script
nick
parents:
diff changeset
19
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
20 COLUMNS = ['sample', 'chr', 'pos', 'A', 'C', 'G', 'T', 'coverage', 'alleles',
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
21 'major', 'minor', 'freq', 'bias']
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
22 COLUMN_LABELS = ['SAMPLE', 'CHR', 'POS', 'A', 'C', 'G', 'T', 'CVRG', 'ALLELES',
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
23 'MAJOR', 'MINOR', 'MAF', 'BIAS']
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
24 CANONICAL_VARIANTS = ['A', 'C', 'G', 'T']
14
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
25 USAGE = """Usage: %prog [options] -i variants.vcf -o alleles.tsv
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
26 cat variants.vcf | %prog [options] > alleles.tsv"""
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
27 OPT_DEFAULTS = {'infile':'-', 'outfile':'-', 'freq_thres':1.0, 'covg_thres':100,
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
28 'print_header':False, 'stdin':False, 'stranded':False, 'no_filter':False,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
29 'debug_loc':'', 'seed':''}
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
30 DESCRIPTION = """This will parse the VCF output of the "Naive Variant Caller"
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
31 (aka "BAM Coverage") Galaxy tool. For each position reported, it counts the
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
32 number of reads of each base, determines the major allele, minor allele (second
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
33 most frequent variant), and number of alleles above a threshold. So currently
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
34 it only considers SNVs (ACGT), including in the coverage figure. By default it
14
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
35 reads from stdin and prints to stdout.
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
36 Prints a tab-delimited set of statistics to stdout.
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
37 To print output column labels, run "$ echo -n | ./allele-counts.py -H".
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
38 The columns are: 1:SAMPLE 2:CHR 3:POS 4:A 5:C 6:G 7:T 8:CVRG 9:ALLELES 10:MAJOR
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
39 11:MINOR 12:MAF 13:BIAS,
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
40 unless the --stranded option is used, in which case they are:
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
41 1:SAMPLE 2:CHR 3:POS 4:+A 5:+C 6:+G 7:+T 8:-A 9:-C 10:-G 11:-T 12:CVRG
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
42 13:ALLELES 14:MAJOR 15:MINOR 16:MAF 17:BIAS.
e5d39283fe4d allele-counts.py: Document output columns.
nicksto <nmapsy@gmail.com>
parents: 13
diff changeset
43 """
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
44 EPILOG = """Requirements:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
45 The input VCF must report the variants for each strand.
57e85db3f13c Uploaded script
nick
parents:
diff changeset
46 The variants should be case-sensitive (e.g. all capital base letters).
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
47 Strand bias: Both strands must show the same bases passing the frequency
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
48 threshold (but not necessarily in the same order). If the site fails this test,
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
49 the number of alleles is reported as 0."""
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
50
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
51
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
52 def get_options(defaults, usage, description='', epilog=''):
57e85db3f13c Uploaded script
nick
parents:
diff changeset
53 """Get options, print usage text."""
57e85db3f13c Uploaded script
nick
parents:
diff changeset
54
57e85db3f13c Uploaded script
nick
parents:
diff changeset
55 parser = OptionParser(usage=usage, description=description, epilog=epilog)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
56
57e85db3f13c Uploaded script
nick
parents:
diff changeset
57 parser.add_option('-i', '--infile', dest='infile',
57e85db3f13c Uploaded script
nick
parents:
diff changeset
58 default=defaults.get('infile'),
57e85db3f13c Uploaded script
nick
parents:
diff changeset
59 help='Read input VCF data from this file instead of stdin.')
57e85db3f13c Uploaded script
nick
parents:
diff changeset
60 parser.add_option('-o', '--outfile', dest='outfile',
57e85db3f13c Uploaded script
nick
parents:
diff changeset
61 default=defaults.get('outfile'),
57e85db3f13c Uploaded script
nick
parents:
diff changeset
62 help='Print output data to this file instead of stdout.')
57e85db3f13c Uploaded script
nick
parents:
diff changeset
63 parser.add_option('-f', '--freq-thres', dest='freq_thres', type='float',
57e85db3f13c Uploaded script
nick
parents:
diff changeset
64 default=defaults.get('freq_thres'),
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
65 help=('Frequency threshold for counting alleles, given in percentage: -f 1 '
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
66 +'= 1% frequency. Default is %default%.'))
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
67 parser.add_option('-c', '--covg-thres', dest='covg_thres', type='int',
57e85db3f13c Uploaded script
nick
parents:
diff changeset
68 default=defaults.get('covg_thres'),
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
69 help=('Coverage threshold. Each site must be supported by at least this '
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
70 +'many reads on each strand. Otherwise the site will not be printed in '
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
71 +'the output. The default is %default reads per strand.'))
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
72 parser.add_option('-n', '--no-filter', dest='no_filter', action='store_const',
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
73 const=not(defaults.get('no_filter')), default=defaults.get('no_filter'),
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
74 help=('Operate without a frequency threshold or coverage threshold. '
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
75 +'Equivalent to "-c 0 -f 0".'))
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
76 parser.add_option('-H', '--header', dest='print_header', action='store_const',
57e85db3f13c Uploaded script
nick
parents:
diff changeset
77 const=not(defaults.get('print_header')), default=defaults.get('print_header'),
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
78 help=('Print header line. This is a #-commented line with the column '
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
79 +'labels. Off by default.'))
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
80 parser.add_option('-s', '--stranded', dest='stranded', action='store_const',
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
81 const=not(defaults.get('stranded')), default=defaults.get('stranded'),
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
82 help='Report variant counts by strand, in separate columns. Off by default.')
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
83 parser.add_option('-r', '--rand-seed', dest='seed',
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
84 default=defaults.get('seed'), help=('Seed for random number generator.'))
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
85 parser.add_option('-d', '--debug', dest='debug_loc',
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
86 default=defaults.get('debug_loc'),
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
87 help=('Turn on debug mode and specify a single site to process using UCSC '
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
88 +'coordinate format. You can also append a sample ID after another ":" '
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
89 +'to restrict it further.'))
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
90
57e85db3f13c Uploaded script
nick
parents:
diff changeset
91 (options, args) = parser.parse_args()
57e85db3f13c Uploaded script
nick
parents:
diff changeset
92
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
93 return (options, args)
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
94
57e85db3f13c Uploaded script
nick
parents:
diff changeset
95
57e85db3f13c Uploaded script
nick
parents:
diff changeset
96 def main():
57e85db3f13c Uploaded script
nick
parents:
diff changeset
97
57e85db3f13c Uploaded script
nick
parents:
diff changeset
98 (options, args) = get_options(OPT_DEFAULTS, USAGE, DESCRIPTION, EPILOG)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
99
57e85db3f13c Uploaded script
nick
parents:
diff changeset
100 infile = options.infile
57e85db3f13c Uploaded script
nick
parents:
diff changeset
101 outfile = options.outfile
57e85db3f13c Uploaded script
nick
parents:
diff changeset
102 print_header = options.print_header
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
103 freq_thres = options.freq_thres / 100
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
104 covg_thres = options.covg_thres
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
105 stranded = options.stranded
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
106 debug_loc = options.debug_loc
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
107 seed = options.seed
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
108
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
109 if options.no_filter:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
110 freq_thres = 0
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
111 covg_thres = 0
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
112
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
113 if seed:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
114 random.seed(seed)
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
115
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
116 debug = False
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
117 print_sample = ''
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
118 if debug_loc:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
119 debug = True
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
120 coords = debug_loc.split(':')
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
121 print_chr = coords[0]
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
122 print_pos = ''
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
123 if len(coords) > 1: print_pos = coords[1]
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
124 if len(coords) > 2: print_sample = coords[2]
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
125
57e85db3f13c Uploaded script
nick
parents:
diff changeset
126 # set infile_handle to either stdin or the input file
57e85db3f13c Uploaded script
nick
parents:
diff changeset
127 if infile == OPT_DEFAULTS.get('infile'):
57e85db3f13c Uploaded script
nick
parents:
diff changeset
128 infile_handle = sys.stdin
57e85db3f13c Uploaded script
nick
parents:
diff changeset
129 sys.stderr.write("Reading from standard input..\n")
57e85db3f13c Uploaded script
nick
parents:
diff changeset
130 else:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
131 if os.path.exists(infile):
57e85db3f13c Uploaded script
nick
parents:
diff changeset
132 infile_handle = open(infile, 'r')
57e85db3f13c Uploaded script
nick
parents:
diff changeset
133 else:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
134 fail('Error: Input VCF file '+infile+' not found.')
57e85db3f13c Uploaded script
nick
parents:
diff changeset
135
57e85db3f13c Uploaded script
nick
parents:
diff changeset
136 # set outfile_handle to either stdout or the output file
57e85db3f13c Uploaded script
nick
parents:
diff changeset
137 if outfile == OPT_DEFAULTS.get('outfile'):
57e85db3f13c Uploaded script
nick
parents:
diff changeset
138 outfile_handle = sys.stdout
57e85db3f13c Uploaded script
nick
parents:
diff changeset
139 else:
2
d83368b907f7 No error on existing output file
nick
parents: 0
diff changeset
140 try:
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
141 outfile_handle = open(outfile, 'w')
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
142 except IOError:
2
d83368b907f7 No error on existing output file
nick
parents: 0
diff changeset
143 fail('Error: The given output filename '+outfile+' could not be opened.')
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
144
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
145 # Take care of column names, print header
3
4627d99aa105 New script version - change in header
nick
parents: 2
diff changeset
146 if len(COLUMNS) != len(COLUMN_LABELS):
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
147 fail('Error: Internal column names list do not match column labels list.')
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
148 if stranded:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
149 COLUMNS[3:7] = ['+A', '+C', '+G', '+T', '-A', '-C', '-G', '-T']
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
150 COLUMN_LABELS[3:7] = ['+A', '+C', '+G', '+T', '-A', '-C', '-G', '-T']
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
151 if print_header:
4
900d91d653cb Add '#' back to header line
nick
parents: 3
diff changeset
152 outfile_handle.write('#'+'\t'.join(COLUMN_LABELS)+"\n")
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
153
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
154 # main loop
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
155 # each iteration processes one VCF line and prints one or more output lines
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
156 # one VCF line = one site, one or more samples
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
157 # one output line = one site, one sample
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
158 sample_names = []
57e85db3f13c Uploaded script
nick
parents:
diff changeset
159 for line in infile_handle:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
160 line = line.rstrip('\r\n')
57e85db3f13c Uploaded script
nick
parents:
diff changeset
161
57e85db3f13c Uploaded script
nick
parents:
diff changeset
162 # header lines
57e85db3f13c Uploaded script
nick
parents:
diff changeset
163 if line[0] == '#':
57e85db3f13c Uploaded script
nick
parents:
diff changeset
164 if line[0:6].upper() == '#CHROM':
57e85db3f13c Uploaded script
nick
parents:
diff changeset
165 sample_names = line.split('\t')[9:]
57e85db3f13c Uploaded script
nick
parents:
diff changeset
166 continue
57e85db3f13c Uploaded script
nick
parents:
diff changeset
167
57e85db3f13c Uploaded script
nick
parents:
diff changeset
168 if not sample_names:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
169 fail("Error in input VCF: Data line encountered before header line. "
57e85db3f13c Uploaded script
nick
parents:
diff changeset
170 +"Failed on line:\n"+line)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
171
57e85db3f13c Uploaded script
nick
parents:
diff changeset
172 site_data = read_site(line, sample_names, CANONICAL_VARIANTS)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
173
57e85db3f13c Uploaded script
nick
parents:
diff changeset
174 if debug:
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
175 if print_pos != site_data['pos']:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
176 continue
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
177 if print_chr != site_data['chr'] and print_chr != '':
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
178 continue
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
179 if print_sample != '':
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
180 for sample in site_data['samples'].keys():
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
181 if sample.lower() != print_sample.lower():
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
182 site_data['samples'].pop(sample, None)
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
183 if len(site_data['samples']) == 0:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
184 sys.stderr.write("Error: Sample '"+print_sample+"' not found.\n")
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
185 sys.exit(1)
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
186
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
187 site_summary = summarize_site(site_data, sample_names, CANONICAL_VARIANTS,
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
188 freq_thres, covg_thres, stranded, debug=debug)
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
189
57e85db3f13c Uploaded script
nick
parents:
diff changeset
190 if debug and site_summary[0]['print']:
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
191 print(line.split('\t')[9].split(':')[-1])
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
192
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
193 try:
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
194 print_site(outfile_handle, site_summary, COLUMNS)
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
195 except IOError as ioe:
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
196 if ioe.errno == errno.EPIPE:
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
197 sys.exit(0)
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
198
57e85db3f13c Uploaded script
nick
parents:
diff changeset
199 # keeps Galaxy from giving an error if there were messages on stderr
57e85db3f13c Uploaded script
nick
parents:
diff changeset
200 sys.exit(0)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
201
57e85db3f13c Uploaded script
nick
parents:
diff changeset
202
57e85db3f13c Uploaded script
nick
parents:
diff changeset
203
57e85db3f13c Uploaded script
nick
parents:
diff changeset
204 def read_site(line, sample_names, canonical):
57e85db3f13c Uploaded script
nick
parents:
diff changeset
205 """Read in a line, parse the variants into a data structure, and return it.
57e85db3f13c Uploaded script
nick
parents:
diff changeset
206 The line should be actual site data, not a header line, so check beforehand.
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
207 Only the variants in 'canonical' will be read; all others are ignored.
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
208 Note: the line is assumed to have been chomped.
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
209 The returned data is stored in a dict, with the following structure:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
210 {
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
211 'chr': 'chr1',
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
212 'pos': '2617',
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
213 'samples': {
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
214 'THYROID': {
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
215 '+A': 32,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
216 '-A': 45,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
217 '-G': 1,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
218 },
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
219 'BLOOD': {
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
220 '+A': 2,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
221 '-C': 1,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
222 '+G': 37,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
223 '-G': 42,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
224 },
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
225 },
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
226 }
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
227 """
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
228
57e85db3f13c Uploaded script
nick
parents:
diff changeset
229 site = {}
57e85db3f13c Uploaded script
nick
parents:
diff changeset
230 fields = line.split('\t')
57e85db3f13c Uploaded script
nick
parents:
diff changeset
231
57e85db3f13c Uploaded script
nick
parents:
diff changeset
232 if len(fields) < 9:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
233 fail("Error in input VCF: wrong number of fields in data line. "
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
234 "Failed on line:\n"+line)
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
235
57e85db3f13c Uploaded script
nick
parents:
diff changeset
236 site['chr'] = fields[0]
57e85db3f13c Uploaded script
nick
parents:
diff changeset
237 site['pos'] = fields[1]
57e85db3f13c Uploaded script
nick
parents:
diff changeset
238 samples = fields[9:]
57e85db3f13c Uploaded script
nick
parents:
diff changeset
239
57e85db3f13c Uploaded script
nick
parents:
diff changeset
240 if len(samples) < len(sample_names):
57e85db3f13c Uploaded script
nick
parents:
diff changeset
241 fail("Error in input VCF: missing sample fields in data line. "
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
242 "Failed on line:\n"+line)
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
243 elif len(samples) > len(sample_names):
57e85db3f13c Uploaded script
nick
parents:
diff changeset
244 fail("Error in input VCF: more sample fields in data line than in header. "
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
245 "Failed on line:\n"+line)
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
246
57e85db3f13c Uploaded script
nick
parents:
diff changeset
247 sample_counts = {}
57e85db3f13c Uploaded script
nick
parents:
diff changeset
248 for i in range(len(samples)):
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
249
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
250 variant_counts = {}
57e85db3f13c Uploaded script
nick
parents:
diff changeset
251 counts = samples[i].split(':')[-1]
57e85db3f13c Uploaded script
nick
parents:
diff changeset
252 counts = counts.split(',')
57e85db3f13c Uploaded script
nick
parents:
diff changeset
253
57e85db3f13c Uploaded script
nick
parents:
diff changeset
254 for count in counts:
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
255 if not count or count == '.':
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
256 continue
57e85db3f13c Uploaded script
nick
parents:
diff changeset
257 fields = count.split('=')
57e85db3f13c Uploaded script
nick
parents:
diff changeset
258 if len(fields) != 2:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
259 fail("Error in input VCF: Incorrect variant data format (must contain "
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
260 "a single '='). Failed on data \"{}\" in line:\n{}"
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
261 .format(count, line))
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
262 (variant, reads) = fields
57e85db3f13c Uploaded script
nick
parents:
diff changeset
263 if variant[1:] not in canonical:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
264 continue
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
265 if not variant.startswith('-') and not variant.startswith('+'):
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
266 fail("Error in input VCF: variant data not strand-specific. Failed on "
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
267 "data \"{}\" on line:\n{}".format(variant, line))
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
268 try:
6
f6d9742c1da0 fixed error on decimal variant counts
nick
parents: 4
diff changeset
269 variant_counts[variant] = int(float(reads))
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
270 except ValueError:
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
271 fail("Error in input VCF: Variant count not a valid number. Failed on "
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
272 "variant count string \"{}\"\nIn the following line:\n{}"
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
273 .format(reads, line))
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
274
57e85db3f13c Uploaded script
nick
parents:
diff changeset
275 sample_counts[sample_names[i]] = variant_counts
57e85db3f13c Uploaded script
nick
parents:
diff changeset
276
57e85db3f13c Uploaded script
nick
parents:
diff changeset
277 site['samples'] = sample_counts
57e85db3f13c Uploaded script
nick
parents:
diff changeset
278
57e85db3f13c Uploaded script
nick
parents:
diff changeset
279 return site
57e85db3f13c Uploaded script
nick
parents:
diff changeset
280
57e85db3f13c Uploaded script
nick
parents:
diff changeset
281
57e85db3f13c Uploaded script
nick
parents:
diff changeset
282 def summarize_site(site, sample_names, canonical, freq_thres, covg_thres,
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
283 stranded=False, debug=False):
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
284 """Take the raw data from the VCF line and transform it into the summary data
57e85db3f13c Uploaded script
nick
parents:
diff changeset
285 to be printed in the output format."""
57e85db3f13c Uploaded script
nick
parents:
diff changeset
286
57e85db3f13c Uploaded script
nick
parents:
diff changeset
287 site_summary = []
57e85db3f13c Uploaded script
nick
parents:
diff changeset
288 for sample_name in sample_names:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
289
57e85db3f13c Uploaded script
nick
parents:
diff changeset
290 sample = {'print':False}
57e85db3f13c Uploaded script
nick
parents:
diff changeset
291 variants = site['samples'].get(sample_name)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
292
57e85db3f13c Uploaded script
nick
parents:
diff changeset
293 sample['sample'] = sample_name
57e85db3f13c Uploaded script
nick
parents:
diff changeset
294 sample['chr'] = site['chr']
57e85db3f13c Uploaded script
nick
parents:
diff changeset
295 sample['pos'] = site['pos']
57e85db3f13c Uploaded script
nick
parents:
diff changeset
296
57e85db3f13c Uploaded script
nick
parents:
diff changeset
297 coverage = sum(variants.values())
57e85db3f13c Uploaded script
nick
parents:
diff changeset
298
57e85db3f13c Uploaded script
nick
parents:
diff changeset
299 # get stranded coverage
57e85db3f13c Uploaded script
nick
parents:
diff changeset
300 covg_plus = 0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
301 covg_minus = 0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
302 for variant in variants:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
303 if variant[0] == '+':
57e85db3f13c Uploaded script
nick
parents:
diff changeset
304 covg_plus += variants[variant]
57e85db3f13c Uploaded script
nick
parents:
diff changeset
305 elif variant[0] == '-':
57e85db3f13c Uploaded script
nick
parents:
diff changeset
306 covg_minus += variants[variant]
57e85db3f13c Uploaded script
nick
parents:
diff changeset
307 # stranded coverage threshold
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
308 if covg_plus < covg_thres or covg_minus < covg_thres:
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
309 site_summary.append(sample)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
310 continue
57e85db3f13c Uploaded script
nick
parents:
diff changeset
311 else:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
312 sample['print'] = True
57e85db3f13c Uploaded script
nick
parents:
diff changeset
313
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
314 # get an ordered list of read counts for all variants (both strands)
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
315 bases = get_read_counts(variants, '+-')
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
316 ranked_bases = process_read_counts(bases, sort=True, debug=debug)
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
317
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
318 # prepare stranded or unstranded lists of base counts
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
319 base_count_lists = []
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
320 if stranded:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
321 strands = ['+', '-']
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
322 base_count_lists.append(get_read_counts(variants, '+'))
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
323 base_count_lists.append(get_read_counts(variants, '-'))
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
324 else:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
325 strands = ['']
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
326 base_count_lists.append(ranked_bases)
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
327
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
328 # record read counts into output dict
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
329 # If stranded, this will loop twice, once for each strand, and prepend '+'
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
330 # or '-' to the base name. If not stranded, it will loop once, and prepend
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
331 # nothing ('').
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
332 for (strand, base_count_list) in zip(strands, base_count_lists):
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
333 for base_count in base_count_list:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
334 sample[strand+base_count[0]] = base_count[1]
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
335 # fill in any zeros
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
336 for base in canonical:
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
337 if strand+base not in sample:
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
338 sample[strand+base] = 0
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
339
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
340 sample['alleles'] = count_alleles(variants, freq_thres, debug=debug)
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
341
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
342 # If there's a tie for 2nd, randomly choose one to be 2nd
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
343 if len(ranked_bases) >= 3 and ranked_bases[1][1] == ranked_bases[2][1]:
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
344 swap = random.choice([True,False])
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
345 if swap:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
346 tmp_base = ranked_bases[1]
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
347 ranked_bases[1] = ranked_bases[2]
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
348 ranked_bases[2] = tmp_base
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
349
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
350 if debug: print("ranked +-: "+str(ranked_bases))
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
351
57e85db3f13c Uploaded script
nick
parents:
diff changeset
352 sample['coverage'] = coverage
57e85db3f13c Uploaded script
nick
parents:
diff changeset
353 try:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
354 sample['major'] = ranked_bases[0][0]
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
355 except IndexError:
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
356 sample['major'] = '.'
57e85db3f13c Uploaded script
nick
parents:
diff changeset
357 try:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
358 sample['minor'] = ranked_bases[1][0]
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
359 sample['freq'] = round(ranked_bases[1][1]/coverage, 5)
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
360 except IndexError:
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
361 sample['minor'] = '.'
57e85db3f13c Uploaded script
nick
parents:
diff changeset
362 sample['freq'] = 0.0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
363
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
364 # Now that we've decided major and minor, we can calculate strand bias
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
365 bias = get_strand_bias(sample, variants)
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
366 if bias is None:
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
367 sample['bias'] = '.'
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
368 else:
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
369 sample['bias'] = round(bias, 5)
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
370
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
371 site_summary.append(sample)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
372
57e85db3f13c Uploaded script
nick
parents:
diff changeset
373 return site_summary
57e85db3f13c Uploaded script
nick
parents:
diff changeset
374
57e85db3f13c Uploaded script
nick
parents:
diff changeset
375
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
376 def get_read_counts(stranded_counts, strands='+-'):
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
377 """Do a simple sum of the read counts per variant, on the specified strands.
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
378 Arguments:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
379 stranded_counts: Dict of the stranded variants (keys) and their read counts
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
380 (values).
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
381 strands: Which strand(s) to count. Can be '+', '-', or '+-' for both (default).
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
382 Return value:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
383 summed_counts: A list of the alleles and their read counts. The elements are
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
384 tuples (variant, read count)."""
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
385
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
386 variants = stranded_counts.keys()
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
387
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
388 summed_counts = {}
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
389 for variant in variants:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
390 strand = variant[0]
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
391 base = variant[1:]
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
392 if strand in strands:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
393 summed_counts[base] = stranded_counts[variant] + summed_counts.get(base, 0)
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
394
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
395 return list(summed_counts.items())
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
396
57e85db3f13c Uploaded script
nick
parents:
diff changeset
397
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
398 def process_read_counts(variant_counts, freq_thres=0, sort=False, debug=False):
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
399 """Process a list of read counts by frequency filtering and/or sorting.
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
400 Arguments:
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
401 variant_counts: List of the non-stranded variants and their read counts. The
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
402 elements are tuples (variant, read count).
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
403 freq_thres: The frequency threshold each allele needs to pass to be included.
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
404 sort: Whether to sort the list in descending order of read counts.
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
405 Return value:
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
406 variant_counts: A list of the processed alleles and their read counts. The
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
407 elements are tuples (variant, read count)."""
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
408
57e85db3f13c Uploaded script
nick
parents:
diff changeset
409 # get coverage for the specified strands
57e85db3f13c Uploaded script
nick
parents:
diff changeset
410 coverage = 0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
411 for variant in variant_counts:
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
412 coverage += variant[1]
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
413
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
414 if coverage <= 0:
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
415 return []
57e85db3f13c Uploaded script
nick
parents:
diff changeset
416
57e85db3f13c Uploaded script
nick
parents:
diff changeset
417 # sort the list of alleles by read count
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
418 if sort:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
419 variant_counts.sort(reverse=True, key=lambda variant: variant[1])
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
420
57e85db3f13c Uploaded script
nick
parents:
diff changeset
421 if debug:
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
422 print('coverage: '+str(coverage)+', freq_thres: '+str(freq_thres))
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
423 for variant in variant_counts:
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
424 print((variant[0]+': '+str(variant[1])+'/'+str(float(coverage))+' = '+
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
425 str(variant[1]/coverage)))
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
426
57e85db3f13c Uploaded script
nick
parents:
diff changeset
427 # remove bases below the frequency threshold
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
428 if freq_thres > 0:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
429 variant_counts = [variant for variant in variant_counts
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
430 if variant[1]/coverage >= freq_thres]
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
431
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
432 return variant_counts
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
433
57e85db3f13c Uploaded script
nick
parents:
diff changeset
434
57e85db3f13c Uploaded script
nick
parents:
diff changeset
435 def count_alleles(variant_counts, freq_thres, debug=False):
57e85db3f13c Uploaded script
nick
parents:
diff changeset
436 """Determine how many alleles to report, based on filtering rules.
57e85db3f13c Uploaded script
nick
parents:
diff changeset
437 The current rule determines which bases pass the frequency threshold on each
57e85db3f13c Uploaded script
nick
parents:
diff changeset
438 strand individually, then compares the two sets of bases. If they are the same
57e85db3f13c Uploaded script
nick
parents:
diff changeset
439 (regardless of order), the allele count is the number of bases. Otherwise it
57e85db3f13c Uploaded script
nick
parents:
diff changeset
440 is zero."""
57e85db3f13c Uploaded script
nick
parents:
diff changeset
441 allele_count = 0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
442
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
443 alleles_plus = get_read_counts(variant_counts, '+')
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
444 alleles_plus = process_read_counts(alleles_plus, freq_thres=freq_thres,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
445 sort=False, debug=debug)
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
446 alleles_minus = get_read_counts(variant_counts, '-')
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
447 alleles_minus = process_read_counts(alleles_minus, freq_thres=freq_thres,
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
448 sort=False, debug=debug)
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
449
57e85db3f13c Uploaded script
nick
parents:
diff changeset
450 if debug:
17
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
451 print('+ '+str(alleles_plus))
44c3abd1b767 "planemo upload for repository https://github.com/galaxyproject/dunovo commit 5a2e08bc1213b0437d0adcb45f7f431bd3c735f4"
nick
parents: 14
diff changeset
452 print('- '+str(alleles_minus))
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
453
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
454 # Check if each strand reports the same set of alleles.
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
455 # Sorting by base is to compare lists without regard to order (as sets).
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
456 alleles_plus_sorted = sorted([base[0] for base in alleles_plus if base[1]])
57e85db3f13c Uploaded script
nick
parents:
diff changeset
457 alleles_minus_sorted = sorted([base[0] for base in alleles_minus if base[1]])
57e85db3f13c Uploaded script
nick
parents:
diff changeset
458 if alleles_plus_sorted == alleles_minus_sorted:
57e85db3f13c Uploaded script
nick
parents:
diff changeset
459 allele_count = len(alleles_plus)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
460
57e85db3f13c Uploaded script
nick
parents:
diff changeset
461 return allele_count
57e85db3f13c Uploaded script
nick
parents:
diff changeset
462
57e85db3f13c Uploaded script
nick
parents:
diff changeset
463
13
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
464 def get_strand_bias(sample, variants):
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
465 """Based on method 1 (SB) of Guo et al., 2012
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
466 If there a denominator would be 0, there is no valid result and this will
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
467 return None. This occurs when there are no reads on one of the strands, or
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
468 when there are no minor allele reads."""
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
469 # using same variable names as in paper
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
470 a = variants.get('+'+sample['major'], 0) # forward major allele
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
471 b = variants.get('+'+sample['minor'], 0) # forward minor allele
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
472 c = variants.get('-'+sample['major'], 0) # reverse major allele
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
473 d = variants.get('-'+sample['minor'], 0) # reverse minor allele
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
474 # no minor allele reads
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
475 try:
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
476 return abs(b/(a+b) - d/(c+d)) / ((b+d) / (a+b+c+d))
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
477 except ZeroDivisionError:
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
478 return None
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
479
df1fb577db0d Version 1.2: Add strand bias column, rename minor allele frequency column.
me <nmapsy@gmail.com>
parents: 10
diff changeset
480
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
481 def print_site(filehandle, site, columns):
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
482 """Print the output lines for one site (one per sample).
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
483 filehandle must be open."""
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
484 for sample in site:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
485 if sample['print']:
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
486 fields = [str(sample.get(column)) for column in columns]
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
487 filehandle.write('\t'.join(fields)+"\n")
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
488
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
489
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
490 def fail(message):
57e85db3f13c Uploaded script
nick
parents:
diff changeset
491 sys.stderr.write(message+'\n')
57e85db3f13c Uploaded script
nick
parents:
diff changeset
492 sys.exit(1)
57e85db3f13c Uploaded script
nick
parents:
diff changeset
493
10
db6f217dc45a Uploaded tarball.
nick
parents: 7
diff changeset
494
0
57e85db3f13c Uploaded script
nick
parents:
diff changeset
495 if __name__ == "__main__":
57e85db3f13c Uploaded script
nick
parents:
diff changeset
496 main()