# -*- coding: utf-8 -*-
"""
Created on Thu Aug 20 15:46:04 2015

@author: JBSUSER
"""

import subprocess,os,math,re,sys,zipfile,datetime,multiprocessing,webbrowser,threading,traceback,time,csv
from tkinter import *
from tkinter import filedialog,ttk
import tkinter as tki
from threading import Thread,Lock
from Bio.Seq import Seq
from bisect import bisect
from Bio import SeqIO

 
class Core:
    workingDirectory=os.getcwd()   #Base directory = D://ChimericSeq for example
    BUILDING=False
    doGTF=True
    addPathsBool=False
    outDir=os.getcwd()
    Bowtie2Folder=workingDirectory+'/bowtie2-2.2.9'
    ViralRefFolder=workingDirectory+'/Viral_Reference'
    HostRefFolder=workingDirectory+'/Host_Reference'
    ViralRefFa='None Selected'
    HostRefFa='None Selected'
    HostGTF='None Selected'
    readLocation=''
    readBaseName=''
    distanceThreshold=10000
    readDir=''
    useBasic=False
    GeneData=None
    FocusData=None
    ChromList=None
    folderMode=False
    Cores=[]
    coreOption=2
    logger=[]
    CSminLen=10
    STOP=False
    doReadClean=False
    YESNO=None
    paired=False
    loadAlignments=False #change to false in final code
    overlapRequested=True
    Na=115
    HostPrefix='humanRef'
    viralPrefix='viralRef'
    GO=False
    autoMode=False #change to false in final code
    Trim=0
    Trim2=0
    otempFilter=70
    olenFilter=24
    htempFilter=25
    hlenFilter=10
    vtempFilter=25
    vlenFilter=10
    runmode=0 #0=integration mode, 1=translocation mode
    preprocessReadLength=0
    preprocessUnknownPercent=100
   
    def __init__(self):
        os.chdir(self.workingDirectory)  #change dir to working directory (ChimericSeq Root folder)
        if self.addPathsBool:
            self.addPaths()
        for i in range (2,multiprocessing.cpu_count()+1,2):  #grab the number of CPUs and make list 2 through X
            self.Cores.append(i)
        self.lock=Lock()
        self.event=threading.Event()
        self.createInterface()
        
    def createInterface(self):
        self.topLevelTK=Tk()
        self.topLevelTK.withdraw()
        root=tki.Toplevel(self.topLevelTK)
        root.protocol('WM_DELETE_WINDOW',self.topLevelTK.destroy)
        self.interface=Interface(root,self)
        root.geometry("1200x555")
        self.app=self.interface
        self.app.printToLog('Logging Session')
        self.app.printToLog('Date Time: '+str(datetime.datetime.now()))
        self.app.printToLog('Number of CPU cores: '+str(multiprocessing.cpu_count()))
        self.printDefaults()
        root.mainloop()
    
    def hello(self):
        print('hello')
        self.printToLog('hola')
        #self.printToLog('hello')
    
    def loadGTF(self):
        if self.HostGTF!='None Selected':
            start=time.time()
            self.printToLog('Building Gene Database...')
            f=open(self.HostGTF,'r')
            focusData=[] #focusData
            chromList=[] #chromList
            genes=[]
            for line in f:
                test=line.split("\t")
                if test[0] not in chromList:
                    chromList.append(test[0])
                    focusData.append([])
                    genes.append([])
                    i=-1
                else:
                    i=chromList.index(test[0])
                try:
                    focusData[i].append(test)
                    if test[2]=='gene':
                        genes[i].append(test)
                except:
                    pass
            f.close()
            self.FocusData=focusData
            self.GeneData=genes
            self.ChromList=chromList
            stop=time.time()
            runtime=stop-start
            self.printToLog('Build complete at '+str(runtime)+ 'seconds')
            self.printToLog('======================================================================')
            self.GO=True
            self.event.set()
        else:
            self.printToLog("No selected Host GTF file to build on")
            self.printToLog('Gene info will not be available. Continue?')
            self.printToLog('======================================================================')
            self.app.yesbttn.configure(command=lambda: self.modGo(True,'set'))
            self.app.nobttn.configure(command=lambda: self.modGo(False,'set'))
            #ask user yes or no buttons
    
    def modGo(self,arg,command):
        self.GO=arg
        if self.GO==False:
            self.printToLog('Run Cancelled')
        if command=='set':
            self.event.set()
            
    def installer(self,install,OS):
        os.chdir(self.workingDirectory)
        if 'blast' in install:
            os.chdir(self.workingDirectory)
            subprocess.call(['ncbi-blast-2.2.31+-win64.exe'])
        if 'bowtie' in install:
            z=zipfile.ZipFile('bowtie2-2.2.5-mingw-win64.zip','r')
            z.extractall(self.Bowtie2Folder)

    def printToLog(self,message):
        self.app.printToLog(message)
        
    def printDefaults(self):
        self.printToLog('Working Directory Set To:\n'+self.workingDirectory)
        self.printToLog('Bowtie2 Folder is set to:\n'+self.Bowtie2Folder)
        self.printToLog('Viral Reference File is set to:\n'+self.ViralRefFa)
        self.printToLog('Bowtie2 viral index prefix: '+self.viralPrefix)
        self.printToLog('Host Reference File is set to:\n'+self.HostRefFa)
        self.printToLog('Bowtie2 host index prefix: '+self.HostPrefix)
        self.printToLog('CPU option: '+str(self.coreOption)+' CPUs engaged')
        self.printToLog('Load Prexisting Alignments: '+str(self.loadAlignments))
        self.printToLog('Clipped Sequence Min Length: '+str(self.CSminLen))
        self.printToLog('Salt concentration: '+str(self.Na)+'mM')
        self.printToLog('Prompting: '+str(not self.autoMode))
        
        
    def setWorkingDir(self):
        self.workingDirectory=filedialog.askdirectory(title='Select Working Directory')
        try:
            os.chdir(self.workingDirectory)
            self.printToLog('Working Directory changed to: '+self.workingDirectory)
        except OSError:
            self.printToLog('No New Working Directory Selected')
        

        
    def getReads(self):
        if self.folderMode==False:
            temp=filedialog.askopenfilenames(title='Select Reads',initialdir=self.workingDirectory)
            if temp:
                if len(temp)>2:
                    self.printToLog('Max selection of 2 reads permitted (forward/reverse)')
                    self.printToLog('If you would like to run more, please use directory mode')
                    return 'break'
                else:
                    self.readLocation=temp
                    if len(self.readLocation) ==2 :
                        if (self.readLocation[0].endswith('.fq') | self.readLocation[0].endswith('.fastq')):
                            if (self.readLocation[1].endswith('.fq') | self.readLocation[1].endswith('.fastq')):
                                self.paired=True
                            else:
                                self.printToLog('Cannot mix file types in mate pair (Fasta with FastQ)')
                                return 'break'
                        elif(self.readLocation[0].endswith('.fa') | self.readLocation[0].endswith('.fasta')):
                            self.printToLog('Cannot have mate pair of Fasta file type')
                            return 'break'
                    else:
                        self.paired=False
                    self.readBaseName=os.path.basename(self.readLocation[0])
                    self.readBaseName=os.path.splitext(self.readBaseName)[0]
                    self.readBaseName=self.readBaseName[0:len(self.readBaseName)-1]
                    self.readDir=os.path.dirname(self.readLocation[0])
                    self.printToLog('Reads Selected:')
                    for i in range (0,len(self.readLocation)):
                        self.printToLog(str(self.readLocation[i]))
                    return self.readLocation
            else:
                self.printToLog('No reads selected')
                return 'break'
        else:
            temp=filedialog.askdirectory(title='Select Reads Directory',initialdir=self.workingDirectory+'/Reads')
            if temp:
                self.readDir=temp
                self.printToLog('Directory Selected:\n'+self.readDir)
                return self.readDir
            else:
                self.printToLog('No directory selected')
                return 'break'
            

    def checkBowtie2FolderExists(self):
        self.printToLog('Verifying Bowtie2 Integrity...')
        GO=False
        if os.path.exists(self.Bowtie2Folder) and os.path.isfile(self.Bowtie2Folder+'/bowtie2'):
            GO=True
        if GO:
            self.printToLog('Bowtie2 Integrity Verified')
        else:
            self.printToLog('Please check Bowtie2 Folder is chosen correctly and is not corrupted')
        return GO
    
    def checkBowtieIndexs(self):
        self.printToLog('Checking Bowtie2 Indexes...')
        stopv=False
        stoph=False
        self.viralPrefix=str(self.app.vp.get(1.0,'end-1c'))
        self.HostPrefix=str(self.app.hp.get(1.0,'end-1c'))
        for i in range (1,7):
            if i<5:
                name=self.ViralRefFolder+'/'+self.viralPrefix+'.'+str(i)+'.bt2'
                name2=self.HostRefFolder+'/'+self.HostPrefix+'.'+str(i)+'.bt2'
            else:
                name=self.ViralRefFolder+'/'+self.viralPrefix+'.rev.'+str(i-4)+'.bt2'
                name2=self.HostRefFolder+'/'+self.HostPrefix+'.rev.'+str(i-4)+'.bt2'
            if not os.path.isfile(name):
                stopv=True
            if not os.path.isfile(name2):
                stoph=True
        if stopv:
            self.printToLog('Bowtie 2 index for viral not found, please create Bowtie2 index or specify correct path')
            self.printToLog('Checked in: '+self.ViralRefFolder+'\nFor: '+self.viralPrefix)
        if stoph:
            self.printToLog('Bowtie 2 index for host not found, please create Bowtie2 index or specify correct path')
            self.printToLog('Checked in: '+self.HostRefFolder+'\nFor: '+self.HostPrefix)
        if stoph==False and stopv==False:
            self.printToLog('Bowtie2 indexes existences verified')
            return True
        else:
            return False
                
    
 

                
    def askbuildBowtie2ViralIndex(self,prefix):
        if self.ViralRefFa!='None Selected':
            self.printToLog('Building Index for file:\n'+self.ViralRefFa)
            self.printToLog("In:\n"+self.ViralRefFolder)  
            self.printToLog('As:\n'+prefix)
            self.printToLog('Please confirm build...(Y/N) button')
            self.app.yesbttn.configure(command=lambda: self.buildBowtie2ViralIndex(prefix))
            self.app.nobttn.configure(command=self.cancel_buildBowtie2Index)
        else:
            self.printToLog('No selected viral reference fasta file to build on')

    def buildBowtie2ViralIndex(self,prefix):    
        def target():
            try:
                os.chdir(str(self.ViralRefFolder))
                temp=subprocess.Popen([self.Bowtie2Folder+'/bowtie2-build',self.ViralRefFa,prefix],stdout=subprocess.PIPE,bufsize=1)#,stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
                self.app.update()
                for line in iter(temp.stdout.readline,b''):
                    self.printToLog(line.decode('utf-8'))
                temp.stdout.close()
                self.printToLog('======================================================================\nBuild Complete')
            except:
                err=traceback.format_exc()
                status=-1
        thread=Thread(target=target)
        thread.start()
        os.chdir(self.workingDirectory)
        self.app.resetYesNoButtons()
        
    def cancel_buildBowtie2Index(self):
        self.printToLog('Bowtie2 Index build canceled!')
        self.app.resetYesNoButtons()
        
    def saveSettings(self):
        try: 
            out=open(self.workingDirectory+'/config.txt','w')
            go=True
        except:
            self.printToLog('Cannot save data, file currently in use')
            go=False
        if go:
            settings=[]
            settings.append('BT2D,'+self.Bowtie2Folder)
            settings.append('VRFa,'+self.ViralRefFa)
            settings.append('VID,'+self.ViralRefFolder)
            settings.append('VP,'+self.viralPrefix)
            settings.append('HRFa,'+self.HostRefFa)
            settings.append('HID,'+self.HostRefFolder)
            settings.append('HP,'+self.HostPrefix)
            settings.append('GTF,'+str(self.HostGTF))
            settings.append('OutDir,'+str(self.outDir))
            settings.append('TC,'+str(self.coreOption))
            settings.append('MinLen,'+str(self.CSminLen))
            settings.append('Na,'+str(self.Na))
            settings.append('Auto,'+str(self.autoMode))
            settings.append('Load,'+str(self.loadAlignments))
            settings.append('DoGene,'+str(self.doGTF))
            settings.append('Trim5,'+str(self.Trim))
            settings.append('Trim3,'+str(self.Trim2))
            settings.append('OverlapTmMax,'+str(self.otempFilter))
            settings.append('OverlapLenMax,'+str(self.olenFilter))
            settings.append('HostTmMin,'+str(self.htempFilter))
            settings.append('HostLenMin,'+str(self.hlenFilter))
            settings.append('ViralTmMin,'+str(self.vtempFilter))
            settings.append('ViralLenMin,'+str(self.vlenFilter))
            settings.append('FilterBasic,'+str(self.useBasic))
            settings.append('GeneThresh,'+str(self.distanceThreshold))
            for item in settings:
                out.write(item+'\n')
            out.close()
        self.printToLog('Settings saved successfully!')
    
    def loadSettings(self):
        temp=filedialog.askopenfilename(title='Select Config File',initialdir=self.workingDirectory)
        if temp:
            out=open(temp,mode='r')
            for line in out:
                a=line.split(',')
                if a[0]=='BT2D':
                    self.Bowtie2Folder=a[1]
                    self.app.changeLabel(self.app.bt2Text,a[1])
                elif a[0]=='VRFa':
                    self.ViralRefFa=a[1]
                    self.app.changeLabel(self.app.vrf,a[1])
                elif a[0]=='VID':
                    self.ViralRefFolder=a[1]
                    self.app.changeLabel(self.app.vdd,a[1])
                elif a[0]=='VP':
                    self.viralPrefix=a[1]
                    self.app.changeLabelFree(self.app.vp,a[1])
                elif a[0]=='HRFa':
                    self.HostRefFa=a[1]
                    self.app.changeLabel(self.app.hrf,a[1])
                elif a[0]=='HID':
                    self.HostRefFolder=a[1]
                    self.app.changeLabel(self.app.hdd,a[1])
                elif a[0]=='HP':
                    self.HostPrefix=a[1]
                    self.app.changeLabelFree(self.app.hp,a[1])
                elif a[0]=='OD':
                    self.workingDirectory=a[1]
                    self.app.changeLabel(self.app.out,a[1])
                elif a[0]=='TC':
                    self.coreOption=int(a[1])
                    self.app.cpuIntVar.set(int(a[1]))
                elif a[0]=='MinLen':
                    self.CSminLen=int(a[1])
                    self.app.changeLabelFree(self.app.clipText,a[1])
                elif a[0]=='Na':
                    self.Na=int(a[1])
                    self.app.changeLabelFree(self.app.saltText,a[1])
                elif a[0]=='Auto':
                    self.autoMode=bool(a[1])
                    if bool(a[1]):
                        self.app.autoModeVar.set(1)
                elif a[0]=='Load':
                    self.loadAlignments=bool(a[1])
                    if bool(a[1]):
                        self.app.loadAlignmentBoolVar.set(1)
            out.close()
        self.printToLog('Config file loaded')
        self.printDefaults()
        
        
        
    def askbuildBowtie2HostIndex(self,prefix): 
        if self.HostRefFa!='None Selected':
            self.printToLog('Building Index for file:\n'+self.HostRefFa)
            self.printToLog("In:\n"+self.HostRefFolder)  
            self.printToLog('As:\n'+prefix)
            self.printToLog('Please confirm build...(Y/N) button')
            self.app.yesbttn.configure(command=lambda: self.buildBowtie2HostIndex(prefix))
            self.app.nobttn.configure(command=self.cancel_buildBowtie2Index)
        else:
            self.printToLog('No selected host reference fasta file to build on')
            
    def buildBowtie2HostIndex(self,prefix): 
        def target():
            try:
                self.app.update()
                os.chdir(str(self.HostRefFolder))
                temp=subprocess.Popen([self.Bowtie2Folder+'/bowtie2-build',self.HostRefFa,prefix],stdout=subprocess.PIPE,bufsize=1)#,stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
                self.app.update()
                for line in iter(temp.stdout.readline,b''):
                    self.printToLog(line.decode('utf-8'))
                temp.stdout.close()
                self.printToLog('======================================================================\nBuild Complete')
            except:
                err=traceback.format_exc()
                status=-1     
                self.printToLog('Error Occured\n'+err)
        thread=Thread(target=target)
        thread.start()
        os.chdir(self.workingDirectory)
        self.app.resetYesNoButtons()

    
    def run(self):
        def target():
            start=time.time()
            if self.doReadClean:
                self.printToLog('Starting read preprocessing')
                try:
                    self.preprocessReadLength=int(self.app.readminlength.get(1.0,'end-1c'))
                    self.preprocessUnknownPercent=int(self.app.maxunknown.get(1.0,'end-1c'))
                except:
                    pass
                for read in self.readLocation:
                    self.sequence_cleaner(read,self.preprocessReadLength,self.preprocessUnknownPercent)
                self.event.wait()
                self.event.clear()
            else:
                self.printToLog('Skipping read preprocessing')
            if self.doGTF:
                self.loadGTF()
                self.event.wait()
                self.event.clear()
            else:
                self.GO=True
            if self.GO:
                self.askviralAlignment()
                self.event.wait()
                self.event.clear()
                if self.GO:
                    self.getCS()
                    if self.GO:
                        self.askHostAlignment()
                        self.event.wait()
                        self.event.clear()
                        if self.GO:
                            self.printToLog('Building Internal Tables...')
                            self.mapper()
                            self.printToLog('Tables Filled!')
                            stop=time.time()
                            runtime=stop-start
                            self.countUnique()
                            self.printToLog('======================================================================\nRun Completed in '+str(runtime)+' seconds')
                            self.GO=False
        try:
            self.distanceThreshold=int(self.app.DistanceText.get(1.0,'end-1c'))
        except:
            self.distanceThreshold=10000               
        temp=self.checkReads()
        stop=False
        if temp==0:
            stop=True
            self.printToLog('Aborting: No Read(s) Selected')
        if stop==False:
            temp=self.checkBowtie2FolderExists()
            if temp:
                temp=self.checkBowtieIndexs()
                if temp:
                    self.printToLog('Initiating Run\n======================================================================')
                    self.event.clear()
                    thread=Thread(target=target)
                    thread.start()

        
    def checkReads(self):
        if not self.folderMode:
            return len(self.readLocation)
    
    def addPaths(self):
        try: 
            os.environ['PATH']+=os.pathsep+self.workingDirectory+'/tcl/tk8.5.2/Python'
        except KeyError:
            os.environ['PATH']=os.pathsep+self.workingDirectory+'/tcl/tk8.5.2/Python'
    
    def askviralAlignment(self):
        stop=False
        forward=-1
        reverse=-1
        mode=None
        count=0
        if not self.folderMode:      #if in single alignment mode (using only one read or one read pair, not batch to folder)
            if len(self.readLocation) ==2 :  #if you have exactly two reads selected
                mode='paired'
                mode2='fq'
                for i in range (0,2):
                    if (self.readLocation[i].endswith('.fq') | self.readLocation[i].endswith('.fastq')):  #check if each read ends with .fq or .fastq
                        if self.readLocation[i].endswith('1.fq')|self.readLocation[i].endswith('1.fastq'):
                            forward=i
                            count+=1
                    else:
                        stop=True
                        self.printToLog("Read "+self.readLocation[i]+' does not have correct file extenstion (expecting .fq or .fastq)') #print error if not ending in .fq or .fastq
                if count!=1:  #makes sure a forward read is identified 
                    stop=True
                    self.printToLog('Could not designate forward read, naming convention set to\nForward=name1.fq/.fastq Reverse=name2.fq/.fastq') 
                else:
                    if forward==1:
                        reverse=0
                    else:
                        reverse=1
                    if self.doReadClean: #change for final code (delete)
                        temp=self.readLocation[forward].split('/')
                        temp[-1]='cleaned_'+temp[-1]
                        s='/'
                        temp2=s.join(temp)
                        self.printToLog('Forward read: '+temp2)
                        temp=self.readLocation[reverse].split('/')
                        temp[-1]='cleaned_'+temp[-1]
                        s='/'
                        temp2=s.join(temp)
                        self.printToLog('Reverse read: '+temp2)
                    else:
                        self.printToLog('Forward read: '+self.readLocation[forward])
                        self.printToLog('Reverse read: '+self.readLocation[reverse])
            elif len(self.readLocation)==1:  #if exactly 1 read is selected
                if (self.readLocation[0].endswith('.fq') | self.readLocation[0].endswith('.fastq')):  #check if read ends with .fq or .fastq
                    mode='single'
                    mode2='fq'
                elif (self.readLocation[0].endswith('.fasta')| self.readLocation[0].endswith('.fa')):
                    mode='single'
                    mode2='fa'
                else:
                    stop=True
                    self.printToLog("Read "+self.readLocation+' does not have correct file extenstion (expecting .fq or .fastq)') #print error if not ending in .fq or .fastq
            else:
                stop=True
                self.printToLog('No Read(s) Selected')
            if not stop:
                changeForFinal=False # change for final code (delete)
                if self.doReadClean and mode=='single' and changeForFinal :
                    test=[]
                    for i in range (0,len(self.readLocation)):
                        temp=self.readLocation[i].split('/')
                        temp[-1]='cleaned_'+temp[-1]
                        s='/'
                        temp2=s.join(temp)
                        test.append(temp2)
                    self.readLocation=test
                self.printToLog('Alignment check complete!')
                self.printToLog('Beginning Alignment of Reads to Viral Reference: '+os.path.basename(self.ViralRefFa))
                if self.autoMode:
                    self.viralAlignment(mode,mode2,forward,reverse)
                else:
                    self.printToLog('Please confirm alignment...(Y/N) button')
                    self.app.yesbttn.configure(command=lambda: self.viralAlignment(mode,mode2,forward,reverse))
                    self.app.nobttn.configure(command=self.cancel_Alignment)
                
                
    def cancel_Alignment(self):
        self.printToLog('Alignment canceled!')
        self.app.resetYesNoButtons()
        self.GO=False
        self.event.set()
        
    def updateRunDirectory(self):
        if self.outDir=='None Selected':
            self.runDirectory=self.readDir+'/'+self.readBaseName
        else:
            self.runDirectory=self.outDir+'/'+self.readBaseName
    
    def viralAlignment(self,mode,mode2,forward,reverse):
        stop=False
        if mode=='single' or mode=='paired':
            self.mode=mode
        try:
            self.Trim=(self.app.TrimmingText.get(1.0,'end-1c'))
            self.Trim2=(self.app.TrimmingText2.get(1.0,'end-1c'))
            self.printToLog('Trimming '+self.Trim+' bases off 5\' end')
            self.printToLog('Trimming '+self.Trim2+' bases off 3\' end')
        except:
            self.printToLog('Trimming not entered correctly in config')
            err=traceback.format_exc()
            self.printToLog(err)
            stop=True
        if not stop:
            self.printToLog('Starting Viral Alignment...')
            os.chdir(self.ViralRefFolder)
            try:
                self.app.update()
                self.updateRunDirectory()
                if not os.path.exists(self.runDirectory):
                    os.makedirs(self.runDirectory)
                self.printToLog('Aligning...')
                os.chdir(self.ViralRefFolder)
                outfile=self.runDirectory+'/'+self.readBaseName+'_viralAlign.sam'
                if os.path.isfile(outfile) and self.loadAlignments:
                    self.printToLog('Loaded Prexisting Alignment:\n'+outfile)
                else:
                    if mode=='paired':   
                        temp=subprocess.Popen([self.Bowtie2Folder+'/bowtie2','--trim5',str(self.Trim),'--trim3',str(self.Trim2),'--very-sensitive-local','--threads',str(self.coreOption),'-x',str(self.viralPrefix),'-1',self.readLocation[forward],'-2',self.readLocation[reverse],'-S',outfile],stderr=subprocess.PIPE)
                        #temp=subprocess.Popen([self.Bowtie2Folder+'/bowtie2.bat','--trim5',str(self.Trim),'--trim3',str(self.Trim2),'-D 20 -R 3 -N 0 -L 10 -i S,1,0.30','--threads',str(self.coreOption),'-x',str(self.viralPrefix),'-1',self.readLocation[forward],'-2',self.readLocation[reverse],'-S',outfile],stderr=subprocess.PIPE)
                    elif mode=='single':
                        #temp=subprocess.Popen([self.Bowtie2Folder+'/bowtie2.bat','--local','-D','20','-R','3','-N','1','-L','12','-i','S,1,0','--trim5',str(self.Trim),'--trim3',str(self.Trim2),'--threads',str(self.coreOption),'-x',str(self.viralPrefix),'-U',self.readLocation[0],'-S',outfile],stderr=subprocess.PIPE)
                        temp=subprocess.Popen([self.Bowtie2Folder+'/bowtie2','--trim5',str(self.Trim),'--trim3',str(self.Trim2),'--very-sensitive-local','--threads',str(self.coreOption),'-x',str(self.viralPrefix),'-U',self.readLocation[0],'-S',outfile],stderr=subprocess.PIPE)
                    for line in iter(temp.stderr.readline,b''):
                        self.printToLog(line.decode('utf-8'))
                    temp.stderr.close()
                self.printToLog('======================================================================\nAlignment Complete')
                self.GO=True
                self.event.set()
            except:
                err=traceback.format_exc()
                self.printToLog('Error Occured\n'+err)  
                self.GO=False
                self.event.set()
            os.chdir(self.workingDirectory)
            self.app.resetYesNoButtons()           

    def askHostAlignment(self):
        self.updateRunDirectory()
        self.CSLocation=self.runDirectory+'/'+self.readBaseName+'_CSList.txt'
        self.CSLocationFull=self.runDirectory+'/'+self.readBaseName+'_CSListFull.txt'
        if os.path.isfile(self.CSLocation) and os.path.isfile(self.CSLocationFull):
            self.printToLog('Alignment check complete!')
            self.printToLog('Beginning Alignment of Reads to Host Reference: '+os.path.basename(self.HostRefFa))
            if self.autoMode:
                self.HostAlignment()
            else:
                self.printToLog('Please confirm alignment...(Y/N) button')
                self.app.yesbttn.configure(command=self.HostAlignment)
                self.app.nobttn.configure(command=self.cancel_Alignment)
        else:
            self.printToLog('No Clipped Sequences Found to Align')
            self.GO=False
                     
        
    def HostAlignment(self):
        self.printToLog('Starting Host Alignment...')
        os.chdir(self.HostRefFolder)
        try:
            self.app.update()
            if not os.path.exists(self.runDirectory):
                os.makedirs(self.runDirectory)
            self.printToLog('Aligning...')
            os.chdir(self.HostRefFolder)
            outfile=self.runDirectory+'/'+self.readBaseName+'_hostAlign.sam'
            if os.path.isfile(outfile) and self.loadAlignments:
                self.printToLog('Loaded Prexisting Alignment:\n'+outfile)
            else:
                if self.overlapRequested:
                    temp=subprocess.Popen([self.Bowtie2Folder+'/bowtie2','--very-sensitive-local','--threads',str(self.coreOption),'-x',str(self.HostPrefix),'-f','-U',self.CSLocationFull,'-S',outfile],stderr=subprocess.PIPE)
                else:
                    temp=subprocess.Popen([self.Bowtie2Folder+'/bowtie2','--very-sensitive-local','--threads',str(self.coreOption),'-x',str(self.HostPrefix),'-f','-U',self.CSLocation,'-S',outfile],stderr=subprocess.PIPE)
                for line in iter(temp.stderr.readline,b''):
                    self.printToLog(line.decode('utf-8'))
                temp.stderr.close()
            self.printToLog('======================================================================\nAlignment Complete')
            self.GO=True
            self.event.set()
        except:
            err=traceback.format_exc()
            self.printToLog('Error Occured\n'+err)  
            self.GO=False
            self.event.set()
        os.chdir(self.workingDirectory)
        self.app.resetYesNoButtons()                


        
    
    def setSingleMode(self):
        if self.folderMode==True:
            self.printToLog('Changed Mode: Single Run')
            self.folderMode=False
    def setDirMode(self):
        if self.folderMode==False:
            self.printToLog('Changed Mode: Directory Run')
            self.folderMode=True
          
        
    def getCS(self):
        self.printToLog('Retrieving Clipped Sequences...')
        try:
            self.app.update()
            self.vSam=self.createSam('v')
            if self.vSam is not None:
                outfile=self.runDirectory+'/'+self.readBaseName+'_CSListFull.txt'
                if os.path.isfile(outfile) and self.loadAlignments:
                    self.printToLog('Loaded Prexisting Clipped Sequences:\n'+outfile)
                else:
                    self.extractClippedSequences()
                self.printToLog('======================================================================\nClipped Sequence Files Generated') 
                self.GO=True
            else:
                self.GO=False
        except:
            err=traceback.format_exc()
            self.printToLog('Error Occured\n'+err)
            self.GO=False
        
           


    def createSam(self,mode):
        switch=True
        if len(self.readLocation)==0:
            switch=False
        if switch:
            self.updateRunDirectory()
            if mode=='v':
                filename=self.runDirectory+'/'+self.readBaseName+'_viralAlign.sam'
                if os.path.isfile(filename):
                    vSam=Sam(filename,False,self.readBaseName)
                    if vSam.Quit==False:
                        return vSam
                    else:
                        self.printToLog('Zero Alignment for the Virus:\n')
                        return None
                else:
                    self.printToLog('No Viral Alignment File exists under name:\n'+filename)
                    return None
                
            elif mode=='h':
                filename=self.runDirectory+'/'+self.readBaseName+'_hostAlign.sam'
                if os.path.isfile(filename):
                    hSam=Sam(filename,False,self.readBaseName)
                    return hSam
                else:
                    self.printToLog('No Host Alignment File exists under name:\n'+filename)
                    return None
            else:
                self.printToLog('Error in reading sam file: no type switch given (virus/host)')
                return None
        else:
            self.printToLog('No Reads Selected')
            return None

    def sequence_cleaner(self,fastq_file, min_length=0, per_n=100):
        self.printToLog('Cleaning: '+fastq_file)
        sequences=[]
        test=[]
        for seq_record in SeqIO.parse(fastq_file, "fastq"):
            sequence = str(seq_record.seq).upper()
            if (len(sequence) >= min_length and (float(sequence.count("N"))/float(len(sequence)))*100 <= per_n):
                if sequence not in sequences:
                    sequences.append(sequence)
                    test.append(seq_record)
        if fastq_file.endswith('1.fq') or fastq_file.endswith('1.fastq'):
            temp='1.fastq'
        elif fastq_file.endswith('2.fq') or fastq_file.endswith('2.fastq'):
            temp='2.fastq'
        else:
            temp='unknown.fastq'
            self.printToLog('Error in fastQ cleanup.  One or more of the file names did not end with 1.fastq/1.fq or 2.fastq/2.fq')
        SeqIO.write(test,self.readDir+'/cleaned_'+self.readBaseName+temp,'fastq')
        temp=fastq_file.split('/')
        temp[-1]='cleaned_'+temp[-1]
        s='/'
        temp2=s.join(temp)
        self.printToLog('Wrote cleaned fastq to: '+temp2)
        self.event.set()


    def extractClippedSequences(self):
        stop=False
        try:
            self.vSam
        except NameError:
            self.printToLog('No alignment file to virus was found')
            stop=True
        try:
            self.CSminLen=int(self.app.clipText.get(1.0,'end-1c'))
        except:
            self.printToLog('Clipped Sequence Min Length not entered correctly in config')
            err=traceback.format_exc()
            self.printToLog(err)
            stop=True
        if not stop:
            self.vSam.extractClippedSeq(self.CSminLen,self.paired)
            
    
    def mapper(self):
        vSam=self.createSam('v')
        hSam=self.createSam('h')
        try:
            if vSam is not None and hSam is not None:
                carryOn=True
            else:
                carryOn=False
        except:
            self.printToLog('One or more .sam files are not loaded')
            carryOn=False
        if carryOn:
            self.Map=Mapper(vSam,hSam,self)
        self.event.set()
    
    def countUnique(self):
        list1=[]
        count=0
        try:
            for i in range(0,len(self.Map.data)):
                seq=Seq(self.Map.data[i]['Sequence'])
                temp=str(seq)
                temp2=str(seq.reverse_complement())
                if list1.count(temp)==0:
                    if list1.count(temp2)==0:
                        count+=1
                    list1.append(temp)
            if self.mode=='paired':
                self.printToLog(str(len(list1))+' reads are unique (counting complements)')
            self.printToLog(str(count)+' reads are unique')
                
        except:
            self.printToLog('Something went wrong')
            err=traceback.format_exc()
            self.printToLog(err)
    
    def saveData(self):
        
        def target():
            try:
                print(self.Map)
            except AttributeError:
                self.printToLog('Data has not been generated for saving')
                return
            self.printToLog('Saving data...')
            ts=time.time()
            st=datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d_%Hh%Mm%Ss')
            try:
                out=open(self.runDirectory+'/'+self.readBaseName+'_OUTPUT_'+st+'.csv','w')
                go=True
            except PermissionError:
                self.printToLog('Cannot save data, file currently in use')
                go=False
            if go:
                sequences=[]
                dataNoC=[]
                data=[]
                attributeList= ['ReadName','ReadLength','Sequence','Chromosome','Gene','InsideGene','DistanceToGene','GeneDirection','Focus','GeneObj','FocusObj','HostLocalCords','Hlength','HostRefCords','HostOrientation','ViralAccession','ViralLocalCords','Vlength','ViralRefCords','ViralOrientation','HTM','HTMAdjusted','VTM','VTMAdjusted','Overlap','OverlapTM','OverlapTMAdjusted','Inserted','Microhomology','HostMapFlag','ViralMapFlag','HMapQ','VMapQ','FastqSource','Index']
                for a in attributeList:
                    out.write(a+',')
                out.write('\n')
                #tempList=[]
                for i in range (0,len(self.Map.data)):
                    for item in attributeList:
                        out.write('"'+str(self.Map.data[i][item])+'"'+',')
                    out.write('\n')
                out.close()
                
                with open (self.runDirectory+'/'+self.readBaseName+'_OUTPUT_'+st+'.csv','r') as csvfile:
                    reader = csv.reader(csvfile, delimiter=',')
                    for row in reader:
                        seq=Seq(row[2])
                        if seq not in sequences:
                            data.append(row)
                            if seq.reverse_complement() not in sequences:
                                dataNoC.append(row)
                            sequences.append(seq)
                with open (self.runDirectory+'/'+self.readBaseName+'_OUTPUT_'+st+'_no_duplicates.csv', 'w') as csvfile1:
                    writer=csv.writer(csvfile1,delimiter=',',lineterminator = '\n')
                    for row in data:
                        writer.writerow(row)
                        
                with open (self.runDirectory+'/'+self.readBaseName+'_OUTPUT_'+st+'_no_complements.csv', 'w') as csvfile2:
                    writer=csv.writer(csvfile2,delimiter=',',lineterminator = '\n')
                    for row in dataNoC:
                        writer.writerow(row)
                        
                self.printToLog('Data saved successfully!')
            try: 
                out2=open(self.runDirectory+'/'+self.readBaseName+'_log.txt','w')
                go=True
            except:
                self.printToLog('Cannot save log, file currently in use')
                go=False
            if go:
                for line in self.logger:
                    out2.write(line+'\n')
                out2.close()
                self.printToLog('Log saved successfully!')
            self.event.set()
                
        thread=Thread(target=target)
        thread.start()
        self.event.wait()
        self.event.clear()
        self.printToLog('======================================================================\n')
        

    

