Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Code from: https://codereview.stackexchange.com/questions/192027/genetic-sequence-visualizer-generating-large-images ; No longer uses `largearray` and removed timing statements (can be done better with cpython)
#!/usr/bin/env python3
# Python3
import logging
from argparse import ArgumentParser
from os import remove
from os.path import exists
from re import sub
from time import time
from PIL import Image, ImageDraw
import numpy as np
uuid = id(time())
parser = ArgumentParser()
parser.add_argument("file", help="Location of input file. path/to/file (FASTA file formats supported)")
parser.add_argument("-i", "--image-name",
help="Where to save finished image file. path/to/file (Default: Name_of_input_file.png)")
parser.add_argument("-d", "--debug-file", help="Where to store debug file. path/to/file (Default ./cache/debug.log")
args = parser.parse_args()
filepath = args.file
ipath = ".".join(filepath.split(".")[:-1]) + ".png"
if not exists(filepath):
raise Exception("Path of input file does not exist")
if args.image_name:
ipath = args.image_name
debugpath = '.cache/debug%d.log' % uuid
if args.debug_file:
debugpath = args.debug_file
if exists(debugpath):
remove(debugpath)
logging.basicConfig(filename=debugpath, level=logging.DEBUG)
logging.info("Init: %d" % uuid)
with open(filepath, 'r') as file:
logging.info("Serializing %s ..." % filepath)
raw = ''.join([n for n in file.readlines() if not n.startswith('>')]).replace('\n', "").lower()
logging.info("Replaced FASTA info")
raw = sub(r'[rykmswbdhv-]', "n", raw) # Handles miscellaneous FASTA characters
raw = sub(r'[^atgcn]', "", raw) # Remove everything except 4 bases and not-known
action_lookup = {
"a": np.array((0, -1)),
"t": np.array((0, 1)),
"g": np.array((-1, 0)),
"c": np.array((1, 0)),
"n": np.array((0, 0)),
}
color_lookup = {
"a": (0, 255, 0),
"t": (255, 0, 0),
"g": (255, 0, 255),
"c": (0, 0, 255),
"n": (0, 0, 0),
}
top_left = np.array((0, 0))
bottom_right = np.array((0, 0))
cursor = np.array((0, 0))
for base in raw:
# get the actions associated from dict
cursor += action_lookup[base]
bottom_right = np.maximum(cursor, bottom_right)
top_left = np.minimum(cursor, top_left)
# Final dimensions of image + 10px border
border = np.array((10, 10))
dim = bottom_right - top_left + 2 * border
with Image.new("RGBA", tuple(dim), None) as img:
logging.info("Initial image created. (%d x %d)" % (dim[0], dim[1]))
draw = ImageDraw.Draw(img)
logging.info("Draw object created")
cursor = np.abs(top_left) + border
for base in raw:
cursor += action_lookup[base]
color = color_lookup[base]
draw.point(tuple(cursor), fill=color)
logging.info("Path Drawn")
# Start and End points are dynamically sized to the dimensions of the final image
start_cursor = np.abs(top_left) + border
dot_size = np.ceil(np.mean(dim) / 500)
size = np.array((dot_size, dot_size))
draw.ellipse([tuple(start_cursor-size), tuple(start_cursor+size)],
fill=(255, 255, 0), outline=(255, 255, 0)) # yellow
draw.ellipse([tuple(cursor-size), tuple(cursor+size)], fill=(51, 255, 255),
outline=(51, 255, 255)) # neon blue
logging.info("Start and End points drawn")
img.save(ipath, "PNG", optimize=True)
logging.info("Image saved at %s" % ipath)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.