Mercurial > repos > greg > gregs
comparison bam_to_bigwig/bam_to_wiggle.py @ 0:bc71417f212c
Uploaded
| author | g2cmnty@test-web1.g2.bx.psu.edu |
|---|---|
| date | Fri, 17 Jun 2011 15:25:25 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:bc71417f212c |
|---|---|
| 1 #!/usr/bin/env python | |
| 2 """Convert BAM files to BigWig file format in a specified region. | |
| 3 | |
| 4 Usage: | |
| 5 bam_to_wiggle.py <BAM file> [<YAML config>] | |
| 6 [--outfile=<output file name> | |
| 7 --chrom=<chrom> | |
| 8 --start=<start> | |
| 9 --end=<end>] | |
| 10 | |
| 11 chrom start and end are optional, in which case they default to everything. | |
| 12 | |
| 13 The config file is in YAML format and specifies the location of the wigToBigWig | |
| 14 program from UCSC: | |
| 15 | |
| 16 program: | |
| 17 ucsc_bigwig: wigToBigWig | |
| 18 | |
| 19 If not specified, these will be assumed to be present in the system path. | |
| 20 | |
| 21 The script requires: | |
| 22 pysam (http://code.google.com/p/pysam/) | |
| 23 wigToBigWig from UCSC (http://hgdownload.cse.ucsc.edu/admin/exe/) | |
| 24 If a configuration file is used, then PyYAML is also required (http://pyyaml.org/) | |
| 25 """ | |
| 26 import os | |
| 27 import sys | |
| 28 import subprocess | |
| 29 import tempfile | |
| 30 from optparse import OptionParser | |
| 31 from contextlib import contextmanager, closing | |
| 32 | |
| 33 import pysam | |
| 34 | |
| 35 def main(bam_file, config_file=None, chrom='all', start=0, end=None, | |
| 36 outfile=None): | |
| 37 if config_file: | |
| 38 import yaml | |
| 39 with open(config_file) as in_handle: | |
| 40 config = yaml.load(in_handle) | |
| 41 else: | |
| 42 config = {"program": {"ucsc_bigwig" : "wigToBigWig"}} | |
| 43 if outfile is None: | |
| 44 outfile = "%s.bigwig" % os.path.splitext(bam_file)[0] | |
| 45 if start > 0: | |
| 46 start = int(start) - 1 | |
| 47 if end is not None: | |
| 48 end = int(end) | |
| 49 regions = [(chrom, start, end)] | |
| 50 if os.path.abspath(bam_file) == os.path.abspath(outfile): | |
| 51 sys.stderr.write("Bad arguments, input and output files are the same.\n") | |
| 52 sys.exit(1) | |
| 53 if not (os.path.exists(outfile) and os.path.getsize(outfile) > 0): | |
| 54 #Use a temp file to avoid any possiblity of not having write permission | |
| 55 out_handle = tempfile.NamedTemporaryFile(delete=False) | |
| 56 wig_file = out_handle.name | |
| 57 with closing(out_handle): | |
| 58 chr_sizes, wig_valid = write_bam_track(bam_file, regions, config, out_handle) | |
| 59 try: | |
| 60 if wig_valid: | |
| 61 convert_to_bigwig(wig_file, chr_sizes, config, outfile) | |
| 62 finally: | |
| 63 os.remove(wig_file) | |
| 64 | |
| 65 @contextmanager | |
| 66 def indexed_bam(bam_file, config): | |
| 67 if not os.path.exists(bam_file + ".bai"): | |
| 68 pysam.index(bam_file) | |
| 69 sam_reader = pysam.Samfile(bam_file, "rb") | |
| 70 yield sam_reader | |
| 71 sam_reader.close() | |
| 72 | |
| 73 def write_bam_track(bam_file, regions, config, out_handle): | |
| 74 out_handle.write("track %s\n" % " ".join(["type=wiggle_0", | |
| 75 "name=%s" % os.path.splitext(os.path.split(bam_file)[-1])[0], | |
| 76 "visibility=full", | |
| 77 ])) | |
| 78 is_valid = False | |
| 79 with indexed_bam(bam_file, config) as work_bam: | |
| 80 sizes = zip(work_bam.references, work_bam.lengths) | |
| 81 if len(regions) == 1 and regions[0][0] == "all": | |
| 82 regions = [(name, 0, length) for name, length in sizes] | |
| 83 for chrom, start, end in regions: | |
| 84 if end is None and chrom in work_bam.references: | |
| 85 end = work_bam.lengths[work_bam.references.index(chrom)] | |
| 86 assert end is not None, "Could not find %s in header" % chrom | |
| 87 out_handle.write("variableStep chrom=%s\n" % chrom) | |
| 88 for col in work_bam.pileup(chrom, start, end): | |
| 89 out_handle.write("%s %s\n" % (col.pos+1, col.n)) | |
| 90 is_valid = True | |
| 91 return sizes, is_valid | |
| 92 | |
| 93 def convert_to_bigwig(wig_file, chr_sizes, config, bw_file=None): | |
| 94 if not bw_file: | |
| 95 bw_file = "%s.bigwig" % (os.path.splitext(wig_file)[0]) | |
| 96 size_file = "%s-sizes.txt" % (os.path.splitext(wig_file)[0]) | |
| 97 with open(size_file, "w") as out_handle: | |
| 98 for chrom, size in chr_sizes: | |
| 99 out_handle.write("%s\t%s\n" % (chrom, size)) | |
| 100 try: | |
| 101 cl = [config["program"]["ucsc_bigwig"], wig_file, size_file, bw_file] | |
| 102 subprocess.check_call(cl) | |
| 103 finally: | |
| 104 os.remove(size_file) | |
| 105 return bw_file | |
| 106 | |
| 107 if __name__ == "__main__": | |
| 108 parser = OptionParser() | |
| 109 parser.add_option("-o", "--outfile", dest="outfile") | |
| 110 parser.add_option("-c", "--chrom", dest="chrom") | |
| 111 parser.add_option("-s", "--start", dest="start") | |
| 112 parser.add_option("-e", "--end", dest="end") | |
| 113 (options, args) = parser.parse_args() | |
| 114 if len(args) not in [1, 2]: | |
| 115 print "Incorrect arguments" | |
| 116 print __doc__ | |
| 117 sys.exit() | |
| 118 kwargs = dict( | |
| 119 outfile=options.outfile, | |
| 120 chrom=options.chrom or 'all', | |
| 121 start=options.start or 0, | |
| 122 end=options.end) | |
| 123 main(*args, **kwargs) |
