def __unmaskedMatrix(self, contacts, rec_mask, lig_mask): """ Map contacts between selected rec and lig atoms back to all atoms matrix. @param contacts: contact matrix, array sum_rec_mask x sum_lig_mask @type contacts: array @param rec_mask: atom mask @type rec_mask: [1|0] @param lig_mask: atom mask @type lig_mask: [1|0] @return: atom contact matrix, array N_atoms_rec x N_atoms_lig @rtype: array """ l_rec = len(self.rec_model) l_lig = len(self.lig_model) ## map contacts back to all atoms matrix r = N0.zeros(l_rec * l_lig) rMask = N0.ravel(N0.outerproduct(rec_mask, lig_mask)) ## (Optimization: nonzero is time consuming step) N0.put(r, N0.nonzero(rMask), N0.ravel(contacts)) return N0.resize(r, (l_rec, l_lig))
def arrayEqual(a, b): """ Compare 2 arrays or lists of numbers for equality. :param a: first array (multi-dimensional is supported) :type a: array / list :param b: second array (multi-dimensional is supported) :type b: array / list :return: 1 if array/list a equals array/list b :rtype: 1|0 """ if a is None or b is None: return a is b if len(a) != len(b): return 0 if type(a) is list: a = N0.array(a) if type(b) is list: b = N0.array(b) a = N0.ravel(a) b = N0.ravel(b) return N0.sum(a == b) == len(a)
def arrayEqual( a, b ): """ Compare 2 arrays or lists of numbers for equality. :param a: first array (multi-dimensional is supported) :type a: array / list :param b: second array (multi-dimensional is supported) :type b: array / list :return: 1 if array/list a equals array/list b :rtype: 1|0 """ if a is None or b is None: return a is b if len(a) != len(b): return 0 if type(a) is list: a = N0.array( a ) if type(b) is list: b = N0.array( b ) a = N0.ravel( a ) b = N0.ravel( b ) return N0.sum( a==b ) == len(a)
def __unmaskedMatrix( self, contacts, rec_mask, lig_mask ): """ Map contacts between selected rec and lig atoms back to all atoms matrix. @param contacts: contact matrix, array sum_rec_mask x sum_lig_mask @type contacts: array @param rec_mask: atom mask @type rec_mask: [1|0] @param lig_mask: atom mask @type lig_mask: [1|0] @return: atom contact matrix, array N_atoms_rec x N_atoms_lig @rtype: array """ l_rec = len( self.rec_model ) l_lig = len( self.lig_model ) ## map contacts back to all atoms matrix r = N0.zeros( l_rec * l_lig ) rMask = N0.ravel( N0.outerproduct( rec_mask, lig_mask ) ) ## (Optimization: nonzero is time consuming step) N0.put( r, N0.nonzero( rMask ), N0.ravel( contacts ) ) return N0.resize( r, (l_rec, l_lig))
def avgRmsd( self, cluster, aMask=None, threshold=0. ): """ Claculate the average pairwise rmsd (in Angstrom) for members of a cluter. @param cluster: cluster number @type cluster: int @param aMask: atom mask applied before calculation @type aMask: [1|0] @param threshold: float 0-1, minimal cluster membership, see L{memberTraj()} @type threshold: float @return: average rmsd and the standard deviation @rtype: float, float """ try: rms = self.memberTraj(cluster,threshold).pairwiseRmsd( aMask ) rms = aboveDiagonal( rms ) except: rms = [] if len(N0.ravel(rms)) == 1: ## was: return N0.average(rms)[0], 0.0 return N0.average(rms), 0.0 if len(N0.ravel(rms)) == 0: return 0.0, 0.0 return N0.average( rms ), SD( rms )
def random2DArray(matrix, ranNr=1, mask=None): """ Create randomized 2D array containing ones and zeros. :param matrix: matrix to randomize :type matrix: 2D array :param mask: mask OR None (default: None) :type mask: list(1|0) :param ranNr: number of matricies to add up (default: 1) :type ranNr: integer :return: 2D array or |ranNr| added contact matricies :rtype:2D array :raise MathUtilError: if mask does not fit matrix """ ## get shape of matrix a, b = N0.shape(matrix) ## get array from matrix that is to be randomized if mask is not None: if len(mask) == len(N0.ravel(matrix)): array = N0.compress(mask, N0.ravel(matrix)) if len(mask) != len(N0.ravel(matrix)): raise MathUtilError( 'MatUtils.random2DArray - mask of incorrect length' + '\tMatrix length: %i Mask length: %i'\ %(len( N0.ravel(matrix) ), len(mask))) if not mask: array = N0.ravel(matrix) ## number of ones and length of array nOnes = int(N0.sum(array)) lenArray = len(array) ranArray = N0.zeros(lenArray) ## create random array for n in range(ranNr): ranArray += randomMask(nOnes, lenArray) ## blow up to size of original matix if mask is not None: r = N0.zeros(a * b) N0.put(r, N0.nonzero(mask), ranArray) return N0.reshape(r, (a, b)) if not mask: return N0.reshape(ranArray, (a, b))
def random2DArray( matrix, ranNr=1, mask=None): """ Create randomized 2D array containing ones and zeros. :param matrix: matrix to randomize :type matrix: 2D array :param mask: mask OR None (default: None) :type mask: list(1|0) :param ranNr: number of matricies to add up (default: 1) :type ranNr: integer :return: 2D array or |ranNr| added contact matricies :rtype:2D array :raise MathUtilError: if mask does not fit matrix """ ## get shape of matrix a,b = N0.shape( matrix ) ## get array from matrix that is to be randomized if mask is not None: if len(mask) == len( N0.ravel(matrix) ): array = N0.compress( mask, N0.ravel(matrix) ) if len(mask) != len( N0.ravel(matrix) ): raise MathUtilError( 'MatUtils.random2DArray - mask of incorrect length' + '\tMatrix length: %i Mask length: %i'\ %(len( N0.ravel(matrix) ), len(mask))) if not mask: array = N0.ravel(matrix) ## number of ones and length of array nOnes = int( N0.sum( array ) ) lenArray = len( array ) ranArray = N0.zeros( lenArray ) ## create random array for n in range(ranNr): ranArray += randomMask( nOnes, lenArray ) ## blow up to size of original matix if mask is not None: r = N0.zeros(a*b) N0.put( r, N0.nonzero(mask), ranArray) return N0.reshape( r, (a,b) ) if not mask: return N0.reshape( ranArray, (a,b) )
def takeMembers( self, mIndices ): """ Take all frames belonging to the members in mIndices:: takeMembers( mIndices ) -> EnsembleTraj with frames of given members :param mIndices: list of member indices :type mIndices: [int] OR array('i') :return: EnsembleTraj with specified members :rtype: EnsembleTraj @todo: return self.__class__ instead of EnsembleTraj """ try: ## assumes that each member traj has same number of frames fi = N0.array( [ self.memberIndices( i ) for i in mIndices ] ) fi = N0.ravel( N0.transpose( fi ) ) n_members = len( mIndices ) ## has wrong n_members and member order t = self.takeFrames( fi ) result = EnsembleTraj( n_members=n_members ) result.__dict__.update( t.__dict__ ) result.n_members = n_members result.resetFrameNames() return result except TypeError: raise EnsembleTrajError('takeMembers TypeError '+\ str(mIndices)+\ "\nlenFrames: %i; n_members: %i" %(len(self), self.n_members))
def test_ComplexTraj(self): """Dock.ComplexTraj test""" import biskit.tools as T ## there is no complex trajectory in the test folder so will have ## to create a fake trajectory with a complex f = [T.testRoot() + '/com/1BGS.pdb'] * 5 t = Trajectory(f, verbose=self.local) t = ComplexTraj(t, recChains=[0]) #if self.local: #print 'plotting contact density...' #t.plotContactDensity( step=2 ) ## create a fake second chain in the ligand for i in range(1093 + 98, 1968): t.ref.atoms['chain_id'][i] = 'B' t.ref.chainIndex(force=1, cache=1) t.cl = [1, 2] r = N0.concatenate( (list(range(1093, 1191)), list(range(0, 1093)), list(range(1191, 1968)))) tt = t.takeAtoms(r) contactMat = tt.atomContacts(1) if self.local: print('Receptor chains: %s Ligand chains: %s' % (t.cr, t.cl)) self.assertEqual(N0.sum(N0.ravel(contactMat)), 308)
def test_rmsFit(self): """rmsFit test""" from . import tools as T self.traj = T.load(T.testRoot('lig_pcr_00/traj.dat')) rt, rmsdLst = match(self.traj.ref.xyz, self.traj[-1].xyz) if self.local: print('RMSD: %.2f' % rmsdLst[0][1]) # return rotation matrix r = abs(N0.sum(N0.ravel(rt[0]))) e = abs(N0.sum(N0.ravel(self.EXPECT))) self.assertAlmostEqual(r, e, 6)
def test_rmsFit( self ): """rmsFit test""" from . import tools as T self.traj = T.load( T.testRoot('lig_pcr_00/traj.dat') ) rt, rmsdLst = match( self.traj.ref.xyz, self.traj[-1].xyz) if self.local: print('RMSD: %.2f' % rmsdLst[0][1]) # return rotation matrix r = abs( N0.sum( N0.ravel( rt[0] ))) e = abs( N0.sum( N0.ravel( self.EXPECT ))) self.assertAlmostEqual(r, e, 6)
def test_ComplexTraj(self): """Dock.ComplexTraj test""" import biskit.tools as T ## there is no complex trajectory in the test folder so will have ## to create a fake trajectory with a complex f = [ T.testRoot()+ '/com/1BGS.pdb' ] * 5 t = Trajectory( f, verbose=self.local ) t = ComplexTraj( t, recChains=[0] ) #if self.local: #print 'plotting contact density...' #t.plotContactDensity( step=2 ) ## create a fake second chain in the ligand for i in range( 1093+98, 1968 ): t.ref.atoms['chain_id'][i] = 'B' t.ref.chainIndex( force=1, cache=1 ) t.cl = [1,2] r = N0.concatenate((list(range(1093,1191)), list(range(0,1093)), list(range(1191,1968)))) tt = t.takeAtoms( r ) contactMat = tt.atomContacts( 1 ) if self.local: print('Receptor chains: %s Ligand chains: %s'%(t.cr, t.cl)) self.assertEqual( N0.sum(N0.ravel(contactMat)), 308 )
def plotContactDensity(self, step=1, cutoff=4.5): """ Example. plot histogramm of contact density. Somehing wrong?? @raise ComplexTrajError: if gnuplot program is not installed """ if not gnuplot.installed: raise ComplexTrajError('gnuplot program is not installed') r = self.averageContacts(step, cutoff) r = N0.ravel(r) r = N0.compress(r, r) gnuplot.plot(hist.density(r, 10))
def plotContactDensity( self, step=1, cutoff=4.5 ): """ Example. plot histogramm of contact density. Somehing wrong?? @raise ComplexTrajError: if gnuplot program is not installed """ if not gnuplot.installed: raise ComplexTrajError('gnuplot program is not installed') r = self.averageContacts( step, cutoff ) r = N0.ravel( r ) r = N0.compress( r, r ) gnuplot.plot( hist.density( r, 10 ) )
def __init__(self, models, name=None, profileName='relAS', verbose=1): """ @param models: List of models display a Ramachandran plot for @type models: [ PDBModel ] OR PDBModel @param name: model name, will show up in plot @type name: str @param profileName: name of profile to use for coloring (default: 'relAS') @type profileName: str @param verbose: verbosity level (default: 1) @type verbose: 1|0 """ if not biggles: raise ImportError('biggles module could not be imported.') if type(models) != type([]): models = [models] self.psi = [] self.phi = [] self.gly = [] self.pro = [] self.prof = [] self.profileName = profileName self.name = name self.verbose = verbose # calculate angles, profiles ... self.calc(models) self.prof = N0.ravel(self.prof) self.gly = N0.ravel(self.gly) self.pro = N0.ravel(self.pro)
def __init__( self, models, name=None, profileName='relAS', verbose=1 ): """ @param models: List of models display a Ramachandran plot for @type models: [ PDBModel ] OR PDBModel @param name: model name, will show up in plot @type name: str @param profileName: name of profile to use for coloring (default: 'relAS') @type profileName: str @param verbose: verbosity level (default: 1) @type verbose: 1|0 """ if not biggles: raise ImportError('biggles module could not be imported.') if type(models) != type([]): models = [ models ] self.psi = [] self.phi = [] self.gly = [] self.pro = [] self.prof=[] self.profileName = profileName self.name=name self.verbose = verbose # calculate angles, profiles ... self.calc( models ) self.prof = N0.ravel(self.prof) self.gly = N0.ravel(self.gly) self.pro = N0.ravel(self.pro)
def getFirstCrdLine(self): """ Return the first line of Amber crd. :return: first line of Amber crd formatted coordinate block :rtype: str """ if not self.xyz: self.getXyz() result = "" for x in N0.ravel(self.xyz)[:10]: result += "%8.3f" % x return result + "\n"
def getFirstCrdLine( self ): """ Return the first line of Amber crd. :return: first line of Amber crd formatted coordinate block :rtype: str """ if not self.xyz: self.getXyz() result = "" for x in N0.ravel( self.xyz )[:10]: result += "%8.3f" % x return result + "\n"
def writeCrd( self, fcrd, append=1, lastAtom=None ): """ Write/Append Amber-formatted block of coordinates to a file. If a file handle is given, the file will not be closed. :param fcrd: file to write to :type fcrd: str or file object :param append: append to existing file (default: 1) :type append: 0|1 :param lastAtom: skip all atoms beyond this one (default: None) :type lastAtom: int """ if not self.xyz: self.getXyz() if type( fcrd ) == file: ## take file handle f = fcrd else: ## create new file handle mode = 'w' if append: mode = 'a' f = open( T.absfile( fcrd ), mode ) newf = (mode=='w' or not os.path.exists( T.absfile(fcrd) )) if newf: f.write("\n") i = 0 for x in N0.ravel( self.xyz ): i = i + 1 f.write( "%8.3f" % x ) if (i % 10) == 0: f.write("\n") if lastAtom and i / 3.0 == lastAtom: break if ((i % 10) != 0): f.write("\n") if type( fcrd ) != file: ## don't close file that was already given f.close()
def writeCrd(self, fcrd, append=1, lastAtom=None): """ Write/Append Amber-formatted block of coordinates to a file. If a file handle is given, the file will not be closed. :param fcrd: file to write to :type fcrd: str or file object :param append: append to existing file (default: 1) :type append: 0|1 :param lastAtom: skip all atoms beyond this one (default: None) :type lastAtom: int """ if not self.xyz: self.getXyz() if type(fcrd) == file: ## take file handle f = fcrd else: ## create new file handle mode = 'w' if append: mode = 'a' f = open(T.absfile(fcrd), mode) newf = (mode == 'w' or not os.path.exists(T.absfile(fcrd))) if newf: f.write("\n") i = 0 for x in N0.ravel(self.xyz): i = i + 1 f.write("%8.3f" % x) if (i % 10) == 0: f.write("\n") if lastAtom and i / 3.0 == lastAtom: break if ((i % 10) != 0): f.write("\n") if type(fcrd) != file: ## don't close file that was already given f.close()
def color_array( self, a, resetLimits=1 ): """ :param a: array of float :type a: array of float :param resetLimits: re-define color range on max and min of values (default: 1) :type resetLimits: 1|0 :return: matrix of color codes with same dimensions as a :rtype: array of float """ s = N0.shape( a ) v = N0.ravel( a ) r = self.colors( v, resetLimits=resetLimits ) r = N0.reshape( r, s ) return r
def packBinaryMatrix(cm): """ Compress sparse array of 0 and ones to list of one-positions (space saving function, upack with :class:`unpackBinaryMatrix`). :param cm: X by Y array of int :type cm: 2D array :return: {'shape':(X,Y), 'nonzero':[int] } :rtype: dict """ if cm is None or type(cm) == dict: return cm result = {} result['shape'] = N0.shape(cm) result['nonzero'] = N0.nonzero(N0.ravel(cm)) result['nonzero'] = result['nonzero'].tolist() return result
def packBinaryMatrix( cm ): """ Compress sparse array of 0 and ones to list of one-positions (space saving function, upack with :class:`unpackBinaryMatrix`). :param cm: X by Y array of int :type cm: 2D array :return: {'shape':(X,Y), 'nonzero':[int] } :rtype: dict """ if cm is None or type( cm ) == dict: return cm result = {} result['shape'] = N0.shape( cm ) result['nonzero'] = N0.nonzero( N0.ravel( cm ) ) result['nonzero'] = result['nonzero'].tolist() return result
def matrixToList(cm): """ Convert matrix into standard python list remembering the dimensions. Unpack with :class:`listToMatrix`. Note: Not used right now. :param cm: array of int :type cm: 2D array :return: {'shape':(int,..), 'lst':[..] } :rtype: dict """ if cm is None or type(cm) == dict: return cm result = {} result['shape'] = N0.shape(cm) result['lst'] = N0.ravel(cm).tolist() return result
def matrixToList( cm ): """ Convert matrix into standard python list remembering the dimensions. Unpack with :class:`listToMatrix`. Note: Not used right now. :param cm: array of int :type cm: 2D array :return: {'shape':(int,..), 'lst':[..] } :rtype: dict """ if cm is None or type( cm ) == dict: return cm result = {} result['shape'] = N0.shape( cm ) result['lst'] = N0.ravel( cm ).tolist() return result
def slim(self): """ Remove coordinates and atoms of ligand and receptor from memory, if they can be restored from file, compress contact matrix. @note: CALLED BEFORE PICKLING """ self.lig_transformed = None self.pw_dist = None ## self.ligandMatrix = self.ligandMatrix.tolist() if 'matrix' in self.info: del self.info['matrix'] ## compress contact matrix array if self.contacts is not None and \ len(N0.shape( self.contacts['result'] ) )==2: m = self.contacts['result'] self.contacts['shape'] = N0.shape( m ) self.contacts['result'] = N0.nonzero( N0.ravel( m ) ).astype(N0.Int32)
def slim(self): """ Remove coordinates and atoms of ligand and receptor from memory, if they can be restored from file, compress contact matrix. @note: CALLED BEFORE PICKLING """ self.lig_transformed = None self.pw_dist = None ## self.ligandMatrix = self.ligandMatrix.tolist() if 'matrix' in self.info: del self.info['matrix'] ## compress contact matrix array if self.contacts is not None and \ len(N0.shape( self.contacts['result'] ) )==2: m = self.contacts['result'] self.contacts['shape'] = N0.shape(m) self.contacts['result'] = N0.nonzero(N0.ravel(m)).astype(N0.Int32)
def writeCrd( self, fname, frames=None ): """ Write frames to Amber crd file (w/o box info). :param fname: output file name :type fname: str :param frames: frame indices (default: all) :type frames: [int] """ if frames is None: frames = list(range( self.lenFrames())) template = " %7.3f" * 10 + '\n' ## open new file out = open( T.absfile(fname), 'wt') __write = out.write ## cache function address for speed __write('\n') n_lines = None for fi in frames: f = N0.ravel( self.frames[ fi ] ) if n_lines is None: n_lines = n_lines or len( f ) // 10 overhang= ( 0 != len( f ) % 10 ) i_lines = range( n_lines ) for i in i_lines: __write( template % tuple( f[10*i:10*i+10] ) ) if overhang: for x in f[i*10+10:]: __write(" %7.3f" % x ) __write('\n') out.close()
def thin( self, step=1 ): """ Keep only each step'th frame from trajectory with 10 ensemble members. :param step: 1..keep all frames, 2..skip first and every second, .. (default: 1) :type step: int :return: reduced EnsembleTraj :rtype: EnsembleTraj """ T.ensure( step, int, forbidden=[0] ) ## 10 x lenFrames/10, frame indices of each member mI = [ self.memberIndices( i ) for i in range(self.n_members) ] mI = N0.array( mI ) mI = N0.take( mI, range( -1, N0.shape( mI )[1], step )[1:], 1 ) mI = N0.transpose( mI ) return self.takeFrames( N0.ravel( mI ))
def conservationScore( self, cons_type='cons_ent', ranNr=150, log=StdLog(), verbose=1 ): """ Score of conserved residue pairs in the interaction surface. Optionally, normalized by radom surface contacts. @param cons_type: precalculated conservation profile name, see L{Biskit.PDBDope}. @type cons_type: str @param ranNr: number of random matricies to use (default: 150) @type ranNr: int @param log: log file [STDOUT] @type log: Biskit.LogFile @param verbose: give progress report [1] @type verbose: bool | int @return: conservation score @rtype: float """ try: recCons = self.rec().profile( cons_type, updateMissing=1 ) except: if verbose: log.add('\n'+'*'*30+'\nNO HHM PROFILE FOR RECEPTOR\n'+\ '*'*30+'\n') recCons = N0.ones( self.rec().lenResidues() ) try: ligCons = self.lig().profile( cons_type, updateMissing=1 ) except: if verbose: log.add(\ '\n'+'*'*30+'\nNO HHM PROFILE FOR LIGAND\n'+'*'*30+'\n') ligCons = N0.ones( self.lig().lenResidues() ) if self.rec().profile( 'surfMask' ): recSurf = self.rec().profile( 'surfMask' ) else: d = PDBDope(self.rec()) d.addSurfaceMask() if self.lig().profile( 'surfMask' ): ligSurf = self.lig().profile( 'surfMask' ) else: d = PDBDope(self.lig()) d.addSurfaceMask() surfMask = N0.ravel(N0.outerproduct( recSurf, ligSurf )) missing = N0.outerproduct( N0.equal( recCons, 0), N0.equal(ligCons,0)) cont = self.resContacts() * N0.logical_not(missing) consMat = N0.outerproduct( recCons, ligCons ) score = cont* consMat # get a random score if ranNr != 0: if self.verbose: self.log.write('.') ranMat = mathUtils.random2DArray( cont, ranNr, mask=surfMask ) random_score = N0.sum(N0.sum( ranMat * consMat ))/( ranNr*1.0 ) return N0.sum(N0.sum(score))/random_score else: return N0.sum(N0.sum(score))/ N0.sum(N0.sum(cont))
def pcMovie( self, ev, steps, factor=1., ref=0, morph=1 ): """ Morph between the two extreme values of a single principal component. :param ev: EigenVector to visualize :type ev: int :param steps: number of intermediate frames :type steps: int :param factor: exageration factor (default: 1 = No exageration) :type factor: float :param ref: take other eigenvecors from this frame (default: 1) :type ref: int :param morph: morph between min and max (1) or take real values (0) (default: 1) :type morph: 1|0 :return: Trajectory with frames visualizing the morphing. :rtype: Trajectory """ fit = 1 if self.pc is not None: fit = self.pc['fit'] pc = self.getPca( fit=fit ) ## eigenvectors (rows) U = pc['u'] ## raveled and centered frames x_avg = N0.average(self.frames, 0) X = N0.array( [N0.ravel(x) for x in self.frames - x_avg] ) ## ev'th eigenvector of reference frame alpha_0 = N0.dot( X[ref], U[ev] ) ## list of deviations of ev'th eigenvector of each frame from ref alpha_range = N0.dot(X, U[ev]) - alpha_0 ## get some representative alphas... if morph: a_min = factor * min(alpha_range) a_max = factor * max(alpha_range) delta = (a_max - a_min) / steps alpha_range = [ a_min + i*(delta) for i in range(0, steps) ] else: alpha_range = N0.sort( alpha_range ) delta = len(alpha_range) / (steps * 1.0) alpha_range = [ alpha_range[ int(round( i*delta )) ] for i in range(0,steps) ] ## scale ev'th eigenvector of ref with different alphas Y = N0.array( [ X[ref] + alpha * U[ev] for alpha in alpha_range] ) ## back convert to N x 3 coordinates Y = N0.reshape(Y, (Y.shape[0], -1, 3)) Y = x_avg + Y result = self.__class__() result.ref = self.ref result.frames = Y return result
def conservationScore(self, cons_type='cons_ent', ranNr=150, log=StdLog(), verbose=1): """ Score of conserved residue pairs in the interaction surface. Optionally, normalized by radom surface contacts. @param cons_type: precalculated conservation profile name, see L{Biskit.PDBDope}. @type cons_type: str @param ranNr: number of random matricies to use (default: 150) @type ranNr: int @param log: log file [STDOUT] @type log: Biskit.LogFile @param verbose: give progress report [1] @type verbose: bool | int @return: conservation score @rtype: float """ try: recCons = self.rec().profile(cons_type, updateMissing=1) except: if verbose: log.add('\n'+'*'*30+'\nNO HHM PROFILE FOR RECEPTOR\n'+\ '*'*30+'\n') recCons = N0.ones(self.rec().lenResidues()) try: ligCons = self.lig().profile(cons_type, updateMissing=1) except: if verbose: log.add(\ '\n'+'*'*30+'\nNO HHM PROFILE FOR LIGAND\n'+'*'*30+'\n') ligCons = N0.ones(self.lig().lenResidues()) if self.rec().profile('surfMask'): recSurf = self.rec().profile('surfMask') else: d = PDBDope(self.rec()) d.addSurfaceMask() if self.lig().profile('surfMask'): ligSurf = self.lig().profile('surfMask') else: d = PDBDope(self.lig()) d.addSurfaceMask() surfMask = N0.ravel(N0.outerproduct(recSurf, ligSurf)) missing = N0.outerproduct(N0.equal(recCons, 0), N0.equal(ligCons, 0)) cont = self.resContacts() * N0.logical_not(missing) consMat = N0.outerproduct(recCons, ligCons) score = cont * consMat # get a random score if ranNr != 0: if self.verbose: self.log.write('.') ranMat = mathUtils.random2DArray(cont, ranNr, mask=surfMask) random_score = N0.sum(N0.sum(ranMat * consMat)) / (ranNr * 1.0) return N0.sum(N0.sum(score)) / random_score else: return N0.sum(N0.sum(score)) / N0.sum(N0.sum(cont))