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 collect and manage information about a docking result
26 """
27
28 from Biskit import PCRModel, PDBModel, PDBDope, molUtils, mathUtils, StdLog, EHandler
29
30 from Biskit.Prosa2003 import Prosa2003
31
32 import Biskit.tools as t
33
34 import numpy.oldnumeric as N
35
36 from copy import deepcopy, copy
37 from numpy.oldnumeric import arraytype
38
39 from difflib import SequenceMatcher
40
42 pass
43
44
46 """
47 Manage receptor and ligand structure, store additional information,
48 calculate some properties.
49 """
50
51 - def __init__(self, rec_model=None,lig_model=None, ligMatrix=None,info={} ):
52 """
53 @param rec_model: model of original receptor conformation
54 @type rec_model: PDBModel OR PCRModel
55 @param lig_model: model of original ligand conformation
56 @type lig_model: PDBModel OR PCRModel
57 @param ligMatrix: Numeric array 4 by 4, ligand transformation matrix
58 @type ligMatrix: matrix
59 @param info: optional dictionary with additional infos
60 e.g. {'eshape':-123.3, 'rms':12.2 }
61 @type info: dict
62 """
63 self.rec_model = rec_model
64 self.lig_model = lig_model
65 self.lig_transformed = None
66 self.pw_dist = None
67
68 self.info = { 'date':t.dateSortString() }
69 self.info.update( info )
70
71 self.ligandMatrix = ligMatrix
72 if self.ligandMatrix == None:
73 self.ligandMatrix = N.array([ [1, 0, 0, 0],
74 [0, 1, 0, 0],
75 [0, 0, 1, 0],
76 [0, 0, 0, 1],], N.Float32)
77
78
79 self.contacts = None
80
81
82 self.initVersion = self.version()
83
84
86 """
87 Version of Dock.Complex
88
89 @return: version of class
90 @rtype: str
91 """
92 return 'Complex $Revision: 2.17 $'
93
94
96 """
97 Called before pickling.
98 """
99 self.slim()
100 return self.__dict__
101
102
104 """
105 @return: C.info[ key ]
106 @rtype: dict
107 """
108 return self.info[ key ]
109
110
113
114
117
118
120 return key in self.info
121
122
124 """
125 called for unpickling the object.
126 """
127 self.__dict__ = state
128 self.ligandMatrix = N.array( self.ligandMatrix,N.Float32 )
129
130 self.__defaults()
131
132
134 """
135 backwards compatibility to earlier pickled models
136 """
137 self.pw_dist = getattr( self, 'pw_dist', None )
138
139
141 """
142 Keys of info dictionary.
143
144 @return: list of keys
145 @rtype: [str]
146 """
147 return self.info.keys()
148
149
151 """
152 Check if info dictionary has key.
153
154 @param k: key to test
155 @type k: str
156
157 @return: dict has key
158 @rtype: 1|0
159 """
160 return self.info.has_key( k )
161
162
163 - def values( self, keys=[], default=None ):
164 """
165 Use::
166 values( keys=None, default=None ) -> list of info dict values
167
168 @param keys: give only values of these keys
169 @type keys: [str]
170 @param default: only used with keys!=[], default value for missing keys
171 @type default: any
172
173 @return: all values (default) or values of requested keys (ordered)
174 @rtype: [any]
175 """
176 if not keys:
177 return self.info.values()
178 return [ self.get( k, default ) for k in keys ]
179
180
181 - def get( self, key, default=None):
182 """
183 Use::
184 C.get(k[,default]) -> C.info[k] if C.info.has_key(k), else
185 default defaults to None.
186
187 @param key: key to call
188 @type key: str
189 @param default: default value if dictionary doesn't have key
190 (default: None)
191 @type default: any
192
193 @return: dictionary value of key OR else default
194 @rtype: any OR None
195 """
196 return self.info.get( key, default )
197
198
200 """
201 Return PCRModel object.
202
203 @return: receptor model
204 @rtype: PCRModel
205 """
206 return self.rec_model
207
208
209 - def lig(self, force=0, cache=1 ):
210 """
211 Return ligand structure transformed. Use cached object, if
212 available.
213
214 @param force: force new transformation (default: 0)
215 @type force: 1|0
216 @param cache: cache transformed model (default: 1)
217 @type cache: 1|0
218
219 @return: ligand model
220 @rtype: PCRModel
221 """
222 try:
223 lig = self.lig_transformed
224 except:
225 lig = None
226
227 if lig == None or force:
228
229 lig = self.lig_model.transform( *self.ligMatrix() )
230
231 if cache:
232 self.lig_transformed = lig
233
234 return lig
235
236
238 """
239 Model with both receptor and ligand.
240
241 @return: single PDBModel with first rec then lig
242 @rtype: PCRModel
243 """
244 return self.rec().concat( self.lig() )
245
246
248 """
249 Return transformation matrix to transform original Ligand
250 PCRModel into docked conformation.
251
252 @return: tuple with rotation and transformation matrix
253 @rtype: array, vector
254 """
255 a = self.ligandMatrix
256
257 return (a[0:3,0:3], a[0:3, 3])
258
259
261 """
262 Set a ligand translation/rotation matrix.
263
264 @param m: translation array 4x4 with rotation
265 @type m: array
266 """
267 self.ligandMatrix = m
268 self.lig_transformed = None
269
270
272 """
273 Return contents of the info dictionary.
274
275 @return: info dictionary
276 @rtype: dict
277 """
278 return self.info
279
280
282 """
283 Write transformed ligand to pdb file. Remove TER record for
284 xplor usage (unless removeTer!=0).
285
286 @param fname: output filename
287 @type fname: str
288 @param ter: option for how to treat the TER statement::
289 - 0, don't write any TER statements (default)
290 - 1, restore original TER statements
291 - 2, put TER between all detected chains
292 @type ter: 0|1|2
293 """
294 pdb = self.lig()
295 pdb.writePdb( t.absfile( fname ), ter )
296
297
299 """
300 Write receptor to pdb without TER statement (unless removeTer!=0).
301
302 @param fname: output file name
303 @type fname: str
304 @param ter: option for how to treat the TER statement::
305 - 0, don't write any TER statements (default)
306 - 1, restore original TER statements
307 - 2, put TER between all detected chains
308 @type ter: 0|1|2
309 """
310 self.rec().writePdb( t.absfile( fname), ter )
311
312
314 """
315 Write single pdb containing both receptor and ligand
316 separated by END but not TER (unless ter!=0).
317
318 @param fname: filename of pdb
319 @type fname: str
320 @param ter: option for how to treat the TER statement::
321 - 0, don't write any TER statements (default)
322 - 1, restore original TER statements
323 - 2, put TER between all detected chains
324 """
325 self.model().writePdb( t.absfile( fname ), ter )
326
327
329 """
330 Remove coordinates and atoms of ligand and receptor from memory,
331 if they can be restored from file, compress contact matrix.
332 @note: CALLED BEFORE PICKLING
333 """
334 self.lig_transformed = None
335 self.pw_dist = None
336
337
338
339 if 'matrix' in self.info:
340 del self.info['matrix']
341
342
343 if self.contacts != None and \
344 len(N.shape( self.contacts['result'] ) )==2:
345 m = self.contacts['result']
346 self.contacts['shape'] = N.shape( m )
347
348 self.contacts['result'] = N.nonzero( N.ravel( m ) ).astype(N.Int32)
349
350
371
372
390
391
407
408
426
427
429 """
430 fraction of atoms/residues that are involved in B{any} contacts
431 in both complexes.
432
433 @param cont: contact matrix
434 @type cont: matrix
435 @param contRef: reference contact matrix
436 @type contRef: matrix
437
438 @return: (fractRec, fractLig), fraction of atoms/residues that
439 are involved in any contacts in both complexes
440 @rtype: (float, float)
441
442 """
443 lig, ligRef = N.clip( N.sum(cont),0,1), N.clip( N.sum(contRef), 0,1)
444 rec = N.clip( N.sum(cont, 1),0,1)
445 recRef = N.clip( N.sum(contRef, 1), 0,1)
446
447 fLig = N.sum( N.logical_and( lig, ligRef )) *1./ N.sum( ligRef )
448 fRec = N.sum( N.logical_and( rec, recRef )) *1./ N.sum( recRef )
449
450 return (fRec, fLig)
451
452
454 """
455 Rms of ligand from reference ligand after superimposing the two
456 receptors.
457
458 @param ref: reference complex, must have identical atoms
459 @type ref: Complex
460
461 @return: ligand rmsd
462 @rtype: float
463
464 @note: not implemented
465 """
466 pass
467
468
470 """
471 Rmsd between this and reference interface. The interface is
472 defined as any residue that has an atom which is within the
473 distance given by |cutoff| from its partner.
474
475 @param ref: reference complex
476 @type ref: Complex
477 @param cutoff: atom distance cutoff for interface residue definition
478 (default: 4.5)
479 @type cutoff: float
480 @param fit: least-squares fit before calculating the rms (default: 1)
481 @type fit: 1|0
482
483 @return: interface rmad
484 @rtype: float
485 """
486
487 this = self
488 if not ref.rec_model.equals( self.rec_model )[1] \
489 or not ref.lig_model.equals( self.lig_model )[1]:
490
491 m_rec, m_rec_ref, m_lig, m_lig_ref = self.equalAtoms( ref )
492 this = self.compress( m_rec, m_lig )
493 ref = ref.compress( m_rec_ref, m_lig_ref )
494
495
496 contacts = ref.resContacts( cutoff )
497
498 if_rec = ref.rec_model.res2atomMask( N.sum( contacts, 1 ) )
499 if_lig = ref.lig_model.res2atomMask( N.sum( contacts, 0 ) )
500
501 mask_interface = N.concatenate( (if_rec, if_lig) )
502 mask_heavy = N.concatenate( (ref.rec().maskHeavy(),
503 ref.lig_model.maskHeavy()) )
504 mask_interface = mask_interface * mask_heavy
505
506
507 ref_model = ref.model()
508 this_model= this.model()
509
510 return ref_model.rms( this_model, mask_interface, fit=fit)
511
512
541
542
571
572
597
598
600 """
601 Count how often (all possible) res-res combinations occur
602 in the given contacts.
603
604 @param cm: pre-calculated contact matrix (default: None)
605 @type cm: matrix
606
607 @return: dict {'AA':3,'AC':0, .. 'WW':2, 'WY':0 }
608 @rtype: dict
609 """
610 resPairs = self.contactResPairs( cm )
611 allAA = molUtils.allAA()
612
613 allPairs = {}
614
615
616 for i in range(0, len(allAA)):
617
618 for j in range(i, len( allAA ) ):
619 key = t.sortString( allAA[j]+allAA[i] )
620 allPairs[key] = 0
621
622
623 for pair in resPairs:
624
625 key = t.sortString( pair[0] + pair[1] )
626 allPairs[ key ] += 1
627
628 return allPairs
629
630
661
662
729
730
732 """
733 Correct one dimension of contactMatrix by inserting and deleting
734 columns, so that it can be later compared to contact matrices based
735 on slightly different sequences.
736
737 @param cm: contact matrix, 2D matrix of residue contacts
738 recceptor x ligand sequence
739 @type cm: array
740 @param thisSeq: AA sequence of this dimension of the contactMatrix
741 @type thisSeq: string
742 @param castSeq: AA sequence of this dimension in the other contact
743 @type castSeq: string
744 @param axis: which dimension to adapt (0=receptor, 1=ligand)
745 @type axis: 1|0
746
747 @return: contact matrix with residue contacts compatible to refSeq.
748 @rtype: 2D array
749 """
750
751 seqdiff = SequenceMatcher(None, thisSeq, castSeq)
752 seqDiff = seqdiff.get_opcodes()
753
754
755
756 if not axis:
757 cm = N.transpose( cm )
758
759 seqCount = 0
760 i=0
761
762 for list in seqDiff:
763
764
765
766 if str( seqDiff[i][0] ) == 'delete':
767
768
769 matrixSeg1 = cm[ :, : seqDiff[i][1] + seqCount ]
770 matrixSeg2 = cm[ :, seqDiff[i][2] + seqCount : ]
771
772 cm = N.concatenate( ( matrixSeg1, matrixSeg2 ), 1)
773 seqCount = seqCount + seqDiff[i][1] - seqDiff[i][2]
774
775
776
777 if str( seqDiff[i][0] ) == 'insert':
778
779
780 insertZeros= seqDiff[i][4] - seqDiff[i][3]
781 insertColumns = N.array( [ [0] * insertZeros ] * N.size(cm,0) )
782
783 matrixSeg1 = cm[ :, : seqDiff[i][1] + seqCount ]
784 matrixSeg2 = cm[ :, seqDiff[i][2] + seqCount : ]
785
786 cm = N.concatenate( (matrixSeg1,insertColumns,matrixSeg2), 1)
787 seqCount = seqCount + seqDiff[i][4] - seqDiff[i][3]
788
789 i=i+1
790
791 if not axis:
792 return N.transpose( cm )
793 return cm
794
795
797 """
798 Map contacts between selected rec and lig atoms back to all atoms
799 matrix.
800
801 @param contacts: contact matrix, array sum_rec_mask x sum_lig_mask
802 @type contacts: array
803 @param rec_mask: atom mask
804 @type rec_mask: [1|0]
805 @param lig_mask: atom mask
806 @type lig_mask: [1|0]
807
808 @return: atom contact matrix, array N_atoms_rec x N_atoms_lig
809 @rtype: array
810 """
811 l_rec = len( self.rec_model )
812 l_lig = len( self.lig_model )
813
814
815 r = N.zeros( l_rec * l_lig )
816 rMask = N.ravel( N.outerproduct( rec_mask, lig_mask ) )
817
818
819 N.put( r, N.nonzero( rMask ), N.ravel( contacts ) )
820
821 return N.resize( r, (l_rec, l_lig))
822
823
855
856
889
890
917
918
920 """
921 Reduce binary matrix of n x k atoms to binary matrix of i x j residues.
922
923 @param m: atom contact matrix,
924 array n x k with 1(contact) or 0(no contact)
925 @type m: array
926
927 @return: residue contact matrix,
928 2-D numpy array(residues_receptor x residues_ligand)
929 @rtype: array
930 """
931 recInd = N.concatenate((self.rec().resIndex(),
932 [ self.rec().lenAtoms()] ))
933 ligInd = N.concatenate((self.lig_model.resIndex(),
934 [ self.lig_model.lenAtoms() ] ))
935
936 residueMatrix = N.zeros(( len(recInd)-1, len(ligInd)-1 ), N.Int)
937
938 for r in range( len(recInd)-1 ):
939
940 for l in range( len(ligInd)-1 ):
941
942 res2res = m[ int(recInd[r]):int(recInd[r+1]),
943 int(ligInd[l]):int(ligInd[l+1]) ]
944
945 if N.any( res2res ):
946 residueMatrix[r, l] = 1
947
948 return residueMatrix
949
950
952 """
953 Compare two complexes' atom content of receptor and ligand.
954 Apply to SORTED models without HETATOMS. Coordinates are not checked.
955
956 @param ref: reference complex
957 @type ref: Complex
958
959 @return: (mask_rec, mask_lig, mask_rec_ref, mask_lig_ref),
960 4 atom masks for all equal atoms
961 @rtype: [1|0], [1|0], [1|0], [1|0]
962
963 @note: in some rare cases m1.equalAtoms( m2 ) gives a different
964 result than m2.equalAtoms( m1 ). This is due to the used
965 SequenceMatcher class.
966 """
967 m_rec, m_rec_ref = self.rec_model.equalAtoms( ref.rec_model )
968 m_lig, m_lig_ref = self.lig_model.equalAtoms( ref.lig_model )
969 return m_rec, m_lig, m_rec_ref, m_lig_ref
970
971
973 """
974 Compare atom content and oder of rec and lig of 2 complexes.
975 Get list of all atom positions of rec and lig in both complexes that
976 have a matching atom (by residue and atom name) in the other complex.
977 Indices for this complex are returned in the right oder to match the
978 atom order of ref. I.e., in contrast to equalAtoms, castAtoms can
979 equalize two complexes where atoms are ordered differently within the
980 residues.
981
982 @param ref: reference complex
983 @type ref: Complex
984
985 @return: (ind_rec, ind_lig, ind_rec_ref, ind_lig_ref),
986 4 lists of indices
987 @rtype: [int], [int], [int], [int]
988 """
989 i_rec, i_rec_ref = self.rec_model.compareAtoms( ref.rec_model )
990 i_lig, i_lig_ref = self.lig_model.compareAtoms( ref.lig_model )
991
992 return i_rec, i_lig, i_rec_ref, i_lig_ref
993
994
995 - def take( self, rec_pos, lig_pos ):
996 """
997 Get copy of this complex with given atoms of rec and lig.
998
999 @param rec_pos: receptor indices to take
1000 @type rec_pos: [int]
1001 @param lig_pos: ligand indices to take
1002 @type lig_pos: [int]
1003
1004 @return: new complex
1005 @rtype: Complex
1006 """
1007 r = self.__class__()
1008 r.lig_model = self.lig_model.take( lig_pos )
1009 r.rec_model = self.rec_model.take( rec_pos )
1010 r.info = deepcopy( self.info )
1011
1012 if self.pw_dist:
1013 r.pw_dist = N.take( self.pw_dist, rec_pos, 1 )
1014 r.pw_dist = N.take( r.pw_dist, lig_pos )
1015
1016 r.ligandMatrix = copy( self.ligandMatrix )
1017
1018
1019
1020 return r
1021
1022
1023 - def compress( self, rec_mask, lig_mask ):
1024 """
1025 Compress complex using a rec and lig mask.
1026
1027 @param rec_mask: atom mask
1028 @type rec_mask: [1|0]
1029 @param lig_mask: atom mask
1030 @type lig_mask: [1|0]
1031
1032 @return: compressed complex
1033 @rtype: Complex
1034 """
1035 return self.take( N.nonzero( rec_mask ), N.nonzero( lig_mask ) )
1036
1037
1039 """
1040 Score interaction surface residue pairs.
1041 Info on Scoring matrix see L{Biskit.molUtils}
1042
1043 @param cutoff: CB-CB distance cutoff for defining a contact
1044 (default: 6.0)
1045 @type cutoff: float
1046
1047 @return: score
1048 @rtype: float
1049 """
1050 score = 0
1051 cm = self.resContacts(cutoff,self.rec().maskCB(), self.lig().maskCB(),
1052 cache=0 )
1053
1054 pairFreq = self.resPairCounts(cm)
1055
1056 for pair in pairFreq:
1057 score += pairFreq[pair]*molUtils.pairScore[pair]
1058
1059 return score
1060
1061
1063 """
1064 Calculate the difference between the surface area of the
1065 complex vs. its free components in square angstrom.
1066
1067 @param profiles: option to return the lig, rec and com profiles
1068 rather than the value (both absolute and relative
1069 values are returned)
1070 @type profiles: 1|0 (default: 0)
1071 @param log: log file [STDOUT]
1072 @type log: Biskit.LogFile
1073 @param verbose: give progress report [1]
1074 @type verbose: bool | int
1075
1076 @return: AS area, MS area OR
1077 a dictionary of lig, rec and com profiles
1078 @rtype: (float, float) or dict
1079 """
1080 rcom = self.rec()
1081 lcom = self.lig()
1082 ccom = self.model()
1083 result = {}
1084
1085 def getSurface( model, key ):
1086 if verbose:
1087 log.write("Calculating SurfaceRacer data for %s..."%key)
1088 d = PDBDope( model )
1089 d.addSurfaceRacer( probe=1.4 )
1090 if verbose:
1091 log.writeln('Done.')
1092 result['%s_AS'%key] = model.profile('AS')
1093 result['%s_MS'%key] = model.profile('MS')
1094 result['%s_relAS'%key] = model.profile('relAS')
1095 result['%s_relMS'%key] = model.profile('relMS')
1096
1097 getSurface( rcom, 'rec' )
1098 getSurface( lcom, 'lig' )
1099 getSurface( ccom, 'com' )
1100
1101 if not profiles:
1102 return sum(result['rec_AS']) + sum(result['lig_AS']) - \
1103 sum(result['com_AS']),\
1104 sum(result['rec_MS']) + sum(result['lig_MS']) - \
1105 sum(result['com_MS'])
1106 else:
1107 return result
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1148 """
1149 Calculate Prosa2003 total energies for the complex.
1150
1151 @return: Prosa energy profiles,
1152 N.array(pair energy, surface energy, combined energy )
1153 @rtype: (array, array, array)
1154 """
1155 rec, lig = self.rec_model, self.lig_model
1156 p = Prosa2003( [rec, lig], debug=1 )
1157 p.run()
1158
1159 return p.prosaEnergy()
1160
1161
1163 """
1164 Calculate E_rec and/or E_lig only if not given::
1165 E_com - (E_rec + E_lig).
1166
1167 @param force: force calc of E_rec and E_lig
1168 @type force: 1|0
1169
1170 @return: dict with the different fold-X energy terms
1171 @rtype: dict
1172 """
1173 rec, lig = self.rec_model, self.lig_model
1174
1175
1176 if not 'foldX' in rec.info or rec.xyzChanged or force:
1177 d = PDBDope( rec )
1178 d.addFoldX()
1179
1180 if not 'foldX' in lig.info or lig.xyzChanged or force:
1181 d = PDBDope( lig )
1182 d.addFoldX()
1183 try:
1184 self.lig_transformed.info = lig.info
1185 except:
1186 pass
1187
1188 m = self.model()
1189
1190 d = PDBDope( m )
1191 d.addFoldX()
1192
1193 e_rec = rec.info['foldX']
1194 e_lig = lig.info['foldX']
1195 e_com = m.info['foldX']
1196
1197 r = {}
1198 for key in e_com:
1199 e = e_com[key] - ( e_lig[key] + e_rec[key] )
1200 r[key] = e
1201
1202 return r
1203
1204
1207 """
1208 Score of conserved residue pairs in the interaction surface.
1209 Optionally, normalized by radom surface contacts.
1210
1211 @param cons_type: precalculated conservation profile name,
1212 see L{Biskit.PDBDope}.
1213 @type cons_type: str
1214 @param ranNr: number of random matricies to use (default: 150)
1215 @type ranNr: int
1216 @param log: log file [STDOUT]
1217 @type log: Biskit.LogFile
1218 @param verbose: give progress report [1]
1219 @type verbose: bool | int
1220
1221 @return: conservation score
1222 @rtype: float
1223 """
1224 try:
1225 recCons = self.rec().profile( cons_type, updateMissing=1 )
1226 except:
1227 if verbose:
1228 log.add('\n'+'*'*30+'\nNO HHM PROFILE FOR RECEPTOR\n'+\
1229 '*'*30+'\n')
1230 recCons = N.ones( self.rec().lenResidues() )
1231 try:
1232 ligCons = self.lig().profile( cons_type, updateMissing=1 )
1233 except:
1234 if verbose:
1235 log.add(\
1236 '\n'+'*'*30+'\nNO HHM PROFILE FOR LIGAND\n'+'*'*30+'\n')
1237 ligCons = N.ones( self.lig().lenResidues() )
1238
1239 if self.rec().profile( 'surfMask' ):
1240 recSurf = self.rec().profile( 'surfMask' )
1241 else:
1242 d = PDBDope(self.rec())
1243 d.addSurfaceMask()
1244
1245 if self.lig().profile( 'surfMask' ):
1246 ligSurf = self.lig().profile( 'surfMask' )
1247 else:
1248 d = PDBDope(self.lig())
1249 d.addSurfaceMask()
1250
1251 surfMask = N.ravel(N.outerproduct( recSurf, ligSurf ))
1252
1253 missing = N.outerproduct( N.equal( recCons, 0), N.equal(ligCons,0))
1254
1255 cont = self.resContacts() * N.logical_not(missing)
1256
1257 consMat = N.outerproduct( recCons, ligCons )
1258
1259 score = cont* consMat
1260
1261
1262 if ranNr != 0:
1263 if self.verbose:
1264 self.log.write('.')
1265 ranMat = mathUtils.random2DArray( cont, ranNr, mask=surfMask )
1266 random_score = N.sum(N.sum( ranMat * consMat ))/( ranNr*1.0 )
1267 return N.sum(N.sum(score))/random_score
1268
1269 else:
1270 return N.sum(N.sum(score))/ N.sum(N.sum(cont))
1271
1272
1274 """
1275 Put rotation and translation matrix into single 4x4 matrix.
1276
1277 @param r: rotation matric, array 3x3 of float
1278 @type r: array
1279 @param t: translation vector, array 1x3 of float
1280 @type t: vector
1281
1282 @return: rotation/translation matrix, array 4x4 of float
1283 @rtype: array
1284 """
1285
1286 result = N.concatenate( (r, N.transpose( [ t.tolist() ] )), 1)
1287
1288 result = N.concatenate( (result, N.array([[0,0,0,1]],N.Float32)), 0)
1289
1290 return result.astype(N.Float32)
1291
1292
1294 """
1295 Find transformation matrix for rigid body-transformed ligand.
1296
1297 @param lig: ligand model
1298 @type lig: PDBModel
1299
1300 @return: rotation/translation matrix, array 4x4 of float
1301 @rtype: array
1302 """
1303 lig = lig.compress( lig.maskCA() )
1304 template = self.lig_model.compress( self.lig_model.maskCA() )
1305
1306 r,t = self.__findTransformation( lig.xyz, template.xyz )
1307
1308 return self.rtTuple2matrix( r, t )
1309
1310
1346
1347
1349 """
1350 pairwise distance between 2 3-D numpy arrays of atom coordinates.
1351
1352 @param u: coordinates
1353 @type u: array
1354 @param v: coordinates
1355 @type v: array
1356
1357 @return: Numpy array len(u) x len(v)
1358 @rtype:array
1359
1360 @author: Wolfgang Rieping.
1361 """
1362
1363 if not type( u ) == arraytype or\
1364 not type( v ) == arraytype:
1365 raise ComplexError('unsupported argument type ' + \
1366 str( type(u) ) + ' or ' + str( type(v) ) )
1367
1368 diag1= N.diagonal(N.dot(u,N.transpose(u)))
1369 diag2= N.diagonal(N.dot(v,N.transpose(v)))
1370 dist= -N.dot(v,N.transpose(u))-N.transpose(N.dot(u,N.transpose(v)))
1371 dist= N.transpose(N.asarray(map(lambda column,a:column+a, \
1372 N.transpose(dist), diag1)))
1373
1374 return N.transpose(N.sqrt(N.asarray(
1375 map(lambda row,a: row+a, dist, diag2))))
1376
1377
1378
1380 """
1381 Compare structure from hex complex with original ligand pdb
1382 and store transformation matrix of ligand in self.ligandMatrix.
1383
1384 @param fcomplex: pdb file with hex complex
1385 @type fcomplex: complec
1386
1387 @return: rotation matrix and translation matrix as tuple
1388 @rtype: (array, array)
1389 """
1390 docked_pdb = self._extractLigandStructure(fcomplex)
1391
1392 xyz_docked = N.compress( docked_pdb.maskCA(), docked_pdb.xyz )
1393 xyz_template = N.compress( self.lig_model.maskCA(),
1394 self.lig_model.xyz )
1395
1396 (r, t) = self._findTransformation(xyz_docked, xyz_template)
1397 return (r,t)
1398
1399
1400
1401
1402
1403
1404 import Biskit.test as BT
1405
1406 -class Test(BT.BiskitTest):
1407 """Test case"""
1408
1410 """Dock.Complex test"""
1411
1412 lig = PCRModel( t.testRoot() + "/com/1BGS.psf",
1413 t.testRoot() + "/com/lig.model")
1414
1415 rec = PCRModel( t.testRoot() + "/com/1BGS.psf",
1416 t.testRoot() + "/com/rec.model")
1417
1418 rec = rec.compress( rec.maskHeavy() )
1419 lig = lig.compress( lig.maskHeavy() )
1420
1421 c = Complex(rec, lig)
1422 c.info['soln'] = 1
1423
1424 cont = c.atomContacts( 6.0 )
1425 contProfile_lig = N.sum( cont )
1426 contProfile_rec = N.sum( cont, 1 )
1427
1428 try:
1429 dope = PDBDope( c.rec_model )
1430 dope.addSurfaceRacer( probe=1.4 )
1431 rec_surf = c.rec_model.profile2mask( 'MS', 0.0000001, 1000 )
1432
1433 dope = PDBDope( c.lig_model )
1434 dope.addSurfaceRacer( probe=1.4 )
1435 lig_surf = c.lig_model.profile2mask( 'MS', 0.0000001, 1000 )
1436 except:
1437 pass
1438
1439 if self.local:
1440 from Biskit import Pymoler
1441
1442 self.pm = Pymoler()
1443 self.pm.addPdb( c.rec(), 'rec' )
1444 self.pm.addPdb( c.lig(), 'lig' )
1445
1446 self.pm.colorAtoms( 'rec', contProfile_rec )
1447 self.pm.colorAtoms( 'lig', contProfile_lig )
1448
1449 rec_sphere = c.rec().clone()
1450 rec_sphere.xyz = mathUtils.projectOnSphere( rec_sphere.xyz )
1451
1452 lig_sphere = c.lig().clone()
1453 lig_sphere.xyz = mathUtils.projectOnSphere( lig_sphere.xyz )
1454
1455 self.pm.addPdb( rec_sphere, 'rec_sphere' )
1456 self.pm.addPdb( lig_sphere, 'lig_sphere' )
1457
1458 self.pm.colorAtoms( 'rec_sphere', contProfile_rec )
1459 self.pm.colorAtoms( 'lig_sphere', contProfile_lig )
1460
1461 self.pm.add( 'hide all')
1462
1463 self.pm.add( 'color grey, (b=0)' )
1464 self.pm.add( 'show stick, (rec or lig)' )
1465 self.pm.add( 'show surf, rec_sphere')
1466
1467 self.pm.add( 'zoom all' )
1468
1469 self.pm.show()
1470
1471 globals().update( locals() )
1472
1473 self.assertEqual( N.sum(contProfile_lig) + N.sum(contProfile_rec),
1474 2462 )
1475
1476
1477 if __name__ == '__main__':
1478
1479 BT.localTest()
1480