예제 #1
0
def transpSurf(amount):
	if amount != -1:
		aopacity = opacity = min(1.0, 1 - amount)
	else:
		opacity = 1
		aopacity = -1
	atoms = selAtoms()
	import Midas
	surfatoms = Midas.atomMSMSModels(atoms)
	for s,atoms in surfatoms.items():
		adjustMSMSTransparency(s, atoms, opacity, aopacity)

	splist = selectedSurfacePieces(implied = True)
	from chimera import MSMSModel
	for p in splist:
		s = p.model
		if isinstance(s, MSMSModel) and s.molecule:
			adjustMSMSTransparency(s, s.atoms, opacity, aopacity)
		else:
			adjustSurfacePieceTransparency(p, opacity)

	if (len(atoms) > 0 and not selection.currentEmpty()
	    and len(surfatoms) == 0 and len(splist) == 0):
		from replyobj import warning
		warning('No surfaces shown for selected atoms.\n')
예제 #2
0
def transpSurf(amount):
    if amount != -1:
        aopacity = opacity = min(1.0, 1 - amount)
    else:
        opacity = 1
        aopacity = -1
    atoms = selAtoms()
    import Midas
    surfatoms = Midas.atomMSMSModels(atoms)
    for s, atoms in surfatoms.items():
        adjustMSMSTransparency(s, atoms, opacity, aopacity)

    splist = selectedSurfacePieces(implied=True)
    from chimera import MSMSModel
    for p in splist:
        s = p.model
        if isinstance(s, MSMSModel) and s.molecule:
            adjustMSMSTransparency(s, s.atoms, opacity, aopacity)
        else:
            adjustSurfacePieceTransparency(p, opacity)

    if (len(atoms) > 0 and not selection.currentEmpty() and len(surfatoms) == 0
            and len(splist) == 0):
        from replyobj import warning
        warning('No surfaces shown for selected atoms.\n')
예제 #3
0
def reregister(name, function):
    """Reregister dialog creation/display function
	
	Same function variations allowed as in register.
	"""
    global _allDialogs
    try:
        dialog = _allDialogs[name]
        _allDialogs[name] = function
    except KeyError:
        replyobj.warning("error dialog %s missing\n" % name)
예제 #4
0
def contextCB(app):
    """Display help for selected widget.
	
	contextCB(app) => None
	"""
    rootX, rootY = chimera.viewer.trackingXY("help")
    if rootX != -1:
        # find widget that was under cursor
        widget = app.winfo_containing(rootX, rootY)
        if widget:
            widget.event_generate('<<Help>>', rootx=rootX, rooty=rootY)
            return
    replyobj.warning('pick part of application to get context help\n')
예제 #5
0
def register(name, function, replace=0):
    """Register dialog creation/display function
	
	The function is called with no arguments.  The function
	can also be a class, or an instance of a class.  If it
	is an instance, then the enter method is called.
	"""
    global _allDialogs
    if not replace and _allDialogs.has_key(name):
        replyobj.warning("error dialog %s already registered\n" % name)
        return

    _allDialogs[name] = function
예제 #6
0
def contextCB(app):
	"""Display help for selected widget.
	
	contextCB(app) => None
	"""
	rootX, rootY = chimera.viewer.trackingXY("help")
	if rootX != -1:
		# find widget that was under cursor
		widget = app.winfo_containing(rootX, rootY)
		if widget:
			widget.event_generate('<<Help>>', rootx=rootX,
								rooty=rootY)
			return
	replyobj.warning('pick part of application to get context help\n')
예제 #7
0
def display(name, wait=False):
    """Display the dialog with the given name.
	
	The registered dialog display function is called.
	If wait is true, then this function doesn't return
	until the dialog is displayed.

	The dialog instance is returned if available.
	"""
    if not _allDialogs.has_key(name):
        replyobj.warning("no known dialog named: %s\n" % name)
        return None
    dialog = find(name, create=1)
    if not callable(dialog) and hasattr(dialog, 'enter'):
        dialog.enter()
    if wait:
        import _tkinter
        import chimera.tkgui
        chimera.tkgui.update_windows()
    return dialog
