Welcome to CASdesigner beta

by Leo d'Espaux leodespaux@gmail.com.

Other development by: Joshua Nixon, William Zhuang

Current as of 9/18/2017

For a detailed user manual and feedback, please go to https://docs.google.com/document/d/11YNoUBtit4rkWZQr_ZclzAOTE_HGMtgB3H_6cvq1Y24/edit?usp=sharing

Instructions

  1. Click on "CLICK HERE" in the cell below
  2. Click on the "play" button in the top bar

    You may need to wait a minute.

    If you get stuck at any time, Kernel/restart/restart, then repeat 1-2.

    Then follow the simple in-line instructions.

Good luck!


In [ ]:
'''
CLICK HERE 



































'''


# import libraries we're using

%matplotlib inline 
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
from Bio import SeqIO
from Bio.SeqUtils import MeltingTemp
import copy
from pandas import *
from pandas import DataFrame, read_csv
import pandas as pd  
import matplotlib.pyplot as plt
import sys
from IPython.display import Image
from IPython.display import display
from Bio import Alphabet
from Bio.SeqFeature import SeqFeature, FeatureLocation #SeptAdd
from Bio.Alphabet import IUPAC  #SeptAddoverh
from pygenome import sg
import random
import re



# define global variables
HomologyLength = 1000
PrimerMaxTm = 55 # As calculated by statluc, more like 65C by Thermo's Phusion program
PrimerMaxLen = 60
OverhangMaxFrac = 1
PromoterLength = 600
TerminatorLength = 250
Post20merLength = 14
nLinker = Seq("GGAGGTGGTGGAGGTGGA")
cLinker = Seq("GGTAGCGGTAGCGGCAGC")
            


def askUser():
    print('Python version ' + sys.version+"\n\n\n\n")
    print("\nHi, welcome to CASdesigner.\n")

          
    print("Refer to this community google doc for documentation and feedback:")
    print("https://casdesigner.jbei.org/static/cassette/casdesigner-manual.pdf")
    print("\n\n\n\nWHAT DO YOU WANT TO DO TO S288C? Type \"1\", \"2\", or \"3\".\n")
    print("\t 1 \t add to empty (insert DNA into a well-characterized site)\n") 
    print("\t 2 \t edit existing (delete or replace a gene of interest)\n")
    print("\t 3 \t stitch (get primers to stich together N fragments)\n")

    areCTags = []
    areNTags = []
    Action= input("Your answer: ")
    if Action == "1":
        fragments, areCTags, areNTags = editEmpty()
        
    elif Action == "2":
        fragments, areCTags, areNTags = editExisting()

    elif Action == "3": # This is more for stitching things together not necessarily for CRISPR
        fragments = buildCustom()
    
    #stitch makes the primers to Gibson/in vivo HR your cassette
    stitch(fragments, areCTags, areNTags)
    #write to a genbank file
    write2gb(fragments)
    
    print("You can find information on the manual on what to do next.")
    print("https://casdesigner.jbei.org/static/cassette/casdesigner-manual.pdf") 
            
            
