## Biskit, a toolkit for the manipulation of macromolecular structures
## Copyright (C) 2004-2012 Raik Gruenberg & Johan Leckner
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 3 of the
## License, or any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## General Public License for more details.
## You find a copy of the GNU General Public License in the file
## license.txt along with this program; if not, write to the Free
## Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
## $Revision: 1086 $
## last $Date: 2012-02-23 19:10:59 -0500 (Thu, 23 Feb 2012) $
## last $Author: graik $
Interface to Xplor
import tempfile
from time import time
import os
import settings
import Biskit.tools as T
from Biskit.Errors import BiskitError
from Biskit.Executor import Executor, RunError
class XplorerError( BiskitError ):
class Xplorer(Executor):
    Prepare and run a xplor job.
    @see: L{Executor} for detailed documentation!
    @note: Command configuration in: biskit/Biskit/data/defaults/exe_xplor.dat
    def __init__( self, template, pipes=None, **params):
        Create an Executor instance for XPlor jobs. The only argument required
        is a template for the control script passed to Xplor. As usual, any
        keyword=value pairs given to this constructor, can be used to
        substitute place holders in the template (see L{Executor}!).
        @param template: template for Xplor input file. This can be the
                         template itself or the path to a file containing it.
        @type  template: str
        @param pipes: push input script directly through a pipe rather
                      than writing it to disc; If != None, this option
                      overrides the default setting from exe_xplor.dat.
                      The default in exe_xplor is pipes = 1 (True).
        @type  pipes: 1|0 or bool
        @param kw: additional key=value parameters for Executor
        for example::
          debug    - 0|1, keep all temporary files (default: 0)
          verbose  - 0|1, print progress messages to log (log != STDOUT)
          node     - str, host for calculation (None->local)
                          (default: None)
          nice     - int, nice level (default: 0)
          log      - Biskit.LogFile, program log (None->STOUT) (default: None)
        Executor.__init__( self, 'xplor', template=template, **params )
        if pipes is not None:
            self.exe.pipes = pipes
        #: will contain copy of Xplor log file after run finished
        self.logLines = None
    def version( self ):
        """Version of class.
        @return: version
        @rtype: str
        return Executor.version(self) + '/ Xplorer $Revision: 1086 $'
    def postProcess( self ):
        Parse xplor log into self.logLines
        self.logLines = open( self.f_out ).readlines()
    def isFailed( self ):
        Calculation completion check.
        @return: if xplor died
        @rtype: 1
        return self.logLines == None or \
               self.logLines[-1].find("X-PLOR: exit time") == -1
    def fail( self ):
        called after aborted calculation, override!
        @raise RunError: if Xplor terminated with an error
        s = ''
            s += ''.join( self.logLines[-7:] )
        raise RunError, 'Xplor terminated with an error:\n' + s
    def saveXLog( self, fname ):
        Save the content of the XPlor log file to a new file.
        @param fname: target file name
        @type  fname: str
        @raise XPlorerError: if logLines is empty (Xplor hasn't been run)
        if not self.logLines:
            raise XplorerError('Xplor log file is (yet) empty.')
        f = open( T.absfile(fname), 'w')
        f.writelines( self.logLines )
##  TESTING        
import Biskit.test as BT
class Test(BT.BiskitTest):
    TAGS = [ BT.EXE ]
    inp = """
!! short test  minimzation 
! ------------------------------------------------------------
! Place holders to be inserted by Python script
! ------------------------------------------------------------
evaluate ($ligandpsf = "%(lig_psf)s")
evaluate ($ligandpdb = "%(lig_pdb)s")
evaluate ($param19 = "%(param19)s" )
evaluate ($lig_out = "%(lig_out)s" )
! -------------------------------------
! read psf and pdb files for the ligand
! -------------------------------------
structure @@$ligandpsf end
coor @@$ligandpdb
delete selection= (resname TIP3) end
! ------------------
! set toplogies etc.
! ------------------
! ------------------------------------------------------------
! minimize
! ------------------------------------------------------------
flags exclude * include bond angle impr elec end
minimize powell nstep=10            end
! ---------------------------------------------------
! write minimized PDBs
! ---------------------------------------------------
write coor output= $lig_out end
    def prepare(self):
        self.dir_out = tempfile.mkdtemp( '_test_Xplorer' )
        ## write a test template inp file to disc
        f = open( self.dir_out +'/test.inp', 'w')
        f.writelines( self.inp )
    def test_Xplorer( self ):
        """Xplorer test"""
        ## input template variables
        param = T.dataRoot() + '/xplor/toppar/param19.pro'
        pdb_out = self.dir_out +'/lig.pdb'
        log_out = self.dir_out +'/test.out'
        pdb_in = T.testRoot() + '/lig/1A19.pdb' 
        psf_in = T.testRoot() + '/lig/1A19.psf'
        self.x = Xplorer( self.dir_out +'/test.inp',
                     xout = log_out,
                     verbose = self.local,
                     lig_psf = psf_in,
                     lig_pdb = pdb_in,
                     param19 = param,
                     lig_out = pdb_out )
        if self.local:
            print """
The minimized structure and the X-Plor log file
have been written to %s and %s, respectively
            """ % (pdb_out, log_out)
            print """See x.logLines for the complete xplor log file!"""
    def cleanUp(self):
        T.tryRemove( self.dir_out, tree=1 )
if __name__ == '__main__':