class Mapper:
    def __init__(self,vSam,hSam,core):
        self.readCount=0
        self.data=[]
        self.vSam=vSam
        self.hSam=hSam
        self.core=core
        self.gatherAligned()
        
    
    def calculateTM(self,seq):
        try:
            self.core.Na=int(self.core.app.saltText.get(1.0,'end-1c'))           
        except:
            return 'Err','Err'
        Na=self.core.Na
        a=seq.count('A')
        c=seq.count('C')
        t=seq.count('T')
        g=seq.count('G')
        if len(seq)<14:
            TMb=(a+t)*2+(g+c)*4
            TMa=(a+t)*2+(g+c)*4-16.6*math.log(0.05,10)+16.6*math.log((Na*10**-3),10)
        else:
            TMb=64.9+41*(g+c-16.4)/(a+t+g+c)
            TMa=100.5+(41*(g+c)/(a+t+g+c))-(820/(a+t+g+c))+16.6*math.log((Na*10**-3),10)
        return TMb,TMa

            
    
    def gatherAligned(self):
        code=1
        stop=False
        self.core.app.listBox1.delete(0,END)
        increment=len(self.hSam.sam)/20.0
        progress=0
        for i in range (0,len(self.hSam.sam)):
            tempProgress=int(i/increment)
            if tempProgress>progress:
                self.printToLog('Progress: '+str(tempProgress*5)+'%')
                progress=tempProgress
            stop=False
            if self.hSam.sam[i][5]=='*':
                stop=True
            if not stop:
                if code==0:
                    name=self.hSam.sam[i][0].split('.')
                    if self.core.paired:
                        name=(name[1]+'.'+name[2]).split('-')
                    else:
                        name=name[1].split('-')
                    name=name[1].split(':')
                    name=':'.join(name[2:len(name)])
                if code==1:
                    name=self.hSam.sam[i][0]
                self.core.app.listBox1.insert(END,name)
                self.readCount+=1  
                self.loadData(i)    
        self.printToLog('Progress: 100%')                          
        self.printToLog(str(self.readCount)+' reads contain host and viral sequences')
    
    
    def loadData(self,number):
        def getOverlap(hstart,hstop,vstart,vstop):
            HostFirst=False
            if vstart<=hstart:
                if vstop>=hstart and hstop>=vstop:
                    overlap=vstop-hstart+1
                elif vstop>=hstart and hstop<vstop:
                    overlap=hstop-hstart+1
                else:
                    overlap=0
            elif hstart<vstart:
                HostFirst=True
                if hstop>=vstart and vstop>=hstop:
                    overlap=hstop-vstart+1
                elif hstop>=vstart and vstop<hstop:
                    overlap=vstop-vstart+1
                else:
                    overlap=0
            return [overlap,HostFirst]
        def getAlignmentLocal(cigar):
            if cigar!="*":
                pairs=re.findall('\d+[A-Z]+',cigar)
                index=0
                inserted=[]
                count=0
                deleted=0
                stop=None
                start=None
                stopSignal=True
                for j in range (0,len(pairs)):
                    length=int(pairs[j][0:len(pairs[j])-1])
                    if pairs[j].endswith('S'):
                        index+=length
                    elif pairs[j].endswith('M'):
                        stopSignal=True
                        if j<len(pairs):
                            for k in range(j+1,len(pairs)):
                                if pairs[k].endswith('M'):
                                    stopSignal=False
                        if count==0:
                            start=index+1
                        index+=length
                        if stopSignal:
                            stop=index
                        count+=1
                    elif pairs[j].endswith('D'):
                        deleted+=length
                    elif pairs[j].endswith('I'):
                        insertedStart=index
                        index+=length
                        insertedStop=index
                        inserted.append([insertedStart,insertedStop])
                        
                return [start,stop,inserted]
            else:
                print('!!! Error Detected - Cigar String Should be not empty (not *)')
                return [None,None]
        data={}
        code=1#for final code - can change depending on what naming specification is.  default =1
        if code==0:
            name=self.hSam.sam[number][0].split('.')
            if self.core.paired:
                name=(name[1]+'.'+name[2]).split('-')
            else:
                name=name[1].split('-')
            name=name[1].split(':')
            name=':'.join(name[2:len(name)])
        else:
            name=self.hSam.sam[number][0]
        data['ReadName']=name
        data['Index']=len(self.data)
        data['Chromosome']=self.hSam.sam[number][2][3:]
        data['HMapQ']=self.hSam.sam[number][4]
        n2=self.hSam.sam[number][0].split('.')
        if len(n2)>2:
            n=int(n2[-1])
            data['FastqSource']=self.core.readLocation[n-1]
        else:
            data['FastqSource']=self.core.readLocation[0]
        n=int(n2[0])
        data['ReadLength']=len(self.vSam.sam[n][9])
        data['VMapQ']=self.vSam.sam[n][4]
        data['HostMapFlag']=self.hSam.sam[number][1]
        data['ViralMapFlag']=self.vSam.sam[n][1]
        
        vswitch=False
        hswitch=False
        if len(self.vSam.flags[n])>=4:
            if self.vSam.flags[n][4]=='1':
                vswitch=True
        if len(self.hSam.flags[number])>=4:
            if self.hSam.flags[number][4]=='1':
                hswitch=True
                
        data['Vswitch']=vswitch
        data['Hswitch']=hswitch
        if not (vswitch):
            data['Sequence']=self.vSam.sam[n][9]
        else:
            fullSeq=Seq(self.vSam.sam[n][9])
            data['Sequence']=str(fullSeq.reverse_complement())
    
        if data['Vswitch']:
            data['ViralOrientation']='Plus/Minus'
        else:
            data['ViralOrientation']='Plus/Plus'
        if data['Hswitch']:
            data['HostOrientation']='Plus/Minus'
        else:
            data['HostOrientation']='Plus/Plus'
            
        cigar=self.vSam.sam[n][5]
        [vstart,vstop,inserted]=getAlignmentLocal(cigar)
        vlen=abs(vstop-vstart)+1
        cigar=self.hSam.sam[number][5]
        [hstart,hstop,inserted]=getAlignmentLocal(cigar)
        hlen=abs(hstop-hstart)+1
        
        data['ViralLocalCords']=[vstart,vstop]
        data['HostLocalCords']=[hstart,hstop]     
        data['Hlength']=hlen
        data['Vlength']=vlen
        
        
        
        if vswitch:
            temp=len(self.hSam.sam[number][9])+1-vstop
            vstop=len(self.hSam.sam[number][9])+1-vstart
            vstart=temp
            data['ViralLocalCords']=[vstart,vstop]
            if hswitch:
                data['HostLocalCords']=[hstart,hstop]
            else:
                temp=len(self.hSam.sam[number][9])+1-hstop
                hstop=len(self.hSam.sam[number][9])+1-hstart
                hstart=temp
                data['HostLocalCords']=[hstart,hstop]
        else:
            data['ViralLocalCords']=[vstart,vstop]
            if hswitch:
                temp=len(self.hSam.sam[number][9])+1-hstop
                hstop=len(self.hSam.sam[number][9])+1-hstart
                hstart=temp
                data['HostLocalCords']=[hstart,hstop]
            else:
                data['HostLocalCords']=[hstart,hstop]
        
        
        if hstart>=vstart and hstop<=vstop:
            data['Microhomology']=True
        elif vstart>=hstart and vstop<=hstop:
            data['Microhomology']=True
        else:
            data['Microhomology']=False
        
        
        
        seq=data['Sequence'][int(hstart)-1:int(hstop)]
        data['HostSeq']=seq
        basicTM,adjustedTM=self.calculateTM(seq)
        data['HTM']=basicTM
        data['HTMAdjusted']=adjustedTM
        data['Inserted']=inserted
        data['ViralAccession']=self.vSam.sam[n][2]
        seq=data['Sequence'][int(vstart)-1:int(vstop)]
        data['ViralSeq']=seq
        basicTM,adjustedTM=self.calculateTM(seq)
        data['VTM']=basicTM
        data['VTMAdjusted']=adjustedTM
        [overlap,HostFirst]=getOverlap(hstart,hstop,vstart,vstop)
        data['Overlap']=overlap
        data['HostFirst']=HostFirst
        if overlap>0: 
            if HostFirst:
                overlapSeq=data['Sequence'][int(hstop)-int(overlap):int(hstop)]
            else:
                overlapSeq=data['Sequence'][int(vstop)-int(overlap):int(vstop)]
            [basicTm,saltadjustedTm]=self.calculateTM(overlapSeq)
            data['OverlapTM']=basicTm
            data['OverlapTMAdjusted']=saltadjustedTm
        else:
            data['OverlapTM']=''
            data['OverlapTMAdjusted']=''
        data['HostRefCords']=[int(self.hSam.sam[number][3]),int(self.hSam.sam[number][3])+hlen]
        data['ViralRefCords']=[int(self.vSam.sam[n][3]),int(self.vSam.sam[n][3])+vlen]
        
        if self.core.doGTF:
            hostStart=data['HostRefCords'][0]
            hostStop=data['HostRefCords'][1]
            hostChrom=data['Chromosome']
            #print (hostStart,hostStop,hostChrom)
            [information,geneObj,focusObj]=self.searchGenes(hostChrom,hostStart,hostStop)
            data['Gene']=information['Gene']
            data['InsideGene']=information['Inside']
            data['GeneDirection']=information['Direction']
            data['DistanceToGene']=information['DistanceToGene']
            data['Focus']=information['Focus']
            data['GeneObj']=geneObj
            data['FocusObj']=focusObj
        else:
            data['Gene']='N/A'
            data['InsideGene']='N/A'
            data['GeneDirection']='N/A'
            data['DistanceToGene']='N/A'
            data['Focus']='N/A'
            data['GeneObj']='N/A'
            data['FocusObj']='N/A'
        self.data.append(data)
        
        
        
    def searchGenes(self,chrom,start,stop):
        distanceThreshold=self.core.distanceThreshold
        information={}
        information['Inside']='N/A'
        information['DistanceToGene']='N/A'
        information['Direction']='N/A'
        information['Gene']='N/A'
        information['Focus']='N/A'
        final=None
        finalData=None
        chrom=str(chrom)
        go=True
        focusGene=None
        focus=None
        try:
            index=self.core.ChromList.index(chrom)
        except:
            go=False
        if go:
            temp=[float(x[3]) for x in self.core.FocusData[index]]
            index2=bisect(temp,start)
            temp2=[float(x[3]) for x in self.core.GeneData[index]]
            index_gene=bisect(temp2,start)
            try:
                preData=self.core.FocusData[index][index2-1]
                pre=self.core.GeneData[index][index_gene-1]
            except:
                pre=None
                preData=None
            try:
                postData=self.core.FocusData[index][index2]
                post=self.core.GeneData[index][index_gene]
            except:
                post=None
                postData=None
            if not pre:
                final='post'
            elif not post:
                final='pre'
            if not preData:
                finalData='post'
            elif not postData:
                finalData='pre'
            if final is None:
                if start<=float(pre[4]):
                    gene=pre[-1].split(';')[2].split(' ')[-1].replace("\"","")
                    information['Inside']='True'
                    information['DistanceToGene']=0
                    information['Direction']='N/A'
                    focusGene=pre
                elif stop>=float(post[3]):
                    gene=post[-1].split(';')[2].split(' ')[-1].replace("\"","")
                    information['Inside']='True'
                    information['DistanceToGene']=0
                    information['Direction']='N/A'
                    focusGene=post
                else:
                    distance1=start-float(pre[4])
                    distance2=float(post[3])-stop
                    if distance1<distanceThreshold and distance1<distance2:
                        gene=pre[-1].split(';')[2].split(' ')[-1].replace("\"","")
                        information['DistanceToGene']=distance1
                        information['Direction']='Down stream'
                        information['Inside']='False'
                        focusGene=pre
                        
                    elif  distance2<distanceThreshold and distance2<distance1:
                        gene=post[-1].split(';')[2].split(' ')[-1].replace("\"","")
                        information['DistanceToGene']=distance2
                        information['Direction']='Up stream'
                        information['Inside']='False'
                        focusGene=post
                    else:
                        gene='N/A'
                        focusGene=None
                        information['DistanceToGene']='N/A'
                        information['Direction']='N/A'
                        information['Inside']='N/A'    
                information['Gene']=gene
            else:
                if final=='pre':
                    gene=pre[-1].split(';')[2].split(' ')[-1].replace("\"","")
                    if start<=float(pre[4]):
                        information['Inside']='True'
                        information['DistanceToGene']=0
                        information['Direction']='N/A'
                        distance1=0
                    else:
                        distance1=start-float(pre[4])
                        information['DistanceToGene']=distance1
                        information['Direction']='Down stream'
                        information['Inside']='False'
                    focusGene=pre     
                else:
                    gene=post[-1].split(';')[2].split(' ')[-1].replace("\"","")
                    if stop>=float(post[3]):
                        information['Inside']='True'
                        information['DistanceToGene']=0
                        information['Direction']='N/A'
                        distance1=0
                    else:
                        distance1=float(post[3])-stop
                        information['DistanceToGene']=distance1
                        information['Direction']='Up stream'
                        information['Inside']='False'
                    focusGene=post
                if distance1<distanceThreshold:
                    information['Gene']=gene
                else:
                    information['Gene']='N/A'
            if finalData is None:
                if start<=float(preData[4]):
                    focus=preData
                elif stop>=float(postData[3]):
                    focus=postData
                else:
                    focus=None
            else:
                if finalData=='pre':
                    if start<=float(preData[4]):
                        focus=preData
                    else:
                        focus=None
                elif finalData=='post':
                    if stop>=float(postData[3]):
                        focus=postData
                    else:
                        focus=None
            if focus is not None and focus[2]!='gene':
                information['Focus']=focus[2]
            else:
                information['Focus']='N/A'
        return [information,focusGene,focus]
                    
                    
                    
    def printToLog(self,message):
        self.core.printToLog(message)
        

    