def editEmpty():    
    
    # I have an excel file where we keep cut site information
    # and load it as a pandas dataframe called cutFrame
    
    cutFrame = pd.read_excel("locusTable.xlsx", index_col="cutName")
    
    #print(cutFrame)
    
    
    #LocusPic=Image("LocusLevelExp.png")
    #display(LocusPic)
    
    
    cutName=input("WHICH CUT SITE DO YOU WANT from the above list? e.g., \"208a\":")

    # cutName is a string that should correspond to one of the variables
    # of the "cutName" column in dataFrame, e.g., 208a
    
    # cutFrame has the 20nt sequence of the gRNA saved, which we load
    # It also has some more information we'll get to later
    cutSequence=cutFrame.loc[cutName,'cutSequence']

    # We need to load the chromosome where the cut site is
    location=cutFrame.loc[cutName,'cutChr']+".fasta"
     
    ChromosomeSeq=SeqIO.read(location, "fasta").seq
    
    if ChromosomeSeq.find(cutSequence)==-1:
        ChromosomeSeq=ChromosomeSeq.reverse_complement()
        if ChromosomeSeq.find(cutSequence)==-1:
            print("CAN'T FIND THE CUT SITE IN YOUR SEQUENCE")

    StartIndex=ChromosomeSeq.find(cutSequence)
    EndIndex=StartIndex+20+Post20merLength
    
    UpSeq=ChromosomeSeq[StartIndex-HomologyLength:StartIndex]
    DownSeq=ChromosomeSeq[EndIndex:EndIndex+HomologyLength]
        
    UpHomRec = SeqRecord(UpSeq, name="up"+cutName)
    DownHomRec = SeqRecord(DownSeq, name="dn"+cutName)
    
    print("\n\n\n\nWhat do you want to do to " + cutName + "?\n")
    print("\t1\t You have a CDS but want help picking promoter and terminator\n")
    print("\t2\t You already have a one-piece cassette and just want to integrate it\n\n")
    # Coming later
    # print("\t3\t You want to construct a donor containing two standard cassettes (pointing away from each other\n")
    areNTags = []
    areCTags = []
    
    typeEdit=input("Your answer: ")
    if typeEdit=="1":
        cassette, areCTags, areNTags = buildCassette()
        areNTags = list(map(lambda x: x+1, areNTags))
        areCTags = list(map(lambda x: x+1, areCTags))
        
        fragments = [UpHomRec] + cassette + [DownHomRec]
        
    elif typeEdit == "2":
        
        orfName=input("What's the name of your custom gene or cassette?")
        orfSeq=Seq(input("What's the sequence? "))
        orfRecord=SeqRecord(orfSeq,name=orfName)
        
        fragments=[UpHomRec, orfRecord, DownHomRec]

    elif typeEdit == "3":
        
        print("Your construct will look like this: ")
        print("up hom-<terminator1-gene1-promoter1<->promoter2-gene2-terminator2>-downhom")
        print("OK, let's build your FIRST cassette")
        PromoterRec1, orfRecord1, TerminatorRec1 = buildCassette()
         
        #now in the construction, these will be in the antisense direction, so let's change their sequences
        rTerminatorRec1=flipRecord(TerminatorRec1)
        rorfRecord1=flipRecord(orfRecord1)
        rPromoterRec1=flipRecord(PromoterRec1)
        
        print("OK, let's build your SECOND cassette")
        PromoterRec2, orfRecord2, TerminatorRec2 = buildCassette()

        fragments=[UpHomRec, rTerminatorRec1, rorfRecord1, rPromoterRec1,PromoterRec2,orfRecord2, TerminatorRec2,DownHomRec]
    
    return fragments, areCTags, areNTags
    print("\n\n\n\n\n\n\n\n")
    
    
    
