예제 #1
0
	def fillInUI(self, parent):
		from chimera.tkoptions import IntOption, BooleanOption, \
							FloatOption
		Tkinter.Label(parent, text="Cluster trajectory",
				relief="ridge", bd=4).grid(row=0,
				column=0, columnspan=2, sticky="ew")

		startFrame = self.movie.startFrame
		endFrame = self.movie.endFrame
		self.startFrame = IntOption(parent, 1, "Starting frame",
			startFrame, None, min=startFrame, max=endFrame, width=6)

		numFrames = endFrame - startFrame + 1
		defStride = 1 + int(numFrames/300)
		self.stride = IntOption(parent, 2, "Step size", defStride,
			None, min=1, max=numFrames, width=3)

		self.endFrame = IntOption(parent, 3, "Ending frame", endFrame,
			None, min=startFrame, max=endFrame, width=6)

		self.useSel = BooleanOption(parent, 4, "Cluster based on "
				"current selection, if any", True, None)

		self.ignoreBulk = BooleanOption(parent, 5, "Ignore solvent/"
							"ions", True, None)
		self.ignoreHyds = BooleanOption(parent, 6, "Ignore hydrogens",
							True, None)
예제 #2
0
	def fillInUI(self, parent):
		Tkinter.Label(parent, text="Collect positions of selected"
			" atoms over trajectory", relief="ridge", bd=4).grid(
			row=0, column=0, columnspan=2, sticky="ew")

		startFrame = self.movie.startFrame
		endFrame = self.movie.endFrame
		from chimera.tkoptions import IntOption, BooleanOption, \
						FloatOption, StringOption
		self.startFrame = IntOption(parent, 1, "Starting frame",
			startFrame, None, min=startFrame, max=endFrame, width=6)

		numFrames = endFrame - startFrame + 1
		defStride = 1 + int(numFrames/300)
		self.stride = IntOption(parent, 2, "Step size", defStride,
			None, min=1, max=numFrames, width=3)

		self.endFrame = IntOption(parent, 3, "Ending frame", endFrame,
			None, min=startFrame, max=endFrame, width=6)

		self.doCutoff = BooleanOption(parent, 4, 'Limit data collection'
			' to within cutoff distance of any "held steady" atoms',
			True, None)

		self.cutoff = FloatOption(parent, 5, "Cutoff distance",
				prefs[VOLUME_CUTOFF], None, width=4)
		self.resolution = FloatOption(parent, 6, "Volume grid spacing",
			prefs[VOLUME_RESOLUTION], None, min=0.0001, width=4)
		self.volumeName = StringOption(parent, 7, "Volume data name",
			self.movie.ensemble.name, None, width=20)
		self.byAtomType = BooleanOption(parent, 8, "Collect data"
			" separately for each atom type in selection",
			True, None, balloon="Create a volume data set for"
			" each type of atom type\n(sp2 oxygen, aromatic carbon,"
			" etc.) in current selection")
예제 #3
0
	def fillInUI(self, parent):
		from chimera.tkoptions import IntOption, BooleanOption, \
							FloatOption
		Tkinter.Label(parent, text="Create RMSD map of trajectory "
			"against itself", relief="ridge", bd=4).grid(row=0,
			column=0, columnspan=2, sticky="ew")

		startFrame = self.movie.startFrame
		endFrame = self.movie.endFrame
		self.startFrame = IntOption(parent, 1, "Starting frame",
			startFrame, None, min=startFrame, max=endFrame, width=6)

		numFrames = endFrame - startFrame + 1
		defStride = 1 + int(numFrames/300)
		self.stride = IntOption(parent, 2, "Step size", defStride,
			None, min=1, max=numFrames, width=3)

		self.endFrame = IntOption(parent, 3, "Ending frame", endFrame,
			None, min=startFrame, max=endFrame, width=6)

		self.minRmsd = FloatOption(parent, 4, "Lower RMSD threshold"
				" (white)", prefs[RMSD_MIN], None, width=6)
		self.maxRmsd = FloatOption(parent, 5, "Upper RMSD threshold"
				" (black)", prefs[RMSD_MAX], None, width=6)

		self.useSel = BooleanOption(parent, 6, "Restrict map to "
				"current selection, if any", True, None)

		self.ignoreBulk = BooleanOption(parent, 7, "Ignore solvent/"
							"ions", True, None)
		self.ignoreHyds = BooleanOption(parent, 8, "Ignore hydrogens",
							True, None)
		self.recolor = BooleanOption(parent, 9, "Auto-recolor for"
				" contrast", prefs[RMSD_AUTOCOLOR], None)
	def fillInUI(self, parent):
		import Pmw, Tkinter
		row = 0
		Tkinter.Label(parent, text="Create plane for selected atoms...").grid(
							row=row, columnspan=2)
		row += 1

		from chimera.tkoptions import StringOption, BooleanOption
		self.nameOpt = StringOption(parent, row, "Plane name", "plane", None)
		row += 1

		self.replaceExistingOpt = BooleanOption(parent, row,
										"Replace existing planes", False, None)
		row += 1

		from chimera.tkoptions import ColorOption, FloatOption
		self.colorOpt = ColorOption(parent, row, "Color", None, None,
			balloon="Plane color.  If No Color, then the plane"
			" will be colored to match the structure")
		row += 1

		self.autoRadiusOpt = BooleanOption(parent, row,
			"Set disk size to enclose atom projections", True, self._radCB)
		row += 1
		self.radRow = row
		self.radOffsetOpt = FloatOption(parent, row, "Extra radius"
			" (padding)", 0.0, None)
		self.radiusOpt = FloatOption(parent, row, "Fixed radius", 10.0, None)
		self.radiusOpt.forget()
		row += 1

		self.thicknessOpt = FloatOption(parent, row, "Disk thickness",
										prefs[PLANE_THICKNESS], None)
class Interface(ModelessDialog):

    title = "Fill Gaps with Modeller"

    def __init__(self, *args, **kw):
        ModelessDialog.__init__(self, *args, **kw)
        # TODO: initialize instance variables

    def fillInUI(self, parent):
        from chimera.widgets import MoleculeOptionMenu
        from chimera.tkoptions import IntOption, BooleanOption, \
          InputFileOption, StringOption
        import itertools
        info = Tk.Label(parent,
                        justify=Tk.LEFT,
                        wraplength=300,
                        text="Select a molecule with gaps")
        info.pack(ipadx=2, ipady=2)
        options = Tk.Frame(parent)
        options.columnconfigure(0, pad=2)
        options.columnconfigure(1, pad=2)
        row = itertools.count()
        molRow = row.next()
        text = Tk.Label(options, text="Restrict selections to molecule:")
        text.grid(row=molRow, column=0)
        self.molecules = MoleculeOptionMenu(options,
                                            command=self.updateMolecule)
        self.molecules.grid(row=molRow, column=1, sticky=Tk.W)
        self.turnsOnly = BooleanOption(options, row.next(),
                                       "Skip gaps at ends of chains", False,
                                       None)
        self.hetatms = BooleanOption(options, row.next(),
                                     "Include HETATM residues", False, None)
        #self.waters = BooleanOption(options, row.next(),
        #		"Include waters", False, None)
        self.nucleic = BooleanOption(options, row.next(),
                                     "Include nucleic acids", False, None)
        self.nucleic.disable()
        hr = Tk.Frame(options, relief=Tk.GROOVE, borderwidth=1, height=2)
        hr.grid(row=row.next(), columnspan=2, sticky='ew')
        # modeller location
        self.modeller = InputFileOption(options, row.next(),
                                        "Modeller location", "mod8v2", None)
        # temporary prefix -- TODO: add unique id
        #self.tempdir = StringOption(options, row.next(),
        #		"Temporary file prefix", "modtmp", None)
        options.pack()

    def updateMolecule(self, *args, **kw):
        print 'updateMolecule', args, kw
        # TODO: look for gaps

    def Apply(self):
        from chimera import selection
        molecule = [self.molecules.getvalue()]
예제 #6
0
class ClusterStarter(ModelessDialog):
	title = "Get Clustering Parameters"

	def __init__(self, movie):
		self.movie = movie
		movie.subdialogs.append(self)
		ModelessDialog.__init__(self)

	def fillInUI(self, parent):
		from chimera.tkoptions import IntOption, BooleanOption, \
							FloatOption
		Tkinter.Label(parent, text="Cluster trajectory",
				relief="ridge", bd=4).grid(row=0,
				column=0, columnspan=2, sticky="ew")

		startFrame = self.movie.startFrame
		endFrame = self.movie.endFrame
		self.startFrame = IntOption(parent, 1, "Starting frame",
			startFrame, None, min=startFrame, max=endFrame, width=6)

		numFrames = endFrame - startFrame + 1
		defStride = 1 + int(numFrames/300)
		self.stride = IntOption(parent, 2, "Step size", defStride,
			None, min=1, max=numFrames, width=3)

		self.endFrame = IntOption(parent, 3, "Ending frame", endFrame,
			None, min=startFrame, max=endFrame, width=6)

		self.useSel = BooleanOption(parent, 4, "Cluster based on "
				"current selection, if any", True, None)

		self.ignoreBulk = BooleanOption(parent, 5, "Ignore solvent/"
							"ions", True, None)
		self.ignoreHyds = BooleanOption(parent, 6, "Ignore hydrogens",
							True, None)
	def Apply(self):
		startFrame = self.startFrame.get()
		stride = self.stride.get()
		endFrame = self.endFrame.get()
		if endFrame <= startFrame:
			self.enter()
			raise UserError("Start frame must be less"
							" than end frame")
		if startFrame < self.movie.startFrame \
		or endFrame > self.movie.endFrame:
			self.enter()
			raise UserError("Start or end frame outside"
							" of trajectory")
		ClusterDialog(self.movie, startFrame, self.stride.get(),
			endFrame, self.useSel.get(), self.ignoreBulk.get(),
			self.ignoreHyds.get())
예제 #7
0
    def __init__(self, parent, dialog, prefPrefix, callback):
        Pmw.Group.__init__(self, parent, tag_text="Spacing")
        self.__callback = callback
        self.__dialog = dialog
        self.__prefPrefix = prefPrefix

        prefs = dialog.mav.prefs
        self.__columnSepEntry = Pmw.EntryField(
            self.interior(),
            command=self.__newColSep,
            labelpos='w',
            label_text="Column separation (pixels)",
            entry_width=2,
            entry_justify='center',
            validate='integer',
            value=prefs[prefPrefix + COLUMN_SEP])
        self.__columnSepEntry.grid(row=0, column=0, columnspan=2, sticky='e')
        dialog._entryWidgets.append(self.__columnSepEntry)

        self.__lineSepEntry = Pmw.EntryField(
            self.interior(),
            command=self.__newLineSep,
            labelpos='w',
            label_text="Line separation (pixels)",
            entry_width=2,
            entry_justify='center',
            validate='integer',
            value=prefs[prefPrefix + LINE_SEP])
        self.__lineSepEntry.grid(row=1, column=0, columnspan=2, sticky='e')
        dialog._entryWidgets.append(self.__lineSepEntry)

        from chimera.tkoptions import BooleanOption
        BooleanOption(self.interior(), 2, "Space after every 10 residues",
                      prefs[prefPrefix + TEN_RES_GAP], self.__resGap)
    def fillInUI(self, parent):
        SaveModeless.fillInUI(self, parent)
        from chimera.tkoptions import SymbolicEnumOption, BooleanOption

        class ColorModeOption(SymbolicEnumOption):
            values = ["color", "gray", "mono"]
            labels = ["color", "grayscale", "black & white"]

        self.colorMode = ColorModeOption(self.clientArea,
                                         0,
                                         "color mode",
                                         "color",
                                         None,
                                         balloon="output color range")
        self.orientation = BooleanOption(
            self.clientArea,
            1,
            "rotate 90",
            False,
            None,
            balloon="If true, output will be rotated 90 degrees\n"
            "(i.e. landscape mode)")

        class ExtentOption(SymbolicEnumOption):
            values = ["visible", "all"]
            labels = ["visible region", "entire alignment"]

        self.extent = ExtentOption(
            self.clientArea,
            2,
            "extent",
            "visible",
            None,
            balloon="save the entire alignment or just the visible part")
        self.hideNodes = BooleanOption(
            self.clientArea,
            3,
            "hide tree control nodes",
            True,
            None,
            balloon="Hide square boxes used as controls for tree")
        if not self.mav.seqCanvas.treeShown:
            self.hideNodes.forget()
        self._nodesHandler = self.mav.triggers.addHandler(
            DISPLAY_TREE, self._treeDispCB, None)
예제 #9
0
	def fillInUI(self, parent):
		from chimera.widgets import MoleculeOptionMenu
		from chimera.tkoptions import IntOption, BooleanOption, \
				InputFileOption, StringOption, EnumOption
		import itertools
		info = Tk.Label(parent, justify=Tk.LEFT, wraplength=300, text=
				"Model alternate conformations of loops using "
				"Modeller from <http://salilab.org/>.\n"
				"First select the loops you wish to model."
				"  Then choose the number of models "
				"you wish to generate.")
		info.pack(ipadx=2, ipady=2)
		options = Tk.Frame(parent)
		options.columnconfigure(0, pad=2)
		options.columnconfigure(1, pad=2)
		row = itertools.count()
		molRow = row.next()
		text = Tk.Label(options,
				text="Restrict selections to molecule:")
		text.grid(row=molRow, column=0)
		self.molecules = MoleculeOptionMenu(options)
		self.molecules.grid(row=molRow, column=1, sticky=Tk.W)
		self.turnsOnly = BooleanOption(options, row.next(),
				"Restrict selections to turns", True, None)
		self.hetatms = BooleanOption(options, row.next(),
				"Include HETATM residues", False, None)
		self.waters = BooleanOption(options, row.next(),
				"Include waters", False, None)
		self.waters.disable()
		self.nucleic = BooleanOption(options, row.next(),
				"Include nucleic acids", False, None)
		self.nucleic.disable()
		self.count = IntOption(options, row.next(), "Number of models",
				10, None, min=1, sticky=Tk.W)
		#self.start = IntOption(options, row.next(),
		#		"Starting model number", 1, None, min=0)
		class Refinement(EnumOption):
			values = ('very fast', 'fast', 'slow', 'very slow',
				'slow large', 'none')
		self.refine = Refinement(options, row.next(), "Refinement",
								'fast', None)
		button = Tk.Button(options, text="Prune selection",
				command=self.prune)
		button.grid(row=row.next(), column=0, columnspan=2, pady=2)
		self.start = 1
		hr = Tk.Frame(options, relief=Tk.GROOVE, borderwidth=1, height=2)
		hr.grid(row=row.next(), columnspan=2, sticky='ew')
		# modeller location
		self.modeller = InputFileOption(options, row.next(),
				"Modeller location", "mod9v2", None)
		# temporary prefix -- TODO: add unique id
		#self.tempdir = StringOption(options, row.next(),
		#		"Temporary file prefix", "modtmp", None)
		options.pack()
예제 #10
0
	def _fillColorKeyPage(self, page):
		from chimera.tkoptions import IntOption, EnumOption, \
						BooleanOption, RGBAOption
		f = Tkinter.Frame(page)
		f.grid(row=0, columnspan=2)
		self.numComponents = IntOption(f, 0, "Number of colors/labels",
					3, self._componentsCB, min=2, width=2)
		self.componentsFrame = Tkinter.Frame(page)
		self.componentsFrame.grid(row=1, column=0, sticky="nsew",
							columnspan=2)
		page.columnconfigure(0, weight=1)
		self.componentsFrame.columnconfigure(1, weight=1)
		class ColorTreatment(EnumOption):
			values = ("distinct", "blended")
		self.colorTreatment = ColorTreatment(page, 2,
			"Color range depiction", "blended", self._keyChangeCB,
			balloon="Should colors be shown as distinct rectangles"
			" or as a continuous range")
		class LabelPosition(EnumOption):
			values = ("left/top", "right/bottom")
		self.labelPos = LabelPosition(page, 3, "Label positions",
			"right/bottom", self._keyChangeCB, balloon="Position of"
			" labels relative to color key.\nLabels always"
			" positioned adjacent to long side.")
		self.labelColor = RGBAOption(page, 4, "Label color",
			self._contrastWithBG(), self._keyChangeCB, balloob=
			"Label color.  If set to 'No color', use corresponding"
			" key color", noneOkay=True)
		class LabelJustification(EnumOption):
			values = ("left", "decimal point", "right")
		self.justification = LabelJustification(page, 5,
			"Label justification", "decimal point",
			self._keyChangeCB, balloon="Justification of label text"
			" in a vertical key layout.\nHorizontal key labels will"
			" always be center justified.")
		self.labelOffset = IntOption(page, 6, "Label offset", 0,
			self._keyChangeCB, width=3, balloon="Additional offset"
			" of labels from color bar, in pixels")
		self.keyFontSize = IntOption(page, 7, "Font size", 24,
			self._keyChangeCB, width=3)
		self.keyFontStyle = FontStyle(page, 8, "Font style",
			oglFont.normal, self._keyChangeCB)
		self.keyFontTypeface = FontTypeface(page, 9, "Font typeface",
			FONT_TYPEFACE_VALUES[0], self._keyChangeCB)
		self.borderColor = RGBAOption(page, 10, "Border color",
			None, self._keyChangeCB, balloon="Color of border"
			" around color key (not each individual color).\n"
			"If 'no color', then no border is drawn.")
		self.borderWidth = IntOption(page, 11, "Border width", 3,
			self._keyChangeCB, balloon="in pixels")
		self.tickMarks = BooleanOption(page, 12, "Show tick marks",
			False, self._keyChangeCB, balloon="Show tick marks"
			" pointing from key to labels")
		self._componentsCB(self.numComponents)
예제 #11
0
    def fillInUI(self, parent):
        OpenModeless.fillInUI(self, parent)

        group = Pmw.Group(self.clientArea, tag_text='Further info')
        group.grid(row=0, column=0, sticky='nsew')
        self.catName = StringOption(group.interior(), 0, "group name", None,
                                    None)

        class PBLineWidthOption(LineWidthOption):
            default = prefs["line width"]
            balloon = "Width of pseudobonds (in pixels)"

        self.lineWidth = PBLineWidthOption(group.interior(), 1, None, None,
                                           None)
        self.clearCat = BooleanOption(group.interior(), 2,
                                      "clear group of previous pseudobonds", 1,
                                      None)
        self.leftModel = IntOption(group.interior(), 3,
                                   "first column specifiers default to model",
                                   0, None)
        self.rightModel = IntOption(
            group.interior(), 4, "second column specifiers default to model",
            0, None)
예제 #12
0
class PBreaderDialog(OpenModeless):
    title = "Pseudobond Reader"
    help = "ContributedSoftware/pbreader/pbreader.html"

    def __init__(self):
        OpenModeless.__init__(self,
                              title="Pseudobond File to Read",
                              historyID="PBReader open",
                              clientPos='s')

    def fillInUI(self, parent):
        OpenModeless.fillInUI(self, parent)

        group = Pmw.Group(self.clientArea, tag_text='Further info')
        group.grid(row=0, column=0, sticky='nsew')
        self.catName = StringOption(group.interior(), 0, "group name", None,
                                    None)

        class PBLineWidthOption(LineWidthOption):
            default = prefs["line width"]
            balloon = "Width of pseudobonds (in pixels)"

        self.lineWidth = PBLineWidthOption(group.interior(), 1, None, None,
                                           None)
        self.clearCat = BooleanOption(group.interior(), 2,
                                      "clear group of previous pseudobonds", 1,
                                      None)
        self.leftModel = IntOption(group.interior(), 3,
                                   "first column specifiers default to model",
                                   0, None)
        self.rightModel = IntOption(
            group.interior(), 4, "second column specifiers default to model",
            0, None)

    def Apply(self):
        if not self.getPaths():
            replyobj.error("No pseudobond file chosen\n")
        lineWidth = self.lineWidth.get()
        prefs["line width"] = lineWidth
        for path in self.getPaths():
            readPBinfo(path,
                       category=self.catName.get(),
                       clearCategory=self.clearCat.get(),
                       lineWidth=lineWidth,
                       drawMode=None,
                       leftModel=str(self.leftModel.get()),
                       rightModel=str(self.rightModel.get()),
                       defColor=None)
예제 #13
0
	def fillInUI(self, parent):
		OpenModeless.fillInUI(self, parent)

		group = Pmw.Group(self.clientArea, tag_text='Further info')
		group.grid(row=0, column=0, sticky='nsew')
		self.catName = StringOption(group.interior(), 0,
			"group name", None, None)
		class PBLineWidthOption(LineWidthOption):
			default = prefs["line width"]
			balloon = "Width of pseudobonds (in pixels)"
		self.lineWidth = PBLineWidthOption(group.interior(), 1, None,
								None, None)
		self.clearCat = BooleanOption(group.interior(), 2,
			"clear group of previous pseudobonds", 1, None)
		self.leftModel = IntOption(group.interior(), 3,
			"first column specifiers default to model", 0, None)
		self.rightModel = IntOption(group.interior(), 4,
			"second column specifiers default to model", 0, None)
예제 #14
0
class PBreaderDialog(OpenModeless):
	title = "Pseudobond Reader"
	help = "ContributedSoftware/pbreader/pbreader.html"

	def __init__(self):
		OpenModeless.__init__(self, title="Pseudobond File to Read",
				historyID="PBReader open", clientPos='s')

	def fillInUI(self, parent):
		OpenModeless.fillInUI(self, parent)

		group = Pmw.Group(self.clientArea, tag_text='Further info')
		group.grid(row=0, column=0, sticky='nsew')
		self.catName = StringOption(group.interior(), 0,
			"group name", None, None)
		class PBLineWidthOption(LineWidthOption):
			default = prefs["line width"]
			balloon = "Width of pseudobonds (in pixels)"
		self.lineWidth = PBLineWidthOption(group.interior(), 1, None,
								None, None)
		self.clearCat = BooleanOption(group.interior(), 2,
			"clear group of previous pseudobonds", 1, None)
		self.leftModel = IntOption(group.interior(), 3,
			"first column specifiers default to model", 0, None)
		self.rightModel = IntOption(group.interior(), 4,
			"second column specifiers default to model", 0, None)

	def Apply(self):
		if not self.getPaths():
			replyobj.error("No pseudobond file chosen\n")
		lineWidth = self.lineWidth.get()
		prefs["line width"] = lineWidth
		for path in self.getPaths():
			readPBinfo(path, category=self.catName.get(),
				clearCategory=self.clearCat.get(),
				lineWidth=lineWidth, drawMode=None,
				leftModel=str(self.leftModel.get()),
				rightModel=str(self.rightModel.get()),
				defColor=None)
    def fillInUI(self, parent):
        from chimera.tkoptions import IntOption, BooleanOption, \
             FloatOption
        Tkinter.Label(parent, text="Cluster trajectory", relief="ridge",
                      bd=4).grid(row=0, column=0, columnspan=2, sticky="ew")

        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        self.startFrame = IntOption(parent,
                                    1,
                                    "Starting frame",
                                    startFrame,
                                    None,
                                    min=startFrame,
                                    max=endFrame,
                                    width=6)

        numFrames = endFrame - startFrame + 1
        defStride = 1 + int(numFrames / 300)
        self.stride = IntOption(parent,
                                2,
                                "Step size",
                                defStride,
                                None,
                                min=1,
                                max=numFrames,
                                width=3)

        self.endFrame = IntOption(parent,
                                  3,
                                  "Ending frame",
                                  endFrame,
                                  None,
                                  min=startFrame,
                                  max=endFrame,
                                  width=6)

        self.useSel = BooleanOption(
            parent, 4, "Cluster based on "
            "current selection, if any", True, None)

        self.ignoreBulk = BooleanOption(parent, 5, "Ignore solvent/"
                                        "ions", True, None)
        self.ignoreHyds = BooleanOption(parent, 6, "Ignore hydrogens", True,
                                        None)