def getSequences(molecule, asDict=False):
	"""return all non-trivial sequences in a molecule

	   This function is also available as molecule.sequences(...)

	   returns a list of sequences for the given molecule, one sequence per
	   multi-residue chain.  The sequence name is "Chain X" where X is
	   the chain ID, or "Principal chain" if there is no chain ID.

	   The 'residues' attribute of each sequence is a list of the
	   residues for that sequence, and the attribute 'resmap' is a
	   dictionary that maps residue to sequence position (zero-based).
	   The 'residues' attribute will self-delete if the corresponding
	   model is closed.

	   If 'asDict' is true, return a dictionary of Sequences keyed on
	   chain ID (can throw AssertionError if multiple chains have same ID),
	   otherwise return a list.
	"""
	from chimera import bondsBetween, openModels, triggers
	from copy import copy

	def connected(res1, res2):
		if res1.id.chainId != ' ' \
		and res1.id.chainId == res2.id.chainId \
		and not res1.isHet and not res2.isHet:
			return True
		return bondsBetween(res1, res2, onlyOne=True)

	if hasattr(molecule, '_SequenceSequences'):
		seqList, seqDict, trigIDs = molecule._SequenceSequences
		if asDict:
			if seqDict is not None:
				return copy(seqDict)
		else:
			return copy(seqList)

	chain = None
	prevRes = None
	seqs = []
	# don't start a sequence until we've seen two residues in the chain
	for res in molecule.residues:
		# if a residue has only one heavy atom, and that is connected
		# to only one other heavy atom, then don't put the residue
		# in the sequence
		# 
		# if heavy is connected to no other heavy atom (presumably
		# metal or ion), end the chain
		atomLists = res.atomsMap.values()
		# take only one atom in each list, to avoid counting 
		# alternate locations as multiple atoms
		atoms = map(lambda l: l[0], atomLists)
		heavys = filter(lambda a: a.element.number > 1, atoms)
		chainBreak = prevRes == None
		if len(heavys) == 0:
			continue
		# heavys more reliably connected than hydrogens
		if prevRes and not connected(prevRes, res):
			didMod = 0
			if seq:
				for sr in seq.residues:
					if connected(sr, res):
						didMod = 1
			if didMod:
				continue
			chainBreak = 1
		elif prevRes and prevRes.id == res.id and len(heavys) == 1:
			continue
		elif chain is not None:
			# HET residues in named chains get the chain name,
			# but in blank chains they get 'het' -- allow for this
			truePrevID = chain
			trueResID = res.id.chainId
			if truePrevID != trueResID:
				if truePrevID in (" ", "het"):
					prevID = " "
				else:
					prevID = truePrevID
				if trueResID in (" ", "het"):
					resID = " "
				else:
					resID = trueResID
				if resID != prevID:
					chainBreak = 1

		if chainBreak:
			# if chain ID changes in middle of connected chain
			# need to remember new chain ID...
			chain = res.id.chainId
			startRes = res
			prevRes = res
			seq = None
			continue # to avoid starting single-residues chains

		if not seq:
			if not chain or chain == " ":
				name = PRINCIPAL
				chain = " "
			else:
				name = CHAIN_FMT % chain
			seq = StructureSequence(startRes.molecule, name)
			seq.chain = chain
			seqs.append(seq)
			seq.append(startRes)
		seq.append(res)
		prevRes = res
			
	sd = {}
	for seq in seqs[:]:
		# set 'fromSeqres' in this loop so that all sequences have it
		seq.fromSeqres = None
		if seq.chain in sd:
			# a sequence of all 'X' residues or all het loses
			if str(seq).replace('X', ' ').isspace() \
			or len([r for r in seq.residues if not r.isHet]) == 0:
				seqs.remove(seq)
				continue
			elif str(sd[seq.chain]).replace('X', ' ').isspace() \
			or len([r for r in sd[seq.chain].residues
							if not r.isHet]) == 0:
				seqs.remove(sd[seq.chain])
				sd[seq.chain] = seq
				continue
			if asDict:
				raise AssertionError("Multiple chains with"
					" same ID: '%s'" % seq.chain)
			sd = None
			break
		sd[seq.chain] = seq

	# use full sequence if available...
	seqresSeqs = seqresSequences(molecule, asDict=True)
	for chain, seq in sd.items():
		try:
			srSeq = seqresSeqs[chain]
		except (KeyError, TypeError):
			continue
		seq.fromSeqres = True
		if len(srSeq) == len(seq):
			# no adjustment needed
			continue
		if len(srSeq) < len(seq):
			seq.fromSeqres = False
			import replyobj
			replyobj.warning("SEQRES record for chain %s of %s is incomplete.\n"
				"Ignoring record as basis for sequence." % (chain, molecule))
			continue

		from MultAlignViewer.structAssoc import estimateAssocParams, tryAssoc
		estLen, segments, gaps = estimateAssocParams(seq)
		# if a jump in numbering is in an unresolved part of the
		# structure, the estimated length can be too long...
		estLen = min(estLen, len(srSeq))
		try:
			# since gapping a structure sequence is considered an
			# "error", need to allow a lot more errors than normal...
			matchMap, numErrors = tryAssoc(srSeq, seq, segments, gaps, estLen,
												maxErrors=int(len(seq)/2))
		except ValueError:
			seq.fromSeqres = False
			continue

		for i in range(len(srSeq)):
			if i in matchMap:
				del matchMap[i]
			else:
				seq.residues.insert(i, None)
		seq.resMap = matchMap
		seq[:] = srSeq[:]

	# try to avoid identical names
	baseNames = {}
	for seq in seqs:
		baseNames.setdefault(seq.name, []).append(seq)
	for baseName, sameNamedSeqs in baseNames.items():
		if len(sameNamedSeqs) > 1:
			for i, seq in enumerate(sameNamedSeqs):
				seq.name += " [%d]" % (i+1)

	if hasattr(molecule, '_SequenceSequences'):
		# deregister from previous sequence's triggers...
		# (don't destroy the old sequences, may be in use elsewhere)
		seqList, seqDict, trigIDs = molecule._SequenceSequences
		for i, seq in enumerate(seqList):
			seq.triggers.deleteHandler(seq.TRIG_DELETE, trigIDs[i])
	else:
		# invalidate the sequences cache if residues added/deleted
		molecule.__cacheHandlerID = triggers.addHandler('Residue',
					_invalidateCacheCB, molecule)
	# register for current sequence's triggers
	trigIDs = []
	for seq in seqs:
		trigIDs.append(
			seq.triggers.addHandler(seq.TRIG_DELETE, _delSeq, None))
	molecule._SequenceSequences = (seqs, sd, trigIDs)
	if asDict:
		return copy(sd)
	return copy(seqs)