def editExisting():
    
    print(" ")
    print("WHICH GENE DO YOU WANT TO EDIT? Tell me a common name, e.g., \"OAF1\"")
    print("I'm smart and pretty and I can fetch it for you.\n")
    
    GeneName= input("Your answer: ")
    
    OrigGeneRecord=fetchGene(GeneName)
    # note that this returns a seqrecord
    
    print("\nI found "+GeneName+", "+OrigGeneRecord.description+".")
    
    dice=random.random()
        
    if dice>.38:
        dice2=random.random()
        if dice2>.3:
            print("\nI have a good feeling about this one.")
        else:
            print("\nI like it.")
            
    else:
        dice2=random.random()
        if dice2>.3:
            print("\nInteresting choice.")
        else:
            print("\nI don't think this will work out well for you but let's proceed.")
    
    # We make seqrecords since that's what we carry through later in the program

    UpHomRec = fetchNeighbor(OrigGeneRecord, "upstream", HomologyLength )
    UpHomRec.name="up"+UpHomRec.name 
    DownHomRec = fetchNeighbor(OrigGeneRecord, "downstream", HomologyLength )
    DownHomRec.name="dn"+DownHomRec.name 

    print("\n\n\n\nWHAT DO YOU WANT TO DO TO " + GeneName + "?\n")
    print("\t1\t DELETE the CDS cleanly (from start to stop codon)\n")
    print("\t2\t replace the CDS with another CDS (or custom one-piece cassette)\n")
    print("\t3\t replace the CDS with a standard cassette (I will help you build it)\n")
    #print("\t4\t replace a specified region near your target gene with another specified region\n")
    
    typeEdit=input("Your answer: ")
    
    # Now let's pick the cut site. This is independent from the donor cassette
    # We have an excel sheet with genes and pre-picked cut sites
    # Or let the user pick
    
    #print("\n\n\n\nHave you heard of CRISPR/Cas9? We will need a gRNA targeting "+GeneName+".") 
    #cutSequence=input("Please enter your 20-nt gRNA here.\n")
    
    areNTags = []
    areCTags = []
    
    #note that in all the below, we want to have fragments be records
    if typeEdit=="1":
        fragments=[UpHomRec,DownHomRec]

    if typeEdit=="2":
        print(" ")
        NewGeneName=input("\n\n\n\nWhat's the name of the gene you're inserting?")
        NewGeneSeq=Seq(input("\n\n\n\nWhat's the sequence of your new gene? "))
        InsertRec = SeqRecord(NewGeneSeq, name=NewGeneName)
        fragments=[UpHomRec, InsertRec, DownHomRec]
        
    if typeEdit=="3":
        cassette, areNTags, areCTags = buildCassette()
        areNTags = list(map(lambda x: x+1, areNTags))
        areCTags = list(map(lambda x: x+1, areCTags))
        fragments=[UpHomRec] + cassette + [DownHomRec] #we need to finish buildcassette to add InsertRec here
        
        
    if typeEdit=="4":
        print("How many pieces (other than homology fragments) are you stitching together.")
        Npieces=input("Your answer: ")
        output = buildCassette()
        

        fragments=[UpHomRec, DownHomRec] #we need to finish buildcassette to add InsertRec here

    
    print("\n\n\n\nHave you heard of CRISPR? We will need a guideRNA. In the future I will help you pick it.")
    cutChoice=input("Please enter your 20-nt gRNA here.\n")
    
    
    if cutChoice=="p":
        cutSequence=cutFinder(GeneName)
    elif len(cutChoice)==20:
        cutSequence=cutChoice
    else:
        cutSequence = 'NNNNNNNNNNNNNNNNNNNN'
        # Later should check that the sequence is present and unique
        

    return fragments, areNTags, areCTags

    # Now we feed the design to a tool to pick primers which amplify each fragment
    # and add terminal homology to the neighboring fragments   

    
    
def buildCustom():
    N = int(input("How many pieces in your custom cassette: "))
    return variableCassette(N)[0]

            
    #------------------------------ FETCH FUNCTIONS -------------------------------------

    
def fetchGene(GeneName):
    
        
    #let's create a record for the oldGene
    DesiredSeq = sg.gene[GeneName].cds.seq
    
    GeneRecord = SeqRecord(DesiredSeq, name=GeneName)

    #now let's add some more information to make it useful
    GeneRecord.features=str(sg.gene[GeneName])[-7:]
    GeneRecord.description=sg.gene[GeneName].short_description

    return GeneRecord 
 
       
    
    
