asciidna/dna.py

86 lines
2.5 KiB
Python

from math import sin, cos, pi
from colorama import Fore,Back,Style
from time import sleep
from random import randint
import argparse
#command line arg stuff
desc="Displays an ASCII art strand of DNA, because why not?"
epi="""Protip: to watch an animated strand of ASCII DNA scroll across the screen,
set length to a really large number and pause to a reasonable number like 50
or 100 milliseconds. Enjoy!"""
parser=argparse.ArgumentParser(description=desc, epilog=epi)
parser.add_argument("-l", "--length", type=int, help="Changes the length of the ASCII DNA. Default = 40")
parser.add_argument("-p", "--pause", type=int, help="Number of milliseconds to pause after plotting each line. Default=0")
parser.add_argument("-b", "--block", action="store_true", help="Display using block characters instead of letters. Default=False")
args=parser.parse_args()
if args.length: length=args.length
else: length=40
if args.pause: pause=args.pause
else: pause=0
if args.block:
chars={"x":"","a":"","t":"","g":"","c":""}
else:
chars={"x":"X","a":"A","t":"T","g":"G","c":"C"}
#define and initialize stuff
class DnaStrand:
def __init__(self, char, func):
self.char=char
self.func=func
def pos(self,x):
return int(self.func(x))
def getchar(self): return self.char
width = 20
blank=[]
lin=[]
theta=0
basecount=2
step=pi/12
bluchar=Fore.BLUE+chars["x"]+Fore.WHITE
blustrand=DnaStrand(bluchar, lambda x: (width/2-1)*(sin(x)+1))
redchar=Fore.RED+chars["x"]+Fore.WHITE
redstrand=DnaStrand(redchar, lambda x: (width/2-1)*(cos(x)+1))
a=Fore.YELLOW+chars["a"]+Fore.WHITE
t=Fore.WHITE+chars["t"]+Fore.WHITE
g=Fore.GREEN+chars["g"]+Fore.WHITE
c=Fore.CYAN+chars["c"]+Fore.WHITE
msg="tilde.club"
for i in range (width):
blank.append(" ")
#Draw
for i in range(length):
lin=blank.copy()
blupos=blustrand.pos(theta)
redpos=redstrand.pos(theta)
lin[blupos]=blustrand.getchar()
lin[redpos]=redstrand.getchar()
if basecount%3==0 and abs(blupos-redpos) > 3:
bp=randint(1,4)
if bp==1:bp1,bp2=a,t
elif bp==2:bp1,bp2=t,a
elif bp==3:bp1,bp2=g,c
else:bp1,bp2=c,g
halfway=int(abs(blupos+redpos)/2)
start=min(redpos,blupos)+1
end=max(redpos,blupos)
lin[start:halfway]=[bp1]*abs(halfway-start)
lin[halfway:end]=[bp2]*abs(end-halfway)
tc=randint(1,5)
if tc==5 and end-start > len (msg):
lin[start:start+len(msg)]=list(msg)
print("".join(lin))
theta += step
basecount+=1
sleep(pause/1000)