예제 #9
0
def display(widgetOrURL, package=chimera, newWindow=False):
    """Display given html help file.

	display(widgetOrURL, package=chimera, newWindow=False) => None
	
	The url may be either a string, or a "widget" that has been
	registered.  In the latter case it is mapped according to
	how it was registered.
	"""
    try:
        # compensate for Pmw megawidgets not being Tk widgets
        widgetOrURL = widgetOrURL.component('hull')
    except:
        pass
    if isinstance(widgetOrURL, basestring):
        url = widgetOrURL
    elif hasattr(widgetOrURL, 'winfo_parent'):
        # show help associated with widget or parent widget
        while widgetOrURL:
            if _helpMap.has_key(widgetOrURL):
                url, package = _helpMap[widgetOrURL]
                break
            parent = widgetOrURL.winfo_parent()
            if not isinstance(parent, str):
                widgetOrURL = parent
            elif parent == "":
                widgetOrURL = None
            else:
                widgetOrURL = widgetOrURL._nametowidget(parent)
        if not widgetOrURL:
            replyobj.warning('internal error -- no help found for widget\n')
            return
    elif isinstance(widgetOrURL, tuple):
        url, package = widgetOrURL
        if isinstance(package, basestring):
            package = __import__(package)
    else:
        replyobj.warning("internal error -- no help avaiable for: %s\n" %
                         widgetOrURL)
        return
    protocol, location, path, parameters, query, fragment = \
     urlparse.urlparse(url, allow_fragments=True)
    path = urllib.quote(path)
    parameters = urllib.quote(parameters)
    query = urllib.quote(query)
    fragment = urllib.quote(fragment)
    if path and path[0] != '/':
        file = os.path.join(package.__path__[0], "helpdir", path)
        if os.path.exists(file):
            protocol = 'file'
            if sys.platform == 'darwin':
                #
                # Setting location to localhost is needed on
                # Mac OS X with Internet Explorer because
                # urlunparse() produces urls like
                # file:/index.blah instead of
                # file:///index.html or
                # file://localhost/index.html
                # required by the browser.
                #
                location = 'localhost'
            path = urllib.pathname2url(file)
            if path[0:3] == '///':
                path = path[2:]
            url = urlparse.urlunparse(
                (protocol, location, path, parameters, query, fragment))
        else:
            # Fetch development version of docs -- a released
            # version would have the help files included.
            protocol = 'http'
            url = urlparse.urljoin('http://www.cgl.ucsf.edu/chimera/docs/',
                                   url)
    replyobj.status("See web browser for %s\n" % url, blankAfter=10)
    import webbrowser
    try:
        webbrowser.open(url, newWindow)
    except webbrowser.Error:
        from chimera import NonChimeraError
        raise NonChimeraError(
            "Could not locate a web browser to use.\n"
            "\nTry setting your BROWSER environment variable to\n"
            "the command-line name of the web browser you want\n"
            "to use and restart Chimera.")
    except OSError, e:
        from chimera import NonChimeraError
        import errno
        if e.errno == errno.ENOENT:
            if protocol == 'file' \
            and not os.path.exists(urllib.url2pathname(path)):
                raise
            # Bug starting webbrowser (firefox, bug 1512),
            # Windows usually opens it eventually
            raise NonChimeraError(
                "Error or delay starting default web browser.\n"
                "\n"
                "Wait a little and if the default web browser\n"
                "doesn't start up, start it by hand, and try\n"
                "again.")
        raise NonChimeraError("Unable to start web browswer.\n"
                              "Open <%s> in your web browswer.\n"
                              "(%s)" % (path, e))