def fetchNeighbor(NeighborRecord, direction, distance):

    # let's load the appropriate chromosome file. The record of the gene we looked up
    # contains in the "features" the systematic name, wherein the second letter
    # corresponds to chromosome number, e.g., 1=A etc
    if NeighborRecord.features[1]=="A":
        ChromosomeRec=SeqIO.read("Scer01.fasta", "fasta")
    if NeighborRecord.features[1]=="B":
        ChromosomeRec=SeqIO.read("Scer02.fasta", "fasta")
    if NeighborRecord.features[1]=="C":
        ChromosomeRec=SeqIO.read("Scer03.fasta", "fasta")
    if NeighborRecord.features[1]=="D":
        ChromosomeRec=SeqIO.read("Scer04.fasta", "fasta")
    if NeighborRecord.features[1]=="E":
        ChromosomeRec=SeqIO.read("Scer05.fasta", "fasta")
    if NeighborRecord.features[1]=="F":
        ChromosomeRec=SeqIO.read("Scer06.fasta", "fasta")
    if NeighborRecord.features[1]=="G":
        ChromosomeRec=SeqIO.read("Scer07.fasta", "fasta")
    if NeighborRecord.features[1]=="H":
        ChromosomeRec=SeqIO.read("Scer08.fasta", "fasta")
    if NeighborRecord.features[1]=="I":
        ChromosomeRec=SeqIO.read("Scer09.fasta", "fasta")
    if NeighborRecord.features[1]=="J":
        ChromosomeRec=SeqIO.read("Scer10.fasta", "fasta")
    if NeighborRecord.features[1]=="K":
        ChromosomeRec=SeqIO.read("Scer11.fasta", "fasta")
    if NeighborRecord.features[1]=="L":
        ChromosomeRec=SeqIO.read("Scer12.fasta", "fasta")
    if NeighborRecord.features[1]=="M":
        ChromosomeRec=SeqIO.read("Scer13.fasta", "fasta")
    if NeighborRecord.features[1]=="N":
        ChromosomeRec=SeqIO.read("Scer14.fasta", "fasta")
    if NeighborRecord.features[1]=="O":
        ChromosomeRec=SeqIO.read("Scer15.fasta", "fasta")
    if NeighborRecord.features[1]=="P":
        ChromosomeRec=SeqIO.read("Scer16.fasta", "fasta") 

    
    
    # let's explicitely name the sequences from the seq record
    NeighborSeq=NeighborRecord.seq
    ChromosomeSeq=ChromosomeRec.seq
    
    # flip the sequence to orient with respect to the old gene
    if ChromosomeSeq.find(NeighborSeq)==-1:
        ChromosomeSeq=ChromosomeSeq.reverse_complement()

    StartIndex=ChromosomeSeq.find(NeighborSeq)
    EndIndex=StartIndex+len(NeighborSeq)
    
    if direction=="upstream":
        DesiredSeq=Seq(str(ChromosomeSeq[StartIndex-distance:StartIndex]),IUPAC.unambiguous_dna)
        NeighborRec=SeqRecord(DesiredSeq, name=NeighborRecord.name)

    if direction=="downstream":
        DesiredSeq=Seq(str(ChromosomeSeq[EndIndex:EndIndex+distance]),IUPAC.unambiguous_dna)
        NeighborRec=SeqRecord(DesiredSeq, name=NeighborRecord.name)
        
    return NeighborRec


    
    
    
    #------------------------------------ CONSTRUCTING STUFF --------------------------------------

def getPrimer(currRecord):
    

    mp = 0
    length = 0
    primer = Seq("")

    seq=currRecord.seq
    
    while mp <= PrimerMaxTm and length < PrimerMaxLen:
        primer = primer + seq[length]
        mp = MeltingTemp.Tm_staluc(primer)
        length += 1

    return primer           
        
def overhangPrimer(currRecord,prevSeq, linker = ""):
    #let's get the template-binding primer first
    primer=getPrimer(currRecord)
    
    #OK let's work on the overhang
    maxOhLen=PrimerMaxLen-len(primer)    
    maxFrac=1
    
    #let's decide on a max overhang length
    if round(len(primer)*(OverhangMaxFrac+1)) < 60:
             maxOhLen=round(len(primer)*OverhangMaxFrac)
    
    #the index must be an integer!!!
    maxOhLen=int(maxOhLen)
    ohprimer=prevSeq.seq[-maxOhLen:]+ linker + primer #we add the .seq so that it returns a string
    
    if len(ohprimer)>60:
        ohprimer=ohprimer[-60:]
    
    return ohprimer      
        

          