#def getViralReferenceFa():
#    return
#
#def getHostReferenceFa():
#    return
#    
#def getFastQReadsLocation():
#    return
#    
#def installDependencies():
#    
#def checkDependencies():
#    
#def checkIndex():
#

    

#=============================================================================================================================================================
#=============================================================================================================================================================
#=============================================================================================================================================================



class Sam:

    Quit=False
    def __init__(self,filename,CS,readBaseName):
        self.sam=[]
        self.readBaseName=readBaseName
        self.runDirectory=os.path.dirname(filename)
        self.storage=[]
        self.header=[]
        self.flags=[]
        self.minLen=10
        self.loadSam(filename)
        if self.Quit==False:
            if CS:
                self.loadFlagsCSAlignment()
            else:
                self.loadFlags()
                
    def loadSam(self,filename):
        file = open(filename,'r')
        for line in file:
            if line.startswith('@'):
                self.header.append(line.split())
            else:
                self.sam.append(line.split())
        file.close()
        if len(self.sam)==0:
            self.Quit=True
        
        
    def loadFlags(self):
        countPaired=0
        countAligned=0
        countUnaligned=0
        
        for i in range (0,len(self.sam)):
            self.flags.append([])
            flag=bin(int(self.sam[i][1]))[2:]
            for j in range (len(flag),0,-1):
                self.flags[i].append(flag[j-1])
            for k in range (0,len(self.flags[i])):
                if k==0 and self.flags[i][k]=='1':
                    countPaired+=1
                if k==1 and self.flags[i][k]=='1':
                    countAligned+=1
                if k==2 and self.flags[i][k]=='1':
                    countUnaligned+=1
        self.alignmentRate=((len(self.sam)-countUnaligned)/len(self.sam))
                    
    
    def loadFlagsCSAlignment(self):
        countAligned=0
        countUnaligned=0
        for i in range (0,len(self.sam)):
            self.flags.append([])
            flag=bin(int(self.sam[i][1]))[2:]
            for j in range (len(flag),0,-1):
                self.flags[i].append(flag[j-1])
            for k in range (0,len(self.flags[i])):
                if k==1 and self.flags[i][k]=='1':
                    countAligned+=1
                if k==2 and self.flags[i][k]=='1':
                    countUnaligned+=1
        self.alignmentRate=((len(self.sam)-countUnaligned)/len(self.sam))
                
    def extractClippedSeq(self,minLen,paired):
        count=0
        out=open(self.runDirectory+'/'+self.readBaseName+'_CSList.txt','w')
        out2=open(self.runDirectory+'/'+self.readBaseName+'_CSListFull.txt','w')
        for i in range (0,len(self.sam)):
            cigar=self.sam[i][5]
            if cigar!="*" and 'S' in cigar:
                pairs=re.findall('\d+[A-Z]+',cigar)
                index=0
                for j in range (0,len(pairs)):
                    length=int(pairs[j][0:len(pairs[j])-1])
                    if pairs[j].endswith('S') and length>=minLen:
                        seq=Seq(self.sam[i][9][index:index+length])
                        fullseq=Seq(self.sam[i][9])
                        rID=self.sam[i][0]
                        if paired:
                            pair=2
                            if self.flags[i][6]=='1':
                                pair=1
                            if self.flags[i][4]=='0':
                                self.storage.append([rID,i,seq])
                                out.write('>'+str(i)+'.'+str(rID)+'.'+str(pair)+'\n')
                                out.write(str(seq)+'\n')
                                out2.write('>'+str(i)+'.'+str(rID)+'.'+str(pair)+'\n')
                                out2.write(str(fullseq)+'\n')
                            else:
                                self.storage.append([rID,i,seq,i])
                                out.write('>'+str(i)+'.'+str(rID)+'.'+str(pair)+'\n')
                                out.write(str(seq.reverse_complement())+'\n')
                                out2.write('>'+str(i)+'.'+str(rID)+'.'+str(pair)+'\n')
                                out2.write(str(fullseq)+'\n') #.reverse_complement()
                        else:
                            self.storage.append([rID,i,seq])
                            out.write('>'+str(i)+'.'+str(rID)+'\n')
                            out.write(str(seq)+'\n')
                            out2.write('>'+str(i)+'.'+str(rID)+'\n')
                            out2.write(str(fullseq)+'\n')
                        count+=1
                        break
                    index+=length
        
        out.close()
        out2.close()
        
                
    def returnAlignedCS(self,s,mode):
        for i in range (0,len(self.sam)):
            if int(self.sam[i][1]) != 4:
                sid=int(self.sam[i][0].split('.')[0])
                
                

