Example #1
0
def _saveCB(okay, dialog, pathInfo=None):
	mav = dialog.mav

	if not okay:
		return

	if dialog.saveRegion.get():
		try:
			saveSeqs, saveFileMarkups = _verifySaveRegion(mav)
		except:
			dialog.enter()
			raise
	else:
		saveSeqs = mav.seqs
		saveFileMarkups = mav.fileMarkups
	if dialog.omitGaps.get():
		saveSeqs, saveFileMarkups = _omitGapColumns(saveSeqs,
							saveFileMarkups)
	if dialog.appendNumberings.get():
		saveSeqs = _appendNumberings(saveSeqs,
						doCopy=(saveSeqs == mav.seqs))
	if pathInfo is None:
		pathInfo = dialog.getPathsAndTypes()
	if not pathInfo:
		dialog.enter()
		raise ValueError, "No filename specified"
	from OpenSave import osOpen
	for path, fileType in pathInfo:
		f = osOpen(path, "w")
		saverFunc[fileType](f, mav, saveSeqs, saveFileMarkups)
		f.close()
		mav.status("Saved %s\n" % path)
	mav._edited = False
Example #2
0
def _saveCB(okay, dialog, pathInfo=None):
    mav = dialog.mav

    if not okay:
        return

    if dialog.saveRegion.get():
        try:
            saveSeqs, saveFileMarkups = _verifySaveRegion(mav)
        except:
            dialog.enter()
            raise
    else:
        saveSeqs = mav.seqs
        saveFileMarkups = mav.fileMarkups
    if dialog.omitGaps.get():
        saveSeqs, saveFileMarkups = _omitGapColumns(saveSeqs, saveFileMarkups)
    if dialog.appendNumberings.get():
        saveSeqs = _appendNumberings(saveSeqs, doCopy=(saveSeqs == mav.seqs))
    if pathInfo is None:
        pathInfo = dialog.getPathsAndTypes()
    if not pathInfo:
        dialog.enter()
        raise ValueError, "No filename specified"
    from OpenSave import osOpen
    for path, fileType in pathInfo:
        f = osOpen(path, "w")
        saverFunc[fileType](f, mav, saveSeqs, saveFileMarkups)
        f.close()
        mav.status("Saved %s\n" % path)
    mav._edited = False
Example #3
0
def parse(fileName):
	from OpenSave import osOpen
	f = osOpen(fileName, "r")
	inSequence = 0
	sequences = []
	for line in f.readlines():
		if inSequence:
			if not line or line.isspace():
				inSequence = 0
				continue
			if line[0] == '>':
				inSequence = 0
				# fall through
			else:
				sequences[-1].extend(line.strip())
		if not inSequence:
			if line[0] == '>':
				if sequences and len(sequences[-1]) == 0:
					raise FormatSyntaxError("No sequence"
					" found for %s" % sequences[-1].name)
				inSequence = 1
				sequences.append(Sequence(makeReadable(
								line[1:])))
	f.close()
	if not sequences:
		raise WrongFileTypeError()
	return sequences, {}, {}
Example #4
0
def writeSel(saveFile, namingStyle=None, selected=True, itemType="Residue"):
	from chimera.selection import currentAtoms, currentBonds, \
		currentEdges, currentResidues, currentMolecules, currentGraphs
	classNames = [c.__name__.lower() for c in classes]
	try:
		classIndex = classNames.index(itemType.lower())
	except ValueError:
		# might be a trailing 's'...
		classIndex = classNames.index(itemType.lower()[:-1])
		
	if selected:
		func = [currentAtoms, currentBonds, lambda : filter(
			lambda b: isinstance(b, chimera.PseudoBond),
			currentEdges()), currentResidues,
			currentMolecules, currentGraphs][classIndex]
	else:
		func = [unselAtoms, unselBonds, unselPseudobonds,
			unselResidues, unselMolecules, unselModels][classIndex]

	from chimera.misc import chimeraLabel, oslCmp
	items = map(lambda i: (i.oslIdent(), i), func())
	if items and not isinstance(items[0][1], chimera.Bond) \
	and not isinstance(items[0][1], chimera.PseudoBond):
		items.sort(oslCmp)
	if saveFile == "-":
		import sys
		f = sys.stdout
	else:
		from OpenSave import osOpen, tildeExpand
		saveFile = tildeExpand(saveFile)
		f = osOpen(saveFile, "w")
	for ident, item in items:
		print>>f, chimeraLabel(item, style=namingStyle, bondSep=" <-> ")
	if saveFile != "-":
		f.close()
def parse(fileName):
    from OpenSave import osOpen
    f = osOpen(fileName, "r")
    # skip header crap
    inHeader = True
    lineNum = 0
    sequences = []
    for line in f:
        line = line.strip()
        lineNum += 1
        if not line:
            continue
        fields = line.split()
        if inHeader:
            if len(fields[0]) == 2:
                continue
            inHeader = False
        if len(fields) != 2:
            # since this format lacks mandatory headers,
            # cannot be sure it _is_ a Pfam file and therefore
            # cannot raise FormatSyntaxError
            raise WrongFileTypeError()
        seq = Sequence(makeReadable(fields[0]))
        seq.extend(fields[1])
        sequences.append(seq)
    f.close()
    if not sequences:
        raise WrongFileTypeError()
    return sequences, {}, {}
Example #6
0
def parse(fileName):
	from OpenSave import osOpen
	f = osOpen(fileName, "r")
	# skip header crap
	inHeader = True
	lineNum = 0
	sequences = []
	for line in f:
		line = line.strip()
		lineNum += 1
		if not line:
			continue
		fields = line.split()
		if inHeader:
			if len(fields[0]) == 2:
				continue
			inHeader = False
		if len(fields) != 2:
			# since this format lacks mandatory headers,
			# cannot be sure it _is_ a Pfam file and therefore
			# cannot raise FormatSyntaxError
			raise WrongFileTypeError()
		seq = Sequence(makeReadable(fields[0]))
		seq.extend(fields[1])
		sequences.append(seq)
	f.close()
	if not sequences:
		raise WrongFileTypeError()
	return sequences, {}, {}
Example #7
0
def writeFile(fileName):
	from OpenSave import osOpen
	f = osOpen(fileName, 'w')
	if _ilabelModel:
		labelIDs = _ilabelModel.labelMap.keys()
		labelIDs.sort()
		for labelID in labelIDs:
			if labelID.startswith(AUTO_ID_PREFIX):
				print>>f, "Label"
			else:
				print>>f, "Label %s" % labelID
			label = _ilabelModel.labelMap[labelID]
			print>>f, "\t(x,y): %s" % repr(label.pos)
			print>>f, "\ttext: %s" % repr(unicode(label))
			print>>f, "\tshown: %s" % label.shown
			print>>f, "\tfont size(s): %s" % _valuesString([str(c.size)
									for l in label.lines for c in l])
			print>>f, "\tfont style(s): %s" % _valuesString([
				FONT_STYLE_LABELS[FONT_STYLE_VALUES.index(c.style)]
									for l in label.lines for c in l])
			print>>f, "\tfont typeface(s): %s" % _valuesString([
				FONT_TYPEFACE_LABELS[FONT_TYPEFACE_VALUES.index(c.fontName)]
									for l in label.lines for c in l])
			print>>f, "\tcolor(s): %s" % _valuesString([repr(c.rgba)
									for l in label.lines for c in l])
	f.close()
Example #8
0
def writeFile(fileName):
    from OpenSave import osOpen
    f = osOpen(fileName, 'w')
    if _ilabelModel:
        labelIDs = _ilabelModel.labelMap.keys()
        labelIDs.sort()
        for labelID in labelIDs:
            if labelID.startswith(AUTO_ID_PREFIX):
                print >> f, "Label"
            else:
                print >> f, "Label %s" % labelID
            label = _ilabelModel.labelMap[labelID]
            print >> f, "\t(x,y): %s" % repr(label.pos)
            print >> f, "\ttext: %s" % repr(unicode(label))
            print >> f, "\tshown: %s" % label.shown
            print >> f, "\tfont size(s): %s" % _valuesString(
                [str(c.size) for l in label.lines for c in l])
            print >> f, "\tfont style(s): %s" % _valuesString([
                FONT_STYLE_LABELS[FONT_STYLE_VALUES.index(c.style)]
                for l in label.lines for c in l
            ])
            print >> f, "\tfont typeface(s): %s" % _valuesString([
                FONT_TYPEFACE_LABELS[FONT_TYPEFACE_VALUES.index(c.fontName)]
                for l in label.lines for c in l
            ])
            print >> f, "\tcolor(s): %s" % _valuesString(
                [repr(c.rgba) for l in label.lines for c in l])
    f.close()
Example #9
0
def processCastpFiles(pdb,
                      mouthAtoms,
                      mouthInfo,
                      pocketAtoms,
                      pocketInfo,
                      identifyAs=None):
    from OpenSave import osOpen
    if not identifyAs:
        identifyAs = pdb[:-4]
    pdb = osOpen(pdb)
    mouthAtoms = osOpen(mouthAtoms)
    mouthInfo = osOpen(mouthInfo)
    pocketAtoms = osOpen(pocketAtoms)
    pocketInfo = osOpen(pocketInfo)
    from chimera import PDBio
    pdbio = PDBio()
    molList = pdbio.readPDBstream(pdb, "CASTp PDB", 0)[0]
    pdb.close()
    if not pdbio.ok():
        raise IOError(pdbio.error())
    if not molList:
        raise ValueError("No structures in CASTp PDB file?!?")
    elif len(molList) > 1:
        raise ValueError("Multiple structures in CASTp PDB file?!?")
    structure = molList[0]
    structure.name = identifyAs
    mouthInfoDicts = processMouthInfoFile(mouthInfo)
    pocketInfoDicts = processPocketInfoFile(pocketInfo)
    mouthInfo.close()
    pocketInfo.close()
    if len(mouthInfoDicts) != len(pocketInfoDicts):
        raise ValueError("Number of mouths (%d) does not match number"
                         " of pockets (%d)." %
                         (len(mouthInfoDicts), len(pocketInfoDicts)))
    bySerial = {}
    for a in structure.atoms:
        bySerial[a.serialNumber] = a
    gatherAtoms(bySerial, "mouth", mouthAtoms, mouthInfoDicts)
    gatherAtoms(bySerial, "pocket", pocketAtoms, pocketInfoDicts)
    mouthAtoms.close()
    pocketAtoms.close()
    cavities = []
    for mid, pid in zip(mouthInfoDicts, pocketInfoDicts):
        cavities.append(CastpCavity(mid, pid))

    #chimera.openModels.add([structure])
    return structure, cavities
Example #10
0
	def __init__(self, f):
		if isinstance(f, basestring):
			from OpenSave import osOpen
			file = osOpen(f)
			self._readMSF(file)
			file.close()
		else:
			self._readMSF(f)
Example #11
0
 def __init__(self, f):
     if isinstance(f, basestring):
         from OpenSave import osOpen
         file = osOpen(f)
         self._readMSF(file)
         file.close()
     else:
         self._readMSF(f)
def _fileOutput(fileName, outputInfo, namingStyle):
	intermodel, intramodel, relaxConstraints, \
			distSlop, angleSlop, modelList, hbonds = outputInfo
	from OpenSave import osOpen
	outFile = osOpen(fileName, 'w')
	if intermodel:
		outFile.write("Finding intermodel H-bonds\n")
	if intramodel:
		outFile.write("Finding intramodel H-bonds\n")
	if relaxConstraints:
		outFile.write("Constraints relaxed by %g angstroms"
			" and %d degrees\n" % (distSlop, angleSlop))
	else:
		outFile.write("Using precise constraint criteria\n")
	outFile.write("Models used:\n")
	for model in modelList:
		outFile.write("\t%s %s\n" % (model.oslIdent(), model.name))
	outFile.write("\nH-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):\n")
	# want the bonds listed in some kind of consistent
	# order...
	hbonds.sort(_oslSort)

	# figure out field widths to make things line up
	dwidth = awidth = hwidth = 0
	labels = {}
	from chimera.misc import chimeraLabel
	for don, acc in hbonds:
		labels[don] = chimeraLabel(don, style=namingStyle)
		labels[acc] = chimeraLabel(acc, style=namingStyle)
		dwidth = max(dwidth, len(labels[don]))
		awidth = max(awidth, len(labels[acc]))
		da = don.xformCoord().distance(acc.xformCoord())
		dha = None
		for h in don.primaryNeighbors():
			if h.element.number != 1:
				continue
			d = h.xformCoord().distance(acc.xformCoord())
			if dha is None or d < dha:
				dha = d
				hyd = h
		if dha is None:
			dhaOut = "N/A"
			hydOut = "no hydrogen"
		else:
			dhaOut = "%5.3f" % dha
			hydOut = chimeraLabel(hyd, style=namingStyle)
		hwidth = max(hwidth, len(hydOut))
		labels[(don, acc)] = (hydOut, da, dhaOut)
	for don, acc in hbonds:
		hydOut, da, dhaOut = labels[(don, acc)]
		outFile.write("%*s  %*s  %*s  %5.3f  %s\n" % (
			0-dwidth, labels[don], 0-awidth, labels[acc],
			0-hwidth, hydOut, da, dhaOut))
	if outFile != fileName:
		# we opened it, so close it...
		outFile.close()
Example #13
0
def _fileChosen(okayed, dialog):
	if okayed:
		paths = dialog.getPaths()
		if paths:
			filename = paths[0]
			from OpenSave import osOpen
			outFile = osOpen(filename, "w")
			outFile.write(dialog._text)
			outFile.close()
	delattr(dialog, "_text")
 def __init__(self, topology):
     from OpenSave import osOpen
     topFile = osOpen(topology, 'rb')
     import os
     self.topFileSize = os.stat(topology).st_size
     from xdrlib import Unpacker
     self.fileString = FileString(topFile, 0, self.topFileSize)
     self.xdr = Unpacker(self.fileString)
     version = self._readHeader()
     self._readTopology(version)
Example #15
0
	def __init__(self, topology):
		from OpenSave import osOpen
		topFile = osOpen(topology, 'rb')
		import os
		self.topFileSize = os.stat(topology).st_size
		from xdrlib import Unpacker
		self.fileString = FileString(topFile, 0, self.topFileSize)
		self.xdr = Unpacker(self.fileString)
		version = self._readHeader()
		self._readTopology(version)
    def __init__(self, topology):
        from OpenSave import osOpen
        self.atomNames = []
        self.resNames = []
        self.resIndices = []
        self.bonds = []
        self.elements = []
        self.molInfo = {}

        topFile = osOpen(topology)
        while self._readLine(topFile):
            pass
        topFile.close()
Example #17
0
	def __init__(self, topology):
		from OpenSave import osOpen
		self.atomNames = []
		self.resNames = []
		self.resIndices = []
		self.bonds = []
		self.elements = []
		self.molInfo = {}

		topFile = osOpen(topology)
		while self._readLine(topFile):
			pass
		topFile.close()
def _fileChosen(okayed, dialog):
	if okayed:
		paths = dialog.getPaths()
		if paths:
			filename = paths[0]
			from OpenSave import osOpen
			outFile = osOpen(filename, "w")
			outFile.write(dialog._output)
			outFile.close()
			if dialog._show:
				import urllib
				from chimera import help
				help.display(urllib.pathname2url(filename))
	delattr(dialog, "_output")
	delattr(dialog, "_show")