def buildCassette():
    def removeStartCodon(CDS):
        # this alternate method would be useful for error handling
        #         i = CDS.find('ATG')
        #         return (CDS[:i], CDS[:i])
        return (CDS[:3], CDS[3:])

    def removeStopCodon(CDS):
        #this alternate method would be useful for error handling
        #         stops = ['TAG', 'TAA', 'TAG']
        #         for codon in stops:
        #             i = CDS.rfind(codon)
        #             print(i)
        #             if i != -1:
        #                 return (CDS[:i], CDS[:i])
        l = len(CDS)
        return (CDS[:l - 3], CDS[l - 3:])
    
    
    # Let's display data
    #PromPic=Image("PromoterLevelExp.png")
    #display(PromPic) 
       
    PromoterName=input("Which PROMOTER do you want to use, e.g., \"TDH3\": ")
    PromoterGeneRec=fetchGene(PromoterName)
    PromoterRec=fetchNeighbor(PromoterGeneRec,"upstream",600)
    PromoterRec.name=PromoterRec.name+"ps"
    
    
    #second, the terminator
    TerminatorName = input("\n\n\n\nWhich TERMINATOR do you want to use, e.g., \"ADH1\": ")
    TerminatorGeneRec=fetchGene(TerminatorName)
    TerminatorRec=fetchNeighbor(TerminatorGeneRec,"downstream",250)
    TerminatorRec.name=TerminatorRec.name+"ts"
    
    #and last, the gene
    orfName = input("\n\n\n\nWhat is the name of your CDS, e.g., \"KlGapDH\": ")
    
    orfSeq=input("\n\n\n\nWhat's the sequence: ")
    
    #LocTags=Image("LocTags.png")
    #display(LocTags)
    
    def makeTags(text):
        if text in validTags():
            return SeqRecord(Seq(tagFinder(text)), name = text+"tag")
        else:
            n, s = text.split()
            return SeqRecord(Seq(s), name = n+"tag")
    
    nTerminalTags = input("Would you like to add an N-TERMINAL PROTEIN TAG? \n*If you don't want a tag, leave blank\n*If you want one of the tags I know, type it's name, e.g. \"MBP\"\n*If you want multiple tags seperate with commas\nIf you want a custom tag type its name followed by a space then the sequence; no commas.")
    nTerminalTags = nTerminalTags.split(',')
    nTerminalTags = list(filter(None, map(lambda x: x.strip(), nTerminalTags)))
    cTerminalTags = input("Would you like to add a C-TERMINAL PROTEIN TAG? \n*If you don't want a tag, leave blank\n*If you want one of the tags I know, type it's name, e.g. \"MBP\"\n*If you want multiple tags seperate with commas\nIf you want a custom tag type its name followed by a space then the sequence; no commas.")
    cTerminalTags = cTerminalTags.split(',')
    cTerminalTags = list(filter(None, map(lambda x: x.strip(), cTerminalTags)))
    
    nTerminals = len(nTerminalTags)
    cTerminals = len(cTerminalTags)
    
    if nTerminals > 0:
        nTerminalTags = list(map(makeTags, nTerminalTags))
        start, orfSeq = removeStartCodon(orfSeq)
        nTerminalTags[0] = start + nTerminalTags[0]
    if cTerminals > 0:
        cTerminalTags = list(map(makeTags, cTerminalTags))
        orfSeq, stop = removeStopCodon(orfSeq)
        cTerminalTags[cTerminals-1] += stop
    areNTags = [i + 1 for i in range(nTerminals)]
    areCTags = [i + 2 + nTerminals for i in range(cTerminals)]

    orfRecord=SeqRecord(Seq(orfSeq), name=orfName)
    
    return ([PromoterRec] + nTerminalTags + [orfRecord] + cTerminalTags + [TerminatorRec], areNTags, areCTags)
    

    

def variableCassette(N, toVary = 0, variants = 0):
    print("")
    print("Let's start building.")
    print("")
    
    # Store both name and sequence in a SeqRecord
    # Append them to a list
    # Return list as fragments to be stitched

    records = []
    for n in range(N):
        name = input("What is the name of sequence " + str(n+1) +":")
        sequence = input("What is the sequence of this fragment:\n")
        Rec = SeqRecord(Seq(sequence), id = str(n+1))
        Rec.name = name
        records.append(Rec)

    variantRecords = []
    variantRecords.append(records)
    # This only happens if there are variants.
    if variants > 0:
        print("Time to make those variants you wanted.")
        for n in range(variants-1):
            name = input("What is the name of variant " + str(n+1) + ":")
            sequence = input("What is the sequence of this variant:")
            Rec = SeqRecord(Seq(sequence), id = str(n+1))
            Rec.name = name
            # Make a copy of the original, switch the fragments and add it to the list. 
            # Deep-copy ensures there are no pointer issues
            tempVariant = copy.deepcopy(records)
            tempVariant[toVary - 1] = Rec
            variantRecords.append(copy.deepcopy(tempVariant))
 
    # Returns a list of lists of the SeqRecords of the fragments
    return variantRecords


