示例#1
0
 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
示例#2
0
 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
示例#3
0
 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
示例#4
0
 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
示例#5
0
 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
示例#6
0
文件: mutate.py 项目: tubapala/peat
 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
示例#7
0
      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:
示例#8
0
        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:
示例#9
0
 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