Example #19
0
def parse(fileName):
	from OpenSave import osOpen
	f = osOpen(fileName, "r")
	inHeader = 1
	sequences = []
	lineNum = 0
	for line in f.readlines():
		lineNum += 1
		if inHeader:
			if line.startswith("CLUSTAL"):
				inHeader = 0
				firstBlock = 1
			else:
				if line.strip() !="":
					raise WrongFileTypeError()
			continue
		if not line or line[0].isspace():
			if sequences:
				firstBlock = 0
				expect = 0
			continue
		try:
			seqName, seqBlock, numResidues = line.split()
		except ValueError:
			try:
				seqName, seqBlock = line.split()
			except ValueError:
				raise FormatSyntaxError("Line %d is not "
					"sequence name followed by sequence "
					" contents and optional ungapped length"
					% lineNum)
		if firstBlock:
			sequences.append(Sequence(makeReadable(seqName)))
			sequences[-1].append(seqBlock)
			continue
		try:
			seq = sequences[expect]
		except IndexError:
			raise FormatSyntaxError("Sequence on line %d not in"
				" initial sequence block" % lineNum)
		expect += 1
		seq.append(seqBlock)
	f.close()
	if not sequences:
		raise WrongFileTypeError()
	return sequences, {}, {}
Example #20
0
def parse(fileName):
    from OpenSave import osOpen
    f = osOpen(fileName, "r")
    inHeader = 1
    sequences = []
    lineNum = 0
    for line in f.readlines():
        lineNum += 1
        if inHeader:
            if line.startswith("CLUSTAL"):
                inHeader = 0
                firstBlock = 1
            else:
                if line.strip() != "":
                    raise WrongFileTypeError()
            continue
        if not line or line[0].isspace():
            if sequences:
                firstBlock = 0
                expect = 0
            continue
        try:
            seqName, seqBlock, numResidues = line.split()
        except ValueError:
            try:
                seqName, seqBlock = line.split()
            except ValueError:
                raise FormatSyntaxError(
                    "Line %d is not "
                    "sequence name followed by sequence "
                    " contents and optional ungapped length" % lineNum)
        if firstBlock:
            sequences.append(Sequence(makeReadable(seqName)))
            sequences[-1].append(seqBlock)
            continue
        try:
            seq = sequences[expect]
        except IndexError:
            raise FormatSyntaxError("Sequence on line %d not in"
                                    " initial sequence block" % lineNum)
        expect += 1
        seq.append(seqBlock)
    f.close()
    if not sequences:
        raise WrongFileTypeError()
    return sequences, {}, {}
Example #21
0
def _fileOutput(fileName, info, namingStyle):
	overlapCutoff, hbondAllowance, bondSeparation, ignoreIntraRes, \
						clashes, outputGrouping = info
	from OpenSave import osOpen
	outFile = osOpen(fileName, 'w')
	print>>outFile, "Allowed overlap: %g" % overlapCutoff
	print>>outFile, "H-bond overlap reduction: %g" % hbondAllowance
	print>>outFile, "Ignore contacts between atoms separated by %d bonds" \
		" or less" % bondSeparation
	if ignoreIntraRes:
		print>>outFile, "Ignore intra-residue contacts"
	else:
		print>>outFile, "Detect intra-residue contacts also"
	seen = set()
	data = []
	from chimera.misc import chimeraLabel
	for a, aclashes in clashes.items():
		for c, val in aclashes.items():
			if (c, a) in seen:
				continue
			seen.add((a, c))
			if a in outputGrouping:
				out1, out2 = a, c
			else:
				out1, out2 = c, a
			l1, l2 = chimeraLabel(out1, style=namingStyle), \
					chimeraLabel(out2, style=namingStyle)
			data.append((val, l1, l2, out1.xformCoord().distance(
							out2.xformCoord())))
	data.sort()
	data.reverse()
	print>>outFile, "\n%d contacts" % len(data)
	print>>outFile, "atom1  atom2  overlap  distance"
	if data:
		fieldWidth1 = max([len(l1) for v, l1, l2, d in data])
		fieldWidth2 = max([len(l2) for v, l1, l2, d in data])
		for v, l1, l2, d in data:
			print>>outFile, "%*s  %*s  %5.3f  %5.3f" % (
				0-fieldWidth1, l1, 0-fieldWidth2, l2, v, d)
	if fileName != outFile:
		# only close file if we opened it...
		outFile.close()
Example #22
0
def _fileOutput(fileName, info, namingStyle):
    overlapCutoff, hbondAllowance, bondSeparation, ignoreIntraRes, \
         clashes, outputGrouping = info
    from OpenSave import osOpen
    outFile = osOpen(fileName, 'w')
    print >> outFile, "Allowed overlap: %g" % overlapCutoff
    print >> outFile, "H-bond overlap reduction: %g" % hbondAllowance
    print>>outFile, "Ignore contacts between atoms separated by %d bonds" \
     " or less" % bondSeparation
    if ignoreIntraRes:
        print >> outFile, "Ignore intra-residue contacts"
    else:
        print >> outFile, "Detect intra-residue contacts also"
    seen = set()
    data = []
    from chimera.misc import chimeraLabel
    for a, aclashes in clashes.items():
        for c, val in aclashes.items():
            if (c, a) in seen:
                continue
            seen.add((a, c))
            if a in outputGrouping:
                out1, out2 = a, c
            else:
                out1, out2 = c, a
            l1, l2 = chimeraLabel(out1, style=namingStyle), \
              chimeraLabel(out2, style=namingStyle)
            data.append(
                (val, l1, l2, out1.xformCoord().distance(out2.xformCoord())))
    data.sort()
    data.reverse()
    print >> outFile, "\n%d contacts" % len(data)
    print >> outFile, "atom1  atom2  overlap  distance"
    if data:
        fieldWidth1 = max([len(l1) for v, l1, l2, d in data])
        fieldWidth2 = max([len(l2) for v, l1, l2, d in data])
        for v, l1, l2, d in data:
            print >> outFile, "%*s  %*s  %5.3f  %5.3f" % (
                0 - fieldWidth1, l1, 0 - fieldWidth2, l2, v, d)
    if fileName != outFile:
        # only close file if we opened it...
        outFile.close()
Example #23
0
def open_mmcif(path):

    from OpenSave import osOpen
    p = osOpen(path)
    
    #
    # No bonds are created for standard mmCIF files from the PDB unless the
    # library_bonds or distance_bonds options are given.
    #
    # It appears that mmlib 0.9.7 can only link residues of a polymer using
    # distance rules.  Residue templates are used for intra-residue bonds.
    #
    from mmLib.FileIO import LoadStructure
    from mmLib.mmCIF import mmCIFSyntaxError
    try:
	struct = LoadStructure(fil=p, format="CIF", library_bonds=True,
				auto_sort=False)
    except mmCIFSyntaxError, e:
        from chimera import NotABug
	raise NotABug("%s: %s" % (path, str(e)))
Example #24
0
def writeDMS(surf, fileName, writeNormals=True, displayedOnly=True):
	from OpenSave import osOpen
	from chimera import UserError, replyobj
	m = surf.molecule
	if not m:
		raise UserError("No molecule for surface")
	out = osOpen(fileName, "wb")
	vMap = {}
	for i, a in enumerate(surf.atomMap):
		vMap.setdefault(a, []).append(i)
	for i, a in enumerate(m.atoms):
		atomPart = atomFormat(a)
		crd = a.coord()
		print>>out, "%s%8.3f %8.3f %8.3f A" % (atomPart, crd.x,
								crd.y, crd.z)
		if displayedOnly and not a.surfaceDisplay:
			continue
		vertices = surf.surface_piece.geometry[0]
		normals = surf.surface_piece.normals
		vtypes = surf.triData[1][:,2]
		# vtypes (according to MSMS man page):
		#   1 == toric reentrant
		#   2 == inside reentrant
		#   3 == inside contact
		vses = surf.triData[0][:,6]
		for vi in vMap.get(a, []):
			v = vertices[vi]
			vtype = vtypes[vi]
			try:
				dmsType = ('S', 'R', 'C')[vtype-1]
			except IndexError:
				raise ValueError("Vertex type (%d) not in"
						" range 1-3" % vtype)
			ses = vses[vi]
			line = "%s%8.3f %8.3f %8.3f S%s0 %6.3f" % (atomPart,
					v[0], v[1], v[2], dmsType, ses)
			if writeNormals:
				line += " %6.3f %6.3f %6.3f" \
							% tuple(normals[vi])
			print>>out, line
	out.close()
Example #25
0
def writeDMS(surf, fileName, writeNormals=True, displayedOnly=True):
    from OpenSave import osOpen
    from chimera import UserError, replyobj
    m = surf.molecule
    if not m:
        raise UserError("No molecule for surface")
    out = osOpen(fileName, "wb")
    vMap = {}
    for i, a in enumerate(surf.atomMap):
        vMap.setdefault(a, []).append(i)
    for i, a in enumerate(m.atoms):
        atomPart = atomFormat(a)
        crd = a.coord()
        print >> out, "%s%8.3f %8.3f %8.3f A" % (atomPart, crd.x, crd.y, crd.z)
        if displayedOnly and not a.surfaceDisplay:
            continue
        vertices = surf.surface_piece.geometry[0]
        normals = surf.surface_piece.normals
        vtypes = surf.triData[1][:, 2]
        # vtypes (according to MSMS man page):
        #   1 == toric reentrant
        #   2 == inside reentrant
        #   3 == inside contact
        vses = surf.triData[0][:, 6]
        for vi in vMap.get(a, []):
            v = vertices[vi]
            vtype = vtypes[vi]
            try:
                dmsType = ('S', 'R', 'C')[vtype - 1]
            except IndexError:
                raise ValueError("Vertex type (%d) not in"
                                 " range 1-3" % vtype)
            ses = vses[vi]
            line = "%s%8.3f %8.3f %8.3f S%s0 %6.3f" % (atomPart, v[0], v[1],
                                                       v[2], dmsType, ses)
            if writeNormals:
                line += " %6.3f %6.3f %6.3f" \
                   % tuple(normals[vi])
            print >> out, line
    out.close()
Example #26
0
def parse(fileName):
	from OpenSave import osOpen
	f = osOpen(fileName, "r")
	want = 'init'
	sequences = []
	for line in f.readlines():
		line = line.strip()
		if want == 'init':
			if len(line) < 4:
				continue
			if line[0] != '>' or line[3] != ';':
				continue
			sequences.append(Sequence(makeReadable(line[4:])))
			pirType = line[1:3]
			if pirType in ("P1", "F1"):
				sequences[-1].nucleic = 0
			else:
				sequences[-1].nucleic = 1
			sequences[-1].PIRtype = pirType
			want = 'descript'
		elif want == 'descript':
			sequences[-1].descript = line
			sequences[-1].PIRdescript = line
			want = 'sequence'
		elif want == 'sequence':
			if not line:
				continue
			if line[-1] == '*':
				want = 'init'
				line = line[:-1]
			sequences[-1].extend(filter(lambda c,
				whsp=string.whitespace: not c in whsp, line))
	f.close()
	if not sequences:
		raise WrongFileTypeError()
	if want != 'init':
		raise FormatSyntaxError("Could not find end of sequence '%s'"
							% sequences[-1].name)
	return sequences, {}, {}
Example #27
0
def parse(fileName):
    from OpenSave import osOpen
    f = osOpen(fileName, "r")
    want = 'init'
    sequences = []
    for line in f.readlines():
        line = line.strip()
        if want == 'init':
            if len(line) < 4:
                continue
            if line[0] != '>' or line[3] != ';':
                continue
            sequences.append(Sequence(makeReadable(line[4:])))
            pirType = line[1:3]
            if pirType in ("P1", "F1"):
                sequences[-1].nucleic = 0
            else:
                sequences[-1].nucleic = 1
            sequences[-1].PIRtype = pirType
            want = 'descript'
        elif want == 'descript':
            sequences[-1].descript = line
            sequences[-1].PIRdescript = line
            want = 'sequence'
        elif want == 'sequence':
            if not line:
                continue
            if line[-1] == '*':
                want = 'init'
                line = line[:-1]
            sequences[-1].extend(
                filter(lambda c, whsp=string.whitespace: not c in whsp, line))
    f.close()
    if not sequences:
        raise WrongFileTypeError()
    if want != 'init':
        raise FormatSyntaxError("Could not find end of sequence '%s'" %
                                sequences[-1].name)
    return sequences, {}, {}
Example #28
0
def open_mmcif(path):

    from OpenSave import osOpen
    p = osOpen(path)

    #
    # No bonds are created for standard mmCIF files from the PDB unless the
    # library_bonds or distance_bonds options are given.
    #
    # It appears that mmlib 0.9.7 can only link residues of a polymer using
    # distance rules.  Residue templates are used for intra-residue bonds.
    #
    from mmLib.FileIO import LoadStructure
    from mmLib.mmCIF import mmCIFSyntaxError
    try:
        struct = LoadStructure(fil=p,
                               format="CIF",
                               library_bonds=True,
                               auto_sort=False)
    except mmCIFSyntaxError, e:
        from chimera import NotABug
        raise NotABug("%s: %s" % (path, str(e)))
Example #29
0
def writeSel(saveFile, namingStyle=None, selected=True, itemType="Residue"):
    from chimera.selection import currentAtoms, currentBonds, \
     currentEdges, currentResidues, currentMolecules, currentGraphs
    classNames = [c.__name__.lower() for c in classes]
    try:
        classIndex = classNames.index(itemType.lower())
    except ValueError:
        # might be a trailing 's'...
        classIndex = classNames.index(itemType.lower()[:-1])

    if selected:
        func = [
            currentAtoms, currentBonds, lambda: filter(
                lambda b: isinstance(b, chimera.PseudoBond), currentEdges()),
            currentResidues, currentMolecules, currentGraphs
        ][classIndex]
    else:
        func = [
            unselAtoms, unselBonds, unselPseudobonds, unselResidues,
            unselMolecules, unselModels
        ][classIndex]

    from chimera.misc import chimeraLabel, oslCmp
    items = map(lambda i: (i.oslIdent(), i), func())
    if items and not isinstance(items[0][1], chimera.Bond) \
    and not isinstance(items[0][1], chimera.PseudoBond):
        items.sort(oslCmp)
    if saveFile == "-":
        import sys
        f = sys.stdout
    else:
        from OpenSave import osOpen, tildeExpand
        saveFile = tildeExpand(saveFile)
        f = osOpen(saveFile, "w")
    for ident, item in items:
        print >> f, chimeraLabel(item, style=namingStyle, bondSep=" <-> ")
    if saveFile != "-":
        f.close()
Example #30
0
 def Apply(self, event=None):
     paths = self.getPaths()
     if not paths:
         raise ValueError, "No filename given for recording"
     fname = paths[0]
     if self.appending.get():
         mode = "a"
     else:
         mode = "w"
     from OpenSave import osOpen
     file = osOpen(fname, mode)
     writePython = self.commandStyle.getvalue()[:6] == "Python"
     if writePython:
         file.write("from chimera import runCommand\n")
     if self.amount.getvalue()[:3] == "all":
         cmds = self.histDialog.listbox.get()
     else:
         cmds = self.histDialog.listbox.getvalue()
     for cmd in cmds:
         if writePython:
             file.write("runCommand(" + repr(cmd) + ")\n")
         else:
             file.write(cmd + "\n")
     file.close()
