1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 """
26 Calculate Contact Area Difference (CAD) with ICMBrowser.
27 """
28
29 import tempfile, re
30
31 from Biskit import Executor, TemplateError
32
33 import Biskit.tools as T
34
35
37 pass
38
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
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
124
125 model['chain_id'] = [''] * len( model )
126 model.writePdb( f_out )
127
128
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
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
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
179 """
180 Overrides Executor method
181 """
182 return self.error is None
183
184
186 """
187 Overrides Executor method
188 """
189 Executor.finish( self )
190 self.result = self.parse_icm( self.output )
191
192
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
227
228 import Biskit.test as BT
229
230 -class Test(BT.BiskitTest):
231 """Test class"""
232
233 TAGS = [ BT.EXE ]
234
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