예제 #16
0
class RecorderDialog(SaveModeless):
	title = "Record Animation of Trajectory"
	help = "ContributedSoftware/movie/movie.html#recording"
	default = "Record"

	def __init__(self, movie):
		self.movie = movie
		movie.subdialogs.append(self)
		from MovieRecorder import RecorderGUI
		formats = []
		exts = []
		for fmtInfo in RecorderGUI.formats:
			fmt, ext = fmtInfo[:2]
			formats.append(fmt)
			exts.append("." + ext)
		filters = []
		for i, fmt in enumerate(formats):
			ext = exts[i]
			filters.append((fmt, '*'+ext, ext))
		SaveModeless.__init__(self, clientPos='s', clientSticky='ew',
				defaultFilter=prefs[RECORDER_FORMAT],
				filters=filters, historyID="MD recorder")
	def map(self, e=None):
		from MovieRecorder import checkLicense
		if not checkLicense():
			self.Close()

	def fillInUI(self, parent):
		SaveModeless.fillInUI(self, parent)
		self.clientArea.columnconfigure(1, weight=1)

		startFrame = self.movie.startFrame
		endFrame = self.movie.endFrame
		from chimera.tkoptions import IntOption, BooleanOption, \
						FloatOption, StringOption
		self.startFrame = IntOption(self.clientArea, 0,
					"Starting frame", startFrame, None,
					min=startFrame, max=endFrame, width=6)

		numFrames = endFrame - startFrame + 1
		defStride = 1 + int(numFrames/300)
		self.stride = IntOption(self.clientArea, 2, "Step size",
			defStride, None, min=1, max=numFrames, width=3)

		self.endFrame = IntOption(self.clientArea, 3, "Ending frame",
			endFrame, None, min=startFrame, max=endFrame, width=6)

		self.roundtrip = BooleanOption(self.clientArea, 4, "Encode"
			' forward then backward ("roundtrip")', prefs[
			RECORDER_ROUNDTRIP], None, balloon=
			"Encode the frames in forward and then reverse\n"
			"order so that if the movie is played as a loop\n"
			"the motion seems continuous")

		class FrameQuality(BooleanOption):
			labels = ["screen", "supersampled"]
		self.supersample = FrameQuality(self.clientArea, 5,
			"Frame quality", prefs[RECORDER_SUPERSAMPLE],
			self.supersampleCB, balloon=
			"Whether each frame should be taken as is from\n"
			"the screen (fast) or redrawn at higher quality\n"
			"with several samples per pixel.")

		from chimera.printer import SupersampleOption
		self.samples = SupersampleOption(self.clientArea, 6,
			"Samples", prefs[RECORDER_SAMPLES], None)
		self.supersampleCB()

		self.raytrace = BooleanOption(self.clientArea, 7, "Raytrace"
			" with POV-Ray", prefs[RECORDER_RAYTRACE], None)
			
		def povOptCB():
			from chimera.dialogs import display
			d = display("preferences")
			from chimera.printer import POVRAY_SETUP
			d.setCategoryMenu(POVRAY_SETUP)
		Tkinter.Button(self.clientArea, text="POV-Ray Options", pady=0,
			command=povOptCB).grid(row=8, column=0, columnspan=2)
			
		self.recordArgs = StringOption(self.clientArea, 9,
			"Additional recording options",
			prefs[RECORDER_RECORD_ARGS], None, balloon=
			"Options (other than 'supersample' and 'raytrace')\n"
			"for recording frames as per Chimera's 'movie record'"
			" command")

		self.encodeArgs = StringOption(self.clientArea, 10,
			"Additional encoding options",
			prefs[RECORDER_ENCODE_ARGS], None, balloon=
			"Options (other than 'mformat', 'output', and\n"
			"'roundtrip') for composing the frames into the\n"
			"final animation as per Chimera's 'movie encode'\n"
			"command")
		
		Tkinter.Label(self.clientArea, text=
			"On some computers it may be necessary to make sure"
			" that no\nwindows occlude the main Chimera graphics"
			" window (even\npartially) during non-raytraced movie"
			" recording").grid(row=11, column=0, columnspan=2)

	def Apply(self):
		from chimera import UserError
		startFrame = self.startFrame.get()
		endFrame = self.endFrame.get()
		if endFrame <= startFrame:
			self.enter()
			raise UserError("Start frame must be less"
							" than end frame")
		if startFrame < self.movie.startFrame \
		or endFrame > self.movie.endFrame:
			self.enter()
			raise UserError("Start or end frame outside"
							" of trajectory")
		path, format = self.getPathsAndTypes()[0]
		prefs[RECORDER_FORMAT] = format
		recordArgs = self.recordArgs.get()
		prefs[RECORDER_RECORD_ARGS] = recordArgs
		encodeArgs = self.encodeArgs.get()
		prefs[RECORDER_ENCODE_ARGS] = encodeArgs
		roundtrip = self.roundtrip.get()
		prefs[RECORDER_ROUNDTRIP] = roundtrip
		supersample = self.supersample.get()
		prefs[RECORDER_SUPERSAMPLE] = supersample
		if supersample:
			samples = self.samples.get()
			prefs[RECORDER_SAMPLES] = samples
			recordArgs = " ".join([recordArgs,
						"supersample", str(samples)])
		raytrace = self.raytrace.get()
		prefs[RECORDER_RAYTRACE] = raytrace
		from MovieRecorder import RecorderGUI
		for ext, fmtInfo in RecorderGUI.command_formats.items():
			if fmtInfo[0] == format:
				break
		recordArgs = " ".join([recordArgs, "raytrace", str(raytrace)])
		reprPath = repr(path)
		if reprPath[0] == 'u':
			# strip unicode indicator
			reprPath = reprPath[1:]
		encodeArgs = " ".join([encodeArgs, "roundtrip", str(roundtrip),
				"mformat", ext, "output", reprPath])
		self.movie.recordAnimation(startFrame=startFrame,
				endFrame=endFrame, step=self.stride.get(),
				recordArgs=recordArgs, encodeArgs=encodeArgs)

	Record = SaveModeless.Save

	def supersampleCB(self, *args):
		if self.supersample.get():
			self.samples.enable()
		else:
			self.samples.disable()
예제 #17
0
	def fillInUI(self, parent):
		SaveModeless.fillInUI(self, parent)
		self.clientArea.columnconfigure(1, weight=1)

		startFrame = self.movie.startFrame
		endFrame = self.movie.endFrame
		from chimera.tkoptions import IntOption, BooleanOption, \
						FloatOption, StringOption
		self.startFrame = IntOption(self.clientArea, 0,
					"Starting frame", startFrame, None,
					min=startFrame, max=endFrame, width=6)

		numFrames = endFrame - startFrame + 1
		defStride = 1 + int(numFrames/300)
		self.stride = IntOption(self.clientArea, 2, "Step size",
			defStride, None, min=1, max=numFrames, width=3)

		self.endFrame = IntOption(self.clientArea, 3, "Ending frame",
			endFrame, None, min=startFrame, max=endFrame, width=6)

		self.roundtrip = BooleanOption(self.clientArea, 4, "Encode"
			' forward then backward ("roundtrip")', prefs[
			RECORDER_ROUNDTRIP], None, balloon=
			"Encode the frames in forward and then reverse\n"
			"order so that if the movie is played as a loop\n"
			"the motion seems continuous")

		class FrameQuality(BooleanOption):
			labels = ["screen", "supersampled"]
		self.supersample = FrameQuality(self.clientArea, 5,
			"Frame quality", prefs[RECORDER_SUPERSAMPLE],
			self.supersampleCB, balloon=
			"Whether each frame should be taken as is from\n"
			"the screen (fast) or redrawn at higher quality\n"
			"with several samples per pixel.")

		from chimera.printer import SupersampleOption
		self.samples = SupersampleOption(self.clientArea, 6,
			"Samples", prefs[RECORDER_SAMPLES], None)
		self.supersampleCB()

		self.raytrace = BooleanOption(self.clientArea, 7, "Raytrace"
			" with POV-Ray", prefs[RECORDER_RAYTRACE], None)
			
		def povOptCB():
			from chimera.dialogs import display
			d = display("preferences")
			from chimera.printer import POVRAY_SETUP
			d.setCategoryMenu(POVRAY_SETUP)
		Tkinter.Button(self.clientArea, text="POV-Ray Options", pady=0,
			command=povOptCB).grid(row=8, column=0, columnspan=2)
			
		self.recordArgs = StringOption(self.clientArea, 9,
			"Additional recording options",
			prefs[RECORDER_RECORD_ARGS], None, balloon=
			"Options (other than 'supersample' and 'raytrace')\n"
			"for recording frames as per Chimera's 'movie record'"
			" command")

		self.encodeArgs = StringOption(self.clientArea, 10,
			"Additional encoding options",
			prefs[RECORDER_ENCODE_ARGS], None, balloon=
			"Options (other than 'mformat', 'output', and\n"
			"'roundtrip') for composing the frames into the\n"
			"final animation as per Chimera's 'movie encode'\n"
			"command")
		
		Tkinter.Label(self.clientArea, text=
			"On some computers it may be necessary to make sure"
			" that no\nwindows occlude the main Chimera graphics"
			" window (even\npartially) during non-raytraced movie"
			" recording").grid(row=11, column=0, columnspan=2)
예제 #18
0
class RecorderDialog(SaveModeless):
    title = "Record Animation of Trajectory"
    help = "ContributedSoftware/movie/movie.html#recording"
    default = "Record"

    def __init__(self, movie):
        self.movie = movie
        movie.subdialogs.append(self)
        from MovieRecorder import RecorderGUI
        formats = []
        exts = []
        for fmtInfo in RecorderGUI.formats:
            fmt, ext = fmtInfo[:2]
            formats.append(fmt)
            exts.append("." + ext)
        filters = []
        for i, fmt in enumerate(formats):
            ext = exts[i]
            filters.append((fmt, '*' + ext, ext))
        SaveModeless.__init__(self,
                              clientPos='s',
                              clientSticky='ew',
                              defaultFilter=prefs[RECORDER_FORMAT],
                              filters=filters,
                              historyID="MD recorder")

    def map(self, e=None):
        from MovieRecorder import checkLicense
        if not checkLicense():
            self.Close()

    def fillInUI(self, parent):
        SaveModeless.fillInUI(self, parent)
        self.clientArea.columnconfigure(1, weight=1)

        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        from chimera.tkoptions import IntOption, BooleanOption, \
            FloatOption, StringOption
        self.startFrame = IntOption(self.clientArea,
                                    0,
                                    "Starting frame",
                                    startFrame,
                                    None,
                                    min=startFrame,
                                    max=endFrame,
                                    width=6)

        numFrames = endFrame - startFrame + 1
        defStride = 1 + int(numFrames / 300)
        self.stride = IntOption(self.clientArea,
                                2,
                                "Step size",
                                defStride,
                                None,
                                min=1,
                                max=numFrames,
                                width=3)

        self.endFrame = IntOption(self.clientArea,
                                  3,
                                  "Ending frame",
                                  endFrame,
                                  None,
                                  min=startFrame,
                                  max=endFrame,
                                  width=6)

        self.roundtrip = BooleanOption(
            self.clientArea,
            4, "Encode"
            ' forward then backward ("roundtrip")',
            prefs[RECORDER_ROUNDTRIP],
            None,
            balloon="Encode the frames in forward and then reverse\n"
            "order so that if the movie is played as a loop\n"
            "the motion seems continuous")

        class FrameQuality(BooleanOption):
            labels = ["screen", "supersampled"]

        self.supersample = FrameQuality(
            self.clientArea,
            5,
            "Frame quality",
            prefs[RECORDER_SUPERSAMPLE],
            self.supersampleCB,
            balloon="Whether each frame should be taken as is from\n"
            "the screen (fast) or redrawn at higher quality\n"
            "with several samples per pixel.")

        from chimera.printer import SupersampleOption
        self.samples = SupersampleOption(self.clientArea, 6, "Samples",
                                         prefs[RECORDER_SAMPLES], None)
        self.supersampleCB()

        self.raytrace = BooleanOption(self.clientArea, 7, "Raytrace"
                                      " with POV-Ray",
                                      prefs[RECORDER_RAYTRACE], None)

        def povOptCB():
            from chimera.dialogs import display
            d = display("preferences")
            from chimera.printer import POVRAY_SETUP
            d.setCategoryMenu(POVRAY_SETUP)

        Tkinter.Button(self.clientArea,
                       text="POV-Ray Options",
                       pady=0,
                       command=povOptCB).grid(row=8, column=0, columnspan=2)

        self.recordArgs = StringOption(
            self.clientArea,
            9,
            "Additional recording options",
            prefs[RECORDER_RECORD_ARGS],
            None,
            balloon="Options (other than 'supersample' and 'raytrace')\n"
            "for recording frames as per Chimera's 'movie record'"
            " command")

        self.encodeArgs = StringOption(
            self.clientArea,
            10,
            "Additional encoding options",
            prefs[RECORDER_ENCODE_ARGS],
            None,
            balloon="Options (other than 'mformat', 'output', and\n"
            "'roundtrip') for composing the frames into the\n"
            "final animation as per Chimera's 'movie encode'\n"
            "command")

        Tkinter.Label(self.clientArea,
                      text="On some computers it may be necessary to make sure"
                      " that no\nwindows occlude the main Chimera graphics"
                      " window (even\npartially) during non-raytraced movie"
                      " recording").grid(row=11, column=0, columnspan=2)

    def Apply(self):
        from chimera import UserError
        startFrame = self.startFrame.get()
        endFrame = self.endFrame.get()
        if endFrame <= startFrame:
            self.enter()
            raise UserError("Start frame must be less" " than end frame")
        if startFrame < self.movie.startFrame \
        or endFrame > self.movie.endFrame:
            self.enter()
            raise UserError("Start or end frame outside" " of trajectory")
        path, format = self.getPathsAndTypes()[0]
        prefs[RECORDER_FORMAT] = format
        recordArgs = self.recordArgs.get()
        prefs[RECORDER_RECORD_ARGS] = recordArgs
        encodeArgs = self.encodeArgs.get()
        prefs[RECORDER_ENCODE_ARGS] = encodeArgs
        roundtrip = self.roundtrip.get()
        prefs[RECORDER_ROUNDTRIP] = roundtrip
        supersample = self.supersample.get()
        prefs[RECORDER_SUPERSAMPLE] = supersample
        if supersample:
            samples = self.samples.get()
            prefs[RECORDER_SAMPLES] = samples
            recordArgs = " ".join([recordArgs, "supersample", str(samples)])
        raytrace = self.raytrace.get()
        prefs[RECORDER_RAYTRACE] = raytrace
        from MovieRecorder import RecorderGUI
        for ext, fmtInfo in RecorderGUI.command_formats.items():
            if fmtInfo[0] == format:
                break
        recordArgs = " ".join([recordArgs, "raytrace", str(raytrace)])
        reprPath = repr(path)
        if reprPath[0] == 'u':
            # strip unicode indicator
            reprPath = reprPath[1:]
        encodeArgs = " ".join([
            encodeArgs, "roundtrip",
            str(roundtrip), "mformat", ext, "output", reprPath
        ])
        self.movie.recordAnimation(startFrame=startFrame,
                                   endFrame=endFrame,
                                   step=self.stride.get(),
                                   recordArgs=recordArgs,
                                   encodeArgs=encodeArgs)

    Record = SaveModeless.Save

    def supersampleCB(self, *args):
        if self.supersample.get():
            self.samples.enable()
        else:
            self.samples.disable()
예제 #19
0
    def fillInUI(self, parent):
        SaveModeless.fillInUI(self, parent)
        self.clientArea.columnconfigure(1, weight=1)

        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        from chimera.tkoptions import IntOption, BooleanOption, \
            FloatOption, StringOption
        self.startFrame = IntOption(self.clientArea,
                                    0,
                                    "Starting frame",
                                    startFrame,
                                    None,
                                    min=startFrame,
                                    max=endFrame,
                                    width=6)

        numFrames = endFrame - startFrame + 1
        defStride = 1 + int(numFrames / 300)
        self.stride = IntOption(self.clientArea,
                                2,
                                "Step size",
                                defStride,
                                None,
                                min=1,
                                max=numFrames,
                                width=3)

        self.endFrame = IntOption(self.clientArea,
                                  3,
                                  "Ending frame",
                                  endFrame,
                                  None,
                                  min=startFrame,
                                  max=endFrame,
                                  width=6)

        self.roundtrip = BooleanOption(
            self.clientArea,
            4, "Encode"
            ' forward then backward ("roundtrip")',
            prefs[RECORDER_ROUNDTRIP],
            None,
            balloon="Encode the frames in forward and then reverse\n"
            "order so that if the movie is played as a loop\n"
            "the motion seems continuous")

        class FrameQuality(BooleanOption):
            labels = ["screen", "supersampled"]

        self.supersample = FrameQuality(
            self.clientArea,
            5,
            "Frame quality",
            prefs[RECORDER_SUPERSAMPLE],
            self.supersampleCB,
            balloon="Whether each frame should be taken as is from\n"
            "the screen (fast) or redrawn at higher quality\n"
            "with several samples per pixel.")

        from chimera.printer import SupersampleOption
        self.samples = SupersampleOption(self.clientArea, 6, "Samples",
                                         prefs[RECORDER_SAMPLES], None)
        self.supersampleCB()

        self.raytrace = BooleanOption(self.clientArea, 7, "Raytrace"
                                      " with POV-Ray",
                                      prefs[RECORDER_RAYTRACE], None)

        def povOptCB():
            from chimera.dialogs import display
            d = display("preferences")
            from chimera.printer import POVRAY_SETUP
            d.setCategoryMenu(POVRAY_SETUP)

        Tkinter.Button(self.clientArea,
                       text="POV-Ray Options",
                       pady=0,
                       command=povOptCB).grid(row=8, column=0, columnspan=2)

        self.recordArgs = StringOption(
            self.clientArea,
            9,
            "Additional recording options",
            prefs[RECORDER_RECORD_ARGS],
            None,
            balloon="Options (other than 'supersample' and 'raytrace')\n"
            "for recording frames as per Chimera's 'movie record'"
            " command")

        self.encodeArgs = StringOption(
            self.clientArea,
            10,
            "Additional encoding options",
            prefs[RECORDER_ENCODE_ARGS],
            None,
            balloon="Options (other than 'mformat', 'output', and\n"
            "'roundtrip') for composing the frames into the\n"
            "final animation as per Chimera's 'movie encode'\n"
            "command")

        Tkinter.Label(self.clientArea,
                      text="On some computers it may be necessary to make sure"
                      " that no\nwindows occlude the main Chimera graphics"
                      " window (even\npartially) during non-raytraced movie"
                      " recording").grid(row=11, column=0, columnspan=2)
예제 #20
0
class VolumeDialog(ModelessDialog):
	title = "Calculate Atomic Occupancy"
	help = "ContributedSoftware/movie/movie.html#occupancy"
	provideStatus = True
	statusPosition = "left"
	buttons = ('OK', 'Close')
	default= 'OK'

	def __init__(self, movie):
		self.movie = movie
		movie.subdialogs.append(self)
		ModelessDialog.__init__(self)

	def map(self, e=None):
		if not self.movie.holdingSteady:
			self.status("No atoms being held steady -- see Help",
							color="red")
	def fillInUI(self, parent):
		Tkinter.Label(parent, text="Collect positions of selected"
			" atoms over trajectory", relief="ridge", bd=4).grid(
			row=0, column=0, columnspan=2, sticky="ew")

		startFrame = self.movie.startFrame
		endFrame = self.movie.endFrame
		from chimera.tkoptions import IntOption, BooleanOption, \
						FloatOption, StringOption
		self.startFrame = IntOption(parent, 1, "Starting frame",
			startFrame, None, min=startFrame, max=endFrame, width=6)

		numFrames = endFrame - startFrame + 1
		defStride = 1 + int(numFrames/300)
		self.stride = IntOption(parent, 2, "Step size", defStride,
			None, min=1, max=numFrames, width=3)

		self.endFrame = IntOption(parent, 3, "Ending frame", endFrame,
			None, min=startFrame, max=endFrame, width=6)

		self.doCutoff = BooleanOption(parent, 4, 'Limit data collection'
			' to within cutoff distance of any "held steady" atoms',
			True, None)

		self.cutoff = FloatOption(parent, 5, "Cutoff distance",
				prefs[VOLUME_CUTOFF], None, width=4)
		self.resolution = FloatOption(parent, 6, "Volume grid spacing",
			prefs[VOLUME_RESOLUTION], None, min=0.0001, width=4)
		self.volumeName = StringOption(parent, 7, "Volume data name",
			self.movie.ensemble.name, None, width=20)
		self.byAtomType = BooleanOption(parent, 8, "Collect data"
			" separately for each atom type in selection",
			True, None, balloon="Create a volume data set for"
			" each type of atom type\n(sp2 oxygen, aromatic carbon,"
			" etc.) in current selection")

	def Apply(self):
		from chimera import UserError
		atoms = chimera.selection.currentAtoms()
		if not atoms:
			self.enter()
			raise UserError("No atoms selected")
		startFrame = self.startFrame.get()
		endFrame = self.endFrame.get()
		if endFrame <= startFrame:
			self.enter()
			raise UserError("Start frame must be less"
							" than end frame")
		if startFrame < self.movie.startFrame \
		or endFrame > self.movie.endFrame:
			self.enter()
			raise UserError("Start or end frame outside"
							" of trajectory")
		if self.doCutoff.get():
			bound = prefs[VOLUME_CUTOFF] = self.cutoff.get()
		else:
			bound = None
		prefs[VOLUME_RESOLUTION] = self.resolution.get()
		step = self.stride.get()
		spacing = self.resolution.get()
		name = self.volumeName.get()
		atomTypes = {}
		if self.byAtomType.get():
			for a in atoms:
				atomTypes.setdefault(a.idatmType, []).append(a)
		if len(atomTypes) > 1:
			for atomType, atAtoms in atomTypes.items():
				self.movie.computeVolume(atAtoms,
					startFrame=startFrame,
					endFrame=endFrame, step=step,
					bound=bound, spacing=spacing,
					volumeName=name+" ["+atomType+"]")
		else:
			self.movie.computeVolume(atoms, startFrame=startFrame,
				endFrame=endFrame, step=step, bound=bound,
				spacing=spacing, volumeName=name)
class RmsdStarter(ModelessDialog):
    title = "Get RMSD Map Parameters"
    help = "ContributedSoftware/movie/movie.html#rmsd"

    def __init__(self, movie):
        self.movie = movie
        movie.subdialogs.append(self)
        ModelessDialog.__init__(self)

    def fillInUI(self, parent):
        from chimera.tkoptions import IntOption, BooleanOption, \
             FloatOption
        Tkinter.Label(parent,
                      text="Create RMSD map of trajectory "
                      "against itself",
                      relief="ridge",
                      bd=4).grid(row=0, column=0, columnspan=2, sticky="ew")

        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        self.startFrame = IntOption(parent,
                                    1,
                                    "Starting frame",
                                    startFrame,
                                    None,
                                    min=startFrame,
                                    max=endFrame,
                                    width=6)

        numFrames = endFrame - startFrame + 1
        defStride = 1 + int(numFrames / 300)
        self.stride = IntOption(parent,
                                2,
                                "Step size",
                                defStride,
                                None,
                                min=1,
                                max=numFrames,
                                width=3)

        self.endFrame = IntOption(parent,
                                  3,
                                  "Ending frame",
                                  endFrame,
                                  None,
                                  min=startFrame,
                                  max=endFrame,
                                  width=6)

        self.minRmsd = FloatOption(parent,
                                   4, "Lower RMSD threshold"
                                   " (white)",
                                   prefs[RMSD_MIN],
                                   None,
                                   width=6)
        self.maxRmsd = FloatOption(parent,
                                   5, "Upper RMSD threshold"
                                   " (black)",
                                   prefs[RMSD_MAX],
                                   None,
                                   width=6)

        self.useSel = BooleanOption(
            parent, 6, "Restrict map to "
            "current selection, if any", True, None)

        self.ignoreBulk = BooleanOption(parent, 7, "Ignore solvent/"
                                        "ions", True, None)
        self.ignoreHyds = BooleanOption(parent, 8, "Ignore hydrogens", True,
                                        None)
        self.recolor = BooleanOption(parent, 9, "Auto-recolor for"
                                     " contrast", prefs[RMSD_AUTOCOLOR], None)

    def Apply(self):
        startFrame = self.startFrame.get()
        stride = self.stride.get()
        if (len(self.movie.ensemble) - (startFrame - 1)) / stride > 1000:
            dlg = AskYesNoDialog("RMSD map will be %d pixels wide"
                                 " and tall. Okay?")
            if dlg.run(self.uiMaster()) == "no":
                self.enter()
                return
        endFrame = self.endFrame.get()
        if endFrame <= startFrame:
            self.enter()
            raise UserError("Start frame must be less" " than end frame")
        if startFrame < self.movie.startFrame \
        or endFrame > self.movie.endFrame:
            self.enter()
            raise UserError("Start or end frame outside" " of trajectory")
        prefs[RMSD_MIN] = self.minRmsd.get()
        prefs[RMSD_MAX] = self.maxRmsd.get()
        prefs[RMSD_AUTOCOLOR] = self.recolor.get()
        RmsdMapDialog(self.movie, startFrame, self.stride.get(), endFrame,
                      self.useSel.get(), prefs[RMSD_MIN], prefs[RMSD_MAX],
                      self.ignoreBulk.get(), self.ignoreHyds.get(),
                      prefs[RMSD_AUTOCOLOR])
예제 #22
0
class Interface(ModelessDialog):

	title = "Model Loops with Modeller"
	buttons = ("OK", "Cancel")
	help = "ContributedSoftware/model/model.html"

	def __init__(self, *args, **kw):
		ModelessDialog.__init__(self, *args, **kw)
		# TODO: initialize instance variables

	def fillInUI(self, parent):
		from chimera.widgets import MoleculeOptionMenu
		from chimera.tkoptions import IntOption, BooleanOption, \
				InputFileOption, StringOption, EnumOption
		import itertools
		info = Tk.Label(parent, justify=Tk.LEFT, wraplength=300, text=
				"Model alternate conformations of loops using "
				"Modeller from <http://salilab.org/>.\n"
				"First select the loops you wish to model."
				"  Then choose the number of models "
				"you wish to generate.")
		info.pack(ipadx=2, ipady=2)
		options = Tk.Frame(parent)
		options.columnconfigure(0, pad=2)
		options.columnconfigure(1, pad=2)
		row = itertools.count()
		molRow = row.next()
		text = Tk.Label(options,
				text="Restrict selections to molecule:")
		text.grid(row=molRow, column=0)
		self.molecules = MoleculeOptionMenu(options)
		self.molecules.grid(row=molRow, column=1, sticky=Tk.W)
		self.turnsOnly = BooleanOption(options, row.next(),
				"Restrict selections to turns", True, None)
		self.hetatms = BooleanOption(options, row.next(),
				"Include HETATM residues", False, None)
		self.waters = BooleanOption(options, row.next(),
				"Include waters", False, None)
		self.waters.disable()
		self.nucleic = BooleanOption(options, row.next(),
				"Include nucleic acids", False, None)
		self.nucleic.disable()
		self.count = IntOption(options, row.next(), "Number of models",
				10, None, min=1, sticky=Tk.W)
		#self.start = IntOption(options, row.next(),
		#		"Starting model number", 1, None, min=0)
		class Refinement(EnumOption):
			values = ('very fast', 'fast', 'slow', 'very slow',
				'slow large', 'none')
		self.refine = Refinement(options, row.next(), "Refinement",
								'fast', None)
		button = Tk.Button(options, text="Prune selection",
				command=self.prune)
		button.grid(row=row.next(), column=0, columnspan=2, pady=2)
		self.start = 1
		hr = Tk.Frame(options, relief=Tk.GROOVE, borderwidth=1, height=2)
		hr.grid(row=row.next(), columnspan=2, sticky='ew')
		# modeller location
		self.modeller = InputFileOption(options, row.next(),
				"Modeller location", "mod9v2", None)
		# temporary prefix -- TODO: add unique id
		#self.tempdir = StringOption(options, row.next(),
		#		"Temporary file prefix", "modtmp", None)
		options.pack()

	def prune(self):
		from chimera import selection
		molecule = self.molecules.getvalue()
		import ModUtil
		pairs, residues = ModUtil.convertSelection(
				selection._currentSelection,
				minLen=4, molecule=molecule,
				keepHet=self.hetatms.get(),
				keepNA=self.nucleic.get(),
				turnsOnly=self.turnsOnly.get())
		sel = selection.ItemizedSelection()
		sel.add(residues)
		sel.addImplied()
		selection.mergeCurrent(selection.INTERSECT, sel)
		return pairs, residues

	def Apply(self):
		pairs, residues = self.prune()
		if not pairs:
			from chimera import replyobj
			replyobj.status("no residues meet loop modelling criteria")
			return

		# create a temporary directory to work in
		import tempfile
		tempdir = tempfile.mkdtemp(prefix="modeller")
		print 'Modeller temporary directory:', tempdir

		# write PDB file with original coordinates
		import os
		fname = os.path.join(tempdir, 'original.pdb')
		molecule = self.molecules.getvalue()
		xform = molecule.openState.xform
		xform.invert()	# want original coordinates
		chimera.viewer.pdbWrite([molecule], xform, fname)
		# write out Modeller input file
		count = self.count.get()
		refine = self.refine.get()
		fname = os.path.join(tempdir, "loopopt.py")
		f = file(fname, 'w')
		writeModeller(f, 'original.pdb', 'loop', pairs, count, refine)
		f.close()

		#  run Modeller -- put up progress dialog
		import ModUtil
		def cb(process, dirname=tempdir, count=count):
			return loopFileCount(dirname, count)
		try:
			prog = self.modeller.get()
			p = ModUtil.run([prog, "loopopt.py"], cb, cwd=tempdir)
		except OSError, e:
			from chimera import replyobj
			replyobj.error("Unable to run modeller: %s\n" % e)
			return

		# Do concurrent work here

		# find atoms that are connected to the residues we will model
		atoms = set()
		for r in residues:
			for a in r.atoms:
				atoms.add(a)
		outsideAtoms = set()
		for a in atoms:
			for b in a.bonds:
				oa = b.otherAtom(a)
				if oa.residue not in residues:
					outsideAtoms.add(oa)
		outsideAtoms = [(a.residue.id, a.name) for a in outsideAtoms]

		residueIds = set([r.id for r in residues])

		# TODO: use triggers to monitor process
		# and then startup dock interface
		# For now, we just wait
		returncode = p.wait()
		if returncode != 0:
			from chimera import replyobj
			replyobj.error("Modeller failed\n")
			return

		# create ViewDock input file from output files
		path = makedock(tempdir, residueIds, outsideAtoms)
		if not path:
			from chimera import replyobj
			replyobj.error("No models were generated\n")
			return

		# undisplay selected residues
		for r in residues:
			for a in r.atoms:
				a.display = False

		# startup dock
		import ViewDock
		v = ViewDock.ViewDock(path, 'Modeller')

		# remove long bonds since makedock can't put TERs
		# from both the model and the "longbond" PseudoBondGroup
		models = [c.chimeraModel for c in v.results.compoundList]
		length = 3
		sqLen = length * length
		for m in models:
			for b in m.bonds:
				if b.sqlength() >= sqLen:
					# get rid of longbond PseudoBonds
					a0, a1 = b.atoms
					pbs = a0.associations(
						chimera.LONGBOND_PBG_NAME, a1)
					for pb in pbs:
						pb.pseudoBondGroup.deletePseudoBond(pb)
					# get rid of bond
					m.deleteBond(b)