Example #31
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
def parse(fileName):
    from OpenSave import osOpen
    from chimera import replyobj
    f = osOpen(fileName, "r")
    lineNum = 0
    fileAttrs = {}
    fileMarkups = {}
    seqAttrs = {}
    seqMarkups = {}
    sequences = {}
    seqSequence = []
    for line in f:
        line = line[:-1]  # drop newline
        lineNum += 1
        if lineNum == 1:
            if line.startswith("# STOCKHOLM"):
                continue
            raise WrongFileTypeError()
        if not line:
            continue
        if line.startswith('#='):
            markupType = line[2:4]
            markup = line[5:].strip()

            def trySplit(numSplit):
                fields = markup.split(None, numSplit)
                if len(fields) == numSplit:
                    # value is empty
                    fields.append("")
                if len(fields) != numSplit + 1:
                    raise FormatSyntaxError("Not enough"
                                            " arguments after #=%s markup"
                                            " on line %d" %
                                            (markupType, lineNum))
                return fields

            if markupType == "GF":
                tag, val = trySplit(1)
                tag = tag.replace("_", " ")
                tag = genericFileAttrs.get(tag, "Stockholm " + tag)
                if tag in fileAttrs:
                    fileAttrs[tag] += '\n' + val
                else:
                    fileAttrs[tag] = val
            elif markupType == "GS":
                seqName, tag, val = trySplit(2)
                tag = tag.replace("_", " ")
                attrs = seqAttrs.setdefault(seqName, {})
                tag = genericSeqAttrs.get(tag, "Stockholm " + tag)
                if tag in attrs:
                    attrs[tag] += '\n' + val
                else:
                    attrs[tag] = val
            elif markupType == "GC":
                tag, val = trySplit(1)
                tag = tag.replace("_", " ")
                fileMarkups[tag] = fileMarkups.get(tag, "") + val
            elif markupType == "GR":
                seqName, tag, val = trySplit(2)
                tag = tag.replace("_", " ")
                seqMarkups.setdefault(seqName, {}).setdefault(tag, "")
                seqMarkups[seqName][tag] += val
            # ignore other types
            continue
        elif line.startswith('#'):
            # unstructured comment
            if 'comments' in fileAttrs:
                fileAttrs['comments'] += "\n" + line[1:]
            else:
                fileAttrs['comments'] = line[1:]
            continue
        elif line.strip() == "//":
            # end of sequence alignment blocks, but comments
            # may follow this, so keep going...
            continue
        # sequence info...
        try:
            seqName, block = line.split(None, 1)
        except ValueError:
            raise FormatSyntaxError("Sequence info not in name/"
                                    "contents format on line %d" % lineNum)
        if seqName not in sequences:
            sequences[seqName] = Sequence(makeReadable(seqName))
            seqSequence.append(seqName)
        sequences[seqName].extend(block)
    f.close()

    if not sequences:
        raise FormatSyntaxError("No sequences found")
    for seqName, seq in sequences.items():
        if seqName in seqAttrs:
            seq.attrs = seqAttrs[seqName]
        if seqName in seqMarkups:
            seq.markups = seqMarkups[seqName]
            for tag, markup in seq.markups.items():
                if len(markup) != len(seq):
                    replyobj.warning("Markup %s for"
                                     " sequence %s is wrong length;"
                                     " ignoring\n" % (tag, seqName))
                    del seq.markups[tag]
    for seqInfo, label in [(seqAttrs, "sequence"), (seqMarkups, "residue")]:
        for seqName in seqInfo.keys():
            if seqName in sequences:
                continue
            # might be sequence name without trailing '/start-end'
            for fullName in sequences.keys():
                if fullName.startswith(seqName) \
                and fullName[len(seqName)] == '/' \
                and '/' not in fullName[len(seqName)+1:]:
                    break
            else:
                raise FormatSyntaxError(
                    "%s annotations "
                    "provided for non-existent sequence %s" %
                    (label.capitalize(), seqName))
            replyobj.info("Updating %s %s annotions with %s "
                          "annotations\n" % (fullName, label, seqName))
            seqInfo[fullName].update(seqInfo[seqName])
            del seqInfo[seqName]
    for tag, markup in fileMarkups.items():
        if len(markup) != len(sequences[seqSequence[0]]):
            raise FormatSyntaxError("Column annotation %s is"
                                    " wrong length" % tag)

    return map(lambda name: sequences[name], seqSequence), \
          fileAttrs, fileMarkups
Example #33
0
	def Apply(self):
		savePaths = self.getPaths()
		if not savePaths:
			replyobj.error("No save file specified\n")
			return
		from OpenSave import osOpen
		saveFile = osOpen(savePaths[0], "w")
		mols = chimera.openModels.list(modelTypes=[chimera.Molecule])
		for mol in mols:
			print>>saveFile, "Model %s is %s" % (mol.oslIdent(),
								mol.name)
		sm = self.structMeasure
		selected = self.saveTypes.getcurselection()
		if DISTANCES in selected:
			print>>saveFile, "\nDistance information"
			output = {}
			for d in sm.distances:
				a1, a2 = d.atoms
				distID = d.id
				if d.distance[-1].isdigit():
					dval = d.distance
				else:
					# omit angstrom character
					dval = d.distance[:-1]
				output[distID] = "%2d  %s <-> %s:  %s" % (
						distID, sm.atomLabel(a1),
						sm.atomLabel(a2), dval)
			ids = output.keys()
			ids.sort()
			for distID in ids:
				print>>saveFile, output[distID]

		if ANGLES in selected:
			print>>saveFile, "\nAngles/Torsions"
			printables = []
			maxLabel = 0
			for atoms in sm.angleInfo:
				labelArgs = tuple([sm.atomLabel(a)
							for a in atoms])
				if len(atoms) == 3:
					label = "%s -> %s -> %s" % labelArgs
					func = chimera.angle
				else:
					label = "%s -> %s -> %s -> %s" \
								% labelArgs
					func = chimera.dihedral
				maxLabel = max(maxLabel, len(label))
				printables.append((label, "%8.3f" %
						func(*tuple([a.xformCoord()
							for a in atoms]))))
			format = "%%%ds: %%s" % maxLabel
			for printArgs in printables:
				print>>saveFile, format % printArgs
				
		if BONDROTS in selected:
			print>>saveFile, "\nBond rotations"
			printables = []
			maxLabel = 0
			for br in sm.rotations:
				na, fa = sm.dihedEndAtoms(br)
				label = "%s -> %s -> %s -> %s" % (
					sm.atomLabel(na),
					sm.atomLabel(br.atoms[0]),
					sm.atomLabel(br.atoms[1]),
					sm.atomLabel(fa))
				maxLabel = max(maxLabel, len(label))
				printables.append((label,
						"%8.3f" % sm.dihedral(br),
						"%8.3f" % br.get()))
			format = "%%%ds: %%s (delta: %%s)" % maxLabel
			for printArgs in printables:
				print>>saveFile, format % printArgs
				
		if GEOMETRIES in selected:
			print>>saveFile, "\nAxes"
			print>>saveFile, "axis name, length, center, direction"
			from Axes import axisManager
			axes = axisManager.axes
			axes.sort(lambda a1, a2: cmp(a1.name, a2.name))
			nameSize = max([0] + [len(a.name) for a in axes])
			from chimera import Point
			for axis in axes:
				ends = [axis.direction * ext + axis.center
						for ext in axis.extents]
				cx, cy, cz = Point(ends)
				dx, dy, dz = axis.direction
				print>>saveFile, "%*s: %6.3f (%7.3f, %7.3f," \
					" %7.3f) (%6.3f, %6.3f, %6.3f)" % (
					nameSize, axis.name,
					abs(axis.extents[0] - axis.extents[1]),
					cx, cy, cz, dx, dy, dz)
			print>>saveFile, "\nPlanes"
			print>>saveFile, "plane name, center, normal, radius"
			from Planes import planeManager
			planes = planeManager.planes
			planes.sort(lambda p1, p2: cmp(p1.name, p2.name))
			nameSize = max([0] + [len(pl.name) for pl in planes])
			for plane in planes:
				ox, oy, oz = plane.plane.origin
				nx, ny, nz = plane.plane.normal
				print>>saveFile, "%*s: (%7.3f, %7.3f, %7.3f)" \
					" (%6.3f, %6.3f, %6.3f) %.3f"  % (nameSize, plane.name,
					ox, oy, oz, nx, ny, nz, plane.radius)
		saveFile.close()
Example #34
0
def writeMol2(models, fileName, status=None, anchor=None, relModel=None,
		hydNamingStyle="sybyl", multimodelHandling="individual",
		skip=None, resNum=True, gaffType=False, gaffFailError=None):
	"""Write a Mol2 file.

	   'models' are the models to write out into a file named 'fileName'.

	   'status', if not None, is a function that takes a string -- used
	   to report the progress of the write.
	   
	   'anchor' is a selection (i.e. instance of a subclass of
	   chimera.selection.Selection) containing atoms/bonds that should
	   be written out to the @SETS section of the file as the rigid
	   framework for flexible ligand docking.

	   'hydNamingStyle' controls whether hydrogen names should be
	   "Sybyl-like" (value: sybyl) or "PDB-like" (value: pdb)
	   -- e.g.  HG21 vs. 1HG2.

	   'multimodelHandling' controls whether multiple models will be
	   combined into a single @MOLECULE section (value: combined) or
	   each given its own section (value: individual).

	   'skip' is a list of atoms to not output

	   'resNum' controls whether residue sequence numbers are included
	   in the substructure name.  Since Sybyl Mol2 files include them,
	   this defaults to True.

	   If 'gaffType' is True, outout GAFF atom types instead of Sybyl
	   atom types.  'gaffFailError', if specified, is the type of error
	   to throw (e.g. UserError) if there is no gaffType attribute for
	   an atom, otherwise throw the standard AttributeError.
	"""

	# open the given file name for writing
	from OpenSave import osOpen
	f = osOpen(fileName, "w")

	sortFunc = serialSort = lambda a1, a2: cmp(a1.coordIndex, a2.coordIndex)

	if isinstance(models, chimera.Molecule):
		models = [models]
	elif isinstance(models, Selection):
		# create a fictitious jumbo model
		if isinstance(models, ItemizedSelection):
			sel = models
		else:
			sel = ItemizedSelection()
			sel.merge(models)
		sel.addImplied()
		class Jumbo:
			def __init__(self, sel):
				self.atoms = sel.atoms()
				self.residues = sel.residues()
				self.bonds = sel.bonds()
				self.name = "(selection)"
		models = [Jumbo(sel)]
		sortFunc = lambda a1, a2: cmp(a1.molecule.id, a2.molecule.id) \
			or cmp(a1.molecule.subid, a2.molecule.subid) \
			or serialSort(a1, a2)
		multimodelHandling = "individual"

	# transform...
	if relModel is None:
		xform = chimera.Xform.identity()
	else:
		xform = relModel.openState.xform
		xform.invert()

	# need to find amide moieties since Sybyl has an explicit amide type
	if status:
		status("Finding amides\n")
	from ChemGroup import findGroup
	amides = findGroup("amide", models)
	amideNs = dict.fromkeys([amide[2] for amide in amides])
	amideCNs = dict.fromkeys([amide[0] for amide in amides])
	amideCNs.update(amideNs)
	amideOs = dict.fromkeys([amide[1] for amide in amides])

	substructureNames = None
	if multimodelHandling == "combined":
		# create a fictitious jumbo model
		class Jumbo:
			def __init__(self, models):
				self.atoms = []
				self.residues = []
				self.bonds = []
				self.name = models[0].name + " (combined)"
				for m in models:
					self.atoms.extend(m.atoms)
					self.residues.extend(m.residues)
					self.bonds.extend(m.bonds)
				# if combining single-residue models,
				# can be more informative to use model name
				# instead of residue type for substructure
				if len(models) == len(self.residues):
					rtypes = [r.type for r in self.residues]
					if len(set(rtypes)) < len(rtypes):
						mnames = [m.name for m in models]
						if len(set(mnames)) == len(mnames):
							self.substructureNames = dict(
								zip(self.residues, mnames))
		models = [Jumbo(models)]
		if hasattr(models[-1], 'substructureNames'):
			substructureNames = models[-1].substructureNames
			delattr(models[-1], 'substructureNames')
		sortFunc = lambda a1, a2: cmp(a1.molecule.id, a2.molecule.id) \
			or cmp(a1.molecule.subid, a2.molecule.subid) \
			or serialSort(a1, a2)

	# write out models
	for mol in models:
		if hasattr(mol, 'mol2comments'):
			for m2c in mol.mol2comments:
				print>>f, m2c
		if hasattr(mol, 'solventInfo' ):
			print>>f, mol.solventInfo

		# molecule section header
		print>>f, "%s" % MOLECULE_HEADER

		# molecule name
		print>>f, "%s" % mol.name

		ATOM_LIST = mol.atoms
		BOND_LIST = mol.bonds
		if skip:
			skip = set(skip)
			ATOM_LIST = [a for a in ATOM_LIST if a not in skip]
			BOND_LIST = [b for b in BOND_LIST
					if b.atoms[0] not in skip
					and b.atoms[1] not in skip]
		RES_LIST  = mol.residues

		# Chimera has an unusual internal order for its atoms, so
		# sort them by input order
		if status:
			status("Putting atoms in input order")
		ATOM_LIST.sort(sortFunc)

		# if anchor is not None, then there will be two entries in
		# the @SETS section of the file...
		if anchor:
			sets = 2
		else:
			sets = 0
		# number of entries for various sections...
		print>>f, "%d %d %d 0 %d" % (len(ATOM_LIST), len(BOND_LIST),
							len(RES_LIST), sets)

		# type of molecule
		if hasattr(mol, "mol2type"):
			mtype = mol.mol2type
		else:
			mtype = "SMALL"
			from chimera.resCode import nucleic3to1, protein3to1
			for r in mol.residues:
				if r.type in protein3to1:
					mtype = "PROTEIN"
					break
				if r.type in nucleic3to1:
					mtype = "NUCLEIC_ACID"
					break
		print>>f, mtype

		# indicate type of charge information
		if hasattr(mol, 'chargeModel'):
			print>>f, mol.chargeModel
		else:
			print>>f, "NO_CHARGES"

		if hasattr(mol, 'mol2comment'):
			print>>f, "\n%s" % mol.mol2comment
		else:
			print>>f, "\n"


		if status:
			status("writing atoms\n")
		# atom section header
		print>>f, "%s" % ATOM_HEADER

		# make a dictionary of residue indices so that we can do
		# quick look ups
		resIndices = {}
		for i, r in enumerate(RES_LIST):
			resIndices[r] = i+1
		for i, atom in enumerate(ATOM_LIST):
			# atom ID, starting from 1
			print>>f, "%7d" % (i+1),

			# atom name, possibly rearranged if it's a hydrogen
			if hydNamingStyle == "sybyl" \
						and not atom.name[0].isalpha():
				atomName = atom.name[1:] + atom.name[0]
			else:
				atomName = atom.name
			print>>f, "%-8s" % atomName,

			# untransformed coordinate position
			coord = xform.apply(atom.xformCoord())
			print>>f, "%9.4f %9.4f %9.4f" % (
						coord.x, coord.y, coord.z),

			# atom type
			if gaffType:
				try:
					atomType = atom.gaffType
				except AttributeError:
					if not gaffFailError:
						raise
					raise gaffFailError("%s has no Amber/GAFF type assigned.\n"
						"Use the AddCharge tool to assign Amber/GAFF types."
						% atom)
			elif hasattr(atom, 'mol2type'):
				atomType = atom.mol2type
			elif atom in amideNs:
				atomType = "N.am"
			elif atom.residue.id.chainId == "water":
				if atom.element.name == "O":
					atomType = "O.t3p"
				else:
					atomType = "H.t3p"
			elif atom.element.name == "N" and len(
			[r for r in atom.minimumRings() if r.aromatic()]) > 0:
				atomType = "N.ar"
			elif atom.idatmType == "C2" and len([nb for nb in atom.neighbors
											if nb.idatmType == "Ng+"]) > 2:
				atomType = "C.cat"
			else:
				try:
					atomType = chimera2sybyl[atom.idatmType]
				except KeyError:
					chimera.replyobj.warning("Atom whose"
						" IDATM type has no equivalent"
						" Sybyl type: %s (type: %s)\n"
						% (atom.oslIdent(),
						atom.idatmType))
					atomType = str(atom.element)
			print>>f, "%-5s" % atomType,

			# residue-related info
			res = atom.residue

			# residue index
			print>>f, "%5d" % resIndices[res],

			# substructure identifier and charge
			if hasattr(atom, 'charge'):
				charge = atom.charge
			else:
				charge = 0.0
			if substructureNames:
				rname = substructureNames[res]
			elif resNum:
				rname = "%3s%-5d" % (res.type, res.id.position)
			else:
				rname = "%3s" % res.type
			print>>f, "%s %9.4f" % (rname, charge)


		if status:
			status("writing bonds\n")
		# bond section header
		print>>f, "%s" % BOND_HEADER


		# make an atom-index dictionary to speed lookups
		atomIndices = {}
		for i, a in enumerate(ATOM_LIST):
			atomIndices[a] = i+1
		for i, bond in enumerate(BOND_LIST):
			a1, a2 = bond.atoms

			# ID
			print>>f, "%6d" % (i+1),

			# atom IDs
			print>>f, "%4d %4d" % (
					atomIndices[a1], atomIndices[a2]),

			# bond order; give it our best shot...
			amideA1 = a1 in amideCNs
			amideA2 = a2 in amideCNs
			if amideA1 and amideA2:
				print>>f, "am"
				continue
			if amideA1 or amideA2:
				if a1 in amideOs or a2 in amideOs:
					print>>f, "2"
				else:
					print>>f, "1"
				continue
				
			aromatic = False
			for ring in bond.minimumRings():
				if ring.aromatic():
					aromatic = True
					break
			if aromatic:
				print>>f, "ar"
				continue

			try:
				geom1 = typeInfo[a1.idatmType].geometry
			except KeyError:
				print>>f, "1"
				continue
			try:
				geom2 = typeInfo[a2.idatmType].geometry
			except KeyError:
				print>>f, "1"
				continue
			if geom1 not in [2,3] or geom2 not in [2,3]:
				print>>f, "1"
				continue
			# if either endpoint atom is in an aromatic ring and
			# the bond isn't, it's a single bond...
			for endp in [a1, a2]:
				aromatic = False
				for ring in endp.minimumRings():
					if ring.aromatic():
						aromatic = True
						break
				if aromatic:
					break
			else:
				# neither endpoint in aromatic ring
				print>>f, "2"
				continue
			print>>f, "1"

		if status:
			status("writing residues")
		# residue section header
		print>>f, "%s" % SUBSTR_HEADER

		for i, res in enumerate(RES_LIST):
			# residue id field
			print>>f, "%6d" % (i+1),

			# residue name field
			if substructureNames:
				rname = substructureNames[res]
			elif resNum:
				rname = "%3s%-4d" % (res.type, res.id.position)
			else:
				rname = "%3s" % res.type
			print>>f, rname,

			# ID of the root atom of the residue
			from chimera.misc import principalAtom
			chainAtom = principalAtom(res)
			if chainAtom is None:
				if hasattr(res, 'atomsMap'):
					chainAtom = res.atoms[0]
				else:
					chainAtom = res.atoms.values()[0][0]
			print>>f, "%5d" % atomIndices[chainAtom],


			print>>f, "RESIDUE           4",

			# Sybyl seems to use chain 'A' when chain ID is blank,
			# so run with that
			chainID = res.id.chainId
			if len(chainID.strip()) != 1:
				chainID = 'A'
			print>>f, "%s     %3s" % (chainID, res.type),

			# number of out-of-substructure bonds
			crossResBonds = 0
			if hasattr(res, "atomsMap"):
				atoms = res.atoms
				for a in atoms:
					for oa in a.bondsMap.keys():
						if oa.residue != res:
							crossResBonds += 1
			else:
				atoms = [a for aList in res.atoms.values()
							for a in aList]
				for a in atoms:
					for oa in a.bonds.keys():
						if oa.residue != res:
							crossResBonds += 1
			print>>f, "%5d" % crossResBonds,
			# print "ROOT" if first or only residue of a chain
			if a.molecule.rootForAtom(a, True).atom.residue == res:
				print>>f, "ROOT"
			else:
				print>>f

		# write flexible ligand docking info
		if anchor:
			if status:
				status("writing anchor info")
			print>>f, "%s" % SET_HEADER
			atomIndices = {}
			for i, a in enumerate(ATOM_LIST):
				atomIndices[a] = i+1
			bondIndices = {}
			for i, b in enumerate(BOND_LIST):
				bondIndices[b] = i+1
			print>>f, "ANCHOR          STATIC     ATOMS    <user>   **** Anchor Atom Set"
			atoms = anchor.atoms()
			print>>f, len(atoms),
			for a in atoms:
				if a in atomIndices:
					print>>f, atomIndices[a],
			print>>f

			print>>f, "RIGID           STATIC     BONDS    <user>   **** Rigid Bond Set"
			bonds = anchor.bonds()
			print>>f, len(bonds),
			for b in bonds:
				if b in bondIndices:
					print>>f, bondIndices[b],
			print>>f

	f.close()
