Mercurial > repos > nick > dna_visualizer
comparison visualize.py @ 8:534516105ca9
visualize.py: The second tool, for a more aesthetic, abstract visualization.
| author | Nick Stoler <nstoler@psu.edu> |
|---|---|
| date | Sun, 02 Mar 2014 23:47:41 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 7:2d99feb4a8e3 | 8:534516105ca9 |
|---|---|
| 1 #!/usr/bin/python | |
| 2 import sys | |
| 3 import random | |
| 4 import hashlib | |
| 5 import Image | |
| 6 import ImageDraw | |
| 7 | |
| 8 def main(): | |
| 9 | |
| 10 if len(sys.argv) == 1: | |
| 11 print """USAGE: | |
| 12 $ ./visualize.py genome.fa outfile.png pxsize | |
| 13 The last two arguments are optional, but must be in those positions. | |
| 14 If no outfile name is given, it will attempt to display the image directly. | |
| 15 If no pxsize is given, the default is 512. A power of 2 is highly | |
| 16 recommended as the resulting image will be much better laid out.""" | |
| 17 sys.exit(0) | |
| 18 | |
| 19 DEFAULT_SIZE = (512,512) | |
| 20 size = DEFAULT_SIZE | |
| 21 if len(sys.argv) > 3: | |
| 22 user_size = int(sys.argv[3]) | |
| 23 size = (user_size,user_size) | |
| 24 | |
| 25 # can skip hashing and specify the seed as an option (for testing) | |
| 26 if len(sys.argv) > 4: | |
| 27 seed = sys.argv[4] | |
| 28 else: | |
| 29 seed = get_hash(sys.argv[1]) | |
| 30 print "seed: "+seed | |
| 31 random.seed(seed) | |
| 32 level = 1 | |
| 33 layers = [] | |
| 34 image = draw_layer(size, level) | |
| 35 while 1: | |
| 36 level+=1 | |
| 37 layers.append(draw_layer(size, level)) | |
| 38 if layers[-1] == False: | |
| 39 break | |
| 40 # opacity = 256/2**level # opacity #1 | |
| 41 opacity = 256/2**(level-1) # opacity #2 | |
| 42 # opacity = 256*(level/2)/2**(level-1) # opacity #3 | |
| 43 # opacity = 256*(level/float(2**level)) # opacity #4 | |
| 44 print "opacity: "+str(int(opacity/2.56))+"%" | |
| 45 mask = Image.new("L", size, color=opacity) | |
| 46 image.paste(layers[-1], (0,0), mask) | |
| 47 | |
| 48 if len(sys.argv) > 2: | |
| 49 image.save(sys.argv[2], 'PNG') | |
| 50 else: | |
| 51 image.show() | |
| 52 | |
| 53 def draw_layer(image_size, level): | |
| 54 """Draw every block for a particular layer | |
| 55 (blocks of a particular pixel size). | |
| 56 Returns an image of the finished layer.""" | |
| 57 (image_width,image_height) = image_size | |
| 58 (width, height) = block_size(image_size, level) | |
| 59 if width < 1 or height < 1: | |
| 60 return False | |
| 61 print "width, height: "+str(width)+", "+str(height) | |
| 62 layer = Image.new("RGB", image_size, (0,0,0)) | |
| 63 draw = ImageDraw.Draw(layer) | |
| 64 (x,y) = (0,0) | |
| 65 while y < image_height: | |
| 66 while x < image_width: | |
| 67 draw.rectangle([(x,y), (x+width-1, y+height-1)], fill=randcolor()) | |
| 68 x += width | |
| 69 y += height | |
| 70 x = 0 | |
| 71 return layer | |
| 72 | |
| 73 def get_hash(filepath): | |
| 74 """Compute hash of the file""" | |
| 75 hashed = hashlib.sha256() | |
| 76 with open(filepath, 'rb') as filehandle: | |
| 77 for chunk in iter(lambda: filehandle.read(65536), b''): | |
| 78 hashed.update(chunk) | |
| 79 return hashed.hexdigest() | |
| 80 | |
| 81 def randcolor(): | |
| 82 """Return a tuple of random color values""" | |
| 83 color = [] | |
| 84 for i in range(3): | |
| 85 color.append(random.randrange(0,255)) | |
| 86 return tuple(color) | |
| 87 | |
| 88 def block_size(image_size, level): | |
| 89 """Compute the block width and height for this layer.""" | |
| 90 (width,height) = image_size | |
| 91 while level > 0: | |
| 92 width = width/2 | |
| 93 height = height/4 | |
| 94 level-=1 | |
| 95 if level < 1: | |
| 96 break | |
| 97 width = width/4 | |
| 98 height = height/2 | |
| 99 level-=1 | |
| 100 return (width,height) | |
| 101 | |
| 102 def format_genome(): | |
| 103 """Eventually I'd like to attempt to process the genome file into a standard | |
| 104 format, stripping out details of representation that can change the output, | |
| 105 such as: | |
| 106 - upper/lowercase | |
| 107 - line endings | |
| 108 - chromosome naming | |
| 109 - chromosome order | |
| 110 - noncanonical chromosomes""" | |
| 111 | |
| 112 def check_genome(): | |
| 113 """Eventually I'd like this to check assumptions I might make about the | |
| 114 genome file. A first check would be that it contains all the chromosomes, in | |
| 115 the format ''>chr1' or ''>1'. If these assumptions (which format_genome() | |
| 116 depends on) aren't met, and the format isn't recognized, then default to a | |
| 117 straight digest of the unmodified file.""" | |
| 118 | |
| 119 if __name__ == "__main__": | |
| 120 main() |
