Ejemplo n.º 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)
Ejemplo n.º 2
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)
Ejemplo n.º 3
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")
Ejemplo n.º 4
0
	def __init__(self, parent):
		from chimera.tkoptions import IntOption, FloatOption
		Tkinter.Frame.__init__(self, parent)
		self.nsteps = IntOption(self, 0, "Steps", 100, None)
		self.stepsize = FloatOption(self, 1, "Step size (A)",
						0.02, None,
						min=0.0001, max=1.0)
		self.interval = IntOption(self, 2, "Update interval", 10, None)
		self.freeze = FreezeOption(self, 3, "Fixed atoms",
						base.FreezeNone, None)
Ejemplo n.º 5
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()
Ejemplo n.º 6
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)
	def fillInUI(self, parent):
		SaveModal.fillInUI(self, parent)
		parent = self.clientArea
		parent.columnconfigure(0, weight=1)
		parent.columnconfigure(1, weight=1)
		parent = Tk.Frame(parent)
		parent.grid()
		self.quality = IntOption(parent, 0,
			'JPEG quality', DEFAULT_JPEG_QUALITY, None,
			min=5, max=95, width=4, sticky=Tk.E)
		if self.millerBrowser.getFilter() != 'JPEG':
			self.quality.gridUnmanage()
Ejemplo n.º 8
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())
Ejemplo n.º 9
0
 def __init__(self, parent):
     from chimera.tkoptions import IntOption, FloatOption
     Tkinter.Frame.__init__(self, parent)
     self.nsteps = IntOption(self, 0, "Steps", 100, None)
     self.stepsize = FloatOption(self,
                                 1,
                                 "Step size (A)",
                                 0.02,
                                 None,
                                 min=0.0001,
                                 max=1.0)
     self.interval = IntOption(self, 2, "Update interval", 10, None)
     self.freeze = FreezeOption(self, 3, "Fixed atoms", base.FreezeNone,
                                None)
Ejemplo n.º 10
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)
Ejemplo n.º 11
0
class RMSD(ModalDialog):
    buttons = ('Cancel', 'Apply')

    def __init__(self, movie):
        self.movie = movie
        self.ref = None
        # self.ref2 = None # for an other value
        ModalDialog.__init__(self)

    def fillInUI(self, parent):
        import Tkinter
        from chimera.tkoptions import IntOption, BooleanOption, FloatOption

        Tkinter.Label(parent, text="Compute RMSD from a reference frame.\nThis calculation can take SEVERAL MINUTES...",
                      relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew")
        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        self.ref = IntOption(parent, 1, "Frame of reference", startFrame, None, min=startFrame, max=endFrame, width=6)
        # self.ref2 = IntOption(parent, 2, "Frame of reference 2", startFrame, None, min=startFrame, max=endFrame, width=6)

    def Apply(self):
        ref = self.ref.get()
        # ref2 = self.ref2.get()
        ModalDialog.Cancel(self, value=(ref, ))

    # def Cancel(self):
    # ModalDialog.Cancel(self, value=None)

    def destroy(self):
        self.movie = None
        ModelessDialog.destroy(self)
Ejemplo n.º 12
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)
Ejemplo n.º 13
0
    def fillInUI(self, parent):
        import Tkinter
        from chimera.tkoptions import IntOption, BooleanOption, FloatOption

        Tkinter.Label(parent, text="Compute RMSD from a reference frame.\nThis calculation can take SEVERAL MINUTES...",
                      relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew")
        startFrame = self.movie.startFrame
        endFrame = self.movie.endFrame
        self.ref = IntOption(parent, 1, "Frame of reference", startFrame, None, min=startFrame, max=endFrame, width=6)
Ejemplo n.º 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)
Ejemplo n.º 15
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)
class _ChooseFileDialog(SaveModal):
	oneshot = True
	title = "Save Image As"
	historyID = "SaveImage"

	def __init__(self, format=None, filterSet='normal'):
		if filterSet == 'normal':
			filters = FilenameFilters
			defaultFilter = DefaultFilter
			title = self.title
			historyID = self.historyID
		elif filterSet == 'stereo':
			filters = FilenameFilters + StereoFilenameFilters
			defaultFilter = DefaultStereoFilter
			title = "Save Stereo Pair As"
			historyID = 'SaveStereoImage'
		elif filterSet == 'povray':
			filters = RaytraceFilenameFilters
			defaultFilter = DefaultRaytraceFilter
			title = self.title
			historyID = self.historyID
		try:
			names = [x[0] for x in filters]
			f = names.index(defaultFilter)
		except ValueError:
			f = 0
		self.quality = None
		SaveModal.__init__(self, title=title, initialfile="image",
			filters=filters, defaultFilter=f,
			setFilterCommand=self._filterChange,
			clientPos='s', clientSticky='ew', historyID=historyID)
		if format:
			self.millerBrowser.setFilter(format)

	def fillInUI(self, parent):
		SaveModal.fillInUI(self, parent)
		parent = self.clientArea
		parent.columnconfigure(0, weight=1)
		parent.columnconfigure(1, weight=1)
		parent = Tk.Frame(parent)
		parent.grid()
		self.quality = IntOption(parent, 0,
			'JPEG quality', DEFAULT_JPEG_QUALITY, None,
			min=5, max=95, width=4, sticky=Tk.E)
		if self.millerBrowser.getFilter() != 'JPEG':
			self.quality.gridUnmanage()

	def _filterChange(self, descript):
		if self.quality is None:
			return
		if descript.endswith("JPEG"):
			self.quality.gridManage()
		else:
			self.quality.gridUnmanage()