def saveSession(filename):
    replyobj.status("Initializing session save...", blankAfter=0)
    from OpenSave import osOpen, tildeExpand
    fullName = tildeExpand(filename)
    try:
        outf = osOpen(fullName, "w")
    except:
        replyobj.reportException("Error opening %s for writing" % filename)
        return
    try:
        from cStringIO import StringIO
    except ImportError:
        from StringIO import StringIO

    class SessionIO:
        def __init__(self, stringIO, fileName):
            self.fileName = fileName
            self.stringIO = stringIO()

        def __getattr__(self, attrName):
            return getattr(self.stringIO, attrName)

    buf = SessionIO(StringIO, fullName)

    print >> outf, "import cPickle, base64"
    print >> outf, "try:"
    print >> outf, "\tfrom SimpleSession.versions.v45 import beginRestore,\\"
    print >> outf, "\t    registerAfterModelsCB, reportRestoreError, checkVersion"
    print >> outf, "except ImportError:"
    print >> outf, "\tfrom chimera import UserError"
    print >> outf, "\traise UserError('Cannot open session that was saved in a'"
    print >> outf, "\t    ' newer version of Chimera; update your version')"
    print >> outf, "checkVersion(%s)" % repr(version.releaseNum)
    print >> outf, "import chimera"
    print >> outf, "from chimera import replyobj"
    print >> outf, "replyobj.status('Beginning session restore...', \\"
    print >> outf, "    blankAfter=0)"
    print >> outf, "beginRestore()"
    print >> outf, """
def restoreCoreModels():
\tfrom SimpleSession.versions.v45 import init, restoreViewer, \\
\t     restoreMolecules, restoreColors, restoreSurfaces, \\
\t     restoreVRML, restorePseudoBondGroups, restoreModelAssociations"""
    global _id2color, _color2id
    _id2color = {}
    _color2id = {}

    molecules = [
        m for m in chimera.openModels.list(modelTypes=[chimera.Molecule],
                                           all=True) if autoRestorable(m)
    ]
    allSurfaces = chimera.openModels.list(modelTypes=[chimera.MSMSModel])
    allVrmls = [
        m for m in chimera.openModels.list(modelTypes=[chimera.VRMLModel])
        if autoRestorable(m)
    ]

    surfaces = [s for s in allSurfaces if s.molecule]
    if surfaces != allSurfaces:
        replyobj.warning(
            "Cannot save surfaces without associated structure.\nSurface will not be saved.\n"
        )
    vrmls = []
    for v in allVrmls:
        source = v.openedAs[0]
        if not source.startswith('#VRML')\
        and not os.path.exists(source):
            replyobj.warning("Source file for VRML model '%s' no"
                             " longer exists.\nThe model will not be"
                             " saved.\n" % v.name)
        else:
            vrmls.append(v)

    atoms = []
    bonds = []
    residues = []
    for m in molecules:
        atoms.extend(m.atoms)
        bonds.extend(m.bonds)
        residues.extend(m.residues)

    mgr = chimera.PseudoBondMgr.mgr()
    pbGroups = []
    for g in mgr.pseudoBondGroups:
        if g.category.startswith("internal-chain-"):
            noAutoRestore(g)
        else:
            pbGroups.append(g)
    pseudobonds = []
    pbMap = {}
    for pbg in pbGroups:
        pbs = [
            pb for pb in pbg.pseudoBonds
            if autoRestorable(pb.atoms[0].molecule)
            and autoRestorable(pb.atoms[1].molecule)
        ]
        pseudobonds.extend(pbs)
        pbMap[pbg] = pbs

    setSessionIDparams(molecules, residues, atoms, bonds, surfaces, vrmls,
                       pseudobonds, pbGroups)

    replyobj.status("Gathering molecule information...", blankAfter=0)
    molInfo = {}
    molInfo['ids'] = summarizeVals([(m.id, m.subid) for m in molecules])
    molInfo['name'] = summarizeVals([m.name for m in molecules])
    molInfo['color'] = summarizeVals([colorID(m.color) for m in molecules])
    molInfo['display'] = summarizeVals([m.display for m in molecules])
    molInfo['lineWidth'] = summarizeVals([m.lineWidth for m in molecules])
    molInfo['pointSize'] = summarizeVals([m.pointSize for m in molecules])
    molInfo['stickScale'] = summarizeVals([m.stickScale for m in molecules])
    molInfo['pdbHeaders'] = [m.pdbHeaders for m in molecules]
    molInfo['surfaceOpacity'] = summarizeVals(
        [m.surfaceOpacity for m in molecules])
    molInfo['ballScale'] = summarizeVals([m.ballScale for m in molecules])
    molInfo['vdwDensity'] = summarizeVals([m.vdwDensity for m in molecules])
    molInfo['autochain'] = summarizeVals([m.autochain for m in molecules])
    molInfo['ribbonHidesMainchain'] = summarizeVals(
        [m.ribbonHidesMainchain for m in molecules])
    molInfo['ribbonInsideColor'] = summarizeVals(
        [colorID(m.ribbonInsideColor) for m in molecules])
    molInfo['aromaticColor'] = summarizeVals(
        [colorID(m.aromaticColor) for m in molecules])
    molInfo['aromaticDisplay'] = summarizeVals(
        [m.aromaticDisplay for m in molecules])
    molInfo['aromaticLineType'] = summarizeVals(
        [m.aromaticLineType for m in molecules])
    molInfo['aromaticMode'] = summarizeVals(
        [m.aromaticMode for m in molecules])
    molInfo['hidden'] = summarizeVals(
        [m in m.openState.hidden for m in molecules])
    molInfo['optional'] = saveOptionalAttrs(chimera.Molecule, molecules)
    print >> outf, "\tmolInfo =", pickled(molInfo)

    replyobj.status("Gathering residue information...", blankAfter=0)
    resInfo = {}
    resInfo['molecule'] = summarizeVals(
        [sessionID(r.molecule) for r in residues], consecutiveExceptions=True)
    resInfo['name'] = summarizeVals([r.type for r in residues])
    resInfo['chain'] = summarizeVals([r.id.chainId for r in residues],
                                     consecutiveExceptions=True)
    resInfo['insert'] = summarizeVals([r.id.insertionCode for r in residues])
    resInfo['position'] = summarizeSequentialVals(
        [r.id.position for r in residues])
    resInfo['ribbonColor'] = summarizeVals(
        [colorID(r.ribbonColor) for r in residues], consecutiveExceptions=True)
    resInfo['labelColor'] = summarizeVals(
        [colorID(r.labelColor) for r in residues], consecutiveExceptions=True)
    resInfo['ss'] = summarizeVals([(r.isHelix, r.isStrand, r.isTurn)
                                   for r in residues],
                                  consecutiveExceptions=True)
    resInfo['ssId'] = summarizeVals([r.ssId for r in residues],
                                    consecutiveExceptions=True)
    resInfo['ribbonDrawMode'] = summarizeVals(
        [r.ribbonDrawMode for r in residues], consecutiveExceptions=True)
    resInfo['ribbonDisplay'] = summarizeVals(
        [r.ribbonDisplay for r in residues], consecutiveExceptions=True)
    resInfo['label'] = summarizeVals([r.label for r in residues])
    resInfo['labelOffset'] = summarizeVals([r.labelOffset for r in residues])
    resInfo['isHet'] = summarizeVals([r.isHet for r in residues],
                                     consecutiveExceptions=True)
    resInfo['fillDisplay'] = summarizeVals([r.fillDisplay for r in residues],
                                           consecutiveExceptions=True)
    resInfo['fillMode'] = summarizeVals([r.fillMode for r in residues],
                                        consecutiveExceptions=True)
    resInfo['optional'] = saveOptionalAttrs(chimera.Residue, residues)
    print >> outf, "\tresInfo =", pickled(resInfo)

    replyobj.status("Gathering atom information...", blankAfter=0)
    atomInfo = {}
    atomInfo['altLoc'] = summarizeVals([a.altLoc for a in atoms])
    atomInfo['residue'] = summarizeVals([sessionID(a.residue) for a in atoms],
                                        consecutiveExceptions=True)
    atomInfo['element'] = summarizeVals([a.element.number for a in atoms])
    atomInfo['name'] = summarizeVals([a.name for a in atoms])
    atomInfo['color'] = summarizeVals([colorID(a.color) for a in atoms])
    atomInfo['vdwColor'] = summarizeVals([colorID(a.vdwColor) for a in atoms])
    atomInfo['labelColor'] = summarizeVals(
        [colorID(a.labelColor) for a in atoms])
    atomInfo['surfaceColor'] = summarizeVals(
        [colorID(a.surfaceColor) for a in atoms])
    atomInfo['drawMode'] = summarizeVals([a.drawMode for a in atoms],
                                         consecutiveExceptions=True)
    atomInfo['display'] = summarizeVals([a.display for a in atoms],
                                        consecutiveExceptions=True)
    atomInfo['label'] = summarizeVals([a.label for a in atoms])
    atomInfo['labelOffset'] = summarizeVals([a.labelOffset for a in atoms])
    atomInfo['radius'] = summarizeVals([a.radius for a in atoms])
    atomInfo['surfaceDisplay'] = summarizeVals(
        [a.surfaceDisplay for a in atoms], consecutiveExceptions=True)
    atomInfo['surfaceCategory'] = summarizeVals(
        [a.surfaceCategory for a in atoms], consecutiveExceptions=True)
    atomInfo['surfaceOpacity'] = summarizeVals(
        [a.surfaceOpacity for a in atoms], consecutiveExceptions=True)
    atomInfo['vdw'] = summarizeVals([a.vdw for a in atoms],
                                    consecutiveExceptions=True)
    atomInfo['optional'] = saveOptionalAttrs(chimera.Atom, atoms)

    # only restore explicitly-set IDATM types...
    atomInfo['idatmType'] = summarizeVals([(a.idatmIsExplicit and a.idatmType)
                                           for a in atoms])
    print >> outf, "\tatomInfo =", pickled(atomInfo)

    replyobj.status("Gathering bond information...", blankAfter=0)
    bondInfo = {}
    bondInfo['atoms'] = [[sessionID(a) for a in b.atoms] for b in bonds]
    bondInfo['drawMode'] = summarizeVals([b.drawMode for b in bonds],
                                         consecutiveExceptions=True)
    bondInfo['display'] = summarizeVals([b.display for b in bonds])
    bondInfo['label'] = summarizeVals([b.label for b in bonds])
    bondInfo['labelOffset'] = summarizeVals([b.labelOffset for b in bonds])
    bondInfo['radius'] = summarizeVals([b.radius for b in bonds])
    bondInfo['optional'] = saveOptionalAttrs(chimera.Bond, bonds)

    print >> outf, "\tbondInfo =", pickled(bondInfo)

    replyobj.status("Gathering coordinates...", blankAfter=0)
    crdInfo = {}
    for m in molecules:
        crdSets = {}
        crdInfo[sessionID(m)] = crdSets
        for key, coordSet in m.coordSets.items():
            crdSets[key] = [(sessionID(a), str(a.coord(coordSet)))
                            for a in m.atoms]
            if coordSet == m.activeCoordSet:
                crdSets['active'] = key
    print >> outf, "\tcrdInfo =", pickled(crdInfo)

    replyobj.status("Gathering surface information...", blankAfter=0)
    surfInfo = {}
    surfInfo['molecule'] = [sessionID(s.molecule) for s in surfaces]
    surfInfo['name'] = [s.name for s in surfaces]
    surfInfo['customColors'] = surfColors = []
    for attrname in ('category', 'colorMode', 'density', 'drawMode', 'display',
                     'probeRadius', 'allComponents', 'lineWidth', 'pointSize',
                     'useLighting', 'twoSidedLighting', 'smoothLines',
                     'transparencyBlendMode', 'oneTransparentLayer'):
        values = [getattr(s, attrname) for s in surfaces]
        surfInfo[attrname] = summarizeVals(values)
    for s in surfaces:
        if s.colorMode == chimera.MSMSModel.Custom:
            surfColors.append(
                summarizeVals([colorID(c) for c in s.customColors]))
        else:
            surfColors.append(summarizeVals([]))
    print >> outf, "\tsurfInfo =", sesRepr(surfInfo)

    replyobj.status("Gathering VRML information...", blankAfter=0)
    vrmlInfo = {}
    vrmlInfo['id'] = summarizeVals([v.id for v in vrmls])
    vrmlInfo['subid'] = summarizeVals([v.subid for v in vrmls])
    vrmlInfo['name'] = summarizeVals([v.name for v in vrmls])
    vrmlInfo['display'] = summarizeVals([v.display for v in vrmls])
    vrmlInfo['vrmlString'] = vrmlStrings = []
    for v in vrmls:
        source = v.openedAs[0]
        if source.startswith('#VRML'):
            vrmlStrings.append(source)
        else:
            # source is file name
            vrmlFile = open(source, 'r')
            vrmlStrings.append(vrmlFile.read())
            vrmlFile.close()
    print >> outf, "\tvrmlInfo =", sesRepr(vrmlInfo)

    replyobj.status("Gathering color information...", blankAfter=0)
    # remember all saved colors/materials...
    knownColors = {}
    knownMaterials = {}
    from chimera import _savedColors, _savedMaterials
    for name, material in _savedMaterials.items():
        knownMaterials[name] = (material.specular, material.shininess)
    for name, color in _savedColors.items():
        if not isinstance(color, chimera.MaterialColor):
            continue
        matName = color.material.name()
        if matName is None:  # unnamed material
            matName = "mat" + str(id(color.material))
        knownColors[name] = (color.ambientDiffuse, color.opacity, matName)
        if matName not in knownMaterials:
            mat = color.material
            knownMaterials[matName] = (mat.specular, mat.shininess)
    print >> outf, "\tcolors =", sesRepr(knownColors)
    print >> outf, "\tmaterials =", sesRepr(knownMaterials)

    replyobj.status("Gathering pseudobond information...", blankAfter=0)
    pbInfo = {}
    pbInfo['category'] = [g.category for g in pbGroups]
    pbInfo['id'] = [g.id for g in pbGroups]
    pbInfo['color'] = summarizeVals([colorID(g.color) for g in pbGroups])
    pbInfo['showStubBonds'] = summarizeVals(
        [g.showStubBonds for g in pbGroups])
    pbInfo['lineWidth'] = summarizeVals([g.lineWidth for g in pbGroups])
    pbInfo['stickScale'] = summarizeVals([g.stickScale for g in pbGroups])
    pbInfo['lineType'] = summarizeVals([g.lineType for g in pbGroups])
    pbInfo['bondInfo'] = pbBondInfos = []
    for g in pbGroups:
        pbs = pbMap[g]
        info = {}
        pbBondInfos.append(info)
        info['atoms'] = [[sessionID(a) for a in pb.atoms] for pb in pbs]
        info['drawMode'] = summarizeVals([pb.drawMode for pb in pbs])
        info['display'] = summarizeVals([pb.display for pb in pbs])
        info['halfbond'] = summarizeVals([pb.halfbond for pb in pbs])
        info['label'] = summarizeVals([pb.label for pb in pbs])
        info['color'] = summarizeVals([colorID(pb.color) for pb in pbs])
        info['labelColor'] = summarizeVals(
            [colorID(pb.labelColor) for pb in pbs])
    print >> outf, "\tpbInfo =", sesRepr(pbInfo)

    associations = {}
    for m in molecules + surfaces + vrmls + pbGroups:
        ams = []
        for am in m.associatedModels():
            if autoRestorable(am):
                ams.append(sessionID(am))
        if ams:
            associations[sessionID(m)] = ams
    print >> outf, "\tmodelAssociations =", sesRepr(associations)

    replyobj.status("Gathering font information...", blankAfter=0)
    from chimera.bgprefs import BACKGROUND, LABEL_FONT
    from chimera import preferences
    fontInfo = {'face': preferences.getOption(BACKGROUND, LABEL_FONT).get()}

    replyobj.status("Gathering clip plane information...", blankAfter=0)
    clipPlaneInfo = {}
    for m in molecules + surfaces:
        if m.useClipPlane:
            pl = m.clipPlane
            clipPlaneInfo[sessionID(m)] = (pl.origin.data(), pl.normal.data(),
                                           m.useClipThickness, m.clipThickness)

    replyobj.status("Gathering selection information...", blankAfter=0)
    curSelIds = []
    curSel = selection.copyCurrent()
    selMols = curSel.molecules()
    badMols = filter(lambda m: not autoRestorable(m), selMols)
    if badMols:
        curSel.remove(badMols)
    for a in curSel.atoms():
        curSelIds.append(sessionID(a))
    for b in curSel.bonds():
        curSelIds.append(sessionID(b))

    savedSels = []
    from copy import copy
    for selName, sel in selection.savedSels.items():
        badMols = [m for m in sel.molecules() if not autoRestorable(m)]
        filtSel = copy(sel)
        if badMols:
            filtSel.remove(badMols)
        ids = []
        for a in filtSel.atoms():
            ids.append(sessionID(a))
        for b in filtSel.bonds():
            ids.append(sessionID(b))
        savedSels.append((selName, ids))

    replyobj.status("Gathering transformation information...", blankAfter=0)
    xfDict = {}
    for m in (molecules + vrmls):
        xf = m.openState.xform
        rotV, angle = xf.getRotation()
        rot = tuple([float(v) for v in str(rotV).split()])
        trans = tuple([float(v) for v in str(xf.getTranslation()).split()])
        xfDict[sessionID(m)] = ((rot, angle), trans, m.openState.active)

    replyobj.status("Gathering view information...", blankAfter=0)
    viewer = chimera.viewer
    camera = viewer.camera

    viewerAttrs = {}
    for va in ("viewSize", "scaleFactor", "clipping", "highlight", "depthCue",
               "depthCueRange", "showSilhouette", "silhouetteColor",
               "silhouetteWidth"):
        if va.endswith("Color"):
            viewerAttrs[va] = colorID(getattr(viewer, va))
        else:
            viewerAttrs[va] = getattr(viewer, va)
    cameraAttrs = {}
    for ca in ("ortho", "nearFar", "focal", "center", "fieldOfView",
               "eyeSeparation"):
        cameraAttrs[ca] = getattr(camera, ca)

    viewerInfo = {
        "detail": chimera.LODControl.get().quality,
        "viewerFog": colorID(viewer.depthCueColor),
        "viewerBG": colorID(viewer.background),
        "viewerHL": colorID(viewer.highlightColor),
        "viewerAttrs": viewerAttrs,
        "cameraAttrs": cameraAttrs,
        "cameraMode": camera.mode(),
    }

    # start printing into buffer so that color map can be inserted here
    replyobj.status("Writing preliminary session info...", blankAfter=0)
    print >> buf, "\tviewerInfo =", sesRepr(viewerInfo)
    print >> buf, """
\treplyobj.status("Initializing session restore...", blankAfter=0)
\tinit(colorInfo)
\treplyobj.status("Restoring colors...", blankAfter=0)
\trestoreColors(colors, materials)
\treplyobj.status("Restoring molecules...", blankAfter=0)
\trestoreMolecules(molInfo, resInfo, atomInfo, bondInfo, crdInfo)
\treplyobj.status("Restoring surfaces...", blankAfter=0)
\trestoreSurfaces(surfInfo)
\treplyobj.status("Restoring VRML models...", blankAfter=0)
\trestoreVRML(vrmlInfo)
\treplyobj.status("Restoring pseudobond groups...", blankAfter=0)
\trestorePseudoBondGroups(pbInfo)
\treplyobj.status("Restoring model associations...", blankAfter=0)
\trestoreModelAssociations(modelAssociations)
\treplyobj.status("Restoring camera...", blankAfter=0)
\trestoreViewer(viewerInfo)

try:
	restoreCoreModels()
except:
	reportRestoreError("Error restoring core models")

\treplyobj.status("Restoring extension info...", blankAfter=0)
"""
    replyobj.status("Writing extension session info...", blankAfter=0)
    chimera.triggers.activateTrigger(SAVE_SESSION, buf)
    replyobj.status("Writing remaining session info...", blankAfter=0)
    print >> buf, """
def restoreRemainder():
\tfrom SimpleSession.versions.v45 import restoreWindowSize, \\
\t     restoreOpenStates, restoreSelections, restoreFontInfo, \\
\t     restoreOpenModelsAttrs, restoreModelClip
"""
    # any use of colors below have to have those colors also run through
    # colorID() before init() gets printed, so that the color map contains
    # those colors
    print >> buf, "\tcurSelIds = ", sesRepr(curSelIds)
    print >> buf, "\tsavedSels =", sesRepr(savedSels)
    print >> buf, "\topenModelsAttrs = { 'cofrMethod': %d }" % (
        chimera.openModels.cofrMethod)
    if chimera.openModels.cofrMethod == chimera.openModels.Fixed:
        cofr = chimera.openModels.cofr
        print >> buf, "\tfrom chimera import Point"
        print>> buf, "\topenModelsAttrs['cofr'] = Point(%g, %g, %g)" \
            % (cofr.x, cofr.y, cofr.z)
    print >> buf, "\twindowSize =", sesRepr(chimera.viewer.windowSize)
    print >> buf, "\txformMap =", sesRepr(xfDict)
    print >> buf, "\tfontInfo =", sesRepr(fontInfo)
    print >> buf, "\tclipPlaneInfo =", sesRepr(clipPlaneInfo)
    print >> buf, """
\treplyobj.status("Restoring window...", blankAfter=0)
\trestoreWindowSize(windowSize)
\treplyobj.status("Restoring open states...", blankAfter=0)
\trestoreOpenStates(xformMap)
\treplyobj.status("Restoring font info...", blankAfter=0)
\trestoreFontInfo(fontInfo)
\treplyobj.status("Restoring selections...", blankAfter=0)
\trestoreSelections(curSelIds, savedSels)
\treplyobj.status("Restoring openModel attributes...", blankAfter=0)
\trestoreOpenModelsAttrs(openModelsAttrs)
\treplyobj.status("Restoring model clipping...", blankAfter=0)
\trestoreModelClip(clipPlaneInfo)

\treplyobj.status("Restoring remaining extension info...", blankAfter=0)
try:
	restoreRemainder()
except:
	reportRestoreError("Error restoring post-model state")
from SimpleSession.versions.v45 import makeAfterModelsCBs
makeAfterModelsCBs()
"""
    print >> buf, "from SimpleSession.versions.v45 import endRestore"
    print >> buf, "replyobj.status('Finishing restore...', blankAfter=0)"
    print >> buf, "endRestore()"

    print >> buf, "replyobj.status('Restore finished.')"

    # insert color map
    print >> outf, "\tcolorInfo =", sesRepr(_id2color)

    # print buffered output
    print >> outf, buf.getvalue()
    buf.close()
    outf.close()
    from versions import globals
    del globals.sessionMap
    _id2color = _color2id = None
    replyobj.status("Session written")
