コード例 #1
0
    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
コード例 #2
0
    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
コード例 #3
0
    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
コード例 #4
0
    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()
コード例 #5
0
 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
コード例 #6
0
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])
コード例 #7
0
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
コード例 #8
0
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
コード例 #9
0
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]
コード例 #10
0
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
コード例 #11
0
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