def stitch(fragments, areNTags = [], areCTags = []):
    #this function takes seq records and prints primers
    
    #let's make an empty sequence file
    Nfrags=len(fragments)
    donor=Seq("")
    index=[]

    print("\n\n\n\nHere are the primers to amplify your fragments and construct your donor DNA cassette:\n")

    for i in range (0, Nfrags):
        if i in areCTags:
            #add the linker before bin
            donor += SeqRecord(cLinker, name="cLinker")
        donor=donor+fragments[i]
        if i in areNTags:
            #add linker after bin
            donor += SeqRecord(nLinker, name="nLinker")
            
            
    start = Seq("")
    stop = Seq("")
    # The names include information on
    # the homology provided by the overhang
    # Note that some primers don't have overhangs
    for i in range (0, Nfrags):
        FLinker = ""
        RLinker = ""
        # this section treats the start and stop codons as linkers that need to be primer-introduced if tags are used
        if i + 1 in areNTags and i not in areNTags:
            #add start codon to reverse primer
            start = fragments[i+1][:3].seq
            fragments[i+1] = fragments[i+1][3:]
            RLinker = start.reverse_complement()   
        if i in areNTags and i-1 not in areNTags:
            #add start codon to forward primer
            FLinker = start
        if i in areCTags and i+1 not in areCTags:
            #add a stop codon to the reverse primer
            l = len(fragments[i])
            stop = fragments[i][l-3:].seq
            fragments[i] = fragments[i][:l-3]
            RLinker = stop.reverse_complement()
        if i-1 in areCTags and i not in areCTags:
            FLinker = stop
        #this section introduces the protein linkers for tags
        if i in areNTags:
            # reverse primer will need a liniker
            RLinker = nLinker.reverse_complement()
        if i-1 in areNTags:
            # forward primer will need a linker
            FLinker = nLinker
        if i+1 in areCTags:
            # reverse primer will need a linker
            RLinker = cLinker.reverse_complement()
        if i in areCTags:
            # forward primer will need a linker
            FLinker = cLinker
        if len(FLinker)>60:
            FLinker=FLinker[-60:]
        if len(RLinker)>60:
            RLinker=RLinker[-60:]
        
        if i==0:
            print("F"+ fragments[i].name + " " + getPrimer(donor))
            print("R"+ fragments[i].name + "(" + fragments[i+1].name + ") " + overhangPrimer(fragments[i].reverse_complement(),fragments[i+1].reverse_complement(), RLinker))
        elif i==Nfrags-1:
            print("F"+ fragments[i].name + "(" + fragments[i-1].name + ") " + overhangPrimer(fragments[i],fragments[i-1], FLinker))
            print("R"+ fragments[i].name + " " + getPrimer(donor.reverse_complement()))
        else:
            print("F"+ fragments[i].name + "(" + fragments[i-1].name + ") " + overhangPrimer(fragments[i],fragments[i-1], FLinker))
            print("R"+ fragments[i].name + "(" + fragments[i+1].name + ") " + overhangPrimer(fragments[i].reverse_complement(),fragments[i+1].reverse_complement(), RLinker))

    print("\n\nThe size and sequence of your donor DNA is below.")

    print(len(donor.seq))

    print(donor.seq)

    print("\n\n\n\nGOOD LUCK! Refer to the this link for user guide, feedback, and community tips.")
    print("https://docs.google.com/document/d/11YNoUBtit4rkWZQr_ZclzAOTE_HGMtgB3H_6cvq1Y24/edit?usp=sharing\n")
    
        
    
        
        
        
