def superpose(self,reference_coords,fit_coords,return_pdbs=False): """Superpose the fit_coords on the reference_coords""" import quatfit self.refcenter,self.fitcenter,self.rotation=quatfit.qfit(len(reference_coords),reference_coords,fit_coords) self.newcoords = quatfit.qtransform(len(reference_coords), fit_coords, self.refcenter, self.fitcenter, self.rotation) # # Calc rmsd # rmsd=0.0 self.rmsd_map=[] for i in range(len(self.newcoords)): disp = self.newcoords[i] - reference_coords[i] self.rmsd_map.append(length(disp)) dist_squared = dot(disp,disp) rmsd = rmsd + dist_squared rmsd=rmsd/float(len(self.newcoords)) import math rmsd=math.sqrt(rmsd) # # If asked then return pdblines for the org and aligned atoms (as CA atoms) # if return_pdbs: pdblines=[] for coords in [reference_coords,self.newcoords]: theselines=[] count=1 for coord in coords: line='ATOM %5i %4s %3s %1s%4i %8.3f%8.3f%8.3f %5s %5s\n' %(count,' CA ','ALA','A',count,float(coord[0]),float(coord[1]),float(coord[2]),'1.0','10.0') count=count+1 theselines.append(line) pdblines.append(theselines) return rmsd,pdblines return rmsd
def build_hydrogen(self,residue,buildH,coords): """Build a hydrogen in the structure when given coordinates, the Hname and the residue""" fit_coords=[] findatoms=sorted(coords.keys()) findatoms.remove(buildH) ref_coords=[] for atom in findatoms: fit_coords.append(coords[atom]) # # Now find the corresponding atom in the structure # struct_res=residue if atom[-2:]=='-1': try: struct_res=self.PI.PreviousResidue(residue) atom=atom[:-2] except ResidueNotFoundError: print 'prev not found' return None ref_coords.append(self.PI.GetPosition('%s:%s' %(struct_res,atom))) # # Get rotation and translation for bb -> bb # import quatfit refcenter,fitcenter,rotation=quatfit.qfit(len(ref_coords),ref_coords,fit_coords) # # Get the atoms that should be transformed # trans_coords=[coords[buildH],coords[buildH]] # # Apply rotation and translation to trans_coords # newcoords = quatfit.qtransform(len(trans_coords), trans_coords, refcenter, fitcenter, rotation) # # Add the atom # struct_atom=self.PI.atoms['%s:CA' %residue] resnumber=struct_atom['RESNUM'] restype=struct_atom['RESNAME'] chainid=struct_atom['CHAINID'] atomnumber=struct_atom['NUMBER'] uniqueid='%s:%s:%s' %(chainid,resnumber,buildH) count=0 if not self.PI.atoms.has_key(uniqueid): self.PI.add_atom(uniqueid,atomnumber=atomnumber, atomname=buildH,chainid=chainid,residuename=restype, residuenumber=resnumber, xcoord=newcoords[count][0],ycoord=newcoords[count][1],zcoord=newcoords[count][2],update=None) # # Fix atom numbers # self.PI.renumber_atoms() return
def superpose(self,reference_coords,fit_coords): """Superpose the fit_coords on the reference_coords""" import quatfit self.refcenter,self.fitcenter,self.rotation=quatfit.qfit(len(reference_coords),reference_coords,fit_coords) self.newcoords = quatfit.qtransform(len(reference_coords), fit_coords, self.refcenter, self.fitcenter, self.rotation) # # Calc rmsd # rmsd=0.0 for i in range(len(self.newcoords)): disp = self.newcoords[i] - reference_coords[i] #disp=length(disp)*length(disp) dist_squared = dot(disp,disp) rmsd = rmsd + dist_squared rmsd=rmsd/float(len(self.newcoords)) import math rmsd=math.sqrt(rmsd) return rmsd
def superpose(self, reference_coords, fit_coords): """Superpose the fit_coords on the reference_coords""" import quatfit self.refcenter, self.fitcenter, self.rotation = quatfit.qfit( len(reference_coords), reference_coords, fit_coords) self.newcoords = quatfit.qtransform(len(reference_coords), fit_coords, self.refcenter, self.fitcenter, self.rotation) # # Calc rmsd # rmsd = 0.0 for i in range(len(self.newcoords)): disp = self.newcoords[i] - reference_coords[i] #disp=length(disp)*length(disp) dist_squared = dot(disp, disp) rmsd = rmsd + dist_squared rmsd = rmsd / float(len(self.newcoords)) import math rmsd = math.sqrt(rmsd) return rmsd
def superpose(self, reference_coords, fit_coords, return_pdbs=False): """Superpose the fit_coords on the reference_coords""" import quatfit self.refcenter, self.fitcenter, self.rotation = quatfit.qfit( len(reference_coords), reference_coords, fit_coords) self.newcoords = quatfit.qtransform(len(reference_coords), fit_coords, self.refcenter, self.fitcenter, self.rotation) # # Calc rmsd # rmsd = 0.0 self.rmsd_map = [] for i in range(len(self.newcoords)): disp = self.newcoords[i] - reference_coords[i] self.rmsd_map.append(length(disp)) dist_squared = dot(disp, disp) rmsd = rmsd + dist_squared rmsd = rmsd / float(len(self.newcoords)) import math rmsd = math.sqrt(rmsd) # # If asked then return pdblines for the org and aligned atoms (as CA atoms) # if return_pdbs: pdblines = [] for coords in [reference_coords, self.newcoords]: theselines = [] count = 1 for coord in coords: line = 'ATOM %5i %4s %3s %1s%4i %8.3f%8.3f%8.3f %5s %5s\n' % ( count, ' CA ', 'ALA', 'A', count, float(coord[0]), float(coord[1]), float(coord[2]), '1.0', '10.0') count = count + 1 theselines.append(line) pdblines.append(theselines) return rmsd, pdblines return rmsd
def mutate(self, residue, newtype, orgtype=None): """Mutate the residue to the new type Normal substitutions: A:0035,GLN,GLU Deletions: A:0035,delete,GLU""" # # Reset score # score = None # # Store the operations # if not getattr(self, 'mutate_operations', None): self.mutate_operations = [] this_operation = [] local_operation = [] # # Get phi and psi for this residue # #import phipsi #phi,psi,omega=phipsi.GetPhiPsi(self.PI,residue) newtype = newtype.upper() aas = self.rots.keys() aas.sort() if not self.aadefs.has_key(newtype): raise Exception, "invalid aa type" # if not self.PI.residues.has_key(residue): res = self.PI.residues.keys() res.sort() raise Exception, "Invalid residue number: %s\nKnown residues are:\n%s" % ( residue, str(res)) # # Special cases # oldtype = self.PI.resname(residue) # # If orgtype was specified then check that there's agreement with the pdb file # if orgtype: if orgtype != oldtype: raise Exception( 'Incorrect original residue type: %s %s. You said: %s' % (residue, oldtype, orgtype)) # # # if newtype == 'ALA' and (oldtype != 'GLY' and oldtype != 'PRO'): this_operation = self.fast_mutatetoALA(residue) score = 0.0 elif newtype == 'GLY': this_operation = self.fast_mutatetoGLY(residue) score = 0.0 elif oldtype == 'ASP' and newtype == 'ASN': # # Just rename # for atom in self.PI.residues[residue]: this_operation.append(['delete', atom, self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME'] = 'ASN' if self.PI.atname(atom) == 'OD2': self.PI.atoms[atom]['ATNAME'] = 'ND2' this_operation.append(['add', atom, self.PI.atoms[atom]]) score = 0.0 elif oldtype == 'ASN' and newtype == 'ASP': # # Just rename # for atom in self.PI.residues[residue]: this_operation.append(['delete', atom, self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME'] = 'ASP' if self.PI.atname(atom) == 'ND2': self.PI.atoms[atom]['ATNAME'] = 'OD2' this_operation.append(['add', atom, self.PI.atoms[atom]]) score = 0.0 elif oldtype == 'GLU' and newtype == 'GLN': # # Just rename # for atom in self.PI.residues[residue]: this_operation.append(['delete', atom, self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME'] = 'GLN' if self.PI.atname(atom) == 'OE2': self.PI.atoms[atom]['ATNAME'] = 'NE2' this_operation.append(['add', atom, self.PI.atoms[atom]]) score = 0.0 elif oldtype == 'GLN' and newtype == 'GLU': # # Just rename # for atom in self.PI.residues[residue]: this_operation.append(['delete', atom, self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME'] = 'GLU' if self.PI.atname(atom) == 'NE2': self.PI.atoms[atom]['ATNAME'] = 'OE2' this_operation.append(['add', atom, self.PI.atoms[atom]]) score = 0.0 elif oldtype == 'TYR' and newtype == 'PHE': # # Delete OH # for atom in self.PI.residues[residue]: if self.PI.atname(atom) == 'OH': this_operation.append( ['delete', atom, self.PI.atoms[atom]]) score = 0.0 else: # # Use generic code # # # Get the standard conformation # std_conf = self.aadefs[newtype] # # See which kind of mutation we do # 1. Just put standard conformation # 2. Standard conf + rotamer search # 3. Use wt rotamer (if possible, otherwise use best rotamer) # All can be used with and without debumping. # # # Get the torsion angles for this residue # org_torsangles = [] number_of_chis = self.get_nonH_torsions(residue) #print 'Number of chi values for %s is %d' %(residue,number_of_chis) for chinum in range(1, number_of_chis + 1): org_torsangles.append(self.get_chi(residue, chinum)) # # Get the backbone atoms from the structure # bb_struct = [] ref_coords = [] for atom in self.PI.residues[residue]: if (self.PI.is_backbone(atom) or self.PI.is_CB(atom)) and not self.PI.is_hydrogen(atom): bb_struct.append(atom) ref_coords.append(self.PI.GetPosition(atom)) # # Get the corresponding atoms from the template # bb_template = [] fit_coords = [] for s_atom in bb_struct: s_atname = self.PI.atname(s_atom) for atom in std_conf['atoms']: if atom[0] == s_atname: bb_template.append(atom[0]) fit_coords.append(atom[1]) break # # Get rotation and translation for bb -> bb # import quatfit refcenter, fitcenter, rotation = quatfit.qfit( len(ref_coords), ref_coords, fit_coords) # # Get the atoms that should be transformed # trans_atoms = [] trans_coords = [] for atom in std_conf['atoms']: if not atom in bb_template and atom[0] != 'O': trans_atoms.append(atom[0]) trans_coords.append(atom[1]) # # Apply rotation and translation to trans_coords # newcoords = quatfit.qtransform(len(trans_coords), trans_coords, refcenter, fitcenter, rotation) # # Delete the old side chain atoms and rename the ones that stay # for atom in self.PI.residues[residue]: if atom.split(':')[-1] in ['OXT', 'O2', "O''"]: # Rename the OXT local_operation.append( ['delete', atom, self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME'] = newtype local_operation.append(['add', atom, self.PI.atoms[atom]]) elif not atom in bb_struct: this_operation.append( ['delete', atom, self.PI.atoms[atom]]) self.PI.remove_atom(atom) else: local_operation.append( ['delete', atom, self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME'] = newtype local_operation.append(['add', atom, self.PI.atoms[atom]]) # # Copy coordinates to Protool array # struct_atom = self.PI.atoms[bb_struct[0]] resnumber = struct_atom['RESNUM'] chainid = struct_atom['CHAINID'] atomnumber = struct_atom['NUMBER'] count = 0 for atom in trans_atoms: if atom[0] != 'H': uniqueid = '%s:%s:%s' % (chainid, resnumber, atom) if not self.PI.atoms.has_key(uniqueid): self.PI.add_atom(uniqueid, atomnumber=atomnumber, atomname=atom, chainid=chainid, residuename=newtype, residuenumber=resnumber, xcoord=newcoords[count][0], ycoord=newcoords[count][1], zcoord=newcoords[count][2]) this_operation.append( ['add', uniqueid, self.PI.atoms[uniqueid]]) count = count + 1 # # Fix atom numbers # self.PI.renumber_atoms() # # Set the chiangles just as the parent residue # new_number_of_chis = self.get_nonH_torsions(residue) count = 1 for chi in org_torsangles: if count > new_number_of_chis: break self.set_chi(residue, count, chi) count = count + 1 # # Score this rotamer, if bump is zero then keep it # score = self.get_bump_value(residue) if (score is None or score > 0.0) and newtype != 'ALA': # # Do rotamer search # score = self.get_best_rotamer(residue) if score is None: return None # ---------------------------------------------------- # # Keep track of the operations # updated_op = [] for op, uniqueid, atom in this_operation: if op == 'delete': updated_op.append([op, uniqueid, {}]) else: added_atom = self.PI.atoms[uniqueid].copy() not_needed = ['CHAINID', 'tag', 'BOUND_TO', 'RESNUM'] for delete in not_needed: if added_atom.has_key(delete): del added_atom[delete] updated_op.append([op, uniqueid, self.PI.atoms[uniqueid]]) self.mutate_operations = self.mutate_operations + updated_op # # Score is bump score # return score
return center_ref,center_fit,vect_ref,vect_fit # # Validate the superpos function every time this module is imported # import copy rv=array([[1,1,1],[0,-1,1],[1,-2,1],[1,-3,1],[-1,-3,2]]) fv=array([[1,1,0],[-1,2,0],[-2,1,0],[-3,1,0],[-3,3,1]]) import quatfit refcenter,fitcenter,rotation=quatfit.qfit(len(rv),rv,fv) newcoords = quatfit.qtransform(len(rv), fv, refcenter, fitcenter, rotation) # # Calc rmsd # rmsd=0.0 for i in range(len(newcoords)): disp = newcoords[i] - rv[i] dist = dot(disp,disp) rmsd = rmsd + dist if rmsd>0.0000001: print 'Superpositioning test failed!!! in geometry.py' print 'RMSD',rmsd print newcoords import sys sys.exit(1) else:
return center_ref, center_fit, vect_ref, vect_fit # # Validate the superpos function every time this module is imported # import copy rv = array([[1, 1, 1], [0, -1, 1], [1, -2, 1], [1, -3, 1], [-1, -3, 2]]) fv = array([[1, 1, 0], [-1, 2, 0], [-2, 1, 0], [-3, 1, 0], [-3, 3, 1]]) import quatfit refcenter, fitcenter, rotation = quatfit.qfit(len(rv), rv, fv) newcoords = quatfit.qtransform(len(rv), fv, refcenter, fitcenter, rotation) # # Calc rmsd # rmsd = 0.0 for i in range(len(newcoords)): disp = newcoords[i] - rv[i] dist = dot(disp, disp) rmsd = rmsd + dist if rmsd > 0.0000001: print 'Superpositioning test failed!!! in geometry.py' print 'RMSD', rmsd print newcoords import sys sys.exit(1) else:
def mutate(self,residue,newtype,orgtype=None): """Mutate the residue to the new type Normal substitutions: A:0035,GLN,GLU Deletions: A:0035,delete,GLU""" # # Reset score # score=None # # Store the operations # if not getattr(self,'mutate_operations',None): self.mutate_operations=[] this_operation=[] local_operation=[] # # Get phi and psi for this residue # #import phipsi #phi,psi,omega=phipsi.GetPhiPsi(self.PI,residue) newtype=newtype.upper() aas=self.rots.keys() aas.sort() if not self.aadefs.has_key(newtype): raise Exception,"invalid aa type" # if not self.PI.residues.has_key(residue): res=self.PI.residues.keys() res.sort() raise Exception,"Invalid residue number: %s\nKnown residues are:\n%s" %(residue,str(res)) # # Special cases # oldtype=self.PI.resname(residue) # # If orgtype was specified then check that there's agreement with the pdb file # if orgtype: if orgtype!=oldtype: raise Exception('Incorrect original residue type: %s %s. You said: %s' %(residue,oldtype,orgtype)) # # # if newtype=='ALA' and (oldtype!='GLY' and oldtype!='PRO'): this_operation=self.fast_mutatetoALA(residue) score=0.0 elif newtype=='GLY': this_operation=self.fast_mutatetoGLY(residue) score=0.0 elif oldtype=='ASP' and newtype=='ASN': # # Just rename # for atom in self.PI.residues[residue]: this_operation.append(['delete',atom,self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME']='ASN' if self.PI.atname(atom)=='OD2': self.PI.atoms[atom]['ATNAME']='ND2' this_operation.append(['add',atom,self.PI.atoms[atom]]) score=0.0 elif oldtype=='ASN' and newtype=='ASP': # # Just rename # for atom in self.PI.residues[residue]: this_operation.append(['delete',atom,self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME']='ASP' if self.PI.atname(atom)=='ND2': self.PI.atoms[atom]['ATNAME']='OD2' this_operation.append(['add',atom,self.PI.atoms[atom]]) score=0.0 elif oldtype=='GLU' and newtype=='GLN': # # Just rename # for atom in self.PI.residues[residue]: this_operation.append(['delete',atom,self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME']='GLN' if self.PI.atname(atom)=='OE2': self.PI.atoms[atom]['ATNAME']='NE2' this_operation.append(['add',atom,self.PI.atoms[atom]]) score=0.0 elif oldtype=='GLN' and newtype=='GLU': # # Just rename # for atom in self.PI.residues[residue]: this_operation.append(['delete',atom,self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME']='GLU' if self.PI.atname(atom)=='NE2': self.PI.atoms[atom]['ATNAME']='OE2' this_operation.append(['add',atom,self.PI.atoms[atom]]) score=0.0 elif oldtype=='TYR' and newtype=='PHE': # # Delete OH # for atom in self.PI.residues[residue]: if self.PI.atname(atom)=='OH': this_operation.append(['delete',atom,self.PI.atoms[atom]]) score=0.0 else: # # Use generic code # # # Get the standard conformation # std_conf=self.aadefs[newtype] # # See which kind of mutation we do # 1. Just put standard conformation # 2. Standard conf + rotamer search # 3. Use wt rotamer (if possible, otherwise use best rotamer) # All can be used with and without debumping. # # # Get the torsion angles for this residue # org_torsangles=[] number_of_chis=self.get_nonH_torsions(residue) #print 'Number of chi values for %s is %d' %(residue,number_of_chis) for chinum in range(1,number_of_chis+1): org_torsangles.append(self.get_chi(residue,chinum)) # # Get the backbone atoms from the structure # bb_struct=[] ref_coords=[] for atom in self.PI.residues[residue]: if (self.PI.is_backbone(atom) or self.PI.is_CB(atom)) and not self.PI.is_hydrogen(atom): bb_struct.append(atom) ref_coords.append(self.PI.GetPosition(atom)) # # Get the corresponding atoms from the template # bb_template=[] fit_coords=[] for s_atom in bb_struct: s_atname=self.PI.atname(s_atom) for atom in std_conf['atoms']: if atom[0]==s_atname: bb_template.append(atom[0]) fit_coords.append(atom[1]) break # # Get rotation and translation for bb -> bb # import quatfit refcenter,fitcenter,rotation=quatfit.qfit(len(ref_coords),ref_coords,fit_coords) # # Get the atoms that should be transformed # trans_atoms=[] trans_coords=[] for atom in std_conf['atoms']: if not atom in bb_template and atom[0]!='O': trans_atoms.append(atom[0]) trans_coords.append(atom[1]) # # Apply rotation and translation to trans_coords # newcoords = quatfit.qtransform(len(trans_coords), trans_coords, refcenter, fitcenter, rotation) # # Delete the old side chain atoms and rename the ones that stay # for atom in self.PI.residues[residue]: if atom.split(':')[-1] in ['OXT','O2',"O''"]: # Rename the OXT local_operation.append(['delete',atom,self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME']=newtype local_operation.append(['add',atom,self.PI.atoms[atom]]) elif not atom in bb_struct: this_operation.append(['delete',atom,self.PI.atoms[atom]]) self.PI.remove_atom(atom) else: local_operation.append(['delete',atom,self.PI.atoms[atom]]) self.PI.atoms[atom]['RESNAME']=newtype local_operation.append(['add',atom,self.PI.atoms[atom]]) # # Copy coordinates to Protool array # struct_atom=self.PI.atoms[bb_struct[0]] resnumber=struct_atom['RESNUM'] chainid=struct_atom['CHAINID'] atomnumber=struct_atom['NUMBER'] count=0 for atom in trans_atoms: if atom[0]!='H': uniqueid='%s:%s:%s' %(chainid,resnumber,atom) if not self.PI.atoms.has_key(uniqueid): self.PI.add_atom(uniqueid,atomnumber=atomnumber, atomname=atom,chainid=chainid,residuename=newtype, residuenumber=resnumber, xcoord=newcoords[count][0],ycoord=newcoords[count][1],zcoord=newcoords[count][2]) this_operation.append(['add',uniqueid,self.PI.atoms[uniqueid]]) count=count+1 # # Fix atom numbers # self.PI.renumber_atoms() # # Set the chiangles just as the parent residue # new_number_of_chis=self.get_nonH_torsions(residue) count=1 for chi in org_torsangles: if count>new_number_of_chis: break self.set_chi(residue,count,chi) count=count+1 # # Score this rotamer, if bump is zero then keep it # score=self.get_bump_value(residue) if (score is None or score>0.0) and newtype!='ALA': # # Do rotamer search # score=self.get_best_rotamer(residue) if score is None: return None # ---------------------------------------------------- # # Keep track of the operations # updated_op=[] for op,uniqueid,atom in this_operation: if op=='delete': updated_op.append([op,uniqueid,{}]) else: added_atom=self.PI.atoms[uniqueid].copy() not_needed=['CHAINID','tag','BOUND_TO','RESNUM'] for delete in not_needed: if added_atom.has_key(delete): del added_atom[delete] updated_op.append([op,uniqueid,self.PI.atoms[uniqueid]]) self.mutate_operations=self.mutate_operations+updated_op # # Score is bump score # return score