def __ssBonds( self, model, cutoff=4. ): """ Identify disulfide bonds. :param model: model :type model: PDBModel :param cutoff: distance cutoff for S-S distance (default: 4.0) :type cutoff: float :return: list with numbers of residue pairs forming S-S :rtype: [(int, int)] """ m = model.compress( model.mask( ['SG'] ) ) if len( m ) < 2: return [] pw = MU.pairwiseDistances( m.xyz, m.xyz ) pw = N0.less( pw, cutoff ) r = [] for i in range( len( pw ) ): for j in range( i+1, len(pw) ): if pw[i,j]: r += [ (m.atoms['residue_number'][i], m.atoms['residue_number'][j]) ] return r
def addDensity( self, radius=6, minasa=None, profName='density' ): """ Count the number of heavy atoms within the given radius. Values are only collected for atoms with |minasa| accessible surface area. @param minasa: relative exposed surface - 0 to 100% @type minasa: float @param radius: in Angstrom @type radius: float """ mHeavy = self.m.maskHeavy() xyz = N0.compress( mHeavy, self.m.getXyz(), 0 ) if minasa and self.m.profile( 'relAS', 0 ) == 0: self.addASA() if minasa: mSurf = self.m.profile2mask( 'relAS', minasa ) else: mSurf = N0.ones( self.m.lenAtoms() ) ## loop over all surface atoms surf_pos = N0.nonzero( mSurf ) contacts = [] for i in surf_pos: dist = N0.sum(( xyz - self.m.xyz[i])**2, 1) contacts += [ N0.sum( N0.less(dist, radius**2 )) -1] self.m.atoms.set( profName, contacts, mSurf, default=-1, comment='atom density radius %3.1fA' % radius, version= T.dateString() + ' ' + self.version() )
def takeFrames( self, indices ): """ Return a copy of the trajectory containing only the specified frames. :param indices: positions to take :type indices: [int] :return: copy of this Trajectory (fewer frames, semi-deep copy of ref) :rtype: Trajectory """ ## remove out-of-bound indices indices = N0.compress( N0.less( indices, len( self.frames) ), indices ) r = self.__class__() ## this step takes some time for large frames ! r.frames = N0.take( self.frames, indices, 0 ) ## semi-deep copy of reference model r.setRef( self.ref.take( list(range( self.ref.lenAtoms()))) ) if self.frameNames is not None: r.frameNames = N0.take( self.frameNames, indices, 0 ) r.frameNames = list(map( ''.join, r.frameNames.tolist() )) r.pc = self.__takePca( indices ) r.profiles = self.profiles.take( indices ) r.resIndex = self.resIndex return r
def __atomContacts(self, cutoff, rec_mask, lig_mask, cache): """ Intermolecular distances below cutoff after applying the two masks. @param cutoff: cutoff for B{atom-atom} contact in \AA @type cutoff: float @param rec_mask: atom mask @type rec_mask: [1|0] @param lig_mask: atom mask @type lig_mask: [1|0] @param cache: cache pairwise atom distance matrix @type cache: 1|0 @return: atom contact matrix, array sum_rec_mask x sum_lig_mask @rtype: array """ ## get atom coordinats as array 3 x all_atoms rec_xyz = self.rec().getXyz() lig_xyz = self.lig().getXyz() ## get pair-wise distances -> atoms_rec x atoms_lig dist = getattr(self, 'pw_dist', None) if dist is None or \ N0.shape( dist ) != ( N0.sum(rec_mask), N0.sum(lig_mask) ): dist = self.__pairwiseDistances(N0.compress(rec_mask, rec_xyz, 0), N0.compress(lig_mask, lig_xyz, 0)) if cache: self.pw_dist = dist ## reduce to 1 (distance < cutoff) or 0 -> n_atoms_rec x n_atoms_lig return N0.less(dist, cutoff)
def __atomContacts(self, cutoff, rec_mask, lig_mask, cache): """ Intermolecular distances below cutoff after applying the two masks. @param cutoff: cutoff for B{atom-atom} contact in \AA @type cutoff: float @param rec_mask: atom mask @type rec_mask: [1|0] @param lig_mask: atom mask @type lig_mask: [1|0] @param cache: cache pairwise atom distance matrix @type cache: 1|0 @return: atom contact matrix, array sum_rec_mask x sum_lig_mask @rtype: array """ ## get atom coordinats as array 3 x all_atoms rec_xyz = self.rec().getXyz() lig_xyz = self.lig().getXyz() ## get pair-wise distances -> atoms_rec x atoms_lig dist = getattr( self, 'pw_dist', None ) if dist is None or \ N0.shape( dist ) != ( N0.sum(rec_mask), N0.sum(lig_mask) ): dist = self.__pairwiseDistances(N0.compress( rec_mask, rec_xyz, 0), N0.compress( lig_mask, lig_xyz, 0) ) if cache: self.pw_dist = dist ## reduce to 1 (distance < cutoff) or 0 -> n_atoms_rec x n_atoms_lig return N0.less( dist, cutoff )
def __ssBonds( self, model, cutoff=4. ): """ Identify disulfide bonds. :param model: model :type model: PDBModel :param cutoff: distance cutoff for S-S distance (default: 4.0) :type cutoff: float :return: list with numbers of residue pairs forming S-S :rtype: [(int, int)] """ m = model.compress( model.mask( ['SG'] ) ) if len( m ) < 2: return [] pw = MU.pairwiseDistances( m.xyz, m.xyz ) pw = N0.less( pw, cutoff ) r = [] for i in range( len( pw ) ): for j in range( i+1, len(pw) ): if pw[i,j]: r += [ (m.atoms['residue_number'][i], m.atoms['residue_number'][j]) ] return r
def __checkProfileIntegrity(self, profile, upperLimit=1.0, lowerLimit=-1.0): """ In some cases SurfaceRacer generates incorrect curvature values for some atoms. This function sets values outside a given range to 0 @param profile: profile name @type profile: str @param upperLimit: upper limit for a valid value (default: 1.0) @type upperLimit: float @param lowerLimit: lower limit for a valid value (default: -1.0) @type lowerLimit: float @return: profile with inspected values @rtype: [float] """ mask = N0.greater(profile, upperLimit) mask += N0.less(profile, lowerLimit) for i in N0.nonzero(mask): print('WARNING! Profile value %.2f set to O\n' % profile[i]) profile[i] = 0 return profile
def __checkProfileIntegrity( self, profile, upperLimit=1.0, lowerLimit=-1.0): """ In some cases SurfaceRacer generates incorrect curvature values for some atoms. This function sets values outside a given range to 0 @param profile: profile name @type profile: str @param upperLimit: upper limit for a valid value (default: 1.0) @type upperLimit: float @param lowerLimit: lower limit for a valid value (default: -1.0) @type lowerLimit: float @return: profile with inspected values @rtype: [float] """ mask = N0.greater( profile, upperLimit ) mask += N0.less( profile, lowerLimit ) for i in N0.nonzero(mask): print('WARNING! Profile value %.2f set to O\n'%profile[i]) profile[i] = 0 return profile
def addDensity(self, radius=6, minasa=None, profName='density'): """ Count the number of heavy atoms within the given radius. Values are only collected for atoms with |minasa| accessible surface area. @param minasa: relative exposed surface - 0 to 100% @type minasa: float @param radius: in Angstrom @type radius: float """ mHeavy = self.m.maskHeavy() xyz = N0.compress(mHeavy, self.m.getXyz(), 0) if minasa and self.m.profile('relAS', 0) == 0: self.addASA() if minasa: mSurf = self.m.profile2mask('relAS', minasa) else: mSurf = N0.ones(self.m.lenAtoms()) ## loop over all surface atoms surf_pos = N0.nonzero(mSurf) contacts = [] for i in surf_pos: dist = N0.sum((xyz - self.m.xyz[i])**2, 1) contacts += [N0.sum(N0.less(dist, radius**2)) - 1] self.m.atoms.set(profName, contacts, mSurf, default=-1, comment='atom density radius %3.1fA' % radius, version=T.dateString() + ' ' + self.version())
def match(x, y, n_iterations=1, z=2, eps_rmsd=0.5, eps_stdv=0.05): """ Matches two arrays onto each other, while iteratively removing outliers. Superimposed array y would be C{ N0.dot(y, N0.transpose(r)) + t }. :param n_iterations: number of calculations:: 1 .. no iteration 0 .. until convergence :type n_iterations: 1|0 :param z: number of standard deviations for outlier definition (default: 2) :type z: float :param eps_rmsd: tolerance in rmsd (default: 0.5) :type eps_rmsd: float :param eps_stdv: tolerance in standard deviations (default: 0.05) :type eps_stdv: float :return: (r,t), [ [percent_considered, rmsd_for_it, outliers] ] :rtype: (array, array), [float, float, int] """ iter_trace = [] rmsd_old = 0 stdv_old = 0 n = 0 converged = 0 mask = N0.ones(len(y), N0.Int32 ) while not converged: ## find transformation for best match r, t = findTransformation(N0.compress(mask, x, 0), N0.compress(mask, y, 0)) ## transform coordinates xt = N0.dot(y, N0.transpose(r)) + t ## calculate row distances d = N0.sqrt(N0.sum(N0.power(x - xt, 2), 1)) * mask ## calculate rmsd and stdv rmsd = N0.sqrt(N0.average(N0.compress(mask, d)**2)) stdv = MU.SD(N0.compress(mask, d)) ## check conditions for convergence d_rmsd = abs(rmsd - rmsd_old) d_stdv = abs(1 - stdv_old / stdv) if d_rmsd < eps_rmsd and d_stdv < eps_stdv: converged = 1 else: rmsd_old = rmsd stdv_old = stdv ## store result perc = round(float(N0.sum(mask)) / float(len(mask)), 2) ## throw out non-matching rows mask = N0.logical_and(mask, N0.less(d, rmsd + z * stdv)) outliers = N0.nonzero( N0.logical_not( mask ) ) iter_trace.append([perc, round(rmsd, 3), outliers]) n += 1 if n_iterations and n >= n_iterations: break return (r, t), iter_trace
def match(x, y, n_iterations=1, z=2, eps_rmsd=0.5, eps_stdv=0.05): """ Matches two arrays onto each other, while iteratively removing outliers. Superimposed array y would be C{ N0.dot(y, N0.transpose(r)) + t }. :param n_iterations: number of calculations:: 1 .. no iteration 0 .. until convergence :type n_iterations: 1|0 :param z: number of standard deviations for outlier definition (default: 2) :type z: float :param eps_rmsd: tolerance in rmsd (default: 0.5) :type eps_rmsd: float :param eps_stdv: tolerance in standard deviations (default: 0.05) :type eps_stdv: float :return: (r,t), [ [percent_considered, rmsd_for_it, outliers] ] :rtype: (array, array), [float, float, int] """ iter_trace = [] rmsd_old = 0 stdv_old = 0 n = 0 converged = 0 mask = N0.ones(len(y), N0.Int32) while not converged: ## find transformation for best match r, t = findTransformation(N0.compress(mask, x, 0), N0.compress(mask, y, 0)) ## transform coordinates xt = N0.dot(y, N0.transpose(r)) + t ## calculate row distances d = N0.sqrt(N0.sum(N0.power(x - xt, 2), 1)) * mask ## calculate rmsd and stdv rmsd = N0.sqrt(N0.average(N0.compress(mask, d)**2)) stdv = MU.SD(N0.compress(mask, d)) ## check conditions for convergence d_rmsd = abs(rmsd - rmsd_old) d_stdv = abs(1 - stdv_old / stdv) if d_rmsd < eps_rmsd and d_stdv < eps_stdv: converged = 1 else: rmsd_old = rmsd stdv_old = stdv ## store result perc = round(float(N0.sum(mask)) / float(len(mask)), 2) ## throw out non-matching rows mask = N0.logical_and(mask, N0.less(d, rmsd + z * stdv)) outliers = N0.nonzero(N0.logical_not(mask)) iter_trace.append([perc, round(rmsd, 3), outliers]) n += 1 if n_iterations and n >= n_iterations: break return (r, t), iter_trace