예제 #23
0
class EspDialog(ModelessDialog):
    title = "Coulombic Surface Coloring"
    name = "ESP computation"
    help = "ContributedSoftware/coulombic/coulombic.html"

    HB = "estimated from H-bonds"

    def fillInUI(self, parent):
        import Pmw, Tkinter
        self.buttonWidgets['OK']['state'] = 'disabled'
        self.buttonWidgets['Apply']['state'] = 'disabled'
        from chimera.widgets import ModelScrolledListBox
        self.surfListBox = ModelScrolledListBox(
            parent,
            labelpos='n',
            label_text='Surfaces to color by ESP:',
            listbox_selectmode="extended",
            filtFunc=lambda m: isinstance(m, chimera.MSMSModel),
            selectioncommand=self._selSurfCB)
        self.surfListBox.grid(row=0, column=0, sticky="nsew", columnspan=2)
        Pmw.OptionMenu(parent,
                       command=self._menuCB,
                       initialitem="3",
                       items=[str(x) for x in range(2, 12)],
                       labelpos='w',
                       label_text="Number of colors/values:").grid(
                           row=1, column=0, columnspan=2)
        f = self.interpFrame = Tkinter.Frame(parent)
        f.grid(row=2, column=0, columnspan=2)
        self.wells = []
        self.values = []
        self._entryOpts = {
            'validate': 'real',
            'entry_justify': 'center',
            'entry_width': 6
        }
        from CGLtk.color.ColorWell import ColorWell
        for color, value in [("red", -10), ("white", 0), ("blue", 10)]:
            well = ColorWell(f, color=color)
            well.grid(row=0, column=len(self.wells))
            self.wells.append(well)
            entry = Pmw.EntryField(f, value=str(value), **self._entryOpts)
            entry.grid(row=1, column=len(self.values))
            self.values.append(entry)

        from chimera.tkoptions import FloatOption, BooleanOption
        self.distDep = BooleanOption(
            parent,
            3,
            "Distance-dependent dielectric",
            True,
            None,
            balloon="If true, charge falls off with distance squared to\n"
            "simulate solvent screening effects")
        self.dielectric = FloatOption(parent, 4, "Dielectric constant", 4.0,
                                      None)
        self.surfDist = FloatOption(parent,
                                    5,
                                    "Distance from surface",
                                    1.4,
                                    None,
                                    balloon="Potential at this distance from\n"
                                    "the surface is used for coloring")

        self.hisGroup = Pmw.Group(parent,
                                  hull_padx=2,
                                  tag_text="Implicit Histidine Protonation")
        self.hisGroup.grid(row=6, column=0, columnspan=2, sticky="nsew")
        self.hisProtVar = Tkinter.StringVar(parent)
        self.hisProtVar.set("name")
        interior = self.hisGroup.interior()
        interior.columnconfigure(0, weight=1)
        lab = Tkinter.Label(
            interior,
            text="Assumed histidine "
            "protonation for\nstructures without explicit hydrogens")
        from tkFont import Font
        font = Font(font=lab.cget('font'))
        font.config(size=int(0.75 * float(font.cget('size'))), slant='italic')
        lab.config(font=font)
        lab.grid(row=0)
        Tkinter.Radiobutton(interior,
                            variable=self.hisProtVar,
                            value="name",
                            text="Residue name-based",
                            command=self._switchHisList).grid(row=1,
                                                              sticky='w')
        f = Tkinter.Frame(interior)
        f.grid(row=2)
        Tkinter.Label(f,
                      text="HID/HIE/HIP = delta/epsilon/both").grid(row=0,
                                                                    sticky='w')
        self.hisDefault = Pmw.OptionMenu(
            f,
            initialitem=self.HB,
            items=[self.HB, "delta", "epsilon", "both"],
            labelpos='w',
            label_text="HIS = ",
            command=lambda a, s=self: setattr(s, 'hisChanged', True))
        self.hisDefault.grid(row=1, sticky='w')
        self._pickText = Tkinter.StringVar(parent)
        self._pickText.set("Specified individually...")
        Tkinter.Radiobutton(interior,
                            variable=self.hisProtVar,
                            value="pick",
                            textvariable=self._pickText,
                            command=self._switchHisList).grid(row=3,
                                                              sticky='w')

        Tkinter.Button(parent,
                       pady=0,
                       command=self._colorKeyCB,
                       text="Create corresponding color key").grid(
                           row=7, column=0, columnspan=2)
        self.hisChanged = False

    def Apply(self):
        for entry in self.values:
            entry.invoke()
        colors = [w.rgba for w in self.wells]
        values = [float(e.getvalue()) for e in self.values]
        if self.hisProtVar.get() == "name":
            hisScheme = {
                self.HB: None,
                'delta': 'HID',
                'epsilon': 'HIE',
                'both': 'HIP'
            }[self.hisDefault.getvalue()]
        else:
            hisScheme = self.hisListingData
        from ESP import colorEsp
        for surf in self.surfListBox.getvalue():
            if self.hisChanged:
                # clear out charge values so that histidines
                # get new charges
                for a in surf.atoms:
                    a.charge = None
            colorEsp(surf,
                     colors,
                     values,
                     dielectric=self.dielectric.get(),
                     distDep=self.distDep.get(),
                     surfDist=self.surfDist.get(),
                     hisScheme=hisScheme)
        self.hisChanged = False

    def _colorKeyCB(self):
        for entry in self.values:
            entry.invoke()
        from Ilabel.gui import IlabelDialog
        from chimera import dialogs
        d = dialogs.display(IlabelDialog.name)
        d.keyConfigure(
            zip([w.rgba for w in self.wells],
                [e.getvalue() for e in self.values]))

    def _menuCB(self, val):
        newNum = int(val)
        oldSettings = []
        for well, entry in zip(self.wells, self.values):
            entry.invoke()
            oldSettings.append((well.rgba, float(entry.getvalue())))
            well.grid_forget()
            well.destroy()
            entry.grid_forget()
            entry.destroy()
        import Pmw
        from CGLtk.color.ColorWell import ColorWell
        self.wells = []
        self.values = []
        scale = (len(oldSettings) - 1.0) / (newNum - 1.0)
        f = self.interpFrame
        for i in range(newNum):
            index = i * scale
            if index == int(index) \
            or int(index) >= len(oldSettings):
                color, value = oldSettings[int(index)]
            else:
                lowc, lowv = oldSettings[int(index)]
                highc, highv = oldSettings[int(index) + 1]
                frac = index - int(index)
                color = []
                for lowcomp, highcomp in zip(lowc, highc):
                    color.append((1.0 - frac) * lowcomp + frac * highcomp)
                value = (1.0 - frac) * lowv + frac * highv
            well = ColorWell(f, color=color)
            well.grid(row=0, column=len(self.wells))
            self.wells.append(well)
            entry = Pmw.EntryField(f, value=str(value), **self._entryOpts)
            entry.grid(row=1, column=len(self.values))
            self.values.append(entry)

    def _selSurfCB(self):
        if self.surfListBox.getvalue():
            state = 'normal'
        else:
            state = 'disabled'
        self.buttonWidgets['OK']['state'] = state
        self.buttonWidgets['Apply']['state'] = state

        self._updateHisListing()

    def _select(self, hisType):
        for r, vars in self._vars.items():
            dv, ev = vars
            if hisType == "delta":
                dv.set(True)
                ev.set(False)
                self.hisListingData[r] = "HID"
            elif hisType == "epsilon":
                dv.set(False)
                ev.set(True)
                self.hisListingData[r] = "HIE"
            else:
                dv.set(True)
                ev.set(True)
                self.hisListingData[r] = "HIP"

    def _switchHisList(self):
        self.hisChanged = True
        if not hasattr(self, 'hisListing'):
            if self.hisProtVar.get() != "pick":
                return
            self.hisListingData = {}
            import Tix, Tkinter
            self.hisFrame = Tkinter.Frame(self.hisGroup.interior())
            self.hisListing = Tix.ScrolledHList(self.hisFrame,
                                                width="3i",
                                                options="""hlist.columns 4
						hlist.header 1
						hlist.indicator 1""")
            self.hisListing.hlist.configure(
                selectbackground=self.hisListing['background'],
                selectborderwidth=0)
            self.hisListing.grid(row=0, column=0, columnspan=3, sticky="nsew")
            self.hisFrame.rowconfigure(1, weight=1)
            self.hisFrame.columnconfigure(0, weight=1)
            self.hisFrame.columnconfigure(1, weight=1)
            hlist = self.hisListing.hlist
            hlist.header_create(0, itemtype="text", text="Model")
            hlist.header_create(1, itemtype="text", text="Residue")
            hlist.header_create(2, itemtype="text", text="Delta")
            hlist.header_create(3, itemtype="text", text="Epsilon")
            self._checkButtonStyle = Tix.DisplayStyle(
                "window",
                background=hlist['background'],
                refwindow=self.hisListing,
                anchor='center')
            self._updateHisListing()

            Tkinter.Button(self.hisFrame,
                           text="All Delta",
                           pady=0,
                           highlightthickness=0,
                           command=lambda p="delta": self._select(p)).grid(
                               row=1, column=0)
            Tkinter.Button(self.hisFrame,
                           text="All Epsilon",
                           pady=0,
                           highlightthickness=0,
                           command=lambda p="epsilon": self._select(p)).grid(
                               row=1, column=1)
            Tkinter.Button(self.hisFrame,
                           text="All Both",
                           pady=0,
                           highlightthickness=0,
                           command=lambda p="both": self._select(p)).grid(
                               row=1, column=2)

        if self.hisProtVar.get() == "pick":
            self._pickText.set("Specified individually:")
            self.hisFrame.grid(row=4, sticky="nsew")
            interior = self.hisGroup.interior()
            interior.rowconfigure(4, weight=1)
            self.uiMaster().rowconfigure(6, weight=4)
        else:
            self._pickText.set("Specified individually...")
            self.hisFrame.grid_forget()
            interior = self.hisGroup.interior()
            interior.rowconfigure(4, weight=0)
            self.uiMaster().rowconfigure(6, weight=0)

    def _toggleDelta(self, res):
        self.hisChanged = True
        old = self.hisListingData[res]
        if old == "HIS":
            new = "HID"
        elif old == "HID":
            new = "HIS"
        elif old == "HIE":
            new = "HIP"
        else:
            new = "HIE"
        self.hisListingData[res] = new

    def _toggleEpsilon(self, res):
        self.hisChanged = True
        old = self.hisListingData[res]
        if old == "HIS":
            new = "HIE"
        elif old == "HID":
            new = "HIP"
        elif old == "HIE":
            new = "HIS"
        else:
            new = "HID"
        self.hisListingData[res] = new

    def _updateHisListing(self):
        if not hasattr(self, 'hisListing'):
            return
        self._updateHisListingData()
        hlist = self.hisListing.hlist
        on = self.hisListing.tk.call('tix', 'getimage', 'ck_on')
        off = self.hisListing.tk.call('tix', 'getimage', 'ck_off')
        hlist.delete_all()
        import Tkinter
        row = 0
        self._vars = {}
        for m in [s.molecule for s in self.surfListBox.getvalue()]:
            for r in m.residues:
                try:
                    hisType = self.hisListingData[r]
                except KeyError:
                    continue
                hlist.add(row,
                          itemtype="text",
                          text="%s (%s)" % (m.name, m.oslIdent()))
                hlist.item_create(row,
                                  1,
                                  itemtype="text",
                                  text=r.oslIdent(start=chimera.SelResidue))
                var = Tkinter.IntVar(hlist)
                var.set(hisType in ["HID", "HIP"])
                cmd = lambda r=r: self._toggleDelta(r)
                self._vars[r] = [var]
                toggle = Tkinter.Checkbutton(hlist,
                                             command=cmd,
                                             variable=var,
                                             image=off,
                                             selectimage=on,
                                             selectcolor="",
                                             indicatoron=False,
                                             borderwidth=0)
                hlist.item_create(row,
                                  2,
                                  itemtype="window",
                                  window=toggle,
                                  style=self._checkButtonStyle)
                var = Tkinter.IntVar(hlist)
                var.set(hisType in ["HIE", "HIP"])
                cmd = lambda r=r: self._toggleEpsilon(r)
                self._vars[r].append(var)
                toggle = Tkinter.Checkbutton(hlist,
                                             command=cmd,
                                             variable=var,
                                             image=off,
                                             selectimage=on,
                                             selectcolor="",
                                             indicatoron=False,
                                             borderwidth=0)
                hlist.item_create(row,
                                  3,
                                  itemtype="window",
                                  window=toggle,
                                  style=self._checkButtonStyle)
                row += 1

    def _updateHisListingData(self):
        newData = {}
        default = {
            'delta': 'HID',
            'epsilon': 'HIE',
            'both': 'HIP',
            self.HB: 'HID'
        }[self.hisDefault.getvalue()]
        for m in [s.molecule for s in self.surfListBox.getvalue()]:
            for r in m.residues:
                if r.type not in ["HIS", "HIE", "HIP", "HID"]:
                    continue
                try:
                    newData[r] = self.hisListingData[r]
                except KeyError:
                    if r.type == 'HIS':
                        newData[r] = default
                    else:
                        newData[r] = r.type
        self.hisListingData = newData
예제 #24
0
class Interface(ModelessDialog):

	title = 'Nucleotides'
	help = "ContributedSoftware/nucleotides/nucleotides.html"
	buttons = ("NDB Colors",) + ModelessDialog.buttons
	provideStatus = True

	def __init__(self, *args, **kw):
		self.currentStyle = self.saveui_defaultItem()
		ModelessDialog.__init__(self, *args, **kw)
		self.__firstcanvas = True

	def fillInUI(self, parent):
		parent.columnconfigure(0, pad=2)
		parent.columnconfigure(1, pad=2)
		import itertools
		row = itertools.count()

		self.showBackbone = BackboneOption(parent, row.next(),
					'Show backbone as', 'ribbon', None)
		self.showSide = SideOption(parent, row.next(),
				'Show side (sugar/base) as', 'fill/slab',
				self._showSideCB)
		self.showOrientation = BooleanOption(parent, row.next(),
				'Show base orientation', default.ORIENT, None)

		import Tix
		self.nb = Tix.NoteBook(parent)
		self.nb.grid(row=row.next(), column=0, columnspan=2, sticky=Tk.EW, padx=2)

		# ladder page
		self.nb.add("ladder", label="Ladder Options")
		f = self.nb.page("ladder")
		if Tk.TkVersion >= 8.5:
			parent.tk.call('grid', 'anchor', f._w, Tk.N)

		prow = itertools.count()
		self.skipNonBase = BooleanOption(f, prow.next(),
				'Ignore non-base H-bonds', default.IGNORE, None)
		self.showStubs = BooleanOption(f, prow.next(),
					'Show stubs', default.STUBS, None)
		self.rungRadius = FloatOption(f, prow.next(), 'Rung radius',
							default.RADIUS, None)
		self.rungRadius.min = 0.0
		self.useExisting = BooleanOption(f, prow.next(),
			'Using existing H-bonds', default.USE_EXISTING,
			self._useExistingCB)
		from FindHBond.gui import RelaxParams
		self.relaxParams = RelaxParams(f, None, colorOptions=False)
		#self.relaxParams.relaxConstraints = False
		self.relaxParams.grid(row=prow.next(), columnspan=2,
							sticky='nsew', padx=2)

		# slab page
		self.nb.add("slab", label="Slab Options")
		f = self.nb.page("slab")
		if Tk.TkVersion >= 8.5:
			parent.tk.call('grid', 'anchor', f._w, Tk.N)

		prow = itertools.count()
		self.thickness = FloatOption(f, prow.next(), 'Thickness',
						default.THICKNESS, None)
		self.thickness.min = 0.01
		self.shape = ShapeOption(f, prow.next(), 'Slab object',
							default.SHAPE, None)
		self.hideBases = BooleanOption(f, prow.next(),
					'Hide base atoms', default.HIDE, None)
		self.showGlycosidic = BooleanOption(f, prow.next(),
				'Separate glycosidic bond', default.GLYCOSIDIC,
				None)

		self.nb.add("style", label="Slab Style", raisecmd=self.map)
		# style page
		f = self.nb.page("style")
		if Tk.TkVersion >= 8.5:
			f.tk.call('grid', 'anchor', f._w, Tk.N)

		info = NA.findStyle(self.currentStyle)
		from chimera.preferences import saveui
		f2 = Tk.Frame(f)
		self.saveui = saveui.SaveUI(f2, self)
		f2.grid(row=prow.next(), column=0, columnspan=2, sticky=Tk.EW,
								padx=2, pady=2)

		self.anchor = AnchorOption(f, prow.next(), 'Anchor',
					info[NA.ANCHOR], self._drawStyle)

		f2 = Pmw.Group(f, tag_text=NA.PURINE.title())
		f2.grid(row=prow.next(), column=0, columnspan=2, sticky=Tk.EW,
									padx=2)
		f2 = f2.interior()
		f2.columnconfigure(0, weight=1, pad=2, uniform='a')
		f2.columnconfigure(1, weight=1, uniform='a')
		f2.columnconfigure(2, weight=1)

		self.purine_canvas = Tk.Canvas(f2, width=1, height=1) #,
						#borderwidth=2, relief=Tk.RIDGE)
		r = prow.next()
		self.purine_canvas.grid(row=r, column=0, rowspan=3,
						sticky=Tk.NSEW, padx=2, pady=2)
		corners = info[NA.PURINE]
		self.puLL = Float2Option(f2, prow.next(), 'Lower left',
					corners[0], self._drawStyle, startCol=1)
		self.puUR = Float2Option(f2, prow.next(), 'Upper right',
					corners[1], self._drawStyle, startCol=1)

		f3 = Pmw.Group(f, tag_text="%s, %s" % (NA.PYRIMIDINE.title(),
						NA.PSEUDO_PYRIMIDINE.title()))
		r = prow.next()
		f3.grid(row=r, column=0, columnspan=2, sticky=Tk.EW, padx=2)
		f3 = f3.interior()
		f3.columnconfigure(0, weight=1, pad=2, uniform='a')
		f3.columnconfigure(1, weight=1, uniform='a')
		f3.columnconfigure(2, weight=1)

		self.pyrimidine_canvas = Tk.Canvas(f3, width=1, height=1) #,
						#borderwidth=2, relief=Tk.RIDGE)
		r = prow.next()
		self.pyrimidine_canvas.grid(row=r, column=0, rowspan=3,
						sticky=Tk.NSEW, padx=2, pady=2)

		corners = info[NA.PYRIMIDINE]
		self.pyLL = Float2Option(f3, prow.next(), 'Lower left',
					corners[0], self._drawStyle, startCol=1)
		self.pyUR = Float2Option(f3, prow.next(), 'Upper right',
					corners[1], self._drawStyle, startCol=1)

		self.restrict = Tk.IntVar(parent)
		self.restrict.set(1)
		cb = Tk.Checkbutton(parent, variable=self.restrict,
		    text="Restrict OK/Apply to current selection, if any")
		cb.grid(row=row.next(), columnspan=2)

		parent.pack(ipady=2)

		self._showSideCB()
		chimera.triggers.addHandler(NA.TRIGGER_SLAB_STYLES,
						self._updateStyles, None)

	def map(self, event=None):
		# need to update_idletasks so canvases in grid will have a size
		page = self.nb.raised()
		if page == 'style':
			if self.__firstcanvas:
				self.uiMaster().update_idletasks()
				self._drawStyle()
				self.__firstcanvas = False

	def _updateStyles(self, trigger, closure, arg):
		# pick up programmic changes in list of slab styles
		self.saveui.updateComboList()

	def saveui_label(self):
		return "Slab Style"

	def saveui_presetItems(self):
		return NA.SystemStyles.keys()

	def saveui_userItems(self):
		return NA.userStyles.keys()

	def saveui_defaultItem(self):
		return 'long'

	def saveui_select(self, name):
		self.currentStyle = name
		self._setSlabStyle(name)

	def saveui_save(self, name):
		info = self._getInfo()
		NA.addStyle(name, info)
		self.status("Slab style \"%s\" saved" % name)
		return True	# successful

	def saveui_delete(self, name):
		NA.removeStyle(name)
		self.status("Slab style \"%s\" deleted" % name)
		return True	# successful

	def _showSideCB(self, *args):
		side = self.showSide.get()
		hasSlab = 'slab' in side
		if side.startswith('fill') or hasSlab:
			self.showOrientation.enable()
		else:
			self.showOrientation.disable()
		if hasSlab:
			self.nb.raise_page('slab')
		elif side == 'ladder':
			self.nb.raise_page('ladder')
		if side == 'tube/slab':
			# tube connects to C1' if no slab
			# if slab, it goes to the middle of slab
			self.showGlycosidic.enable()
			return
		self.showGlycosidic.disable()

	def _useExistingCB(self, *args):
		useExisting = self.useExisting.get()
		if useExisting:
			self.relaxParams.disable()
		else:
			self.relaxParams.enable()

	def Apply(self):
		from chimera import selection
		if not self.restrict.get() or selection.currentEmpty():
			molecules = chimera.openModels.list(
						modelTypes=[chimera.Molecule])
			residues = []
			for mol in molecules:
				residues.extend(mol.residues)
		else:
			residues = selection.currentResidues()
			molecules = tuple(set(r.molecule for r in residues))
		residues = [r for r in residues
					if r.ribbonResidueClass.isNucleic()]

		backbone = self.showBackbone.get()
		display = backbone != 'atoms & bonds'
		for r in residues:
			r.ribbonDisplay = display

		side = self.showSide.get()
		if side == 'ladder':
			distSlop = 0.0
			angleSlop = 0.0
			relax = self.relaxParams.relaxConstraints
			if relax:
				distSlop = self.relaxParams.relaxDist
				angleSlop = self.relaxParams.relaxAngle
			NA.set_ladder(molecules, residues,
				rungRadius=self.rungRadius.get(),
				showStubs=self.showStubs.get(),
				skipNonBaseHBonds=self.skipNonBase.get(),
				useExisting=self.useExisting.get(),
				distSlop=distSlop, angleSlop=angleSlop)
			return
		if side.endswith('slab'):
			if self.currentStyle is None:
				info = self._getInfo()
				NA.addStyle(None, info)
			showGly = self.anchor.get() != NA.SUGAR
			if showGly and side.startswith('tube'):
				showGly = self.showGlycosidic.get()
			NA.set_slab(side, molecules, residues,
				style=self.currentStyle,
				thickness=self.thickness.get(),
				orient=self.showOrientation.get(),
				shape=self.shape.get(), showGly=showGly,
				hide=self.hideBases.get())
		if side.startswith('fill'):
			for r in residues:
				r.fillDisplay = True
		else:
			for r in residues:
				r.fillDisplay = False
		if side.endswith('fill'):
			if self.showOrientation.get():
				NA.set_orient(molecules, residues)
			else:
				NA.set_normal(molecules, residues)
		elif side.startswith('atoms'):
			NA.set_normal(molecules, residues)
		return

	def _showBase(self, type, info, canvas):
		# assume height is greater than width
		# keep in mind, canvases are "left-handed", so y is inverted
		# get unique bases of given type
		unique_bases = {}
		for b in NA.standard_bases.values():
			if b['type'] == type:
				unique_bases[id(b)] = b
		# compute drawing parameters
		win_width = canvas.winfo_width()
		if win_width == 1:
			# no size assigned yet
			return
		win_height = canvas.winfo_height()

		# TODO: figure out how much room we really need for text
		if win_width < win_height:
			win_scale = .8 * win_width
		else:
			win_scale = .8 * win_height
		x_offset = .1 * win_width + 2	# 2==borderwidth
		if type == NA.PURINE:
			min = NA.purine_min
			max = NA.purine_max
			other = NA.pyrimidine_max[0] - NA.pyrimidine_min[0]
		elif type == NA.PYRIMIDINE:
			min = NA.pyrimidine_min
			max = NA.pyrimidine_max
			other = NA.purine_max[0] - NA.purine_min[0]
		width = max[0] - min[0]
		if other > width:
			width = other
		scale = win_scale / width
		# center vertically
		height = (max[1] - min[1]) * scale
		win_height -= (win_height - height) / 2

		# clear canvas
		canvas.addtag_all('all')
		canvas.delete('all')
		def cvt_coords(c):
			for i in range(0, len(c), 2):
				c[i] = (c[i] - min[0]) * scale + x_offset
				c[i + 1] = win_height \
					- (c[i + 1] - min[1]) * scale
				
		def draw_line(b, names):
			coords = []
			for n in names:
				c = b[n]
				coords += [c[0], c[1]]
			if len(names) > 2:
				# close line
				coords += coords[0:2]
			cvt_coords(coords)
			kw = {'width':2}
			canvas.create_line(*coords, **kw)
		c1p_coords = None
		for b in unique_bases.values():
			rn = b['ring atom names']
			draw_line(b, rn)
			for o in b['other bonds']:
				draw_line(b, o)
			if c1p_coords is None:
				c1p_coords = list(b["C1'"][0:2])
			else:
				coords = b["C1'"][0:2]
				if coords[0] < c1p_coords[0]:
					c1p_coords[0] = coords[0]
				if coords[1] > c1p_coords[1]:
					c1p_coords[1] = coords[1]
		corners = info[type]
		anchor = NA.anchor(info[NA.ANCHOR], type)
		offset = b[anchor]
		coords = [
			offset[0] + corners[0][0], offset[1] + corners[0][1],
			offset[0] + corners[1][0], offset[1] + corners[1][1]
		]
		cvt_coords(coords)
		kw = {'fill':'gray25', 'stipple':'gray25'}
		canvas.create_rectangle(*coords, **kw)
		coords = [min[0], max[1]]
		cvt_coords(c1p_coords)
		kw = {'text':" C1'", 'anchor':'s'}
		canvas.create_text(*c1p_coords, **kw)

	def _getInfo(self):
		info = {
			NA.ANCHOR: self.anchor.get(),
			NA.PURINE: (self.puLL.get(), self.puUR.get()),
			NA.PYRIMIDINE: (self.pyLL.get(), self.pyUR.get()),
			NA.PSEUDO_PYRIMIDINE: (self.pyLL.get(), self.pyUR.get())
		}
		return info

	def _drawStyle(self, *args):
		if args:
			self.saveui.setItemChanged(True)
			self.currentStyle = None

		# fill in parameters
		info = self._getInfo()

		# show bases
		self._showBase(NA.PURINE, info, self.purine_canvas)
		self._showBase(NA.PYRIMIDINE, info, self.pyrimidine_canvas)

	def _setSlabStyle(self, name):
		# make options reflect current style
		info = NA.findStyle(name)
		if not info:
			return
		self.currentStyle = name
		self.anchor.set(info[NA.ANCHOR])
		corners = info[NA.PURINE]
		self.puLL.set(corners[0])
		self.puUR.set(corners[1])
		corners = info[NA.PYRIMIDINE]
		self.pyLL.set(corners[0])
		self.pyUR.set(corners[1])
		self._drawStyle()

	def NDBColors(self):
		from chimera import selection
		if selection.currentEmpty():
			import Midas
			residues = Midas._selectedResidues('#')
		else:
			residues = selection.currentResidues()
		NA.NDBColors(residues)
