# $CVSHeader: pal8e/src/PSEAReliability.py,v 1.2 2005/02/15 01:10:26 indraneel Rel $

import os
import string
from Bin import Bin
from Sigma import Sigma

class Parm:
    logfile = 'reliable-log.psea'
    outfile = 'reliable-out.psea'
    pdbdir = '/mnt/e12/data/indraneel/cull100/'
    noisepdbdir = '/mnt/e12/data/indraneel/PDBNoise.psea/'

    PSEAdir = '../../dat/cull100.psea/'
    PSEANoisedir = '/mnt/e12/data/indraneel/PDBNoise.psea/'

    maxdistorsions = 10
    maxversions = 100

class PSEAReliability:
    def __init__(self, parm):
        self.parm = parm
        self.resPercentFound = []
        self.resPercentFoundE = []
        self.resPercentFoundH = []
        self.resBasePercentFoundE = []
        self.resBasePercentFoundH = []

    def getLine(self, fname):
        fh = file(fname)
        psealines = fh.readlines()
        fh.close()
        if len(psealines) == 0: return ''
        for (i, line) in enumerate(psealines):
            if line[:6] == '>p-sea': break
        psealines = psealines[i+1:]
        psealines = map(lambda x: x[:-1], psealines)
        psealine = string.join(psealines, '')
        return psealine

    def testReliability(self, fnameBase, fnameNoise):
        baseLine = self.getLine(fnameBase)
        noiseLine = self.getLine(fnameNoise)
        if len(baseLine) != len(noiseLine):
            return None
        total = len(baseLine)
        if not total: return None
        match = 0
        baseE = 0
        baseH = 0
        testE = 0
        testH = 0
        for (b, n) in zip(baseLine, noiseLine):
            if b == n: match += 1
            if b == 'b': baseE += 1
            elif b == 'a': baseH += 1
            if n == 'b': testE += 1
            elif n == 'a': testH += 1
        self.resPercentFound.append(float(match)/total*100)
        self.resPercentFoundE.append(float(testE)/total*100)
        self.resPercentFoundH.append(float(testH)/total*100)
        self.resBasePercentFoundE.append(float(baseE)/total*100)
        self.resBasePercentFoundH.append(float(baseH)/total*100)

    def reportReliability(self, fh=None, handle=''):
        resPercentFound = self.resPercentFound
        items = len(resPercentFound)
        total = sum(resPercentFound)
        mean = total/items
        sigma = Sigma(resPercentFound)
        s = sigma.sigma()
        line = "%7.2f" % (mean)+'\t'+ "%6.2f" % (s)+'\t'+handle
        line += '\t'+ "%7.2f" % (sum(self.resPercentFoundE)/items)
        line += '\t'+ "%7.2f" % (sum(self.resPercentFoundH)/items)
        line += '\t'+ "%7.2f" % (sum(self.resBasePercentFoundE)/items)
        line += '\t'+ "%7.2f" % (sum(self.resBasePercentFoundH)/items)
        line += '\n'
        if fh == None:
            fh=file(self.parm.outfile,'a', 1) # line buffered
            fh.write(line)
            fh.close()
        else: fh.write(line)

    def compare(self, itn, ofh):
        parm = self.parm
        TypeInDir = parm.PSEAdir
        TypeNoiseInDir = parm.PSEANoisedir
        TypeFileExt = '.sea'
        fileList = os.listdir(TypeInDir)
        for (i, fn) in enumerate(fileList):
            fileID = string.join(fn.split('.')[:-1], '')
            baseTypeFname = TypeInDir+fileID+TypeFileExt
            for n in range(self.parm.maxversions):
                noiseTypeFname = TypeNoiseInDir+fileID+ \
                                 '_'+str(itn)+'_'+str(n)+TypeFileExt
                self.testReliability(baseTypeFname, noiseTypeFname)
        handle = "%2.1f" % (itn*0.2) +'\t'+TypeFileExt
        self.reportReliability(ofh, handle)

    def forkJobs(self, itn, ofh):
        if len(self.children.keys()) > self.multiprocess:
            pid,stat = os.wait()
            del self.children[pid]
            
        newpid = os.fork()
        if newpid == 0:
            self.compare(itn, ofh)
            os._exit(0)
        else:
            self.children[newpid] = 1

    def runall(self, processes):
        self.children = {}
        self.multiprocess = processes
        ofh=file(self.parm.outfile,'w', 1) # line buffered
        line = '# mean\tsigma\titn\tprog\titnE\titnH\tbaseE\tbaseH\n'
        ofh.write(line)
        for itn in range(1,self.parm.maxdistorsions+1):
            self.forkJobs(itn, ofh)
        while len(self.children.keys()):
            pid,stat = os.wait()
            del self.children[pid]
        ofh.close()
        
if __name__ == '__main__':
    parm = Parm()
    psea = PSEAReliability(parm)
    psea.runall(processes=40)
    