Example #36
0
def readPBinfo(fileName, category=None, clearCategory=1, lineWidth=None,
		drawMode=None, leftModel=None, rightModel=None, defColor=None):
	"""read a file containing pseudobond info and display those bonds

	   'category' defaults to 'fileName'.  'clearCategory' controls
	   whether the pseudobond group should be cleared of pre-existing
	   pseudobonds before reading the file.  'lineWidth' is a floating-
	   point number and controls the width of lines used to draw the
	   pseudobonds.  This only is relevant if 'drawMode' is Wire.
	   'drawMode' controls the depiction style of the pseudobonds.
	   Possible modes are:

	   	Wire (aka chimera.Bond_Wire) -- wireframe
		Stick (aka chimera.Bond_Stick) -- sticks
	
	   'leftModel' and 'rightModel' control what models the endpoints
	   of the pseudobond lie in, if none are specified in the input file.
	   'defColor' is the color assigned to the pseudobond group as a whole,
	   which can be overridden by specific pseudobonds.
	"""
	foundErrors = False
	colorCache = {}

	if not category:
		category = fileName
	
	group = chimera.misc.getPseudoBondGroup(category)
	if lineWidth:
		group.lineWidth = lineWidth
	if drawMode:
		group.drawMode = drawMode

	if clearCategory:
		group.deleteAll()
	
	if defColor:
		if isinstance(defColor, basestring):
			c = chimera.Color.lookup(defColor)
			if not c:
				replyobj.message(
					"Cannot find color '%s'\n" % defColor)
				foundErrors = True
		else:
			c = defColor
		group.color = c

	from OpenSave import osOpen
	bondFile = osOpen(fileName)
	lineNum = 0
	for line in bondFile.readlines():
		line = line.strip()
		lineNum = lineNum + 1

		if not line:
			# blank line
			continue
		
		try:
			spec1, spec2, color = line.split(None, 2)
		except:
			label = color = None
			try:
				spec1, spec2 = line.split()
			except ValueError:
				replyobj.message("Line %d does not have at"
					" least two atom specifiers.")
				foundErrors = True
				continue
		if color:
			# try to distinguish between color name and label
			try:
				color, label = color.split(None, 1)
			except:
				label = None
			if color[0] != "#":
				while (label and not colors.has_key(color)):
					try:
						c, label = label.split(None, 1)
					except:
						color = " ".join([color, label])
						label = None
					else:
						color = " ".join([color, c])
						
		atom1 = _processSpec(spec1, leftModel)
		if not atom1:
			replyobj.message(
				"Left atom spec of line %d of file doesn't"
						" select exactly one atom."
						"  Skipping.\n" % lineNum)
			foundErrors = True
			continue

		atom2 = _processSpec(spec2, leftModel)
		if not atom2:
			replyobj.message(
				"Right atom spec of line %d of file doesn't"
						" select exactly one atom."
						"  Skipping.\n" % lineNum)
			foundErrors = True
			continue

		if color:
			if color[0] == '#':
				fieldLen = int((len(color) - 1) / 3)
				if 3 * fieldLen + 1 != len(color):
					replyobj.message("Bad Tk color '%s'"
						" on line %d of file.\n"
						% (color, lineNum))
					foundErrors = True
				elif colorCache.has_key(color):
					color = colorCache[color]
				else:
					r = color[1:1+fieldLen]
					g = color[1+fieldLen:1+2*fieldLen]
					b = color[1+2*fieldLen:]
					r = int(r, 16)
					g = int(g, 16)
					b = int(b, 16)
					maxVal = int('f' * fieldLen, 16)
					maxVal = float(maxVal)
					c = chimera.MaterialColor(r/maxVal,
							g/maxVal, b/maxVal)
					colorCache[color] = c
					color = c
			else:
				try:
					color = getColorByName(color)
				except KeyError:
					replyobj.message(
						"Unknown color '%s' on line %d"
						" of file.\n" % (color,lineNum))
					foundErrors = True
					color = None
		
		pb = group.newPseudoBond(atom1, atom2)
		if color:
			pb.color = color
		if label:
			pb.label = label
	bondFile.close()

	if foundErrors:
		chimera.replyobj.error(
				"Errors encountered while reading file.\n"
				"Check reply log for details.\n")