예제 #25
0
    def _fillColorKeyPage(self, page):
        from chimera.tkoptions import IntOption, EnumOption, \
            BooleanOption, RGBAOption
        f = Tkinter.Frame(page)
        f.grid(row=0, columnspan=2)
        self.numComponents = IntOption(f,
                                       0,
                                       "Number of colors/labels",
                                       3,
                                       self._componentsCB,
                                       min=2,
                                       width=2)
        self.componentsFrame = Tkinter.Frame(page)
        self.componentsFrame.grid(row=1, column=0, sticky="nsew", columnspan=2)
        page.columnconfigure(0, weight=1)
        self.componentsFrame.columnconfigure(1, weight=1)

        class ColorTreatment(EnumOption):
            values = ("distinct", "blended")

        self.colorTreatment = ColorTreatment(
            page,
            2,
            "Color range depiction",
            "blended",
            self._keyChangeCB,
            balloon="Should colors be shown as distinct rectangles"
            " or as a continuous range")

        class LabelPosition(EnumOption):
            values = ("left/top", "right/bottom")

        self.labelPos = LabelPosition(
            page,
            3,
            "Label positions",
            "right/bottom",
            self._keyChangeCB,
            balloon="Position of"
            " labels relative to color key.\nLabels always"
            " positioned adjacent to long side.")
        self.labelColor = RGBAOption(
            page,
            4,
            "Label color",
            self._contrastWithBG(),
            self._keyChangeCB,
            balloob="Label color.  If set to 'No color', use corresponding"
            " key color",
            noneOkay=True)

        class LabelJustification(EnumOption):
            values = ("left", "decimal point", "right")

        self.justification = LabelJustification(
            page,
            5,
            "Label justification",
            "decimal point",
            self._keyChangeCB,
            balloon="Justification of label text"
            " in a vertical key layout.\nHorizontal key labels will"
            " always be center justified.")
        self.labelOffset = IntOption(page,
                                     6,
                                     "Label offset",
                                     0,
                                     self._keyChangeCB,
                                     width=3,
                                     balloon="Additional offset"
                                     " of labels from color bar, in pixels")
        self.keyFontSize = IntOption(page,
                                     7,
                                     "Font size",
                                     24,
                                     self._keyChangeCB,
                                     width=3)
        self.keyFontStyle = FontStyle(page, 8, "Font style", oglFont.normal,
                                      self._keyChangeCB)
        self.keyFontTypeface = FontTypeface(page, 9, "Font typeface",
                                            FONT_TYPEFACE_VALUES[0],
                                            self._keyChangeCB)
        self.borderColor = RGBAOption(
            page,
            10,
            "Border color",
            None,
            self._keyChangeCB,
            balloon="Color of border"
            " around color key (not each individual color).\n"
            "If 'no color', then no border is drawn.")
        self.borderWidth = IntOption(page,
                                     11,
                                     "Border width",
                                     3,
                                     self._keyChangeCB,
                                     balloon="in pixels")
        self.tickMarks = BooleanOption(page,
                                       12,
                                       "Show tick marks",
                                       False,
                                       self._keyChangeCB,
                                       balloon="Show tick marks"
                                       " pointing from key to labels")
        self._componentsCB(self.numComponents)
예제 #26
0
	def fillInUI(self, parent):
		parent.columnconfigure(0, pad=2)
		parent.columnconfigure(1, pad=2)
		import itertools
		row = itertools.count()

		self.showBackbone = BackboneOption(parent, row.next(),
					'Show backbone as', 'ribbon', None)
		self.showSide = SideOption(parent, row.next(),
				'Show side (sugar/base) as', 'fill/slab',
				self._showSideCB)
		self.showOrientation = BooleanOption(parent, row.next(),
				'Show base orientation', default.ORIENT, None)

		import Tix
		self.nb = Tix.NoteBook(parent)
		self.nb.grid(row=row.next(), column=0, columnspan=2, sticky=Tk.EW, padx=2)

		# ladder page
		self.nb.add("ladder", label="Ladder Options")
		f = self.nb.page("ladder")
		if Tk.TkVersion >= 8.5:
			parent.tk.call('grid', 'anchor', f._w, Tk.N)

		prow = itertools.count()
		self.skipNonBase = BooleanOption(f, prow.next(),
				'Ignore non-base H-bonds', default.IGNORE, None)
		self.showStubs = BooleanOption(f, prow.next(),
					'Show stubs', default.STUBS, None)
		self.rungRadius = FloatOption(f, prow.next(), 'Rung radius',
							default.RADIUS, None)
		self.rungRadius.min = 0.0
		self.useExisting = BooleanOption(f, prow.next(),
			'Using existing H-bonds', default.USE_EXISTING,
			self._useExistingCB)
		from FindHBond.gui import RelaxParams
		self.relaxParams = RelaxParams(f, None, colorOptions=False)
		#self.relaxParams.relaxConstraints = False
		self.relaxParams.grid(row=prow.next(), columnspan=2,
							sticky='nsew', padx=2)

		# slab page
		self.nb.add("slab", label="Slab Options")
		f = self.nb.page("slab")
		if Tk.TkVersion >= 8.5:
			parent.tk.call('grid', 'anchor', f._w, Tk.N)

		prow = itertools.count()
		self.thickness = FloatOption(f, prow.next(), 'Thickness',
						default.THICKNESS, None)
		self.thickness.min = 0.01
		self.shape = ShapeOption(f, prow.next(), 'Slab object',
							default.SHAPE, None)
		self.hideBases = BooleanOption(f, prow.next(),
					'Hide base atoms', default.HIDE, None)
		self.showGlycosidic = BooleanOption(f, prow.next(),
				'Separate glycosidic bond', default.GLYCOSIDIC,
				None)

		self.nb.add("style", label="Slab Style", raisecmd=self.map)
		# style page
		f = self.nb.page("style")
		if Tk.TkVersion >= 8.5:
			f.tk.call('grid', 'anchor', f._w, Tk.N)

		info = NA.findStyle(self.currentStyle)
		from chimera.preferences import saveui
		f2 = Tk.Frame(f)
		self.saveui = saveui.SaveUI(f2, self)
		f2.grid(row=prow.next(), column=0, columnspan=2, sticky=Tk.EW,
								padx=2, pady=2)

		self.anchor = AnchorOption(f, prow.next(), 'Anchor',
					info[NA.ANCHOR], self._drawStyle)

		f2 = Pmw.Group(f, tag_text=NA.PURINE.title())
		f2.grid(row=prow.next(), column=0, columnspan=2, sticky=Tk.EW,
									padx=2)
		f2 = f2.interior()
		f2.columnconfigure(0, weight=1, pad=2, uniform='a')
		f2.columnconfigure(1, weight=1, uniform='a')
		f2.columnconfigure(2, weight=1)

		self.purine_canvas = Tk.Canvas(f2, width=1, height=1) #,
						#borderwidth=2, relief=Tk.RIDGE)
		r = prow.next()
		self.purine_canvas.grid(row=r, column=0, rowspan=3,
						sticky=Tk.NSEW, padx=2, pady=2)
		corners = info[NA.PURINE]
		self.puLL = Float2Option(f2, prow.next(), 'Lower left',
					corners[0], self._drawStyle, startCol=1)
		self.puUR = Float2Option(f2, prow.next(), 'Upper right',
					corners[1], self._drawStyle, startCol=1)

		f3 = Pmw.Group(f, tag_text="%s, %s" % (NA.PYRIMIDINE.title(),
						NA.PSEUDO_PYRIMIDINE.title()))
		r = prow.next()
		f3.grid(row=r, column=0, columnspan=2, sticky=Tk.EW, padx=2)
		f3 = f3.interior()
		f3.columnconfigure(0, weight=1, pad=2, uniform='a')
		f3.columnconfigure(1, weight=1, uniform='a')
		f3.columnconfigure(2, weight=1)

		self.pyrimidine_canvas = Tk.Canvas(f3, width=1, height=1) #,
						#borderwidth=2, relief=Tk.RIDGE)
		r = prow.next()
		self.pyrimidine_canvas.grid(row=r, column=0, rowspan=3,
						sticky=Tk.NSEW, padx=2, pady=2)

		corners = info[NA.PYRIMIDINE]
		self.pyLL = Float2Option(f3, prow.next(), 'Lower left',
					corners[0], self._drawStyle, startCol=1)
		self.pyUR = Float2Option(f3, prow.next(), 'Upper right',
					corners[1], self._drawStyle, startCol=1)

		self.restrict = Tk.IntVar(parent)
		self.restrict.set(1)
		cb = Tk.Checkbutton(parent, variable=self.restrict,
		    text="Restrict OK/Apply to current selection, if any")
		cb.grid(row=row.next(), columnspan=2)

		parent.pack(ipady=2)

		self._showSideCB()
		chimera.triggers.addHandler(NA.TRIGGER_SLAB_STYLES,
						self._updateStyles, None)
예제 #27
0
    def fillInUI(self, parent):

        super(SonifyAttrDialog, self).fillInUI(parent)

        #self.modeNotebook = Pmw.NoteBook(parent,raisecommand=self._pageChangeCB,tabpos=None)

        # Pitch Markers
        self.renderPitchMarkers = self.renderHistogram.addmarkers(
            newcolor='pink', activate=False, coordtype='relative')
        if len(prefs[PITCH_RANGE]) == 1:
            self.renderPitchMarkers.append(((0.5, 0.0), None))
        else:
            self.renderPitchMarkers.extend(
                map(
                    lambda e:
                    ((e[0] / float(len(prefs[PITCH_RANGE]) - 1), 0.0), None),
                    enumerate(prefs[PITCH_RANGE])))
        for i, rad in enumerate(prefs[PITCH_RANGE]):
            self.renderPitchMarkers[i].radius = rad

        #self.renderNotebook = Pmw.NoteBook(renderFrame, tabpos=None)

        self.renderNotebook.add("Pitch")

        # Pitch tab
        f = self.renderNotebook.page("Pitch")
        self.pitchWarning = Tkinter.Label(
            f,
            text="pitch can only be used with\n"
            "atom, residue or molecule attributes.")
        self.pitchWarning.grid()  # for later setnaturalsize

        self.pitchFrame = Tkinter.Frame(f)
        from chimera.tkoptions import EnumOption, BooleanOption, FloatOption

        class SonificationOption(FloatOption):
            min = 0,
            max = 127

        class SoundStyleOption(EnumOption):
            values = ["sine", "piano"]

        self.soundStyle = SoundStyleOption(
            self.pitchFrame,
            0,
            "Sound style",
            prefs[SOUND_STYLE],
            lambda o: self.renderNotebook.setnaturalsize(),
            balloon="How worm radius changes between residues:\n"
            "   smooth: radius changes smoothly\n"
            "   segmented: radius changes abruptly")
        self.doNoValuePitch = BooleanOption(
            self.pitchFrame,
            1,
            "Play no-value residues",
            False,
            None,
            balloon="Play something for residues not having\n"
            "this attribute or leave them silent")
        self.noValuePitch = SonificationOption(
            self.pitchFrame,
            2,
            "No-value pitch",
            prefs[NOVAL_PITCH],
            None,
            balloon="Residues without this attribute will\n"
            "be given this pitch")

        self.renderNotebook.selectpage("Pitch")

        self.targetMenu.invoke(ShowAttr.attrsPrefMap[prefs[TARGET]].menuName)
예제 #28
0
class RmsdStarter(ModelessDialog):
	title = "Get RMSD Map Parameters"
	help = "ContributedSoftware/movie/movie.html#rmsd"

	def __init__(self, movie):
		self.movie = movie
		movie.subdialogs.append(self)
		ModelessDialog.__init__(self)

	def fillInUI(self, parent):
		from chimera.tkoptions import IntOption, BooleanOption, \
							FloatOption
		Tkinter.Label(parent, text="Create RMSD map of trajectory "
			"against itself", relief="ridge", bd=4).grid(row=0,
			column=0, columnspan=2, sticky="ew")

		startFrame = self.movie.startFrame
		endFrame = self.movie.endFrame
		self.startFrame = IntOption(parent, 1, "Starting frame",
			startFrame, None, min=startFrame, max=endFrame, width=6)

		numFrames = endFrame - startFrame + 1
		defStride = 1 + int(numFrames/300)
		self.stride = IntOption(parent, 2, "Step size", defStride,
			None, min=1, max=numFrames, width=3)

		self.endFrame = IntOption(parent, 3, "Ending frame", endFrame,
			None, min=startFrame, max=endFrame, width=6)

		self.minRmsd = FloatOption(parent, 4, "Lower RMSD threshold"
				" (white)", prefs[RMSD_MIN], None, width=6)
		self.maxRmsd = FloatOption(parent, 5, "Upper RMSD threshold"
				" (black)", prefs[RMSD_MAX], None, width=6)

		self.useSel = BooleanOption(parent, 6, "Restrict map to "
				"current selection, if any", True, None)

		self.ignoreBulk = BooleanOption(parent, 7, "Ignore solvent/"
							"ions", True, None)
		self.ignoreHyds = BooleanOption(parent, 8, "Ignore hydrogens",
							True, None)
		self.recolor = BooleanOption(parent, 9, "Auto-recolor for"
				" contrast", prefs[RMSD_AUTOCOLOR], None)
	def Apply(self):
		startFrame = self.startFrame.get()
		stride = self.stride.get()
		if (len(self.movie.ensemble) - (startFrame-1)) / stride > 1000:
			dlg = AskYesNoDialog("RMSD map will be %d pixels wide"
				" and tall. Okay?")
			if dlg.run(self.uiMaster()) == "no":
				self.enter()
				return
		endFrame = self.endFrame.get()
		if endFrame <= startFrame:
			self.enter()
			raise UserError("Start frame must be less"
							" than end frame")
		if startFrame < self.movie.startFrame \
		or endFrame > self.movie.endFrame:
			self.enter()
			raise UserError("Start or end frame outside"
							" of trajectory")
		prefs[RMSD_MIN] = self.minRmsd.get()
		prefs[RMSD_MAX] = self.maxRmsd.get()
		prefs[RMSD_AUTOCOLOR] = self.recolor.get()
		RmsdMapDialog(self.movie, startFrame, self.stride.get(),
			endFrame, self.useSel.get(), prefs[RMSD_MIN],
			prefs[RMSD_MAX], self.ignoreBulk.get(),
			self.ignoreHyds.get(), prefs[RMSD_AUTOCOLOR])
class EpsDialog(SaveModeless):
    """Dialog to allow the user to save alignment as EPS"""
    def __init__(self, mav):
        self.mav = mav
        self.title = "Save EPS of %s" % mav.title
        defaultFile = os.path.splitext(self.mav.title or "alignment")[0]
        SaveModeless.__init__(self,
                              clientPos='s',
                              initialfile=defaultFile,
                              filters=[("EPS", "*.eps", ".eps")])

    def fillInUI(self, parent):
        SaveModeless.fillInUI(self, parent)
        from chimera.tkoptions import SymbolicEnumOption, BooleanOption

        class ColorModeOption(SymbolicEnumOption):
            values = ["color", "gray", "mono"]
            labels = ["color", "grayscale", "black & white"]

        self.colorMode = ColorModeOption(self.clientArea,
                                         0,
                                         "color mode",
                                         "color",
                                         None,
                                         balloon="output color range")
        self.orientation = BooleanOption(
            self.clientArea,
            1,
            "rotate 90",
            False,
            None,
            balloon="If true, output will be rotated 90 degrees\n"
            "(i.e. landscape mode)")

        class ExtentOption(SymbolicEnumOption):
            values = ["visible", "all"]
            labels = ["visible region", "entire alignment"]

        self.extent = ExtentOption(
            self.clientArea,
            2,
            "extent",
            "visible",
            None,
            balloon="save the entire alignment or just the visible part")
        self.hideNodes = BooleanOption(
            self.clientArea,
            3,
            "hide tree control nodes",
            True,
            None,
            balloon="Hide square boxes used as controls for tree")
        if not self.mav.seqCanvas.treeShown:
            self.hideNodes.forget()
        self._nodesHandler = self.mav.triggers.addHandler(
            DISPLAY_TREE, self._treeDispCB, None)

    def destroy(self):
        self.mav.triggers.deleteHandler(DISPLAY_TREE, self._nodesHandler)
        self.mav = None
        ModelessDialog.destroy(self)

    def Apply(self):
        if not self.getPaths():
            replyobj.error("No EPS save file specified.\n")
            self.enter()
            return
        self.mav.saveEPS(self.getPaths()[0],
                         colorMode=self.colorMode.get(),
                         rotate=self.orientation.get(),
                         extent=self.extent.get(),
                         hideNodes=self.hideNodes.get())

    def _treeDispCB(self, trigName, myData, tree):
        if tree:
            self.hideNodes.manage()
        else:
            self.hideNodes.forget()
    def fillInUI(self, parent):
        from chimera.tkoptions import IntOption, BooleanOption, \
             FloatOption
        Tkinter.Label(parent,
                      text="Create RMSD map of trajectory "
                      "against itself",
                      relief="ridge",
                      bd=4).grid(row=0, column=0, columnspan=2, sticky="ew")

        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        self.startFrame = IntOption(parent,
                                    1,
                                    "Starting frame",
                                    startFrame,
                                    None,
                                    min=startFrame,
                                    max=endFrame,
                                    width=6)

        numFrames = endFrame - startFrame + 1
        defStride = 1 + int(numFrames / 300)
        self.stride = IntOption(parent,
                                2,
                                "Step size",
                                defStride,
                                None,
                                min=1,
                                max=numFrames,
                                width=3)

        self.endFrame = IntOption(parent,
                                  3,
                                  "Ending frame",
                                  endFrame,
                                  None,
                                  min=startFrame,
                                  max=endFrame,
                                  width=6)

        self.minRmsd = FloatOption(parent,
                                   4, "Lower RMSD threshold"
                                   " (white)",
                                   prefs[RMSD_MIN],
                                   None,
                                   width=6)
        self.maxRmsd = FloatOption(parent,
                                   5, "Upper RMSD threshold"
                                   " (black)",
                                   prefs[RMSD_MAX],
                                   None,
                                   width=6)

        self.useSel = BooleanOption(
            parent, 6, "Restrict map to "
            "current selection, if any", True, None)

        self.ignoreBulk = BooleanOption(parent, 7, "Ignore solvent/"
                                        "ions", True, None)
        self.ignoreHyds = BooleanOption(parent, 8, "Ignore hydrogens", True,
                                        None)
        self.recolor = BooleanOption(parent, 9, "Auto-recolor for"
                                     " contrast", prefs[RMSD_AUTOCOLOR], None)
