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

## compares assignment reliability with erroneous coordinate input
## forks 10 (distortions x program types) processes (run on cluster)

import os
from Log import LogFH
import string

#from PSSDParser import PSSD
#from DSSPParser import DSSP
from Comparisons import Common, PSSD, DSSP, PSEA

class TestParm:
    logfile = 'reliable-log'
    outfile = 'reliable-out'
    pdbdir = '../../dat/x/'
    noisepdbdir = '../../dat/y/'

    PSSDdir = '../../dat/x.pssd/'
    PSSDNoisedir = '../../dat/y.pssd/'
    pssd = [PSSD, PSSDdir, PSSDNoisedir, '.ssd']

    DSSPdir = '../../dat/x.dssp/'
    DSSPNoisedir = '../../dat/y.dssp/'
    dssp = [DSSP, DSSPdir, DSSPNoisedir, '.dssp']

    PSEAdir = '../../dat/x.psea/'
    PSEANoisedir = '../../dat/y.psea/'
    psea = [PSEA, PSEAdir, PSEANoisedir, '.sea']

    maxdistorsions = 10
    maxversions = 100

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

    PSSDdir = '../../dat/cull100.pssd/'
    PSSDNoisedir = '/mnt/e12/data/indraneel/PDBNoise.pssd/'
    pssd = [PSSD, PSSDdir, PSSDNoisedir, '.ssd']

    DSSPdir = '../../dat/cull100.dssp/'
    DSSPNoisedir = '/mnt/e12/data/indraneel/PDBNoise.dssp/'
    dssp = [DSSP, DSSPdir, DSSPNoisedir, '.dssp']

    PSEAdir = '../../dat/cull100.psea/'
    PSEANoisedir = '/mnt/e12/data/indraneel/PDBNoise.psea/'
    psea = [PSEA, PSEAdir, PSEANoisedir, '.sea']

    maxdistorsions = 10
    maxversions = 100

class Runner:
    def __init__(self, parm):
        self.parm = parm
        self.logger = LogFH(parm.logfile, mode='w')
        if os.path.isfile(parm.outfile):
            os.unlink(parm.outfile)
        self.cmptypes = []
        
    def set_cmptype(self, Type):
        self.cmptypes.append(Type)
        
    def compare(self, cmptype, itn, ofh):
        common = Common(self.logger, self.parm.outfile)
        [TypeClass, TypeInDir, TypeNoiseInDir, TypeFileExt] = cmptype
        fileList = os.listdir(TypeInDir)
        for (i, fn) in enumerate(fileList):
            fileID = string.join(fn.split('.')[:-1], '')
            #baseTypeFname = TypeInDir+fileID+TypeFileExt
            baseTypeFname = self.parm.dssp[1]+fileID+'.dssp'
            firstNoise = TypeNoiseInDir+fileID+'_1_0'+TypeFileExt
            if not os.path.isfile(firstNoise):
                continue
            #baseInstance = TypeClass(self.logger)
	    baseInstance = DSSP(self.logger)
            if baseInstance.typeclass == 'PSEA':
                if len(fileID) == 4: chainID = ' '
                elif len(fileID) == 6: chainID = fileID[-1]
                baseInstance.setChain(chainID)
                baseInstance.setPDBDir(self.parm.pdbdir)
            if (baseInstance.store(baseTypeFname) == 'Err'): continue
            for n in range(self.parm.maxversions):
                noiseTypeFname = TypeNoiseInDir+fileID+ \
                                 '_'+str(itn)+'_'+str(n)+TypeFileExt
                noiseInstance = TypeClass(self.logger)
                if noiseInstance.typeclass == 'PSEA':
                    if len(fileID) == 4: chainID = ' '
                    elif len(fileID) == 6: chainID = fileID[-1]
                    noiseInstance.setChain(chainID)
                    noiseInstance.setPDBDir(self.parm.noisepdbdir)
                if (noiseInstance.store(noiseTypeFname) == 'Err'):
                    continue
                self.logger.log(TypeFileExt+'\t'+str(itn)+'\t'+ \
                                str(i)+'\t'+str(n)+'\t'+fileID)
                common.compareReliabilityFound(baseInstance, noiseInstance)
        handle = "%2.1f" % (itn*0.2) +'\t'+TypeFileExt
        common.setHandle(handle)
        common.reportReliability(ofh)

    def forkJobs(self, cmptype, 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(cmptype, itn, ofh)
            os._exit(0)
        else:
            self.logger.log(cmptype[-1]+' '+str(itn)+' (cid: '+str(newpid)+')')
            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 cmptype in self.cmptypes:
            for itn in range(1,self.parm.maxdistorsions+1):
                self.forkJobs(cmptype, itn, ofh)
        while len(self.children.keys()):
            pid,stat = os.wait()
            del self.children[pid]
        ofh.close()
        self.logger.close()
        
if __name__ == '__main__':
    parm = Parm()
    #parm = TestParm()
    runner = Runner(parm)
    #runner.set_cmptype(parm.dssp)
    #runner.set_cmptype(parm.pssd)
    runner.set_cmptype(parm.psea)
    runner.runall(processes=20)
