def marker_molecule(self, model_id=None): if self.molecule == None: from chimera import Molecule, openModels m = Molecule() m.name = self.name if model_id == None: id = subid = openModels.Default else: id, subid = model_id self.set_marker_molecule(m) openModels.add([m], baseId=id, subid=subid, noprefs=True) return self.molecule
def rgba(self, allow_none=False): if allow_none and self.bond.color is None: return None import Molecule rgba = Molecule.bond_rgba(self.bond) return rgba
def rgba(self, allow_none=False): if allow_none and self.atom.color is None: return None import Molecule rgba = Molecule.atom_rgba(self.atom) return rgba
def parse_XML_channel(file_path, name, mole_object): xml = parse(file_path) pool = ['Tunnel', 'Pore', 'Path'] for element in pool: i = 1 for tunnel in xml.getElementsByTagName(element): if mole_object.plugin_type == "PyMOL": model = Indexed() individual_model = None else: model = Molecule() individual_model = model.newResidue( "Tunnel_" + str(i), " ", 1, " ") for node in tunnel.getElementsByTagName('Node'): nodes = [ float(node.getAttribute('X')), float(node.getAttribute('Y')), float(node.getAttribute('Z')), float(node.getAttribute('Radius')) ] plugin.append_node(model, nodes, individual_model) model = plugin.make_channel(model, i) i += 1 if mole_object.plugin_type == "PyMOL": plugin.center()
def __init__(self, fileName, ncInfo): from chimera import UserError, Molecule, Element, openModels, replyobj from chimera import Coord, connectMolecule self.name = "Particle trajectory from %s" % fileName self.molecule = m = Molecule() self.isRealMolecule = False try: m.name = ncInfo.title except AttributeError: m.name = fileName tc = Element("Tc") coords = ncInfo.variables['coordinates'] try: pnames = ncInfo.variables['particle_names'] except KeyError: pnames = ["prt"] * len(coords) try: radii = ncInfo.variables['radii'] except KeyError: radii = [1.0] * len(coords) try: mnames = ncInfo.variables['molecule_names'] mnumbers = ncInfo.variables['molecule_numbers'] except KeyError: mnames = ["PRT"] mnumbers = [1] * len(coords) serial = 1 atoms = [] residues = {} for name, radius, crd, mnumber in zip(pnames[:], radii[:], coords[0][:], mnumbers[:]): try: r = residues[mnumber] except KeyError: r = m.newResidue(string(mnames[mnumber - 1]), " ", mnumber, " ") name = string(name) a = m.newAtom(name, tc) atoms.append(a) a.radius = radius r.addAtom(a) a.setCoord(Coord(*tuple(crd))) a.serialNumber = serial serial += 1 try: connections = ncInfo.variables['connections'] except KeyError: connections = [] for i1, i2 in connections[:]: m.newBond(atoms[i1 - 1], atoms[i2 - 1]) csNum = 1 for crds in coords[1:]: cs = m.newCoordSet(csNum) for a, crd in zip(atoms, crds): a.setCoord(Coord(*tuple(crd)), cs) csNum += 1
def createCN(): cn= Molecule() # create an instance of a molecule # r = cn.newResidue(residue type, chain identifier, sequence number, insertion code) r = cn.newResidue("cn", " ", 1, " ") atomC = cn.newAtom("CE", Element("C")) # now create the atoms of the residue. atomN = cn.newAtom("NF", Element("N")) bondLength_cn = 1.156 atomC.setCoord(Coord(0, 0, 0)) atomN.setCoord(Coord(bondLength_cn, 0, 0)) r.addAtom(atomC) r.addAtom(atomN) cn.newBond(atomC, atomN) openModels.add([cn])
def combine(mols, refMol, newChainIDs=True, log=False, returnMapping=False): from chimera import replyobj # figure out residue chain/number remapping origChainIDs = {} numChains = 0 minNums = {} maxNums = {} for m in mols: seenIDs = set() for r in m.residues: chainID = r.id.chainId num = r.id.position key = (m, chainID) if key in minNums: if num > maxNums[key]: maxNums[key] = num elif num < minNums[key]: minNums[key] = num else: minNums[key] = maxNums[key] = num if chainID in seenIDs: continue numChains += 1 seenIDs.add(chainID) origChainIDs.setdefault(chainID, []).append(m) resMap = {} if newChainIDs: if numChains > 62: raise CombineError("More than 62 chains; cannot" " uniquely identify with single characters") from string import uppercase, lowercase, digits possibleIDs = uppercase + lowercase + digits usedChainIDs = set(origChainIDs.keys()) chainIDmap = {} for chainID, idMols in origChainIDs.items(): if len(chainID) > 1: continue chainIDmap[(idMols[0], chainID)] = chainID usedChainIDs.add(chainID) for m in idMols[1:]: for c in possibleIDs: if c not in usedChainIDs: break if log: replyobj.info("Remapping %s chain %s" " to %s\n" % (m, chainID, c)) usedChainIDs.add(c) chainIDmap[(m, chainID)] = c for m in mols: for r in m.residues: chainID = r.id.chainId if len(chainID) > 1: continue resMap[r] = (chainIDmap[(m, chainID)], r.id.position) # handle renumbering for all chains if newChainIDs False, # otherwise just water/het chains offsets = {} for chainID, idMols in origChainIDs.items(): if newChainIDs and len(chainID) < 2: continue minMaxs = [] for m in idMols: mmin = minNums[(m, chainID)] mmax = maxNums[(m, chainID)] for omin, omax in minMaxs: if omin < mmin < omax or omin < mmax < omax: gmax = max([mm[1] for mm in minMaxs]) offset = gmax - mmin + 1 break else: offset = 0 offsets[(m, chainID)] = offset minMaxs.append((mmin+offset, mmax+offset)) if log and offset: replyobj.info("Adding %d to %s chain %s" " numbering\n" % (offset, m, chainID)) for m in mols: for r in m.residues: chainID = r.id.chainId try: offset = offsets[(m, chainID)] except KeyError: continue resMap[r] = (chainID, r.id.position + offset) # combine... from chimera import Atom, Bond, Residue, Molecule combined = Molecule() combined.name = "combination" from SimpleSession.save import optionalAttributes from chimera.molEdit import addAtom atomAttrs = optionalAttributes[Atom].keys() + ['color', 'vdwColor', 'labelColor', 'surfaceColor', 'drawMode', 'display', 'label', 'radius', 'surfaceDisplay', 'surfaceCategory', 'surfaceOpacity', 'vdw'] bondAttrs = optionalAttributes[Bond].keys() + ['drawMode', 'display', 'radius'] resAttrs = optionalAttributes[Residue].keys() + ['ribbonColor', 'labelColor', 'isHelix', 'isSheet', 'isTurn', 'ribbonDrawMode', 'ribbonDisplay', 'label', 'isHet'] serial = 1 atomMap = {} for m in mols: if m.openState == refMol.openState: xform = None else: xform = refMol.openState.xform xform.invert() for r in m.residues: chainID, pos = resMap[r] nr = combined.newResidue(r.type, chainID, pos, r.id.insertionCode) for attrName in resAttrs: try: setattr(nr, attrName, getattr(r, attrName)) except AttributeError: continue ratoms = r.atoms ratoms.sort(lambda a1, a2: cmp(a1.coordIndex, a2.coordIndex)) for a in ratoms: if xform is None: crd = a.coord() else: crd = xform.apply(a.xformCoord()) na = addAtom(a.name, a.element, nr, crd, serialNumber=serial) na.altLoc = a.altLoc atomMap[a] = na serial += 1 for attrName in atomAttrs: try: setattr(na, attrName, getattr(a, attrName)) except AttributeError: continue for b in m.bonds: a1, a2 = b.atoms nb = combined.newBond(atomMap[a1], atomMap[a2]) for attrName in bondAttrs: try: setattr(nb, attrName, getattr(b, attrName)) except AttributeError: continue consensusAttrs = ['color', 'display', 'lineWidth', 'pointSize', 'stickScale', 'surfaceOpacity', 'ballScale', 'vdwDensity', 'autochain', 'ribbonHidesMainchain'] for attrName in consensusAttrs: consensusVal = None for m in mols: val = getattr(m, attrName) if consensusVal == None: consensusVal = val elif val != consensusVal: break else: setattr(combined, attrName, consensusVal) associatedModels = set() for m in mols: associatedModels.update(m.associatedModels()) from chimera import PseudoBondMgr for opbg in PseudoBondMgr.mgr().pseudoBondGroups: if opbg in associatedModels: if opbg.category.startswith("internal-chain-"): continue assert(opbg.category.startswith("coordination complex")) from chimera.misc import getPseudoBondGroup pbg = getPseudoBondGroup("coordination complexes of %s" % combined.name, associateWith=[combined]) for attrName in ['color', 'showStubBonds', 'lineWidth', 'stickScale', 'lineType']: setattr(pbg, attrName, getattr(opbg, attrName)) else: pbg = opbg for opb in opbg.pseudoBonds: oa1, oa2 = opb.atoms na1 = atomMap.get(oa1, oa1) na2 = atomMap.get(oa2, oa2) if oa1 == na1 and oa2 == na2: continue pb = pbg.newPseudoBond(na1, na2) for attrName in ['drawMode', 'display', 'halfbond', 'label', 'color', 'labelColor']: setattr(pb, attrName, getattr(opb, attrName)) if returnMapping: return atomMap, combined return combined
def combine(mols, refMol, newChainIDs=True, log=False, returnMapping=False): from chimera import replyobj # figure out residue chain/number remapping origChainIDs = {} numChains = 0 minNums = {} maxNums = {} for m in mols: seenIDs = set() for r in m.residues: chainID = r.id.chainId num = r.id.position key = (m, chainID) if key in minNums: if num > maxNums[key]: maxNums[key] = num elif num < minNums[key]: minNums[key] = num else: minNums[key] = maxNums[key] = num if chainID in seenIDs: continue numChains += 1 seenIDs.add(chainID) origChainIDs.setdefault(chainID, []).append(m) resMap = {} if newChainIDs: if numChains > 62: raise CombineError("More than 62 chains; cannot" " uniquely identify with single characters") from string import uppercase, lowercase, digits possibleIDs = uppercase + lowercase + digits usedChainIDs = set(origChainIDs.keys()) chainIDmap = {} for chainID, idMols in origChainIDs.items(): if len(chainID) > 1: continue chainIDmap[(idMols[0], chainID)] = chainID usedChainIDs.add(chainID) for m in idMols[1:]: for c in possibleIDs: if c not in usedChainIDs: break if log: replyobj.info("Remapping %s chain %s" " to %s\n" % (m, chainID, c)) usedChainIDs.add(c) chainIDmap[(m, chainID)] = c for m in mols: for r in m.residues: chainID = r.id.chainId if len(chainID) > 1: continue resMap[r] = (chainIDmap[(m, chainID)], r.id.position) # handle renumbering for all chains if newChainIDs False, # otherwise just water/het chains offsets = {} for chainID, idMols in origChainIDs.items(): if newChainIDs and len(chainID) < 2: continue minMaxs = [] for m in idMols: mmin = minNums[(m, chainID)] mmax = maxNums[(m, chainID)] for omin, omax in minMaxs: if omin < mmin < omax or omin < mmax < omax: gmax = max([mm[1] for mm in minMaxs]) offset = gmax - mmin + 1 break else: offset = 0 offsets[(m, chainID)] = offset minMaxs.append((mmin + offset, mmax + offset)) if log and offset: replyobj.info("Adding %d to %s chain %s" " numbering\n" % (offset, m, chainID)) for m in mols: for r in m.residues: chainID = r.id.chainId try: offset = offsets[(m, chainID)] except KeyError: continue resMap[r] = (chainID, r.id.position + offset) # combine... from chimera import Atom, Bond, Residue, Molecule combined = Molecule() combined.name = "combination" from SimpleSession.save import optionalAttributes from chimera.molEdit import addAtom atomAttrs = optionalAttributes[Atom].keys() + [ 'color', 'vdwColor', 'labelColor', 'surfaceColor', 'drawMode', 'display', 'label', 'radius', 'surfaceDisplay', 'surfaceCategory', 'surfaceOpacity', 'vdw' ] bondAttrs = optionalAttributes[Bond].keys() + [ 'drawMode', 'display', 'radius' ] resAttrs = optionalAttributes[Residue].keys() + [ 'ribbonColor', 'labelColor', 'isHelix', 'isSheet', 'isTurn', 'ribbonDrawMode', 'ribbonDisplay', 'label', 'isHet' ] serial = 1 atomMap = {} for m in mols: if m.openState == refMol.openState: xform = None else: xform = refMol.openState.xform xform.invert() for r in m.residues: chainID, pos = resMap[r] nr = combined.newResidue(r.type, chainID, pos, r.id.insertionCode) for attrName in resAttrs: try: setattr(nr, attrName, getattr(r, attrName)) except AttributeError: continue ratoms = r.atoms ratoms.sort(lambda a1, a2: cmp(a1.coordIndex, a2.coordIndex)) for a in ratoms: if xform is None: crd = a.coord() else: crd = xform.apply(a.xformCoord()) na = addAtom(a.name, a.element, nr, crd, serialNumber=serial) na.altLoc = a.altLoc atomMap[a] = na serial += 1 for attrName in atomAttrs: try: setattr(na, attrName, getattr(a, attrName)) except AttributeError: continue for b in m.bonds: a1, a2 = b.atoms nb = combined.newBond(atomMap[a1], atomMap[a2]) for attrName in bondAttrs: try: setattr(nb, attrName, getattr(b, attrName)) except AttributeError: continue consensusAttrs = [ 'color', 'display', 'lineWidth', 'pointSize', 'stickScale', 'surfaceOpacity', 'ballScale', 'vdwDensity', 'autochain', 'ribbonHidesMainchain' ] for attrName in consensusAttrs: consensusVal = None for m in mols: val = getattr(m, attrName) if consensusVal == None: consensusVal = val elif val != consensusVal: break else: setattr(combined, attrName, consensusVal) associatedModels = set() for m in mols: associatedModels.update(m.associatedModels()) from chimera import PseudoBondMgr for opbg in PseudoBondMgr.mgr().pseudoBondGroups: if opbg in associatedModels: if opbg.category.startswith("internal-chain-"): continue assert (opbg.category.startswith("coordination complex")) from chimera.misc import getPseudoBondGroup pbg = getPseudoBondGroup("coordination complexes of %s" % combined.name, associateWith=[combined]) for attrName in [ 'color', 'showStubBonds', 'lineWidth', 'stickScale', 'lineType' ]: setattr(pbg, attrName, getattr(opbg, attrName)) else: pbg = opbg for opb in opbg.pseudoBonds: oa1, oa2 = opb.atoms na1 = atomMap.get(oa1, oa1) na2 = atomMap.get(oa2, oa2) if oa1 == na1 and oa2 == na2: continue pb = pbg.newPseudoBond(na1, na2) for attrName in [ 'drawMode', 'display', 'halfbond', 'label', 'color', 'labelColor' ]: setattr(pb, attrName, getattr(opb, attrName)) if returnMapping: return atomMap, combined return combined
def readAIM(fileName): import re from OpenSave import osOpen from chimera import UserError, Molecule, Element, openModels, replyobj from chimera import Coord, connectMolecule, MaterialColor anums = {} ## Open the file getatoms = osOpen(fileName) ## Search for the string: ## 'Number of NACPs' ## which gives us the number of atoms ## and store it in numAtoms for data in getatoms: data = data.strip() if data.startswith("Number of NACPs"): a,b,c,d,e = data.split() numAtoms = int(e) getatoms.close() ################################################################### f = osOpen(fileName) readAtoms = 0 state = "init" ## Skip the 26 header lines from the mpgviz file #f = f.readlines()[4:] for lines in f: lines = lines.strip() if lines.startswith("Atom Charge X Y Z"): f.next() for line in f: if readAtoms == numAtoms: break line = line.strip() if state == "init": state = "post" m = Molecule() r = m.newResidue("UNK", " ", 1, " ") state = "atoms" serial = 1 if not line: continue elem, charge, x, y, z = line.split() x, y, z = [float(c) for c in [x,y,z]] ## Remove the number from the atomic symbol elem = filter(lambda x: x.isalpha(), elem) element = Element(elem) anum = anums.get(element.name, 0) + 1 anums[element.name] = anum a = m.newAtom("%s%d" % (element.name, anum), element) r.addAtom(a) a.setCoord(Coord((x*0.52918), (y*0.52918), (z*0.52918))) a.serialNumber = serial serial += 1 readAtoms += 1 connectMolecule(m) ################################################################### ## Critical points idNACP = 1 mNACP = Molecule() rNACP = mNACP.newResidue("Nuclear atractors critical points", " ", 1, " ") idBCP = 1 mBCP = Molecule() rBCP = mBCP.newResidue("Bond critical points", " ", 1, " ") idBPP = 1 mBPP = Molecule() rBPP = mBPP.newResidue("Bond path points", " ", 1, " ") cpnumber = 1 cpread = 0 getcriticalpoints = osOpen(fileName) for text in getcriticalpoints: text = text.strip() if cpread == 0: if text.startswith("CP#"): readtext = text cpread = 1 elif cpread == 1: if text.startswith("Type = (3,-3)"): a,b,signature,type,atom1 = text.split() cpnum,id,a,b,x,y,z = readtext.split() x, y, z = [float(c) for c in [x,y,z]] ## Remove the number from the atomic symbol elem = filter(lambda x: x.isalpha(), atom1) element = Element(elem) anum = anums.get(element.name, 0) + 1 anums[element.name] = anum #atomNACP = m.newAtom("%s%d" % (element.name, anum), element) atomNACP = mNACP.newAtom("%s%s" % ("NACP# ", atom1), element) atomNACP.serialNumber = serial #atomNACP = mNACP.newAtom(atom1, Element("NACP")) atomNACP.drawMode = 1 atomNACP.radius = 0.2 rNACP.addAtom(atomNACP) atomNACP.setCoord(Coord((x*0.52918), (y*0.52918), (z*0.52918))) cpread = 0 serial += 1 elif text.startswith("Type = (3,+3)"): print 'CCP' cpread = 0 elif text.startswith("Type = (3,+1)"): print 'RCP' cpread = 0 elif text.startswith("Type = (3,-1)"): a,b,signature,type,atom1,atom2 = text.split() cpnum,id,a,b,x,y,z = readtext.split() x, y, z = [float(c) for c in [x,y,z]] ## Remove the number from the atomic symbol elem = filter(lambda x: x.isalpha(), atom1) element = Element(elem) anum = anums.get(element.name, 0) + 1 anums[element.name] = anum atomBCP = mBCP.newAtom("%s%s" % ("BCP# ", id), element) atomBCP.serialNumber = serial #atomBCP = mBCP.newAtom(atom1, Element("He")) atomBCP.color = MaterialColor(1,0,0,1) atomBCP.drawMode = 1 atomBCP.radius = 0.07 rBCP.addAtom(atomBCP) atomBCP.setCoord(Coord((x*0.52918), (y*0.52918), (z*0.52918))) cpread = 0 serial += 1 ################################################################### ## Bond Paths getbondpaths = osOpen(fileName) statusSamples = 0 countSamples = 0 totalSamples = 0 skip = 0 for samples in getbondpaths: samples = samples.strip() if re.match("(.*)sample points along path from BCP to atom(.*)", samples): numSamples,a,b,c,d,e,tipo,g,h,atom = samples.split() numSamples = int(numSamples) statusSamples = 1 totalSamples = int(totalSamples) if statusSamples == 1: totalSamples = totalSamples + statusSamples if countSamples == numSamples: countSamples = 0 statusSamples = 0 else: try: x,y,z,rho = samples.split() x, y, z = [float(c) for c in [x,y,z]] ## Remove the number from the atomic symbol elem = filter(lambda x: x.isalpha(), atom1) element = Element(elem) anum = anums.get(element.name, 0) + 1 anums[element.name] = anum atomBPP = mBPP.newAtom("%s%s" % ("BPP", serial), element) atomBPP.serialNumber = serial #atomBPP = mBPP.newAtom(atom1, Element("kr")) #atomBPP = mBPP.newAtom("%s%s" % ("BPP", serial), element) atomBPP.color = MaterialColor(0,206,209,1) atomBPP.drawMode = 1 atomBPP.radius = 0.01 rBPP.addAtom(atomBPP) atomBPP.setCoord(Coord((x*0.52918), (y*0.52918), (z*0.52918))) #cpread = 0 serial += 1 #cpnumber += 1 countSamples += 1 except ValueError: countSamples += 1 continue mNACP.isRealMolecule = False # mNACP.noprefs = True mBCP.isRealMolecule = False mBCP.noprefs = True mBPP.isRealMolecule = False mBPP.noprefs = True ## Return molecules return [m, mNACP, mBCP, mBPP]
def readSDF(fileName, identifyAs=None): from OpenSave import osOpen from chimera import UserError, Molecule, Element, openModels, replyobj from chimera import Coord state = "init" f = osOpen(fileName) mols = [] nonblank = False for l in f: line = l.strip() nonblank = nonblank or line if state == "init": state = "post header 1" molName = line elif state == "post header 1": state = "post header 2" elif state == "post header 2": state = "counts" elif state == "counts": if not line: break state = "atoms" serial = 1 anums = {} atoms = [] try: numAtoms = int(l[:3].strip()) numBonds = int(l[3:6].strip()) except ValueError: raise UserError("Atom/bond counts line of" " MOL/SDF file '%s' is botched: '%s'" % (fileName, l)) m = Molecule() mols.append(m) if identifyAs: m.name = identifyAs else: from chimera.misc import isInformativeName mn = molName.strip() if isInformativeName(mn): m.name = mn else: import os.path m.name = os.path.split(fileName)[-1] r = m.newResidue("UNK", " ", 1, " ") elif state == "atoms": numAtoms -= 1 if numAtoms == 0: if numBonds: state = "bonds" else: state = "properties" try: x = float(l[:10].strip()) y = float(l[10:20].strip()) z = float(l[21:30].strip()) elem = l[31:34].strip() except ValueError: raise UserError("Atom line of MOL/SDF file" " '%s' is not x y z element...: '%s'" % (fileName, l)) element = Element(elem) if element.number == 0: # lone pair or somesuch atoms.append(None) continue anum = anums.get(element.name, 0) + 1 anums[element.name] = anum a = m.newAtom("%s%d" % (element.name, anum), element) atoms.append(a) r.addAtom(a) a.setCoord(Coord(x, y, z)) a.serialNumber = serial serial += 1 elif state == "bonds": numBonds -= 1 if numBonds == 0: state = "properties" try: a1index = int(l[:3].strip()) a2index = int(l[3:6].strip()) order = int(l[6:9].strip()) except ValueError: raise UserError("Bond line of MOL/SDF file" " '%s' is not a1 a2 order...: '%s'" % (fileName, l)) a1 = atoms[a1index-1] a2 = atoms[a2index-1] if not a1 or not a2: continue m.newBond(a1, a2).order = order elif state == "properties": if not m.atoms: raise UserError("No atoms found for compound" " '%s' in MOL/SDF file '%s'" % (m.name, fileName)) if line.split() == ["M", "END"]: state = "data" elif state == "data": if line == "$$$$": nonblank = False state = "init" f.close() if nonblank and state not in ["data", "init"]: if mols: replyobj.warning("Extraneous text after final $$$$" " in MOL/SDF file '%s'" % fileName) else: raise UserError("Unexpected end of file (parser state:" " %s) in MOL/SDF file '%s'" % (state, fileName)) return mols
def readSDF(fileName, identifyAs=None): from OpenSave import osOpen from chimera import UserError, Molecule, Element, openModels, replyobj from chimera import Coord state = "init" f = osOpen(fileName) mols = [] nonblank = False for l in f: line = l.strip() nonblank = nonblank or line if state == "init": state = "post header 1" molName = line elif state == "post header 1": state = "post header 2" elif state == "post header 2": state = "counts" elif state == "counts": if not line: break state = "atoms" serial = 1 anums = {} atoms = [] try: numAtoms = int(l[:3].strip()) numBonds = int(l[3:6].strip()) except ValueError: raise UserError("Atom/bond counts line of" " MOL/SDF file '%s' is botched: '%s'" % (fileName, l)) m = Molecule() mols.append(m) if identifyAs: m.name = identifyAs else: from chimera.misc import isInformativeName mn = molName.strip() if isInformativeName(mn): m.name = mn else: import os.path m.name = os.path.split(fileName)[-1] r = m.newResidue("UNK", " ", 1, " ") elif state == "atoms": numAtoms -= 1 if numAtoms == 0: if numBonds: state = "bonds" else: state = "properties" try: x = float(l[:10].strip()) y = float(l[10:20].strip()) z = float(l[21:30].strip()) elem = l[31:34].strip() except ValueError: raise UserError("Atom line of MOL/SDF file" " '%s' is not x y z element...: '%s'" % (fileName, l)) element = Element(elem) if element.number == 0: # lone pair or somesuch atoms.append(None) continue anum = anums.get(element.name, 0) + 1 anums[element.name] = anum a = m.newAtom("%s%d" % (element.name, anum), element) atoms.append(a) r.addAtom(a) a.setCoord(Coord(x, y, z)) a.serialNumber = serial serial += 1 elif state == "bonds": numBonds -= 1 if numBonds == 0: state = "properties" try: a1index = int(l[:3].strip()) a2index = int(l[3:6].strip()) order = int(l[6:9].strip()) except ValueError: raise UserError("Bond line of MOL/SDF file" " '%s' is not a1 a2 order...: '%s'" % (fileName, l)) a1 = atoms[a1index - 1] a2 = atoms[a2index - 1] if not a1 or not a2: continue m.newBond(a1, a2).order = order elif state == "properties": if not m.atoms: raise UserError("No atoms found for compound" " '%s' in MOL/SDF file '%s'" % (m.name, fileName)) if line.split() == ["M", "END"]: state = "data" elif state == "data": if line == "$$$$": nonblank = False state = "init" f.close() if nonblank and state not in ["data", "init"]: if mols: replyobj.warning("Extraneous text after final $$$$" " in MOL/SDF file '%s'" % fileName) else: raise UserError("Unexpected end of file (parser state:" " %s) in MOL/SDF file '%s'" % (state, fileName)) return mols