예제 #31
0
class IlabelDialog(ModelessDialog):
    name = "2D Labels/Color Key"
    provideStatus = True
    buttons = ("Delete", "Close")

    LABELS = "Labels"
    COLOR_KEY = "Color Key"

    MOUSE_LABEL_TEXT = "Use mouse for label placement"
    MOUSE_KEY_TEXT = "Use mouse for key placement"

    EmphasisColor = "forest green"

    def __init__(self):
        import os.path
        myDir, junk = os.path.split(__file__)
        addFunction('place text', (self._pickLabel, self._moveLabel, None),
                    icon=chimage.get(
                        Image.open(os.path.join(myDir, 'ilabel.png')),
                        tkgui.app))
        addFunction('place key',
                    (self._startOrGrabKey, self._sizeOrMoveKey, None),
                    icon=chimage.get(
                        Image.open(os.path.join(myDir, 'key.png')), tkgui.app))

        import Ilabel
        if not Ilabel._ilabelModel:
            Ilabel.IlabelModel()
        self.model = Ilabel._ilabelModel
        ModelessDialog.__init__(self)
        self._sessionHandlerID = chimera.triggers.addHandler(
            SAVE_SESSION, self._saveSession, None)
        self._closeHandlerID = chimera.triggers.addHandler(
            CLOSE_SESSION, self.destroy, None)
        self._beginRestoreHandlerID = chimera.triggers.addHandler(
            BEGIN_RESTORE_SESSION, self.destroy, None)

    def fillInUI(self, parent):
        top = parent.winfo_toplevel()
        menubar = Tkinter.Menu(top, type="menubar", tearoff=False)
        top.config(menu=menubar)

        self.fileMenu = Tkinter.Menu(menubar)
        menubar.add_cascade(label="File", menu=self.fileMenu)
        self.fileMenu.add_command(label="Write...", command=self._writeFileCB)
        self.fileMenu.add_command(label="Read...", command=self._readFileCB)
        from chimera.tkgui import aquaMenuBar
        aquaMenuBar(menubar, parent, row=0)

        from ColorKey import KeyModel
        parent.rowconfigure(1, weight=1)
        parent.columnconfigure(0, weight=1)
        # _pageRaisedCB uses mouseModeVar, so define first
        self.mouseLabelingVar = Tkinter.IntVar(parent)
        self.mouseLabelingVar.set(True)
        self.mlLabelVar = Tkinter.StringVar(parent)
        self.mouseModeButton = Tkinter.Checkbutton(
            parent,
            command=self._mouseFuncCB,
            variable=self.mouseLabelingVar,
            textvariable=self.mlLabelVar)
        self.mouseModeButton.grid(row=2, column=0)
        self.notebook = Pmw.NoteBook(parent, raisecommand=self._pageRaisedCB)
        self.notebook.add(self.LABELS, tab_text=self.LABELS)
        self.notebook.add(self.COLOR_KEY, tab_text=self.COLOR_KEY)
        self.notebook.grid(row=1, column=0, sticky="nsew")
        self._fillLabelsPage(self.notebook.page(self.LABELS))
        self.keyModel = KeyModel(self)
        self.keyPosition = None
        self._fillColorKeyPage(self.notebook.page(self.COLOR_KEY))

    def _fillLabelsPage(self, page):
        page.columnconfigure(0, weight=1)
        page.columnconfigure(1, weight=1)
        page.columnconfigure(2, weight=1)

        row = 0
        from CGLtk.Table import SortableTable
        self.labelTable = SortableTable(page, automultilineHeaders=False)
        self.labelTable.addColumn("Label [(x, y) text]",
                                  self._labelListing,
                                  anchor='w')
        self.labelTable.addColumn("Shown", "shown", format=bool)
        self.labelTable.setData(self.model.labels)
        self.labelTable.launch(browseCmd=self._tableCB, selectMode="single")
        self.labelTable.grid(row=row, column=0, columnspan=3, sticky="nsew")
        page.rowconfigure(row, weight=1)
        row += 1

        self.labelText = Pmw.ScrolledText(page,
                                          labelpos='w',
                                          label_text="Text",
                                          text_height=3,
                                          text_width=20,
                                          text_wrap='none',
                                          text_state='disabled',
                                          text_exportselection=False)
        text = self.labelText.component('text')
        text.bind("<<Modified>>", self._textCB)
        text.bind("<<Selection>>", self._updateTextAttrWidgets)
        self.labelText.grid(row=row, column=0, sticky='nsew', columnspan=3)
        page.rowconfigure(row, weight=1)
        row += 1

        self.labelSymbolMenu = Pmw.OptionMenu(
            page,
            labelpos='w',
            label_text="Insert symbol:",
            command=self._insertSymbol,
            items=[
                u'\N{GREEK SMALL LETTER ALPHA}',
                u'\N{GREEK SMALL LETTER BETA}',
                u'\N{GREEK SMALL LETTER GAMMA}',
                u'\N{GREEK SMALL LETTER DELTA}',
                u'\N{GREEK SMALL LETTER EPSILON}',
                u'\N{GREEK SMALL LETTER PI}', u'\N{GREEK SMALL LETTER PHI}',
                u'\N{GREEK SMALL LETTER CHI}', u'\N{GREEK SMALL LETTER PSI}',
                u'\N{GREEK SMALL LETTER OMEGA}', u'\N{LEFTWARDS ARROW}',
                u'\N{RIGHTWARDS ARROW}', u'\N{LEFT RIGHT ARROW}',
                u'\N{UPWARDS ARROW}', u'\N{DOWNWARDS ARROW}',
                u'\N{SUPERSCRIPT TWO}', u'\N{SUPERSCRIPT THREE}',
                u'\N{DEGREE SIGN}',
                u'\N{LATIN CAPITAL LETTER A WITH RING ABOVE}', "more..."
            ])
        self.labelSymbolMenu.grid(row=row, column=0, columnspan=3)

        row += 1

        colorHouse = Pmw.LabeledWidget(page, labelpos='w', label_text="Color")
        colorHouse.grid(row=row, column=0, rowspan=3)
        from CGLtk.color.ColorWell import ColorWell
        self.colorWell = ColorWell(colorHouse.interior(),
                                   color=self._contrastWithBG(),
                                   callback=self._colorCB)
        self.colorWell.grid()

        from chimera.tkoptions import IntOption
        self.labelFontSize = IntOption(page,
                                       row,
                                       "Font size",
                                       24,
                                       self._labelChangeCB,
                                       startCol=1,
                                       min=1,
                                       attribute="size",
                                       width=3)
        row += 1
        self.labelFontStyle = FontStyle(page,
                                        row,
                                        "Font style",
                                        oglFont.normal,
                                        self._labelChangeCB,
                                        startCol=1)
        row += 1
        self.labelFontTypeface = FontTypeface(page,
                                              row,
                                              "Font typeface",
                                              FONT_TYPEFACE_VALUES[0],
                                              self._labelChangeCB,
                                              startCol=1)
        row += 1

        if self.model.curLabel:
            self.changeToLabel(self.model.curLabel, force=True)

    def _fillColorKeyPage(self, page):
        from chimera.tkoptions import IntOption, EnumOption, \
            BooleanOption, RGBAOption
        f = Tkinter.Frame(page)
        f.grid(row=0, columnspan=2)
        self.numComponents = IntOption(f,
                                       0,
                                       "Number of colors/labels",
                                       3,
                                       self._componentsCB,
                                       min=2,
                                       width=2)
        self.componentsFrame = Tkinter.Frame(page)
        self.componentsFrame.grid(row=1, column=0, sticky="nsew", columnspan=2)
        page.columnconfigure(0, weight=1)
        self.componentsFrame.columnconfigure(1, weight=1)

        class ColorTreatment(EnumOption):
            values = ("distinct", "blended")

        self.colorTreatment = ColorTreatment(
            page,
            2,
            "Color range depiction",
            "blended",
            self._keyChangeCB,
            balloon="Should colors be shown as distinct rectangles"
            " or as a continuous range")

        class LabelPosition(EnumOption):
            values = ("left/top", "right/bottom")

        self.labelPos = LabelPosition(
            page,
            3,
            "Label positions",
            "right/bottom",
            self._keyChangeCB,
            balloon="Position of"
            " labels relative to color key.\nLabels always"
            " positioned adjacent to long side.")
        self.labelColor = RGBAOption(
            page,
            4,
            "Label color",
            self._contrastWithBG(),
            self._keyChangeCB,
            balloob="Label color.  If set to 'No color', use corresponding"
            " key color",
            noneOkay=True)

        class LabelJustification(EnumOption):
            values = ("left", "decimal point", "right")

        self.justification = LabelJustification(
            page,
            5,
            "Label justification",
            "decimal point",
            self._keyChangeCB,
            balloon="Justification of label text"
            " in a vertical key layout.\nHorizontal key labels will"
            " always be center justified.")
        self.labelOffset = IntOption(page,
                                     6,
                                     "Label offset",
                                     0,
                                     self._keyChangeCB,
                                     width=3,
                                     balloon="Additional offset"
                                     " of labels from color bar, in pixels")
        self.keyFontSize = IntOption(page,
                                     7,
                                     "Font size",
                                     24,
                                     self._keyChangeCB,
                                     width=3)
        self.keyFontStyle = FontStyle(page, 8, "Font style", oglFont.normal,
                                      self._keyChangeCB)
        self.keyFontTypeface = FontTypeface(page, 9, "Font typeface",
                                            FONT_TYPEFACE_VALUES[0],
                                            self._keyChangeCB)
        self.borderColor = RGBAOption(
            page,
            10,
            "Border color",
            None,
            self._keyChangeCB,
            balloon="Color of border"
            " around color key (not each individual color).\n"
            "If 'no color', then no border is drawn.")
        self.borderWidth = IntOption(page,
                                     11,
                                     "Border width",
                                     3,
                                     self._keyChangeCB,
                                     balloon="in pixels")
        self.tickMarks = BooleanOption(page,
                                       12,
                                       "Show tick marks",
                                       False,
                                       self._keyChangeCB,
                                       balloon="Show tick marks"
                                       " pointing from key to labels")
        self._componentsCB(self.numComponents)

    def destroy(self, *args):
        self.mouseLabelingVar.set(True)
        self.mouseModeButton.invoke()
        chimera.triggers.deleteHandler(SAVE_SESSION, self._sessionHandlerID)
        chimera.triggers.deleteHandler(CLOSE_SESSION, self._closeHandlerID)
        chimera.triggers.deleteHandler(BEGIN_RESTORE_SESSION,
                                       self._beginRestoreHandlerID)
        chimera.openModels.close([self.model, self.keyModel])
        ModelessDialog.destroy(self)

    def map(self, e=None):
        self._pageRaisedCB(self.notebook.getcurselection())

    def unmap(self, e=None):
        self.mouseLabelingVar.set(True)
        self.mouseModeButton.invoke()

    def changeToLabel(self, nextLabel, force=False):
        if nextLabel == self.model.curLabel and not force:
            return
        if self.model.curLabel and not unicode(self.model.curLabel) \
        and self.model.curLabel != nextLabel:
            # remove previous label if empty
            self.removeLabel(self.model.curLabel)
        self.model.changeToLabel(nextLabel)
        self.labelText.component('text').configure(state='normal')
        self.labelTable.select(nextLabel)
        self.labelText.settext(unicode(nextLabel))
        text = self.labelText.component('text')
        lineIndex = 1
        for line in self.model.curLabel.lines:
            charIndex = 0
            for c in line:
                text.tag_add(id(c), "%d.%d" % (lineIndex, charIndex))
                charIndex += 1
            text.tag_add(id(line), "%d.%d" % (lineIndex, charIndex))
            lineIndex += 1

    def Delete(self):
        if self.notebook.getcurselection() == self.LABELS:
            self.labelText.clear()
            if not self.model.curLabel:
                self.status("No label to delete", color="red", blankAfter=10)
                return
            self.removeLabel(self.model.curLabel)
            self.labelText.component('text').configure(state='disabled')
        else:
            self.keyPosition = None
            self._keyChangeCB()

    def Help(self):
        helpLoc = "ContributedSoftware/2dlabels/2dlabels.html"
        if self.notebook.getcurselection() == self.COLOR_KEY:
            helpLoc += "#colorkey"
        chimera.help.display(helpLoc)

    def keyConfigure(self, data, pageChange=True):
        self._componentsCB(len(data), update=False)
        for datum, well, label in zip(data, self.wells, self.labels):
            color, text = datum
            well.showColor(color, doCallback=False)
            label.variable.set(text, invoke_callbacks=False)
        self._keyChangeCB()
        if pageChange:
            self.notebook.selectpage(self.COLOR_KEY)

    def makeChar(self, char, model):
        attrs = {}
        try:
            attrs['rgba'] = self.colorWell.rgba
        except AttributeError:  # multi or None
            if model:
                attrs['rgba'] = model.rgba
        size = self.labelFontSize.get()
        if size is not None:
            attrs['size'] = size
        style = self.labelFontStyle.get()
        if style is not None:
            attrs['style'] = style
        fontName = self.labelFontTypeface.get()
        if fontName is not None:
            attrs['fontName'] = fontName
        return Character(char, **attrs)

    def newLabel(self, pos):
        label = self.model.newLabel(pos)
        self.labelTable.setData(self.model.labels)
        self.status("Mouse drag to reposition label", color=self.EmphasisColor)
        return label

    def removeLabel(self, label):
        self.model.removeLabel(label)
        self.labelTable.setData(self.model.labels)
        if self.model.curLabel is not None:
            self.labelTable.select(self.model.curLabel)

    def reverseKey(self):
        data = zip([w.rgba for w in self.wells],
                   [l.variable.get() for l in self.labels])
        data.reverse()
        self.keyConfigure(data)

    def setLabelFromText(self):
        curLabel = self.model.curLabel
        text = self.labelText.component('text')
        # delete parts of label not in text...
        #
        # newlines first...
        while len(curLabel.lines) > 1:
            for i, line in enumerate(curLabel.lines[:-1]):
                if not text.tag_ranges(id(line)):
                    curLabel.lines[i + 1][:0] = line
                    del curLabel.lines[i]
                    break
            else:
                break
        # characters...
        for line in curLabel.lines:
            for c in line[:]:
                if not text.tag_ranges(id(c)):
                    line.remove(c)

        # get new parts of text into label
        model = None
        targets = []
        lines = curLabel.lines
        for line in lines:
            targets.extend([id(c) for c in line])
            if not model and line:
                model = line[0]
            if line is not lines[-1]:
                targets.append(id(line))
        contents = self.labelText.get()[:-1]  # drop trailing newline

        if targets:
            target = targets.pop(0)
        else:
            target = None

        textLine = 1
        textIndex = -1
        curLine = lines[0]
        for c in contents:
            textIndex += 1
            if str(target) in text.tag_names("%d.%d" % (textLine, textIndex)):
                if targets:
                    target = targets.pop(0)
                else:
                    target = None
                if c == '\n':
                    textLine += 1
                    textIndex = -1
                    curLine = lines[[id(l)
                                     for l in lines].index(id(curLine)) + 1]
                elif curLine:
                    model = curLine[textIndex]
            elif c == '\n':
                insertLine = curLine[0:textIndex]
                lines.insert(textLine - 1, insertLine)
                del curLine[0:textIndex]
                text.tag_add(id(insertLine), "%d.%d" % (textLine, textIndex))
                textLine += 1
                textIndex = -1
            else:
                labelChar = self.makeChar(c, model)
                curLine.insert(textIndex, labelChar)
                text.tag_add(id(labelChar), "%d.%d" % (textLine, textIndex))
        self.model.setMajorChange()

    def updateGUI(self, source="gui"):
        curLabel = self.model.curLabel
        if curLabel and source == "gui":
            self.setLabelFromText()
        self.labelTable.setData(self.model.labels)
        if curLabel:
            self.labelTable.select(curLabel)
        self._updateTextAttrWidgets()

    def _colorCB(self, color):
        curLabel = self.model.curLabel
        if not curLabel:
            self.status("No label to color", color='red')
            return
        self.model.setMajorChange()
        for c in self._selChars():
            c.rgba = color

    def _componentsCB(self, opt, update=True):
        cf = self.componentsFrame
        if hasattr(self, 'wells'):
            for well in self.wells:
                well.grid_forget()
                well.destroy()
            for label in self.labels:
                label.frame.grid_forget()
            self.reverseButton.grid_forget()
            self.reverseButton.destroy()
        else:
            Tkinter.Label(cf, text="Colors").grid(row=0)
            Tkinter.Label(cf, text="Labels").grid(row=0, column=1)
        if isinstance(opt, int):
            numComponents = opt
            self.numComponents.set(opt)
        else:
            numComponents = opt.get()
        wellSize = min(38, int((7 * 38) / numComponents))
        from CGLtk.color.ColorWell import ColorWell
        self.wells = []
        self.labels = []
        from CGLtk import Hybrid
        for i in range(numComponents):
            well = ColorWell(cf,
                             width=wellSize,
                             height=wellSize,
                             callback=self._keyChangeCB,
                             color='white')
            well.grid(row=i + 1)
            self.wells.append(well)
            label = Hybrid.Entry(cf, "", 10)
            label.variable.add_callback(self._keyTypingCB)
            label.frame.grid(row=i + 1, column=1, sticky='ew')
            self.labels.append(label)
        self.reverseButton = Tkinter.Button(cf,
                                            command=self.reverseKey,
                                            text="Reverse ordering of above",
                                            pady=0)
        self.reverseButton.grid(row=numComponents + 1, column=0, columnspan=2)
        self.notebook.setnaturalsize()
        if update:
            self._keyChangeCB()

    def _contrastWithBG(self):
        bg = chimera.viewer.background
        if bg:
            bgColor = bg.rgba()
        else:
            bgColor = (0, 0, 0)
        if bgColor[0] * 2 + bgColor[1] * 3 + bgColor[2] < 0.417:
            return (1, 1, 1)
        else:
            return (0, 0, 0)

    def _eventToPos(self, viewer, event, offset=(0, 0)):
        w, h = viewer.windowSize
        return (event.x - offset[0]) / float(w), \
          (h - event.y - offset[1]) / float(h)

    def _handleTextChange(self):
        self.updateGUI()
        self.labelText.edit_modified(False)

    def _insertSymbol(self, item):
        if len(item) > 1:
            from chimera import help
            help.display("ContributedSoftware/2dlabels/symbols.html")
            return
        if not self.model.labels:
            self.status("No labels have been created yet", color="red")
            return
        if not self.labelTable.selected():
            self.status("No labels active", color="red")
        self.labelText.insert("insert", item)
        self.setLabelFromText()

    def _keyChangeCB(self, *args):
        self.keyModel.setMajorChange()

    def _keyTypingCB(self, fromAfter=False):
        # wait for a pause in typing before updating key...
        if fromAfter:
            self._typingHandler = None
            self._keyChangeCB()
            return
        handle = getattr(self, '_typingHandler', None)
        if handle:
            self.componentsFrame.after_cancel(handle)
        self._typingHandler = self.componentsFrame.after(
            500, lambda: self._keyTypingCB(fromAfter=True))

    def _labelChangeCB(self, option):
        curLabel = self.model.curLabel
        self.model.setMajorChange()
        val = option.get()
        attrName = option.attribute
        for c in self._selChars():
            setattr(c, attrName, val)

    def _labelListing(self, label):
        text = unicode(label)
        if '\n' in text:
            newline = text.index('\n')
            text = text[:newline] + "..."
        if not text:
            text = "<empty>"
        return "(%.2f, %.2f) %s" % (label.pos[0], label.pos[1], text)

    def _mouseFuncCB(self):
        self.status("")
        if not self.mouseLabelingVar.get():
            if hasattr(self, "_prevMouse"):
                setButtonFunction("1", (), self._prevMouse)
                delattr(self, "_prevMouse")
        elif self.mlLabelVar.get() == self.MOUSE_LABEL_TEXT:
            if not hasattr(self, "_prevMouse"):
                self._prevMouse = getFuncName("1", ())
            setButtonFunction("1", (), "place text")
        else:
            if not hasattr(self, "_prevMouse"):
                self._prevMouse = getFuncName("1", ())
            setButtonFunction("1", (), "place key")

    def _moveLabel(self, viewer, event):
        pos = self._eventToPos(viewer, event, self._moveOffset)
        self.model.moveLabel(pos)
        curLabel = self.model.curLabel
        self.labelTable.setData(self.model.labels)
        self.labelTable.select(curLabel)

    def _pageRaisedCB(self, pageName):
        if pageName == "Labels":
            pageItem = self.MOUSE_LABEL_TEXT
            if not self.model.labels:
                self.status(
                    "Click mouse button 1 in graphics\n"
                    "window to place first label",
                    color=self.EmphasisColor)
            for index in range(0, self.fileMenu.index('end') + 1):
                self.fileMenu.entryconfigure(index, state='normal')
        else:
            pageItem = self.MOUSE_KEY_TEXT
            self.status("Drag mouse to position/size key",
                        color=self.EmphasisColor)
            for index in range(0, self.fileMenu.index('end') + 1):
                self.fileMenu.entryconfigure(index, state='disabled')
        self.mlLabelVar.set(pageItem)
        # just setting the var doesn't cause the callback, and
        # yet using invoke() toggles the var, so set it _opposite_
        # to what's desired before calling invoke()
        self.mouseLabelingVar.set(False)
        self.mouseModeButton.invoke()

    def _pickLabel(self, viewer, event):
        w, h = viewer.windowSize
        pos = self._eventToPos(viewer, event)
        label, self._moveOffset = self.model.pickLabel(pos, w, h)
        if label is None:
            label = self.newLabel(pos)
            self._moveOffset = (0, 0)
        self.changeToLabel(label)
        self.labelText.component('text').focus_set()

    def _readFile(self, okayed, dialog):
        if not okayed:
            return
        from Ilabel import readFiles
        readFiles(dialog.getPaths(), clear=dialog.deleteExistingVar.get())

    def _readFileCB(self):
        if not hasattr(self, "_readFileDialog"):
            self._readFileDialog = ReadFileDialog(command=self._readFile,
                                                  clientPos='s')
        self._readFileDialog.enter()

    def _restoreSession(self, info):
        if info["sel ranges"]:
            self.labelText.tag_add("sel", *info["sel ranges"])
        self._updateTextAttrWidgets()
        self._suppressMap = True
        self.labelText.edit_modified(False)
        if "key position" not in info:
            self.notebook.selectpage(self.LABELS)
            if info["mouse func"] == "normal":
                self.mouseLabelingVar.set(True)
                self.mouseModeButton.invoke()
            return
        self.keyPosition = info["key position"]
        self.colorTreatment.set(info["color depiction"])
        self.labelPos.set(info["label positions"])
        self.labelColor.set(info["label color"])
        self.justification.set(info["label justification"])
        self.labelOffset.set(info["label offset"])
        self.keyFontSize.set(info["font size"])
        self.keyFontStyle.set(info["font typeface"])
        if "font name" in info:
            self.keyFontTypeface.set(info["font name"])
        self.borderColor.set(info["border color"])
        self.borderWidth.set(info["border width"])
        self.tickMarks.set(info["show ticks"])
        self.keyConfigure(info["colors/labels"])
        if self.keyPosition:
            self.notebook.selectpage(self.COLOR_KEY)
        else:
            self.notebook.selectpage(self.LABELS)
        if info["mouse func"] == "normal":
            self.mouseLabelingVar.set(True)
            self.mouseModeButton.invoke()
        return info

    def _saveSession(self, triggerName, myData, sessionFile):
        print >> sessionFile, """
def restore2DLabelDialog(info):
	from chimera.dialogs import find, display
	from Ilabel.gui import IlabelDialog
	dlg = find(IlabelDialog.name)
	if dlg is not None:
		dlg.destroy()
	dlg = display(IlabelDialog.name)
	dlg._restoreSession(info)

import SimpleSession
SimpleSession.registerAfterModelsCB(restore2DLabelDialog, %s)

""" % repr(self._sessionInfo())

    def _selChars(self):
        chars = []
        curLabel = self.model.curLabel
        if curLabel:
            sel = self.labelText.tag_ranges("sel")
            if sel:
                sline, schar = [int(x) for x in str(sel[0]).split('.')]
                eline, echar = [int(x) for x in str(sel[1]).split('.')]
                sline -= 1
                eline -= 1
                for li, line in enumerate(curLabel.lines):
                    if li < sline:
                        continue
                    if li > eline:
                        break
                    if sline == eline:
                        chars.extend(line[schar:echar])
                    elif li == sline:
                        chars.extend(line[schar:])
                    elif li == eline:
                        chars.extend(line[:echar])
                    else:
                        chars.extend(line)
            else:
                for l in curLabel.lines:
                    chars.extend(l)
        return chars

    def _sessionInfo(self):
        info = {}
        info["sel ranges"] = tuple(
            [str(tr) for tr in self.labelText.tag_ranges("sel")])
        if self.mouseLabelingVar.get():
            info["mouse func"] = "labeling"
        else:
            info["mouse func"] = "normal"
        info["key position"] = self.keyPosition
        info["colors/labels"] = [(w.rgba, l.variable.get())
                                 for w, l in zip(self.wells, self.labels)]
        info["color depiction"] = self.colorTreatment.get()
        info["label positions"] = self.labelPos.get()
        info["label color"] = self.labelColor.get()
        info["label justification"] = self.justification.get()
        info["label offset"] = self.labelOffset.get()
        info["font size"] = self.keyFontSize.get()
        info["font typeface"] = self.keyFontStyle.get()
        info["font name"] = self.keyFontTypeface.get()
        info["border color"] = self.borderColor.get()
        info["border width"] = self.borderWidth.get()
        info["show ticks"] = self.tickMarks.get()
        return info

    def _sizeOrMoveKey(self, viewer, event):
        pos = self._eventToPos(viewer, event)
        if self.grabPos:
            deltas = [pos[axis] - self.grabPos[axis] for axis in [0, 1]]
            for posIndex in [0, 1]:
                old = self.keyPosition[posIndex]
                self.keyPosition[posIndex] = (old[0] + deltas[0],
                                              old[1] + deltas[1])
            self.grabPos = pos
        elif len(self.keyPosition) == 1:
            self.keyPosition.append(pos)
        else:
            self.keyPosition[1] = pos
        self._keyChangeCB()

    def _startOrGrabKey(self, viewer, event):
        pos = self._eventToPos(viewer, event)
        if self.keyPosition and len(self.keyPosition) == 2:
            # possible grab;
            # see if in middle third of long side...
            p1, p2 = self.keyPosition
            x1, y1 = p1
            x2, y2 = p2
            if abs(x2 - x1) < abs(y2 - y1):
                longAxis = 1
                ymin = min(y2, y1)
                ymax = max(y2, y1)
                b1 = (2 * ymin + ymax) / 3.0
                b2 = (2 * ymax + ymin) / 3.0
                o1 = min(x1, x2)
                o2 = max(x1, x2)
            else:
                longAxis = 0
                xmin = min(x2, x1)
                xmax = max(x2, x1)
                b1 = (2 * xmin + xmax) / 3.0
                b2 = (2 * xmax + xmin) / 3.0
                o1 = min(y1, y2)
                o2 = max(y1, y2)
            if b1 < pos[longAxis] < b2 \
            and o1 < pos[1-longAxis] < o2:
                self.grabPos = pos
                return
        self.grabPos = None
        self.keyPosition = [pos]
        self._keyChangeCB()
        self.status("Grab middle of key to reposition",
                    color=self.EmphasisColor)

    def _tableCB(self, sel):
        if not sel:
            return
        self.changeToLabel(sel)

    def _textCB(self, e):
        text = self.labelText.component('text')
        if not text.tk.call((text._w, 'edit', 'modified')):
            #if not text.edit_modified():
            return
        # this callback can happen _before_ the change
        # actually occurs, so do the processing after idle
        text.after_idle(self._handleTextChange)

    def _updateTextAttrWidgets(self, e=None):
        rgba = None
        multiple = False
        for c in self._selChars():
            if rgba is None:
                rgba = c.rgba
            elif rgba != c.rgba:
                multiple = True
                break
        if rgba is not None:
            self.colorWell.showColor(rgba, multiple=multiple, doCallback=False)
            self.labelFontSize.display(self._selChars())
            self.labelFontStyle.display(self._selChars())
            self.labelFontTypeface.display(self._selChars())

    def _writeFile(self, okayed, dialog):
        if not okayed:
            return
        from Ilabel import writeFile
        writeFile(dialog.getPaths()[0])

    def _writeFileCB(self):
        if not hasattr(self, "_writeFileDialog"):
            from OpenSave import SaveModeless
            self._writeFileDialog = SaveModeless(command=self._writeFile,
                                                 title="Write 2D Labels Info")
        self._writeFileDialog.enter()