#=============================================================================================================================================================
#=============================================================================================================================================================
#=============================================================================================================================================================

def hello():
    pass





class Interface(Frame):
    pairedReads=True
    filtered=False
    useBasic=False
    filteredReroute=[]
    def __init__(self, master,c):
        Frame.__init__(self, master)
        self.c=c
        self.defaultbg=master.cget('bg')
        self.create_widgets()
        self.master=master
        

    def create_widgets(self):
        self.master.title("JBS ChimericSeq")

        self.label1=Text(self.master,height=1,width=20,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.label1,'Fastq File(s):')
        self.label1.grid(row=0,column=0,columnspan=1,sticky=W)        
        
        self.frame1=Frame(self.master)
        self.frame1.grid(row=1,column=0,sticky='nw',columnspan=2)         
        self.bttn1=Button(self.frame1,text = '. . .', command=self.getReads)
        self.bttn1.grid(row=0,column=0,sticky='',ipadx=3,ipady=5)
        self.fastqBox=Text(self.frame1,height=2,width=70,state=DISABLED,background=self.defaultbg)
        self.fastqBox.grid(row=0,column=1,sticky=W,columnspan=1)
        self.scrollbarFile=ttk.Scrollbar(self.frame1,command=self.fastqBox.yview)
        self.fastqBox.config(yscrollcommand=self.scrollbarFile.set)
        self.scrollbarFile.grid(row=0,column=2,sticky='ns')
      
        self.label2=Text(self.master,height=2,width=65,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.label2,'Reads Containing\nChimeric Sequences:')
        self.label2.grid(row=2,column=0,columnspan=2,sticky=W)

        self.listBoxFrame=Frame(self.master)
        self.listBoxFrame.grid(row=3,column=0,columnspan=1,rowspan=1,sticky='wens')
        self.listBox1=Listbox(self.listBoxFrame,selectmode=SINGLE,height=20,width=25,activestyle=NONE)
        self.listBox1.grid(row=0,column=0,sticky='wens')