Example #37
0
def readFiles(fileNames, clear=True):
    if not _ilabelModel:
        IlabelModel()
    if clear:
        for label in _ilabelModel.labels[:]:
            _ilabelModel.removeLabel(label)
    _ilabelModel.setMajorChange()
    from chimera import UserError
    for fileName in fileNames:
        from OpenSave import osOpen
        f = osOpen(fileName)
        label = labelID = text = None
        for ln, line in enumerate(f):
            lineNum = ln + 1
            if not line.strip() or line.strip().startswith('#'):
                # skip blank lines / comments
                continue
            if line.lower().startswith("label"):
                labelID = line[5:].strip()
                continue
            if line[0] != '\t':
                f.close()
                raise UserError("%s, line %d: line must start with 'Label'"
                                " or tab" % (fileName, lineNum))
            try:
                semi = line.index(':')
            except ValueError:
                f.close()
                raise UserError("%s, line %d: line must have semi-colon" %
                                (fileName, lineNum))
            name = line[1:semi].lower()
            if not label and name != "(x,y)":
                f.close()
                raise UserError("%s, line %d: xy position must immediately"
                                " follow 'Label' line" % (fileName, lineNum))
            if label and text is None and name != "text":
                f.close()
                raise UserError("%s, line %d: text must immediately"
                                " follow xy position" % (fileName, lineNum))
            value = line[semi + 1:].strip()
            if name == "(x,y)":
                text = None
                try:
                    pos = eval(value)
                except:
                    f.close()
                    raise UserError("%s, line %d: could not parse xy value" %
                                    (fileName, lineNum))
                if labelID:
                    label = _ilabelModel.newLabel(pos)
                else:
                    label = _ilabelModel.newLabel(pos, labelID=labelID)
            elif name == "text":
                try:
                    text = eval(value)
                except:
                    f.close()
                    _ilabelModel.removeLabel(label)
                    raise UserError(
                        "%s, line %d: could not parse 'text' value" %
                        (fileName, lineNum))
                label.set(text)
            elif name == "shown":
                if name == "shown":
                    try:
                        label.shown = eval(value.capitalize())
                    except:
                        f.close()
                        _ilabelModel.removeLabel(label)
                        raise UserError("%s, line %d: could not parse 'shown'"
                                        " value" % (fileName, lineNum))
            else:
                chars = []
                for l in label.lines:
                    chars.extend(l)
                if '),' in value:
                    values = value.split('),')
                    for i, v in enumerate(values[:-1]):
                        values[i] = v + ')'
                elif ',' in value and not value.strip().startswith('('):
                    values = value.split(',')
                else:
                    values = [value] * len(chars)
                if len(values) != len(chars):
                    f.close()
                    raise UserError(
                        "%s, line %d: number of values not equal"
                        " to numbers of characters in text (and not a single"
                        " value)" % (fileName, lineNum))
                if name.startswith("font size"):
                    try:
                        values = [eval(v) for v in values]
                    except:
                        f.close()
                        _ilabelModel.removeLabel(label)
                        raise UserError("%s, line %d: could not parse"
                                        " 'font size' value(s)" %
                                        (fileName, lineNum))
                    for c, v in zip(chars, values):
                        c.size = v
                elif name.startswith("font style"):
                    for c, v in zip(chars, values):
                        try:
                            c.style = styleLookup(v.strip().lower())
                        except:
                            f.close()
                            _ilabelModel.removeLabel(label)
                            raise UserError("%s, line %d: could not parse"
                                            " 'font style' value(s)" %
                                            (fileName, lineNum))
                elif name.startswith("font typeface"):
                    for c, v in zip(chars, values):
                        try:
                            c.fontName = typefaceLookup(v.strip().lower())
                        except:
                            f.close()
                            _ilabelModel.removeLabel(label)
                            raise UserError("%s, line %d: could not parse"
                                            " 'font typeface' value(s)" %
                                            (fileName, lineNum))
                elif name.startswith("color"):
                    try:
                        values = [eval(v) for v in values]
                    except:
                        f.close()
                        _ilabelModel.removeLabel(label)
                        raise UserError("%s, line %d: could not parse"
                                        " 'color' value(s)" %
                                        (fileName, lineNum))
                    for c, v in zip(chars, values):
                        c.rgba = v
                else:
                    _ilabelModel.removeLabel(label)
                    raise UserError(
                        "%s, line %d: unknown label attribute '%s'" %
                        (fileName, lineNum, name))
        f.close()
    if chimera.nogui:
        dlg = None
    else:
        from gui import IlabelDialog
        from chimera import dialogs
        dlg = dialogs.find(IlabelDialog.name)
    if dlg:
        dlg.updateGUI("file")
Example #38
0
def readFiles(fileNames, clear=True):
	if not _ilabelModel:
		IlabelModel()
	if clear:
		for label in _ilabelModel.labels[:]:
			_ilabelModel.removeLabel(label)
	_ilabelModel.setMajorChange()
	from chimera import UserError
	for fileName in fileNames:
		from OpenSave import osOpen
		f = osOpen(fileName)
		label = labelID = text = None
		for ln, line in enumerate(f):
			lineNum = ln + 1
			if not line.strip() or line.strip().startswith('#'):
				# skip blank lines / comments
				continue
			if line.lower().startswith("label"):
				labelID = line[5:].strip()
				continue
			if line[0] != '\t':
				f.close()
				raise UserError("%s, line %d: line must start with 'Label'"
					" or tab" % (fileName, lineNum))
			try:
				semi = line.index(':')
			except ValueError:
				f.close()
				raise UserError("%s, line %d: line must have semi-colon"
					% (fileName, lineNum))
			name = line[1:semi].lower()
			if not label and name != "(x,y)":
				f.close()
				raise UserError("%s, line %d: xy position must immediately"
					" follow 'Label' line" % (fileName, lineNum))
			if label and text is None and name != "text":
				f.close()
				raise UserError("%s, line %d: text must immediately"
					" follow xy position" % (fileName, lineNum))
			value = line[semi+1:].strip()
			if name == "(x,y)":
				text = None
				try:
					pos = eval(value)
				except:
					f.close()
					raise UserError("%s, line %d: could not parse xy value"
						% (fileName, lineNum))
				if labelID:
					label = _ilabelModel.newLabel(pos)
				else:
					label = _ilabelModel.newLabel(pos, labelID=labelID)
			elif name == "text":
				try:
					text = eval(value)
				except:
					f.close()
					_ilabelModel.removeLabel(label)
					raise UserError("%s, line %d: could not parse 'text' value"
						% (fileName, lineNum))
				label.set(text)
			elif name == "shown":
				if name == "shown":
					try:
						label.shown = eval(value.capitalize())
					except:
						f.close()
						_ilabelModel.removeLabel(label)
						raise UserError("%s, line %d: could not parse 'shown'"
							" value" % (fileName, lineNum))
			else:
				chars = []
				for l in label.lines:
					chars.extend(l)
				if '),' in value:
					values = value.split('),')
					for i, v in enumerate(values[:-1]):
						values[i] = v + ')'
				elif ',' in value and not value.strip().startswith('('):
					values = value.split(',')
				else:
					values = [value] * len(chars)
				if len(values) != len(chars):
					f.close()
					raise UserError("%s, line %d: number of values not equal"
						" to numbers of characters in text (and not a single"
						" value)" % (fileName, lineNum))
				if name.startswith("font size"):
					try:
						values = [eval(v) for v in values]
					except:
						f.close()
						_ilabelModel.removeLabel(label)
						raise UserError("%s, line %d: could not parse"
							" 'font size' value(s)" % (fileName, lineNum))
					for c, v in zip(chars, values):
						c.size = v
				elif name.startswith("font style"):
					for c, v in zip(chars, values):
						try:
							c.style = styleLookup(v.strip().lower())
						except:
							f.close()
							_ilabelModel.removeLabel(label)
							raise UserError("%s, line %d: could not parse"
								" 'font style' value(s)" % (fileName, lineNum))
				elif name.startswith("font typeface"):
					for c, v in zip(chars, values):
						try:
							c.fontName = typefaceLookup(v.strip().lower())
						except:
							f.close()
							_ilabelModel.removeLabel(label)
							raise UserError("%s, line %d: could not parse"
								" 'font typeface' value(s)" %
								(fileName, lineNum))
				elif name.startswith("color"):
					try:
						values = [eval(v) for v in values]
					except:
						f.close()
						_ilabelModel.removeLabel(label)
						raise UserError("%s, line %d: could not parse"
							" 'color' value(s)" % (fileName, lineNum))
					for c, v in zip(chars, values):
						c.rgba = v
				else:
					_ilabelModel.removeLabel(label)
					raise UserError("%s, line %d: unknown label attribute '%s'"
						% (fileName, lineNum, name))
		f.close()
	if chimera.nogui:
		dlg = None
	else:
		from gui import IlabelDialog
		from chimera import dialogs
		dlg = dialogs.find(IlabelDialog.name)
	if dlg:
		dlg.updateGUI("file")
Example #39
0
def readPBinfo(fileName,
               category=None,
               clearCategory=1,
               lineWidth=None,
               drawMode=None,
               leftModel=None,
               rightModel=None,
               defColor=None):
    """read a file containing pseudobond info and display those bonds

	   'category' defaults to 'fileName'.  'clearCategory' controls
	   whether the pseudobond group should be cleared of pre-existing
	   pseudobonds before reading the file.  'lineWidth' is a floating-
	   point number and controls the width of lines used to draw the
	   pseudobonds.  This only is relevant if 'drawMode' is Wire.
	   'drawMode' controls the depiction style of the pseudobonds.
	   Possible modes are:

	   	Wire (aka chimera.Bond_Wire) -- wireframe
		Stick (aka chimera.Bond_Stick) -- sticks
	
	   'leftModel' and 'rightModel' control what models the endpoints
	   of the pseudobond lie in, if none are specified in the input file.
	   'defColor' is the color assigned to the pseudobond group as a whole,
	   which can be overridden by specific pseudobonds.
	"""
    foundErrors = False
    colorCache = {}

    if not category:
        category = fileName

    group = chimera.misc.getPseudoBondGroup(category)
    if lineWidth:
        group.lineWidth = lineWidth
    if drawMode:
        group.drawMode = drawMode

    if clearCategory:
        group.deleteAll()

    if defColor:
        if isinstance(defColor, basestring):
            c = chimera.Color.lookup(defColor)
            if not c:
                replyobj.message("Cannot find color '%s'\n" % defColor)
                foundErrors = True
        else:
            c = defColor
        group.color = c

    from OpenSave import osOpen
    bondFile = osOpen(fileName)
    lineNum = 0
    for line in bondFile.readlines():
        line = line.strip()
        lineNum = lineNum + 1

        if not line:
            # blank line
            continue

        try:
            spec1, spec2, color = line.split(None, 2)
        except:
            label = color = None
            try:
                spec1, spec2 = line.split()
            except ValueError:
                replyobj.message("Line %d does not have at"
                                 " least two atom specifiers.")
                foundErrors = True
                continue
        if color:
            # try to distinguish between color name and label
            try:
                color, label = color.split(None, 1)
            except:
                label = None
            if color[0] != "#":
                while (label and not colors.has_key(color)):
                    try:
                        c, label = label.split(None, 1)
                    except:
                        color = " ".join([color, label])
                        label = None
                    else:
                        color = " ".join([color, c])

        atom1 = _processSpec(spec1, leftModel)
        if not atom1:
            replyobj.message("Left atom spec of line %d of file doesn't"
                             " select exactly one atom."
                             "  Skipping.\n" % lineNum)
            foundErrors = True
            continue

        atom2 = _processSpec(spec2, leftModel)
        if not atom2:
            replyobj.message("Right atom spec of line %d of file doesn't"
                             " select exactly one atom."
                             "  Skipping.\n" % lineNum)
            foundErrors = True
            continue

        if color:
            if color[0] == '#':
                fieldLen = int((len(color) - 1) / 3)
                if 3 * fieldLen + 1 != len(color):
                    replyobj.message("Bad Tk color '%s'"
                                     " on line %d of file.\n" %
                                     (color, lineNum))
                    foundErrors = True
                elif colorCache.has_key(color):
                    color = colorCache[color]
                else:
                    r = color[1:1 + fieldLen]
                    g = color[1 + fieldLen:1 + 2 * fieldLen]
                    b = color[1 + 2 * fieldLen:]
                    r = int(r, 16)
                    g = int(g, 16)
                    b = int(b, 16)
                    maxVal = int('f' * fieldLen, 16)
                    maxVal = float(maxVal)
                    c = chimera.MaterialColor(r / maxVal, g / maxVal,
                                              b / maxVal)
                    colorCache[color] = c
                    color = c
            else:
                try:
                    color = getColorByName(color)
                except KeyError:
                    replyobj.message("Unknown color '%s' on line %d"
                                     " of file.\n" % (color, lineNum))
                    foundErrors = True
                    color = None

        pb = group.newPseudoBond(atom1, atom2)
        if color:
            pb.color = color
        if label:
            pb.label = label
    bondFile.close()

    if foundErrors:
        chimera.replyobj.error("Errors encountered while reading file.\n"
                               "Check reply log for details.\n")