예제 #32
0
class EspDialog(ModelessDialog):
	title = "Coulombic Surface Coloring"
	name = "ESP computation"
	help = "ContributedSoftware/coulombic/coulombic.html"

	HB = "estimated from H-bonds"

	def fillInUI(self, parent):
		import Pmw, Tkinter
		self.buttonWidgets['OK']['state'] = 'disabled'
		self.buttonWidgets['Apply']['state'] = 'disabled'
		from chimera.widgets import ModelScrolledListBox
		self.surfListBox = ModelScrolledListBox(parent, labelpos='n',
			label_text='Surfaces to color by ESP:',
			listbox_selectmode="extended",
			filtFunc=lambda m: isinstance(m, chimera.MSMSModel),
			selectioncommand=self._selSurfCB)
		self.surfListBox.grid(row=0, column=0, sticky="nsew",
							columnspan=2)
		Pmw.OptionMenu(parent, command=self._menuCB, initialitem="3",
			items=[str(x) for x in range(2, 12)], labelpos='w',
			label_text="Number of colors/values:").grid(row=1,
			column=0, columnspan=2)
		f = self.interpFrame = Tkinter.Frame(parent)
		f.grid(row=2, column=0, columnspan=2)
		self.wells = []
		self.values = []
		self._entryOpts = {
			'validate': 'real',
			'entry_justify': 'center',
			'entry_width': 6
		}
		from CGLtk.color.ColorWell import ColorWell
		for color, value in [("red", -10), ("white", 0), ("blue", 10)]:
			well = ColorWell(f, color=color)
			well.grid(row=0, column=len(self.wells))
			self.wells.append(well)
			entry = Pmw.EntryField(f, value=str(value),
							**self._entryOpts)
			entry.grid(row=1, column=len(self.values))
			self.values.append(entry)

		from chimera.tkoptions import FloatOption, BooleanOption
		self.distDep = BooleanOption(parent, 3,
			"Distance-dependent dielectric", True, None, balloon=
			"If true, charge falls off with distance squared to\n"
			"simulate solvent screening effects")
		self.dielectric = FloatOption(parent, 4, "Dielectric constant",
								4.0, None)
		self.surfDist = FloatOption(parent, 5, "Distance from surface",
			1.4, None, balloon="Potential at this distance from\n"
			"the surface is used for coloring")

		self.hisGroup = Pmw.Group(parent, hull_padx=2,
			tag_text="Implicit Histidine Protonation")
		self.hisGroup.grid(row=6, column=0, columnspan=2, sticky="nsew")
		self.hisProtVar = Tkinter.StringVar(parent)
		self.hisProtVar.set("name")
		interior = self.hisGroup.interior()
		interior.columnconfigure(0, weight=1)
		lab = Tkinter.Label(interior, text="Assumed histidine "
			"protonation for\nstructures without explicit hydrogens")
		from tkFont import Font
		font = Font(font=lab.cget('font'))
		font.config(size=int(0.75 * float(font.cget('size'))),
								slant='italic')
		lab.config(font=font)
		lab.grid(row=0)
		Tkinter.Radiobutton(interior, variable=self.hisProtVar,
			value="name", text="Residue name-based", command=
			self._switchHisList).grid(row=1, sticky='w')
		f = Tkinter.Frame(interior)
		f.grid(row=2)
		Tkinter.Label(f, text="HID/HIE/HIP = delta/epsilon/both").grid(
			row=0, sticky='w')
		self.hisDefault = Pmw.OptionMenu(f, initialitem=self.HB,
			items=[self.HB, "delta", "epsilon", "both"], labelpos='w',
			label_text="HIS = ", command=lambda a, s=self:
			setattr(s, 'hisChanged', True))
		self.hisDefault.grid(row=1, sticky='w')
		self._pickText = Tkinter.StringVar(parent)
		self._pickText.set("Specified individually...")
		Tkinter.Radiobutton(interior, variable=self.hisProtVar,
			value="pick", textvariable=self._pickText,
			command=self._switchHisList).grid(row=3, sticky='w')

		Tkinter.Button(parent, pady=0, command=self._colorKeyCB,
			text="Create corresponding color key").grid(row=7,
			column=0, columnspan=2)
		self.hisChanged = False

	def Apply(self):
		for entry in self.values:
			entry.invoke()
		colors = [w.rgba for w in self.wells]
		values = [float(e.getvalue()) for e in self.values]
		if self.hisProtVar.get() == "name":
			hisScheme = {
				self.HB: None,
				'delta': 'HID',
				'epsilon': 'HIE',
				'both': 'HIP'
			}[self.hisDefault.getvalue()]
		else:
			hisScheme = self.hisListingData
		from ESP import colorEsp
		for surf in self.surfListBox.getvalue():
			if self.hisChanged:
				# clear out charge values so that histidines
				# get new charges
				for a in surf.atoms:
					a.charge = None
			colorEsp(surf, colors, values,
					dielectric=self.dielectric.get(),
					distDep=self.distDep.get(),
					surfDist=self.surfDist.get(),
					hisScheme=hisScheme)
		self.hisChanged = False

	def _colorKeyCB(self):
		for entry in self.values:
			entry.invoke()
		from Ilabel.gui import IlabelDialog
		from chimera import dialogs
		d = dialogs.display(IlabelDialog.name)
		d.keyConfigure(zip([w.rgba for w in self.wells],
					[e.getvalue() for e in self.values]))

	def _menuCB(self, val):
		newNum = int(val)
		oldSettings = []
		for well, entry in zip(self.wells, self.values):
			entry.invoke()
			oldSettings.append((well.rgba, float(entry.getvalue())))
			well.grid_forget()
			well.destroy()
			entry.grid_forget()
			entry.destroy()
		import Pmw
		from CGLtk.color.ColorWell import ColorWell
		self.wells = []
		self.values = []
		scale = (len(oldSettings) - 1.0) / (newNum - 1.0)
		f = self.interpFrame
		for i in range(newNum):
			index = i * scale
			if index == int(index) \
			or int(index) >= len(oldSettings):
				color, value = oldSettings[int(index)]
			else:
				lowc, lowv = oldSettings[int(index)]
				highc, highv = oldSettings[int(index)+1]
				frac = index - int(index)
				color = []
				for lowcomp, highcomp in zip(lowc, highc):
					color.append((1.0 - frac) * lowcomp
							+ frac * highcomp)
				value = (1.0 - frac) * lowv + frac * highv
			well = ColorWell(f, color=color)
			well.grid(row=0, column=len(self.wells))
			self.wells.append(well)
			entry = Pmw.EntryField(f, value=str(value),
							**self._entryOpts)
			entry.grid(row=1, column=len(self.values))
			self.values.append(entry)
				
	def _selSurfCB(self):
		if self.surfListBox.getvalue():
			state = 'normal'
		else:
			state = 'disabled'
		self.buttonWidgets['OK']['state'] = state
		self.buttonWidgets['Apply']['state'] = state

		self._updateHisListing()

	def _select(self, hisType):
		for r, vars in self._vars.items():
			dv, ev = vars
			if hisType == "delta":
				dv.set(True)
				ev.set(False)
				self.hisListingData[r] = "HID"
			elif hisType == "epsilon":
				dv.set(False)
				ev.set(True)
				self.hisListingData[r] = "HIE"
			else:
				dv.set(True)
				ev.set(True)
				self.hisListingData[r] = "HIP"

			
	def _switchHisList(self):
		self.hisChanged = True
		if not hasattr(self, 'hisListing'):
			if self.hisProtVar.get() != "pick":
				return
			self.hisListingData = {}
			import Tix, Tkinter
			self.hisFrame = Tkinter.Frame(self.hisGroup.interior())
			self.hisListing = Tix.ScrolledHList(self.hisFrame,
						width="3i",
						options="""hlist.columns 4
						hlist.header 1
						hlist.indicator 1""")
			self.hisListing.hlist.configure(
				selectbackground=self.hisListing['background'],
				selectborderwidth=0)
			self.hisListing.grid(row=0, column=0, columnspan=3,
								sticky="nsew")
			self.hisFrame.rowconfigure(1, weight=1)
			self.hisFrame.columnconfigure(0, weight=1)
			self.hisFrame.columnconfigure(1, weight=1)
			hlist = self.hisListing.hlist
			hlist.header_create(0, itemtype="text", text="Model")
			hlist.header_create(1, itemtype="text", text="Residue")
			hlist.header_create(2, itemtype="text", text="Delta")
			hlist.header_create(3, itemtype="text", text="Epsilon")
			self._checkButtonStyle = Tix.DisplayStyle("window",
				background=hlist['background'],
				refwindow=self.hisListing, anchor='center')
			self._updateHisListing()

			Tkinter.Button(self.hisFrame, text="All Delta",
				pady=0, highlightthickness=0,
				command=lambda p="delta": self._select(p)
				).grid(row=1, column=0)
			Tkinter.Button(self.hisFrame, text="All Epsilon",
				pady=0, highlightthickness=0,
				command=lambda p="epsilon": self._select(p)
				).grid(row=1, column=1)
			Tkinter.Button(self.hisFrame, text="All Both",
				pady=0, highlightthickness=0,
				command=lambda p="both": self._select(p)
				).grid(row=1, column=2)

		if self.hisProtVar.get() == "pick":
			self._pickText.set("Specified individually:")
			self.hisFrame.grid(row=4, sticky="nsew")
			interior = self.hisGroup.interior()
			interior.rowconfigure(4, weight=1)
			self.uiMaster().rowconfigure(6, weight=4)
		else:
			self._pickText.set("Specified individually...")
			self.hisFrame.grid_forget()
			interior = self.hisGroup.interior()
			interior.rowconfigure(4, weight=0)
			self.uiMaster().rowconfigure(6, weight=0)

	def _toggleDelta(self, res):
		self.hisChanged = True
		old = self.hisListingData[res]
		if old == "HIS":
			new = "HID"
		elif old == "HID":
			new = "HIS"
		elif old == "HIE":
			new = "HIP"
		else:
			new = "HIE"
		self.hisListingData[res] = new

	def _toggleEpsilon(self, res):
		self.hisChanged = True
		old = self.hisListingData[res]
		if old == "HIS":
			new = "HIE"
		elif old == "HID":
			new = "HIP"
		elif old == "HIE":
			new = "HIS"
		else:
			new = "HID"
		self.hisListingData[res] = new

	def _updateHisListing(self):
		if not hasattr(self, 'hisListing'):
			return
		self._updateHisListingData()
		hlist = self.hisListing.hlist
		on = self.hisListing.tk.call('tix', 'getimage', 'ck_on')
		off = self.hisListing.tk.call('tix', 'getimage', 'ck_off')
		hlist.delete_all()
		import Tkinter
		row = 0
		self._vars = {}
		for m in [s.molecule for s in self.surfListBox.getvalue()]:
			for r in m.residues:
				try:
					hisType = self.hisListingData[r]
				except KeyError:
					continue
				hlist.add(row, itemtype="text", text="%s (%s)"
						% (m.name, m.oslIdent()))
				hlist.item_create(row, 1, itemtype="text",
						text=r.oslIdent(
						start=chimera.SelResidue))
				var = Tkinter.IntVar(hlist)
				var.set(hisType in ["HID", "HIP"])
				cmd = lambda r=r: self._toggleDelta(r)
				self._vars[r] = [var]
				toggle = Tkinter.Checkbutton(hlist, command=cmd,
					variable=var, image=off, selectimage=on,
					selectcolor="", indicatoron=False,
					borderwidth=0)
				hlist.item_create(row, 2, itemtype="window",
					window=toggle,
					style=self._checkButtonStyle)
				var = Tkinter.IntVar(hlist)
				var.set(hisType in ["HIE", "HIP"])
				cmd = lambda r=r: self._toggleEpsilon(r)
				self._vars[r].append(var)
				toggle = Tkinter.Checkbutton(hlist, command=cmd,
					variable=var, image=off, selectimage=on,
					selectcolor="", indicatoron=False,
					borderwidth=0)
				hlist.item_create(row, 3, itemtype="window",
					window=toggle,
					style=self._checkButtonStyle)
				row += 1

	def _updateHisListingData(self):
		newData = {}
		default = {
			'delta': 'HID',
			'epsilon': 'HIE',
			'both': 'HIP',
			self.HB: 'HID'
		}[self.hisDefault.getvalue()]
		for m in [s.molecule for s in self.surfListBox.getvalue()]:
			for r in m.residues:
				if r.type not in ["HIS", "HIE", "HIP", "HID"]:
					continue
				try:
					newData[r] = self.hisListingData[r]
				except KeyError:
					if r.type == 'HIS':
						newData[r] = default
					else:
						newData[r] = r.type
		self.hisListingData = newData
class VolumeDialog(ModelessDialog):
    title = "Calculate Atomic Occupancy"
    help = "ContributedSoftware/movie/movie.html#occupancy"
    provideStatus = True
    statusPosition = "left"
    buttons = ('OK', 'Close')
    default = 'OK'

    def __init__(self, movie):
        self.movie = movie
        movie.subdialogs.append(self)
        ModelessDialog.__init__(self)

    def map(self, e=None):
        if not self.movie.holdingSteady:
            self.status("No atoms being held steady -- see Help", color="red")

    def fillInUI(self, parent):
        Tkinter.Label(parent,
                      text="Collect positions of selected"
                      " atoms over trajectory",
                      relief="ridge",
                      bd=4).grid(row=0, column=0, columnspan=2, sticky="ew")

        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        from chimera.tkoptions import IntOption, BooleanOption, \
            FloatOption, StringOption
        self.startFrame = IntOption(parent,
                                    1,
                                    "Starting frame",
                                    startFrame,
                                    None,
                                    min=startFrame,
                                    max=endFrame,
                                    width=6)

        numFrames = endFrame - startFrame + 1
        defStride = 1 + int(numFrames / 300)
        self.stride = IntOption(parent,
                                2,
                                "Step size",
                                defStride,
                                None,
                                min=1,
                                max=numFrames,
                                width=3)

        self.endFrame = IntOption(parent,
                                  3,
                                  "Ending frame",
                                  endFrame,
                                  None,
                                  min=startFrame,
                                  max=endFrame,
                                  width=6)

        self.doCutoff = BooleanOption(
            parent, 4, 'Limit data collection'
            ' to within cutoff distance of any "held steady" atoms', True,
            None)

        self.cutoff = FloatOption(parent,
                                  5,
                                  "Cutoff distance",
                                  prefs[VOLUME_CUTOFF],
                                  None,
                                  width=4)
        self.resolution = FloatOption(parent,
                                      6,
                                      "Volume grid spacing",
                                      prefs[VOLUME_RESOLUTION],
                                      None,
                                      min=0.0001,
                                      width=4)
        self.volumeName = StringOption(parent,
                                       7,
                                       "Volume data name",
                                       self.movie.ensemble.name,
                                       None,
                                       width=20)
        self.byAtomType = BooleanOption(
            parent,
            8, "Collect data"
            " separately for each atom type in selection",
            True,
            None,
            balloon="Create a volume data set for"
            " each type of atom type\n(sp2 oxygen, aromatic carbon,"
            " etc.) in current selection")

    def Apply(self):
        from chimera import UserError
        atoms = chimera.selection.currentAtoms()
        if not atoms:
            self.enter()
            raise UserError("No atoms selected")
        startFrame = self.startFrame.get()
        endFrame = self.endFrame.get()
        if endFrame <= startFrame:
            self.enter()
            raise UserError("Start frame must be less" " than end frame")
        if startFrame < self.movie.startFrame \
        or endFrame > self.movie.endFrame:
            self.enter()
            raise UserError("Start or end frame outside" " of trajectory")
        if self.doCutoff.get():
            bound = prefs[VOLUME_CUTOFF] = self.cutoff.get()
        else:
            bound = None
        prefs[VOLUME_RESOLUTION] = self.resolution.get()
        step = self.stride.get()
        spacing = self.resolution.get()
        name = self.volumeName.get()
        atomTypes = {}
        if self.byAtomType.get():
            for a in atoms:
                atomTypes.setdefault(a.idatmType, []).append(a)
        if len(atomTypes) > 1:
            for atomType, atAtoms in atomTypes.items():
                self.movie.computeVolume(atAtoms,
                                         startFrame=startFrame,
                                         endFrame=endFrame,
                                         step=step,
                                         bound=bound,
                                         spacing=spacing,
                                         volumeName=name + " [" + atomType +
                                         "]")
        else:
            self.movie.computeVolume(atoms,
                                     startFrame=startFrame,
                                     endFrame=endFrame,
                                     step=step,
                                     bound=bound,
                                     spacing=spacing,
                                     volumeName=name)
예제 #34
0
	def fillInUI(self, parent):
		import Pmw, Tkinter
		self.buttonWidgets['OK']['state'] = 'disabled'
		self.buttonWidgets['Apply']['state'] = 'disabled'
		from chimera.widgets import ModelScrolledListBox
		self.surfListBox = ModelScrolledListBox(parent, labelpos='n',
			label_text='Surfaces to color by ESP:',
			listbox_selectmode="extended",
			filtFunc=lambda m: isinstance(m, chimera.MSMSModel),
			selectioncommand=self._selSurfCB)
		self.surfListBox.grid(row=0, column=0, sticky="nsew",
							columnspan=2)
		Pmw.OptionMenu(parent, command=self._menuCB, initialitem="3",
			items=[str(x) for x in range(2, 12)], labelpos='w',
			label_text="Number of colors/values:").grid(row=1,
			column=0, columnspan=2)
		f = self.interpFrame = Tkinter.Frame(parent)
		f.grid(row=2, column=0, columnspan=2)
		self.wells = []
		self.values = []
		self._entryOpts = {
			'validate': 'real',
			'entry_justify': 'center',
			'entry_width': 6
		}
		from CGLtk.color.ColorWell import ColorWell
		for color, value in [("red", -10), ("white", 0), ("blue", 10)]:
			well = ColorWell(f, color=color)
			well.grid(row=0, column=len(self.wells))
			self.wells.append(well)
			entry = Pmw.EntryField(f, value=str(value),
							**self._entryOpts)
			entry.grid(row=1, column=len(self.values))
			self.values.append(entry)

		from chimera.tkoptions import FloatOption, BooleanOption
		self.distDep = BooleanOption(parent, 3,
			"Distance-dependent dielectric", True, None, balloon=
			"If true, charge falls off with distance squared to\n"
			"simulate solvent screening effects")
		self.dielectric = FloatOption(parent, 4, "Dielectric constant",
								4.0, None)
		self.surfDist = FloatOption(parent, 5, "Distance from surface",
			1.4, None, balloon="Potential at this distance from\n"
			"the surface is used for coloring")

		self.hisGroup = Pmw.Group(parent, hull_padx=2,
			tag_text="Implicit Histidine Protonation")
		self.hisGroup.grid(row=6, column=0, columnspan=2, sticky="nsew")
		self.hisProtVar = Tkinter.StringVar(parent)
		self.hisProtVar.set("name")
		interior = self.hisGroup.interior()
		interior.columnconfigure(0, weight=1)
		lab = Tkinter.Label(interior, text="Assumed histidine "
			"protonation for\nstructures without explicit hydrogens")
		from tkFont import Font
		font = Font(font=lab.cget('font'))
		font.config(size=int(0.75 * float(font.cget('size'))),
								slant='italic')
		lab.config(font=font)
		lab.grid(row=0)
		Tkinter.Radiobutton(interior, variable=self.hisProtVar,
			value="name", text="Residue name-based", command=
			self._switchHisList).grid(row=1, sticky='w')
		f = Tkinter.Frame(interior)
		f.grid(row=2)
		Tkinter.Label(f, text="HID/HIE/HIP = delta/epsilon/both").grid(
			row=0, sticky='w')
		self.hisDefault = Pmw.OptionMenu(f, initialitem=self.HB,
			items=[self.HB, "delta", "epsilon", "both"], labelpos='w',
			label_text="HIS = ", command=lambda a, s=self:
			setattr(s, 'hisChanged', True))
		self.hisDefault.grid(row=1, sticky='w')
		self._pickText = Tkinter.StringVar(parent)
		self._pickText.set("Specified individually...")
		Tkinter.Radiobutton(interior, variable=self.hisProtVar,
			value="pick", textvariable=self._pickText,
			command=self._switchHisList).grid(row=3, sticky='w')

		Tkinter.Button(parent, pady=0, command=self._colorKeyCB,
			text="Create corresponding color key").grid(row=7,
			column=0, columnspan=2)
		self.hisChanged = False
예제 #35
0
    def fillInUI(self, parent):
        import Pmw, Tkinter
        self.buttonWidgets['OK']['state'] = 'disabled'
        self.buttonWidgets['Apply']['state'] = 'disabled'
        from chimera.widgets import ModelScrolledListBox
        self.surfListBox = ModelScrolledListBox(
            parent,
            labelpos='n',
            label_text='Surfaces to color by ESP:',
            listbox_selectmode="extended",
            filtFunc=lambda m: isinstance(m, chimera.MSMSModel),
            selectioncommand=self._selSurfCB)
        self.surfListBox.grid(row=0, column=0, sticky="nsew", columnspan=2)
        Pmw.OptionMenu(parent,
                       command=self._menuCB,
                       initialitem="3",
                       items=[str(x) for x in range(2, 12)],
                       labelpos='w',
                       label_text="Number of colors/values:").grid(
                           row=1, column=0, columnspan=2)
        f = self.interpFrame = Tkinter.Frame(parent)
        f.grid(row=2, column=0, columnspan=2)
        self.wells = []
        self.values = []
        self._entryOpts = {
            'validate': 'real',
            'entry_justify': 'center',
            'entry_width': 6
        }
        from CGLtk.color.ColorWell import ColorWell
        for color, value in [("red", -10), ("white", 0), ("blue", 10)]:
            well = ColorWell(f, color=color)
            well.grid(row=0, column=len(self.wells))
            self.wells.append(well)
            entry = Pmw.EntryField(f, value=str(value), **self._entryOpts)
            entry.grid(row=1, column=len(self.values))
            self.values.append(entry)

        from chimera.tkoptions import FloatOption, BooleanOption
        self.distDep = BooleanOption(
            parent,
            3,
            "Distance-dependent dielectric",
            True,
            None,
            balloon="If true, charge falls off with distance squared to\n"
            "simulate solvent screening effects")
        self.dielectric = FloatOption(parent, 4, "Dielectric constant", 4.0,
                                      None)
        self.surfDist = FloatOption(parent,
                                    5,
                                    "Distance from surface",
                                    1.4,
                                    None,
                                    balloon="Potential at this distance from\n"
                                    "the surface is used for coloring")

        self.hisGroup = Pmw.Group(parent,
                                  hull_padx=2,
                                  tag_text="Implicit Histidine Protonation")
        self.hisGroup.grid(row=6, column=0, columnspan=2, sticky="nsew")
        self.hisProtVar = Tkinter.StringVar(parent)
        self.hisProtVar.set("name")
        interior = self.hisGroup.interior()
        interior.columnconfigure(0, weight=1)
        lab = Tkinter.Label(
            interior,
            text="Assumed histidine "
            "protonation for\nstructures without explicit hydrogens")
        from tkFont import Font
        font = Font(font=lab.cget('font'))
        font.config(size=int(0.75 * float(font.cget('size'))), slant='italic')
        lab.config(font=font)
        lab.grid(row=0)
        Tkinter.Radiobutton(interior,
                            variable=self.hisProtVar,
                            value="name",
                            text="Residue name-based",
                            command=self._switchHisList).grid(row=1,
                                                              sticky='w')
        f = Tkinter.Frame(interior)
        f.grid(row=2)
        Tkinter.Label(f,
                      text="HID/HIE/HIP = delta/epsilon/both").grid(row=0,
                                                                    sticky='w')
        self.hisDefault = Pmw.OptionMenu(
            f,
            initialitem=self.HB,
            items=[self.HB, "delta", "epsilon", "both"],
            labelpos='w',
            label_text="HIS = ",
            command=lambda a, s=self: setattr(s, 'hisChanged', True))
        self.hisDefault.grid(row=1, sticky='w')
        self._pickText = Tkinter.StringVar(parent)
        self._pickText.set("Specified individually...")
        Tkinter.Radiobutton(interior,
                            variable=self.hisProtVar,
                            value="pick",
                            textvariable=self._pickText,
                            command=self._switchHisList).grid(row=3,
                                                              sticky='w')

        Tkinter.Button(parent,
                       pady=0,
                       command=self._colorKeyCB,
                       text="Create corresponding color key").grid(
                           row=7, column=0, columnspan=2)
        self.hisChanged = False
class CreatePlaneDialog(ModelessDialog):
	title = "Define Plane"
	help = "ContributedSoftware/structuremeas/structuremeas.html#define-plane"
	provideStatus = True
	statusPosition = "above"

	def fillInUI(self, parent):
		import Pmw, Tkinter
		row = 0
		Tkinter.Label(parent, text="Create plane for selected atoms...").grid(
							row=row, columnspan=2)
		row += 1

		from chimera.tkoptions import StringOption, BooleanOption
		self.nameOpt = StringOption(parent, row, "Plane name", "plane", None)
		row += 1

		self.replaceExistingOpt = BooleanOption(parent, row,
										"Replace existing planes", False, None)
		row += 1

		from chimera.tkoptions import ColorOption, FloatOption
		self.colorOpt = ColorOption(parent, row, "Color", None, None,
			balloon="Plane color.  If No Color, then the plane"
			" will be colored to match the structure")
		row += 1

		self.autoRadiusOpt = BooleanOption(parent, row,
			"Set disk size to enclose atom projections", True, self._radCB)
		row += 1
		self.radRow = row
		self.radOffsetOpt = FloatOption(parent, row, "Extra radius"
			" (padding)", 0.0, None)
		self.radiusOpt = FloatOption(parent, row, "Fixed radius", 10.0, None)
		self.radiusOpt.forget()
		row += 1

		self.thicknessOpt = FloatOption(parent, row, "Disk thickness",
										prefs[PLANE_THICKNESS], None)

	def Apply(self):
		from chimera import UserError
		if self.replaceExistingOpt.get():
			planeManager.removePlanes(planeManager.planes)
		kw = {
			'color': self.colorOpt.get(),
			'thickness': self.thicknessOpt.get()
		}
		prefs[PLANE_THICKNESS] = kw['thickness']
		if self.autoRadiusOpt.get():
			kw['radiusOffset'] = self.radOffsetOpt.get()
		else:
			kw['radius'] = self.radiusOpt.get()

		replyobj.info("Creating plane\n")
		selAtoms = selection.currentAtoms()
		if len(selAtoms) < 3:
			self.enter()
			raise UserError("Need to select at least three"
					" atoms to define a plane")
		planeManager.createPlane(self.nameOpt.get().strip(), selAtoms, **kw)

	def _radCB(self, opt):
		if opt.get():
			self.radiusOpt.forget()
			self.radOffsetOpt.manage()
		else:
			self.radOffsetOpt.forget()
			self.radiusOpt.manage()
    def fillInUI(self, parent):
        Tkinter.Label(parent,
                      text="Collect positions of selected"
                      " atoms over trajectory",
                      relief="ridge",
                      bd=4).grid(row=0, column=0, columnspan=2, sticky="ew")

        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        from chimera.tkoptions import IntOption, BooleanOption, \
            FloatOption, StringOption
        self.startFrame = IntOption(parent,
                                    1,
                                    "Starting frame",
                                    startFrame,
                                    None,
                                    min=startFrame,
                                    max=endFrame,
                                    width=6)

        numFrames = endFrame - startFrame + 1
        defStride = 1 + int(numFrames / 300)
        self.stride = IntOption(parent,
                                2,
                                "Step size",
                                defStride,
                                None,
                                min=1,
                                max=numFrames,
                                width=3)

        self.endFrame = IntOption(parent,
                                  3,
                                  "Ending frame",
                                  endFrame,
                                  None,
                                  min=startFrame,
                                  max=endFrame,
                                  width=6)

        self.doCutoff = BooleanOption(
            parent, 4, 'Limit data collection'
            ' to within cutoff distance of any "held steady" atoms', True,
            None)

        self.cutoff = FloatOption(parent,
                                  5,
                                  "Cutoff distance",
                                  prefs[VOLUME_CUTOFF],
                                  None,
                                  width=4)
        self.resolution = FloatOption(parent,
                                      6,
                                      "Volume grid spacing",
                                      prefs[VOLUME_RESOLUTION],
                                      None,
                                      min=0.0001,
                                      width=4)
        self.volumeName = StringOption(parent,
                                       7,
                                       "Volume data name",
                                       self.movie.ensemble.name,
                                       None,
                                       width=20)
        self.byAtomType = BooleanOption(
            parent,
            8, "Collect data"
            " separately for each atom type in selection",
            True,
            None,
            balloon="Create a volume data set for"
            " each type of atom type\n(sp2 oxygen, aromatic carbon,"
            " etc.) in current selection")
