annotate dedup_barcode_fingerprint.py @ 0:6d2ac5ec56c8 draft default tip

Uploaded first file
author brenninc
date Thu, 24 Mar 2016 09:41:40 -0400
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
1 """
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
2 .. module:: fingerprint
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
3 :platform: Unix
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
4 :synopsis: Use UMI to count transcripts
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
5 :version: 1.0
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
6
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
7 .. moduleauthor:: Mickael Mendez <mendez.mickael@gmail.com>
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
8
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
9 .. source: https://github.com/mmendez12/umicount
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
10
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
11 """
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
12
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
13 import csv
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
14 import itertools
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
15 import subprocess
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
16 import argparse
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
17 import tempfile
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
18 import os
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
19 import shutil
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
20 from collections import defaultdict
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
21
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
22 import bed12
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
23
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
24
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
25 def get_fingerprint(read):
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
26 """Get fingerprint id from the read's name. It assumes that the read's name
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
27 contains the following pattern *FP:XXX;* where *XXX* is the fingerprint id.
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
28
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
29 Args:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
30 read: A list of twelve elements where each element refers to a field in the BED format.
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
31
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
32 Returns:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
33 A string containing the fingerprint id
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
34
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
35 >>> read = ['chrX', '100', '200', 'BC:ATGC;FP:0012', '12', '+', '100', '110', '255,0,0', '2', '21,25', '0,75']
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
36 >>> get_fingerprint(read)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
37 '0012'
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
38 """
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
39 return read[3].split('FP:')[1].split(';')[0]
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
40
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
41
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
42 def get_barcode(read):
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
43 """Get barcode from the read's name. It assumes that the read's name
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
44 contains the following pattern *BC:XXX;* where *XXX* is the actual barcode.
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
45
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
46 Args:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
47 read: A list of twelve elements where each element refers to a field in the BED format.
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
48
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
49 Returns:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
50 A string containing the barcode
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
51
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
52 >>> read = ['chrX', '100', '200', 'BC:ATGC;FP:0012', '12', '+', '100', '110', '255,0,0', '2', '21,25', '0,75']
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
53 >>> get_barcode(read)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
54 'ATGC'
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
55 """
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
56 return read[3].split('BC:')[1].split(';')[0]
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
57
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
58
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
59 def print_read_to_bed12(key, reads):
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
60 """ Merge the reads by blocks and print a single read in the BED12 format on stdout.
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
61 It assumes that the reads are on the same TSS and contains
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
62 barcode and fingerprint information in the read's name.
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
63
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
64 Args:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
65 key: A tuple that contain the chromosome, barcode and fingerprint information.
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
66
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
67 reads: A list of reads (in a list) from the same TSS, that have similar barcode and fingerprint.
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
68
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
69 >>> reads = []
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
70 >>> reads.append(['chrX', '100', '200', 'BC:AAA;FP:0012', '12', '+', '100', '110', '255,0,0', '2', '20,25', '0,75'])
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
71 >>> reads.append(['chrX', '100', '300', 'BC:AAA;FP:0012', '12', '+', '100', '110', '255,0,0', '3', '20,25', '0,175'])
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
72 >>> print_read_to_bed12(('chrX', 'AAA', '0012'), reads) #doctest: +NORMALIZE_WHITESPACE
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
73 chrX 100 300 BC:AAA;FP:0012 2 + 100 120 255,0,0 3 20,25,25 0,75,175
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
74 """
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
75 block_sizes, block_starts = bed12.merge_overlapping_blocks(reads)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
76
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
77 #bed12
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
78 first_read = sorted(reads, key = bed12.get_start)[0]
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
79 chrom, barcode, fingerprint = key
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
80 start = bed12.get_start(first_read)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
81 end = start + block_starts[-1] + block_sizes[-1]
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
82 name = "BC:{0};FP:{1}".format(barcode, fingerprint)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
83 score = len(reads)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
84
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
85 strand = bed12.get_strand(first_read)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
86
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
87 if strand == '+':
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
88 thick_start = start
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
89 thick_end = start + block_sizes[0]
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
90 else:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
91 thick_start = end - block_sizes[-1]
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
92 thick_end = end
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
93
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
94 color = "255,0,0"
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
95 block_count = len(block_sizes)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
96 block_sizes = ','.join(map(str, block_sizes))
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
97 block_starts = ','.join(map(str, block_starts))
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
98
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
99 output = [chrom, start, end, name, score, strand, thick_start, thick_end,
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
100 color, block_count, block_sizes, block_starts]
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
101
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
102 output_str = map(str, output)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
103 print '\t'.join(output_str)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
104
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
105
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
106 def main():
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
107
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
108 #PARSER TODO: move this code somewhere else
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
109 parser = argparse.ArgumentParser()
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
110 group = parser.add_mutually_exclusive_group(required=True)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
111 group.add_argument("-d", "--directory", help="absolute path of the folder containing the bed files")
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
112 group.add_argument("-f", "--file", help="a bed file")
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
113 parser.add_argument("-o", help='name of the output file. Only works if the script is called with the -f option, \
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
114 ignored otherwise.')
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
115
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
116 args = parser.parse_args()
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
117
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
118 if args.directory:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
119 path, folder, files = os.walk(args.directory).next()
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
120 elif args.file:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
121 path = ''
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
122 files = [args.file]
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
123 #ENDPARSER
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
124
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
125 #create a temporary directory
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
126 tmp_dir = tempfile.mkdtemp()
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
127
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
128 plus_strand_tmp_file = open(os.path.join(tmp_dir, '+'), 'w')
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
129 minus_strand_tmp_file = open(os.path.join(tmp_dir, '-'), 'w')
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
130 plus_and_minus_sorted_path = os.path.join(tmp_dir, '+-s')
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
131
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
132 #creates two temporary bed files containing either reads on the plus or minus strand
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
133 for bed_file in files:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
134
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
135 with open(os.path.join(path, bed_file)) as bed_file:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
136 reader = csv.reader(bed_file, delimiter='\t')
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
137
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
138 for read in reader:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
139 strand = bed12.get_strand(read)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
140 if strand == '+':
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
141 plus_strand_tmp_file.write('\t'.join(read) + '\n')
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
142 elif strand == '-':
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
143 minus_strand_tmp_file.write('\t'.join(read) + '\n')
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
144
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
145
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
146 #close the files
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
147 plus_strand_tmp_file.close()
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
148 minus_strand_tmp_file.close()
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
149
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
150 #call unix sort on the file containing reads on the plus strand by tss
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
151 with open(os.path.join(tmp_dir, '+sorted'), "w") as outfile:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
152 subprocess.call(["sort", '-k2,2n', os.path.join(tmp_dir, '+')], stdout=outfile)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
153
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
154 #call unix sort on the file containing reads on the minus strand by tss
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
155 with open(os.path.join(tmp_dir, '-sorted'), "w") as outfile:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
156 subprocess.call(["sort", '-k3,3n', os.path.join(tmp_dir, '-')], stdout=outfile)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
157
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
158 #concatenate the files sorted by tss
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
159 with open(plus_and_minus_sorted_path, "w") as outfile:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
160 subprocess.call(['cat', os.path.join(tmp_dir, '+sorted'), os.path.join(tmp_dir, '-sorted')], stdout=outfile)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
161
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
162 with open(plus_and_minus_sorted_path) as bedfile:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
163 reader = csv.reader(bedfile, delimiter='\t')
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
164 reads = (line for line in reader)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
165
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
166 #for each reads on the same tss
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
167 for tss, reads in itertools.groupby(reads, bed12.get_tss):
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
168 d = defaultdict(list)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
169
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
170 #group the reads by chr, barcode and fingerprint
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
171 for read in reads:
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
172 key = (bed12.get_chrom(read), get_barcode(read), get_fingerprint(read))
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
173 d[key].append(read)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
174
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
175 #merge and print the reads that have similar tss, barcode and fingerprint
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
176 for key, reads in d.iteritems():
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
177 print_read_to_bed12(key, reads)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
178
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
179 shutil.rmtree(tmp_dir)
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
180
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
181
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
182 if __name__ == '__main__':
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
183 main()
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
184
6d2ac5ec56c8 Uploaded first file
brenninc
parents:
diff changeset
185 #TODO: combine this script with dedup_fingerprint