Example #40
0
def loadEnsemble(inputs, startFrame, endFrame, callback, relativeTo=None):
	from chimera import replyobj
	style = inputs[0]
	files = inputs[1:]
	if relativeTo:
		for i, f in enumerate(files):
			if not isinstance(f, basestring) or os.path.isabs(f):
				continue
			files[i] = os.path.join(relativeTo, f)
	if style.lower().startswith("multiple"):
		startFile, endFile = files
		errMsg = "Can't determine numeric sequence from starting file name (%s) to ending file name (%s)" % (startFile, endFile)
		for i, c in enumerate(startFile):
			if i >= len(endFile):
				raise ValueError(errMsg)
			if endFile[i] != c:
				break
		else:
			raise ValueError(errMsg)
		# push trailing digits on the prefix back into the number part,
		# otherwise ranges like 1-100 are bug problems
		while i > 0 and startFile[i-1].isdigit():
			i -= 1
		prefixIndex = i
		prefix = startFile[:i]
		while i < len(startFile) and startFile[i].isdigit():
			i += 1
		startSuffixIndex = i
		endSuffixIndex = i + len(endFile) - len(startFile)
		suffix = startFile[startSuffixIndex:]
		replyobj.status("Collating PDB files\n", blankAfter=0)
		first = int(startFile[prefixIndex:startSuffixIndex])
		if first < 1:
			offset = 1 - first
			first += offset
			replyobj.info("Adjusting frame numbers to start at 1\n")
		else:
			offset = 0
		try:
			last = int(endFile[prefixIndex:endSuffixIndex]) + offset
		except ValueError:
			raise ValueError("Last file name not similar to first"
				" file name\nCan't determine numeric sequence")
		if startFrame is None:
			startFrame = first
		elif startFrame < first:
			replyobj.error("Starting frame (%d) less than first"
				" file's frame (%d); using the latter\n"
				% (startFrame, first))
			startFrame = first
		if endFrame is None:
			endFrame = last
		elif endFrame > last:
			replyobj.error("Ending frame (%d) greater than last"
				" file's frame (%d); using the latter\n"
				% (endFrame, last))
			endFrame = last
		if startFrame > endFrame:
			raise ValueError("Start frame > end frame")
		addMODEL = True
		sf = file(startFile, "r")
		for line in sf:
			if line.startswith("MODEL"):
				addMODEL = False
				break
			if line.strip() == "END":
				raise ValueError("PDB files must not contain"
								" END records")
		sf.close()
		from tempfile import mkstemp
		(handle, trajFile) = mkstemp(suffix=".pdb")
		os.close(handle)
		collation = open(trajFile, "w")
		zeroPad = len(startFile) == len(endFile)
		for f in range(startFrame, endFrame+1):
			if addMODEL:
				print>>collation, "MODEL %8d" % f
			if zeroPad:
				fname = prefix + "%0*d" % (startSuffixIndex
					- prefixIndex, f-offset) + suffix
			else:
				fname = prefix + "%d" % (f-offset) + suffix
			replyobj.status("Collating file %s\n" % fname,
								blankAfter=0)
			try:
				frameFile = open(fname, "r")
			except IOError:
				collation.close()
				os.unlink(trajFile)
				raise
			collation.write(frameFile.read())
			frameFile.close()
			if addMODEL:
				print>>collation, "ENDMDL"
		collation.close()
			
		replyobj.status("Done collating PDB files\n")
	else:
		trajFile = files[0]
	class PdbTraj:
		def __len__(self):
			return len(self.molecule.coordSets)
	ensemble = PdbTraj()
	ensemble.name = "PDB trajectory from %s" % os.path.basename(files[0])
	ensemble.startFrame = startFrame
	ensemble.endFrame = endFrame
	from chimera import PDBio
	pdbio = PDBio()
	pdbio.explodeNMR = False
	replyobj.status("Reading PDB trajectory\n", blankAfter=0)
	# allow for compression...
	from OpenSave import osOpen
	pdbStream = osOpen(trajFile)
	traj, lineNum = pdbio.readPDBstream(pdbStream, trajFile, 0)
	pdbStream.close()
	replyobj.status("Done reading PDB trajectory\n")
	if style == "multiple files":
		os.unlink(trajFile)
		ensemble.name += "..."
	if not pdbio.ok():
		raise ValueError(pdbio.error())
	elif not traj:
		raise ValueError("No structures in the PDB file!")
	else:
		traj = traj[0]
	if len(traj.coordSets) < 2:
		raise ValueError("The PDB file contains only one structure")
			
	ensemble.molecule = traj
	traj.name = os.path.basename(files[0])
	replyobj.status("Creating interface\n", blankAfter=0)
	try:
		callback(ensemble)
	finally:
		replyobj.status("Interface created\n")
def writeMol2(models,
              fileName,
              status=None,
              anchor=None,
              relModel=None,
              hydNamingStyle="sybyl",
              multimodelHandling="individual",
              skip=None,
              resNum=True,
              gaffType=False,
              gaffFailError=None):
    """Write a Mol2 file.

	   'models' are the models to write out into a file named 'fileName'.

	   'status', if not None, is a function that takes a string -- used
	   to report the progress of the write.
	   
	   'anchor' is a selection (i.e. instance of a subclass of
	   chimera.selection.Selection) containing atoms/bonds that should
	   be written out to the @SETS section of the file as the rigid
	   framework for flexible ligand docking.

	   'hydNamingStyle' controls whether hydrogen names should be
	   "Sybyl-like" (value: sybyl) or "PDB-like" (value: pdb)
	   -- e.g.  HG21 vs. 1HG2.

	   'multimodelHandling' controls whether multiple models will be
	   combined into a single @MOLECULE section (value: combined) or
	   each given its own section (value: individual).

	   'skip' is a list of atoms to not output

	   'resNum' controls whether residue sequence numbers are included
	   in the substructure name.  Since Sybyl Mol2 files include them,
	   this defaults to True.

	   If 'gaffType' is True, outout GAFF atom types instead of Sybyl
	   atom types.  'gaffFailError', if specified, is the type of error
	   to throw (e.g. UserError) if there is no gaffType attribute for
	   an atom, otherwise throw the standard AttributeError.
	"""

    # open the given file name for writing
    from OpenSave import osOpen
    f = osOpen(fileName, "w")

    sortFunc = serialSort = lambda a1, a2: cmp(a1.coordIndex, a2.coordIndex)

    if isinstance(models, chimera.Molecule):
        models = [models]
    elif isinstance(models, Selection):
        # create a fictitious jumbo model
        if isinstance(models, ItemizedSelection):
            sel = models
        else:
            sel = ItemizedSelection()
            sel.merge(models)
        sel.addImplied()

        class Jumbo:
            def __init__(self, sel):
                self.atoms = sel.atoms()
                self.residues = sel.residues()
                self.bonds = sel.bonds()
                self.name = "(selection)"

        models = [Jumbo(sel)]
        sortFunc = lambda a1, a2: cmp(a1.molecule.id, a2.molecule.id) \
         or cmp(a1.molecule.subid, a2.molecule.subid) \
         or serialSort(a1, a2)
        multimodelHandling = "individual"

    # transform...
    if relModel is None:
        xform = chimera.Xform.identity()
    else:
        xform = relModel.openState.xform
        xform.invert()

    # need to find amide moieties since Sybyl has an explicit amide type
    if status:
        status("Finding amides\n")
    from ChemGroup import findGroup
    amides = findGroup("amide", models)
    amideNs = dict.fromkeys([amide[2] for amide in amides])
    amideCNs = dict.fromkeys([amide[0] for amide in amides])
    amideCNs.update(amideNs)
    amideOs = dict.fromkeys([amide[1] for amide in amides])

    substructureNames = None
    if multimodelHandling == "combined":
        # create a fictitious jumbo model
        class Jumbo:
            def __init__(self, models):
                self.atoms = []
                self.residues = []
                self.bonds = []
                self.name = models[0].name + " (combined)"
                for m in models:
                    self.atoms.extend(m.atoms)
                    self.residues.extend(m.residues)
                    self.bonds.extend(m.bonds)
                # if combining single-residue models,
                # can be more informative to use model name
                # instead of residue type for substructure
                if len(models) == len(self.residues):
                    rtypes = [r.type for r in self.residues]
                    if len(set(rtypes)) < len(rtypes):
                        mnames = [m.name for m in models]
                        if len(set(mnames)) == len(mnames):
                            self.substructureNames = dict(
                                zip(self.residues, mnames))

        models = [Jumbo(models)]
        if hasattr(models[-1], 'substructureNames'):
            substructureNames = models[-1].substructureNames
            delattr(models[-1], 'substructureNames')
        sortFunc = lambda a1, a2: cmp(a1.molecule.id, a2.molecule.id) \
         or cmp(a1.molecule.subid, a2.molecule.subid) \
         or serialSort(a1, a2)

    # write out models
    for mol in models:
        if hasattr(mol, 'mol2comments'):
            for m2c in mol.mol2comments:
                print >> f, m2c
        if hasattr(mol, 'solventInfo'):
            print >> f, mol.solventInfo

        # molecule section header
        print >> f, "%s" % MOLECULE_HEADER

        # molecule name
        print >> f, "%s" % mol.name

        ATOM_LIST = mol.atoms
        BOND_LIST = mol.bonds
        if skip:
            skip = set(skip)
            ATOM_LIST = [a for a in ATOM_LIST if a not in skip]
            BOND_LIST = [
                b for b in BOND_LIST
                if b.atoms[0] not in skip and b.atoms[1] not in skip
            ]
        RES_LIST = mol.residues

        # Chimera has an unusual internal order for its atoms, so
        # sort them by input order
        if status:
            status("Putting atoms in input order")
        ATOM_LIST.sort(sortFunc)

        # if anchor is not None, then there will be two entries in
        # the @SETS section of the file...
        if anchor:
            sets = 2
        else:
            sets = 0
        # number of entries for various sections...
        print >> f, "%d %d %d 0 %d" % (len(ATOM_LIST), len(BOND_LIST),
                                       len(RES_LIST), sets)

        # type of molecule
        if hasattr(mol, "mol2type"):
            mtype = mol.mol2type
        else:
            mtype = "SMALL"
            from chimera.resCode import nucleic3to1, protein3to1
            for r in mol.residues:
                if r.type in protein3to1:
                    mtype = "PROTEIN"
                    break
                if r.type in nucleic3to1:
                    mtype = "NUCLEIC_ACID"
                    break
        print >> f, mtype

        # indicate type of charge information
        if hasattr(mol, 'chargeModel'):
            print >> f, mol.chargeModel
        else:
            print >> f, "NO_CHARGES"

        if hasattr(mol, 'mol2comment'):
            print >> f, "\n%s" % mol.mol2comment
        else:
            print >> f, "\n"

        if status:
            status("writing atoms\n")
        # atom section header
        print >> f, "%s" % ATOM_HEADER

        # make a dictionary of residue indices so that we can do
        # quick look ups
        resIndices = {}
        for i, r in enumerate(RES_LIST):
            resIndices[r] = i + 1
        for i, atom in enumerate(ATOM_LIST):
            # atom ID, starting from 1
            print >> f, "%7d" % (i + 1),

            # atom name, possibly rearranged if it's a hydrogen
            if hydNamingStyle == "sybyl" \
               and not atom.name[0].isalpha():
                atomName = atom.name[1:] + atom.name[0]
            else:
                atomName = atom.name
            print >> f, "%-8s" % atomName,

            # untransformed coordinate position
            coord = xform.apply(atom.xformCoord())
            print >> f, "%9.4f %9.4f %9.4f" % (coord.x, coord.y, coord.z),

            # atom type
            if gaffType:
                try:
                    atomType = atom.gaffType
                except AttributeError:
                    if not gaffFailError:
                        raise
                    raise gaffFailError(
                        "%s has no Amber/GAFF type assigned.\n"
                        "Use the AddCharge tool to assign Amber/GAFF types." %
                        atom)
            elif hasattr(atom, 'mol2type'):
                atomType = atom.mol2type
            elif atom in amideNs:
                atomType = "N.am"
            elif atom.residue.id.chainId == "water":
                if atom.element.name == "O":
                    atomType = "O.t3p"
                else:
                    atomType = "H.t3p"
            elif atom.element.name == "N" and len(
                [r for r in atom.minimumRings() if r.aromatic()]) > 0:
                atomType = "N.ar"
            elif atom.idatmType == "C2" and len(
                [nb for nb in atom.neighbors if nb.idatmType == "Ng+"]) > 2:
                atomType = "C.cat"
            else:
                try:
                    atomType = chimera2sybyl[atom.idatmType]
                except KeyError:
                    chimera.replyobj.warning("Atom whose"
                                             " IDATM type has no equivalent"
                                             " Sybyl type: %s (type: %s)\n" %
                                             (atom.oslIdent(), atom.idatmType))
                    atomType = str(atom.element)
            print >> f, "%-5s" % atomType,

            # residue-related info
            res = atom.residue

            # residue index
            print >> f, "%5d" % resIndices[res],

            # substructure identifier and charge
            if hasattr(atom, 'charge'):
                charge = atom.charge
            else:
                charge = 0.0
            if substructureNames:
                rname = substructureNames[res]
            elif resNum:
                rname = "%3s%-5d" % (res.type, res.id.position)
            else:
                rname = "%3s" % res.type
            print >> f, "%s %9.4f" % (rname, charge)

        if status:
            status("writing bonds\n")
        # bond section header
        print >> f, "%s" % BOND_HEADER

        # make an atom-index dictionary to speed lookups
        atomIndices = {}
        for i, a in enumerate(ATOM_LIST):
            atomIndices[a] = i + 1
        for i, bond in enumerate(BOND_LIST):
            a1, a2 = bond.atoms

            # ID
            print >> f, "%6d" % (i + 1),

            # atom IDs
            print >> f, "%4d %4d" % (atomIndices[a1], atomIndices[a2]),

            # bond order; give it our best shot...
            amideA1 = a1 in amideCNs
            amideA2 = a2 in amideCNs
            if amideA1 and amideA2:
                print >> f, "am"
                continue
            if amideA1 or amideA2:
                if a1 in amideOs or a2 in amideOs:
                    print >> f, "2"
                else:
                    print >> f, "1"
                continue

            aromatic = False
            for ring in bond.minimumRings():
                if ring.aromatic():
                    aromatic = True
                    break
            if aromatic:
                print >> f, "ar"
                continue

            try:
                geom1 = typeInfo[a1.idatmType].geometry
            except KeyError:
                print >> f, "1"
                continue
            try:
                geom2 = typeInfo[a2.idatmType].geometry
            except KeyError:
                print >> f, "1"
                continue
            if geom1 not in [2, 3] or geom2 not in [2, 3]:
                print >> f, "1"
                continue
            # if either endpoint atom is in an aromatic ring and
            # the bond isn't, it's a single bond...
            for endp in [a1, a2]:
                aromatic = False
                for ring in endp.minimumRings():
                    if ring.aromatic():
                        aromatic = True
                        break
                if aromatic:
                    break
            else:
                # neither endpoint in aromatic ring
                print >> f, "2"
                continue
            print >> f, "1"

        if status:
            status("writing residues")
        # residue section header
        print >> f, "%s" % SUBSTR_HEADER

        for i, res in enumerate(RES_LIST):
            # residue id field
            print >> f, "%6d" % (i + 1),

            # residue name field
            if substructureNames:
                rname = substructureNames[res]
            elif resNum:
                rname = "%3s%-4d" % (res.type, res.id.position)
            else:
                rname = "%3s" % res.type
            print >> f, rname,

            # ID of the root atom of the residue
            from chimera.misc import principalAtom
            chainAtom = principalAtom(res)
            if chainAtom is None:
                if hasattr(res, 'atomsMap'):
                    chainAtom = res.atoms[0]
                else:
                    chainAtom = res.atoms.values()[0][0]
            print >> f, "%5d" % atomIndices[chainAtom],

            print >> f, "RESIDUE           4",

            # Sybyl seems to use chain 'A' when chain ID is blank,
            # so run with that
            chainID = res.id.chainId
            if len(chainID.strip()) != 1:
                chainID = 'A'
            print >> f, "%s     %3s" % (chainID, res.type),

            # number of out-of-substructure bonds
            crossResBonds = 0
            if hasattr(res, "atomsMap"):
                atoms = res.atoms
                for a in atoms:
                    for oa in a.bondsMap.keys():
                        if oa.residue != res:
                            crossResBonds += 1
            else:
                atoms = [a for aList in res.atoms.values() for a in aList]
                for a in atoms:
                    for oa in a.bonds.keys():
                        if oa.residue != res:
                            crossResBonds += 1
            print >> f, "%5d" % crossResBonds,
            # print "ROOT" if first or only residue of a chain
            if a.molecule.rootForAtom(a, True).atom.residue == res:
                print >> f, "ROOT"
            else:
                print >> f

        # write flexible ligand docking info
        if anchor:
            if status:
                status("writing anchor info")
            print >> f, "%s" % SET_HEADER
            atomIndices = {}
            for i, a in enumerate(ATOM_LIST):
                atomIndices[a] = i + 1
            bondIndices = {}
            for i, b in enumerate(BOND_LIST):
                bondIndices[b] = i + 1
            print >> f, "ANCHOR          STATIC     ATOMS    <user>   **** Anchor Atom Set"
            atoms = anchor.atoms()
            print >> f, len(atoms),
            for a in atoms:
                if a in atomIndices:
                    print >> f, atomIndices[a],
            print >> f

            print >> f, "RIGID           STATIC     BONDS    <user>   **** Rigid Bond Set"
            bonds = anchor.bonds()
            print >> f, len(bonds),
            for b in bonds:
                if b in bondIndices:
                    print >> f, bondIndices[b],
            print >> f

    f.close()