예제 #38
0
    def __init__(self, parent, dialog, prefPrefix, callback):
        Pmw.Group.__init__(self, parent, tag_text="Line wrapping")
        self.__callback = callback
        self.__dialog = dialog
        self.__prefPrefix = prefPrefix

        self.__wrapVar = Tkinter.IntVar(dialog.uiMaster())
        if dialog.mav.prefs[prefPrefix + WRAP_IF]:
            self.__wrapVar.set(2)
        elif dialog.mav.prefs[prefPrefix + WRAP]:
            self.__wrapVar.set(0)
        else:
            self.__wrapVar.set(1)

        row = 0
        f = Tkinter.Frame(self.interior())
        f.grid(row=row, column=0, columnspan=2, sticky="w")
        b = Tkinter.Radiobutton(f,
                                text="Wrap to new line every ",
                                variable=self.__wrapVar,
                                value=0,
                                command=self.__newWrap)
        b.grid(row=0, column=0, sticky="e")
        self.__lineWidthEntry = Pmw.EntryField(
            f,
            command=self.__newWrap,
            labelpos="e",
            label_text="0 residues",
            entry_width=2,
            entry_justify='right',
            validate='numeric',
            value=dialog.mav.prefs[prefPrefix + LINE_WIDTH] / 10)
        self.__lineWidthEntry.grid(row=0, column=1, sticky="w")
        dialog._entryWidgets.append(self.__lineWidthEntry)
        row += 1

        if not prefPrefix:
            f = Tkinter.Frame(self.interior())
            f.grid(row=row, column=0, columnspan=2, sticky="w")
            b = Tkinter.Radiobutton(f,
                                    text="Wrap if ",
                                    variable=self.__wrapVar,
                                    value=2,
                                    command=self.__newWrap)
            b.grid(row=0, column=0, sticky="e")
            self.__wrapThresholdEntry = Pmw.EntryField(
                f,
                command=self.__newWrap,
                labelpos="e",
                entry_width=2,
                validate='numeric',
                entry_justify='center',
                label_text=" or fewer sequences",
                value=dialog.mav.prefs[prefPrefix + WRAP_THRESHOLD])
            self.__wrapThresholdEntry.grid(row=0, column=1, sticky="w")
            dialog._entryWidgets.append(self.__wrapThresholdEntry)
            row += 1

        b = Tkinter.Radiobutton(self.interior(),
                                text="Never wrap",
                                variable=self.__wrapVar,
                                value=1,
                                command=self.__newWrap)
        b.grid(row=row, column=0, columnspan=2, sticky="w")
        row += 1

        from chimera.tkoptions import BooleanOption
        BooleanOption(self.interior(), row, "Space between wrapped blocks",
                      dialog.mav.prefs[prefPrefix + BLOCK_SPACE],
                      self.__blockSpace)
예제 #39
0
class IlabelDialog(ModelessDialog):
	name = "2D Labels/Color Key"
	provideStatus = True
	buttons = ("Delete", "Close")

	LABELS = "Labels"
	COLOR_KEY = "Color Key"

	MOUSE_LABEL_TEXT = "Use mouse for label placement"
	MOUSE_KEY_TEXT = "Use mouse for key placement"

	EmphasisColor = "forest green"

	def __init__(self):
		import os.path
		myDir, junk = os.path.split(__file__)
		addFunction('place text', (self._pickLabel, self._moveLabel,
			None), icon=chimage.get(Image.open(os.path.join(myDir,
						'ilabel.png')), tkgui.app))
		addFunction('place key', (self._startOrGrabKey,
			self._sizeOrMoveKey, None), icon=chimage.get(
			Image.open(os.path.join(myDir, 'key.png')), tkgui.app))

		import Ilabel
		if not Ilabel._ilabelModel:
			Ilabel.IlabelModel()
		self.model = Ilabel._ilabelModel
		ModelessDialog.__init__(self)
		self._sessionHandlerID = chimera.triggers.addHandler(
					SAVE_SESSION, self._saveSession, None)
		self._closeHandlerID = chimera.triggers.addHandler(
					CLOSE_SESSION, self.destroy, None)
		self._beginRestoreHandlerID = chimera.triggers.addHandler(
				BEGIN_RESTORE_SESSION, self.destroy, None)
	
	def fillInUI(self, parent):
		top = parent.winfo_toplevel()
		menubar = Tkinter.Menu(top, type="menubar", tearoff=False)
		top.config(menu=menubar)

		self.fileMenu = Tkinter.Menu(menubar)
		menubar.add_cascade(label="File", menu=self.fileMenu)
		self.fileMenu.add_command(label="Write...", command=self._writeFileCB)
		self.fileMenu.add_command(label="Read...", command=self._readFileCB)
		from chimera.tkgui import aquaMenuBar
		aquaMenuBar(menubar, parent, row=0)

		from ColorKey import KeyModel
		parent.rowconfigure(1, weight=1)
		parent.columnconfigure(0, weight=1)
		# _pageRaisedCB uses mouseModeVar, so define first
		self.mouseLabelingVar = Tkinter.IntVar(parent)
		self.mouseLabelingVar.set(True)
		self.mlLabelVar = Tkinter.StringVar(parent)
		self.mouseModeButton = Tkinter.Checkbutton(parent,
					command=self._mouseFuncCB,
					variable=self.mouseLabelingVar,
					textvariable=self.mlLabelVar)
		self.mouseModeButton.grid(row=2, column=0)
		self.notebook = Pmw.NoteBook(parent,
					raisecommand=self._pageRaisedCB)
		self.notebook.add(self.LABELS, tab_text=self.LABELS)
		self.notebook.add(self.COLOR_KEY, tab_text=self.COLOR_KEY)
		self.notebook.grid(row=1, column=0, sticky="nsew")
		self._fillLabelsPage(self.notebook.page(self.LABELS))
		self.keyModel = KeyModel(self)
		self.keyPosition = None
		self._fillColorKeyPage(self.notebook.page(self.COLOR_KEY))

	def _fillLabelsPage(self, page):
		page.columnconfigure(0, weight=1)
		page.columnconfigure(1, weight=1)
		page.columnconfigure(2, weight=1)

		row = 0
		from CGLtk.Table import SortableTable
		self.labelTable = SortableTable(page, automultilineHeaders=False)
		self.labelTable.addColumn("Label [(x, y) text]", self._labelListing,
			anchor='w')
		self.labelTable.addColumn("Shown", "shown", format=bool)
		self.labelTable.setData(self.model.labels)
		self.labelTable.launch(browseCmd=self._tableCB, selectMode="single")
		self.labelTable.grid(row=row, column=0, columnspan=3, sticky="nsew")
		page.rowconfigure(row, weight=1)
		row += 1

		self.labelText = Pmw.ScrolledText(page, labelpos='w',
			label_text="Text", text_height=3, text_width=20,
			text_wrap='none', text_state='disabled',
			text_exportselection=False)
		text = self.labelText.component('text')
		text.bind("<<Modified>>", self._textCB)
		text.bind("<<Selection>>", self._updateTextAttrWidgets)
		self.labelText.grid(row=row, column=0,
						sticky='nsew', columnspan=3)
		page.rowconfigure(row, weight=1)
		row += 1

		self.labelSymbolMenu = Pmw.OptionMenu(page, labelpos='w',
			label_text="Insert symbol:", command=self._insertSymbol,
			items=[
				u'\N{GREEK SMALL LETTER ALPHA}',
				u'\N{GREEK SMALL LETTER BETA}',
				u'\N{GREEK SMALL LETTER GAMMA}',
				u'\N{GREEK SMALL LETTER DELTA}',
				u'\N{GREEK SMALL LETTER EPSILON}',
				u'\N{GREEK SMALL LETTER PI}',
				u'\N{GREEK SMALL LETTER PHI}',
				u'\N{GREEK SMALL LETTER CHI}',
				u'\N{GREEK SMALL LETTER PSI}',
				u'\N{GREEK SMALL LETTER OMEGA}',
				u'\N{LEFTWARDS ARROW}',
				u'\N{RIGHTWARDS ARROW}',
				u'\N{LEFT RIGHT ARROW}',
				u'\N{UPWARDS ARROW}',
				u'\N{DOWNWARDS ARROW}',
				u'\N{SUPERSCRIPT TWO}',
				u'\N{SUPERSCRIPT THREE}',
				u'\N{DEGREE SIGN}',
				u'\N{LATIN CAPITAL LETTER A WITH RING ABOVE}',
				"more..."
			])
		self.labelSymbolMenu.grid(row=row, column=0, columnspan=3)

		row += 1

		colorHouse = Pmw.LabeledWidget(page, labelpos='w',
			label_text="Color")
		colorHouse.grid(row=row, column=0, rowspan=3)
		from CGLtk.color.ColorWell import ColorWell
		self.colorWell = ColorWell(colorHouse.interior(),
			color=self._contrastWithBG(), callback=self._colorCB)
		self.colorWell.grid()

		from chimera.tkoptions import IntOption
		self.labelFontSize = IntOption(page, row, "Font size", 24,
					self._labelChangeCB, startCol=1, min=1,
					attribute="size", width=3)
		row += 1
		self.labelFontStyle = FontStyle(page, row, "Font style",
			oglFont.normal, self._labelChangeCB, startCol=1)
		row += 1
		self.labelFontTypeface = FontTypeface(page, row, "Font typeface",
					FONT_TYPEFACE_VALUES[0],
					self._labelChangeCB, startCol=1)
		row += 1

		if self.model.curLabel:
			self.changeToLabel(self.model.curLabel, force=True)

	def _fillColorKeyPage(self, page):
		from chimera.tkoptions import IntOption, EnumOption, \
						BooleanOption, RGBAOption
		f = Tkinter.Frame(page)
		f.grid(row=0, columnspan=2)
		self.numComponents = IntOption(f, 0, "Number of colors/labels",
					3, self._componentsCB, min=2, width=2)
		self.componentsFrame = Tkinter.Frame(page)
		self.componentsFrame.grid(row=1, column=0, sticky="nsew",
							columnspan=2)
		page.columnconfigure(0, weight=1)
		self.componentsFrame.columnconfigure(1, weight=1)
		class ColorTreatment(EnumOption):
			values = ("distinct", "blended")
		self.colorTreatment = ColorTreatment(page, 2,
			"Color range depiction", "blended", self._keyChangeCB,
			balloon="Should colors be shown as distinct rectangles"
			" or as a continuous range")
		class LabelPosition(EnumOption):
			values = ("left/top", "right/bottom")
		self.labelPos = LabelPosition(page, 3, "Label positions",
			"right/bottom", self._keyChangeCB, balloon="Position of"
			" labels relative to color key.\nLabels always"
			" positioned adjacent to long side.")
		self.labelColor = RGBAOption(page, 4, "Label color",
			self._contrastWithBG(), self._keyChangeCB, balloob=
			"Label color.  If set to 'No color', use corresponding"
			" key color", noneOkay=True)
		class LabelJustification(EnumOption):
			values = ("left", "decimal point", "right")
		self.justification = LabelJustification(page, 5,
			"Label justification", "decimal point",
			self._keyChangeCB, balloon="Justification of label text"
			" in a vertical key layout.\nHorizontal key labels will"
			" always be center justified.")
		self.labelOffset = IntOption(page, 6, "Label offset", 0,
			self._keyChangeCB, width=3, balloon="Additional offset"
			" of labels from color bar, in pixels")
		self.keyFontSize = IntOption(page, 7, "Font size", 24,
			self._keyChangeCB, width=3)
		self.keyFontStyle = FontStyle(page, 8, "Font style",
			oglFont.normal, self._keyChangeCB)
		self.keyFontTypeface = FontTypeface(page, 9, "Font typeface",
			FONT_TYPEFACE_VALUES[0], self._keyChangeCB)
		self.borderColor = RGBAOption(page, 10, "Border color",
			None, self._keyChangeCB, balloon="Color of border"
			" around color key (not each individual color).\n"
			"If 'no color', then no border is drawn.")
		self.borderWidth = IntOption(page, 11, "Border width", 3,
			self._keyChangeCB, balloon="in pixels")
		self.tickMarks = BooleanOption(page, 12, "Show tick marks",
			False, self._keyChangeCB, balloon="Show tick marks"
			" pointing from key to labels")
		self._componentsCB(self.numComponents)

	def destroy(self, *args):
		self.mouseLabelingVar.set(True)
		self.mouseModeButton.invoke()
		chimera.triggers.deleteHandler(SAVE_SESSION,
							self._sessionHandlerID)
		chimera.triggers.deleteHandler(CLOSE_SESSION,
							self._closeHandlerID)
		chimera.triggers.deleteHandler(BEGIN_RESTORE_SESSION,
						self._beginRestoreHandlerID)
		chimera.openModels.close([self.model, self.keyModel])
		ModelessDialog.destroy(self)

	def map(self, e=None):
		self._pageRaisedCB(self.notebook.getcurselection())

	def unmap(self, e=None):
		self.mouseLabelingVar.set(True)
		self.mouseModeButton.invoke()

	def changeToLabel(self, nextLabel, force=False):
		if nextLabel == self.model.curLabel and not force:
			return
		if self.model.curLabel and not unicode(self.model.curLabel) \
		and self.model.curLabel != nextLabel:
			# remove previous label if empty
			self.removeLabel(self.model.curLabel)
		self.model.changeToLabel(nextLabel)
		self.labelText.component('text').configure(state='normal')
		self.labelTable.select(nextLabel)
		self.labelText.settext(unicode(nextLabel))
		text = self.labelText.component('text')
		lineIndex = 1
		for line in self.model.curLabel.lines:
			charIndex = 0
			for c in line:
				text.tag_add(id(c),
					"%d.%d" % (lineIndex, charIndex))
				charIndex += 1
			text.tag_add(id(line), "%d.%d" % (lineIndex, charIndex))
			lineIndex += 1
				
	def Delete(self):
		if self.notebook.getcurselection() == self.LABELS:
			self.labelText.clear()
			if not self.model.curLabel:
				self.status("No label to delete", color="red",
								blankAfter=10)
				return
			self.removeLabel(self.model.curLabel)
			self.labelText.component('text').configure(
							state='disabled')
		else:
			self.keyPosition = None
			self._keyChangeCB()

	def Help(self):
		helpLoc = "ContributedSoftware/2dlabels/2dlabels.html"
		if self.notebook.getcurselection() == self.COLOR_KEY:
			helpLoc += "#colorkey"
		chimera.help.display(helpLoc)

	def keyConfigure(self, data, pageChange=True):
		self._componentsCB(len(data), update=False)
		for datum, well, label in zip(data, self.wells, self.labels):
			color, text = datum
			well.showColor(color, doCallback=False)
			label.variable.set(text, invoke_callbacks=False)
		self._keyChangeCB()
		if pageChange:
			self.notebook.selectpage(self.COLOR_KEY)

	def makeChar(self, char, model):
		attrs = {}
		try:
			attrs['rgba'] = self.colorWell.rgba
		except AttributeError: # multi or None
			if model:
				attrs['rgba'] = model.rgba
		size = self.labelFontSize.get()
		if size is not None:
			attrs['size'] = size
		style = self.labelFontStyle.get()
		if style is not None:
			attrs['style'] = style
		fontName = self.labelFontTypeface.get()
		if fontName is not None:
			attrs['fontName'] = fontName
		return Character(char, **attrs)

	def newLabel(self, pos):
		label = self.model.newLabel(pos)
		self.labelTable.setData(self.model.labels)
		self.status("Mouse drag to reposition label",
						color=self.EmphasisColor)
		return label

	def removeLabel(self, label):
		self.model.removeLabel(label)
		self.labelTable.setData(self.model.labels)
		if self.model.curLabel is not None:
			self.labelTable.select(self.model.curLabel)

	def reverseKey(self):
		data = zip([w.rgba for w in self.wells],
				[l.variable.get() for l in self.labels])
		data.reverse()
		self.keyConfigure(data)
	def setLabelFromText(self):
		curLabel = self.model.curLabel
		text = self.labelText.component('text')
		# delete parts of label not in text...
		#
		# newlines first...
		while len(curLabel.lines) > 1:
			for i, line in enumerate(curLabel.lines[:-1]):
				if not text.tag_ranges(id(line)):
					curLabel.lines[i+1][:0] = line
					del curLabel.lines[i]
					break
			else:
				break
		# characters...
		for line in curLabel.lines:
			for c in line[:]:
				if not text.tag_ranges(id(c)):
					line.remove(c)
		
		# get new parts of text into label
		model = None
		targets = []
		lines = curLabel.lines
		for line in lines:
			targets.extend([id(c) for c in line])
			if not model and line:
				model = line[0]
			if line is not lines[-1]:
				targets.append(id(line))
		contents = self.labelText.get()[:-1] # drop trailing newline

		if targets:
			target = targets.pop(0)
		else:
			target = None

		textLine = 1
		textIndex = -1
		curLine = lines[0]
		for c in contents:
			textIndex += 1
			if str(target) in text.tag_names("%d.%d"
						% (textLine, textIndex)):
				if targets:
					target = targets.pop(0)
				else:
					target = None
				if c == '\n':
					textLine += 1
					textIndex = -1
					curLine = lines[[id(l)
							for l in lines].index(
							id(curLine))+1]
				elif curLine:
					model = curLine[textIndex]
			elif c == '\n':
				insertLine = curLine[0:textIndex]
				lines.insert(textLine-1, insertLine)
				del curLine[0:textIndex]
				text.tag_add(id(insertLine), "%d.%d"
							% (textLine, textIndex))
				textLine += 1
				textIndex = -1
			else:
				labelChar = self.makeChar(c, model)
				curLine.insert(textIndex, labelChar)
				text.tag_add(id(labelChar), "%d.%d"
							% (textLine, textIndex))
		self.model.setMajorChange()

	def updateGUI(self, source="gui"):
		curLabel = self.model.curLabel
		if curLabel and source == "gui":
			self.setLabelFromText()
		self.labelTable.setData(self.model.labels)
		if curLabel:
			self.labelTable.select(curLabel)
		self._updateTextAttrWidgets()

	def _colorCB(self, color):
		curLabel = self.model.curLabel
		if not curLabel:
			self.status("No label to color", color='red')
			return
		self.model.setMajorChange()
		for c in self._selChars():
			c.rgba = color

	def _componentsCB(self, opt, update=True):
		cf = self.componentsFrame
		if hasattr(self, 'wells'):
			for well in self.wells:
				well.grid_forget()
				well.destroy()
			for label in self.labels:
				label.frame.grid_forget()
			self.reverseButton.grid_forget()
			self.reverseButton.destroy()
		else:
			Tkinter.Label(cf, text="Colors").grid(row=0)
			Tkinter.Label(cf, text="Labels").grid(row=0, column=1)
		if isinstance(opt, int):
			numComponents = opt
			self.numComponents.set(opt)
		else:
			numComponents = opt.get()
		wellSize = min(38, int( (7 * 38) / numComponents ))
		from CGLtk.color.ColorWell import ColorWell
		self.wells = []
		self.labels = []
		from CGLtk import Hybrid
		for i in range(numComponents):
			well = ColorWell(cf, width=wellSize, height=wellSize,
				callback=self._keyChangeCB, color='white')
			well.grid(row=i+1)
			self.wells.append(well)
			label = Hybrid.Entry(cf, "", 10)
			label.variable.add_callback(self._keyTypingCB)
			label.frame.grid(row=i+1, column=1, sticky='ew')
			self.labels.append(label)
		self.reverseButton = Tkinter.Button(cf, command=self.reverseKey,
				text="Reverse ordering of above", pady=0)
		self.reverseButton.grid(row=numComponents+1, column=0,
								columnspan=2)
		self.notebook.setnaturalsize()
		if update:
			self._keyChangeCB()

	def _contrastWithBG(self):
		bg = chimera.viewer.background
		if bg:
			bgColor = bg.rgba()
		else:
			bgColor = (0, 0, 0)
		if bgColor[0]*2 + bgColor[1]*3 + bgColor[2] < 0.417:
			return (1, 1, 1)
		else:
			return (0, 0, 0)

	def _eventToPos(self, viewer, event, offset = (0, 0)):
		w, h = viewer.windowSize
		return (event.x - offset[0]) / float(w), \
				(h - event.y - offset[1]) / float(h)
		
	def _handleTextChange(self):
		self.updateGUI()
		self.labelText.edit_modified(False)

	def _insertSymbol(self, item):
		if len(item) > 1:
			from chimera import help
			help.display("ContributedSoftware/2dlabels/symbols.html")
			return
		if not self.model.labels:
			self.status("No labels have been created yet", color="red")
			return
		if not self.labelTable.selected():
			self.status("No labels active", color="red")
		self.labelText.insert("insert", item)
		self.setLabelFromText()

	def _keyChangeCB(self, *args):
		self.keyModel.setMajorChange()

	def _keyTypingCB(self, fromAfter=False):
		# wait for a pause in typing before updating key...
		if fromAfter:
			self._typingHandler = None
			self._keyChangeCB()
			return
		handle = getattr(self, '_typingHandler', None)
		if handle:
			self.componentsFrame.after_cancel(handle)
		self._typingHandler = self.componentsFrame.after(500,
				lambda: self._keyTypingCB(fromAfter=True))

	def _labelChangeCB(self, option):
		curLabel = self.model.curLabel
		self.model.setMajorChange()
		val = option.get()
		attrName = option.attribute
		for c in self._selChars():
			setattr(c, attrName, val)

	def _labelListing(self, label):
		text = unicode(label)
		if '\n' in text:
			newline = text.index('\n')
			text= text[:newline] + "..." 
		if not text:
			text = "<empty>"
		return "(%.2f, %.2f) %s" % (label.pos[0], label.pos[1], text)

	def _mouseFuncCB(self):
		self.status("")
		if not self.mouseLabelingVar.get():
			if hasattr(self, "_prevMouse"):
				setButtonFunction("1", (), self._prevMouse)
				delattr(self, "_prevMouse")
		elif self.mlLabelVar.get() == self.MOUSE_LABEL_TEXT:
			if not hasattr(self, "_prevMouse"):
				self._prevMouse = getFuncName("1", ())
			setButtonFunction("1", (), "place text")
		else:
			if not hasattr(self, "_prevMouse"):
				self._prevMouse = getFuncName("1", ())
			setButtonFunction("1", (), "place key")

	def _moveLabel(self, viewer, event):
		pos = self._eventToPos(viewer, event, self._moveOffset)
		self.model.moveLabel(pos)
		curLabel = self.model.curLabel
		self.labelTable.setData(self.model.labels)
		self.labelTable.select(curLabel)
		
	def _pageRaisedCB(self, pageName):
		if pageName == "Labels":
			pageItem = self.MOUSE_LABEL_TEXT
			if not self.model.labels:
				self.status("Click mouse button 1 in graphics\n"
						"window to place first label",
						color=self.EmphasisColor)
			for index in range(0, self.fileMenu.index('end')+1):
				self.fileMenu.entryconfigure(index, state='normal')
		else:
			pageItem = self.MOUSE_KEY_TEXT
			self.status("Drag mouse to position/size key",
						color=self.EmphasisColor)
			for index in range(0, self.fileMenu.index('end')+1):
				self.fileMenu.entryconfigure(index, state='disabled')
		self.mlLabelVar.set(pageItem)
		# just setting the var doesn't cause the callback, and
		# yet using invoke() toggles the var, so set it _opposite_
		# to what's desired before calling invoke()
		self.mouseLabelingVar.set(False)
		self.mouseModeButton.invoke()
		
	def _pickLabel(self, viewer, event):
		w, h = viewer.windowSize
		pos = self._eventToPos(viewer, event)
		label, self._moveOffset = self.model.pickLabel(pos, w, h)
		if label is None:
			label = self.newLabel(pos)
			self._moveOffset = (0, 0)
		self.changeToLabel(label)
		self.labelText.component('text').focus_set()

	def _readFile(self, okayed, dialog):
		if not okayed:
			return
		from Ilabel import readFiles
		readFiles(dialog.getPaths(), clear=dialog.deleteExistingVar.get())

	def _readFileCB(self):
		if not hasattr(self, "_readFileDialog"):
			self._readFileDialog = ReadFileDialog(
				command=self._readFile, clientPos='s')
		self._readFileDialog.enter()

	def _restoreSession(self, info):
		if info["sel ranges"]:
			self.labelText.tag_add("sel", *info["sel ranges"])
		self._updateTextAttrWidgets()
		self._suppressMap = True
		self.labelText.edit_modified(False)
		if "key position" not in info:
			self.notebook.selectpage(self.LABELS)
			if info["mouse func"] == "normal":
				self.mouseLabelingVar.set(True)
				self.mouseModeButton.invoke()
			return
		self.keyPosition = info["key position"]
		self.colorTreatment.set(info["color depiction"])
		self.labelPos.set(info["label positions"])
		self.labelColor.set(info["label color"])
		self.justification.set(info["label justification"])
		self.labelOffset.set(info["label offset"])
		self.keyFontSize.set(info["font size"])
		self.keyFontStyle.set(info["font typeface"])
		if "font name" in info:
			self.keyFontTypeface.set(info["font name"])
		self.borderColor.set(info["border color"])
		self.borderWidth.set(info["border width"])
		self.tickMarks.set(info["show ticks"])
		self.keyConfigure(info["colors/labels"])
		if self.keyPosition:
			self.notebook.selectpage(self.COLOR_KEY)
		else:
			self.notebook.selectpage(self.LABELS)
		if info["mouse func"] == "normal":
			self.mouseLabelingVar.set(True)
			self.mouseModeButton.invoke()
		return info

	def _saveSession(self, triggerName, myData, sessionFile):
		print>>sessionFile, """
def restore2DLabelDialog(info):
	from chimera.dialogs import find, display
	from Ilabel.gui import IlabelDialog
	dlg = find(IlabelDialog.name)
	if dlg is not None:
		dlg.destroy()
	dlg = display(IlabelDialog.name)
	dlg._restoreSession(info)

import SimpleSession
SimpleSession.registerAfterModelsCB(restore2DLabelDialog, %s)

""" % repr(self._sessionInfo())

	def _selChars(self):
		chars = []
		curLabel = self.model.curLabel
		if curLabel:
			sel = self.labelText.tag_ranges("sel")
			if sel:
				sline, schar = [int(x)
					for x in str(sel[0]).split('.')]
				eline, echar = [int(x)
					for x in str(sel[1]).split('.')]
				sline -= 1
				eline -= 1
				for li, line in enumerate(curLabel.lines):
					if li < sline:
						continue
					if li > eline:
						break
					if sline == eline:
						chars.extend(line[schar:echar])
					elif li == sline:
						chars.extend(line[schar:])
					elif li == eline:
						chars.extend(line[:echar])
					else:
						chars.extend(line)
			else:
				for l in curLabel.lines:
					chars.extend(l)
		return chars

	def _sessionInfo(self):
		info = {}
		info["sel ranges"] = tuple([str(tr)
				for tr in self.labelText.tag_ranges("sel")])
		if self.mouseLabelingVar.get():
			info["mouse func"] = "labeling"
		else:
			info["mouse func"] = "normal"
		info["key position"] = self.keyPosition
		info["colors/labels"] = [(w.rgba, l.variable.get())
				for w, l in zip(self.wells, self.labels)]
		info["color depiction"] = self.colorTreatment.get()
		info["label positions"] = self.labelPos.get()
		info["label color"] = self.labelColor.get()
		info["label justification"] = self.justification.get()
		info["label offset"] = self.labelOffset.get()
		info["font size"] = self.keyFontSize.get()
		info["font typeface"] = self.keyFontStyle.get()
		info["font name"] = self.keyFontTypeface.get()
		info["border color"] = self.borderColor.get()
		info["border width"] = self.borderWidth.get()
		info["show ticks"] = self.tickMarks.get()
		return info

	def _sizeOrMoveKey(self, viewer, event):
		pos = self._eventToPos(viewer, event)
		if self.grabPos:
			deltas = [pos[axis] - self.grabPos[axis]
							for axis in [0, 1]]
			for posIndex in [0, 1]:
				old = self.keyPosition[posIndex]
				self.keyPosition[posIndex] = (
					old[0] + deltas[0], old[1] + deltas[1])
			self.grabPos = pos
		elif len(self.keyPosition) == 1:
			self.keyPosition.append(pos)
		else:
			self.keyPosition[1] = pos
		self._keyChangeCB()
		
	def _startOrGrabKey(self, viewer, event):
		pos = self._eventToPos(viewer, event)
		if self.keyPosition and len(self.keyPosition) == 2:
			# possible grab;
			# see if in middle third of long side...
			p1, p2 = self.keyPosition
			x1, y1 = p1
			x2, y2 = p2
			if abs(x2 - x1) < abs(y2 - y1):
				longAxis = 1
				ymin = min(y2, y1)
				ymax = max(y2, y1)
				b1 = (2* ymin + ymax) / 3.0
				b2 = (2* ymax + ymin) / 3.0
				o1 = min(x1, x2)
				o2 = max(x1, x2)
			else:
				longAxis = 0
				xmin = min(x2, x1)
				xmax = max(x2, x1)
				b1 = (2* xmin + xmax) / 3.0
				b2 = (2* xmax + xmin) / 3.0
				o1 = min(y1, y2)
				o2 = max(y1, y2)
			if b1 < pos[longAxis] < b2 \
			and o1 < pos[1-longAxis] < o2:
				self.grabPos = pos
				return
		self.grabPos = None
		self.keyPosition = [pos]
		self._keyChangeCB()
		self.status("Grab middle of key to reposition",
						color=self.EmphasisColor)

	def _tableCB(self, sel):
		if not sel:
			return
		self.changeToLabel(sel)

	def _textCB(self, e):
		text = self.labelText.component('text')
		if not text.tk.call((text._w, 'edit', 'modified')):
		#if not text.edit_modified():
			return
		# this callback can happen _before_ the change
		# actually occurs, so do the processing after idle
		text.after_idle(self._handleTextChange)

	def _updateTextAttrWidgets(self, e=None):
		rgba = None
		multiple = False
		for c in self._selChars():
			if rgba is None:
				rgba = c.rgba
			elif rgba != c.rgba:
				multiple = True
				break
		if rgba is not None:
			self.colorWell.showColor(rgba, multiple=multiple,
							doCallback=False)
			self.labelFontSize.display(self._selChars())
			self.labelFontStyle.display(self._selChars())
			self.labelFontTypeface.display(self._selChars())

	def _writeFile(self, okayed, dialog):
		if not okayed:
			return
		from Ilabel import writeFile
		writeFile(dialog.getPaths()[0])

	def _writeFileCB(self):
		if not hasattr(self, "_writeFileDialog"):
			from OpenSave import SaveModeless
			self._writeFileDialog = SaveModeless(command=self._writeFile,
				title="Write 2D Labels Info")
		self._writeFileDialog.enter()