def write2gb(fragments):
    # This function takes the seqRecord fragments, which contains records for every fragment, and writes and annotates a genbank file.
    Nfrags=len(fragments)
    AnnotatedDonorSeq=Seq("", IUPAC.unambiguous_dna)      #donor is of seq class. 
    start_index=0
    AnnotatedDonorRecord=SeqRecord(AnnotatedDonorSeq)




    for i in range (0, Nfrags):
        
        AnnotatedDonorRecord.seq=AnnotatedDonorRecord.seq+Seq(str(fragments[i].seq), IUPAC.unambiguous_dna) #convert fragment to string then to unambiguous_dna alphabet
        end_index=start_index+len(fragments[i])
        
        #print("start and stop at "+str(start_index)+", "+str(end_index))
        
        
        if fragments[i].name[0:2] == "up":
            upstream_homology = SeqFeature(FeatureLocation(start_index, end_index), type="homology_region", strand=+1)
            upstream_homology.qualifiers["name"] = fragments[i].name
            upstream_homology.qualifiers["source"] = "BY4742 genomic DNA" 
            AnnotatedDonorRecord.features.append(upstream_homology)
            
        elif fragments[i].name[0:2] == "dn":
            downstream_homology = SeqFeature(FeatureLocation(start_index, end_index), type="homology_region", strand=+1)
            downstream_homology.qualifiers["name"] = fragments[i].name
            downstream_homology.qualifiers["source"] = "BY4742 genomic DNA" 
            AnnotatedDonorRecord.features.append(downstream_homology)
            
        elif fragments[i].name[-3:] == "tag":
            protein_tag = SeqFeature(FeatureLocation(start_index, end_index), type="protein_tag", strand=+1)
            protein_tag.qualifiers["name"] = fragments[i].name
            protein_tag.qualifiers["source"] = "BY4742 genomic DNA" 
            AnnotatedDonorRecord.features.append(protein_tag)
            
        elif fragments[i].name[-2:] == "ps":
            promoter = SeqFeature(FeatureLocation(start_index, end_index), type="promoter", strand=+1)
            promoter.qualifiers["name"] = fragments[i].name
            promoter.qualifiers["source"] = "BY4742 genomic DNA" 
            AnnotatedDonorRecord.features.append(promoter)
             
        elif fragments[i].name[-2:] == "ts":
            terminator = SeqFeature(FeatureLocation(start_index, end_index), type="terminator", strand=+1)
            terminator.qualifiers["name"] = fragments[i].name
            terminator.qualifiers["source"] = "BY4742 genomic DNA" 
            AnnotatedDonorRecord.features.append(terminator)
        
        else:
            CDS = SeqFeature(FeatureLocation(start_index, end_index), type="CDS", strand=+1)
            CDS.qualifiers["name"] = fragments[i].name
            CDS.qualifiers["source"] = "Custom template" 
            AnnotatedDonorRecord.features.append(CDS)
            
        start_index=end_index
        
    SeqIO.write(AnnotatedDonorRecord, "CASdesigner_Output.gb", "genbank")

    
    
    
    
    
    
def flipRecord(origRecord):
    origRecord.seq=origRecord.seq.reverse_complement()
    origRecord.name="r"+origRecord.name
    return origRecord
    
    
    
    
    
def cutFinder(GeneName):
    cutFrame = pd.read_excel("cutsTable.xlsx", index_col="cutName")
    
    # cutFrame has the 20nt sequence of the gRNA saved, which we load
    # It also has some more information we'll get to later
    
    cutSequence=cutFrame.loc[GeneName,'cutSequence']
    
    print("\nI picked the following cut site for you "+cutSequence)
    
    return cutSequence

def validTags():
    tagFrame = pd.read_excel("ProteinTags.xlsx")
    return tagFrame["tagName"].tolist()

def tagFinder(tagName):
    tagFrame = pd.read_excel("ProteinTags.xlsx", index_col="tagName")
    
    sequence = tagFrame.loc[tagName,'sequence']
    
    return sequence

askUser()






















'''
Hold on a moment, it's working... 
The interface should appear below momentarily.











'''

In [ ]: