Package Biskit :: Module IcmCad
[hide private]
[frames] | no frames]

Source Code for Module Biskit.IcmCad

  1  ## 
  2  ## Biskit, a toolkit for the manipulation of macromolecular structures 
  3  ## Copyright (C) 2004-2006 Raik Gruenberg & Johan Leckner 
  4  ## 
  5  ## This program is free software; you can redistribute it and/or 
  6  ## modify it under the terms of the GNU General Public License as 
  7  ## published by the Free Software Foundation; either version 2 of the 
  8  ## License, or any later version. 
  9  ## 
 10  ## This program is distributed in the hope that it will be useful, 
 11  ## but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 13  ## General Public License for more details. 
 14  ## 
 15  ## You find a copy of the GNU General Public License in the file 
 16  ## license.txt along with this program; if not, write to the Free 
 17  ## Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 18  ## 
 19  ## 
 20   
 21  ## last $Author: graik $ 
 22  ## last $Date: 2007/04/06 10:55:55 $ 
 23  ## $Revision: 2.10 $ 
 24   
 25  """ 
 26  Calculate Contact Area Difference (CAD) with ICMBrowser. 
 27  """ 
 28   
 29  import tempfile, re 
 30   
 31  from Biskit import Executor, TemplateError 
 32  ## import Biskit.settings as S 
 33  import Biskit.tools as T 
 34   
 35   
36 -class IcmCadError( Exception ):
37 pass
38
39 -class IcmCad( Executor ):
40 """ 41 CAD calculation 42 =============== 43 Calculate ContactAreaDifference between a reference structure and one or 44 many other structures. Described in Abagyan and Totrov, 1997. 45 46 Example usage 47 ------------- 48 >>> x = IcmCad( ref_model, [ m1, m2 ], verbose=1 ) 49 >>> result = x.run() 50 51 IcmCad writes temporary pdb files, calls the icmbrowser program, 52 and parses the result from the STDOUT pipe. The result values are then in 53 x.result (if x is the IcmCad instance). As recommended, the value 54 is multiplied by factor 1.8 which puts it into a range from 0 (identical) 55 to 100 (completely different). This scaling is not recommended for 56 docking solutions. 57 58 @todo: Not speed-optimized! 59 - it should be possible to pipe the PDB-files directly into 60 icmbrowser instead of writing temporary files to disc 61 - Abagyan and Totrov mention a c-library available -- the best 62 solution would hence be to wrap this c-library in python... 63 64 @note: Command configuration in: biskit/external/defaults/exe_icmbrowser.da 65 """ 66 67 inp_head = \ 68 """ 69 call _startup 70 read pdb unix cat \"%(f_ref)s\" 71 copy a_ \"mol1\" 72 """ 73 inp_tail = "quit\n" 74 75 inp_calc = \ 76 """ 77 read pdb unix cat \"%(f_pdb)s\" 78 copy a_ \"mol2\" delete 79 1.8*Cad( a_mol1./* a_mol2./* ) 80 """ 81
82 - def __init__( self, ref_model, models, **kw ):
83 """ 84 @param ref_model: reference 85 @type ref_model: PDBModel 86 @param models: structures to be compared with reference 87 @type models: [PDBModel] 88 89 @param kw: additional key=value parameters for Executor: 90 @type kw: key=value pairs 91 :: 92 debug - 0|1, keep all temporary files (default: 0) 93 verbose - 0|1, print progress messages to log (log != STDOUT) 94 node - str, host for calculation (None->local) NOT TESTED 95 (default: None) 96 nice - int, nice level (default: 0) 97 log - Biskit.LogFile, program log (None->STOUT) (default: None) 98 """ 99 Executor.__init__( self, 'icmbrowser', template=self.inp_head, **kw ) 100 101 self.f_ref = tempfile.mktemp('_icmcad_ref.pdb') 102 self.f_pdb = tempfile.mktemp('_icmcad_%i.pdb') 103 104 self.ref_model = ref_model 105 self.models = models 106 107 if not isinstance( self.models, list ): 108 self.models = [ self.models ]
109 110
111 - def __prepareModel( self, model, f_out ):
112 """ 113 Prepare a model that ICM likes. 114 - consecutive numbering of residues 115 - no chain identifier 116 117 @param model: model 118 @type model: PDBModel 119 @param f_out: name of pdb file to write 120 @type f_out: str 121 """ 122 model.renumberResidues() 123 #for a in model.getAtoms(): 124 #a['chain_id']='' 125 model['chain_id'] = [''] * len( model ) 126 model.writePdb( f_out )
127 128
129 - def prepare( self ):
130 """ 131 Overrides Executor method. 132 """ 133 self.__prepareModel( self.ref_model, self.f_ref ) 134 135 for i,m in enumerate( self.models ): 136 137 self.__prepareModel( m, self.f_pdb % i )
138 139
140 - def cleanup( self ):
141 """ 142 Tidy up the mess you created. 143 """ 144 Executor.cleanup( self ) 145 146 if not self.debug: 147 T.tryRemove( self.f_ref ) 148 149 for i in range( len(self.models)): 150 T.tryRemove( self.f_pdb % i )
151 152
153 - def parse_icm( self, output ):
154 """ 155 Extract CAD value from icm output. 156 157 @param output: STDOUT result of ICM run 158 @type output: [str] 159 160 @return: ICM result 161 @rtype: [str] 162 163 @raise IcmCadError: if no result 164 """ 165 lines = output.split('\n') 166 if len(lines) == 0: 167 raise IcmCadError, 'no ICM result' 168 169 r = [] 170 171 for i, l in enumerate(lines): 172 if re.match('.+1.8\*Cad.+', l ): 173 r.append( float( lines[i+1].strip() ) ) 174 175 return r
176 177
178 - def isFailed( self ):
179 """ 180 Overrides Executor method 181 """ 182 return self.error is None
183 184
185 - def finish( self ):
186 """ 187 Overrides Executor method 188 """ 189 Executor.finish( self ) 190 self.result = self.parse_icm( self.output )
191 192
193 - def generateInp(self):
194 """ 195 Has to be overridden to support head / segment / tail structure. 196 Replace formatstr place holders in inp by fields of this class. 197 198 @return: ICM input script 199 @rtype: [str] 200 201 @raise TemplateError: if template not found 202 """ 203 try: 204 s = self.inp_head % self.__dict__ 205 206 for i,m in enumerate( self.models ): 207 s += self.inp_calc % { 'f_pdb' : self.f_pdb % i } 208 209 s += self.inp_tail 210 211 return s 212 213 except KeyError, why: 214 s = "Unknown option/place holder in template file." 215 s += "\n Template asked for a option called " + str( why[0] ) 216 raise TemplateError, s 217 218 except Exception, why: 219 s = "Error while creating template file." 220 s += "\n why: " + str( why ) 221 s += "\n Error:\n " + T.lastError() 222 raise TemplateError, s
223 224 225 ############# 226 ## TESTING 227 ############# 228 import Biskit.test as BT 229
230 -class Test(BT.BiskitTest):
231 """Test class""" 232 233 TAGS = [ BT.EXE ] 234
235 - def test_IcmCad( self ):
236 """IcmCad test""" 237 from Biskit import PDBModel 238 239 if self.local: print 'Loading PDB...' 240 241 self.f = T.testRoot() + '/lig/1A19.pdb' 242 self.m1 = PDBModel(self.f) 243 self.m1 = self.m1.compress( self.m1.maskProtein() ) 244 245 self.ms = [] 246 247 self.lig_traj = T.Load( T.testRoot() + '/lig_pcr_00/traj.dat' ) 248 for m in self.lig_traj[:3]: 249 m = m.compress( m.maskProtein() ) 250 self.ms.append(m) 251 252 if self.local: print 'Starting ICM' 253 self.x = IcmCad( self.m1, self.ms, debug=self.DEBUG, 254 verbose=self.local ) 255 256 if self.local: 257 print 'Running' 258 259 self.r = self.x.run() 260 261 if self.local: 262 print "Result: ", self.r 263 264 self.assertEqual( self.r, [8.8603529999999999, 9.0315890000000003, 265 8.5055429999999994] )
266 267 268 269 if __name__ == '__main__': 270 271 BT.localTest() 272