def saveImage(filename=None, width=None, height=None, format=None,
	      units="pixels", description=None, supersample=None,
	      master=None, printMode=None, raytrace=False,
	      raytracePreview=None, raytraceWait=None,
	      raytraceKeepInput=None,
	      hideDialogs=True, statusMessages=True, raiseWindow=True,
	      task=None):
	if chimera.nogui and chimera.opengl_platform() != 'OSMESA':
		raise chimera.UserError, "Need graphics to save images (or use headless Linux version)"
	if statusMessages:
		from replyobj import status
	else:
		def status(*args, **kw):
			pass
	if printMode is None:
		printMode = chimera.viewer.camera.mode()
	horizPixels, vertPixels, supersample = \
			imageArgs(units, width, height, supersample)
	savedSD = None	# saved screen distance
	if units != 'pixels':
		adjustFOV = preferences.get(IMAGE_SETUP, ADJUST_FOV)
		if adjustFOV == 1 or (adjustFOV == ONLY_STEREO_CAMERAS
						and printMode != 'mono'):
			# if image is twice as wide as screen,
			# screenDistance is half as much
			savedSD = chimera.viewer.camera.screenDistance
			adjust = convert[units] / convert['millimeters']
			image_width = width * adjust
			adjust = chimera.viewer.camera.windowWidth / image_width
			chimera.viewer.camera.screenDistance *= adjust
	if raytrace:
		if not checkPovrayLicense():
			return
		# TODO: make default an argument or preference
		if raytraceWait is None:
			raytraceWait = preferences.get(POVRAY_SETUP, WAIT_POVRAY)
		if raytraceKeepInput is None:
			raytraceKeepInput = preferences.get(POVRAY_SETUP, KEEP_INPUT)
		if raytracePreview is None:
			raytracePreview = preferences.get(POVRAY_SETUP, SHOW_PREVIEW)
		quality = DEFAULT_JPEG_QUALITY
		format = 'PNG'
		if not chimera.nogui and not filename:
			if not master:
				master = tkgui.app
			chooseDialog = _ChooseFileDialog(filterSet='povray',
					format=format)
			result = chooseDialog.run(master)
			if result is None:
				status("Image save cancelled.")
				return
			filename, format = result[0]
			quality = chooseDialog.quality.get()
		if not filename:
			replyobj.error("Need filename for POV-Ray output")
			return
		if filename.endswith('.png') or filename.endswith('.jpg'):
			povfilename = filename[:-4] + '.pov'
			inifilename = filename[:-4] + '.ini'
		else:
			povfilename = filename + '.pov'
			inifilename = filename + '.ini'
		if task is None:
			from chimera.tasks import Task
			task = Task("raytrace image", None)
		task.updateStatus("Generating POV-Ray data file")
		import exports
		exports.doExportCommand('POV-Ray', povfilename)
		task.updateStatus("Generating POV-Ray parameter file")
		if savedSD is not None:
			chimera.viewer.camera.screenDistance = savedSD
		import SubprocessMonitor as SM
		cmd = [
			preferences.get(POVRAY_SETUP, POVRAY_EXE),
			inifilename,
			"+I%s" % povfilename,
			"+O%s" % filename,
			"+V"		# need verbose to monitor progress
		]
		inifile = open(inifilename, 'w')
		print >> inifile, (
			"Width=%d\n"
			"Height=%d\n"
			# add font path, CHIMERA/share/fonts
			"Library_Path=\"%s\"\n"
			"Bounding=On\n"
			"Bounding_Threshold=1\n"
			"Split_Unions=On\n"
			"Remove_Bounds=On\n"
			"Quality=%d"
		) % (
			horizPixels,
			vertPixels,
			os.path.join(os.environ['CHIMERA'], 'share', 'fonts'),
			preferences.get(POVRAY_SETUP, POV_QUALITY)
		)
		if not preferences.get(POVRAY_SETUP, ANTIALIAS):
			print >> inifile, "Antialias=Off"
		else:
			print >> inifile, (
				"Antialias=On\n"
				"Antialias_Threshold=%f\n"
				"Antialias_Depth=%d\n"
				"Sampling_Method=%d"
			) % (
				preferences.get(POVRAY_SETUP, ANTIALIAS_THRESHOLD),
				preferences.get(POVRAY_SETUP, ANTIALIAS_DEPTH),
				preferences.get(POVRAY_SETUP, ANTIALIAS_METHOD)
			)
		if not preferences.get(POVRAY_SETUP, JITTER):
			print >> inifile, "Jitter=Off"
		else:
			print >> inifile, (
				"Jitter=On\n"
				"Jitter_Amount=%f\n"
			) % (
				preferences.get(POVRAY_SETUP, JITTER_AMOUNT),
			)
		oa = preferences.get(POVRAY_SETUP, OUTPUT_ALPHA)
		if oa == 1 or (oa == 2 and chimera.bgopacity):
			if chimera.viewer.depthCue:
				replyobj.warning("Depth-cueing disables transparent background")
			print >> inifile, "Output_Alpha=On"
		if format in ('PNG', 'Stereo PNG'):
			print >> inifile, ("; output PNG\n"
							"Output_File_Type=N8")
		elif format in ('JPEG', 'Stereo JPEG'):
			print >> inifile, ("; output JPEG\n"
					"Output_File_Type=J%d") % quality
		elif format in ('PPM'):
			print >> inifile, ("; output PPM\n"
							"Output_File_Type=P")
		if chimera.nogui or not raytracePreview:
			print >> inifile, "Display=Off"
		else:
			print >> inifile, "Display=On"
			if not raytraceWait:
				print >> inifile, "Pause_when_Done=On"
		inifile.close()
		if raytraceKeepInput:
			inputs = []
		else:
			inputs = [ povfilename, inifilename ]
		def afterCB(aborted, inputs=inputs, outputs=[filename]):
			import os
			for fn in inputs:
				try:
					os.remove(fn)
				except OSError:
					pass
			if aborted:
				for fn in outputs:
					try:
						os.remove(fn)
					except OSError:
						pass
		task.updateStatus("Starting POV-Ray")
		try:
			subproc = SM.Popen(cmd, stdin=None, stdout=None,
						stderr=SM.PIPE, daemon=True)
		except OSError, e:
			raise chimera.UserError, "Unable run POV-Ray executable: %s" % e
		progress = povrayProgress(subproc)
		progress.start()
		subproc.setProgress(progress)
		info = 'running "%s"' % '" "'.join(cmd)
		if not chimera.nogui and statusMessages:
			from chimera import dialogs, tkgui
			dialogs.display(tkgui._ReplyDialog.name)
			replyobj.info(info + '\n')
		task.updateStatus(info)
		subprog = SM.monitor('running POV-Ray', subproc,
					title="POV-Ray progress",
					task=task,
					afterCB=afterCB)
		if raytraceWait:
			subprog.wait()
		return
