def sequential_residues(sel1, offset=1): """ PURPOSE: renumbers the selected residues sequentially, regardless of gaps USAGE: sequential_residues protName # first residue is 1 USAGE: sequential_residues protName, 5 # first residue is 5 EXAMPLE: sequential_residues * """ offset = int(offset) # A counter from offset up stored.offset = int(offset) - 1 stored.curr_res = None cmd.alter( sel1, """ if stored.curr_res != int(resi): stored.offset=stored.offset + 1 stored.curr_res=int(resi) resi=stored.offset else: resi=stored.offset """, ) cmd.sort()
def flipAtomName(targetResidueSelection): """ switch the atom names of specific residues """ # Create flipped residue cmd.create("flippedRes", targetResidueSelection + " and not alt B") targetResidueCa = cmd.get_model("flippedRes and name CA") for g in targetResidueCa.atom: # print g.resn if g.resn == 'ARG': switchName("flippedRes", "NH1", "NH2") elif g.resn == 'HIS': switchName("flippedRes", "ND1", "CD2") switchName("flippedRes", "CE1", "NE2") elif g.resn == 'ASP': switchName("flippedRes", "OD1", "OD2") elif g.resn == 'PHE': switchName("flippedRes", "CD1", "CD2") switchName("flippedRes", "CE1", "CE2") elif g.resn == 'GLN': switchName("flippedRes", "OE1", "NE2") elif g.resn == 'GLU': switchName("flippedRes", "OE1", "OE2") elif g.resn == 'LEU': switchName("flippedRes", "CD1", "CD2") elif g.resn == 'ASN': switchName("flippedRes", "OD1", "ND2") elif g.resn == 'TYR': switchName("flippedRes", "CD1", "CD2") switchName("flippedRes", "CE1", "CE2") elif g.resn == 'VAL': switchName("flippedRes", "CG1", "CG2") cmd.sort() # cmd.label("flippedRes","name") return "flippedRes"
def corexHDXRateUpdateB(obj, infoFile, exchangeRateFile): """Sets the B-factor column to the HDX rate. infoFile is used to establish the mapping between pdb and corex numbers (*.info). exchangeRateFile gives the HDX rates (*.Exchange_Rates). """ hdx = CorexExchangeRates(exchangeRateFile) info = CorexAtomInfo(infoFile) if info is None: print "Error parsing %s" % infoFile return if hdx is None: print "Error parsing %s" % exchangeRateFile return assignPDBNums( [atom.res for atom in info.getAtoms() if not atom.isHet], hdx.getResidues() ) cmd.alter(obj, "b = -10") for res in hdx.getResidues(): if res.pdbNum is not None and res.exchangeRate is not None: sel = "%s and i. %s and chain %s" % ( obj, res.pdbNum, res.chain) cmd.alter( sel, "b = %f" % res.exchangeRate) cmd.sort(obj)
def corexProtectionFactorUpdateB(obj, infoFile, pfFile): """Sets the B-factor column to the protection factors. infoFile is used to establish the mapping between pdb and corex numbers (*.info). pfFile gives the protection factors (*.Protection_Factors). """ pf = CorexProtectionFactors(pfFile) info = CorexAtomInfo(infoFile) if info is None: print "Error parsing %s" % infoFile return if pf is None: print "Error parsing %s" % exchangeRateFile return assignPDBNums( [atom.res for atom in info.getAtoms() if not atom.isHet], pf.getResidues() ) cmd.alter(obj, "b = -10") for res in pf.getResidues(): if res.pdbNum is not None and res.modifiedProtectionFactor is not None: sel = "%s and i. %s and chain %s" % ( obj, res.pdbNum, res.chain) cmd.alter( sel, "b = %f" % res.modifiedProtectionFactor) cmd.sort(obj)
def number_chains(selection='all', numbers='ABCDEFGHIJKLMNOPQRSTUVWXYZ'): """ DESCRIPTION Find chains and number them consecutively USAGE number_chains [selection [, numbers]] ARGUMENTS selection = the selection in which this function operates numbers = list of symbols to be applied. Defaults to capital letters of the ABC """ cmd.alter(selection, 'chain=""') chains = iter(numbers) foundchains = [] logger.debug('Finding chains among {} atoms'.format( cmd.count_atoms(selection))) for idx in iterate_indices(selection): if get_chain(idx, selection): # if this atom already has a chain ID set, continue with the next atom. continue foundchains.append(next(chains)) cmd.alter('(bymol idx {}) and ({})'.format(idx, selection), 'chain="{}"'.format(foundchains[-1])) cmd.sort(selection) logger.debug('Found chains: ' + ', '.join([str(c) for c in foundchains])) return foundchains
def label_chains(selection): """ DESCRIPTION Detect and label chains USAGE label_chains selection ARGUMENTS selection = name of the selection on which to operate. Atoms outside the selection won't be changed """ chainlabels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' cmd.alter(selection, 'chain=""') for label in chainlabels: space = {'stored': []} cmd.iterate('({}) and (chain "")'.format(selection), 'stored.append(index)', space=space) unnamedindices = space['stored'] if not unnamedindices: break cmd.alter( '({}) and (bymol (({}) and index {}))'.format( selection, selection, unnamedindices[0]), 'chain="{}"'.format(label)) cmd.sort()
def renumber_residues(sel="polymer", start=1): """Renumber residues. Selection should be a single chain. Run from Pymol. See also this module for renumbering based on connectivity: https://pymolwiki.org/index.php/Renumber """ class gen_resi_cl: def __init__(self, start): self.prev_new_resi = start self.prev_old_resi = None def __call__(self, cur_old_resi): if self.prev_old_resi is None: ret = self.prev_new_resi else: if self.prev_old_resi != cur_old_resi: ret = self.prev_new_resi + 1 else: ret = self.prev_new_resi self.prev_old_resi = cur_old_resi self.prev_new_resi = ret print(ret, cur_old_resi) return ret space = dict(gen_resi=gen_resi_cl(start=start)) cmd.alter(sel, "resi=gen_resi(resi)", space=space) cmd.rebuild() cmd.sort()
def remap_residues(index_file, sel="polymer"): import pandas as pd from string import ascii_uppercase as ins df = pd.read_csv(index_file, dialect="excel-tab") gr_df = df.groupby("id_from") for chain, group in gr_df: ind = {} prev_to_ind = None i_ins = 0 for i_x, x in enumerate(group[["from_ind", "to_ind"]].itertuples(index=False)): item = tuple(str(_) for _ in tuple(x)) from_ind, to_ind = item ## runs of identical to_ind cause insertion codes if i_x > 0: if to_ind == prev_to_ind: to_ind = to_ind + ins[i_ins] i_ins += 1 else: i_ins = 0 if from_ind not in ind: ind[from_ind] = to_ind prev_to_ind = item[1] space = dict(ind_map=ind) cmd.alter("{} and chain {}".format(sel, chain), "resi=ind_map[resi]", space=space) cmd.rebuild() cmd.sort()
def corexDiffSAUpdateB(obj, corex1, corex2): """Sets the B-factor column to the difference in surface areas between files corex1-corex2 """ corex1 = CorexAtomInfo(corex1) if corex1 is None: print "Error parsing %s" % corex1 return corex2 = CorexAtomInfo(corex2) if corex2 is None: print "Error parsing %s" % corex2 return atoms1 = corex1.getAtoms() atoms2 = corex2.getAtoms() if len(atoms1) != len(atoms2): print "Error: Corex files must have identical atoms" #TODO line up atoms1 and atoms2 somehow for i in xrange(len(atoms1)): sel = "%s and n. %s and i. %s and chain %s" % ( obj, atoms1[i].name, atoms1[i].res.pdbNum, atoms1[i].res.chain) cmd.alter( sel, "b = %f" % (atoms1[i].sa-atoms2[i].sa)) print "b = %f" % (atoms1[i].sa-atoms2[i].sa) cmd.sort(obj)
def test_sort(self): cmd.pseudoatom('m1', name='PS2') cmd.pseudoatom('m1', name='PS1') v = [a.name for a in cmd.get_model().atom] self.assertEqual(['PS2', 'PS1'], v) cmd.sort() v = [a.name for a in cmd.get_model().atom] self.assertEqual(['PS1', 'PS2'], v)
def builderMembrane(lipid, runNumber): """ build membrane bilayer from single lipid PDB file """ refresh() cmd.load(lipid + ".pdb", "start_lipid") cmd.alter("start_lipid", "chain = 'X'") cmd.alter("start_lipid", "segi = 'mema'") # cmd.rotate('x', 90, "start_lipid") dmax = findMaxDist("start_lipid") # create lipid copies and translate them to new position nlip = 20 # number of lipids forming edge of bilayer s0 = range(1, nlip, 1) s1 = range(1, nlip + 1, 1) # excludes first lipid step_x = 0 # translation in x (TODO: automatic determination of spacing without clashes) step_y = 7 step_z = 0 step_x2 = 7 step_y2 = 0 step_z2 = 0 for i in s1: # first column cmd.copy("lip{}".format(i), "start_lipid") # row of lipids cmd.alter("lip{}".format(i), "resi={}".format(i)) # change residue numbers y = i * step_y cmd.translate("[{},{},{}]".format(step_x, y, step_z), "lip{}".format(i)) # generate remaining rows/columns in same leaflet for j in s0: k = int(nlip) * i + j # TODO: general counter to write correct lipid number cmd.copy("lip{}".format(k), "lip{}".format(i)) # adjacent row of lipids cmd.alter("lip{}".format(k), "resi={}".format(k)) # change residue numbers x2 = j * step_x2 cmd.translate("[{},{},{}]".format(x2, step_y2, step_z2), "lip{}".format(k)) cmd.sort() # sort atom order # create second leaflet # simple method by creating a single leaflet object: cmd.create("mema", "(lip*)") cmd.delete("lip*") cmd.copy("memb", "mema") cmd.alter("memb", "segi = 'memb'") cmd.rotate("x", 180, "memb") cmd.translate("[0,0,{}]".format((-1.0 * (dmax + 0.5))), "memb") # cmd.color("yellow", "segi = 'mema'") # cmd.color("blue", "segi = 'memb'") cmd.translate("[3.5,3.5,0]", "memb") # optional shift of single leaflet to avoid aliphatic clashes s = "{}_bilayer".format(lipid) cmd.create(s, "(mema,memb)") cmd.delete("mema ,memb, start_lipid") center(s) cmd.save(s + ".pdb", s) cmd.reset() return s
def mutate(selection, aa): aa = fix_aa(aa) cmd.set("retain_order", 0) cmd.wizard("mutagenesis") cmd.refresh_wizard() for single_res in iter_residues(selection): mutate_one(single_res, aa) cmd.set_wizard() cmd.sort()
def test_sort(self): cmd.pseudoatom('m1', name='PS2') cmd.pseudoatom('m1', name='PS1') cmd.alter('all', 'name = name_list.pop()', space={'name_list': ['PS1', 'PS2']}) v = [a.name for a in cmd.get_model().atom] self.assertEqual(['PS2', 'PS1'], v) cmd.sort() v = [a.name for a in cmd.get_model().atom] self.assertEqual(['PS1', 'PS2'], v)
def testDir(self): seq = 'ACD' resv = 5 cmd.fab(seq, 'm1', resi=resv, dir=-1) # incentive needs sort, opensource is already sorted cmd.sort() cmd.iterate('first m1', 'stored.v = (resv, resn)') self.assertEqual(stored.v, (resv - 2, 'ASP'))
def builder(residues, bonds, mol_name): """Using the list generated by read_input connects monosacharides in a single oligosaccharide""" cmd.set('suspend_updates', 'on') cmd.feedback('disable', 'executive', 'actions') every_object = cmd.get_object_list('all') if mol_name in every_object: cmd.delete(mol_name) every_object.remove(mol_name) if every_object: sel = 'not (' + ' or '.join(every_object) + ') and' else: sel = '' for i in range(0, len(residues)): res_name = residues[i] cmd.load(os.path.join(path, 'db_glycans', '%s.pdb' % res_name)) cmd.set_name(res_name, i) #rename object (necessary to avoid repeating names) cmd.alter(i, 'resi = %s' % i) #name residues for further referencing cmd.sort(i) for i in range(0, len(bonds)): resi_i, resi_j, atom_i, atom_j = bonds[i][0], bonds[i][2], bonds[i][ 4], bonds[i][5] if atom_i > atom_j: cmd.remove('%s (resi %s and name O%s+H%so)' % (sel, resi_j, atom_j, atom_j)) cmd.remove('%s (resi %s and name H%so)' % (sel, resi_i, atom_i)) cmd.fuse('%s (resi %s and name O%s)' % (sel, resi_i, atom_i), '%s (resi %s and name C%s)' % (sel, resi_j, atom_j), mode=2) else: cmd.remove('%s (resi %s and name O%s+H%so)' % (sel, resi_i, atom_i, atom_i)) cmd.remove('%s (resi %s and name H%so)' % (sel, resi_j, atom_j)) cmd.fuse('%s (resi %s and name C%s)' % (sel, resi_i, atom_i), '%s (resi %s and name O%s)' % (sel, resi_j, atom_j), mode=2) cmd.delete('%s' % i) cmd.copy(mol_name, '%s' % resi_j) cmd.delete('%s' % resi_j) for i in range(0, len(bonds)): set_phi(mol_name, bonds[i], -60) set_psi(mol_name, bonds[i], 120) cmd.delete('pk1') cmd.delete('pk2') cmd.delete('pkbond') cmd.delete('pkmol') if babel: fast_min(mol_name, 5000) minimize(mol_name) else: fast_min(mol_name, 5000) cmd.feedback('enable', 'executive', 'actions') cmd.set('suspend_updates', 'off')
def corexSAUpdateB(obj, corexFile): """Sets the B-factor column to the surface area specified in corexFile""" corex = CorexAtomInfo(corexFile) if corex is None: print "Error parsing %s" % corexFile return cmd.alter(obj, "b = -10") for atom in corex.getAtoms(): sel = "%s and n. %s and i. %s and chain %s" % ( obj, atom.name, atom.res.pdbNum, atom.res.chain) cmd.alter( sel, "b = %f" % atom.sa) cmd.sort(obj)
def mse2met(selection='all', quiet=1): ''' DESCRIPTION Mutate selenomethionine to methionine ''' quiet = int(quiet) x = cmd.alter('(%s) and MSE/SE' % selection, 'name="SD";elem="S"') cmd.flag('ignore', '(%s) and MSE/' % (selection), 'clear') cmd.alter('(%s) and MSE/' % selection, 'resn="MET";type="ATOM"') if not quiet: print('Altered %d MSE residues to MET' % (x)) cmd.sort()
def mse2met(selection="all", quiet=1): """ DESCRIPTION Mutate selenomethionine to methionine """ quiet = int(quiet) x = cmd.alter("(%s) and MSE/SE" % selection, 'name="SD";elem="S"') cmd.flag("ignore", "(%s) and MSE/" % (selection), "clear") cmd.alter("(%s) and MSE/" % selection, 'resn="MET";type="ATOM"') if not quiet: print "Altered %d MSE residues to MET" % (x) cmd.sort()
def polyala(selection="all", quiet=1): """ DESCRIPTION Mutate any residue to Alanine (except Glycines) SEE ALSO stub2ala """ quiet = int(quiet) cmd.remove("polymer and (%s) and not name C+N+O+CA+CB+OXT" % (selection)) cmd.alter("polymer and (%s) and not resn GLY" % (selection), 'resn = "ALA"') cmd.sort()
def polyala(selection='all', quiet=1): ''' DESCRIPTION Mutate any residue to Alanine (except Glycines) SEE ALSO stub2ala ''' quiet = int(quiet) cmd.remove('polymer and (%s) and not name C+N+O+CA+CB+OXT' % (selection)) cmd.alter('polymer and (%s) and not resn GLY' % (selection), 'resn = "ALA"') cmd.sort()
def displacementUpdateBAll(objA, alnAri, objB, alnBri): print( "This will take a while to go through the for loops. Give me around 3-5 minutes..." ) # If residue is unassigned in one of the pdb files, we reset its value for x in range(len(alnAri)): s1 = objA + " and resi " + alnAri[x][0] + " and name " + str( alnAri[x][1]) cmd.alter(s1, "b = " + str(-0.01)) for x in range(len(alnBri)): s2 = objB + " and resi " + alnBri[x][0] + " and name " + alnBri[x][1] cmd.alter(s2, "b = " + str(-0.01)) cmd.sort(objA) cmd.sort(objB) for x in range(len(alnAri)): s1 = objA + " and resi " + alnAri[x][0] + " and name " + alnAri[x][1] s2 = objB + " and resi " + alnAri[x][0] + " and name " + alnAri[x][1] # Names starting with __ (underscores) are normally hidden by PyMOL tempObject = "__tempObject" Displacement = cmd.distance(tempObject, s1, s2) cmd.alter(s1, "b = " + str(Displacement)) cmd.alter(s2, "b = " + str(Displacement)) cmd.delete(tempObject) cmd.sort(objA) cmd.sort(objB)
def cap(object): from pymol import cmd model = cmd.get_model(object) # guarantee identical ordering cmd.delete(object) cmd.load_model(model,object) n_list = cmd.identify("(n;n &!(n;c a;2.0))") c_list = cmd.identify("(n;c &!(n;n a;2.0))") print n_list print c_list for a in n_list: newat = copy.deepcopy(model.atom[a]) newat.coord = [ newat.coord[0] + random.random(), newat.coord[1] + random.random(), newat.coord[2] + random.random(), ] newat.symbol = 'H' newat.name = 'HN' newat.numeric_type = 43 bond = Bond() bond.order = 1 bond.stereo = 0 bond.index = [ a, model.nAtom ] print "adding",newat.name,bond.index model.add_atom(newat) model.add_bond(bond) for a in c_list: newat = copy.deepcopy(model.atom[a]) newat.coord = [ newat.coord[0] + random.random(), newat.coord[1] + random.random(), newat.coord[2] + random.random(), ] newat.symbol = 'H' newat.name = 'HC' newat.numeric_type = 41 bond = Bond() bond.order = 1 bond.stereo = 0 bond.index = [ a, model.nAtom ] print "adding",newat.name,bond.index model.add_atom(newat) model.add_bond(bond) # reload cmd.delete(object) cmd.load_model(model,object) cmd.sort(object)
def pose_from_pdb(pdb_file_name): """Gets information from the pdb like the number of residues, the sequence, the number of states and the name of the object""" pose = pdb_file_name remStr = "all and not (alt ''+A)" cmd.remove(remStr) cmd.alter('all', "alt=''") stored.residues = [] stored.ResiduesNumber = [] cmd.iterate('(name ca)','stored.residues.append((resn))') cmd.iterate('all','stored.ResiduesNumber.append((resi))') first = int(stored.ResiduesNumber[0]) cmd.alter(pose, 'resi=str(int(resi)-%s)' % (first)) cmd.sort(pose) states = cmd.count_states('all') + 1 return pose, stored.residues, len(stored.residues), states
def builder(residues, bonds, mol_name): """Using the list generated by read_input connects monosacharides in a single oligosaccharide""" cmd.set('suspend_updates', 'on') cmd.feedback('disable', 'executive', 'actions') every_object = cmd.get_object_list('all') if mol_name in every_object: cmd.delete(mol_name) every_object.remove(mol_name) if every_object: sel = 'not (' + ' or '.join(every_object) + ') and' else: sel = '' for i in range(0, len(residues)): res_name = residues[i] cmd.load(os.path.join(path, 'db_glycans', '%s.pdb' % res_name)) cmd.set_name(res_name, i) #rename object (necessary to avoid repeating names) cmd.alter(i, 'resi = %s' % i) #name residues for further referencing cmd.sort(i) for i in range(0, len(bonds)): resi_i, resi_j, atom_i, atom_j = bonds[i][0], bonds[i][2], bonds[i][4], bonds[i][5] if atom_i > atom_j: cmd.remove('%s (resi %s and name O%s+H%so)' % (sel, resi_j, atom_j, atom_j)) cmd.remove('%s (resi %s and name H%so)' % (sel, resi_i, atom_i)) cmd.fuse('%s (resi %s and name O%s)' % (sel, resi_i, atom_i), '%s (resi %s and name C%s)' % (sel, resi_j, atom_j), mode=2) else: cmd.remove('%s (resi %s and name O%s+H%so)' % (sel, resi_i, atom_i, atom_i)) cmd.remove('%s (resi %s and name H%so)' % (sel, resi_j, atom_j)) cmd.fuse('%s (resi %s and name C%s)' % (sel, resi_i, atom_i), '%s (resi %s and name O%s)' % (sel, resi_j, atom_j), mode=2) cmd.delete('%s' % i) cmd.copy(mol_name, '%s' % resi_j) cmd.delete('%s' % resi_j) for i in range(0, len(bonds)): set_phi(mol_name, bonds[i], -60) set_psi(mol_name, bonds[i], 120) cmd.delete('pk1') cmd.delete('pk2') cmd.delete('pkbond') cmd.delete('pkmol') if babel: fast_min(mol_name, 5000) minimize(mol_name) else: fast_min(mol_name, 5000) cmd.feedback('enable', 'executive', 'actions') cmd.set('suspend_updates', 'off')
def stub2ala(selection='all', quiet=1): ''' DESCRIPTION Mutate stub residues to ALA SEE ALSO polyala ''' quiet = int(quiet) namesets = dict() lookslike = { # keys are sorted tuples of backbone atoms ( 'CA', ): 'GLY', ('CA', 'CB'): 'ALA', ('CA', 'CB', 'CG1', 'CG2'): 'VAL', ('CA', 'CB', 'CD1', 'CD2', 'CE1', 'CE2', 'CG', 'CZ'): 'PHE', } cmd.iterate( '(%s) and polymer and (not hydro) and (not name C+N+O+OXT)' % (selection), 'namesets.setdefault((model,segi,chain,resv,resn,resi), set()).add(name)', space={ 'namesets': namesets, 'set': set }) for key in sorted(namesets): resn = key[-2] name_tuple = tuple(sorted(namesets[key])) key_str = '/%s/%s/%s/%s`%s' % (key[:3] + key[4:]) if name_tuple == ('CA', 'CB', 'CG'): key_str_cg = key_str + '/CG' if not quiet: print('Removing ' + str(key_str_cg)) cmd.remove(key_str_cg) name_tuple = ('CA', 'CB') lookslike_resn = lookslike.get(name_tuple, resn) if lookslike_resn != resn: if not quiet: print('Altering %s to %s' % (key_str, lookslike_resn)) cmd.alter(key_str, 'resn = %s' % (repr(lookslike_resn))) cmd.sort()
def remove_alt(selection='all', keep='A', quiet=1): ''' DESCRIPTION Remove alternative location atoms. USAGE remove_alt [selection [, keep]] ARGUMENTS selection = string: atom selection keep = string: AltLoc to keep {default: A} ''' cmd.remove('(%s) and not alt +%s' % (selection, keep), quiet=int(quiet)) cmd.alter(selection, '(alt,q)=("",1.0)') cmd.sort()
def remove_alt(selection="all", keep="A", quiet=1): """ DESCRIPTION Remove alternative location atoms. USAGE remove_alt [selection [, keep]] ARGUMENTS selection = string: atom selection keep = string: AltLoc to keep {default: A} """ cmd.remove("(%s) and not alt +%s" % (selection, keep), quiet=int(quiet)) cmd.alter(selection, '(alt,q)=("",1.0)') cmd.sort()
def stub2ala(selection="all", quiet=1): """ DESCRIPTION Mutate stub residues to ALA SEE ALSO polyala """ quiet = int(quiet) namesets = dict() lookslike = { # keys are sorted tuples of backbone atoms ("CA",): "GLY", ("CA", "CB"): "ALA", ("CA", "CB", "CG1", "CG2"): "VAL", ("CA", "CB", "CD1", "CD2", "CE1", "CE2", "CG", "CZ"): "PHE", } cmd.iterate( "(%s) and polymer and (not hydro) and (not name C+N+O+OXT)" % (selection), "namesets.setdefault((model,segi,chain,resv,resn,resi), set()).add(name)", space={"namesets": namesets, "set": set}, ) for key in sorted(namesets): resn = key[-2] name_tuple = tuple(sorted(namesets[key])) key_str = "/%s/%s/%s/%s`%s" % (key[:3] + key[4:]) if name_tuple == ("CA", "CB", "CG"): key_str_cg = key_str + "/CG" if not quiet: print "Removing", key_str_cg cmd.remove(key_str_cg) name_tuple = ("CA", "CB") lookslike_resn = lookslike.get(name_tuple, resn) if lookslike_resn != resn: if not quiet: print "Altering %s to %s" % (key_str, lookslike_resn) cmd.alter(key_str, "resn = %s" % (repr(lookslike_resn))) cmd.sort()
def stub2ala(selection='all', quiet=1): ''' DESCRIPTION Mutate stub residues to ALA SEE ALSO polyala ''' quiet = int(quiet) namesets = dict() lookslike = { # keys are sorted tuples of backbone atoms ('CA',): 'GLY', ('CA', 'CB'): 'ALA', ('CA', 'CB', 'CG1', 'CG2'): 'VAL', ('CA', 'CB', 'CD1', 'CD2', 'CE1', 'CE2', 'CG', 'CZ'): 'PHE', } cmd.iterate('(%s) and polymer and (not hydro) and (not name C+N+O+OXT)' % (selection), 'namesets.setdefault((model,segi,chain,resv,resn,resi), set()).add(name)', space={'namesets': namesets, 'set': set}) for key in sorted(namesets): resn = key[-2] name_tuple = tuple(sorted(namesets[key])) key_str = '/%s/%s/%s/%s`%s' % (key[:3] + key[4:]) if name_tuple == ('CA', 'CB', 'CG'): key_str_cg = key_str + '/CG' if not quiet: print('Removing', key_str_cg) cmd.remove(key_str_cg) name_tuple = ('CA', 'CB') lookslike_resn = lookslike.get(name_tuple, resn) if lookslike_resn != resn: if not quiet: print('Altering %s to %s' % (key_str, lookslike_resn)) cmd.alter(key_str, 'resn = %s' % (repr(lookslike_resn))) cmd.sort()
def displacementUpdateBAll(objA, alnAri, objB, alnBri): print "This will take a while to go through the for loops. Give me around 3-5 minutes..." ### If residue is unassigned in one of the pdb files, we reset its value for x in range(len(alnAri)): s1 = objA + " and resi " + alnAri[x][0] + " and name " + str(alnAri[x][1]) cmd.alter( s1, "b = " + str(-0.01)) for x in range(len(alnBri)): s2 = objB + " and resi " + alnBri[x][0] + " and name " + alnBri[x][1] cmd.alter( s2, "b = " + str(-0.01)) cmd.sort(objA); cmd.sort(objB) for x in range(len(alnAri)): s1 = objA + " and resi " + alnAri[x][0] + " and name " + alnAri[x][1] s2 = objB + " and resi " + alnAri[x][0] + " and name " + alnAri[x][1] ### Names starting with __ (underscores) are normally hidden by PyMOL tempObject = "__tempObject" Displacement = cmd.distance(tempObject, s1, s2) cmd.alter( s1, "b = " + str(Displacement)) cmd.alter( s2, "b = " + str(Displacement)) cmd.delete(tempObject) cmd.sort(objA); cmd.sort(objB)
def ColorByDisplacementAll(objSel1, objSel2, super1='all', super2='all', doColor="True", doAlign="True", AlignedWhite='yes'): # First create backup copies; names starting with __ (underscores) are normally hidden by PyMOL tObj1, tObj2, aln = "__tempObj1", "__tempObj2", "__aln" if strTrue(doAlign): # Create temp objects cmd.create(tObj1, objSel1) cmd.create(tObj2, objSel2) # Align and make create an object aln which indicates which atoms were paired between the two structures # Super is must faster than align http://www.pymolwiki.org/index.php/Super cmd.super(tObj1 + ' and ' + str(super1), tObj2 + ' and ' + str(super2), object=aln) # Modify the original matrix of object1 from the alignment cmd.matrix_copy(tObj1, objSel1) else: # Create temp objects cmd.create(tObj1, objSel1) cmd.create(tObj2, objSel2) # Align and make create an object aln which indicates which atoms were paired between the two structures # Super is must faster than align http://www.pymolwiki.org/index.php/Super cmd.super(tObj1 + ' and ' + str(super1), tObj2 + ' and ' + str(super2), object=aln) # Modify the B-factor columns of the original objects, # in order to identify the residues NOT used for alignment, later on cmd.alter(objSel1 + " or " + objSel2, "b=-0.2") cmd.alter(tObj1 + " or " + tObj2, "chain='A'") cmd.alter(tObj1 + " or " + tObj2, "segi='A'") # Update pymol internal representations; one of these should do the trick cmd.refresh() cmd.rebuild() cmd.sort(tObj1) cmd.sort(tObj2) # Create lists for storage stored.alnAres, stored.alnBres = [], [] # Iterate over objects and get resi if AlignedWhite == 'yes': cmd.iterate(tObj1 + " and not " + aln, "stored.alnAres.append((resi, name))") cmd.iterate(tObj2 + " and not " + aln, "stored.alnBres.append((resi, name))") else: cmd.iterate(tObj1, "stored.alnAres.append((resi, name))") cmd.iterate(tObj2, "stored.alnBres.append((resi, name))") # Change the B-factors for EACH object displacementUpdateBAll(tObj1, stored.alnAres, tObj2, stored.alnBres) # Store the NEW B-factors stored.alnAnb, stored.alnBnb = [], [] # Iterate over objects and get b if AlignedWhite == 'yes': # Iterate over objects which is not aligned cmd.iterate(tObj1 + " and not " + aln, "stored.alnAnb.append(b)") cmd.iterate(tObj2 + " and not " + aln, "stored.alnBnb.append(b)") else: # Or Iterate over all objects with CA cmd.iterate(tObj1, "stored.alnAnb.append(b)") cmd.iterate(tObj2, "stored.alnBnb.append(b)") # Get rid of all intermediate objects and clean up cmd.delete(tObj1) cmd.delete(tObj2) cmd.delete(aln) # Assign the just stored NEW B-factors to the original objects print "Sooon ready. 1 more minute" for x in range(len(stored.alnAres)): cmd.alter(objSel1 + " and resi " + str(stored.alnAres[x][0]) + " and name " + str(stored.alnAres[x][1]), "b = " + str(stored.alnAnb[x])) for x in range(len(stored.alnBres)): cmd.alter(objSel2 + " and resi " + str(stored.alnBres[x][0]) + " and name " + str(stored.alnBres[x][1]), "b = " + str(stored.alnBnb[x])) cmd.rebuild() cmd.refresh() cmd.sort(objSel1) cmd.sort(objSel2) # Provide some useful information stored.allRMSDval = [] stored.allRMSDval = stored.alnAnb + stored.alnBnb print "\nColorByDisplacementAll completed successfully." print "The MAXIMUM Displacement is: " + str(max(stored.allRMSDval)) + " residue " + str(stored.alnAres[int(stored.allRMSDval.index(max(stored.allRMSDval)))]) if strTrue(doColor): # Showcase what we did # cmd.orient() # cmd.hide("all") cmd.show("sticks", objSel1 + " or " + objSel2) # Select the residues not used for alignment; they still have their B-factors as "-0.2" cmd.select("notUsedForAln", "b = -0.2") # White-wash the residues not used for alignment cmd.color("white", "notUsedForAln") # Select the residues not in both pdb files; they have their B-factors as "-0.01" cmd.select("ResNotInBothPDB", "b = -0.01") # White-wash the residues not used for alignment cmd.color("black", "ResNotInBothPDB") # Color the residues used for alignment according to their B-factors (Displacement values) #cmd.spectrum("b", 'rainbow', "((" + objSel1 + ") or (" + objSel2 +" )) and not notUsedForAln+ResNotInBothPDB") cmd.spectrum("b", 'rainbow', "((" + objSel1 + ") or (" + objSel2 + " )) and not (notUsedForAln or ResNotInBothPDB)") # Delete the selection of atoms not used for alignment # If you would like to keep this selection intact, # just comment "cmd.delete" line and # uncomment the "cmd.disable" line abowe. cmd.disable("notUsedForAln") cmd.delete("notUsedForAln") cmd.disable("ResNotInBothPDB") cmd.delete("ResNotInBothPDB") print "\nObjects are now colored by C-alpha displacement deviation." print "Blue is minimum and red is maximum..." print "White is those residues used in the alignment algorithm. Can be turned off in top of algorithm." print "Black is residues that does not exist in both files..."
ligand_name = file.split('_')[0] loaded_ligs.append(ligand_name) cmd.load('ligs/' + file, ligand_name) #select the ligand atomes of the original ligand to align with target_atom1 = 'RA95_target and name C3' target_atom2 = 'RA95_target and name C4' target_atom3 = 'RA95_target and name C5' #select the ligand atomes of the new ligand to align with and align the selected atoms of old and new ligand for ligand in loaded_ligs: mobile_atom1 = ligand + ' and name CL1' mobile_atom2 = ligand + ' and name CL' mobile_atom3 = ligand + ' and name CL2' cmd.pair_fit(mobile_atom1, target_atom1, mobile_atom2, target_atom2, mobile_atom3, target_atom3) #remove old ligand cmd.remove('RA95_target and resn PEN') #build bond between Lys83 and the new ligand and generate pdb file for ligand in loaded_ligs: cmd.copy('RA95_' + ligand, 'RA95_target') cmd.fuse(ligand + ' and name CL', 'RA95_' + ligand + ' and resn LYX and name NZ', '3') cmd.bond('RA95_' + ligand + ' and resn LYX and name NZ', 'RA95_' + ligand + ' and name CL') cmd.alter('RA95_' + ligand + ' and resn ' + ligand, 'segi="B"') cmd.sort('RA95_' + ligand) cmd.save('RA95_' + ligand + '.pdb', 'RA95_' + ligand, '0')
def builderMembrane(lipid): """ build membrane bilayer from single lipid PDB file """ ###FIXME: add protein to the model and change the modelName if not empty. Otherwise call the model "{protein}_{lipid}" cmd.load(lipid + ".pdb", "start_lipid") cmd.alter("start_lipid", "chain = 'X'") cmd.alter("start_lipid", "segi = 'mema'") cmd.rotate('x', 90, "start_lipid") dmax = findMaxDist("start_lipid") # create lipid copies and translate them to new position nlip = 20 # number of lipids forming edge of bilayer s0 = range(1, nlip, 1) s1 = range(1, nlip + 1, 1) # excludes first lipid step_x = 0 # translation in x (TODO: automatic determination of spacing without clashes) step_y = 7 step_z = 0 step_x2 = 7 step_y2 = 0 step_z2 = 0 for i in s1: # first column cmd.copy(f"lip{i}", "start_lipid") # row of lipids cmd.alter(f"lip{i}", f"resi{i}") # change residue numbers y = i * step_y cmd.translate(f"[{step_x},{y},{step_z}]", f"lip{i}") # generate remaining rows/columns in same leaflet for j in s0: k = int( nlip ) * i + j # TODO: general counter to write correct lipid number cmd.copy(f"lip{k}", f"lip{i}") # adjacent row of lipids cmd.alter(f"lip{k}", f"resi={k}") # change residue numbers x2 = j * step_x2 cmd.translate(f"[{x2},{step_y2},{step_z2}]", f"lip{k}") cmd.sort() # sort atom order # create second leaflet # simple method by creating a single leaflet object: cmd.create("mema", "(lip*)") cmd.delete("lip*") cmd.copy("memb", "mema") cmd.alter("memb", "segi = 'memb'") cmd.rotate("x", 180, "memb") cmd.translate(f"[0,0,{(-1.0*(dmax + 0.5))}]", "memb") #cmd.color("yellow", "segi = 'mema'") #cmd.color("blue", "segi = 'memb'") cmd.translate( "[3.5,3.5,0]", "memb") # optional shift of single leaflet to avoid aliphatic clashes s = f"{lipid}_bilayer" cmd.create(s, "(mema,memb)") cmd.delete("mema ,memb, start_lipid") center(s) cmd.save(s + ".pdb", s) cmd.reset() return s
def add_missing_atoms(selection='all', cycles=200, quiet=1): ''' DESCRIPTION Mutate those residues to themselves which have missing atoms SEE ALSO stub2ala ''' from collections import defaultdict from chempy import fragments cycles, quiet = int(cycles), int(quiet) reference = { 'ALA': set(['CB']), 'ARG': set(['CB', 'CG', 'NE', 'CZ', 'NH1', 'NH2', 'CD']), 'ASN': set(['CB', 'CG', 'OD1', 'ND2']), 'ASP': set(['CB', 'CG', 'OD1', 'OD2']), 'CYS': set(['CB', 'SG']), 'GLN': set(['CB', 'CG', 'CD', 'NE2', 'OE1']), 'GLU': set(['CB', 'CG', 'OE2', 'CD', 'OE1']), 'GLY': set([]), 'HIS': set(['CE1', 'CB', 'CG', 'CD2', 'ND1', 'NE2']), 'ILE': set(['CB', 'CD1', 'CG1', 'CG2']), 'LEU': set(['CB', 'CG', 'CD1', 'CD2']), 'LYS': set(['CB', 'CG', 'NZ', 'CE', 'CD']), 'MET': set(['CB', 'CG', 'CE', 'SD']), 'PHE': set(['CE1', 'CB', 'CG', 'CZ', 'CD1', 'CD2', 'CE2']), 'PRO': set(['CB', 'CG', 'CD']), 'SER': set(['OG', 'CB']), 'THR': set(['CB', 'OG1', 'CG2']), 'TRP': set(['CZ2', 'CB', 'CG', 'CH2', 'CE3', 'CD1', 'CD2', 'CZ3', 'NE1', 'CE2']), 'TYR': set(['CE1', 'OH', 'CB', 'CG', 'CZ', 'CD1', 'CD2', 'CE2']), 'VAL': set(['CB', 'CG1', 'CG2']), } namedsele = cmd.get_unused_name('_') cmd.select(namedsele, selection, 0) namelists = defaultdict(list) cmd.iterate('(%s) and polymer' % namedsele, 'namelists[model,segi,chain,resn,resi,resv].append(name)', space=locals()) sele_dict = defaultdict(list) tmp_name = cmd.get_unused_name('_') for key, namelist in namelists.items(): resn = key[3] if resn not in reference: if not quiet: print(' Unknown residue: + ' + resn) continue if not reference[resn].issubset(namelist): try: frag = fragments.get(resn.lower()) for a in frag.atom: a.segi = key[1] a.chain = key[2] a.resi = key[4] a.resi_number = key[5] cmd.load_model(frag, tmp_name, 1, zoom=0) skey = '/%s/%s/%s/%s`%s' % key[:5] cmd.remove(skey + ' and not name N+C+O+OXT+CA') cmd.align(tmp_name, skey + ' and name N+C+CA', cycles=0) cmd.remove(tmp_name + ' and (name N+C+O+CA or hydro)') cmd.fuse('name CB and ' + tmp_name, 'name CA and ' + skey, move=0) if resn == 'PRO': cmd.bond(skey + '/N', skey + '/CD') cmd.unpick() cmd.delete(tmp_name) sele_dict[key[0]].append(skey) if not quiet: print(' Mutated ' + skey) except: print(' Mutating ' + skey + ' failed') for model in sele_dict: cmd.sort(model) sculpt_relax(' '.join(sele_dict[model]), 0, 0, model, cycles) cmd.delete(namedsele)
def number_residues(selection): """ DESCRIPTION Number residues in a peptid chain USAGE number_residues selection ARGUMENTS selection = a selection containing the peptide chain """ logger.debug('number_residues in selection "{}"'.format(selection)) cmd.alter(selection, 'resv={}'.format(0)) peptide_bonds = list(find_peptide_bonds(selection)) logger.debug('Number of peptide bonds found: {}'.format( len(peptide_bonds))) for i, n in enumerate([n for h, n, c, o in peptide_bonds]): cmd.alter('(idx {}) and ({})'.format(n, selection), 'resv={}'.format(i + 1)) for i, n in enumerate([n for h, n, c, o in peptide_bonds]): flood_fill_resi(n, get_resv(n, selection), [c for h, n, c, o in peptide_bonds], selection) # now set the residue index of the amide bond C=O-s for h, n, c, o in peptide_bonds: for idx in iterate_neighbours(c, selection): if not cmd.count_atoms( '(idx {}) and ({}) and (idx {} or idx {})'.format( idx, selection, n, o)): # this is the alpha carbon of the current residue cmd.alter( '(idx {} or idx {}) and ({})'.format(c, o, selection), 'resv={}'.format(get_resv(idx, selection))) cmd.sort(selection) # now residue "0" will be the n-terminal residue. Adjust the numbers to be consecutive residue_order = [] pairs = [(get_resv(c, selection), get_resv(n, selection)) for h, n, c, o in peptide_bonds] residue_order = list(pairs[0]) while True: # try to add the next number at the end try: nextpair = [p for p in pairs if p[0] == residue_order[-1]][0] residue_order.append(nextpair[1]) continue except IndexError: pass try: prevpair = [p for p in pairs if p[1] == residue_order[0]][0] residue_order.insert(0, prevpair[0]) continue except IndexError: pass break indices_for_residues = [ list(iterate_indices('({}) and (resi {})'.format(selection, resi))) for resi in range(len(peptide_bonds) + 1) ] for newresi, oldresi in enumerate(residue_order): sel = '({}) and '.format(selection) + '(idx ' + '+'.join( [str(i) for i in indices_for_residues[oldresi]]) + ')' logger.debug('SEL: {}'.format(sel)) cmd.alter(sel, 'resv={}'.format(newresi)) cmd.sort(selection) return list(range(len(peptide_bonds) + 1))
def recognize_peptide(rtpfile, selection='all'): """ DESCRIPTION Analyze a model, assign chain and residue IDs and name atoms according to a GROMACS forcefield USAGE recognize_peptide rtpfile [, selection] ARGUMENTS rtpfile = a GROMACS residue database (.rtp file) or a GROMACS forcefield directory selection = selected group of atoms to operate on. Defaults to 'all'. NOTES First the selection is divided into chains according to connectivity. Each chain is subsequently divided into residues by finding peptide bonds. The residues are numbered consecutively from 0, starting at the N terminus. Lastly, every residue of every chain is compared to the entries in the rtp file and if matching is found, the residue name and atom names are updated. CAVEATS The residue matching is done using graph isomorphism (VF2 algorithm, as implemented by the networkx package), taking only bonds and element symbols into account. This has the following consequences: 1) There is no distinction between ligands of the same element. E.g. the naming of the two hydrogens bound to the nitrogen of the amide group at the end of the sidechain of Gln and Asn is undefined, although they have slightly different partial charges in the Charmm36m forcefield. This has to be fixed by the user. 2) If the RTP file contains isomorphous residues, the first one will be matched. A typical example for this is stereoisomeric amino acids: e.g. ALA and DALA, GLN and DGLN in the Charmm36m forcefield. This also needs to be fixed by the user. """ chains = number_chains(selection) rtpdata = list(graphs_from_rtp(rtpfile)) for ch in chains: print('Looking at chain {}'.format(ch)) residues = number_residues('({}) and (chain {})'.format(selection, ch)) print(' Found residues {} to {}'.format(min(residues), max(residues))) for r in residues: # analyze each residue resn = match_amino_acid( '({}) and (chain {}) and (resi {})'.format(selection, ch, r), rtpdata) if resn is not None: print(' Residue {}/{}/ {}'.format(ch, r, resn)) else: print(' Residue {}/{}/ not matched'.format(ch, r)) if resn in ['B3Q', 'DB3Q']: fix_gln_hydrogens('({}) and (chain {}) and (resi {})'.format( selection, ch, r)) cmd.sort()
def morpheasy(source, target, source_state=0, target_state=0, name=None, refinement=5, quiet=1): ''' DESCRIPTION Morph source to target, based on sequence alignment USAGE morpheasy source, target [, source_state [, target_state [, name ]]] EXAMPLE fetch 1akeA 4akeA, async=0 extra_fit morpheasy 1akeA, 4akeA ''' try: from epymol import rigimol except ImportError: print 'No epymol available, please use a "Incentive PyMOL" build' print 'You may use "morpheasy_linear" instead' return from .editing import mse2met from .querying import get_selection_state # arguments source_state = int(source_state) target_state = int(target_state) refinement = int(refinement) quiet = int(quiet) if source_state < 1: source_state = get_selection_state(source) if target_state < 1: target_state = get_selection_state(target) # temporary objects # IMPORTANT: cmd.get_raw_alignment does not work with underscore object names! alnobj = cmd.get_unused_name('_aln') so_obj = cmd.get_unused_name('source') # see above ta_obj = cmd.get_unused_name('target') # see above so_sel = cmd.get_unused_name('_source_sel') ta_sel = cmd.get_unused_name('_target_sel') cmd.create(so_obj, source, source_state, 1) cmd.create(ta_obj, target, target_state, 1) mse2met(so_obj) mse2met(ta_obj) # align sequence cmd.align(ta_obj, so_obj, object=alnobj, cycles=0, transform=0, mobile_state=1, target_state=1) cmd.refresh() cmd.select(so_sel, '%s and %s' % (so_obj, alnobj)) cmd.select(ta_sel, '%s and %s' % (ta_obj, alnobj)) alnmap = dict(cmd.get_raw_alignment(alnobj)) alnmap.update(dict((v,k) for (k,v) in alnmap.iteritems())) # copy source atom identifiers to temporary target idmap = dict() cmd.iterate(so_sel, 'idmap[model,index] = (segi,chain,resi,resn,name)', space={'idmap': idmap}) cmd.alter(ta_sel, '(segi,chain,resi,resn,name) = idmap[alnmap[model,index]]', space={'idmap': idmap, 'alnmap': alnmap}) # remove unaligned cmd.remove('%s and not %s' % (so_obj, so_sel)) cmd.remove('%s and not %s' % (ta_obj, ta_sel)) assert cmd.count_atoms(so_obj) == cmd.count_atoms(ta_obj) cmd.sort(so_obj) cmd.sort(ta_obj) # append target to source as 2-state morph-in object cmd.create(so_obj, ta_obj, 1, 2) # morph if name is None: name = cmd.get_unused_name('morph') rigimol.morph(so_obj, name, refinement=refinement, async=0) # clean up for obj in [alnobj, so_obj, so_sel, ta_obj, ta_sel]: cmd.delete(obj) return name
def morpheasy(source, target, source_state=0, target_state=0, name=None, refinement=5, quiet=1): ''' DESCRIPTION Morph source to target, based on sequence alignment USAGE morpheasy source, target [, source_state [, target_state [, name ]]] EXAMPLE fetch 1akeA 4akeA, async=0 extra_fit morpheasy 1akeA, 4akeA ''' try: from epymol import rigimol except ImportError: print('No epymol available, please use a "Incentive PyMOL" build') print('You may use "morpheasy_linear" instead') return from .editing import mse2met from .querying import get_selection_state # arguments source_state = int(source_state) target_state = int(target_state) refinement = int(refinement) quiet = int(quiet) if source_state < 1: source_state = get_selection_state(source) if target_state < 1: target_state = get_selection_state(target) # temporary objects # IMPORTANT: cmd.get_raw_alignment does not work with underscore object names! alnobj = cmd.get_unused_name('_aln') so_obj = cmd.get_unused_name('source') # see above ta_obj = cmd.get_unused_name('target') # see above so_sel = cmd.get_unused_name('_source_sel') ta_sel = cmd.get_unused_name('_target_sel') cmd.create(so_obj, source, source_state, 1) cmd.create(ta_obj, target, target_state, 1) mse2met(so_obj) mse2met(ta_obj) # align sequence cmd.align(ta_obj, so_obj, object=alnobj, cycles=0, transform=0, mobile_state=1, target_state=1) cmd.refresh() cmd.select(so_sel, '%s and %s' % (so_obj, alnobj)) cmd.select(ta_sel, '%s and %s' % (ta_obj, alnobj)) alnmap = dict(cmd.get_raw_alignment(alnobj)) alnmap.update(dict((v, k) for (k, v) in alnmap.items())) # copy source atom identifiers to temporary target idmap = dict() cmd.iterate(so_sel, 'idmap[model,index] = (segi,chain,resi,resn,name)', space={'idmap': idmap}) cmd.alter(ta_sel, '(segi,chain,resi,resn,name) = idmap[alnmap[model,index]]', space={ 'idmap': idmap, 'alnmap': alnmap }) # remove unaligned cmd.remove('%s and not %s' % (so_obj, so_sel)) cmd.remove('%s and not %s' % (ta_obj, ta_sel)) assert cmd.count_atoms(so_obj) == cmd.count_atoms(ta_obj) cmd.sort(so_obj) cmd.sort(ta_obj) # append target to source as 2-state morph-in object cmd.create(so_obj, ta_obj, 1, 2) # morph if name is None: name = cmd.get_unused_name('morph') rigimol.morph(so_obj, name, refinement=refinement, async=0) # clean up for obj in [alnobj, so_obj, so_sel, ta_obj, ta_sel]: cmd.delete(obj) return name
def add_missing_atoms(selection='all', cycles=200, quiet=1): ''' DESCRIPTION Mutate those residues to themselves which have missing atoms SEE ALSO stub2ala ''' from collections import defaultdict from chempy import fragments cycles, quiet = int(cycles), int(quiet) reference = { 'ALA': set(['CB']), 'ARG': set(['CB', 'CG', 'NE', 'CZ', 'NH1', 'NH2', 'CD']), 'ASN': set(['CB', 'CG', 'OD1', 'ND2']), 'ASP': set(['CB', 'CG', 'OD1', 'OD2']), 'CYS': set(['CB', 'SG']), 'GLN': set(['CB', 'CG', 'CD', 'NE2', 'OE1']), 'GLU': set(['CB', 'CG', 'OE2', 'CD', 'OE1']), 'GLY': set([]), 'HIS': set(['CE1', 'CB', 'CG', 'CD2', 'ND1', 'NE2']), 'ILE': set(['CB', 'CD1', 'CG1', 'CG2']), 'LEU': set(['CB', 'CG', 'CD1', 'CD2']), 'LYS': set(['CB', 'CG', 'NZ', 'CE', 'CD']), 'MET': set(['CB', 'CG', 'CE', 'SD']), 'PHE': set(['CE1', 'CB', 'CG', 'CZ', 'CD1', 'CD2', 'CE2']), 'PRO': set(['CB', 'CG', 'CD']), 'SER': set(['OG', 'CB']), 'THR': set(['CB', 'OG1', 'CG2']), 'TRP': set(['CZ2', 'CB', 'CG', 'CH2', 'CE3', 'CD1', 'CD2', 'CZ3', 'NE1', 'CE2']), 'TYR': set(['CE1', 'OH', 'CB', 'CG', 'CZ', 'CD1', 'CD2', 'CE2']), 'VAL': set(['CB', 'CG1', 'CG2']), } namedsele = cmd.get_unused_name('_') cmd.select(namedsele, selection, 0) namelists = defaultdict(list) cmd.iterate('(%s) and polymer' % namedsele, 'namelists[model,segi,chain,resn,resi,resv].append(name)', space=locals()) sele_dict = defaultdict(list) tmp_name = cmd.get_unused_name('_') for key, namelist in namelists.items(): resn = key[3] if resn not in reference: if not quiet: print(' Unknown residue:', resn) continue if not reference[resn].issubset(namelist): try: frag = fragments.get(resn.lower()) for a in frag.atom: a.segi = key[1] a.chain = key[2] a.resi = key[4] a.resi_number = key[5] cmd.load_model(frag, tmp_name, 1, zoom=0) skey = '/%s/%s/%s/%s`%s' % key[:5] cmd.remove(skey + ' and not name N+C+O+OXT+CA') cmd.align(tmp_name, skey + ' and name N+C+CA', cycles=0) cmd.remove(tmp_name + ' and (name N+C+O+CA or hydro)') cmd.fuse('name CB and ' + tmp_name, 'name CA and ' + skey, move=0) if resn == 'PRO': cmd.bond(skey + '/N', skey + '/CD') cmd.unpick() cmd.delete(tmp_name) sele_dict[key[0]].append(skey) if not quiet: print(' Mutated ', skey) except: print(' Mutating', skey, 'failed') for model in sele_dict: cmd.sort(model) sculpt_relax(' '.join(sele_dict[model]), 0, 0, model, cycles) cmd.delete(namedsele)