class ImageSaveDialog(ModelessDialog):

	name = "Save Image"
	buttons = ['Tips', 'Save As', Cancel]
	default = 'Save As'
	help = 'UsersGuide/print.html'
	provideStatus = True

	def fillInUI(self, master):
		self._ModelTrigger = None
		#self._SetupTrigger = None
		self._SizeTrigger = None
		self.raytrace = None
		# Image Size
		imageSetup = Tix.LabelFrame(master, label="Image Size")
		imageSetup.pack(fill=Tk.X, ipadx=2, ipady=2)
		subframe = imageSetup.frame
		#subframe = Tk.Frame(imageSetup.frame)
		#subframe.pack(fill=Tk.BOTH, expand=1)

		# add in conversion factor for pixels and graphics screen
		from chimera import tkgui
		win = tkgui.app.graphics
		res = tkgui.getScreenMMWidth() / win.winfo_screenwidth()
		convert['pixels'] = mm2pt(res)

		self.matchAspect = Tk.BooleanVar(master)
		self.matchAspect.set(1)

		self.usePrint = Tk.BooleanVar(master)
		self.usePrint.set(preferences.get(IMAGE_SETUP, USE_PRINT_UNITS))
		import itertools
		row = itertools.count()

		self.showUsePrint = Tk.Checkbutton(subframe, indicatoron=1,
				variable=self.usePrint, highlightthickness=0,
				text=USE_PRINT_UNITS,
				command=self._updateUsePrint)
		self.showUsePrint.grid(columnspan=2, row=row.next(), sticky=Tk.W)

		w, h = chimera.viewer.windowSize
		self.units = ImageUnitsOption(subframe, row.next(), UNITS,
						'pixels', self.updateImageUnits)
		self.iWidth = FloatOption(subframe, row.next(), 'Image width',
					w, self.updateImageWidth, min=1e-10)
		self.iHeight = FloatOption(subframe, row.next(), 'Image height',
					h, self.updateImageHeight, min=1e-10)

		matchAspect = Tk.Checkbutton(subframe, indicatoron=1,
				variable=self.matchAspect, highlightthickness=0,
				text="Maintain current aspect ratio",
				command=self.updateMatchAspect)
		matchAspect.grid(columnspan=2, row=row.next(), sticky=Tk.W)
		self.grow = Tk.Button(imageSetup.frame, text="Grow to Fit",
					command=self.Resize, state=Tk.DISABLED)
		fitrow = row.next()
		self.grow.grid(row=fitrow, column=0, padx=2, pady=2,
								sticky=Tk.NSEW)
		self.shrink = Tk.Button(imageSetup.frame, text="Shrink to Fit",
				command=lambda f=self.Resize: f(False),
				state=Tk.DISABLED)
		self.shrink.grid(row=fitrow, column=1, padx=2, pady=2,
								sticky=Tk.NSEW)

		#fetch = Tk.Button(imageSetup.frame, text="Get Pixels",
		#				command=self.fetchWindowSize)
		#fetch.grid(row=row.next(), column=0, padx=2, pady=2, sticky=Tk.NSEW)

		#calc = Tk.Button(imageSetup.frame, text="Image Setup",
		#			command=self.showImageSetupDialog)
		#calc.grid(row=row.next(), column=1, padx=2, pady=2, sticky=Tk.NSEW)

		self.printRes = FloatOption(subframe, row.next(), DPI,
				preferences.get(IMAGE_SETUP, DPI),
				self._updatePrint, min=1)

		# Image Information
		info = Tix.LabelFrame(master, label="Image Information")
		info.pack(fill=Tk.X)
		d = Tk.Label(info.frame, text="Description:")
		d.grid(columnspan=2, row=0, column=0, sticky=Tk.W, padx=2,
									pady=1)
		self.description = Tk.Entry(info.frame)
		info.frame.grid_columnconfigure(0, weight=1)
		info.frame.grid_columnconfigure(1, weight=1)
		self.description.grid(columnspan=2, row=1, column=0,
						sticky=Tk.EW, padx=2, pady=2)
		imageCredits = Tk.Button(info.frame,
					text="Image Credits",
					command=self.showImageCreditsDialog)
		imageCredits.grid(row=2, column=0, padx=2, pady=2)
		credit = Tk.Button(info.frame, text="Citing Chimera",
				command=lambda: help.display("credits.html"))
		credit.grid(row=2, column=1, padx=2, pady=2)

		# Image camera
		self.raytrace = BooleanOption(master, -1,
				'Raytrace with POV-Ray', False,
				self._updateRaytrace)
		self.raytraceOptions = Tk.Button(master, text=POVRAY_SETUP,
					command=self.showPOVRayOptions)
		self.raytraceOptions.pack()
		self.raytraceOptions.pack_forget()
		self.supersample = SupersampleOption(master, -1, SUPERSAMPLE,
				preferences.get(IMAGE_SETUP, SUPERSAMPLE),
				self._updateSS)
		self.adjustFOV = AdjustFOVOption(master, -1, ADJUST_FOV,
				preferences.get(IMAGE_SETUP, ADJUST_FOV),
				self._updateAdjustFOV)
		self.printMode = _PrintModeOption(master, -1,
				'Image camera mode', _PrintModeOption.SAME,
				self._updatePrintMode)
		self.lenticular = IntOption(master, -1,
				'Number of lenticular images',
				chimera.Camera.lenticularImageCount(),
				self._updateLenticular, min=2, width=4)
		self.lenticular.forget()

		# switch to user's prefered units
		self.adjust = convert['pixels']
		units = preferences.get(IMAGE_SETUP, UNITS)
		self._updateUsePrint()
		self.units.set(units)
		self.updateImageUnits()

	def map(self, event=None):
		self._ModelTrigger = chimera.triggers.addHandler('Model',
						self._computeMaxLineWidth, None)
		#self._SetupTrigger = chimera.triggers.addHandler(IMAGE_SETUP,
		#				self._computeMaxLineWidth, None)
		self._SizeTrigger = chimera.triggers.addHandler(
				'graphics window size', self._resetSize, None)
		self._computeMaxLineWidth()

	def unmap(self, event=None):
		if self._ModelTrigger:
			chimera.triggers.deleteHandler('Model',
							self._ModelTrigger)
			self._ModelTrigger = None
		#if self._SetupTrigger:
		#	chimera.triggers.deleteHandler(IMAGE_SETUP,
		#					self._SetupTrigger)
		#	self._SetupTrigger = None

	def _computeMaxLineWidth(self, *args):
		if self.raytrace and self.raytrace.get():
			# not relevant if raytracing
			self.status('', blankAfter=0)
			return
		# this should be called models are modified, when the
		# image size changes and when image setup parameters
		# change (DPI, supersampling)
		opengl_max = min(
				chimera.opengl_getFloat("max point size"),
				chimera.opengl_getFloat("max line width"))
		max_lw = max([m.lineWidth
				for m in chimera.openModels.list(all=True)
					if hasattr(m, 'lineWidth')])
		# compute tile scaling factor like C++ code does
		width = self.iWidth.get()
		height = self.iHeight.get()
		horizPixels, vertPixels, supersample = \
				imageArgs(self.units.get(), width, height)
		width, height = chimera.viewer.windowSize
		tileScale = float(horizPixels) / float(width)
		tmp = float(vertPixels) / float(height)
		if tmp > tileScale:
			tileScale = tmp
		tileScale *= supersample

		opengl_max /= tileScale
		if max_lw > opengl_max:
			color = 'red'
		else:
			color = 'black'
		self.status('effective maximum line width is %g' % opengl_max,
				color=color, blankAfter=0)

	#def Print(self):
	#	self.Cancel()
	#	image, options = self.getImage()
	#	filename = tempfile.mktemp()
	#	image.save(filename, **options)
	#	cmd = preferences.get(PAGE_SETUP, PRINTER_CMD)
	#	cmd = re.sub('%s', "'" + filename + "'", cmd)
	#	os.system(cmd)
	#	os.unlink(filename)

	def SaveAs(self):
		# now save the image
		self.Cancel()
		printMode = self.printMode.get()
		raytrace = self.raytrace.get()
		if printMode == _PrintModeOption.SAME:
			printMode = None
		if not chimera.nogui and raytrace and chimera.viewer.clipping:
			dialog = ClipWarning()
			if not dialog.run(chimera.tkgui.app):
				return
		saveImage(None, self.iWidth.get(), self.iHeight.get(), 
				units=self.units.get(), master=self.uiMaster(),
				description=self.description.get().strip(),
				printMode=printMode, raytrace=raytrace)

	def Tips(self):
		import help
		help.display(self.help + "#tips")

	def Resize(self, larger=True):
		vw, vh = chimera.viewer.windowSize
		iw = self.iWidth.get()
		ih = self.iHeight.get()
		vaspect = vw / float(vh)
		iaspect = iw / float(ih)
		from chimera import tkgui
		top = tkgui.app.winfo_toplevel()
		if larger:
			if vaspect < iaspect:
				w = int(vw * iaspect / vaspect + 0.5)
				if w != vw:
					top.wm_geometry('')
					tkgui.app.graphics.config(width=w)
			elif vaspect > iaspect:
				h = int(vh * vaspect / iaspect + 0.5)
				if h != vh:
					top.wm_geometry('')
					tkgui.app.graphics.config(height=h)
		else:
			if vaspect < iaspect:
				h = int(vh * vaspect / iaspect + 0.5)
				if h != vh:
					top.wm_geometry('')
					tkgui.app.graphics.config(height=h)
			elif vaspect > iaspect:
				w = int(vw * iaspect / vaspect + 0.5)
				if w != vw:
					top.wm_geometry('')
					tkgui.app.graphics.config(width=w)

	def fetchWindowSize(self):
		w, h = chimera.viewer.windowSize
		self.units.set('pixels')
		self.updateImageUnits()
		self.iWidth.set(w)
		self.iHeight.set(h)

	def _updateRaytrace(self, option):
		raytrace = option.get()
		if raytrace:
			self.printMode.forget()
			self.lenticular.forget()
			self.supersample.forget()
			self.raytraceOptions.pack()
		else:
			self.raytraceOptions.pack_forget()
			self.printMode.manage()
			self.supersample.manage()
			self._updatePrintMode(self.printMode)
		self._computeMaxLineWidth()

	def _updatePrintMode(self, option):
		printMode = option.get()
		if printMode == 'lenticular':
			self.lenticular.manage()
		else:
			self.lenticular.forget()

	def _updateLenticular(self, option):
		count = option.get()
		chimera.Camera.setLenticularImageCount(count)

	def updateMatchAspect(self, *args):
		if self.matchAspect.get():
			self.grow.config(state=Tk.DISABLED)
			self.shrink.config(state=Tk.DISABLED)
			self.Resize()
		else:
			self.grow.config(state=Tk.NORMAL)
			self.shrink.config(state=Tk.NORMAL)

	def updateImageUnits(self, *args):
		units = self.units.get()
		if units == 'pixels':
			self.printRes.disable()
			self.adjustFOV.disable()
		else:
			self.printRes.enable()
			self.adjustFOV.enable()
		if units != preferences.get(IMAGE_SETUP, UNITS):
			preferences.set(IMAGE_SETUP, UNITS, units)
		try:
			adjust = convert[units]
		except KeyError:
			adjust = -1
		if adjust == self.adjust:
			return
		if self.adjust != -1 and adjust != -1:
			factor = self.adjust / adjust
			w = self.iWidth.get() * factor
			self.iWidth.set(w)
			h = self.iHeight.get() * factor
			self.iHeight.set(h)
		if adjust == -1:
			# entering pixel mode
			w, h = chimera.viewer.windowSize
			self.iWidth.set(w)
			self.iHeight.set(h)
		elif self.adjust == -1:
			pass
			# leaving pixel mode, sanity check
			#w, h = paper_types[preferences.get(PAGE_SETUP, PAPER_TYPE)]
			#if self.iWidth.get() > w:
			#	self.iWidth.set(w)
			#if self.iHeight.get() > h:
			#	self.iHeight.set(h)
		self.adjust = adjust
		self._computeMaxLineWidth()

	def updateImageWidth(self, option):
		# adjust height to compensate for new width
		if self.matchAspect.get():
			iWidth = option.get()
			w, h = chimera.viewer.windowSize
			self.iHeight.set(iWidth * h / w)
		self._computeMaxLineWidth()

	def updateImageHeight(self, option):
		# adjust width to compensate for new height
		if self.matchAspect.get():
			iHeight = option.get()
			w, h = chimera.viewer.windowSize
			self.iWidth.set(iHeight * w / h)
		self._computeMaxLineWidth()

	def _resetSize(self, triggerName, myData, sizes):
		width, height, mmwidth, mmheight = sizes
		units = self.units.get()
		if units == 'pixels':
			self.iWidth.set(width)
			self.iHeight.set(height)
		else:
			adjust = convert['millimeters'] / convert[units]
			self.iWidth.set(mmwidth * adjust)
			self.iHeight.set(mmheight * adjust)
		self._computeMaxLineWidth()

	def _updateUsePrint(self):
		usePrint = self.usePrint.get()
		preferences.set(IMAGE_SETUP, USE_PRINT_UNITS, usePrint)
		if not usePrint:
			values = ['pixels']
		else:
			values = convert.keys()
			try:
				values.remove('pixels')
			except ValueError:
				pass
			values.sort()
		self.units.values = values
		self.units.remakeMenu()
		if usePrint:
			self.units.set('inches')
		else:
			self.units.set('pixels')
		self.updateImageUnits()
		if not usePrint:
			self.fetchWindowSize()

	def _updatePrint(self, option):
		res = option.get()
		preferences.set(IMAGE_SETUP, DPI, res)

	def _updateAdjustFOV(self, option):
		adjust = option.get()
		preferences.set(IMAGE_SETUP, ADJUST_FOV, adjust)

	def _updateSS(self, option):
		ss = option.get()
		preferences.set(IMAGE_SETUP, SUPERSAMPLE, ss)
		self._computeMaxLineWidth()

	#def showImageSetupDialog(self, *args):
	#	import dialogs
	#	d = dialogs.display("preferences")
	#	d.setCategoryMenu(IMAGE_SETUP)

	def showImageCreditsDialog(self, *args):
		import dialogs
		d = dialogs.display("preferences")
		d.setCategoryMenu(IMAGE_CREDITS)

	def showPOVRayOptions(self, *args):
		import dialogs
		d = dialogs.display("preferences")
		d.setCategoryMenu(POVRAY_SETUP)
	def fillInUI(self, master):
		self._ModelTrigger = None
		#self._SetupTrigger = None
		self._SizeTrigger = None
		self.raytrace = None
		# Image Size
		imageSetup = Tix.LabelFrame(master, label="Image Size")
		imageSetup.pack(fill=Tk.X, ipadx=2, ipady=2)
		subframe = imageSetup.frame
		#subframe = Tk.Frame(imageSetup.frame)
		#subframe.pack(fill=Tk.BOTH, expand=1)

		# add in conversion factor for pixels and graphics screen
		from chimera import tkgui
		win = tkgui.app.graphics
		res = tkgui.getScreenMMWidth() / win.winfo_screenwidth()
		convert['pixels'] = mm2pt(res)

		self.matchAspect = Tk.BooleanVar(master)
		self.matchAspect.set(1)

		self.usePrint = Tk.BooleanVar(master)
		self.usePrint.set(preferences.get(IMAGE_SETUP, USE_PRINT_UNITS))
		import itertools
		row = itertools.count()

		self.showUsePrint = Tk.Checkbutton(subframe, indicatoron=1,
				variable=self.usePrint, highlightthickness=0,
				text=USE_PRINT_UNITS,
				command=self._updateUsePrint)
		self.showUsePrint.grid(columnspan=2, row=row.next(), sticky=Tk.W)

		w, h = chimera.viewer.windowSize
		self.units = ImageUnitsOption(subframe, row.next(), UNITS,
						'pixels', self.updateImageUnits)
		self.iWidth = FloatOption(subframe, row.next(), 'Image width',
					w, self.updateImageWidth, min=1e-10)
		self.iHeight = FloatOption(subframe, row.next(), 'Image height',
					h, self.updateImageHeight, min=1e-10)

		matchAspect = Tk.Checkbutton(subframe, indicatoron=1,
				variable=self.matchAspect, highlightthickness=0,
				text="Maintain current aspect ratio",
				command=self.updateMatchAspect)
		matchAspect.grid(columnspan=2, row=row.next(), sticky=Tk.W)
		self.grow = Tk.Button(imageSetup.frame, text="Grow to Fit",
					command=self.Resize, state=Tk.DISABLED)
		fitrow = row.next()
		self.grow.grid(row=fitrow, column=0, padx=2, pady=2,
								sticky=Tk.NSEW)
		self.shrink = Tk.Button(imageSetup.frame, text="Shrink to Fit",
				command=lambda f=self.Resize: f(False),
				state=Tk.DISABLED)
		self.shrink.grid(row=fitrow, column=1, padx=2, pady=2,
								sticky=Tk.NSEW)

		#fetch = Tk.Button(imageSetup.frame, text="Get Pixels",
		#				command=self.fetchWindowSize)
		#fetch.grid(row=row.next(), column=0, padx=2, pady=2, sticky=Tk.NSEW)

		#calc = Tk.Button(imageSetup.frame, text="Image Setup",
		#			command=self.showImageSetupDialog)
		#calc.grid(row=row.next(), column=1, padx=2, pady=2, sticky=Tk.NSEW)

		self.printRes = FloatOption(subframe, row.next(), DPI,
				preferences.get(IMAGE_SETUP, DPI),
				self._updatePrint, min=1)

		# Image Information
		info = Tix.LabelFrame(master, label="Image Information")
		info.pack(fill=Tk.X)
		d = Tk.Label(info.frame, text="Description:")
		d.grid(columnspan=2, row=0, column=0, sticky=Tk.W, padx=2,
									pady=1)
		self.description = Tk.Entry(info.frame)
		info.frame.grid_columnconfigure(0, weight=1)
		info.frame.grid_columnconfigure(1, weight=1)
		self.description.grid(columnspan=2, row=1, column=0,
						sticky=Tk.EW, padx=2, pady=2)
		imageCredits = Tk.Button(info.frame,
					text="Image Credits",
					command=self.showImageCreditsDialog)
		imageCredits.grid(row=2, column=0, padx=2, pady=2)
		credit = Tk.Button(info.frame, text="Citing Chimera",
				command=lambda: help.display("credits.html"))
		credit.grid(row=2, column=1, padx=2, pady=2)

		# Image camera
		self.raytrace = BooleanOption(master, -1,
				'Raytrace with POV-Ray', False,
				self._updateRaytrace)
		self.raytraceOptions = Tk.Button(master, text=POVRAY_SETUP,
					command=self.showPOVRayOptions)
		self.raytraceOptions.pack()
		self.raytraceOptions.pack_forget()
		self.supersample = SupersampleOption(master, -1, SUPERSAMPLE,
				preferences.get(IMAGE_SETUP, SUPERSAMPLE),
				self._updateSS)
		self.adjustFOV = AdjustFOVOption(master, -1, ADJUST_FOV,
				preferences.get(IMAGE_SETUP, ADJUST_FOV),
				self._updateAdjustFOV)
		self.printMode = _PrintModeOption(master, -1,
				'Image camera mode', _PrintModeOption.SAME,
				self._updatePrintMode)
		self.lenticular = IntOption(master, -1,
				'Number of lenticular images',
				chimera.Camera.lenticularImageCount(),
				self._updateLenticular, min=2, width=4)
		self.lenticular.forget()

		# switch to user's prefered units
		self.adjust = convert['pixels']
		units = preferences.get(IMAGE_SETUP, UNITS)
		self._updateUsePrint()
		self.units.set(units)
		self.updateImageUnits()
class ClusterStarter(ModelessDialog):
    title = "Get Clustering Parameters"

    def __init__(self, movie):
        self.movie = movie
        movie.subdialogs.append(self)
        ModelessDialog.__init__(self)

    def fillInUI(self, parent):
        from chimera.tkoptions import IntOption, BooleanOption, \
             FloatOption
        Tkinter.Label(parent, text="Cluster trajectory", relief="ridge",
                      bd=4).grid(row=0, column=0, columnspan=2, sticky="ew")

        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        self.startFrame = IntOption(parent,
                                    1,
                                    "Starting frame",
                                    startFrame,
                                    None,
                                    min=startFrame,
                                    max=endFrame,
                                    width=6)

        numFrames = endFrame - startFrame + 1
        defStride = 1 + int(numFrames / 300)
        self.stride = IntOption(parent,
                                2,
                                "Step size",
                                defStride,
                                None,
                                min=1,
                                max=numFrames,
                                width=3)

        self.endFrame = IntOption(parent,
                                  3,
                                  "Ending frame",
                                  endFrame,
                                  None,
                                  min=startFrame,
                                  max=endFrame,
                                  width=6)

        self.useSel = BooleanOption(
            parent, 4, "Cluster based on "
            "current selection, if any", True, None)

        self.ignoreBulk = BooleanOption(parent, 5, "Ignore solvent/"
                                        "ions", True, None)
        self.ignoreHyds = BooleanOption(parent, 6, "Ignore hydrogens", True,
                                        None)

    def Apply(self):
        startFrame = self.startFrame.get()
        stride = self.stride.get()
        endFrame = self.endFrame.get()
        if endFrame <= startFrame:
            self.enter()
            raise UserError("Start frame must be less" " than end frame")
        if startFrame < self.movie.startFrame \
        or endFrame > self.movie.endFrame:
            self.enter()
            raise UserError("Start or end frame outside" " of trajectory")
        ClusterDialog(self.movie, startFrame, self.stride.get(), endFrame,
                      self.useSel.get(), self.ignoreBulk.get(),
                      self.ignoreHyds.get())