#        self.listBox1.insert(END, "a list entry dfsgdfg dfg dfg dfg dfg dfg dfg dfg dfg df ")        
#        for item in ["one", "two", "three", "four","one", "two", "three", "four","one", "two", "three", "four","one", "two", "three", "four"]:
#            self.listBox1.insert(END, item)
        self.scrollbar1=ttk.Scrollbar(self.listBoxFrame,command=self.listBox1.yview)
        self.scrollbar2=ttk.Scrollbar(self.listBoxFrame,command=self.listBox1.xview,orient=HORIZONTAL)
        self.listBox1.config(xscrollcommand=self.scrollbar2.set)
        self.listBox1.config(yscrollcommand=self.scrollbar1.set)
        self.list1Selection=0
        self.listBox1.select_set(self.list1Selection)
        self.scrollbar1.grid(row=0,column=1,sticky='wns')
        self.scrollbar2.grid(row=1,column=0,sticky='ew')
        self.listBox1.bind('<Button-1>',self.listChoiceClick)
        self.listBox1.bind('<Up>',self.listChoice)
        self.listBox1.bind('<Down>',self.listChoice)
        
        self.statsFrame=Frame(self.master)
        self.statsFrame.grid(row=3,column=1,sticky='nswe',rowspan=1)  
        
        self.statsTreeCols=['Attribute','Value']
        self.statsTree=ttk.Treeview(self.statsFrame,columns=self.statsTreeCols,show='headings',height=15)
        self.statsTree.bind("<Button-3>",self.popTreeMenu)
        self.ysb=ttk.Scrollbar(self.statsFrame,orient=VERTICAL, command= self.statsTree.yview)
        self.xsb=ttk.Scrollbar(self.statsFrame,orient=HORIZONTAL, command= self.statsTree.xview)
        self.statsTree.column(0,width=170)
        self.statsTree.column(1,width=250)
        self.statsTree['yscroll'] = self.ysb.set
        self.statsTree['xscroll'] = self.xsb.set
        self.statsTree.grid(row=0,column=0,sticky='ns')
        self.ysb.grid(row=0,column=1,sticky='ns')
        self.xsb.grid(row=1,column=0,sticky='ew')
        for c in self.statsTreeCols:
            self.statsTree.heading(c,text=c.title())#command=lambda c=c: self._column_sort(c,True)
        self.attributeList=['{Read Name}','{Read Length}','{Fastq Source}','{Index}','{Viral Component Length}','{Local Viral Coordinates}',
        '{Viral Reference Coordinates}','{Viral Accession}','{Viral Orientation}',
        '{Viral TM (Basic)}','{Viral TM (Salt Adjusted)}',
        '{Host Component Length}','{Local Host Coordinates}','{Host Reference Coordinates}','{Chromosome}','{Gene}',
        '{Inside Gene}','{Distance To Gene}','{Direction}','{Focus Region}','{Host Orientation}',
        '{Host TM (Basic)}','{Host TM (Salt Adjusted)}','{Inserted Regions}','{Overlap}','{Overlap TM (Basic)}',
        '{Overlap TM (Salt Adjusted)}','{Host Map Quality}','{Viral Map Quality}','{Fastq score}']
        self.genericAttributeList=['{Max Mapping Score}','{Min Mapping Score}','{Aligned to Chromosome 1}','{Aligned to Chromosome 2}','{Aligned to Chromosome 3}',
        '{Aligned to Chromosome 4}','{Aligned to Chromosome 5}','{Aligned to Chromosome 6}','{Aligned to Chromosome 7}','{Aligned to Chromosome 8}','{Aligned to Chromosome 9}',
        '{Aligned to Chromosome 10}','{Aligned to Chromosome 11}','{Aligned to Chromosome 12}','{Aligned to Chromosome 13}','{Aligned to Chromosome 14}','{Aligned to Chromosome 15}',
        '{Aligned to Chromosome 16}','{Aligned to Chromosome 17}','{Aligned to Chromosome 18}','{Aligned to Chromosome 19}','{Aligned to Chromosome 20}','{Aligned to Chromosome 21}',
        '{Aligned to Chromosome 22}','{Aligned to Chromosome X}','{Aligned to Chromosome Y}',]
        for item in self.attributeList:
            self.statsTree.insert('','end',item,values=item)

                
        self.seqFrame=Frame(self.master)
        self.seqFrame.grid(row=0,column=2,ipadx=0,rowspan=3,columnspan=5,sticky='nw')
        self.seqLabel=Text(self.seqFrame,height=1,width=37,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.seqLabel.tag_configure("Virus", foreground="red")
        self.seqLabel.tag_configure('Host',background='yellow')
        self.seqLabel.tag_configure('Overlap',underline=True)
        self.changeLabel(self.seqLabel,'Sequence: Red=Viral Highlighted=Host')
        self.seqLabel.tag_add('Virus','1.10','1.13')
        self.seqLabel.tag_add('Host','1.20','1.31')
        self.seqLabel.grid(row=0,column=0,sticky='nw')
        self.seqBox=Text(self.seqFrame,height=4,width=70,state=DISABLED,relief=SUNKEN)
        self.seqBox.grid(row=1,column=0,sticky='nw')
        self.seqBox.tag_configure("Virus", foreground="red")
        self.seqBox.tag_configure('Host',background='yellow')
        self.seqBox.tag_configure('Overlap',underline=True)
        self.scrollbar3=ttk.Scrollbar(self.seqFrame,command=self.seqBox.yview)
        self.seqBox.config(yscrollcommand=self.scrollbar3.set)
        self.scrollbar3.grid(row=1,column=1,sticky='ns')
              
        self.logFrame=Frame(self.master)
        self.logFrame.grid(row=3,column=2,sticky='nwse',ipadx=0,ipady=0,rowspan=1,columnspan=5)
        self.log=Text(self.logFrame,height=20,width=70,state=DISABLED)
        self.log.tag_configure("Error", foreground="red")
        self.log.tag_configure("Important", background='yellow')
        self.log.grid(row=0,column=0,sticky='e')      
        self.scrollbar=ttk.Scrollbar(self.logFrame,command=self.log.yview)
        self.log.config(yscrollcommand=self.scrollbar.set)
        self.scrollbar.grid(row=0,column=1,sticky='nse')

        self.logoFrame=Frame(self.master)
        self.logoL=Text(self.logoFrame,height=1,width=45,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.logoL,'')
        self.logoL.grid(row=0,column=0,columnspan=1,sticky=W)
        self.logoCanvas=Canvas(self.logoFrame)
        self.logo=PhotoImage(file=self.c.workingDirectory+'/JBS.gif')
        self.logoCanvas.create_image(0,0,image=self.logo,anchor=NW)
        self.logoCanvas.grid(row=0,column=1)
        self.logoFrame.grid(row=4,column=3)  

        
        
        
        self.buttonFrame=Frame(self.master)
        self.buttonFrame.grid(row=4,column=0,sticky='nw',columnspan=2)
        self.buttonL=Text(self.buttonFrame,height=1,width=15,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.buttonL,'Controls:')
        self.buttonL.grid(row=0,column=0,columnspan=2,sticky=W)
        self.bttnStart = Button(self.buttonFrame, text = "Start Run", command=self.c.run)
        self.bttnStart.grid(row=1,column=0,columnspan=2,sticky='nesw')
        self.yesbttn=Button(self.buttonFrame,text='Yes',command=hello)
        self.yesbttn.grid(row=2,column=0,sticky='nwes')
        self.nobttn=Button(self.buttonFrame,text='No',command=hello)
        self.nobttn.grid(row=2,column=1,sticky='nwes')
        
        
        self.modeIntVar=IntVar()
        self.menubar = Menu(self.master)
        self.filemenu = Menu(self.menubar, tearoff=0)
        self.modeMenu=Menu(self.filemenu,tearoff=0)   
        self.modeMenu.add_radiobutton(label='Integration',command=self.changeMode,variable=self.modeIntVar,value=0)
        self.modeMenu.add_radiobutton(label='Translocation',command=self.changeMode,variable=self.modeIntVar,value=1)
        self.modeIntVar.set(0)
        self.filemenu.add_cascade(label="Mode", menu=self.modeMenu)
        self.filemenu.add_separator()
        self.filemenu.add_command(label="Load Settings", command=self.c.loadSettings)
        self.filemenu.add_separator()
        self.filemenu.add_command(label="Save", command=self.c.saveData)
        self.filemenu.add_command(label='Save Settings', command=self.c.saveSettings)
        self.filemenu.add_separator()
        self.filemenu.add_command(label="Exit", command=self.EXIT)
        self.menubar.add_cascade(label="File", menu=self.filemenu)
        self.editmenu = Menu(self.menubar, tearoff=0)
        self.cpumenu = Menu(self.editmenu,tearoff=0)
        self.cpuIntVar=IntVar()
        self.autoModeVar=IntVar()
        self.autoModeVar.set(1)  ##set to 1 for final code
        self.loadAlignmentBoolVar=IntVar()
        self.loadAlignmentBoolVar.set(0)  ##set to 0 for final code
        self.editmenu.add_command(label="Set Locations", command=self.newWindow)
        self.editmenu.add_command(label='Configurations',command=self.optionsWindow)
        self.otempFilter=IntVar()
        self.otempFilter.set(0)
        self.olenFilter=IntVar()
        self.olenFilter.set(0)
        self.htempFilter=IntVar()
        self.htempFilter.set(0)
        self.hlenFilter=IntVar()
        self.hlenFilter.set(0)
        self.vtempFilter=IntVar()
        self.vtempFilter.set(0)
        self.vlenFilter=IntVar()
        self.vlenFilter.set(0)
        self.doGTFBoolVar=IntVar()
        self.doGTFBoolVar.set(1) # set to 1 for final code
        self.doReadCleanBoolVar=IntVar()
        self.doReadCleanBoolVar.set(0) # set to 1 for final code
        self.filtermenu = Menu(self.editmenu,tearoff=0)
        self.editmenu.add_cascade(label='Filtering',menu=self.filtermenu)
        self.filtermenu.add_checkbutton(label='Overlap TM',command=lambda: self.changeFilter(1),onvalue=1,offvalue=0,variable=self.otempFilter)
        self.filtermenu.add_checkbutton(label='Overlap Length',command=lambda: self.changeFilter(2),onvalue=1,offvalue=0,variable=self.olenFilter)
        self.filtermenu.add_checkbutton(label='Host TM',command=lambda: self.changeFilter(3),onvalue=1,offvalue=0,variable=self.htempFilter)
        self.filtermenu.add_checkbutton(label='Host Length',command=lambda: self.changeFilter(4),onvalue=1,offvalue=0,variable=self.hlenFilter)
        self.filtermenu.add_checkbutton(label='Viral TM',command=lambda: self.changeFilter(5),onvalue=1,offvalue=0,variable=self.vtempFilter)
        self.filtermenu.add_checkbutton(label='Viral Length',command=lambda: self.changeFilter(6),onvalue=1,offvalue=0,variable=self.vlenFilter)
        self.filtermenu.add_separator()
        self.filtermenu.add_command(label='Reset Filters',command=self.resetFilters)
        self.editmenu.add_cascade(label='Thread Count',menu=self.cpumenu)
        self.editmenu.add_checkbutton(label='Prompting',command=self.changePrompting,onvalue=1,offvalue=0,variable=self.autoModeVar)
        self.editmenu.add_checkbutton(label='Read cleaning',command=self.doReadClean,onvalue=1,offvalue=0,variable=self.doReadCleanBoolVar)
        self.editmenu.add_checkbutton(label='Load Alignments When Possible',command=self.loadAlignment,onvalue=1,offvalue=0,variable=self.loadAlignmentBoolVar)
        self.editmenu.add_checkbutton(label='Get Gene info',command=self.doGTF,onvalue=1,offvalue=0,variable=self.doGTFBoolVar)
        self.menubar.add_cascade(label="Options", menu=self.editmenu)
        self.helpmenu = Menu(self.menubar, tearoff=0)
        self.helpmenu.add_command(label="About", command=self.openWeb)
        self.menubar.add_cascade(label="Help", menu=self.helpmenu)
        self.master.config(menu=self.menubar)
        for i in self.c.Cores:
            self.cpumenu.add_radiobutton(label=i,command=self.changeCores,variable=self.cpuIntVar,value=i)
            temp=i
        self.cpuIntVar.set(temp)
        self.c.coreOption=int(self.cpuIntVar.get())
        
        self.treeMenu=Menu(self.statsFrame,tearoff=0)
        self.treeMenu.add_command(label='Copy',command=self.copySelection)
                

        self.OptionsWin=tki.Toplevel(self.master)
        self.OptionsWin.title('Configurations')
        self.OptionsWin.geometry('300x300')   
        self.OptionsWin.protocol('WM_DELETE_WINDOW',self.OptionsWin.withdraw)
        self.OptionsWin.withdraw()
        self.clipLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.clipLabel.grid(row=0,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.clipLabel,'Clipped Sequence Min Length:')
        self.clipText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.clipText.bind('<Return>',self.noReturn)
        self.clipText.bind('<space>',self.noReturn)
        self.clipText.insert(END,self.c.CSminLen)
        self.clipText.grid(row=0,column=1,columnspan=1,sticky=W)
        self.saltLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.saltLabel.grid(row=1,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.saltLabel,'Salt Concentration (mM):')
        self.saltText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.saltText.bind('<Return>',self.noReturn)
        self.saltText.bind('<space>',self.noReturn)
        self.saltText.insert(END,self.c.Na)
        self.saltText.grid(row=1,column=1,columnspan=1,sticky=W)
        self.TrimmingLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.TrimmingLabel.grid(row=2,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.TrimmingLabel,'Trimming 5\' (bp):')
        self.TrimmingText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.TrimmingText.bind('<Return>',self.noReturn)
        self.TrimmingText.bind('<space>',self.noReturn)
        self.TrimmingText.insert(END,self.c.Trim)
        self.TrimmingText.grid(row=2,column=1,columnspan=1,sticky=W)
        self.TrimmingLabel2=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.TrimmingLabel2.grid(row=3,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.TrimmingLabel2,'Trimming 3\' (bp):')
        self.TrimmingText2=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.TrimmingText2.bind('<Return>',self.noReturn)
        self.TrimmingText2.bind('<space>',self.noReturn)
        self.TrimmingText2.insert(END,self.c.Trim2)
        self.TrimmingText2.grid(row=3,column=1,columnspan=1,sticky=W)
        self.tempFilterLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.tempFilterLabel.grid(row=4,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.tempFilterLabel,'Overlap TM Max (C):')
        self.tempFilterText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.tempFilterText.bind('<Return>',self.noReturn)
        self.tempFilterText.bind('<space>',self.noReturn)
        self.tempFilterText.insert(END,self.c.otempFilter)
        self.tempFilterText.grid(row=4,column=1,columnspan=1,sticky=W)
        self.lenFilterLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.lenFilterLabel.grid(row=5,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.lenFilterLabel,'Overlap Length Max:')
        self.lenFilterText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.lenFilterText.bind('<Return>',self.noReturn)
        self.lenFilterText.bind('<space>',self.noReturn)
        self.lenFilterText.insert(END,self.c.olenFilter)
        self.lenFilterText.grid(row=5,column=1,columnspan=1,sticky=W)
        self.htempFilterLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.htempFilterLabel.grid(row=6,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.htempFilterLabel,'Host TM Min (C):')
        self.htempFilterText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.htempFilterText.bind('<Return>',self.noReturn)
        self.htempFilterText.bind('<space>',self.noReturn)
        self.htempFilterText.insert(END,self.c.htempFilter)
        self.htempFilterText.grid(row=6,column=1,columnspan=1,sticky=W)
        self.hlenFilterLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.hlenFilterLabel.grid(row=7,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.hlenFilterLabel,'Host Length Min:')
        self.hlenFilterText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.hlenFilterText.bind('<Return>',self.noReturn)
        self.hlenFilterText.bind('<space>',self.noReturn)
        self.hlenFilterText.insert(END,self.c.hlenFilter)
        self.hlenFilterText.grid(row=7,column=1,columnspan=1,sticky=W)        
        self.vtempFilterLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.vtempFilterLabel.grid(row=8,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.vtempFilterLabel,'Viral TM Min (C):')
        self.vtempFilterText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.vtempFilterText.bind('<Return>',self.noReturn)
        self.vtempFilterText.bind('<space>',self.noReturn)
        self.vtempFilterText.insert(END,self.c.vtempFilter)
        self.vtempFilterText.grid(row=8,column=1,columnspan=1,sticky=W)
        self.vlenFilterLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.vlenFilterLabel.grid(row=9,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.vlenFilterLabel,'Viral Length Min:')
        self.vlenFilterText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.vlenFilterText.bind('<Return>',self.noReturn)
        self.vlenFilterText.bind('<space>',self.noReturn)
        self.vlenFilterText.insert(END,self.c.vlenFilter)
        self.vlenFilterText.grid(row=9,column=1,columnspan=1,sticky=W)
        self.useBasicLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.useBasicLabel.grid(row=10,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.useBasicLabel,'Filter with Basic Temperature:')
        self.useBasicBttn=Button(self.OptionsWin,text = "False", command=self.switchBasic)
        self.useBasicBttn.grid(row=10,column=1,columnspan=1,sticky=W+E)
        self.DistanceLabel=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.DistanceLabel.grid(row=11,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.DistanceLabel,'Gene Distance Threshold:')
        self.DistanceText=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.DistanceText.bind('<Return>',self.noReturn)
        self.DistanceText.bind('<space>',self.noReturn)
        self.DistanceText.insert(END,self.c.distanceThreshold)
        self.DistanceText.grid(row=11,column=1,columnspan=1,sticky=E+W)
        
        self.readminlength=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.readminlength.grid(row=12,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.readminlength,'Read Min Length Preprocessing:')
        self.readminlength=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.readminlength.bind('<Return>',self.noReturn)
        self.readminlength.bind('<space>',self.noReturn)
        self.readminlength.insert(END,self.c.preprocessReadLength)
        self.readminlength.grid(row=12,column=1,columnspan=1,sticky=E+W)
        
        self.maxunknown=Text(self.OptionsWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.maxunknown.grid(row=13,column=0,columnspan=1,sticky=W)
        self.changeLabel(self.maxunknown,'Max % Unknown Nucleotides:')
        self.maxunknown=Text(self.OptionsWin,height=1,width=5,state=NORMAL)
        self.maxunknown.bind('<Return>',self.noReturn)
        self.maxunknown.bind('<space>',self.noReturn)
        self.maxunknown.insert(END,self.c.preprocessUnknownPercent)
        self.maxunknown.grid(row=13,column=1,columnspan=1,sticky=E+W)        
        
        self.NewWin=tki.Toplevel(self.master)
        self.NewWin.title('Location Options')
        self.NewWin.geometry('620x490')
        self.NewWin.protocol('WM_DELETE_WINDOW',self.NewWin.withdraw)
        self.NewWin.withdraw()
        self.bt2locLabel=Text(self.NewWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.bt2locLabel,'Bowtie2 Directory:')
        self.bt2locLabel.grid(row=0,column=0,columnspan=2,sticky=W)
        self.bttn2=Button(self.NewWin,text = '. . .', command=self.setBT2Folder)
        self.bttn2.grid(row=1,column=0,sticky=W,ipadx=3)
        self.bt2Text=Text(self.NewWin,height=1,width=70,state=DISABLED,background=self.defaultbg)
        self.changeLabel(self.bt2Text,self.c.Bowtie2Folder)
        self.bt2Text.grid(row=1,column=1,sticky=W,columnspan=4)
        self.vrfLabel=Text(self.NewWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.vrfLabel,'Viral Reference *.fa:')
        self.vrfLabel.grid(row=2,column=0,columnspan=2,sticky=W)
        self.bttn3=Button(self.NewWin,text = '. . .', command=self.setViralRefFa)
        self.bttn3.grid(row=3,column=0,sticky=W,ipadx=3)
        self.vrf=Text(self.NewWin,height=1,width=70,state=DISABLED,background=self.defaultbg)
        self.changeLabel(self.vrf,self.c.ViralRefFa)
        self.vrf.grid(row=3,column=1,sticky=W,columnspan=4)
        self.vddLabel=Text(self.NewWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.vddLabel,'Viral Index Directory:')
        self.vddLabel.grid(row=4,column=0,columnspan=2,sticky=W)
        self.bttn4=Button(self.NewWin,text = '. . .', command=self.setViralRefFolder)
        self.bttn4.grid(row=5,column=0,sticky=W,ipadx=3)
        self.vdd=Text(self.NewWin,height=1,width=70,state=DISABLED,background=self.defaultbg)
        self.changeLabel(self.vdd,self.c.ViralRefFolder)
        self.vdd.grid(row=5,column=1,sticky=W,columnspan=4)
        self.vpLabel=Text(self.NewWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.vpLabel,'Viral Bowtie2 Prefix:')
        self.vpLabel.grid(row=6,column=0,columnspan=2,sticky=W)
        self.vp=Text(self.NewWin,height=1,width=70,state=NORMAL)
        self.vp.insert(INSERT,self.c.viralPrefix)
        self.vp.bind('<Return>',self.noReturn)
        self.vp.bind('<space>',self.noReturn)
        self.vp.grid(row=7,column=1,sticky=W,columnspan=4)
        self.vpbttn=Button(self.NewWin,text = 'Build', command=lambda: self.c.askbuildBowtie2ViralIndex(self.vp.get(1.0,'end-1c')))
        self.vpbttn.grid(row=7,column=0,sticky=W)
        self.hrfLabel=Text(self.NewWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.hrfLabel,'Host Reference *.fa:')
        self.hrfLabel.grid(row=8,column=0,columnspan=2,sticky=W)
        self.bttn5=Button(self.NewWin,text = '. . .', command=self.setHostRefFa)
        self.bttn5.grid(row=9,column=0,sticky=W,ipadx=3)
        self.hrf=Text(self.NewWin,height=1,width=70,state=DISABLED,background=self.defaultbg)
        self.changeLabel(self.hrf,self.c.HostRefFa)
        self.hrf.grid(row=9,column=1,sticky=W,columnspan=4)
        self.hddLabel=Text(self.NewWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.hddLabel,'Host Index Directory:')
        self.hddLabel.grid(row=10,column=0,columnspan=2,sticky=W)
        self.bttn6=Button(self.NewWin,text = '. . .', command=self.setHostRefFolder)
        self.bttn6.grid(row=11,column=0,sticky=W,ipadx=3)
        self.hdd=Text(self.NewWin,height=1,width=70,state=DISABLED,background=self.defaultbg)
        self.changeLabel(self.hdd,self.c.HostRefFolder)
        self.hdd.grid(row=11,column=1,sticky=W,columnspan=4)
        self.hpLabel=Text(self.NewWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.hpLabel,'Host Bowtie2 Prefix:')
        self.hpLabel.grid(row=12,column=0,columnspan=2,sticky=W)
        self.hp=Text(self.NewWin,height=1,width=70,state=NORMAL)
        self.hp.insert(INSERT,self.c.HostPrefix)
        self.hp.grid(row=13,column=1,sticky=W,columnspan=4)
        self.hp.bind('<Return>',self.noReturn)
        self.hp.bind('<space>',self.noReturn)
        self.hpbttn=Button(self.NewWin,text = 'Build', command=lambda: self.c.askbuildBowtie2HostIndex(self.hp.get(1.0,'end-1c')))
        self.hpbttn.grid(row=13,column=0,sticky=W)

        self.hgtfLabel=Text(self.NewWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)
        self.changeLabel(self.hgtfLabel,'Host GTF File:')
        self.hgtfLabel.grid(row=14,column=0,columnspan=2,sticky=W)
        self.hgtf=Text(self.NewWin,height=1,width=70,state=DISABLED,background=self.defaultbg)
        self.changeLabel(self.hgtf,'None')
        self.hgtf.grid(row=15,column=1,sticky=W,columnspan=4)
        self.hgtfbttn=Button(self.NewWin,text = '. . .', command=self.setHostGTF)
        self.hgtfbttn.grid(row=15,column=0,sticky=W,ipadx=3)
        
        self.outLabel=Text(self.NewWin,height=1,width=30,state=DISABLED,relief=FLAT,background=self.defaultbg)        
        self.changeLabel(self.outLabel,'Output Directory:')
        self.outLabel.grid(row=16,column=0,columnspan=2,sticky=W)
        self.bttn7=Button(self.NewWin,text = '. . .', command=self.setOutputDir)
        self.bttn7.grid(row=17,column=0,sticky=W,ipadx=3)
        self.out=Text(self.NewWin,height=1,width=70,state=DISABLED,background=self.defaultbg)
        self.changeLabel(self.out,self.c.outDir)
        self.out.grid(row=17,column=1,sticky=W,columnspan=4)

    def changeMode(self):
        self.c.runmode=int(self.modeIntVar.get())
        if self.c.runmode==0:
            self.printToLog('Switching to integration discovery mode')
        else:
            self.printToLog('Switching to translocation discovery mode')
    
    
    def popTreeMenu(self,event):
        iid=self.statsTree.identify_row(event.y)
        if iid:
            iid='\"'+iid+'\"'
            self.statsTree.selection_set(iid)
            self.treeMenu.post(event.x_root,event.y_root)
        
        
    def copySelection(self):
        item = self.statsTree.focus()
        copy=(self.statsTree.item(item)['values'])
        self.c.topLevelTK.clipboard_clear()
        self.c.topLevelTK.clipboard_append(str(copy))
    
    def resetYesNoButtons(self):
        self.yesbttn.configure(command=hello)
        self.nobttn.configure(command=hello)
    
    def listChoiceClick(self,event):
        self.listBox1.select_clear(self.list1Selection)
        self.list1Selection=self.listBox1.nearest(event.y)
        self.listBox1.select_set(self.list1Selection)
        self.loadSelection()
    
    def doGTF(self):
        if self.doGTFBoolVar.get()==1:
            self.c.doGTF=True
            self.printToLog('Including gene characterization')
        else:
            self.c.doGTF=False
            self.printToLog('Excluding gene characterization')
    
    def doReadClean(self):
        if self.doReadCleanBoolVar.get()==1:
            self.c.doReadClean=True
            self.printToLog('Read Preprocessing Enabled')
        else:
            self.c.doReadClean=False
            self.printToLog('Read Preprocessing Disabled')
            
            
    def EXIT(self):
        self.master.destroy()
        sys.exit()
    
    def openWeb(self):
        webbrowser.open('http://www.jbs-science.com/ChimericSeq.php')
    
    def changeFilter(self,num):
        if num==1:
            if self.otempFilter.get()==1:
                self.printToLog('Overlap TM Filter: Enabled')
            else:
                self.printToLog('Overlap TM Filter: Disabled')
        elif num==2:
            if self.olenFilter.get()==1:
                self.printToLog('Overlap Length Filter: Enabled')
            else:
                self.printToLog('Overlap Length Filter: Disabled')
        elif num==3:
            if self.htempFilter.get()==1:
                self.printToLog('Host TM Filter: Enabled')
            else:
                self.printToLog('Host TM Filter: Disabled')
        elif num==4:
            if self.hlenFilter.get()==1:
                self.printToLog('Host Length Filter: Enabled')
            else:
                self.printToLog('Host Length Filter: Disabled')
        elif num==5:
            if self.vtempFilter.get()==1:
                self.printToLog('Viral TM Filter: Enabled')
            else:
                self.printToLog('Viral TM Filter: Disabled')
        elif num==6:
            if self.vlenFilter.get()==1:
                self.printToLog('Viral Length Filter: Enabled')
            else:
                self.printToLog('Viral Length Filter: Disabled')
        self.updateFilterValues()
        self.listRedraw()
    
    def updateFilterValues(self):
        self.c.olenFilter=float(self.lenFilterText.get(1.0,'end-1c'))
        self.c.otempFilter=float(self.tempFilterText.get(1.0,'end-1c'))
        self.c.hlenFilter=float(self.hlenFilterText.get(1.0,'end-1c'))
        self.c.htempFilter=float(self.htempFilterText.get(1.0,'end-1c'))
        self.c.vlenFilter=float(self.vlenFilterText.get(1.0,'end-1c'))
        self.c.vtempFilter=float(self.vtempFilterText.get(1.0,'end-1c'))
    
    def resetFilters(self):
        self.otempFilter.set(0)
        self.olenFilter.set(0)
        self.htempFilter.set(0)
        self.hlenFilter.set(0)
        self.vtempFilter.set(0)
        self.vlenFilter.set(0)
        self.printToLog('Filters Reset')
        try:
            len(self.c.Map.data)
            self.listRedraw()
        except:
            pass
        
    def switchBasic(self):
        self.useBasic=not self.useBasic
        self.c.useBasic=self.useBasic
        if self.useBasic:
            self.changeBttnText(self.useBasicBttn,'True')
            self.printToLog('Using Basic Melt Temperatures for Filtering')
        else:
            self.changeBttnText(self.useBasicBttn,'False')
            self.printToLog('Using Salt Adjusted Melt Temperatures for Filtering')
        self.listRedraw()
            
            
            
    def listChoice(self,event):
        #self.listBox1.yview_scroll(1,'units')
        if self.list1Selection<self.listBox1.size()-1 and event.keycode==40:
            self.listBox1.select_clear(self.list1Selection)
            self.list1Selection+=1
            self.listBox1.select_set(self.list1Selection)
        elif self.list1Selection>0 and event.keycode==38:
            self.listBox1.select_clear(self.list1Selection)
            self.list1Selection-=1
            self.listBox1.select_set(self.list1Selection)
        self.loadSelection()
    
    def loadSelection(self):  ##update to use property index instead of position in list
        try:
            self.c.Map
            carryon=True
        except:
            carryon=False
        if carryon:
            try:
                if self.filtered:
                    index=self.filteredReroute[self.listBox1.curselection()[0]]##self.filteredReroute[self.c.Map.data[self.listBox1.curselection()[0]]['Index']]
                else:
                    index=self.listBox1.curselection()[0]##self.c.Map.data[self.listBox1.curselection()[0]]['Index']
                #print self.c.Map.data.keys()[self.c.Map.data.values().index()
                self.statsTree.set('{Read Name}',column='Value',value=self.c.Map.data[index]['ReadName'])
                self.statsTree.set('{Read Length}',column='Value',value=self.c.Map.data[index]['ReadLength'])
                self.statsTree.set('{Fastq Source}',column='Value',value=self.c.Map.data[index]['FastqSource'])
                self.statsTree.set('{Index}',column='Value',value=self.c.Map.data[index]['Index'])
                self.statsTree.set('{Viral Component Length}',column='Value',value=self.c.Map.data[index]['Vlength'])
                self.statsTree.set('{Host Component Length}',column='Value',value=self.c.Map.data[index]['Hlength'])
                self.statsTree.set('{Local Viral Coordinates}',column='Value',value=self.c.Map.data[index]['ViralLocalCords'])
                self.statsTree.set('{Local Host Coordinates}',column='Value',value=self.c.Map.data[index]['HostLocalCords'])
                self.statsTree.set('{Chromosome}',column='Value',value=self.c.Map.data[index]['Chromosome'])
                
                self.statsTree.set('{Overlap}',column='Value',value=self.c.Map.data[index]['Overlap'])
                self.changeLabel(self.seqBox,self.c.Map.data[index]['Sequence'])
                self.statsTree.set('{Viral Reference Coordinates}',column='Value',value=self.c.Map.data[index]['ViralRefCords'])
                self.statsTree.set('{Host Reference Coordinates}',column='Value',value=self.c.Map.data[index]['HostRefCords'])
                self.statsTree.set('{Inserted Regions}',column='Value',value=self.c.Map.data[index]['Inserted'])
                self.statsTree.set('{Overlap TM (Basic)}',column='Value',value=str(self.c.Map.data[index]['OverlapTM'])+'°C')
                self.statsTree.set('{Overlap TM (Salt Adjusted)}',column='Value',value=str(self.c.Map.data[index]['OverlapTMAdjusted'])+'°C')
                self.statsTree.set('{Viral Accession}',column='Value',value=self.c.Map.data[index]['ViralAccession'])
                self.statsTree.set('{Viral TM (Basic)}',column='Value',value=str(self.c.Map.data[index]['VTM'])+'°C')
                self.statsTree.set('{Host TM (Basic)}',column='Value',value=str(self.c.Map.data[index]['HTM'])+'°C')
                self.statsTree.set('{Viral TM (Salt Adjusted)}',column='Value',value=str(self.c.Map.data[index]['VTMAdjusted'])+'°C')
                self.statsTree.set('{Host TM (Salt Adjusted)}',column='Value',value=str(self.c.Map.data[index]['HTMAdjusted'])+'°C')
                self.statsTree.set('{Viral Orientation}',column='Value',value=self.c.Map.data[index]['ViralOrientation'])
                self.statsTree.set('{Host Orientation}',column='Value',value=self.c.Map.data[index]['HostOrientation'])
                self.statsTree.set('{Host Map Quality}',column='Value',value=self.c.Map.data[index]['HMapQ'])
                self.statsTree.set('{Viral Map Quality}',column='Value',value=self.c.Map.data[index]['VMapQ'])
                self.statsTree.set('{Gene}',column='Value',value=self.c.Map.data[index]['Gene'])
                self.statsTree.set('{Inside Gene}',column='Value',value=self.c.Map.data[index]['InsideGene'])
                self.statsTree.set('{Direction}',column='Value',value=self.c.Map.data[index]['GeneDirection'])
                self.statsTree.set('{Distance To Gene}',column='Value',value=self.c.Map.data[index]['DistanceToGene'])
                self.statsTree.set('{Focus Region}',column='Value',value=self.c.Map.data[index]['Focus'])   
                viralIndexStart='1.'+str(self.c.Map.data[index]['ViralLocalCords'][0]-1)
                viralIndexStop='1.'+str(self.c.Map.data[index]['ViralLocalCords'][1])
                self.seqBox.tag_add('Virus',viralIndexStart, viralIndexStop)
                HostIndexStart='1.'+str(self.c.Map.data[index]['HostLocalCords'][0]-1)
                HostIndexStop='1.'+str(self.c.Map.data[index]['HostLocalCords'][1])
                self.seqBox.tag_add('Host',HostIndexStart, HostIndexStop)
                if self.c.Map.data[index]['Overlap']>0:
                    if self.c.Map.data[index]['HostFirst']:
                        overlapIndexStop=HostIndexStop
                        overlapIndexStart='1.'+str(self.c.Map.data[index]['HostLocalCords'][1]-self.c.Map.data[index]['Overlap'])
                    else: 
                        overlapIndexStop=viralIndexStop
                        overlapIndexStart='1.'+str(self.c.Map.data[index]['ViralLocalCords'][1]-self.c.Map.data[index]['Overlap'])
                    self.seqBox.tag_add('Overlap',overlapIndexStart,overlapIndexStop)
            except IndexError:
                self.printToLog('Index Out of Range: Please Refresh List')
                
    def listRedraw(self):
        try:
            len(self.c.Map.data)
            GO=True
        except AttributeError:
            self.printToLog('Please do not apply filteres until after data has been processed')
            self.resetFilters()
            GO=False
        if GO:
            self.listBox1.delete(0,END)
            self.filteredReroute=[]
            if self.otempFilter.get()==1 or self.olenFilter.get()==1 or self.htempFilter.get()==1 or self.hlenFilter.get()==1 or self.vtempFilter.get()==1 or self.vlenFilter.get()==1:
                self.filtered=True
            else:
                self.filtered=False
            if self.filtered:
                for i in range(0,len(self.c.Map.data)):
                    stop=False    
                    if self.otempFilter.get()==1:
                        try:
                            if self.useBasic:
                                temp=float(self.c.Map.data[i]['OverlapTM'])
                            else:
                                temp=float(self.c.Map.data[i]['OverlapTMAdjusted'])
                            if temp>float(self.c.otempFilter): ##switch < to a > for final code
                                stop=True
                        except ValueError:
                            stop=True
                    if self.olenFilter.get()==1:
                        try:
                            temp=float(self.c.Map.data[i]['Overlap'])
                            if temp>float(self.c.olenFilter):   ##switch < to a > for final code
                                stop=True
                        except ValueError:
                            stop=True
                    if self.htempFilter.get()==1:
                        try:
                            if self.useBasic:
                                temp=float(self.c.Map.data[i]['HTM'])
                            else:
                                temp=float(self.c.Map.data[i]['HTMAdjusted'])
                            if temp<float(self.c.htempFilter):
                                stop=True
                        except ValueError:
                            stop=True
                    if self.hlenFilter.get()==1:
                        try:
                            temp=float(self.c.Map.data[i]['Hlength'])
                            if temp<float(self.c.hlenFilter):
                                stop=True
                        except ValueError:
                            stop=True
                    if self.vtempFilter.get()==1:
                        try:
                            if self.useBasic:
                                temp=float(self.c.Map.data[i]['VTM'])
                            else:
                                temp=float(self.c.Map.data[i]['VTMAdjusted'])
                            if temp<float(self.c.vtempFilter):
                                stop=True
                        except ValueError:
                            stop=True
                    if self.vlenFilter:
                        try:
                            temp=float(self.c.Map.data[i]['Vlength'])
                            if temp<float(self.c.vlenFilter):
                                stop=True
                        except ValueError:
                            stop=True
                    if not stop:
                        #print ('adding ',i,self.c.Map.data[i]['Index'],self.c.Map.data[i]['Overlap'])
                        self.filteredReroute.append(i)
                        name=self.c.Map.data[i]['ReadName']
                        self.listBox1.insert(END,name)
            else:
                for i in range(0,len(self.c.Map.data)):
                    name=self.c.Map.data[i]['ReadName']
                    self.listBox1.insert(END,name)
    
    
    def loadAlignment(self):
        if self.loadAlignmentBoolVar.get()==1:
            self.printToLog('Loading prexisting alignments, if any')
            self.c.loadAlignments=True
        else:
            self.printToLog('Not loading prexisting alignments')
            self.c.loadAlignments=False
    def changePrompting(self):
        if self.autoModeVar.get()==1:
            self.printToLog('Prompting Enabled')
            self.c.autoMode=False
        else:
            self.printToLog('Prompting Disabled')
            self.c.autoMode=True
            
    
    def getReads(self):
        readNames=self.c.getReads()
        if readNames=='break':
            self.STOP=True
            return
        temp=''
        if self.c.folderMode==False:
            for i in range (0,len(readNames)):
                if i<len(readNames)-1:
                    temp=temp+readNames[i]+'\n'
                else:
                    temp=temp+readNames[i]
            self.changeLabel(self.fastqBox,temp)
        else:
            self.changeLabel(self.fastqBox,readNames)
        self.STOP=False
        
    def switchRunMode(self):
        if self.c.folderMode:
            self.editmenu.entryconfig(2,label='Directory Mode')
            self.c.folderMode=False
            self.changeLabel(self.label1,'Fastq File(s):')
            self.changeLabel(self.fastqBox,'')
            self.printToLog('Mode: Single Run')
        else:
            self.editmenu.entryconfig(2,label='Single Run Mode')
            self.c.folderMode=True
            self.changeLabel(self.label1,'Fastq Directory:')
            self.changeLabel(self.fastqBox,'')
            self.printToLog('Mode: Directory Run')
            
#    def switchAutoMode(self):            
#        if self.c.autoMode:
#            self.autoBttn.config(text='Turn prompting off')
#            self.c.autoMode=False
#            self.printToLog('Prompting OFF')
#        else:
#            self.autoBttn.config(text='Turn prompting on')
#            self.c.autoMode=True
#            self.printToLog('Prompting ON')
            
    def changeCores(self):
        self.c.coreOption=int(self.cpuIntVar.get())
        self.printToLog('Using '+str(self.cpuIntVar.get())+' CPU cores')
        
    def setBT2Folder(self):
        temp=filedialog.askdirectory(title='Select Bowtie2 Root Directory',initialdir=self.c.workingDirectory)
        if temp:
            self.c.Bowtie2Folder=temp
            self.printToLog('Bowtie2 Folder changed to:\n'+self.c.Bowtie2Folder)
            self.changeLabel(self.bt2Text,self.c.Bowtie2Folder)
    
    def setOutputDir(self):
        temp=filedialog.askdirectory(title='Select Output Directory',initialdir=self.c.workingDirectory)
        if temp:
            self.c.outDir=temp
            self.printToLog('Output Directory Selected:\n'+self.c.outDir)
            self.changeLabel(self.out,self.c.outDir)
            
    def setViralRefFa(self):
        temp=filedialog.askopenfilename(title='Select Viral Reference Fa',initialdir=self.c.ViralRefFolder)
        if temp:
            self.c.ViralRefFa=temp
            self.c.ViralRefFolder=os.path.dirname(self.c.ViralRefFa)
            self.changeLabel(self.vrf,self.c.ViralRefFa)
            self.changeLabel(self.vdd,self.c.ViralRefFolder)
            self.printToLog('Viral Reference .fa set to:\n'+self.c.ViralRefFa)
    
    def setHostGTF(self):
        temp=filedialog.askopenfilename(title='Select Host GTF',initialdir=self.c.HostRefFolder)
        if temp:
            self.c.HostGTF=temp
            self.changeLabel(self.hgtf,self.c.HostGTF)
            self.printToLog('Host GTF set to:\n'+self.c.HostGTF)
    
    def setHostRefFa(self):
        temp=filedialog.askopenfilename(title='Select Host Reference Fa',initialdir=self.c.HostRefFolder)
        if temp:
            self.c.HostRefFa=temp
            self.c.HostRefFolder=os.path.dirname(self.c.HostRefFa)    
            self.changeLabel(self.hrf,self.c.HostRefFa)
            self.changeLabel(self.hdd,self.c.HostRefFolder)
            self.printToLog('Host Reference .fa set to:\n'+self.c.HostRefFa) 
    
    def setHostRefFolder(self):
        temp=filedialog.askdirectory(title='Select Host Reference Folder',initialdir=self.c.workingDirectory)
        if temp:
            self.c.HostRefFolder=temp
            self.printToLog('Host Reference Folder set to:\n'+self.c.HostRefFolder)
            self.changeLabel(self.hdd,self.c.HostRefFolder)
    
    def setViralRefFolder(self):
        temp=filedialog.askdirectory(title='Select Viral Reference Folder',initialdir=self.c.workingDirectory)
        if temp:
            self.c.ViralRefFolder=temp
            self.printToLog('Viral Reference Folder set to:\n'+self.c.ViralRefFolder)
            self.changeLabel(self.vdd,self.c.ViralRefFolder)
        
        
    def changeLabel(self,label,message):
        label.configure(state=NORMAL)
        label.delete(1.0,END)
        label.insert(INSERT,message)
        label.configure(state=DISABLED)
        
    def changeBttnText(self,bttn,mytext):
        bttn.config(text=mytext)
        
        
    def changeLabelFree(self,label,message):
        label.configure(state=NORMAL)
        label.delete(1.0,END)
        label.insert(INSERT,message)
    def noReturn(self,x):
        return 'break'
    def newWindow(self):
#        NewWin=tki.Toplevel(self.master)
#        NewWin.title('Location Options')
#        NewWin.geometry('400x600')
#        NewWin.config(state='disable')
        self.NewWin.deiconify()
#        def quit_win():
#            NewWin.destroy()
#            NewWin.config(state='normal')       
#        NewWin.protocol('WM_DELETE_WINDOW',quit_win)
    
    def optionsWindow(self):
        self.OptionsWin.deiconify()
    

#    def toggle_text(self):
#    
#        if self.bttn3['text'] == "Hi":
#        # switch to Goodbye
#            self.bttn3["text"] = "Goodbye"
#        else:
#        # reset to Hi
#            self.bttn3["text"] = "Hi"   
#        
#        self.printToLog('hi')
        
    def printToLog(self,message):
        self.log.configure(state=NORMAL)
        self.log.insert(END,message+'\n')
        self.log.configure(state=DISABLED)
        self.log.see(END)
        self.c.logger.append(message)





c=Core()