Example #42
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
def parse(fileName):
	IN_HEADER = 0
	START_ATTRS = 1
	IN_ATTRS = 2
	IN_FEATURES = 3
	IN_SEQ = 4

	state = IN_HEADER

	from OpenSave import osOpen
	f = osOpen(fileName, "r")
	sequences = []
	lineNum = 0
	hasOffset = 0
	longest = None
	fileAttrs = {}
	for line in f:
		line = line.rstrip() # remove trailing whitespace/newline
		lineNum += 1
		if lineNum == 1:
			if line.startswith("!!RICH_SEQUENCE"):
				continue
			raise WrongFileTypeError()
		if state == IN_HEADER:
			if line.strip() == "..":
				state = START_ATTRS
				continue
			if "comments" in fileAttrs:
				fileAttrs["comments"] += "\n" + line
			else:
				fileAttrs["comments"] = line
			continue
		if not line.strip():
			continue
		if state == START_ATTRS:
			if line.strip() == "{":
				state = IN_ATTRS
				curAttr = None
				attrs = {}
			elif line:
				raise FormatSyntaxError("Unexpected text before"
						" start of sequence on line %d"
						% lineNum)
			continue
		if state == IN_ATTRS or state == IN_FEATURES:
			if line.strip() == "sequence" and line[0] == "s":
				if "RSF name" not in attrs:
					raise FormatSyntaxError("sequence on "
						"line %d has no name" % lineNum)
				state = IN_SEQ
				seq = Sequence(makeReadable(attrs["RSF name"]))
				del attrs["RSF name"]
				seq.attrs = attrs
				if "RSF descrip" in attrs:
					attrs["description"] = attrs[
								"RSF descrip"]
					del attrs["RSF descrip"]
				sequences.append(seq)
				if "RSF offset" in attrs:
					seq.extend("." * int(
							attrs["RSF offset"]))
					hasOffset = 1
					del attrs["RSF offset"]
				continue
			if line.startswith("feature"):
				if state == IN_ATTRS:
					attrs["RSF features"] = [[line[8:]]]
				else:
					attrs["RSF features"].append([line[8:]])
				state = IN_FEATURES
				continue

		if state == IN_ATTRS:
			if line[0].isspace():
				# continuation
				if not curAttr:
					raise FormatSyntaxError("Bogus "
							"indentation at line %d"
							% lineNum)
				if attrs[curAttr]:
					attrs[curAttr] += "\n" + line
				else:
					attrs[curAttr] = line
				continue
			if " " in line.strip():
				curAttr, val = line.split(None, 1)
				curAttr.replace("_", " ")
				curAttr = "RSF " + curAttr
				attrs[curAttr] = val.strip()
			else:
				curAttr = "RSF " + line.strip().replace("_", " ")
				attrs[curAttr] = ""
			continue

		if state == IN_FEATURES:
			attrs["RSF features"][-1].append(line)
			continue
		if line.strip() == "}":
			state = START_ATTRS
			if not longest:
				longest = len(seq)
			else:
				if len(seq) < longest:
					seq.extend("." * (longest - len(seq)))
				elif len(seq) > longest:
					longest = len(seq)
					for s in sequences[:-1]:
						s.extend("." *
							(longest - len(s)))
			continue
		seq.extend(line.strip())
		if not seq[0].isalpha():
			hasOffset = 1
			
	f.close()
	if state == IN_HEADER:
		raise FormatSyntaxError(
				"No end to header (i.e. '..' line) found")
	if state == IN_ATTRS or state == IN_FEATURES:
		if "RSF name" in attrs:
			raise FormatSyntaxError(
					"No sequence data found for sequence %s"
					% attrs["RSF name"])
		raise FormatSyntaxError("Sequence without sequence data")
	
	if state == IN_SEQ:
		raise FormatSyntaxError("No terminating brace for sequence %s"
							% attrs["RSF name"])
			
	if not sequences:
		raise FormatSyntaxError("No sequences found")
	if not hasOffset:
		from chimera import replyobj
		replyobj.warning("No offset fields in RSF file;"
						" assuming zero offset\n")
	return sequences, fileAttrs, {}
Example #44
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]
Example #45
0
def parse(fileName):
    from OpenSave import osOpen
    f = osOpen(fileName, "r")
    doing = None
    sequences = []
    headerOK = False
    lineNum = 0
    alignStartIndex = None
    for line in f:
        if doing == 'alignments':
            # don't strip() alignment section since it has significant
            # leading spaces
            line = line.rstrip()
        else:
            line = line.strip()
        lineNum += 1
        if not headerOK:
            if line.lower().startswith('hssp'):
                headerOK = True
                continue
            raise WrongFileTypeError("No initial HSSP header line")
        if line.startswith('##'):
            if doing == 'proteins' and not sequences:
                raise FormatSyntaxError("No entries in PROTEINS section")
            try:
                doing = line.split()[1].lower()
            except IndexError:
                doing = None
            if doing == 'alignments':
                try:
                    hashes, alignments, begin, dash, end = line.strip().split()
                    begin = int(begin)
                    end = int(end)
                except ValueError:
                    raise FormatSyntaxError(
                        "ALIGNMENTS line (line #%d) not of "
                        "the form: ## ALIGNMENTS (number) - (number)" %
                        lineNum)
            continue
        if doing == 'proteins':
            if not line[0].isdigit():
                continue
            try:
                seqName = line.split()[2]
            except IndexError:
                raise WrongFormatError(
                    "Line %d in PROTEINS section does not "
                    "start with [integer] : [sequence name]" % lineNum)
            sequences.append(Sequence(makeReadable(seqName)))
        elif doing == 'alignments':
            if line.lstrip().lower().startswith('seqno'):
                try:
                    alignStartIndex = line.index('.')
                except:
                    raise FormatSyntaxError(
                        "No indication of alignment "
                        " starting column ('.' character) in SeqNo line "
                        " in ALIGNMENTS section")
                continue
            if alignStartIndex == None:
                raise FormatSyntaxError("No initial SeqNo line in "
                                        "ALIGNMENTS section")
            block = line[alignStartIndex:]
            if not block:
                raise FormatSyntaxError("No alignment block given on line %d" %
                                        lineNum)
            blockLen = end - begin + 1
            if len(block) > blockLen:
                raise FormatSyntaxError(
                    "Too many characters (%d, only %d "
                    " sequences) in alignment block given on line %d" %
                    (len(block), blockLen, lineNum))
            block = block + ' ' * (blockLen - len(block))
            for seq, c in zip(sequences[begin - 1:end], block):
                seq.append(c)
    f.close()
    return sequences, {}, {}
Example #46
0
def clustalInfo(fileName=None):
	if fileName is None:
		return _clustalCategories, _clustalColorings

	from prefs import RC_HYDROPHOBICITY
	if fileName == RC_HYDROPHOBICITY:
		import os.path
		fileName = os.path.join(os.path.dirname(__file__),
							"kdHydrophob.par")
	colorInfo = {}
	for colorName in [ "RED", "BLUE", "GREEN", "CYAN",
					"PINK", "MAGENTA", "YELLOW", "ORANGE"]:
		colorInfo[colorName] = eval("_clustal%s"
						% colorName.capitalize())
	from OpenSave import osOpen
	from chimera import UserError
	f = osOpen(fileName)
	section = None
	colorSeen = False
	categories = []
	colorings = {}
	for line in f:
		line = line.strip()
		if line.startswith("@"):
			section = line[1:].lower()
			continue
		if not line:
			continue
		if section == "rgbindex":
			try:
				name, sr, sg, sb = line.split()
			except ValueError:
				raise UserError("Line in @rgbindex section of"
					" %s is not color name followed by"
					" red, green and blue values: '%s'"
					% (fileName, line))
			try:
				r, g, b = [float(x) for x in [sr, sg, sb]]
			except ValueError:
				raise UserError("Line in @rgbindex section of"
					" %s has non-floating-point"
					" red, green or blue value: '%s'"
					% (fileName, line))
			if r>1 or g>1 or b>1 or r<0 or g<0 or b<0:
				raise UserError("Line in @rgbindex section of"
					" %s has red, green or blue value"
					" not in the range 0-1: '%s'"
					% (fileName, line))
			colorInfo[name] = rgba2tk((r, g, b))
		elif section == "consensus":
			try:
				symbol, eq, percent, composition = line.split()
			except ValueError:
				raise UserError("Line in @consensus section of"
					" %s is not of the form 'symbol = "
					" percentage%% res-list: '%s'"
					% (fileName, line))
			if eq != '=':
				raise UserError("Line in @consensus section of"
					" %s doesn't have '=' as second"
					" component: '%s'" % (fileName, line))
			if percent[-1] != '%':
				raise UserError("Line in @consensus section of"
					" %s doesn't have '%' as last character"
					" of third component: '%s'"
					% (fileName, line))
			try:
				percentage = float(percent[:-1])
			except ValueError:
				raise UserError("Line in @consensus section of"
					" %s doesn't have a number before the"
					" '%' of third component: '%s'"
					% (fileName, line))
			if percentage < 0 or percentage > 100:
				raise UserError("Line in @consensus section of"
					" %s has a percentage not in the range"
					" 0-100: '%s'" % (fileName, line))
			composition = composition.replace(":", "")
			categories.append((composition, percentage/100.0,
								symbol))
		elif section == "color":
			colorSeen = True
			fields = line.split()
			if len(fields) not in [3,5]:
				raise UserError("Line in @color section of"
					" %s not of the form AA = color"
					" [if consensus-list]: '%s'"
					% (fileName, line))
			aa, eq, color = fields[:3]
			if len(aa) > 1 or not aa.islower():
				raise UserError("Line in @color section of"
					" %s uses amino-acid code that is not"
					" a single lowercase character: '%s'"
					% (fileName, line))
			if eq != '=':
				raise UserError("Line in @color section of"
					" %s doesn't have '=' as second"
					" component: '%s'" % (fileName, line))
			if color not in colorInfo:
				raise UserError("Line in @color section of"
					" %s uses an unknown color:"
					" '%s'" % (fileName, line))
			if len(fields) == 3:
				colorings.setdefault(aa.upper(), []).append(
						(colorInfo[color], None))
				continue
			if fields[3] != 'if':
				raise UserError("Line in @color section of"
					" %s doesn't have 'if' as fourth"
					" component: '%s'" % (fileName, line))
			colorings.setdefault(aa.upper(), []).append(
				(colorInfo[color], fields[-1].replace(":", "")))
	f.close()
	if not colorSeen:
		raise UserError("'%s' has missing or empty @color section"
								% fileName)
	return categories, colorings
	def loadScfFile(self, path, colorStructures=True):
		if path is None:
			if not self._scfDialog:
				self._scfDialog = ScfDialog(
						self.seqCanvas.mav.prefs[
						SCF_COLOR_STRUCTURES],
						command=self.loadScfCB)
			self._scfDialog.enter()
			return

		seqs = self.seqCanvas.seqs
		from OpenSave import osOpen
		scfFile = osOpen(path)
		lineNum = 0
		regionInfo = {}
		for line in scfFile.readlines():
			lineNum += 1
			line.strip()
			if not line or line[0] == '#' \
			or line.startswith('//'):
				continue
			for commentIntro in ['//', '#']:
				commentPos = line.find(commentIntro)
				if commentPos >= 0:
					break
			if commentPos >= 0:
				comment = line[commentPos
					+ len(commentIntro):].strip()
				line = line[:commentPos].strip()
			else:
				comment = None

			try:
				pos1, pos2, seq1, seq2, r, g, b = map(
						int, line.split())
				if seq1 == -1:
					# internal to jevtrace/webmol
					continue
				if seq1 == 0:
					seq2 = -1
				else:
					seq1 -= 1
					seq2 -= 1
			except:
				try:
					pos, seq, r, g, b = map(int,
							line.split())
					pos1 = pos2 = pos
				except:
					replyobj.error("Bad format for line %d of %s [not 5 or 7 integers]\n" % (lineNum, path))
					scfFile.close()
					return
				if seq == 0:
					seq1 = 0
					seq2 = -1
				else:
					seq1 = seq2 = seq - 1
			key = ((r, g, b), comment)
			if key in regionInfo:
				regionInfo[key].append((seqs[seq1],
					seqs[seq2], pos1, pos2))
			else:
				regionInfo[key] = [(seqs[seq1],
					seqs[seq2], pos1, pos2)]
		scfFile.close()

		if not regionInfo:
			replyobj.error("No annotations found in %s\n"
				% path)
			return
		for rgbComment, blocks in regionInfo.items():
			rgb, comment = rgbComment
			rgb = map(lambda v: v/255.0, rgb)
			region = self.newRegion(namePrefix="Seqsel: ",
				blocks=blocks, name=comment, fill=rgb,
				coverGaps=True)
			if not colorStructures:
				continue
			c = chimera.MaterialColor(*rgb)
			for res in self.regionResidues(region):
				res.ribbonColor = c
				for a in res.atoms:
					a.color = c
		self.seqCanvas.mav.status("%d scf regions created\n"
						% len(regionInfo))
def addAttributes(attrFile, models=None, log=False, raiseAttrDialog=True):
	"""add/set attributes from a file

	   'attrFile' indicates a file path or an opened file object.  The
	   file contains control lines and data lines.  Control and data lines
	   may be freely interspersed.  The data lines are of the form:

	   	<tab>selector<tab>attribute value

	   The selector is an atom specification (as per the Atom Specification
	   section of the User's Guide).  The attribute value is a boolean,
	   integer, float, or string.  If it is necessary to specify a string
	   attribute that could be interpreted as one of the other types,
	   embed the value in double quotes (it will then be evaluated as a
	   Python string, including backslash interpretation).

	   The control lines are of the form:

	   	name: value
	   
	   The possible name/value pairs are:

	   	Name         Value
		----         -----
		attribute    name of the attribute to assign to
		match mode   expected matches per selector:
		                "1 to 1":  exactly one match per selector
				"non-zero":  at least one match per selector
				"any":  no constraint
			     selectors not conforming to the match mode will
			     generate an error
		recipient    where to put attribute (atoms/residues/molecules)
	   
	   The only mandatory control line is 'attribute', which must precede
	   any data lines.  The default match mode is 1 to 1, and the default
	   recipient is atoms.

	   Empty lines are ignored and lines beginning with the '#' character
	   are considered comments and ignored.

	   'log' controls whether information about what each selector matched
	   is sent to the reply log.

	   'models' restricts any selector matching to the given models.  If
	   'models' is None, then no restriction occurs.

	   This function return a list of recipient/attribute tuples that
	   actually were set in at least one object.  If an error occurred,
	   None is returned instead.
	"""

	from OpenSave import osOpen
	try:
		if isinstance(attrFile, basestring):
			attrFile = osOpen(attrFile)
			try:
				return _addAttr(attrFile, models, log,
								raiseAttrDialog)
			finally:
				attrFile.close()
		else:
			return _addAttr(attrFile, models, log, raiseAttrDialog)
	except SyntaxError, v:
		replyobj.error(str(v) + "\n")
		return None