def _newResidue(model, name): # find an number unused in both the 'het' and 'water' chains... pos = 1 while model.findResidue(chimera.MolResId('het', pos)) \ or model.findResidue(chimera.MolResId('water', pos)): pos += 1 return model.newResidue(name, 'het', pos, ' ')
def create_box(self): m = chimera.Molecule() m.name = 'Subregion Selection Box' chimera.openModels.add([m], noprefs=True) chimera.addModelClosedCallback(m, self.model_closed_cb) rid = chimera.MolResId(1) r = m.newResidue('markers', rid) corners = [] for name in ('a000', 'a001', 'a010', 'a011', 'a100', 'a101', 'a110', 'a111'): a = m.newAtom(name, chimera.elements.H) r.addAtom(a) corners.append(a) green = chimera.MaterialColor(0, 1, 0, 1) for a1, a2 in ((0, 1), (2, 3), (4, 5), (6, 7), (0, 2), (1, 3), (4, 6), (5, 7), (0, 4), (1, 5), (2, 6), (3, 7)): b = m.newBond(corners[a1], corners[a2]) b.halfbond = 0 b.drawMode = chimera.Bond.Wire b.color = green return corners
def make_model(self, length, thickness, rgb, label, xy_offset, label_rgb, model_id): m = chimera.Molecule() m.name = 'scale bar' # # Need to create a residue because atom without residue causes # unknown C++ exceptions. # rid = chimera.MolResId(1) r = m.newResidue('sb', rid) atoms = [] for name, pos in (('1', (-length / 2.0, 0, 0)), ('2', (length / 2.0, 0, 0)), ('label', (xy_offset[0], xy_offset[1] + thickness / 2.0, 0))): a = m.newAtom(name, chimera.elements.H) r.addAtom(a) c = chimera.Coord() c.x, c.y, c.z = pos a.setCoord(c) # a.coord = c does not work a.display = 0 atoms.append(a) m.atom1, m.atom2, m.label_atom = atoms m.label_atom.color = background_color() m.label_atom.display = 1 b = m.newBond(m.atom1, m.atom2) b.display = b.Always b.drawMode = b.Stick b.radius = thickness / 2.0 b.color = chimera_color(rgb) b.halfbond = 0 m.label_atom.label = label m.label_atom.labelColor = chimera_color(label_rgb) self.model = m if model_id == None: id, subid = (self.model_id(), chimera.openModels.Default) else: id, subid = model_id chimera.openModels.add([m], baseId=id, subid=subid) chimera.addModelClosedCallback(m, self.model_closed_cb) import SimpleSession SimpleSession.noAutoRestore(m) m.openState.active = False z_near, z_far = clip_plane_positions() self.set_depth(.5 * (z_near + z_far)) self.set_screen_position(self.screen_position) self.orientation_cb() return m
def toChimeraResId(resid): """Take a Modeller residue id and convert it to a chimera one""" num, chain = resid.split(':') insertCode = '' while not str.isdigit(num[-1]): insertCode = num[-1] + insertCode num = num[:-1] pos = int(num) return chimera.MolResId(chain, pos, insert=insertCode)
def makedock(dirname, residueIds, outsideAtoms): outfn = os.path.join(dirname, 'dock.ent') out = open(outfn, 'w') found_file = False outsideResidueIds = set([id for id, name in outsideAtoms]) def isOutside(id, name): if id not in outsideResidueIds: return False name = name.strip() for oid, oname in outsideAtoms: if id == oid and name == oname: return True return False for fn in os.listdir(dirname): if not fn.endswith('.pdb') or not pat.match(fn): continue found_file = True number = int(fn[-12:-8]) print >> out, "REMARK Number:", number conect = set() f = open(os.path.join(dirname, fn), 'rU') for line in f: if line.startswith('CONECT'): serial = int(line[6:11]) if serial in conect: out.write(line) continue if not line.startswith('ATOM') \ and not line.startswith('HETATM'): out.write(line) continue chain = line[21] pos = int(line[22:26]) insertCode = line[26] id = chimera.MolResId(chain, pos, insert=insertCode) if id in residueIds or isOutside(id, line[12:16]): serial = int(line[6:11]) conect.add(serial) out.write(line) f.close() out.close() if found_file: return outfn os.remove(outfn) return None
def build_chimera_molecule(mmlib_structure): from mmLib.Structure import fragment_id_split import chimera import numpy from string import letters modelMap = {} # mmLib structure to Chimera molecule atoms = {} # mmLib atom to chimera atom mapping residues = {} # fragment to chimera residue mapping seq2frag = {} # entity-sequence to fragment mapping sa2r = {} # sequence-asym_id to chimera residue mapping e2c = {} # entity to chain mapping # Make molecules for mm in mmlib_structure.iter_models(): m = chimera.Molecule() modelMap[mm] = m seq2frag[m] = {} sa2r[m] = {} e2c[m] = {} # Make atoms and residues as needed name_to_element = element_table() for mm in mmlib_structure.iter_models(): m = modelMap[mm] for ma in mm.iter_all_atoms(): mf = ma.get_fragment() try: chain_id = ma.asym_id.strip() except AttributeError: chain_id = ma.chain_id.strip() try: r = residues[mf] except KeyError: seq, icode = fragment_id_split(mf.fragment_id) if icode is None: rid = chimera.MolResId(chain_id, seq) else: rid = chimera.MolResId(chain_id, seq, insert=icode) r = m.newResidue(mf.res_name, rid) residues[mf] = r if not mf.is_standard_residue(): r.isHet = True sf_key = (ma.label_entity_id, ma.label_seq_id) d = seq2frag[m].setdefault(sf_key, {}) d[chain_id] = mf sa2r[m][(ma.label_seq_id, ma.label_asym_id)] = r s = e2c[m].setdefault(ma.label_entity_id, set([])) s.add(chain_id) if not ma.element: ename = ma.name[0] if len(ma.name) > 1 and ma.name[1] in letters: ename += ma.name[1].lower() elif len(ma.element) > 1: ename = ma.element[0].upper() + ma.element[1:].lower() else: ename = ma.element try: element = name_to_element[ename] except KeyError: # Don't know what it is, guess carbon element = name_to_element['C'] a = m.newAtom(ma.name.replace('*', "'"), element) a.altLoc = ma.alt_loc c = chimera.Coord() c.x, c.y, c.z = ma.position a.setCoord(c) # a.coord = c does not work a.bfactor = ma.temp_factor a.occupancy = ma.occupancy if ma.U is not None: a.anisoU = numpy.array(ma.U, 'f') atoms[ma] = a r.addAtom(a) # Make bonds numBonds = 0 for mm in mmlib_structure.iter_models(): m = modelMap[mm] for ma in mm.iter_all_atoms(): for mb in ma.iter_bonds(): a1 = atoms[mb.get_atom1()] a2 = atoms[mb.get_atom2()] try: m.newBond(a1, a2) except TypeError: pass else: numBonds += 1 # Make inter-residue bonds from chimera.resCode import res3to1 from chimera import Sequence residueAfter = {} try: table = mmlib_structure.cifdb["entity_poly_seq"] except KeyError: pass else: for m in modelMap.itervalues(): seqMap = {} prevEntity = None prevDict = None for row in table.iter_rows(): thisEntity = row["entity_id"] try: chains = e2c[m][thisEntity] except KeyError: pass else: monomer = res3to1(row["mon_id"]) for chainId in chains: try: seq = seqMap[chainId] except KeyError: if chainId == " ": name = Sequence.PRINCIPAL else: name = Sequence.CHAIN_FMT % chainId seq = Sequence.Sequence(name) seqMap[chainId] = seq seq.append(monomer) num = row["num"] try: thisDict = seq2frag[m][(thisEntity, num)] except KeyError: # leave the prev variables so we will connect # residues in the same chain. continue if prevDict is not None and prevEntity == thisEntity: for chain_id, prevR in prevDict.iteritems(): try: thisR = thisDict[chain_id] except KeyError: continue isAA = thisR.is_amino_acid() isNA = thisR.is_nucleic_acid() wasAA = prevR.is_amino_acid() wasNA = prevR.is_nucleic_acid() if isAA and wasAA: numBonds += connectResidues( prevR, ["C"], thisR, ["N"], atoms, residueAfter) if isNA and wasNA: numBonds += connectResidues( prevR, ["O3'", "O3*"], thisR, ["P"], atoms, residueAfter) prevDict = thisDict prevEntity = thisEntity m.cifPolySeq = seqMap # If no bonds were made, make them if numBonds == 0: import chimera for m in modelMap.itervalues(): chimera.connectMolecule(m) # Assign secondary structure (helix and turn) try: table = mmlib_structure.cifdb["struct_conf"] except KeyError: pass else: for m in modelMap.itervalues(): for row in table.iter_rows(): typeId = row["conf_type_id"] if typeId.startswith("HELX"): ssType = "isHelix" elif typeId.startswith("TURN"): ssType = "isTurn" else: continue bAsymId = row["beg_label_asym_id"] bSeqId = row["beg_label_seq_id"] eAsymId = row["end_label_asym_id"] eSeqId = row["end_label_seq_id"] try: bRes = sa2r[m][(bSeqId, bAsymId)] except KeyError: print "No residue match asym_id=%s seq_id=%s" % (bAsymId, bSeqId) continue try: eRes = sa2r[m][(eSeqId, eAsymId)] except KeyError: print "No residue match asym_id=%s seq_id=%s" % (eAsymId, eSeqId) continue # Make sure we have a clear list of residues # from beginning to end r = bRes while r is not eRes and r is not None: r = residueAfter.get(r, None) if r is None: print "Non-consecutive residues (%s.%s) -> (%s.%s)" % ( bSeqId, bAsymId, eSeqId, eAsymId) continue r = bRes while r is not eRes: setattr(r, ssType, True) r = residueAfter[r] setattr(eRes, ssType, True) # Assign secondary structure (sheet) try: table = mmlib_structure.cifdb["struct_sheet_range"] except KeyError: pass else: for m in modelMap.itervalues(): for row in table.iter_rows(): bAsymId = row["beg_label_asym_id"] bSeqId = row["beg_label_seq_id"] eAsymId = row["end_label_asym_id"] eSeqId = row["end_label_seq_id"] try: bRes = sa2r[m][(bSeqId, bAsymId)] except KeyError: print "No residue match asym_id=%s seq_id=%s" % (bAsymId, bSeqId) continue try: eRes = sa2r[m][(eSeqId, eAsymId)] except KeyError: print "No residue match asym_id=%s seq_id=%s" % (eAsymId, eSeqId) continue # Make sure we have a clear list of residues # from beginning to end r = bRes while r is not eRes and r is not None: r = residueAfter.get(r, None) if r is None: print "Non-consecutive residues (%s.%s) -> (%s.%s)" % ( bSeqId, bAsymId, eSeqId, eAsymId) continue r = bRes while r is not eRes: r.isSheet = True r = residueAfter[r] eRes.isSheet = True # Add any modres information to resCode dictionaries try: table = mmlib_structure.cifdb["struct_conn"] except KeyError: pass else: from chimera import resCode dicts = (resCode.regex3to1, resCode.nucleic3to1, resCode.protein3to1, resCode.standard3to1) for row in table.iter_rows(): if row["conn_type_id"] != "modres": continue try: name = row["ptnr1_auth_comp_id"] except KeyError: name = row["ptnr1_label_comp_id"] stdName = row["pdbx_ptnr1_standard_comp_id"] for d in dicts: if stdName in d: d[name] = d[stdName] return modelMap.values()
def ReadMol ( fpath, log=False ) : from random import random cif, loops = ReadCif ( fpath, log ) # descriptions by chain id: descrByEntityId = GetEntityDescr ( cif, loops ) try : atoms = loops['_atom_site']['data'] print " - %d atom records" % len(atoms) except : print " - no atoms in cif?" return None labels = loops['_atom_site']['labels'] if 0 : print "Labels:" for l in labels : print " : ", l import time start = time.time() rmap = {} nmol = chimera.Molecule() from os import path #nmol.name = path.splitext ( path.split (fpath)[1] )[0] nmol.name = path.split (fpath) [1] nmol.openedAs = [ fpath, [] ] nmol.cif = cif nmol.cifLoops = loops nmol.chainColors = {} nmol.chainDescr = {} numQ = 0 first = True for at in atoms : mp = at['asMap'] if log and first : #for label, val in mp.iteritems () : for li, label in enumerate ( labels ) : print " %d : %s : %s" % (li+1, label, mp[label]) first = False atType = mp['type_symbol'] atName = mp['label_atom_id'] rtype = mp['label_comp_id'] chainId = mp['label_asym_id'] chainEId = mp['label_entity_id'] px = mp['Cartn_x'] py = mp['Cartn_y'] pz = mp['Cartn_z'] occ = mp['occupancy'] bfactor = mp['B_iso_or_equiv'] altLoc = mp['label_alt_id'] if altLoc == "." : altLoc = '' if chainEId in descrByEntityId : nmol.chainDescr [chainId] = descrByEntityId [chainEId] resId = ResId ( mp ) if resId == None : continue ris = "%s%d" % (chainId, resId) res = None if not ris in rmap : res = nmol.newResidue ( rtype, chimera.MolResId(chainId, resId) ) rmap[ris] = res else : res = rmap[ris] clr = None if not chainId in nmol.chainColors : clr = chimera.MaterialColor ( random(), random(), random(), 1.0 ) nmol.chainColors[chainId] = clr if 0 and log : print " - chain %s" % chainId else : clr = nmol.chainColors [chainId] nat = nmol.newAtom ( atName, chimera.Element(atType) ) drawRib = rtype in protein3to1 or rtype in nucleic3to1 #aMap[at] = nat res.addAtom( nat ) nat.setCoord ( chimera.Point( float(px), float(py), float(pz) ) ) nat.altLoc = altLoc nat.occupancy = float(occ) nat.bfactor = float(bfactor) if 'Q-score' in mp : try : Q = float ( mp['Q-score'] ) nat.Q = Q numQ += 1 except : #print " - q score is", mp['Q-score'] pass end = time.time() print " - created %d atoms, %.1fs, %d q-scores" % ( len(nmol.atoms), end-start, numQ ) return nmol
def LoadMolCh_ ( fpath, log=False, task=None ) : mol = ReadMol ( fpath, log=False ) from chimera.resCode import nucleic3to1 from chimera.resCode import protein3to1, protein1to3 protein3to1['HSD'] = protein3to1['HIS'] protein3to1['HSE'] = protein3to1['HIS'] nucleic1to3 = { 'T':'THY', 'C':'CYT', 'G':'GUA', 'A':'ADE', 'U':'URA'} nucleic3to1['GDP'] = nucleic3to1['GUA'] crmap = {} rmolmap = {} print " - adding bonds" import time start = time.time() for r in mol.residues : if not r.id.chainId in crmap : crmap[r.id.chainId] = { r.id.position : r } else : crmap[r.id.chainId][r.id.position] = r chains = mol.chainColors.keys() print "%d residues - %d chains" % ( len(mol.residues), len(chains) ) from os.path import splitext chMols = {} for ch in chains : start = time.time() chMol = chimera.Molecule() chMol.name = splitext ( mol.name )[0] + "_" + ch rmap0 = crmap[ch] chMols[ch] = chMol print " - %s - %d residues" % (ch, len(rmap0)), rmap = {} for ri, res in rmap0.iteritems() : nr = chMol.newResidue ( res.type, chimera.MolResId(ch, res.id.position) ) rmap[nr.id.position] = nr for at in res.atoms : nat = chMol.newAtom ( at.name, at.element ) nr.addAtom ( nat ) nat.setCoord ( at.coord() ) print ", %d atoms" % len(chMol.atoms), for ri, r in rmap.iteritems() : #if ri % 100 == 0 : # print "%d/%d" % ( ri, len(mol.residues) ) # if task : # task.updateStatus( "%d/%d" % ( ri, len(mol.residues) ) ) rmol = None rtype = r.type.upper() if rtype.lower() in rmolmap : rmol = rmolmap[ rtype.lower() ] else : rmol = GetResMol ( rtype.lower() ) if rmol != None : rmolmap[rtype.lower()] = rmol if rmol != None : for b in rmol.bonds : a1n, a2n = b.atoms[0].name, b.atoms[1].name if a1n in r.atomsMap and a2n in r.atomsMap : for a1 in r.atomsMap[a1n] : for a2 in r.atomsMap[a2n] : #print "%s - %s" % ( At(a1), At(a2) ) nb = chMol.newBond ( a1, a2 ) pass else : print " - rmol %s not found" % rtype if 1 : if r.type.upper() in protein3to1 : if r.id.position-1 in rmap : pres = rmap[r.id.position-1] if pres.type.upper() in protein3to1 : #GetSS ( pres, r ) if "C" in pres.atomsMap and "N" in r.atomsMap : for a1 in pres.atomsMap["C"] : for a2 in r.atomsMap["N"] : #print a1.name, pres.id.position, a2.name, r.id.position nb = chMol.newBond ( a1, a2 ) pass if r.type.upper() in nucleic1to3 or r.type.upper() in nucleic3to1 : if r.id.position-1 in rmap : pres = rmap[r.id.position-1] if pres.type.upper() in nucleic1to3 or pres.type.upper() in nucleic3to1 : if "O3'" in pres.atomsMap and "P" in r.atomsMap : for a1 in pres.atomsMap["O3'"] : for a2 in r.atomsMap["P"] : #print a1.name, pres.id.position, a2.name, r.id.position nb = chMol.newBond ( a1, a2 ) pass print ( ", %d bonds, %.1fs" % (len(chMol.bonds), time.time()-start) ) #start = time.time() #chimera.openModels.add ( [chMol] ) #print " - added mol %ss, %.1fs" % (chMol.name, time.time()-start) start = time.time() for r in chMol.residues : rt = r.type.upper() if rt in protein3to1 or rt in nucleic3to1 or rt in nucleic1to3 : r.ribbonDisplay = True r.ribbonDrawMode = 2 r.ribbonColor = mol.chainColors[r.id.chainId] for at in r.atoms : at.display = False at.drawMode = at.EndCap if at.element.name.upper() in atomColors : at.color = atomColors[at.element.name.upper()] else : at.color = mol.chainColors[r.id.chainId] else : for at in r.atoms : at.display = True at.drawMode = at.EndCap if at.element.name.upper() in atomColors : at.color = atomColors[at.element.name.upper()] else : at.color = mol.chainColors[r.id.chainId] for b in mol.bonds : b.drawMode = b.Stick b.display = b.Smart #print " - changed mol disp %s - %.1fs" % (chMol.name, time.time()-start) return mol
def molecule_from_atoms(m, atoms): import chimera cm = chimera.Molecule() cm.color = m.color cm.display = m.display for attr in ('name', 'openedAs'): if hasattr(m, attr): setattr(cm, attr, getattr(m, attr)) if hasattr(m, 'pdbHeaders'): cm.setAllPDBHeaders(m.pdbHeaders) rmap = {} rlist = atom_residues(atoms) rlist.sort(lambda r1, r2: cmp(r1.id.position, r2.id.position)) for r in rlist: crid = chimera.MolResId(r.id.chainId, r.id.position) cr = cm.newResidue(r.type, crid) cr.isHet = r.isHet cr.isHelix = r.isHelix cr.isSheet = r.isSheet cr.isTurn = r.isTurn cr.ribbonColor = r.ribbonColor cr.ribbonStyle = r.ribbonStyle cr.ribbonDrawMode = r.ribbonDrawMode cr.ribbonDisplay = r.ribbonDisplay rmap[r] = cr amap = {} for a in atoms: ca = cm.newAtom(a.name, a.element) ca.setCoord(a.coord()) ca.altLoc = a.altLoc ca.color = a.color ca.drawMode = a.drawMode ca.display = a.display if hasattr(a, 'bfactor'): ca.bfactor = a.bfactor amap[a] = ca cr = rmap[a.residue] cr.addAtom(ca) for b in atom_bonds(atoms): a1, a2 = b.atoms cb = cm.newBond(amap[a1], amap[a2]) cb.color = b.color cb.drawMode = b.drawMode cb.display = b.display for am in m.associatedModels(): if not isinstance(am, chimera.PseudoBondGroup): continue if not am.category.startswith("coordination complexes"): continue for pb in am.pseudoBonds: a1, a2 = pb.atoms if a1 not in amap or a2 not in amap: continue cm.newBond(amap[a1], amap[a2]) return cm
def placePeptide(sequence, phiPsis, model="scratch", position=None, rotlib=None, chainID='A'): """place a peptide sequence 'sequence' contains the (upper case) sequence 'phiPsis' is a list of phi/psi tuples, one per residue 'model' can either be a chimera.Molecule instance or a string. If the latter, then a new model is created with the string as its .name attribute. 'position' can either be a chimera.Point or None. If None, then the fragment is positioned at the center of the view. """ if not sequence: raise ValueError("No sequence supplied") sequence = sequence.upper() if not sequence.isupper(): raise ValueError("Sequence contains non-alphabetic characters") from chimera.resCode import protein1to3 for c in sequence: if c not in protein1to3: raise ValueError("Unrecognized protein 1-letter code:" " %s" % c) if len(sequence) != len(phiPsis): raise ValueError("Number of phi/psis not equal to" " sequence length") if isinstance(model, basestring): model = _newModel(model) needFocus = False if position is None: if len(chimera.openModels.list()) == 1: needFocus = True xf = model.openState.xform position = xf.inverse().apply(Point(*chimera.viewer.camera.center)) prev = [None] * 3 pos = 1 from Midas.addAA import DIST_N_C, DIST_CA_N, DIST_C_CA, DIST_C_O from chimera.molEdit import findPt, addAtom, addDihedralAtom serialNumber = None residues = [] for c, phiPsi in zip(sequence, phiPsis): phi, psi = phiPsi while model.findResidue(chimera.MolResId(chainID, pos)): pos += 1 r = model.newResidue(protein1to3[c], chainID, pos, ' ') residues.append(r) for backbone, dist, angle, dihed in (('N', DIST_N_C, 116.6, psi), ('CA', DIST_CA_N, 121.9, 180.0), ('C', DIST_C_CA, 110.1, phi)): if prev[0] == None: pt = Point(0.0, 0.0, 0.0) elif prev[1] == None: pt = Point(dist, 0.0, 0.0) elif prev[2] == None: pt = findPt(prev[0].coord(), prev[1].coord(), Point(0.0, 1.0, 0.0), dist, angle, 0.0) else: pt = findPt(prev[0].coord(), prev[1].coord(), prev[2].coord(), dist, angle, dihed) a = addAtom(backbone, Element(backbone[0]), r, pt, serialNumber=serialNumber, bondedTo=prev[0]) serialNumber = a.serialNumber + 1 prev = [a] + prev[:2] o = addDihedralAtom("O", Element("O"), prev[0], prev[1], prev[2], DIST_C_O, 120.4, 180.0 + psi, bonded=True) # C terminus O/OXT at different angle than mainchain O model.deleteAtom(o) addDihedralAtom("O", Element("O"), prev[0], prev[1], prev[2], DIST_C_O, 117.0, 180.0 + psi, bonded=True) addDihedralAtom("OXT", Element("O"), prev[0], prev[1], prev[2], DIST_C_O, 117.0, psi, bonded=True) from Rotamers import useBestRotamers # have to process one by one, otherwise side-chain clashes will occur kw = {} if rotlib: kw['lib'] = rotlib for r in residues: useBestRotamers("same", [r], criteria="cp", log=False, **kw) # find peptide center coords = [] for r in residues: coords.extend([a.coord() for a in r.atoms]) center = Point(coords) correction = position - center for r in residues: for a in r.atoms: a.setCoord(a.coord() + correction) from Midas import ksdssp ksdssp([model]) if needFocus: chimera.runCommand("focus") return residues
def addAA(residue_type, residue_seq, last_res, conformation=None): """add an amino acid to a model. """ phi, psi = getPhiPsiVals(conformation) if not isLastRes(last_res): raise AddAAError, "Can only add to last residue." last_bbone_ats = {} ## find 'C' atom of last residue last_C = getBboneAtom(last_res, 'C') if not last_C: raise AddAAError, "Couldn't find 'C' backbone atom of last residue" else: last_bbone_ats['C'] = last_C ## find 'CA' atom of last residue last_CA = getBboneAtom(last_res, 'CA') if not last_CA: raise AddAAError, "Couldn't find 'CA' backbone atom of last residue" else: last_atom_drawMode = last_CA.drawMode last_bond_drawMode = last_CA.bondsMap[last_C].drawMode last_bbone_ats['CA'] = last_CA ## find 'N' atom of last residue last_N = getBboneAtom(last_res, 'N') if not last_N: raise AddAAError, "Couldn't find 'N' backbone atom of last residue" else: last_bbone_ats['N'] = last_N ## find 'O' atom of last residue last_O = getBboneAtom(last_res, 'O') if not last_O: raise AddAAError, "Couldn't find 'O' backbone atom of last residue" else: last_bbone_ats['O'] = last_O ## make a new residue insert_char = residue_seq[-1] if insert_char.isalpha(): ## insertion specified residue_seq = residue_seq[:-1] else: insert_char = ' ' if residue_seq.isdigit(): residue_seq = int(residue_seq) else: raise AddAAError, "Residue sequence argument can contain at most one insertion character" mol = last_res.molecule mrid = chimera.MolResId(last_res.id.chainId, residue_seq, insert=insert_char) if mol.findResidue(mrid): raise AddAAError, "Can't add amino acid, model already contains residue with sequence '%s'." % \ residue_seq new_res = mol.newResidue(residue_type, mrid, neighbor=last_res, after=True) if conformation == 'alpha': new_res.isHelix = True elif conformation in ('abeta', 'pbeta'): new_res.isSheet = True bFac = getBFactor(mol) ## now delete any terminal atoms from the last residue, if there is one ## there. try: pruneLastResidue(last_res) except AddAAError, what: cleanUp(mol, new_res, []) raise AddAAError, what