Ejemplo n.º 17
0
	def fillInUI(self, parent):
		from chimera.widgets import MoleculeScrolledListBox
		self.molListBox = MoleculeScrolledListBox(parent,
			listbox_selectmode='extended', labelpos='w',
			label_text="Molecules to combine/copy:")
		if self.initModels:
			self.molListBox.setvalue(self.initModels)
		self.molListBox.grid(row=0, column=0, columnspan=2,
							sticky="nsew")
		parent.rowconfigure(0, weight=1)
		parent.columnconfigure(1, weight=1)
		from chimera.tkoptions import StringOption, IntOption
		self.molNameEntry = StringOption(parent, 1, "New model's"
						" name", "combination", None)

		curIDs = set([i1 for i1, i2 in openModels.listIds()])
		mid = 0
		while mid in curIDs:
			mid += 1
		self.modelID = IntOption(parent, 2, "New model's ID", mid, None)

		from chimera.widgets import MoleculeOptionMenu
		self.refMolMenu = MoleculeOptionMenu(parent, labelpos='w',
			label_text="Coordinate system of:",
			initialitem=self.initModels[0])
		self.refMolMenu.grid(row=3, column=0, columnspan=2, sticky='w')

		import Pmw
		chb = self.chainHandlingButtons = Pmw.RadioSelect(parent,
			buttontype="radiobutton", labelpos='w',
			label_text="If original molecules have duplicate\n"
			"single-letter chain IDs, then:", orient="vertical")
		self.buttonTexts = ["rename them uniquely",
				"retain them (residues may be renumbered)"]
		for bt in self.buttonTexts:
			chb.add(bt)
		chb.setvalue(self.buttonTexts[0])
		chb.grid(row=4, column=0, columnspan=2)

		import Tkinter
		self.closeModelsVar = Tkinter.IntVar(parent)
		self.closeModelsVar.set(False)
		Tkinter.Checkbutton(parent, text="Close source models",
					variable=self.closeModelsVar).grid(
					row=5, column=0, columnspan=2)
    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)
Ejemplo n.º 19
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)
Ejemplo n.º 20
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)
Ejemplo n.º 21
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)
Ejemplo n.º 22
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])
Ejemplo n.º 23
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()
Ejemplo n.º 24
0
    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 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 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)
Ejemplo n.º 27
0
	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)
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())
Ejemplo n.º 29
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()
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 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)
Ejemplo n.º 32
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()
Ejemplo n.º 33
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()
Ejemplo n.º 34
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)
Ejemplo n.º 35
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)
	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 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])