예제 #11
0
def display(widgetOrURL, package=chimera, newWindow=False):
	"""Display given html help file.

	display(widgetOrURL, package=chimera, newWindow=False) => None
	
	The url may be either a string, or a "widget" that has been
	registered.  In the latter case it is mapped according to
	how it was registered.
	"""
	try:
		# compensate for Pmw megawidgets not being Tk widgets
		widgetOrURL = widgetOrURL.component('hull')
	except:
		pass
	if isinstance(widgetOrURL, basestring):
		url = widgetOrURL
	elif hasattr(widgetOrURL, 'winfo_parent'):
		# show help associated with widget or parent widget
		while widgetOrURL:
			if _helpMap.has_key(widgetOrURL):
				url, package = _helpMap[widgetOrURL]
				break
			parent = widgetOrURL.winfo_parent()
			if not isinstance(parent, str):
				widgetOrURL = parent
			elif parent == "":
				widgetOrURL = None
			else:
				widgetOrURL = widgetOrURL._nametowidget(parent)
		if not widgetOrURL:
			replyobj.warning('internal error -- no help found for widget\n')
			return
	elif isinstance(widgetOrURL, tuple):
		url, package = widgetOrURL
		if isinstance(package, basestring):
			package = __import__(package)
	else:
		replyobj.warning("internal error -- no help avaiable for: %s\n" % widgetOrURL)
		return
	protocol, location, path, parameters, query, fragment = \
		urlparse.urlparse(url, allow_fragments=True)
	path = urllib.quote(path)
	parameters = urllib.quote(parameters)
	query = urllib.quote(query)
	fragment = urllib.quote(fragment)
	if path and path[0] != '/':
		file = os.path.join(package.__path__[0], "helpdir", path)
		if os.path.exists(file):
			protocol = 'file'
			if sys.platform == 'darwin':
				#
				# Setting location to localhost is needed on
				# Mac OS X with Internet Explorer because
				# urlunparse() produces urls like
				# file:/index.blah instead of
				# file:///index.html or
				# file://localhost/index.html
				# required by the browser.
				#
				location = 'localhost'
			path = urllib.pathname2url(file)
			if path[0:3] == '///':
				path = path[2:]
			url = urlparse.urlunparse((protocol, location,
							path, parameters,
							query, fragment))
		else:
			# Fetch development version of docs -- a released
			# version would have the help files included.
			protocol = 'http'
			url = urlparse.urljoin(
				'http://www.cgl.ucsf.edu/chimera/docs/', url)
	replyobj.status("See web browser for %s\n" % url, blankAfter=10)
	import webbrowser
	try:
		webbrowser.open(url, newWindow)
	except webbrowser.Error:
		from chimera import NonChimeraError
		raise NonChimeraError("Could not locate a web browser to use.\n"
			"\nTry setting your BROWSER environment variable to\n"
			"the command-line name of the web browser you want\n"
			"to use and restart Chimera.")
	except OSError, e:
		from chimera import NonChimeraError
		import errno
		if e.errno == errno.ENOENT:
			if protocol == 'file' \
			and not os.path.exists(urllib.url2pathname(path)):
				raise
			# Bug starting webbrowser (firefox, bug 1512),
			# Windows usually opens it eventually
			raise NonChimeraError(
				"Error or delay starting default web browser.\n"
				"\n"
				"Wait a little and if the default web browser\n"
				"doesn't start up, start it by hand, and try\n"
				"again.")
		raise NonChimeraError("Unable to start web browswer.\n"
				"Open <%s> in your web browswer.\n"
				"(%s)" % (path, e))