# Welcome to PathCom.  This program
# is intended to provide estimates of
# whether certain disassembly reactions
# are compatible with ChIP data.

from pylab import *

def Mechs(Assoc):        
        def init_seq (size, alist=[]):

            if size == 0: return [""]

            seq = []

            for base in alist:
                for ele in init_seq(size-1, alist):
                    if base not in ele: seq.append( base + ele )

            return seq
            
        BASE = []
        for pro in Assoc:
            BASE.append(pro)
        Dissoc = init_seq(len(BASE), BASE)
        fp5 = open("Dissociations.txt", 'w')
        for i in Dissoc:
            fp5.write(str(Dissoc.index(i)+1) + '\t' + str(i) + '\n')
        return Dissoc, BASE


def Find_Comps(Assoc, Dissoc, p, fp3, BASE):
        no_of = len(Assoc)
        factorial = 1
        for az in range(1, no_of+1):
            factorial*=az
        
        for q in range(1, factorial+1): #!!!!!!!
            fp3.write('Mech ' + str(q) + '\t')
        fp3.write('\n')   

        Occ = {}
        TxtPos = {}
        pos = 0
        p0 = p[0]
        p1 = p0.split('\t')
        if p1[-1].strip() != 'Cluster':
            print "Label the cluster column 'Cluster'"
            sys.exit()
        p1 = p1[0:len(p1)-1]
        
        for yyy in p1:
            Occ[yyy[0]] = 0
            TxtPos[yyy[0]] = pos
            pos+=1
                
        for line in p[1:]:
            for yy in Assoc:
                try:
                    Occ[yy] = float(line.split('\t')[TxtPos[yy]])
                    if Occ[yy]<0:
                        print "Cannot have negative occupancies"
                        sys.exit()
                except ValueError:
                    print "All occupancies must be numbers, or there are missing occupancy values, or you misplaced the column with cluster labels, which must come after the occupancy columns"
                    print "Follow the exact format shown in the tutorial."
                    sys.exit()
            Combo = str(line.split('\t')[len(Assoc)])

            Com_Mechs = []
            Incom_Mechs = []

            BASE_short = BASE[1:len(BASE)-1]
            Mech = []
            COMPATIBLE = True
            for k in Dissoc:
                Mech.append(Assoc)
                Mech.append(k)
                COMPATIBLE = True

                for i in BASE:
                    for j in BASE:                        
                        if (j==i): pass
                        else:
                            if ((Mech[0].find(i) < Mech[0].find(j)) and (Mech[1].find(i) > Mech[1].find(j))):
                                if (Occ[i] <= Occ[j]): COMPATIBLE = False

                if COMPATIBLE == True:
                    for w in BASE_short:
                        for m in BASE:
                            for n in BASE:
                                if (m==n) or (m==w) or (n==w): pass
                                else:
                                    if (Occ[w] > (Occ[m] + Occ[n])) and (Mech[0].find(w) > Mech[0].find(m)) and (Mech[0].find(w) < Mech[0].find(n)) and (Mech[1].find(w) > Mech[1].find(m)) and (Mech[1].find(w) < Mech[1].find(n)):
                                        COMPATIBLE = False
                
                if COMPATIBLE == True: Com_Mechs.append(Mech[1])
                elif COMPATIBLE == False: Incom_Mechs.append(Mech[1])

                Mech = []
                COMPATIBLE = True

            fp3.write(str(Combo.strip()) + '\t')
            for counter in range(1, factorial+1):
                try:
                    Com_Mechs.index(Dissoc[counter-1])
                    fp3.write('-1' + '\t')
                except ValueError:
                    fp3.write('0' + '\t')
            fp3.write('\n')
        print "See your results in the text file CompatibilityTable.txt"
        sys.exit()


def GUI_Exec():
    fp3 = open("CompatibilityTable.txt", 'w')
    fp3.write('Cluster' + '\t')
    
    try:
        fp2 = open("Text2.txt",'r')
    except IOError:
        print "Input file must be called Text2.txt"
        sys.exit()
    p = fp2.readlines()
    
    Header = p[0].split('\t')
    Header1 = Header[0:len(Header)-1]
    Assoc = ''
    PosNo = {}
    for jj in Header1:
        try:
            PosNo[int(jj[1:])]
            print "Two proteins cannot have the same number in their association order"
            sys.exit()
        except KeyError:
            try:
                PosNo[int(jj[1:])] = jj[0]
            except ValueError:
                print "Protein identifiers must be only one character long"
                sys.exit()
    
    keys = PosNo.keys()
    keys.sort()
    
    for iii in keys:
        Assoc += PosNo[iii]

    Dissoc, BASE = Mechs(Assoc)
    Find_Comps(Assoc, Dissoc, p, fp3, BASE)

GUI_Exec()