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 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)
def fillInUI(self, parent): import Pmw, Tkinter row = 0 Tkinter.Label(parent, text="Create plane for selected atoms...").grid( row=row, columnspan=2) row += 1 from chimera.tkoptions import StringOption, BooleanOption self.nameOpt = StringOption(parent, row, "Plane name", "plane", None) row += 1 self.replaceExistingOpt = BooleanOption(parent, row, "Replace existing planes", False, None) row += 1 from chimera.tkoptions import ColorOption, FloatOption self.colorOpt = ColorOption(parent, row, "Color", None, None, balloon="Plane color. If No Color, then the plane" " will be colored to match the structure") row += 1 self.autoRadiusOpt = BooleanOption(parent, row, "Set disk size to enclose atom projections", True, self._radCB) row += 1 self.radRow = row self.radOffsetOpt = FloatOption(parent, row, "Extra radius" " (padding)", 0.0, None) self.radiusOpt = FloatOption(parent, row, "Fixed radius", 10.0, None) self.radiusOpt.forget() row += 1 self.thicknessOpt = FloatOption(parent, row, "Disk thickness", prefs[PLANE_THICKNESS], None)
class Interface(ModelessDialog): title = "Fill Gaps with Modeller" def __init__(self, *args, **kw): ModelessDialog.__init__(self, *args, **kw) # TODO: initialize instance variables def fillInUI(self, parent): from chimera.widgets import MoleculeOptionMenu from chimera.tkoptions import IntOption, BooleanOption, \ InputFileOption, StringOption import itertools info = Tk.Label(parent, justify=Tk.LEFT, wraplength=300, text="Select a molecule with gaps") info.pack(ipadx=2, ipady=2) options = Tk.Frame(parent) options.columnconfigure(0, pad=2) options.columnconfigure(1, pad=2) row = itertools.count() molRow = row.next() text = Tk.Label(options, text="Restrict selections to molecule:") text.grid(row=molRow, column=0) self.molecules = MoleculeOptionMenu(options, command=self.updateMolecule) self.molecules.grid(row=molRow, column=1, sticky=Tk.W) self.turnsOnly = BooleanOption(options, row.next(), "Skip gaps at ends of chains", False, None) self.hetatms = BooleanOption(options, row.next(), "Include HETATM residues", False, None) #self.waters = BooleanOption(options, row.next(), # "Include waters", False, None) self.nucleic = BooleanOption(options, row.next(), "Include nucleic acids", False, None) self.nucleic.disable() hr = Tk.Frame(options, relief=Tk.GROOVE, borderwidth=1, height=2) hr.grid(row=row.next(), columnspan=2, sticky='ew') # modeller location self.modeller = InputFileOption(options, row.next(), "Modeller location", "mod8v2", None) # temporary prefix -- TODO: add unique id #self.tempdir = StringOption(options, row.next(), # "Temporary file prefix", "modtmp", None) options.pack() def updateMolecule(self, *args, **kw): print 'updateMolecule', args, kw # TODO: look for gaps def Apply(self): from chimera import selection molecule = [self.molecules.getvalue()]
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())
def __init__(self, parent, dialog, prefPrefix, callback): Pmw.Group.__init__(self, parent, tag_text="Spacing") self.__callback = callback self.__dialog = dialog self.__prefPrefix = prefPrefix prefs = dialog.mav.prefs self.__columnSepEntry = Pmw.EntryField( self.interior(), command=self.__newColSep, labelpos='w', label_text="Column separation (pixels)", entry_width=2, entry_justify='center', validate='integer', value=prefs[prefPrefix + COLUMN_SEP]) self.__columnSepEntry.grid(row=0, column=0, columnspan=2, sticky='e') dialog._entryWidgets.append(self.__columnSepEntry) self.__lineSepEntry = Pmw.EntryField( self.interior(), command=self.__newLineSep, labelpos='w', label_text="Line separation (pixels)", entry_width=2, entry_justify='center', validate='integer', value=prefs[prefPrefix + LINE_SEP]) self.__lineSepEntry.grid(row=1, column=0, columnspan=2, sticky='e') dialog._entryWidgets.append(self.__lineSepEntry) from chimera.tkoptions import BooleanOption BooleanOption(self.interior(), 2, "Space after every 10 residues", prefs[prefPrefix + TEN_RES_GAP], self.__resGap)
def fillInUI(self, parent): SaveModeless.fillInUI(self, parent) from chimera.tkoptions import SymbolicEnumOption, BooleanOption class ColorModeOption(SymbolicEnumOption): values = ["color", "gray", "mono"] labels = ["color", "grayscale", "black & white"] self.colorMode = ColorModeOption(self.clientArea, 0, "color mode", "color", None, balloon="output color range") self.orientation = BooleanOption( self.clientArea, 1, "rotate 90", False, None, balloon="If true, output will be rotated 90 degrees\n" "(i.e. landscape mode)") class ExtentOption(SymbolicEnumOption): values = ["visible", "all"] labels = ["visible region", "entire alignment"] self.extent = ExtentOption( self.clientArea, 2, "extent", "visible", None, balloon="save the entire alignment or just the visible part") self.hideNodes = BooleanOption( self.clientArea, 3, "hide tree control nodes", True, None, balloon="Hide square boxes used as controls for tree") if not self.mav.seqCanvas.treeShown: self.hideNodes.forget() self._nodesHandler = self.mav.triggers.addHandler( DISPLAY_TREE, self._treeDispCB, None)
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 _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): 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 PBreaderDialog(OpenModeless): title = "Pseudobond Reader" help = "ContributedSoftware/pbreader/pbreader.html" def __init__(self): OpenModeless.__init__(self, title="Pseudobond File to Read", historyID="PBReader open", clientPos='s') def fillInUI(self, parent): OpenModeless.fillInUI(self, parent) group = Pmw.Group(self.clientArea, tag_text='Further info') group.grid(row=0, column=0, sticky='nsew') self.catName = StringOption(group.interior(), 0, "group name", None, None) class PBLineWidthOption(LineWidthOption): default = prefs["line width"] balloon = "Width of pseudobonds (in pixels)" self.lineWidth = PBLineWidthOption(group.interior(), 1, None, None, None) self.clearCat = BooleanOption(group.interior(), 2, "clear group of previous pseudobonds", 1, None) self.leftModel = IntOption(group.interior(), 3, "first column specifiers default to model", 0, None) self.rightModel = IntOption( group.interior(), 4, "second column specifiers default to model", 0, None) def Apply(self): if not self.getPaths(): replyobj.error("No pseudobond file chosen\n") lineWidth = self.lineWidth.get() prefs["line width"] = lineWidth for path in self.getPaths(): readPBinfo(path, category=self.catName.get(), clearCategory=self.clearCat.get(), lineWidth=lineWidth, drawMode=None, leftModel=str(self.leftModel.get()), rightModel=str(self.rightModel.get()), defColor=None)
def fillInUI(self, parent): 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 PBreaderDialog(OpenModeless): title = "Pseudobond Reader" help = "ContributedSoftware/pbreader/pbreader.html" def __init__(self): OpenModeless.__init__(self, title="Pseudobond File to Read", historyID="PBReader open", clientPos='s') def fillInUI(self, parent): OpenModeless.fillInUI(self, parent) group = Pmw.Group(self.clientArea, tag_text='Further info') group.grid(row=0, column=0, sticky='nsew') self.catName = StringOption(group.interior(), 0, "group name", None, None) class PBLineWidthOption(LineWidthOption): default = prefs["line width"] balloon = "Width of pseudobonds (in pixels)" self.lineWidth = PBLineWidthOption(group.interior(), 1, None, None, None) self.clearCat = BooleanOption(group.interior(), 2, "clear group of previous pseudobonds", 1, None) self.leftModel = IntOption(group.interior(), 3, "first column specifiers default to model", 0, None) self.rightModel = IntOption(group.interior(), 4, "second column specifiers default to model", 0, None) def Apply(self): if not self.getPaths(): replyobj.error("No pseudobond file chosen\n") lineWidth = self.lineWidth.get() prefs["line width"] = lineWidth for path in self.getPaths(): readPBinfo(path, category=self.catName.get(), clearCategory=self.clearCat.get(), lineWidth=lineWidth, drawMode=None, leftModel=str(self.leftModel.get()), rightModel=str(self.rightModel.get()), defColor=None)
def fillInUI(self, parent): from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption Tkinter.Label(parent, text="Cluster trajectory", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.useSel = BooleanOption( parent, 4, "Cluster based on " "current selection, if any", True, None) self.ignoreBulk = BooleanOption(parent, 5, "Ignore solvent/" "ions", True, None) self.ignoreHyds = BooleanOption(parent, 6, "Ignore hydrogens", True, None)
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()
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)
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()
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)
class VolumeDialog(ModelessDialog): title = "Calculate Atomic Occupancy" help = "ContributedSoftware/movie/movie.html#occupancy" provideStatus = True statusPosition = "left" buttons = ('OK', 'Close') default= 'OK' def __init__(self, movie): self.movie = movie movie.subdialogs.append(self) ModelessDialog.__init__(self) def map(self, e=None): if not self.movie.holdingSteady: self.status("No atoms being held steady -- see Help", color="red") def fillInUI(self, parent): Tkinter.Label(parent, text="Collect positions of selected" " atoms over trajectory", relief="ridge", bd=4).grid( row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption, StringOption self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames/300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.doCutoff = BooleanOption(parent, 4, 'Limit data collection' ' to within cutoff distance of any "held steady" atoms', True, None) self.cutoff = FloatOption(parent, 5, "Cutoff distance", prefs[VOLUME_CUTOFF], None, width=4) self.resolution = FloatOption(parent, 6, "Volume grid spacing", prefs[VOLUME_RESOLUTION], None, min=0.0001, width=4) self.volumeName = StringOption(parent, 7, "Volume data name", self.movie.ensemble.name, None, width=20) self.byAtomType = BooleanOption(parent, 8, "Collect data" " separately for each atom type in selection", True, None, balloon="Create a volume data set for" " each type of atom type\n(sp2 oxygen, aromatic carbon," " etc.) in current selection") def Apply(self): from chimera import UserError atoms = chimera.selection.currentAtoms() if not atoms: self.enter() raise UserError("No atoms selected") startFrame = self.startFrame.get() endFrame = self.endFrame.get() if endFrame <= startFrame: self.enter() raise UserError("Start frame must be less" " than end frame") if startFrame < self.movie.startFrame \ or endFrame > self.movie.endFrame: self.enter() raise UserError("Start or end frame outside" " of trajectory") if self.doCutoff.get(): bound = prefs[VOLUME_CUTOFF] = self.cutoff.get() else: bound = None prefs[VOLUME_RESOLUTION] = self.resolution.get() step = self.stride.get() spacing = self.resolution.get() name = self.volumeName.get() atomTypes = {} if self.byAtomType.get(): for a in atoms: atomTypes.setdefault(a.idatmType, []).append(a) if len(atomTypes) > 1: for atomType, atAtoms in atomTypes.items(): self.movie.computeVolume(atAtoms, startFrame=startFrame, endFrame=endFrame, step=step, bound=bound, spacing=spacing, volumeName=name+" ["+atomType+"]") else: self.movie.computeVolume(atoms, startFrame=startFrame, endFrame=endFrame, step=step, bound=bound, spacing=spacing, volumeName=name)
class RmsdStarter(ModelessDialog): title = "Get RMSD Map Parameters" help = "ContributedSoftware/movie/movie.html#rmsd" def __init__(self, movie): self.movie = movie movie.subdialogs.append(self) ModelessDialog.__init__(self) def fillInUI(self, parent): from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption Tkinter.Label(parent, text="Create RMSD map of trajectory " "against itself", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.minRmsd = FloatOption(parent, 4, "Lower RMSD threshold" " (white)", prefs[RMSD_MIN], None, width=6) self.maxRmsd = FloatOption(parent, 5, "Upper RMSD threshold" " (black)", prefs[RMSD_MAX], None, width=6) self.useSel = BooleanOption( parent, 6, "Restrict map to " "current selection, if any", True, None) self.ignoreBulk = BooleanOption(parent, 7, "Ignore solvent/" "ions", True, None) self.ignoreHyds = BooleanOption(parent, 8, "Ignore hydrogens", True, None) self.recolor = BooleanOption(parent, 9, "Auto-recolor for" " contrast", prefs[RMSD_AUTOCOLOR], None) def Apply(self): startFrame = self.startFrame.get() stride = self.stride.get() if (len(self.movie.ensemble) - (startFrame - 1)) / stride > 1000: dlg = AskYesNoDialog("RMSD map will be %d pixels wide" " and tall. Okay?") if dlg.run(self.uiMaster()) == "no": self.enter() return endFrame = self.endFrame.get() if endFrame <= startFrame: self.enter() raise UserError("Start frame must be less" " than end frame") if startFrame < self.movie.startFrame \ or endFrame > self.movie.endFrame: self.enter() raise UserError("Start or end frame outside" " of trajectory") prefs[RMSD_MIN] = self.minRmsd.get() prefs[RMSD_MAX] = self.maxRmsd.get() prefs[RMSD_AUTOCOLOR] = self.recolor.get() RmsdMapDialog(self.movie, startFrame, self.stride.get(), endFrame, self.useSel.get(), prefs[RMSD_MIN], prefs[RMSD_MAX], self.ignoreBulk.get(), self.ignoreHyds.get(), prefs[RMSD_AUTOCOLOR])
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)
class EspDialog(ModelessDialog): title = "Coulombic Surface Coloring" name = "ESP computation" help = "ContributedSoftware/coulombic/coulombic.html" HB = "estimated from H-bonds" def fillInUI(self, parent): import Pmw, Tkinter self.buttonWidgets['OK']['state'] = 'disabled' self.buttonWidgets['Apply']['state'] = 'disabled' from chimera.widgets import ModelScrolledListBox self.surfListBox = ModelScrolledListBox( parent, labelpos='n', label_text='Surfaces to color by ESP:', listbox_selectmode="extended", filtFunc=lambda m: isinstance(m, chimera.MSMSModel), selectioncommand=self._selSurfCB) self.surfListBox.grid(row=0, column=0, sticky="nsew", columnspan=2) Pmw.OptionMenu(parent, command=self._menuCB, initialitem="3", items=[str(x) for x in range(2, 12)], labelpos='w', label_text="Number of colors/values:").grid( row=1, column=0, columnspan=2) f = self.interpFrame = Tkinter.Frame(parent) f.grid(row=2, column=0, columnspan=2) self.wells = [] self.values = [] self._entryOpts = { 'validate': 'real', 'entry_justify': 'center', 'entry_width': 6 } from CGLtk.color.ColorWell import ColorWell for color, value in [("red", -10), ("white", 0), ("blue", 10)]: well = ColorWell(f, color=color) well.grid(row=0, column=len(self.wells)) self.wells.append(well) entry = Pmw.EntryField(f, value=str(value), **self._entryOpts) entry.grid(row=1, column=len(self.values)) self.values.append(entry) from chimera.tkoptions import FloatOption, BooleanOption self.distDep = BooleanOption( parent, 3, "Distance-dependent dielectric", True, None, balloon="If true, charge falls off with distance squared to\n" "simulate solvent screening effects") self.dielectric = FloatOption(parent, 4, "Dielectric constant", 4.0, None) self.surfDist = FloatOption(parent, 5, "Distance from surface", 1.4, None, balloon="Potential at this distance from\n" "the surface is used for coloring") self.hisGroup = Pmw.Group(parent, hull_padx=2, tag_text="Implicit Histidine Protonation") self.hisGroup.grid(row=6, column=0, columnspan=2, sticky="nsew") self.hisProtVar = Tkinter.StringVar(parent) self.hisProtVar.set("name") interior = self.hisGroup.interior() interior.columnconfigure(0, weight=1) lab = Tkinter.Label( interior, text="Assumed histidine " "protonation for\nstructures without explicit hydrogens") from tkFont import Font font = Font(font=lab.cget('font')) font.config(size=int(0.75 * float(font.cget('size'))), slant='italic') lab.config(font=font) lab.grid(row=0) Tkinter.Radiobutton(interior, variable=self.hisProtVar, value="name", text="Residue name-based", command=self._switchHisList).grid(row=1, sticky='w') f = Tkinter.Frame(interior) f.grid(row=2) Tkinter.Label(f, text="HID/HIE/HIP = delta/epsilon/both").grid(row=0, sticky='w') self.hisDefault = Pmw.OptionMenu( f, initialitem=self.HB, items=[self.HB, "delta", "epsilon", "both"], labelpos='w', label_text="HIS = ", command=lambda a, s=self: setattr(s, 'hisChanged', True)) self.hisDefault.grid(row=1, sticky='w') self._pickText = Tkinter.StringVar(parent) self._pickText.set("Specified individually...") Tkinter.Radiobutton(interior, variable=self.hisProtVar, value="pick", textvariable=self._pickText, command=self._switchHisList).grid(row=3, sticky='w') Tkinter.Button(parent, pady=0, command=self._colorKeyCB, text="Create corresponding color key").grid( row=7, column=0, columnspan=2) self.hisChanged = False def Apply(self): for entry in self.values: entry.invoke() colors = [w.rgba for w in self.wells] values = [float(e.getvalue()) for e in self.values] if self.hisProtVar.get() == "name": hisScheme = { self.HB: None, 'delta': 'HID', 'epsilon': 'HIE', 'both': 'HIP' }[self.hisDefault.getvalue()] else: hisScheme = self.hisListingData from ESP import colorEsp for surf in self.surfListBox.getvalue(): if self.hisChanged: # clear out charge values so that histidines # get new charges for a in surf.atoms: a.charge = None colorEsp(surf, colors, values, dielectric=self.dielectric.get(), distDep=self.distDep.get(), surfDist=self.surfDist.get(), hisScheme=hisScheme) self.hisChanged = False def _colorKeyCB(self): for entry in self.values: entry.invoke() from Ilabel.gui import IlabelDialog from chimera import dialogs d = dialogs.display(IlabelDialog.name) d.keyConfigure( zip([w.rgba for w in self.wells], [e.getvalue() for e in self.values])) def _menuCB(self, val): newNum = int(val) oldSettings = [] for well, entry in zip(self.wells, self.values): entry.invoke() oldSettings.append((well.rgba, float(entry.getvalue()))) well.grid_forget() well.destroy() entry.grid_forget() entry.destroy() import Pmw from CGLtk.color.ColorWell import ColorWell self.wells = [] self.values = [] scale = (len(oldSettings) - 1.0) / (newNum - 1.0) f = self.interpFrame for i in range(newNum): index = i * scale if index == int(index) \ or int(index) >= len(oldSettings): color, value = oldSettings[int(index)] else: lowc, lowv = oldSettings[int(index)] highc, highv = oldSettings[int(index) + 1] frac = index - int(index) color = [] for lowcomp, highcomp in zip(lowc, highc): color.append((1.0 - frac) * lowcomp + frac * highcomp) value = (1.0 - frac) * lowv + frac * highv well = ColorWell(f, color=color) well.grid(row=0, column=len(self.wells)) self.wells.append(well) entry = Pmw.EntryField(f, value=str(value), **self._entryOpts) entry.grid(row=1, column=len(self.values)) self.values.append(entry) def _selSurfCB(self): if self.surfListBox.getvalue(): state = 'normal' else: state = 'disabled' self.buttonWidgets['OK']['state'] = state self.buttonWidgets['Apply']['state'] = state self._updateHisListing() def _select(self, hisType): for r, vars in self._vars.items(): dv, ev = vars if hisType == "delta": dv.set(True) ev.set(False) self.hisListingData[r] = "HID" elif hisType == "epsilon": dv.set(False) ev.set(True) self.hisListingData[r] = "HIE" else: dv.set(True) ev.set(True) self.hisListingData[r] = "HIP" def _switchHisList(self): self.hisChanged = True if not hasattr(self, 'hisListing'): if self.hisProtVar.get() != "pick": return self.hisListingData = {} import Tix, Tkinter self.hisFrame = Tkinter.Frame(self.hisGroup.interior()) self.hisListing = Tix.ScrolledHList(self.hisFrame, width="3i", options="""hlist.columns 4 hlist.header 1 hlist.indicator 1""") self.hisListing.hlist.configure( selectbackground=self.hisListing['background'], selectborderwidth=0) self.hisListing.grid(row=0, column=0, columnspan=3, sticky="nsew") self.hisFrame.rowconfigure(1, weight=1) self.hisFrame.columnconfigure(0, weight=1) self.hisFrame.columnconfigure(1, weight=1) hlist = self.hisListing.hlist hlist.header_create(0, itemtype="text", text="Model") hlist.header_create(1, itemtype="text", text="Residue") hlist.header_create(2, itemtype="text", text="Delta") hlist.header_create(3, itemtype="text", text="Epsilon") self._checkButtonStyle = Tix.DisplayStyle( "window", background=hlist['background'], refwindow=self.hisListing, anchor='center') self._updateHisListing() Tkinter.Button(self.hisFrame, text="All Delta", pady=0, highlightthickness=0, command=lambda p="delta": self._select(p)).grid( row=1, column=0) Tkinter.Button(self.hisFrame, text="All Epsilon", pady=0, highlightthickness=0, command=lambda p="epsilon": self._select(p)).grid( row=1, column=1) Tkinter.Button(self.hisFrame, text="All Both", pady=0, highlightthickness=0, command=lambda p="both": self._select(p)).grid( row=1, column=2) if self.hisProtVar.get() == "pick": self._pickText.set("Specified individually:") self.hisFrame.grid(row=4, sticky="nsew") interior = self.hisGroup.interior() interior.rowconfigure(4, weight=1) self.uiMaster().rowconfigure(6, weight=4) else: self._pickText.set("Specified individually...") self.hisFrame.grid_forget() interior = self.hisGroup.interior() interior.rowconfigure(4, weight=0) self.uiMaster().rowconfigure(6, weight=0) def _toggleDelta(self, res): self.hisChanged = True old = self.hisListingData[res] if old == "HIS": new = "HID" elif old == "HID": new = "HIS" elif old == "HIE": new = "HIP" else: new = "HIE" self.hisListingData[res] = new def _toggleEpsilon(self, res): self.hisChanged = True old = self.hisListingData[res] if old == "HIS": new = "HIE" elif old == "HID": new = "HIP" elif old == "HIE": new = "HIS" else: new = "HID" self.hisListingData[res] = new def _updateHisListing(self): if not hasattr(self, 'hisListing'): return self._updateHisListingData() hlist = self.hisListing.hlist on = self.hisListing.tk.call('tix', 'getimage', 'ck_on') off = self.hisListing.tk.call('tix', 'getimage', 'ck_off') hlist.delete_all() import Tkinter row = 0 self._vars = {} for m in [s.molecule for s in self.surfListBox.getvalue()]: for r in m.residues: try: hisType = self.hisListingData[r] except KeyError: continue hlist.add(row, itemtype="text", text="%s (%s)" % (m.name, m.oslIdent())) hlist.item_create(row, 1, itemtype="text", text=r.oslIdent(start=chimera.SelResidue)) var = Tkinter.IntVar(hlist) var.set(hisType in ["HID", "HIP"]) cmd = lambda r=r: self._toggleDelta(r) self._vars[r] = [var] toggle = Tkinter.Checkbutton(hlist, command=cmd, variable=var, image=off, selectimage=on, selectcolor="", indicatoron=False, borderwidth=0) hlist.item_create(row, 2, itemtype="window", window=toggle, style=self._checkButtonStyle) var = Tkinter.IntVar(hlist) var.set(hisType in ["HIE", "HIP"]) cmd = lambda r=r: self._toggleEpsilon(r) self._vars[r].append(var) toggle = Tkinter.Checkbutton(hlist, command=cmd, variable=var, image=off, selectimage=on, selectcolor="", indicatoron=False, borderwidth=0) hlist.item_create(row, 3, itemtype="window", window=toggle, style=self._checkButtonStyle) row += 1 def _updateHisListingData(self): newData = {} default = { 'delta': 'HID', 'epsilon': 'HIE', 'both': 'HIP', self.HB: 'HID' }[self.hisDefault.getvalue()] for m in [s.molecule for s in self.surfListBox.getvalue()]: for r in m.residues: if r.type not in ["HIS", "HIE", "HIP", "HID"]: continue try: newData[r] = self.hisListingData[r] except KeyError: if r.type == 'HIS': newData[r] = default else: newData[r] = r.type self.hisListingData = newData
class Interface(ModelessDialog): title = 'Nucleotides' help = "ContributedSoftware/nucleotides/nucleotides.html" buttons = ("NDB Colors",) + ModelessDialog.buttons provideStatus = True def __init__(self, *args, **kw): self.currentStyle = self.saveui_defaultItem() ModelessDialog.__init__(self, *args, **kw) self.__firstcanvas = True def fillInUI(self, parent): parent.columnconfigure(0, pad=2) parent.columnconfigure(1, pad=2) import itertools row = itertools.count() self.showBackbone = BackboneOption(parent, row.next(), 'Show backbone as', 'ribbon', None) self.showSide = SideOption(parent, row.next(), 'Show side (sugar/base) as', 'fill/slab', self._showSideCB) self.showOrientation = BooleanOption(parent, row.next(), 'Show base orientation', default.ORIENT, None) import Tix self.nb = Tix.NoteBook(parent) self.nb.grid(row=row.next(), column=0, columnspan=2, sticky=Tk.EW, padx=2) # ladder page self.nb.add("ladder", label="Ladder Options") f = self.nb.page("ladder") if Tk.TkVersion >= 8.5: parent.tk.call('grid', 'anchor', f._w, Tk.N) prow = itertools.count() self.skipNonBase = BooleanOption(f, prow.next(), 'Ignore non-base H-bonds', default.IGNORE, None) self.showStubs = BooleanOption(f, prow.next(), 'Show stubs', default.STUBS, None) self.rungRadius = FloatOption(f, prow.next(), 'Rung radius', default.RADIUS, None) self.rungRadius.min = 0.0 self.useExisting = BooleanOption(f, prow.next(), 'Using existing H-bonds', default.USE_EXISTING, self._useExistingCB) from FindHBond.gui import RelaxParams self.relaxParams = RelaxParams(f, None, colorOptions=False) #self.relaxParams.relaxConstraints = False self.relaxParams.grid(row=prow.next(), columnspan=2, sticky='nsew', padx=2) # slab page self.nb.add("slab", label="Slab Options") f = self.nb.page("slab") if Tk.TkVersion >= 8.5: parent.tk.call('grid', 'anchor', f._w, Tk.N) prow = itertools.count() self.thickness = FloatOption(f, prow.next(), 'Thickness', default.THICKNESS, None) self.thickness.min = 0.01 self.shape = ShapeOption(f, prow.next(), 'Slab object', default.SHAPE, None) self.hideBases = BooleanOption(f, prow.next(), 'Hide base atoms', default.HIDE, None) self.showGlycosidic = BooleanOption(f, prow.next(), 'Separate glycosidic bond', default.GLYCOSIDIC, None) self.nb.add("style", label="Slab Style", raisecmd=self.map) # style page f = self.nb.page("style") if Tk.TkVersion >= 8.5: f.tk.call('grid', 'anchor', f._w, Tk.N) info = NA.findStyle(self.currentStyle) from chimera.preferences import saveui f2 = Tk.Frame(f) self.saveui = saveui.SaveUI(f2, self) f2.grid(row=prow.next(), column=0, columnspan=2, sticky=Tk.EW, padx=2, pady=2) self.anchor = AnchorOption(f, prow.next(), 'Anchor', info[NA.ANCHOR], self._drawStyle) f2 = Pmw.Group(f, tag_text=NA.PURINE.title()) f2.grid(row=prow.next(), column=0, columnspan=2, sticky=Tk.EW, padx=2) f2 = f2.interior() f2.columnconfigure(0, weight=1, pad=2, uniform='a') f2.columnconfigure(1, weight=1, uniform='a') f2.columnconfigure(2, weight=1) self.purine_canvas = Tk.Canvas(f2, width=1, height=1) #, #borderwidth=2, relief=Tk.RIDGE) r = prow.next() self.purine_canvas.grid(row=r, column=0, rowspan=3, sticky=Tk.NSEW, padx=2, pady=2) corners = info[NA.PURINE] self.puLL = Float2Option(f2, prow.next(), 'Lower left', corners[0], self._drawStyle, startCol=1) self.puUR = Float2Option(f2, prow.next(), 'Upper right', corners[1], self._drawStyle, startCol=1) f3 = Pmw.Group(f, tag_text="%s, %s" % (NA.PYRIMIDINE.title(), NA.PSEUDO_PYRIMIDINE.title())) r = prow.next() f3.grid(row=r, column=0, columnspan=2, sticky=Tk.EW, padx=2) f3 = f3.interior() f3.columnconfigure(0, weight=1, pad=2, uniform='a') f3.columnconfigure(1, weight=1, uniform='a') f3.columnconfigure(2, weight=1) self.pyrimidine_canvas = Tk.Canvas(f3, width=1, height=1) #, #borderwidth=2, relief=Tk.RIDGE) r = prow.next() self.pyrimidine_canvas.grid(row=r, column=0, rowspan=3, sticky=Tk.NSEW, padx=2, pady=2) corners = info[NA.PYRIMIDINE] self.pyLL = Float2Option(f3, prow.next(), 'Lower left', corners[0], self._drawStyle, startCol=1) self.pyUR = Float2Option(f3, prow.next(), 'Upper right', corners[1], self._drawStyle, startCol=1) self.restrict = Tk.IntVar(parent) self.restrict.set(1) cb = Tk.Checkbutton(parent, variable=self.restrict, text="Restrict OK/Apply to current selection, if any") cb.grid(row=row.next(), columnspan=2) parent.pack(ipady=2) self._showSideCB() chimera.triggers.addHandler(NA.TRIGGER_SLAB_STYLES, self._updateStyles, None) def map(self, event=None): # need to update_idletasks so canvases in grid will have a size page = self.nb.raised() if page == 'style': if self.__firstcanvas: self.uiMaster().update_idletasks() self._drawStyle() self.__firstcanvas = False def _updateStyles(self, trigger, closure, arg): # pick up programmic changes in list of slab styles self.saveui.updateComboList() def saveui_label(self): return "Slab Style" def saveui_presetItems(self): return NA.SystemStyles.keys() def saveui_userItems(self): return NA.userStyles.keys() def saveui_defaultItem(self): return 'long' def saveui_select(self, name): self.currentStyle = name self._setSlabStyle(name) def saveui_save(self, name): info = self._getInfo() NA.addStyle(name, info) self.status("Slab style \"%s\" saved" % name) return True # successful def saveui_delete(self, name): NA.removeStyle(name) self.status("Slab style \"%s\" deleted" % name) return True # successful def _showSideCB(self, *args): side = self.showSide.get() hasSlab = 'slab' in side if side.startswith('fill') or hasSlab: self.showOrientation.enable() else: self.showOrientation.disable() if hasSlab: self.nb.raise_page('slab') elif side == 'ladder': self.nb.raise_page('ladder') if side == 'tube/slab': # tube connects to C1' if no slab # if slab, it goes to the middle of slab self.showGlycosidic.enable() return self.showGlycosidic.disable() def _useExistingCB(self, *args): useExisting = self.useExisting.get() if useExisting: self.relaxParams.disable() else: self.relaxParams.enable() def Apply(self): from chimera import selection if not self.restrict.get() or selection.currentEmpty(): molecules = chimera.openModels.list( modelTypes=[chimera.Molecule]) residues = [] for mol in molecules: residues.extend(mol.residues) else: residues = selection.currentResidues() molecules = tuple(set(r.molecule for r in residues)) residues = [r for r in residues if r.ribbonResidueClass.isNucleic()] backbone = self.showBackbone.get() display = backbone != 'atoms & bonds' for r in residues: r.ribbonDisplay = display side = self.showSide.get() if side == 'ladder': distSlop = 0.0 angleSlop = 0.0 relax = self.relaxParams.relaxConstraints if relax: distSlop = self.relaxParams.relaxDist angleSlop = self.relaxParams.relaxAngle NA.set_ladder(molecules, residues, rungRadius=self.rungRadius.get(), showStubs=self.showStubs.get(), skipNonBaseHBonds=self.skipNonBase.get(), useExisting=self.useExisting.get(), distSlop=distSlop, angleSlop=angleSlop) return if side.endswith('slab'): if self.currentStyle is None: info = self._getInfo() NA.addStyle(None, info) showGly = self.anchor.get() != NA.SUGAR if showGly and side.startswith('tube'): showGly = self.showGlycosidic.get() NA.set_slab(side, molecules, residues, style=self.currentStyle, thickness=self.thickness.get(), orient=self.showOrientation.get(), shape=self.shape.get(), showGly=showGly, hide=self.hideBases.get()) if side.startswith('fill'): for r in residues: r.fillDisplay = True else: for r in residues: r.fillDisplay = False if side.endswith('fill'): if self.showOrientation.get(): NA.set_orient(molecules, residues) else: NA.set_normal(molecules, residues) elif side.startswith('atoms'): NA.set_normal(molecules, residues) return def _showBase(self, type, info, canvas): # assume height is greater than width # keep in mind, canvases are "left-handed", so y is inverted # get unique bases of given type unique_bases = {} for b in NA.standard_bases.values(): if b['type'] == type: unique_bases[id(b)] = b # compute drawing parameters win_width = canvas.winfo_width() if win_width == 1: # no size assigned yet return win_height = canvas.winfo_height() # TODO: figure out how much room we really need for text if win_width < win_height: win_scale = .8 * win_width else: win_scale = .8 * win_height x_offset = .1 * win_width + 2 # 2==borderwidth if type == NA.PURINE: min = NA.purine_min max = NA.purine_max other = NA.pyrimidine_max[0] - NA.pyrimidine_min[0] elif type == NA.PYRIMIDINE: min = NA.pyrimidine_min max = NA.pyrimidine_max other = NA.purine_max[0] - NA.purine_min[0] width = max[0] - min[0] if other > width: width = other scale = win_scale / width # center vertically height = (max[1] - min[1]) * scale win_height -= (win_height - height) / 2 # clear canvas canvas.addtag_all('all') canvas.delete('all') def cvt_coords(c): for i in range(0, len(c), 2): c[i] = (c[i] - min[0]) * scale + x_offset c[i + 1] = win_height \ - (c[i + 1] - min[1]) * scale def draw_line(b, names): coords = [] for n in names: c = b[n] coords += [c[0], c[1]] if len(names) > 2: # close line coords += coords[0:2] cvt_coords(coords) kw = {'width':2} canvas.create_line(*coords, **kw) c1p_coords = None for b in unique_bases.values(): rn = b['ring atom names'] draw_line(b, rn) for o in b['other bonds']: draw_line(b, o) if c1p_coords is None: c1p_coords = list(b["C1'"][0:2]) else: coords = b["C1'"][0:2] if coords[0] < c1p_coords[0]: c1p_coords[0] = coords[0] if coords[1] > c1p_coords[1]: c1p_coords[1] = coords[1] corners = info[type] anchor = NA.anchor(info[NA.ANCHOR], type) offset = b[anchor] coords = [ offset[0] + corners[0][0], offset[1] + corners[0][1], offset[0] + corners[1][0], offset[1] + corners[1][1] ] cvt_coords(coords) kw = {'fill':'gray25', 'stipple':'gray25'} canvas.create_rectangle(*coords, **kw) coords = [min[0], max[1]] cvt_coords(c1p_coords) kw = {'text':" C1'", 'anchor':'s'} canvas.create_text(*c1p_coords, **kw) def _getInfo(self): info = { NA.ANCHOR: self.anchor.get(), NA.PURINE: (self.puLL.get(), self.puUR.get()), NA.PYRIMIDINE: (self.pyLL.get(), self.pyUR.get()), NA.PSEUDO_PYRIMIDINE: (self.pyLL.get(), self.pyUR.get()) } return info def _drawStyle(self, *args): if args: self.saveui.setItemChanged(True) self.currentStyle = None # fill in parameters info = self._getInfo() # show bases self._showBase(NA.PURINE, info, self.purine_canvas) self._showBase(NA.PYRIMIDINE, info, self.pyrimidine_canvas) def _setSlabStyle(self, name): # make options reflect current style info = NA.findStyle(name) if not info: return self.currentStyle = name self.anchor.set(info[NA.ANCHOR]) corners = info[NA.PURINE] self.puLL.set(corners[0]) self.puUR.set(corners[1]) corners = info[NA.PYRIMIDINE] self.pyLL.set(corners[0]) self.pyUR.set(corners[1]) self._drawStyle() def NDBColors(self): from chimera import selection if selection.currentEmpty(): import Midas residues = Midas._selectedResidues('#') else: residues = selection.currentResidues() NA.NDBColors(residues)
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): parent.columnconfigure(0, pad=2) parent.columnconfigure(1, pad=2) import itertools row = itertools.count() self.showBackbone = BackboneOption(parent, row.next(), 'Show backbone as', 'ribbon', None) self.showSide = SideOption(parent, row.next(), 'Show side (sugar/base) as', 'fill/slab', self._showSideCB) self.showOrientation = BooleanOption(parent, row.next(), 'Show base orientation', default.ORIENT, None) import Tix self.nb = Tix.NoteBook(parent) self.nb.grid(row=row.next(), column=0, columnspan=2, sticky=Tk.EW, padx=2) # ladder page self.nb.add("ladder", label="Ladder Options") f = self.nb.page("ladder") if Tk.TkVersion >= 8.5: parent.tk.call('grid', 'anchor', f._w, Tk.N) prow = itertools.count() self.skipNonBase = BooleanOption(f, prow.next(), 'Ignore non-base H-bonds', default.IGNORE, None) self.showStubs = BooleanOption(f, prow.next(), 'Show stubs', default.STUBS, None) self.rungRadius = FloatOption(f, prow.next(), 'Rung radius', default.RADIUS, None) self.rungRadius.min = 0.0 self.useExisting = BooleanOption(f, prow.next(), 'Using existing H-bonds', default.USE_EXISTING, self._useExistingCB) from FindHBond.gui import RelaxParams self.relaxParams = RelaxParams(f, None, colorOptions=False) #self.relaxParams.relaxConstraints = False self.relaxParams.grid(row=prow.next(), columnspan=2, sticky='nsew', padx=2) # slab page self.nb.add("slab", label="Slab Options") f = self.nb.page("slab") if Tk.TkVersion >= 8.5: parent.tk.call('grid', 'anchor', f._w, Tk.N) prow = itertools.count() self.thickness = FloatOption(f, prow.next(), 'Thickness', default.THICKNESS, None) self.thickness.min = 0.01 self.shape = ShapeOption(f, prow.next(), 'Slab object', default.SHAPE, None) self.hideBases = BooleanOption(f, prow.next(), 'Hide base atoms', default.HIDE, None) self.showGlycosidic = BooleanOption(f, prow.next(), 'Separate glycosidic bond', default.GLYCOSIDIC, None) self.nb.add("style", label="Slab Style", raisecmd=self.map) # style page f = self.nb.page("style") if Tk.TkVersion >= 8.5: f.tk.call('grid', 'anchor', f._w, Tk.N) info = NA.findStyle(self.currentStyle) from chimera.preferences import saveui f2 = Tk.Frame(f) self.saveui = saveui.SaveUI(f2, self) f2.grid(row=prow.next(), column=0, columnspan=2, sticky=Tk.EW, padx=2, pady=2) self.anchor = AnchorOption(f, prow.next(), 'Anchor', info[NA.ANCHOR], self._drawStyle) f2 = Pmw.Group(f, tag_text=NA.PURINE.title()) f2.grid(row=prow.next(), column=0, columnspan=2, sticky=Tk.EW, padx=2) f2 = f2.interior() f2.columnconfigure(0, weight=1, pad=2, uniform='a') f2.columnconfigure(1, weight=1, uniform='a') f2.columnconfigure(2, weight=1) self.purine_canvas = Tk.Canvas(f2, width=1, height=1) #, #borderwidth=2, relief=Tk.RIDGE) r = prow.next() self.purine_canvas.grid(row=r, column=0, rowspan=3, sticky=Tk.NSEW, padx=2, pady=2) corners = info[NA.PURINE] self.puLL = Float2Option(f2, prow.next(), 'Lower left', corners[0], self._drawStyle, startCol=1) self.puUR = Float2Option(f2, prow.next(), 'Upper right', corners[1], self._drawStyle, startCol=1) f3 = Pmw.Group(f, tag_text="%s, %s" % (NA.PYRIMIDINE.title(), NA.PSEUDO_PYRIMIDINE.title())) r = prow.next() f3.grid(row=r, column=0, columnspan=2, sticky=Tk.EW, padx=2) f3 = f3.interior() f3.columnconfigure(0, weight=1, pad=2, uniform='a') f3.columnconfigure(1, weight=1, uniform='a') f3.columnconfigure(2, weight=1) self.pyrimidine_canvas = Tk.Canvas(f3, width=1, height=1) #, #borderwidth=2, relief=Tk.RIDGE) r = prow.next() self.pyrimidine_canvas.grid(row=r, column=0, rowspan=3, sticky=Tk.NSEW, padx=2, pady=2) corners = info[NA.PYRIMIDINE] self.pyLL = Float2Option(f3, prow.next(), 'Lower left', corners[0], self._drawStyle, startCol=1) self.pyUR = Float2Option(f3, prow.next(), 'Upper right', corners[1], self._drawStyle, startCol=1) self.restrict = Tk.IntVar(parent) self.restrict.set(1) cb = Tk.Checkbutton(parent, variable=self.restrict, text="Restrict OK/Apply to current selection, if any") cb.grid(row=row.next(), columnspan=2) parent.pack(ipady=2) self._showSideCB() chimera.triggers.addHandler(NA.TRIGGER_SLAB_STYLES, self._updateStyles, None)
def fillInUI(self, parent): super(SonifyAttrDialog, self).fillInUI(parent) #self.modeNotebook = Pmw.NoteBook(parent,raisecommand=self._pageChangeCB,tabpos=None) # Pitch Markers self.renderPitchMarkers = self.renderHistogram.addmarkers( newcolor='pink', activate=False, coordtype='relative') if len(prefs[PITCH_RANGE]) == 1: self.renderPitchMarkers.append(((0.5, 0.0), None)) else: self.renderPitchMarkers.extend( map( lambda e: ((e[0] / float(len(prefs[PITCH_RANGE]) - 1), 0.0), None), enumerate(prefs[PITCH_RANGE]))) for i, rad in enumerate(prefs[PITCH_RANGE]): self.renderPitchMarkers[i].radius = rad #self.renderNotebook = Pmw.NoteBook(renderFrame, tabpos=None) self.renderNotebook.add("Pitch") # Pitch tab f = self.renderNotebook.page("Pitch") self.pitchWarning = Tkinter.Label( f, text="pitch can only be used with\n" "atom, residue or molecule attributes.") self.pitchWarning.grid() # for later setnaturalsize self.pitchFrame = Tkinter.Frame(f) from chimera.tkoptions import EnumOption, BooleanOption, FloatOption class SonificationOption(FloatOption): min = 0, max = 127 class SoundStyleOption(EnumOption): values = ["sine", "piano"] self.soundStyle = SoundStyleOption( self.pitchFrame, 0, "Sound style", prefs[SOUND_STYLE], lambda o: self.renderNotebook.setnaturalsize(), balloon="How worm radius changes between residues:\n" " smooth: radius changes smoothly\n" " segmented: radius changes abruptly") self.doNoValuePitch = BooleanOption( self.pitchFrame, 1, "Play no-value residues", False, None, balloon="Play something for residues not having\n" "this attribute or leave them silent") self.noValuePitch = SonificationOption( self.pitchFrame, 2, "No-value pitch", prefs[NOVAL_PITCH], None, balloon="Residues without this attribute will\n" "be given this pitch") self.renderNotebook.selectpage("Pitch") self.targetMenu.invoke(ShowAttr.attrsPrefMap[prefs[TARGET]].menuName)
class RmsdStarter(ModelessDialog): title = "Get RMSD Map Parameters" help = "ContributedSoftware/movie/movie.html#rmsd" def __init__(self, movie): self.movie = movie movie.subdialogs.append(self) ModelessDialog.__init__(self) def fillInUI(self, parent): from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption Tkinter.Label(parent, text="Create RMSD map of trajectory " "against itself", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames/300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.minRmsd = FloatOption(parent, 4, "Lower RMSD threshold" " (white)", prefs[RMSD_MIN], None, width=6) self.maxRmsd = FloatOption(parent, 5, "Upper RMSD threshold" " (black)", prefs[RMSD_MAX], None, width=6) self.useSel = BooleanOption(parent, 6, "Restrict map to " "current selection, if any", True, None) self.ignoreBulk = BooleanOption(parent, 7, "Ignore solvent/" "ions", True, None) self.ignoreHyds = BooleanOption(parent, 8, "Ignore hydrogens", True, None) self.recolor = BooleanOption(parent, 9, "Auto-recolor for" " contrast", prefs[RMSD_AUTOCOLOR], None) def Apply(self): startFrame = self.startFrame.get() stride = self.stride.get() if (len(self.movie.ensemble) - (startFrame-1)) / stride > 1000: dlg = AskYesNoDialog("RMSD map will be %d pixels wide" " and tall. Okay?") if dlg.run(self.uiMaster()) == "no": self.enter() return endFrame = self.endFrame.get() if endFrame <= startFrame: self.enter() raise UserError("Start frame must be less" " than end frame") if startFrame < self.movie.startFrame \ or endFrame > self.movie.endFrame: self.enter() raise UserError("Start or end frame outside" " of trajectory") prefs[RMSD_MIN] = self.minRmsd.get() prefs[RMSD_MAX] = self.maxRmsd.get() prefs[RMSD_AUTOCOLOR] = self.recolor.get() RmsdMapDialog(self.movie, startFrame, self.stride.get(), endFrame, self.useSel.get(), prefs[RMSD_MIN], prefs[RMSD_MAX], self.ignoreBulk.get(), self.ignoreHyds.get(), prefs[RMSD_AUTOCOLOR])
class EpsDialog(SaveModeless): """Dialog to allow the user to save alignment as EPS""" def __init__(self, mav): self.mav = mav self.title = "Save EPS of %s" % mav.title defaultFile = os.path.splitext(self.mav.title or "alignment")[0] SaveModeless.__init__(self, clientPos='s', initialfile=defaultFile, filters=[("EPS", "*.eps", ".eps")]) def fillInUI(self, parent): SaveModeless.fillInUI(self, parent) from chimera.tkoptions import SymbolicEnumOption, BooleanOption class ColorModeOption(SymbolicEnumOption): values = ["color", "gray", "mono"] labels = ["color", "grayscale", "black & white"] self.colorMode = ColorModeOption(self.clientArea, 0, "color mode", "color", None, balloon="output color range") self.orientation = BooleanOption( self.clientArea, 1, "rotate 90", False, None, balloon="If true, output will be rotated 90 degrees\n" "(i.e. landscape mode)") class ExtentOption(SymbolicEnumOption): values = ["visible", "all"] labels = ["visible region", "entire alignment"] self.extent = ExtentOption( self.clientArea, 2, "extent", "visible", None, balloon="save the entire alignment or just the visible part") self.hideNodes = BooleanOption( self.clientArea, 3, "hide tree control nodes", True, None, balloon="Hide square boxes used as controls for tree") if not self.mav.seqCanvas.treeShown: self.hideNodes.forget() self._nodesHandler = self.mav.triggers.addHandler( DISPLAY_TREE, self._treeDispCB, None) def destroy(self): self.mav.triggers.deleteHandler(DISPLAY_TREE, self._nodesHandler) self.mav = None ModelessDialog.destroy(self) def Apply(self): if not self.getPaths(): replyobj.error("No EPS save file specified.\n") self.enter() return self.mav.saveEPS(self.getPaths()[0], colorMode=self.colorMode.get(), rotate=self.orientation.get(), extent=self.extent.get(), hideNodes=self.hideNodes.get()) def _treeDispCB(self, trigName, myData, tree): if tree: self.hideNodes.manage() else: self.hideNodes.forget()
def fillInUI(self, parent): from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption Tkinter.Label(parent, text="Create RMSD map of trajectory " "against itself", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.minRmsd = FloatOption(parent, 4, "Lower RMSD threshold" " (white)", prefs[RMSD_MIN], None, width=6) self.maxRmsd = FloatOption(parent, 5, "Upper RMSD threshold" " (black)", prefs[RMSD_MAX], None, width=6) self.useSel = BooleanOption( parent, 6, "Restrict map to " "current selection, if any", True, None) self.ignoreBulk = BooleanOption(parent, 7, "Ignore solvent/" "ions", True, None) self.ignoreHyds = BooleanOption(parent, 8, "Ignore hydrogens", True, None) self.recolor = BooleanOption(parent, 9, "Auto-recolor for" " contrast", prefs[RMSD_AUTOCOLOR], None)
class IlabelDialog(ModelessDialog): name = "2D Labels/Color Key" provideStatus = True buttons = ("Delete", "Close") LABELS = "Labels" COLOR_KEY = "Color Key" MOUSE_LABEL_TEXT = "Use mouse for label placement" MOUSE_KEY_TEXT = "Use mouse for key placement" EmphasisColor = "forest green" def __init__(self): import os.path myDir, junk = os.path.split(__file__) addFunction('place text', (self._pickLabel, self._moveLabel, None), icon=chimage.get( Image.open(os.path.join(myDir, 'ilabel.png')), tkgui.app)) addFunction('place key', (self._startOrGrabKey, self._sizeOrMoveKey, None), icon=chimage.get( Image.open(os.path.join(myDir, 'key.png')), tkgui.app)) import Ilabel if not Ilabel._ilabelModel: Ilabel.IlabelModel() self.model = Ilabel._ilabelModel ModelessDialog.__init__(self) self._sessionHandlerID = chimera.triggers.addHandler( SAVE_SESSION, self._saveSession, None) self._closeHandlerID = chimera.triggers.addHandler( CLOSE_SESSION, self.destroy, None) self._beginRestoreHandlerID = chimera.triggers.addHandler( BEGIN_RESTORE_SESSION, self.destroy, None) def fillInUI(self, parent): top = parent.winfo_toplevel() menubar = Tkinter.Menu(top, type="menubar", tearoff=False) top.config(menu=menubar) self.fileMenu = Tkinter.Menu(menubar) menubar.add_cascade(label="File", menu=self.fileMenu) self.fileMenu.add_command(label="Write...", command=self._writeFileCB) self.fileMenu.add_command(label="Read...", command=self._readFileCB) from chimera.tkgui import aquaMenuBar aquaMenuBar(menubar, parent, row=0) from ColorKey import KeyModel parent.rowconfigure(1, weight=1) parent.columnconfigure(0, weight=1) # _pageRaisedCB uses mouseModeVar, so define first self.mouseLabelingVar = Tkinter.IntVar(parent) self.mouseLabelingVar.set(True) self.mlLabelVar = Tkinter.StringVar(parent) self.mouseModeButton = Tkinter.Checkbutton( parent, command=self._mouseFuncCB, variable=self.mouseLabelingVar, textvariable=self.mlLabelVar) self.mouseModeButton.grid(row=2, column=0) self.notebook = Pmw.NoteBook(parent, raisecommand=self._pageRaisedCB) self.notebook.add(self.LABELS, tab_text=self.LABELS) self.notebook.add(self.COLOR_KEY, tab_text=self.COLOR_KEY) self.notebook.grid(row=1, column=0, sticky="nsew") self._fillLabelsPage(self.notebook.page(self.LABELS)) self.keyModel = KeyModel(self) self.keyPosition = None self._fillColorKeyPage(self.notebook.page(self.COLOR_KEY)) def _fillLabelsPage(self, page): page.columnconfigure(0, weight=1) page.columnconfigure(1, weight=1) page.columnconfigure(2, weight=1) row = 0 from CGLtk.Table import SortableTable self.labelTable = SortableTable(page, automultilineHeaders=False) self.labelTable.addColumn("Label [(x, y) text]", self._labelListing, anchor='w') self.labelTable.addColumn("Shown", "shown", format=bool) self.labelTable.setData(self.model.labels) self.labelTable.launch(browseCmd=self._tableCB, selectMode="single") self.labelTable.grid(row=row, column=0, columnspan=3, sticky="nsew") page.rowconfigure(row, weight=1) row += 1 self.labelText = Pmw.ScrolledText(page, labelpos='w', label_text="Text", text_height=3, text_width=20, text_wrap='none', text_state='disabled', text_exportselection=False) text = self.labelText.component('text') text.bind("<<Modified>>", self._textCB) text.bind("<<Selection>>", self._updateTextAttrWidgets) self.labelText.grid(row=row, column=0, sticky='nsew', columnspan=3) page.rowconfigure(row, weight=1) row += 1 self.labelSymbolMenu = Pmw.OptionMenu( page, labelpos='w', label_text="Insert symbol:", command=self._insertSymbol, items=[ u'\N{GREEK SMALL LETTER ALPHA}', u'\N{GREEK SMALL LETTER BETA}', u'\N{GREEK SMALL LETTER GAMMA}', u'\N{GREEK SMALL LETTER DELTA}', u'\N{GREEK SMALL LETTER EPSILON}', u'\N{GREEK SMALL LETTER PI}', u'\N{GREEK SMALL LETTER PHI}', u'\N{GREEK SMALL LETTER CHI}', u'\N{GREEK SMALL LETTER PSI}', u'\N{GREEK SMALL LETTER OMEGA}', u'\N{LEFTWARDS ARROW}', u'\N{RIGHTWARDS ARROW}', u'\N{LEFT RIGHT ARROW}', u'\N{UPWARDS ARROW}', u'\N{DOWNWARDS ARROW}', u'\N{SUPERSCRIPT TWO}', u'\N{SUPERSCRIPT THREE}', u'\N{DEGREE SIGN}', u'\N{LATIN CAPITAL LETTER A WITH RING ABOVE}', "more..." ]) self.labelSymbolMenu.grid(row=row, column=0, columnspan=3) row += 1 colorHouse = Pmw.LabeledWidget(page, labelpos='w', label_text="Color") colorHouse.grid(row=row, column=0, rowspan=3) from CGLtk.color.ColorWell import ColorWell self.colorWell = ColorWell(colorHouse.interior(), color=self._contrastWithBG(), callback=self._colorCB) self.colorWell.grid() from chimera.tkoptions import IntOption self.labelFontSize = IntOption(page, row, "Font size", 24, self._labelChangeCB, startCol=1, min=1, attribute="size", width=3) row += 1 self.labelFontStyle = FontStyle(page, row, "Font style", oglFont.normal, self._labelChangeCB, startCol=1) row += 1 self.labelFontTypeface = FontTypeface(page, row, "Font typeface", FONT_TYPEFACE_VALUES[0], self._labelChangeCB, startCol=1) row += 1 if self.model.curLabel: self.changeToLabel(self.model.curLabel, force=True) def _fillColorKeyPage(self, page): from chimera.tkoptions import IntOption, EnumOption, \ BooleanOption, RGBAOption f = Tkinter.Frame(page) f.grid(row=0, columnspan=2) self.numComponents = IntOption(f, 0, "Number of colors/labels", 3, self._componentsCB, min=2, width=2) self.componentsFrame = Tkinter.Frame(page) self.componentsFrame.grid(row=1, column=0, sticky="nsew", columnspan=2) page.columnconfigure(0, weight=1) self.componentsFrame.columnconfigure(1, weight=1) class ColorTreatment(EnumOption): values = ("distinct", "blended") self.colorTreatment = ColorTreatment( page, 2, "Color range depiction", "blended", self._keyChangeCB, balloon="Should colors be shown as distinct rectangles" " or as a continuous range") class LabelPosition(EnumOption): values = ("left/top", "right/bottom") self.labelPos = LabelPosition( page, 3, "Label positions", "right/bottom", self._keyChangeCB, balloon="Position of" " labels relative to color key.\nLabels always" " positioned adjacent to long side.") self.labelColor = RGBAOption( page, 4, "Label color", self._contrastWithBG(), self._keyChangeCB, balloob="Label color. If set to 'No color', use corresponding" " key color", noneOkay=True) class LabelJustification(EnumOption): values = ("left", "decimal point", "right") self.justification = LabelJustification( page, 5, "Label justification", "decimal point", self._keyChangeCB, balloon="Justification of label text" " in a vertical key layout.\nHorizontal key labels will" " always be center justified.") self.labelOffset = IntOption(page, 6, "Label offset", 0, self._keyChangeCB, width=3, balloon="Additional offset" " of labels from color bar, in pixels") self.keyFontSize = IntOption(page, 7, "Font size", 24, self._keyChangeCB, width=3) self.keyFontStyle = FontStyle(page, 8, "Font style", oglFont.normal, self._keyChangeCB) self.keyFontTypeface = FontTypeface(page, 9, "Font typeface", FONT_TYPEFACE_VALUES[0], self._keyChangeCB) self.borderColor = RGBAOption( page, 10, "Border color", None, self._keyChangeCB, balloon="Color of border" " around color key (not each individual color).\n" "If 'no color', then no border is drawn.") self.borderWidth = IntOption(page, 11, "Border width", 3, self._keyChangeCB, balloon="in pixels") self.tickMarks = BooleanOption(page, 12, "Show tick marks", False, self._keyChangeCB, balloon="Show tick marks" " pointing from key to labels") self._componentsCB(self.numComponents) def destroy(self, *args): self.mouseLabelingVar.set(True) self.mouseModeButton.invoke() chimera.triggers.deleteHandler(SAVE_SESSION, self._sessionHandlerID) chimera.triggers.deleteHandler(CLOSE_SESSION, self._closeHandlerID) chimera.triggers.deleteHandler(BEGIN_RESTORE_SESSION, self._beginRestoreHandlerID) chimera.openModels.close([self.model, self.keyModel]) ModelessDialog.destroy(self) def map(self, e=None): self._pageRaisedCB(self.notebook.getcurselection()) def unmap(self, e=None): self.mouseLabelingVar.set(True) self.mouseModeButton.invoke() def changeToLabel(self, nextLabel, force=False): if nextLabel == self.model.curLabel and not force: return if self.model.curLabel and not unicode(self.model.curLabel) \ and self.model.curLabel != nextLabel: # remove previous label if empty self.removeLabel(self.model.curLabel) self.model.changeToLabel(nextLabel) self.labelText.component('text').configure(state='normal') self.labelTable.select(nextLabel) self.labelText.settext(unicode(nextLabel)) text = self.labelText.component('text') lineIndex = 1 for line in self.model.curLabel.lines: charIndex = 0 for c in line: text.tag_add(id(c), "%d.%d" % (lineIndex, charIndex)) charIndex += 1 text.tag_add(id(line), "%d.%d" % (lineIndex, charIndex)) lineIndex += 1 def Delete(self): if self.notebook.getcurselection() == self.LABELS: self.labelText.clear() if not self.model.curLabel: self.status("No label to delete", color="red", blankAfter=10) return self.removeLabel(self.model.curLabel) self.labelText.component('text').configure(state='disabled') else: self.keyPosition = None self._keyChangeCB() def Help(self): helpLoc = "ContributedSoftware/2dlabels/2dlabels.html" if self.notebook.getcurselection() == self.COLOR_KEY: helpLoc += "#colorkey" chimera.help.display(helpLoc) def keyConfigure(self, data, pageChange=True): self._componentsCB(len(data), update=False) for datum, well, label in zip(data, self.wells, self.labels): color, text = datum well.showColor(color, doCallback=False) label.variable.set(text, invoke_callbacks=False) self._keyChangeCB() if pageChange: self.notebook.selectpage(self.COLOR_KEY) def makeChar(self, char, model): attrs = {} try: attrs['rgba'] = self.colorWell.rgba except AttributeError: # multi or None if model: attrs['rgba'] = model.rgba size = self.labelFontSize.get() if size is not None: attrs['size'] = size style = self.labelFontStyle.get() if style is not None: attrs['style'] = style fontName = self.labelFontTypeface.get() if fontName is not None: attrs['fontName'] = fontName return Character(char, **attrs) def newLabel(self, pos): label = self.model.newLabel(pos) self.labelTable.setData(self.model.labels) self.status("Mouse drag to reposition label", color=self.EmphasisColor) return label def removeLabel(self, label): self.model.removeLabel(label) self.labelTable.setData(self.model.labels) if self.model.curLabel is not None: self.labelTable.select(self.model.curLabel) def reverseKey(self): data = zip([w.rgba for w in self.wells], [l.variable.get() for l in self.labels]) data.reverse() self.keyConfigure(data) def setLabelFromText(self): curLabel = self.model.curLabel text = self.labelText.component('text') # delete parts of label not in text... # # newlines first... while len(curLabel.lines) > 1: for i, line in enumerate(curLabel.lines[:-1]): if not text.tag_ranges(id(line)): curLabel.lines[i + 1][:0] = line del curLabel.lines[i] break else: break # characters... for line in curLabel.lines: for c in line[:]: if not text.tag_ranges(id(c)): line.remove(c) # get new parts of text into label model = None targets = [] lines = curLabel.lines for line in lines: targets.extend([id(c) for c in line]) if not model and line: model = line[0] if line is not lines[-1]: targets.append(id(line)) contents = self.labelText.get()[:-1] # drop trailing newline if targets: target = targets.pop(0) else: target = None textLine = 1 textIndex = -1 curLine = lines[0] for c in contents: textIndex += 1 if str(target) in text.tag_names("%d.%d" % (textLine, textIndex)): if targets: target = targets.pop(0) else: target = None if c == '\n': textLine += 1 textIndex = -1 curLine = lines[[id(l) for l in lines].index(id(curLine)) + 1] elif curLine: model = curLine[textIndex] elif c == '\n': insertLine = curLine[0:textIndex] lines.insert(textLine - 1, insertLine) del curLine[0:textIndex] text.tag_add(id(insertLine), "%d.%d" % (textLine, textIndex)) textLine += 1 textIndex = -1 else: labelChar = self.makeChar(c, model) curLine.insert(textIndex, labelChar) text.tag_add(id(labelChar), "%d.%d" % (textLine, textIndex)) self.model.setMajorChange() def updateGUI(self, source="gui"): curLabel = self.model.curLabel if curLabel and source == "gui": self.setLabelFromText() self.labelTable.setData(self.model.labels) if curLabel: self.labelTable.select(curLabel) self._updateTextAttrWidgets() def _colorCB(self, color): curLabel = self.model.curLabel if not curLabel: self.status("No label to color", color='red') return self.model.setMajorChange() for c in self._selChars(): c.rgba = color def _componentsCB(self, opt, update=True): cf = self.componentsFrame if hasattr(self, 'wells'): for well in self.wells: well.grid_forget() well.destroy() for label in self.labels: label.frame.grid_forget() self.reverseButton.grid_forget() self.reverseButton.destroy() else: Tkinter.Label(cf, text="Colors").grid(row=0) Tkinter.Label(cf, text="Labels").grid(row=0, column=1) if isinstance(opt, int): numComponents = opt self.numComponents.set(opt) else: numComponents = opt.get() wellSize = min(38, int((7 * 38) / numComponents)) from CGLtk.color.ColorWell import ColorWell self.wells = [] self.labels = [] from CGLtk import Hybrid for i in range(numComponents): well = ColorWell(cf, width=wellSize, height=wellSize, callback=self._keyChangeCB, color='white') well.grid(row=i + 1) self.wells.append(well) label = Hybrid.Entry(cf, "", 10) label.variable.add_callback(self._keyTypingCB) label.frame.grid(row=i + 1, column=1, sticky='ew') self.labels.append(label) self.reverseButton = Tkinter.Button(cf, command=self.reverseKey, text="Reverse ordering of above", pady=0) self.reverseButton.grid(row=numComponents + 1, column=0, columnspan=2) self.notebook.setnaturalsize() if update: self._keyChangeCB() def _contrastWithBG(self): bg = chimera.viewer.background if bg: bgColor = bg.rgba() else: bgColor = (0, 0, 0) if bgColor[0] * 2 + bgColor[1] * 3 + bgColor[2] < 0.417: return (1, 1, 1) else: return (0, 0, 0) def _eventToPos(self, viewer, event, offset=(0, 0)): w, h = viewer.windowSize return (event.x - offset[0]) / float(w), \ (h - event.y - offset[1]) / float(h) def _handleTextChange(self): self.updateGUI() self.labelText.edit_modified(False) def _insertSymbol(self, item): if len(item) > 1: from chimera import help help.display("ContributedSoftware/2dlabels/symbols.html") return if not self.model.labels: self.status("No labels have been created yet", color="red") return if not self.labelTable.selected(): self.status("No labels active", color="red") self.labelText.insert("insert", item) self.setLabelFromText() def _keyChangeCB(self, *args): self.keyModel.setMajorChange() def _keyTypingCB(self, fromAfter=False): # wait for a pause in typing before updating key... if fromAfter: self._typingHandler = None self._keyChangeCB() return handle = getattr(self, '_typingHandler', None) if handle: self.componentsFrame.after_cancel(handle) self._typingHandler = self.componentsFrame.after( 500, lambda: self._keyTypingCB(fromAfter=True)) def _labelChangeCB(self, option): curLabel = self.model.curLabel self.model.setMajorChange() val = option.get() attrName = option.attribute for c in self._selChars(): setattr(c, attrName, val) def _labelListing(self, label): text = unicode(label) if '\n' in text: newline = text.index('\n') text = text[:newline] + "..." if not text: text = "<empty>" return "(%.2f, %.2f) %s" % (label.pos[0], label.pos[1], text) def _mouseFuncCB(self): self.status("") if not self.mouseLabelingVar.get(): if hasattr(self, "_prevMouse"): setButtonFunction("1", (), self._prevMouse) delattr(self, "_prevMouse") elif self.mlLabelVar.get() == self.MOUSE_LABEL_TEXT: if not hasattr(self, "_prevMouse"): self._prevMouse = getFuncName("1", ()) setButtonFunction("1", (), "place text") else: if not hasattr(self, "_prevMouse"): self._prevMouse = getFuncName("1", ()) setButtonFunction("1", (), "place key") def _moveLabel(self, viewer, event): pos = self._eventToPos(viewer, event, self._moveOffset) self.model.moveLabel(pos) curLabel = self.model.curLabel self.labelTable.setData(self.model.labels) self.labelTable.select(curLabel) def _pageRaisedCB(self, pageName): if pageName == "Labels": pageItem = self.MOUSE_LABEL_TEXT if not self.model.labels: self.status( "Click mouse button 1 in graphics\n" "window to place first label", color=self.EmphasisColor) for index in range(0, self.fileMenu.index('end') + 1): self.fileMenu.entryconfigure(index, state='normal') else: pageItem = self.MOUSE_KEY_TEXT self.status("Drag mouse to position/size key", color=self.EmphasisColor) for index in range(0, self.fileMenu.index('end') + 1): self.fileMenu.entryconfigure(index, state='disabled') self.mlLabelVar.set(pageItem) # just setting the var doesn't cause the callback, and # yet using invoke() toggles the var, so set it _opposite_ # to what's desired before calling invoke() self.mouseLabelingVar.set(False) self.mouseModeButton.invoke() def _pickLabel(self, viewer, event): w, h = viewer.windowSize pos = self._eventToPos(viewer, event) label, self._moveOffset = self.model.pickLabel(pos, w, h) if label is None: label = self.newLabel(pos) self._moveOffset = (0, 0) self.changeToLabel(label) self.labelText.component('text').focus_set() def _readFile(self, okayed, dialog): if not okayed: return from Ilabel import readFiles readFiles(dialog.getPaths(), clear=dialog.deleteExistingVar.get()) def _readFileCB(self): if not hasattr(self, "_readFileDialog"): self._readFileDialog = ReadFileDialog(command=self._readFile, clientPos='s') self._readFileDialog.enter() def _restoreSession(self, info): if info["sel ranges"]: self.labelText.tag_add("sel", *info["sel ranges"]) self._updateTextAttrWidgets() self._suppressMap = True self.labelText.edit_modified(False) if "key position" not in info: self.notebook.selectpage(self.LABELS) if info["mouse func"] == "normal": self.mouseLabelingVar.set(True) self.mouseModeButton.invoke() return self.keyPosition = info["key position"] self.colorTreatment.set(info["color depiction"]) self.labelPos.set(info["label positions"]) self.labelColor.set(info["label color"]) self.justification.set(info["label justification"]) self.labelOffset.set(info["label offset"]) self.keyFontSize.set(info["font size"]) self.keyFontStyle.set(info["font typeface"]) if "font name" in info: self.keyFontTypeface.set(info["font name"]) self.borderColor.set(info["border color"]) self.borderWidth.set(info["border width"]) self.tickMarks.set(info["show ticks"]) self.keyConfigure(info["colors/labels"]) if self.keyPosition: self.notebook.selectpage(self.COLOR_KEY) else: self.notebook.selectpage(self.LABELS) if info["mouse func"] == "normal": self.mouseLabelingVar.set(True) self.mouseModeButton.invoke() return info def _saveSession(self, triggerName, myData, sessionFile): print >> sessionFile, """ def restore2DLabelDialog(info): from chimera.dialogs import find, display from Ilabel.gui import IlabelDialog dlg = find(IlabelDialog.name) if dlg is not None: dlg.destroy() dlg = display(IlabelDialog.name) dlg._restoreSession(info) import SimpleSession SimpleSession.registerAfterModelsCB(restore2DLabelDialog, %s) """ % repr(self._sessionInfo()) def _selChars(self): chars = [] curLabel = self.model.curLabel if curLabel: sel = self.labelText.tag_ranges("sel") if sel: sline, schar = [int(x) for x in str(sel[0]).split('.')] eline, echar = [int(x) for x in str(sel[1]).split('.')] sline -= 1 eline -= 1 for li, line in enumerate(curLabel.lines): if li < sline: continue if li > eline: break if sline == eline: chars.extend(line[schar:echar]) elif li == sline: chars.extend(line[schar:]) elif li == eline: chars.extend(line[:echar]) else: chars.extend(line) else: for l in curLabel.lines: chars.extend(l) return chars def _sessionInfo(self): info = {} info["sel ranges"] = tuple( [str(tr) for tr in self.labelText.tag_ranges("sel")]) if self.mouseLabelingVar.get(): info["mouse func"] = "labeling" else: info["mouse func"] = "normal" info["key position"] = self.keyPosition info["colors/labels"] = [(w.rgba, l.variable.get()) for w, l in zip(self.wells, self.labels)] info["color depiction"] = self.colorTreatment.get() info["label positions"] = self.labelPos.get() info["label color"] = self.labelColor.get() info["label justification"] = self.justification.get() info["label offset"] = self.labelOffset.get() info["font size"] = self.keyFontSize.get() info["font typeface"] = self.keyFontStyle.get() info["font name"] = self.keyFontTypeface.get() info["border color"] = self.borderColor.get() info["border width"] = self.borderWidth.get() info["show ticks"] = self.tickMarks.get() return info def _sizeOrMoveKey(self, viewer, event): pos = self._eventToPos(viewer, event) if self.grabPos: deltas = [pos[axis] - self.grabPos[axis] for axis in [0, 1]] for posIndex in [0, 1]: old = self.keyPosition[posIndex] self.keyPosition[posIndex] = (old[0] + deltas[0], old[1] + deltas[1]) self.grabPos = pos elif len(self.keyPosition) == 1: self.keyPosition.append(pos) else: self.keyPosition[1] = pos self._keyChangeCB() def _startOrGrabKey(self, viewer, event): pos = self._eventToPos(viewer, event) if self.keyPosition and len(self.keyPosition) == 2: # possible grab; # see if in middle third of long side... p1, p2 = self.keyPosition x1, y1 = p1 x2, y2 = p2 if abs(x2 - x1) < abs(y2 - y1): longAxis = 1 ymin = min(y2, y1) ymax = max(y2, y1) b1 = (2 * ymin + ymax) / 3.0 b2 = (2 * ymax + ymin) / 3.0 o1 = min(x1, x2) o2 = max(x1, x2) else: longAxis = 0 xmin = min(x2, x1) xmax = max(x2, x1) b1 = (2 * xmin + xmax) / 3.0 b2 = (2 * xmax + xmin) / 3.0 o1 = min(y1, y2) o2 = max(y1, y2) if b1 < pos[longAxis] < b2 \ and o1 < pos[1-longAxis] < o2: self.grabPos = pos return self.grabPos = None self.keyPosition = [pos] self._keyChangeCB() self.status("Grab middle of key to reposition", color=self.EmphasisColor) def _tableCB(self, sel): if not sel: return self.changeToLabel(sel) def _textCB(self, e): text = self.labelText.component('text') if not text.tk.call((text._w, 'edit', 'modified')): #if not text.edit_modified(): return # this callback can happen _before_ the change # actually occurs, so do the processing after idle text.after_idle(self._handleTextChange) def _updateTextAttrWidgets(self, e=None): rgba = None multiple = False for c in self._selChars(): if rgba is None: rgba = c.rgba elif rgba != c.rgba: multiple = True break if rgba is not None: self.colorWell.showColor(rgba, multiple=multiple, doCallback=False) self.labelFontSize.display(self._selChars()) self.labelFontStyle.display(self._selChars()) self.labelFontTypeface.display(self._selChars()) def _writeFile(self, okayed, dialog): if not okayed: return from Ilabel import writeFile writeFile(dialog.getPaths()[0]) def _writeFileCB(self): if not hasattr(self, "_writeFileDialog"): from OpenSave import SaveModeless self._writeFileDialog = SaveModeless(command=self._writeFile, title="Write 2D Labels Info") self._writeFileDialog.enter()
class EspDialog(ModelessDialog): title = "Coulombic Surface Coloring" name = "ESP computation" help = "ContributedSoftware/coulombic/coulombic.html" HB = "estimated from H-bonds" def fillInUI(self, parent): import Pmw, Tkinter self.buttonWidgets['OK']['state'] = 'disabled' self.buttonWidgets['Apply']['state'] = 'disabled' from chimera.widgets import ModelScrolledListBox self.surfListBox = ModelScrolledListBox(parent, labelpos='n', label_text='Surfaces to color by ESP:', listbox_selectmode="extended", filtFunc=lambda m: isinstance(m, chimera.MSMSModel), selectioncommand=self._selSurfCB) self.surfListBox.grid(row=0, column=0, sticky="nsew", columnspan=2) Pmw.OptionMenu(parent, command=self._menuCB, initialitem="3", items=[str(x) for x in range(2, 12)], labelpos='w', label_text="Number of colors/values:").grid(row=1, column=0, columnspan=2) f = self.interpFrame = Tkinter.Frame(parent) f.grid(row=2, column=0, columnspan=2) self.wells = [] self.values = [] self._entryOpts = { 'validate': 'real', 'entry_justify': 'center', 'entry_width': 6 } from CGLtk.color.ColorWell import ColorWell for color, value in [("red", -10), ("white", 0), ("blue", 10)]: well = ColorWell(f, color=color) well.grid(row=0, column=len(self.wells)) self.wells.append(well) entry = Pmw.EntryField(f, value=str(value), **self._entryOpts) entry.grid(row=1, column=len(self.values)) self.values.append(entry) from chimera.tkoptions import FloatOption, BooleanOption self.distDep = BooleanOption(parent, 3, "Distance-dependent dielectric", True, None, balloon= "If true, charge falls off with distance squared to\n" "simulate solvent screening effects") self.dielectric = FloatOption(parent, 4, "Dielectric constant", 4.0, None) self.surfDist = FloatOption(parent, 5, "Distance from surface", 1.4, None, balloon="Potential at this distance from\n" "the surface is used for coloring") self.hisGroup = Pmw.Group(parent, hull_padx=2, tag_text="Implicit Histidine Protonation") self.hisGroup.grid(row=6, column=0, columnspan=2, sticky="nsew") self.hisProtVar = Tkinter.StringVar(parent) self.hisProtVar.set("name") interior = self.hisGroup.interior() interior.columnconfigure(0, weight=1) lab = Tkinter.Label(interior, text="Assumed histidine " "protonation for\nstructures without explicit hydrogens") from tkFont import Font font = Font(font=lab.cget('font')) font.config(size=int(0.75 * float(font.cget('size'))), slant='italic') lab.config(font=font) lab.grid(row=0) Tkinter.Radiobutton(interior, variable=self.hisProtVar, value="name", text="Residue name-based", command= self._switchHisList).grid(row=1, sticky='w') f = Tkinter.Frame(interior) f.grid(row=2) Tkinter.Label(f, text="HID/HIE/HIP = delta/epsilon/both").grid( row=0, sticky='w') self.hisDefault = Pmw.OptionMenu(f, initialitem=self.HB, items=[self.HB, "delta", "epsilon", "both"], labelpos='w', label_text="HIS = ", command=lambda a, s=self: setattr(s, 'hisChanged', True)) self.hisDefault.grid(row=1, sticky='w') self._pickText = Tkinter.StringVar(parent) self._pickText.set("Specified individually...") Tkinter.Radiobutton(interior, variable=self.hisProtVar, value="pick", textvariable=self._pickText, command=self._switchHisList).grid(row=3, sticky='w') Tkinter.Button(parent, pady=0, command=self._colorKeyCB, text="Create corresponding color key").grid(row=7, column=0, columnspan=2) self.hisChanged = False def Apply(self): for entry in self.values: entry.invoke() colors = [w.rgba for w in self.wells] values = [float(e.getvalue()) for e in self.values] if self.hisProtVar.get() == "name": hisScheme = { self.HB: None, 'delta': 'HID', 'epsilon': 'HIE', 'both': 'HIP' }[self.hisDefault.getvalue()] else: hisScheme = self.hisListingData from ESP import colorEsp for surf in self.surfListBox.getvalue(): if self.hisChanged: # clear out charge values so that histidines # get new charges for a in surf.atoms: a.charge = None colorEsp(surf, colors, values, dielectric=self.dielectric.get(), distDep=self.distDep.get(), surfDist=self.surfDist.get(), hisScheme=hisScheme) self.hisChanged = False def _colorKeyCB(self): for entry in self.values: entry.invoke() from Ilabel.gui import IlabelDialog from chimera import dialogs d = dialogs.display(IlabelDialog.name) d.keyConfigure(zip([w.rgba for w in self.wells], [e.getvalue() for e in self.values])) def _menuCB(self, val): newNum = int(val) oldSettings = [] for well, entry in zip(self.wells, self.values): entry.invoke() oldSettings.append((well.rgba, float(entry.getvalue()))) well.grid_forget() well.destroy() entry.grid_forget() entry.destroy() import Pmw from CGLtk.color.ColorWell import ColorWell self.wells = [] self.values = [] scale = (len(oldSettings) - 1.0) / (newNum - 1.0) f = self.interpFrame for i in range(newNum): index = i * scale if index == int(index) \ or int(index) >= len(oldSettings): color, value = oldSettings[int(index)] else: lowc, lowv = oldSettings[int(index)] highc, highv = oldSettings[int(index)+1] frac = index - int(index) color = [] for lowcomp, highcomp in zip(lowc, highc): color.append((1.0 - frac) * lowcomp + frac * highcomp) value = (1.0 - frac) * lowv + frac * highv well = ColorWell(f, color=color) well.grid(row=0, column=len(self.wells)) self.wells.append(well) entry = Pmw.EntryField(f, value=str(value), **self._entryOpts) entry.grid(row=1, column=len(self.values)) self.values.append(entry) def _selSurfCB(self): if self.surfListBox.getvalue(): state = 'normal' else: state = 'disabled' self.buttonWidgets['OK']['state'] = state self.buttonWidgets['Apply']['state'] = state self._updateHisListing() def _select(self, hisType): for r, vars in self._vars.items(): dv, ev = vars if hisType == "delta": dv.set(True) ev.set(False) self.hisListingData[r] = "HID" elif hisType == "epsilon": dv.set(False) ev.set(True) self.hisListingData[r] = "HIE" else: dv.set(True) ev.set(True) self.hisListingData[r] = "HIP" def _switchHisList(self): self.hisChanged = True if not hasattr(self, 'hisListing'): if self.hisProtVar.get() != "pick": return self.hisListingData = {} import Tix, Tkinter self.hisFrame = Tkinter.Frame(self.hisGroup.interior()) self.hisListing = Tix.ScrolledHList(self.hisFrame, width="3i", options="""hlist.columns 4 hlist.header 1 hlist.indicator 1""") self.hisListing.hlist.configure( selectbackground=self.hisListing['background'], selectborderwidth=0) self.hisListing.grid(row=0, column=0, columnspan=3, sticky="nsew") self.hisFrame.rowconfigure(1, weight=1) self.hisFrame.columnconfigure(0, weight=1) self.hisFrame.columnconfigure(1, weight=1) hlist = self.hisListing.hlist hlist.header_create(0, itemtype="text", text="Model") hlist.header_create(1, itemtype="text", text="Residue") hlist.header_create(2, itemtype="text", text="Delta") hlist.header_create(3, itemtype="text", text="Epsilon") self._checkButtonStyle = Tix.DisplayStyle("window", background=hlist['background'], refwindow=self.hisListing, anchor='center') self._updateHisListing() Tkinter.Button(self.hisFrame, text="All Delta", pady=0, highlightthickness=0, command=lambda p="delta": self._select(p) ).grid(row=1, column=0) Tkinter.Button(self.hisFrame, text="All Epsilon", pady=0, highlightthickness=0, command=lambda p="epsilon": self._select(p) ).grid(row=1, column=1) Tkinter.Button(self.hisFrame, text="All Both", pady=0, highlightthickness=0, command=lambda p="both": self._select(p) ).grid(row=1, column=2) if self.hisProtVar.get() == "pick": self._pickText.set("Specified individually:") self.hisFrame.grid(row=4, sticky="nsew") interior = self.hisGroup.interior() interior.rowconfigure(4, weight=1) self.uiMaster().rowconfigure(6, weight=4) else: self._pickText.set("Specified individually...") self.hisFrame.grid_forget() interior = self.hisGroup.interior() interior.rowconfigure(4, weight=0) self.uiMaster().rowconfigure(6, weight=0) def _toggleDelta(self, res): self.hisChanged = True old = self.hisListingData[res] if old == "HIS": new = "HID" elif old == "HID": new = "HIS" elif old == "HIE": new = "HIP" else: new = "HIE" self.hisListingData[res] = new def _toggleEpsilon(self, res): self.hisChanged = True old = self.hisListingData[res] if old == "HIS": new = "HIE" elif old == "HID": new = "HIP" elif old == "HIE": new = "HIS" else: new = "HID" self.hisListingData[res] = new def _updateHisListing(self): if not hasattr(self, 'hisListing'): return self._updateHisListingData() hlist = self.hisListing.hlist on = self.hisListing.tk.call('tix', 'getimage', 'ck_on') off = self.hisListing.tk.call('tix', 'getimage', 'ck_off') hlist.delete_all() import Tkinter row = 0 self._vars = {} for m in [s.molecule for s in self.surfListBox.getvalue()]: for r in m.residues: try: hisType = self.hisListingData[r] except KeyError: continue hlist.add(row, itemtype="text", text="%s (%s)" % (m.name, m.oslIdent())) hlist.item_create(row, 1, itemtype="text", text=r.oslIdent( start=chimera.SelResidue)) var = Tkinter.IntVar(hlist) var.set(hisType in ["HID", "HIP"]) cmd = lambda r=r: self._toggleDelta(r) self._vars[r] = [var] toggle = Tkinter.Checkbutton(hlist, command=cmd, variable=var, image=off, selectimage=on, selectcolor="", indicatoron=False, borderwidth=0) hlist.item_create(row, 2, itemtype="window", window=toggle, style=self._checkButtonStyle) var = Tkinter.IntVar(hlist) var.set(hisType in ["HIE", "HIP"]) cmd = lambda r=r: self._toggleEpsilon(r) self._vars[r].append(var) toggle = Tkinter.Checkbutton(hlist, command=cmd, variable=var, image=off, selectimage=on, selectcolor="", indicatoron=False, borderwidth=0) hlist.item_create(row, 3, itemtype="window", window=toggle, style=self._checkButtonStyle) row += 1 def _updateHisListingData(self): newData = {} default = { 'delta': 'HID', 'epsilon': 'HIE', 'both': 'HIP', self.HB: 'HID' }[self.hisDefault.getvalue()] for m in [s.molecule for s in self.surfListBox.getvalue()]: for r in m.residues: if r.type not in ["HIS", "HIE", "HIP", "HID"]: continue try: newData[r] = self.hisListingData[r] except KeyError: if r.type == 'HIS': newData[r] = default else: newData[r] = r.type self.hisListingData = newData
class VolumeDialog(ModelessDialog): title = "Calculate Atomic Occupancy" help = "ContributedSoftware/movie/movie.html#occupancy" provideStatus = True statusPosition = "left" buttons = ('OK', 'Close') default = 'OK' def __init__(self, movie): self.movie = movie movie.subdialogs.append(self) ModelessDialog.__init__(self) def map(self, e=None): if not self.movie.holdingSteady: self.status("No atoms being held steady -- see Help", color="red") def fillInUI(self, parent): Tkinter.Label(parent, text="Collect positions of selected" " atoms over trajectory", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption, StringOption self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.doCutoff = BooleanOption( parent, 4, 'Limit data collection' ' to within cutoff distance of any "held steady" atoms', True, None) self.cutoff = FloatOption(parent, 5, "Cutoff distance", prefs[VOLUME_CUTOFF], None, width=4) self.resolution = FloatOption(parent, 6, "Volume grid spacing", prefs[VOLUME_RESOLUTION], None, min=0.0001, width=4) self.volumeName = StringOption(parent, 7, "Volume data name", self.movie.ensemble.name, None, width=20) self.byAtomType = BooleanOption( parent, 8, "Collect data" " separately for each atom type in selection", True, None, balloon="Create a volume data set for" " each type of atom type\n(sp2 oxygen, aromatic carbon," " etc.) in current selection") def Apply(self): from chimera import UserError atoms = chimera.selection.currentAtoms() if not atoms: self.enter() raise UserError("No atoms selected") startFrame = self.startFrame.get() endFrame = self.endFrame.get() if endFrame <= startFrame: self.enter() raise UserError("Start frame must be less" " than end frame") if startFrame < self.movie.startFrame \ or endFrame > self.movie.endFrame: self.enter() raise UserError("Start or end frame outside" " of trajectory") if self.doCutoff.get(): bound = prefs[VOLUME_CUTOFF] = self.cutoff.get() else: bound = None prefs[VOLUME_RESOLUTION] = self.resolution.get() step = self.stride.get() spacing = self.resolution.get() name = self.volumeName.get() atomTypes = {} if self.byAtomType.get(): for a in atoms: atomTypes.setdefault(a.idatmType, []).append(a) if len(atomTypes) > 1: for atomType, atAtoms in atomTypes.items(): self.movie.computeVolume(atAtoms, startFrame=startFrame, endFrame=endFrame, step=step, bound=bound, spacing=spacing, volumeName=name + " [" + atomType + "]") else: self.movie.computeVolume(atoms, startFrame=startFrame, endFrame=endFrame, step=step, bound=bound, spacing=spacing, volumeName=name)
def fillInUI(self, parent): import Pmw, Tkinter self.buttonWidgets['OK']['state'] = 'disabled' self.buttonWidgets['Apply']['state'] = 'disabled' from chimera.widgets import ModelScrolledListBox self.surfListBox = ModelScrolledListBox(parent, labelpos='n', label_text='Surfaces to color by ESP:', listbox_selectmode="extended", filtFunc=lambda m: isinstance(m, chimera.MSMSModel), selectioncommand=self._selSurfCB) self.surfListBox.grid(row=0, column=0, sticky="nsew", columnspan=2) Pmw.OptionMenu(parent, command=self._menuCB, initialitem="3", items=[str(x) for x in range(2, 12)], labelpos='w', label_text="Number of colors/values:").grid(row=1, column=0, columnspan=2) f = self.interpFrame = Tkinter.Frame(parent) f.grid(row=2, column=0, columnspan=2) self.wells = [] self.values = [] self._entryOpts = { 'validate': 'real', 'entry_justify': 'center', 'entry_width': 6 } from CGLtk.color.ColorWell import ColorWell for color, value in [("red", -10), ("white", 0), ("blue", 10)]: well = ColorWell(f, color=color) well.grid(row=0, column=len(self.wells)) self.wells.append(well) entry = Pmw.EntryField(f, value=str(value), **self._entryOpts) entry.grid(row=1, column=len(self.values)) self.values.append(entry) from chimera.tkoptions import FloatOption, BooleanOption self.distDep = BooleanOption(parent, 3, "Distance-dependent dielectric", True, None, balloon= "If true, charge falls off with distance squared to\n" "simulate solvent screening effects") self.dielectric = FloatOption(parent, 4, "Dielectric constant", 4.0, None) self.surfDist = FloatOption(parent, 5, "Distance from surface", 1.4, None, balloon="Potential at this distance from\n" "the surface is used for coloring") self.hisGroup = Pmw.Group(parent, hull_padx=2, tag_text="Implicit Histidine Protonation") self.hisGroup.grid(row=6, column=0, columnspan=2, sticky="nsew") self.hisProtVar = Tkinter.StringVar(parent) self.hisProtVar.set("name") interior = self.hisGroup.interior() interior.columnconfigure(0, weight=1) lab = Tkinter.Label(interior, text="Assumed histidine " "protonation for\nstructures without explicit hydrogens") from tkFont import Font font = Font(font=lab.cget('font')) font.config(size=int(0.75 * float(font.cget('size'))), slant='italic') lab.config(font=font) lab.grid(row=0) Tkinter.Radiobutton(interior, variable=self.hisProtVar, value="name", text="Residue name-based", command= self._switchHisList).grid(row=1, sticky='w') f = Tkinter.Frame(interior) f.grid(row=2) Tkinter.Label(f, text="HID/HIE/HIP = delta/epsilon/both").grid( row=0, sticky='w') self.hisDefault = Pmw.OptionMenu(f, initialitem=self.HB, items=[self.HB, "delta", "epsilon", "both"], labelpos='w', label_text="HIS = ", command=lambda a, s=self: setattr(s, 'hisChanged', True)) self.hisDefault.grid(row=1, sticky='w') self._pickText = Tkinter.StringVar(parent) self._pickText.set("Specified individually...") Tkinter.Radiobutton(interior, variable=self.hisProtVar, value="pick", textvariable=self._pickText, command=self._switchHisList).grid(row=3, sticky='w') Tkinter.Button(parent, pady=0, command=self._colorKeyCB, text="Create corresponding color key").grid(row=7, column=0, columnspan=2) self.hisChanged = False
def fillInUI(self, parent): import Pmw, Tkinter self.buttonWidgets['OK']['state'] = 'disabled' self.buttonWidgets['Apply']['state'] = 'disabled' from chimera.widgets import ModelScrolledListBox self.surfListBox = ModelScrolledListBox( parent, labelpos='n', label_text='Surfaces to color by ESP:', listbox_selectmode="extended", filtFunc=lambda m: isinstance(m, chimera.MSMSModel), selectioncommand=self._selSurfCB) self.surfListBox.grid(row=0, column=0, sticky="nsew", columnspan=2) Pmw.OptionMenu(parent, command=self._menuCB, initialitem="3", items=[str(x) for x in range(2, 12)], labelpos='w', label_text="Number of colors/values:").grid( row=1, column=0, columnspan=2) f = self.interpFrame = Tkinter.Frame(parent) f.grid(row=2, column=0, columnspan=2) self.wells = [] self.values = [] self._entryOpts = { 'validate': 'real', 'entry_justify': 'center', 'entry_width': 6 } from CGLtk.color.ColorWell import ColorWell for color, value in [("red", -10), ("white", 0), ("blue", 10)]: well = ColorWell(f, color=color) well.grid(row=0, column=len(self.wells)) self.wells.append(well) entry = Pmw.EntryField(f, value=str(value), **self._entryOpts) entry.grid(row=1, column=len(self.values)) self.values.append(entry) from chimera.tkoptions import FloatOption, BooleanOption self.distDep = BooleanOption( parent, 3, "Distance-dependent dielectric", True, None, balloon="If true, charge falls off with distance squared to\n" "simulate solvent screening effects") self.dielectric = FloatOption(parent, 4, "Dielectric constant", 4.0, None) self.surfDist = FloatOption(parent, 5, "Distance from surface", 1.4, None, balloon="Potential at this distance from\n" "the surface is used for coloring") self.hisGroup = Pmw.Group(parent, hull_padx=2, tag_text="Implicit Histidine Protonation") self.hisGroup.grid(row=6, column=0, columnspan=2, sticky="nsew") self.hisProtVar = Tkinter.StringVar(parent) self.hisProtVar.set("name") interior = self.hisGroup.interior() interior.columnconfigure(0, weight=1) lab = Tkinter.Label( interior, text="Assumed histidine " "protonation for\nstructures without explicit hydrogens") from tkFont import Font font = Font(font=lab.cget('font')) font.config(size=int(0.75 * float(font.cget('size'))), slant='italic') lab.config(font=font) lab.grid(row=0) Tkinter.Radiobutton(interior, variable=self.hisProtVar, value="name", text="Residue name-based", command=self._switchHisList).grid(row=1, sticky='w') f = Tkinter.Frame(interior) f.grid(row=2) Tkinter.Label(f, text="HID/HIE/HIP = delta/epsilon/both").grid(row=0, sticky='w') self.hisDefault = Pmw.OptionMenu( f, initialitem=self.HB, items=[self.HB, "delta", "epsilon", "both"], labelpos='w', label_text="HIS = ", command=lambda a, s=self: setattr(s, 'hisChanged', True)) self.hisDefault.grid(row=1, sticky='w') self._pickText = Tkinter.StringVar(parent) self._pickText.set("Specified individually...") Tkinter.Radiobutton(interior, variable=self.hisProtVar, value="pick", textvariable=self._pickText, command=self._switchHisList).grid(row=3, sticky='w') Tkinter.Button(parent, pady=0, command=self._colorKeyCB, text="Create corresponding color key").grid( row=7, column=0, columnspan=2) self.hisChanged = False
class CreatePlaneDialog(ModelessDialog): title = "Define Plane" help = "ContributedSoftware/structuremeas/structuremeas.html#define-plane" provideStatus = True statusPosition = "above" def fillInUI(self, parent): import Pmw, Tkinter row = 0 Tkinter.Label(parent, text="Create plane for selected atoms...").grid( row=row, columnspan=2) row += 1 from chimera.tkoptions import StringOption, BooleanOption self.nameOpt = StringOption(parent, row, "Plane name", "plane", None) row += 1 self.replaceExistingOpt = BooleanOption(parent, row, "Replace existing planes", False, None) row += 1 from chimera.tkoptions import ColorOption, FloatOption self.colorOpt = ColorOption(parent, row, "Color", None, None, balloon="Plane color. If No Color, then the plane" " will be colored to match the structure") row += 1 self.autoRadiusOpt = BooleanOption(parent, row, "Set disk size to enclose atom projections", True, self._radCB) row += 1 self.radRow = row self.radOffsetOpt = FloatOption(parent, row, "Extra radius" " (padding)", 0.0, None) self.radiusOpt = FloatOption(parent, row, "Fixed radius", 10.0, None) self.radiusOpt.forget() row += 1 self.thicknessOpt = FloatOption(parent, row, "Disk thickness", prefs[PLANE_THICKNESS], None) def Apply(self): from chimera import UserError if self.replaceExistingOpt.get(): planeManager.removePlanes(planeManager.planes) kw = { 'color': self.colorOpt.get(), 'thickness': self.thicknessOpt.get() } prefs[PLANE_THICKNESS] = kw['thickness'] if self.autoRadiusOpt.get(): kw['radiusOffset'] = self.radOffsetOpt.get() else: kw['radius'] = self.radiusOpt.get() replyobj.info("Creating plane\n") selAtoms = selection.currentAtoms() if len(selAtoms) < 3: self.enter() raise UserError("Need to select at least three" " atoms to define a plane") planeManager.createPlane(self.nameOpt.get().strip(), selAtoms, **kw) def _radCB(self, opt): if opt.get(): self.radiusOpt.forget() self.radOffsetOpt.manage() else: self.radOffsetOpt.forget() self.radiusOpt.manage()
def fillInUI(self, parent): Tkinter.Label(parent, text="Collect positions of selected" " atoms over trajectory", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption, StringOption self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.doCutoff = BooleanOption( parent, 4, 'Limit data collection' ' to within cutoff distance of any "held steady" atoms', True, None) self.cutoff = FloatOption(parent, 5, "Cutoff distance", prefs[VOLUME_CUTOFF], None, width=4) self.resolution = FloatOption(parent, 6, "Volume grid spacing", prefs[VOLUME_RESOLUTION], None, min=0.0001, width=4) self.volumeName = StringOption(parent, 7, "Volume data name", self.movie.ensemble.name, None, width=20) self.byAtomType = BooleanOption( parent, 8, "Collect data" " separately for each atom type in selection", True, None, balloon="Create a volume data set for" " each type of atom type\n(sp2 oxygen, aromatic carbon," " etc.) in current selection")
def __init__(self, parent, dialog, prefPrefix, callback): Pmw.Group.__init__(self, parent, tag_text="Line wrapping") self.__callback = callback self.__dialog = dialog self.__prefPrefix = prefPrefix self.__wrapVar = Tkinter.IntVar(dialog.uiMaster()) if dialog.mav.prefs[prefPrefix + WRAP_IF]: self.__wrapVar.set(2) elif dialog.mav.prefs[prefPrefix + WRAP]: self.__wrapVar.set(0) else: self.__wrapVar.set(1) row = 0 f = Tkinter.Frame(self.interior()) f.grid(row=row, column=0, columnspan=2, sticky="w") b = Tkinter.Radiobutton(f, text="Wrap to new line every ", variable=self.__wrapVar, value=0, command=self.__newWrap) b.grid(row=0, column=0, sticky="e") self.__lineWidthEntry = Pmw.EntryField( f, command=self.__newWrap, labelpos="e", label_text="0 residues", entry_width=2, entry_justify='right', validate='numeric', value=dialog.mav.prefs[prefPrefix + LINE_WIDTH] / 10) self.__lineWidthEntry.grid(row=0, column=1, sticky="w") dialog._entryWidgets.append(self.__lineWidthEntry) row += 1 if not prefPrefix: f = Tkinter.Frame(self.interior()) f.grid(row=row, column=0, columnspan=2, sticky="w") b = Tkinter.Radiobutton(f, text="Wrap if ", variable=self.__wrapVar, value=2, command=self.__newWrap) b.grid(row=0, column=0, sticky="e") self.__wrapThresholdEntry = Pmw.EntryField( f, command=self.__newWrap, labelpos="e", entry_width=2, validate='numeric', entry_justify='center', label_text=" or fewer sequences", value=dialog.mav.prefs[prefPrefix + WRAP_THRESHOLD]) self.__wrapThresholdEntry.grid(row=0, column=1, sticky="w") dialog._entryWidgets.append(self.__wrapThresholdEntry) row += 1 b = Tkinter.Radiobutton(self.interior(), text="Never wrap", variable=self.__wrapVar, value=1, command=self.__newWrap) b.grid(row=row, column=0, columnspan=2, sticky="w") row += 1 from chimera.tkoptions import BooleanOption BooleanOption(self.interior(), row, "Space between wrapped blocks", dialog.mav.prefs[prefPrefix + BLOCK_SPACE], self.__blockSpace)
class IlabelDialog(ModelessDialog): name = "2D Labels/Color Key" provideStatus = True buttons = ("Delete", "Close") LABELS = "Labels" COLOR_KEY = "Color Key" MOUSE_LABEL_TEXT = "Use mouse for label placement" MOUSE_KEY_TEXT = "Use mouse for key placement" EmphasisColor = "forest green" def __init__(self): import os.path myDir, junk = os.path.split(__file__) addFunction('place text', (self._pickLabel, self._moveLabel, None), icon=chimage.get(Image.open(os.path.join(myDir, 'ilabel.png')), tkgui.app)) addFunction('place key', (self._startOrGrabKey, self._sizeOrMoveKey, None), icon=chimage.get( Image.open(os.path.join(myDir, 'key.png')), tkgui.app)) import Ilabel if not Ilabel._ilabelModel: Ilabel.IlabelModel() self.model = Ilabel._ilabelModel ModelessDialog.__init__(self) self._sessionHandlerID = chimera.triggers.addHandler( SAVE_SESSION, self._saveSession, None) self._closeHandlerID = chimera.triggers.addHandler( CLOSE_SESSION, self.destroy, None) self._beginRestoreHandlerID = chimera.triggers.addHandler( BEGIN_RESTORE_SESSION, self.destroy, None) def fillInUI(self, parent): top = parent.winfo_toplevel() menubar = Tkinter.Menu(top, type="menubar", tearoff=False) top.config(menu=menubar) self.fileMenu = Tkinter.Menu(menubar) menubar.add_cascade(label="File", menu=self.fileMenu) self.fileMenu.add_command(label="Write...", command=self._writeFileCB) self.fileMenu.add_command(label="Read...", command=self._readFileCB) from chimera.tkgui import aquaMenuBar aquaMenuBar(menubar, parent, row=0) from ColorKey import KeyModel parent.rowconfigure(1, weight=1) parent.columnconfigure(0, weight=1) # _pageRaisedCB uses mouseModeVar, so define first self.mouseLabelingVar = Tkinter.IntVar(parent) self.mouseLabelingVar.set(True) self.mlLabelVar = Tkinter.StringVar(parent) self.mouseModeButton = Tkinter.Checkbutton(parent, command=self._mouseFuncCB, variable=self.mouseLabelingVar, textvariable=self.mlLabelVar) self.mouseModeButton.grid(row=2, column=0) self.notebook = Pmw.NoteBook(parent, raisecommand=self._pageRaisedCB) self.notebook.add(self.LABELS, tab_text=self.LABELS) self.notebook.add(self.COLOR_KEY, tab_text=self.COLOR_KEY) self.notebook.grid(row=1, column=0, sticky="nsew") self._fillLabelsPage(self.notebook.page(self.LABELS)) self.keyModel = KeyModel(self) self.keyPosition = None self._fillColorKeyPage(self.notebook.page(self.COLOR_KEY)) def _fillLabelsPage(self, page): page.columnconfigure(0, weight=1) page.columnconfigure(1, weight=1) page.columnconfigure(2, weight=1) row = 0 from CGLtk.Table import SortableTable self.labelTable = SortableTable(page, automultilineHeaders=False) self.labelTable.addColumn("Label [(x, y) text]", self._labelListing, anchor='w') self.labelTable.addColumn("Shown", "shown", format=bool) self.labelTable.setData(self.model.labels) self.labelTable.launch(browseCmd=self._tableCB, selectMode="single") self.labelTable.grid(row=row, column=0, columnspan=3, sticky="nsew") page.rowconfigure(row, weight=1) row += 1 self.labelText = Pmw.ScrolledText(page, labelpos='w', label_text="Text", text_height=3, text_width=20, text_wrap='none', text_state='disabled', text_exportselection=False) text = self.labelText.component('text') text.bind("<<Modified>>", self._textCB) text.bind("<<Selection>>", self._updateTextAttrWidgets) self.labelText.grid(row=row, column=0, sticky='nsew', columnspan=3) page.rowconfigure(row, weight=1) row += 1 self.labelSymbolMenu = Pmw.OptionMenu(page, labelpos='w', label_text="Insert symbol:", command=self._insertSymbol, items=[ u'\N{GREEK SMALL LETTER ALPHA}', u'\N{GREEK SMALL LETTER BETA}', u'\N{GREEK SMALL LETTER GAMMA}', u'\N{GREEK SMALL LETTER DELTA}', u'\N{GREEK SMALL LETTER EPSILON}', u'\N{GREEK SMALL LETTER PI}', u'\N{GREEK SMALL LETTER PHI}', u'\N{GREEK SMALL LETTER CHI}', u'\N{GREEK SMALL LETTER PSI}', u'\N{GREEK SMALL LETTER OMEGA}', u'\N{LEFTWARDS ARROW}', u'\N{RIGHTWARDS ARROW}', u'\N{LEFT RIGHT ARROW}', u'\N{UPWARDS ARROW}', u'\N{DOWNWARDS ARROW}', u'\N{SUPERSCRIPT TWO}', u'\N{SUPERSCRIPT THREE}', u'\N{DEGREE SIGN}', u'\N{LATIN CAPITAL LETTER A WITH RING ABOVE}', "more..." ]) self.labelSymbolMenu.grid(row=row, column=0, columnspan=3) row += 1 colorHouse = Pmw.LabeledWidget(page, labelpos='w', label_text="Color") colorHouse.grid(row=row, column=0, rowspan=3) from CGLtk.color.ColorWell import ColorWell self.colorWell = ColorWell(colorHouse.interior(), color=self._contrastWithBG(), callback=self._colorCB) self.colorWell.grid() from chimera.tkoptions import IntOption self.labelFontSize = IntOption(page, row, "Font size", 24, self._labelChangeCB, startCol=1, min=1, attribute="size", width=3) row += 1 self.labelFontStyle = FontStyle(page, row, "Font style", oglFont.normal, self._labelChangeCB, startCol=1) row += 1 self.labelFontTypeface = FontTypeface(page, row, "Font typeface", FONT_TYPEFACE_VALUES[0], self._labelChangeCB, startCol=1) row += 1 if self.model.curLabel: self.changeToLabel(self.model.curLabel, force=True) def _fillColorKeyPage(self, page): from chimera.tkoptions import IntOption, EnumOption, \ BooleanOption, RGBAOption f = Tkinter.Frame(page) f.grid(row=0, columnspan=2) self.numComponents = IntOption(f, 0, "Number of colors/labels", 3, self._componentsCB, min=2, width=2) self.componentsFrame = Tkinter.Frame(page) self.componentsFrame.grid(row=1, column=0, sticky="nsew", columnspan=2) page.columnconfigure(0, weight=1) self.componentsFrame.columnconfigure(1, weight=1) class ColorTreatment(EnumOption): values = ("distinct", "blended") self.colorTreatment = ColorTreatment(page, 2, "Color range depiction", "blended", self._keyChangeCB, balloon="Should colors be shown as distinct rectangles" " or as a continuous range") class LabelPosition(EnumOption): values = ("left/top", "right/bottom") self.labelPos = LabelPosition(page, 3, "Label positions", "right/bottom", self._keyChangeCB, balloon="Position of" " labels relative to color key.\nLabels always" " positioned adjacent to long side.") self.labelColor = RGBAOption(page, 4, "Label color", self._contrastWithBG(), self._keyChangeCB, balloob= "Label color. If set to 'No color', use corresponding" " key color", noneOkay=True) class LabelJustification(EnumOption): values = ("left", "decimal point", "right") self.justification = LabelJustification(page, 5, "Label justification", "decimal point", self._keyChangeCB, balloon="Justification of label text" " in a vertical key layout.\nHorizontal key labels will" " always be center justified.") self.labelOffset = IntOption(page, 6, "Label offset", 0, self._keyChangeCB, width=3, balloon="Additional offset" " of labels from color bar, in pixels") self.keyFontSize = IntOption(page, 7, "Font size", 24, self._keyChangeCB, width=3) self.keyFontStyle = FontStyle(page, 8, "Font style", oglFont.normal, self._keyChangeCB) self.keyFontTypeface = FontTypeface(page, 9, "Font typeface", FONT_TYPEFACE_VALUES[0], self._keyChangeCB) self.borderColor = RGBAOption(page, 10, "Border color", None, self._keyChangeCB, balloon="Color of border" " around color key (not each individual color).\n" "If 'no color', then no border is drawn.") self.borderWidth = IntOption(page, 11, "Border width", 3, self._keyChangeCB, balloon="in pixels") self.tickMarks = BooleanOption(page, 12, "Show tick marks", False, self._keyChangeCB, balloon="Show tick marks" " pointing from key to labels") self._componentsCB(self.numComponents) def destroy(self, *args): self.mouseLabelingVar.set(True) self.mouseModeButton.invoke() chimera.triggers.deleteHandler(SAVE_SESSION, self._sessionHandlerID) chimera.triggers.deleteHandler(CLOSE_SESSION, self._closeHandlerID) chimera.triggers.deleteHandler(BEGIN_RESTORE_SESSION, self._beginRestoreHandlerID) chimera.openModels.close([self.model, self.keyModel]) ModelessDialog.destroy(self) def map(self, e=None): self._pageRaisedCB(self.notebook.getcurselection()) def unmap(self, e=None): self.mouseLabelingVar.set(True) self.mouseModeButton.invoke() def changeToLabel(self, nextLabel, force=False): if nextLabel == self.model.curLabel and not force: return if self.model.curLabel and not unicode(self.model.curLabel) \ and self.model.curLabel != nextLabel: # remove previous label if empty self.removeLabel(self.model.curLabel) self.model.changeToLabel(nextLabel) self.labelText.component('text').configure(state='normal') self.labelTable.select(nextLabel) self.labelText.settext(unicode(nextLabel)) text = self.labelText.component('text') lineIndex = 1 for line in self.model.curLabel.lines: charIndex = 0 for c in line: text.tag_add(id(c), "%d.%d" % (lineIndex, charIndex)) charIndex += 1 text.tag_add(id(line), "%d.%d" % (lineIndex, charIndex)) lineIndex += 1 def Delete(self): if self.notebook.getcurselection() == self.LABELS: self.labelText.clear() if not self.model.curLabel: self.status("No label to delete", color="red", blankAfter=10) return self.removeLabel(self.model.curLabel) self.labelText.component('text').configure( state='disabled') else: self.keyPosition = None self._keyChangeCB() def Help(self): helpLoc = "ContributedSoftware/2dlabels/2dlabels.html" if self.notebook.getcurselection() == self.COLOR_KEY: helpLoc += "#colorkey" chimera.help.display(helpLoc) def keyConfigure(self, data, pageChange=True): self._componentsCB(len(data), update=False) for datum, well, label in zip(data, self.wells, self.labels): color, text = datum well.showColor(color, doCallback=False) label.variable.set(text, invoke_callbacks=False) self._keyChangeCB() if pageChange: self.notebook.selectpage(self.COLOR_KEY) def makeChar(self, char, model): attrs = {} try: attrs['rgba'] = self.colorWell.rgba except AttributeError: # multi or None if model: attrs['rgba'] = model.rgba size = self.labelFontSize.get() if size is not None: attrs['size'] = size style = self.labelFontStyle.get() if style is not None: attrs['style'] = style fontName = self.labelFontTypeface.get() if fontName is not None: attrs['fontName'] = fontName return Character(char, **attrs) def newLabel(self, pos): label = self.model.newLabel(pos) self.labelTable.setData(self.model.labels) self.status("Mouse drag to reposition label", color=self.EmphasisColor) return label def removeLabel(self, label): self.model.removeLabel(label) self.labelTable.setData(self.model.labels) if self.model.curLabel is not None: self.labelTable.select(self.model.curLabel) def reverseKey(self): data = zip([w.rgba for w in self.wells], [l.variable.get() for l in self.labels]) data.reverse() self.keyConfigure(data) def setLabelFromText(self): curLabel = self.model.curLabel text = self.labelText.component('text') # delete parts of label not in text... # # newlines first... while len(curLabel.lines) > 1: for i, line in enumerate(curLabel.lines[:-1]): if not text.tag_ranges(id(line)): curLabel.lines[i+1][:0] = line del curLabel.lines[i] break else: break # characters... for line in curLabel.lines: for c in line[:]: if not text.tag_ranges(id(c)): line.remove(c) # get new parts of text into label model = None targets = [] lines = curLabel.lines for line in lines: targets.extend([id(c) for c in line]) if not model and line: model = line[0] if line is not lines[-1]: targets.append(id(line)) contents = self.labelText.get()[:-1] # drop trailing newline if targets: target = targets.pop(0) else: target = None textLine = 1 textIndex = -1 curLine = lines[0] for c in contents: textIndex += 1 if str(target) in text.tag_names("%d.%d" % (textLine, textIndex)): if targets: target = targets.pop(0) else: target = None if c == '\n': textLine += 1 textIndex = -1 curLine = lines[[id(l) for l in lines].index( id(curLine))+1] elif curLine: model = curLine[textIndex] elif c == '\n': insertLine = curLine[0:textIndex] lines.insert(textLine-1, insertLine) del curLine[0:textIndex] text.tag_add(id(insertLine), "%d.%d" % (textLine, textIndex)) textLine += 1 textIndex = -1 else: labelChar = self.makeChar(c, model) curLine.insert(textIndex, labelChar) text.tag_add(id(labelChar), "%d.%d" % (textLine, textIndex)) self.model.setMajorChange() def updateGUI(self, source="gui"): curLabel = self.model.curLabel if curLabel and source == "gui": self.setLabelFromText() self.labelTable.setData(self.model.labels) if curLabel: self.labelTable.select(curLabel) self._updateTextAttrWidgets() def _colorCB(self, color): curLabel = self.model.curLabel if not curLabel: self.status("No label to color", color='red') return self.model.setMajorChange() for c in self._selChars(): c.rgba = color def _componentsCB(self, opt, update=True): cf = self.componentsFrame if hasattr(self, 'wells'): for well in self.wells: well.grid_forget() well.destroy() for label in self.labels: label.frame.grid_forget() self.reverseButton.grid_forget() self.reverseButton.destroy() else: Tkinter.Label(cf, text="Colors").grid(row=0) Tkinter.Label(cf, text="Labels").grid(row=0, column=1) if isinstance(opt, int): numComponents = opt self.numComponents.set(opt) else: numComponents = opt.get() wellSize = min(38, int( (7 * 38) / numComponents )) from CGLtk.color.ColorWell import ColorWell self.wells = [] self.labels = [] from CGLtk import Hybrid for i in range(numComponents): well = ColorWell(cf, width=wellSize, height=wellSize, callback=self._keyChangeCB, color='white') well.grid(row=i+1) self.wells.append(well) label = Hybrid.Entry(cf, "", 10) label.variable.add_callback(self._keyTypingCB) label.frame.grid(row=i+1, column=1, sticky='ew') self.labels.append(label) self.reverseButton = Tkinter.Button(cf, command=self.reverseKey, text="Reverse ordering of above", pady=0) self.reverseButton.grid(row=numComponents+1, column=0, columnspan=2) self.notebook.setnaturalsize() if update: self._keyChangeCB() def _contrastWithBG(self): bg = chimera.viewer.background if bg: bgColor = bg.rgba() else: bgColor = (0, 0, 0) if bgColor[0]*2 + bgColor[1]*3 + bgColor[2] < 0.417: return (1, 1, 1) else: return (0, 0, 0) def _eventToPos(self, viewer, event, offset = (0, 0)): w, h = viewer.windowSize return (event.x - offset[0]) / float(w), \ (h - event.y - offset[1]) / float(h) def _handleTextChange(self): self.updateGUI() self.labelText.edit_modified(False) def _insertSymbol(self, item): if len(item) > 1: from chimera import help help.display("ContributedSoftware/2dlabels/symbols.html") return if not self.model.labels: self.status("No labels have been created yet", color="red") return if not self.labelTable.selected(): self.status("No labels active", color="red") self.labelText.insert("insert", item) self.setLabelFromText() def _keyChangeCB(self, *args): self.keyModel.setMajorChange() def _keyTypingCB(self, fromAfter=False): # wait for a pause in typing before updating key... if fromAfter: self._typingHandler = None self._keyChangeCB() return handle = getattr(self, '_typingHandler', None) if handle: self.componentsFrame.after_cancel(handle) self._typingHandler = self.componentsFrame.after(500, lambda: self._keyTypingCB(fromAfter=True)) def _labelChangeCB(self, option): curLabel = self.model.curLabel self.model.setMajorChange() val = option.get() attrName = option.attribute for c in self._selChars(): setattr(c, attrName, val) def _labelListing(self, label): text = unicode(label) if '\n' in text: newline = text.index('\n') text= text[:newline] + "..." if not text: text = "<empty>" return "(%.2f, %.2f) %s" % (label.pos[0], label.pos[1], text) def _mouseFuncCB(self): self.status("") if not self.mouseLabelingVar.get(): if hasattr(self, "_prevMouse"): setButtonFunction("1", (), self._prevMouse) delattr(self, "_prevMouse") elif self.mlLabelVar.get() == self.MOUSE_LABEL_TEXT: if not hasattr(self, "_prevMouse"): self._prevMouse = getFuncName("1", ()) setButtonFunction("1", (), "place text") else: if not hasattr(self, "_prevMouse"): self._prevMouse = getFuncName("1", ()) setButtonFunction("1", (), "place key") def _moveLabel(self, viewer, event): pos = self._eventToPos(viewer, event, self._moveOffset) self.model.moveLabel(pos) curLabel = self.model.curLabel self.labelTable.setData(self.model.labels) self.labelTable.select(curLabel) def _pageRaisedCB(self, pageName): if pageName == "Labels": pageItem = self.MOUSE_LABEL_TEXT if not self.model.labels: self.status("Click mouse button 1 in graphics\n" "window to place first label", color=self.EmphasisColor) for index in range(0, self.fileMenu.index('end')+1): self.fileMenu.entryconfigure(index, state='normal') else: pageItem = self.MOUSE_KEY_TEXT self.status("Drag mouse to position/size key", color=self.EmphasisColor) for index in range(0, self.fileMenu.index('end')+1): self.fileMenu.entryconfigure(index, state='disabled') self.mlLabelVar.set(pageItem) # just setting the var doesn't cause the callback, and # yet using invoke() toggles the var, so set it _opposite_ # to what's desired before calling invoke() self.mouseLabelingVar.set(False) self.mouseModeButton.invoke() def _pickLabel(self, viewer, event): w, h = viewer.windowSize pos = self._eventToPos(viewer, event) label, self._moveOffset = self.model.pickLabel(pos, w, h) if label is None: label = self.newLabel(pos) self._moveOffset = (0, 0) self.changeToLabel(label) self.labelText.component('text').focus_set() def _readFile(self, okayed, dialog): if not okayed: return from Ilabel import readFiles readFiles(dialog.getPaths(), clear=dialog.deleteExistingVar.get()) def _readFileCB(self): if not hasattr(self, "_readFileDialog"): self._readFileDialog = ReadFileDialog( command=self._readFile, clientPos='s') self._readFileDialog.enter() def _restoreSession(self, info): if info["sel ranges"]: self.labelText.tag_add("sel", *info["sel ranges"]) self._updateTextAttrWidgets() self._suppressMap = True self.labelText.edit_modified(False) if "key position" not in info: self.notebook.selectpage(self.LABELS) if info["mouse func"] == "normal": self.mouseLabelingVar.set(True) self.mouseModeButton.invoke() return self.keyPosition = info["key position"] self.colorTreatment.set(info["color depiction"]) self.labelPos.set(info["label positions"]) self.labelColor.set(info["label color"]) self.justification.set(info["label justification"]) self.labelOffset.set(info["label offset"]) self.keyFontSize.set(info["font size"]) self.keyFontStyle.set(info["font typeface"]) if "font name" in info: self.keyFontTypeface.set(info["font name"]) self.borderColor.set(info["border color"]) self.borderWidth.set(info["border width"]) self.tickMarks.set(info["show ticks"]) self.keyConfigure(info["colors/labels"]) if self.keyPosition: self.notebook.selectpage(self.COLOR_KEY) else: self.notebook.selectpage(self.LABELS) if info["mouse func"] == "normal": self.mouseLabelingVar.set(True) self.mouseModeButton.invoke() return info def _saveSession(self, triggerName, myData, sessionFile): print>>sessionFile, """ def restore2DLabelDialog(info): from chimera.dialogs import find, display from Ilabel.gui import IlabelDialog dlg = find(IlabelDialog.name) if dlg is not None: dlg.destroy() dlg = display(IlabelDialog.name) dlg._restoreSession(info) import SimpleSession SimpleSession.registerAfterModelsCB(restore2DLabelDialog, %s) """ % repr(self._sessionInfo()) def _selChars(self): chars = [] curLabel = self.model.curLabel if curLabel: sel = self.labelText.tag_ranges("sel") if sel: sline, schar = [int(x) for x in str(sel[0]).split('.')] eline, echar = [int(x) for x in str(sel[1]).split('.')] sline -= 1 eline -= 1 for li, line in enumerate(curLabel.lines): if li < sline: continue if li > eline: break if sline == eline: chars.extend(line[schar:echar]) elif li == sline: chars.extend(line[schar:]) elif li == eline: chars.extend(line[:echar]) else: chars.extend(line) else: for l in curLabel.lines: chars.extend(l) return chars def _sessionInfo(self): info = {} info["sel ranges"] = tuple([str(tr) for tr in self.labelText.tag_ranges("sel")]) if self.mouseLabelingVar.get(): info["mouse func"] = "labeling" else: info["mouse func"] = "normal" info["key position"] = self.keyPosition info["colors/labels"] = [(w.rgba, l.variable.get()) for w, l in zip(self.wells, self.labels)] info["color depiction"] = self.colorTreatment.get() info["label positions"] = self.labelPos.get() info["label color"] = self.labelColor.get() info["label justification"] = self.justification.get() info["label offset"] = self.labelOffset.get() info["font size"] = self.keyFontSize.get() info["font typeface"] = self.keyFontStyle.get() info["font name"] = self.keyFontTypeface.get() info["border color"] = self.borderColor.get() info["border width"] = self.borderWidth.get() info["show ticks"] = self.tickMarks.get() return info def _sizeOrMoveKey(self, viewer, event): pos = self._eventToPos(viewer, event) if self.grabPos: deltas = [pos[axis] - self.grabPos[axis] for axis in [0, 1]] for posIndex in [0, 1]: old = self.keyPosition[posIndex] self.keyPosition[posIndex] = ( old[0] + deltas[0], old[1] + deltas[1]) self.grabPos = pos elif len(self.keyPosition) == 1: self.keyPosition.append(pos) else: self.keyPosition[1] = pos self._keyChangeCB() def _startOrGrabKey(self, viewer, event): pos = self._eventToPos(viewer, event) if self.keyPosition and len(self.keyPosition) == 2: # possible grab; # see if in middle third of long side... p1, p2 = self.keyPosition x1, y1 = p1 x2, y2 = p2 if abs(x2 - x1) < abs(y2 - y1): longAxis = 1 ymin = min(y2, y1) ymax = max(y2, y1) b1 = (2* ymin + ymax) / 3.0 b2 = (2* ymax + ymin) / 3.0 o1 = min(x1, x2) o2 = max(x1, x2) else: longAxis = 0 xmin = min(x2, x1) xmax = max(x2, x1) b1 = (2* xmin + xmax) / 3.0 b2 = (2* xmax + xmin) / 3.0 o1 = min(y1, y2) o2 = max(y1, y2) if b1 < pos[longAxis] < b2 \ and o1 < pos[1-longAxis] < o2: self.grabPos = pos return self.grabPos = None self.keyPosition = [pos] self._keyChangeCB() self.status("Grab middle of key to reposition", color=self.EmphasisColor) def _tableCB(self, sel): if not sel: return self.changeToLabel(sel) def _textCB(self, e): text = self.labelText.component('text') if not text.tk.call((text._w, 'edit', 'modified')): #if not text.edit_modified(): return # this callback can happen _before_ the change # actually occurs, so do the processing after idle text.after_idle(self._handleTextChange) def _updateTextAttrWidgets(self, e=None): rgba = None multiple = False for c in self._selChars(): if rgba is None: rgba = c.rgba elif rgba != c.rgba: multiple = True break if rgba is not None: self.colorWell.showColor(rgba, multiple=multiple, doCallback=False) self.labelFontSize.display(self._selChars()) self.labelFontStyle.display(self._selChars()) self.labelFontTypeface.display(self._selChars()) def _writeFile(self, okayed, dialog): if not okayed: return from Ilabel import writeFile writeFile(dialog.getPaths()[0]) def _writeFileCB(self): if not hasattr(self, "_writeFileDialog"): from OpenSave import SaveModeless self._writeFileDialog = SaveModeless(command=self._writeFile, title="Write 2D Labels Info") self._writeFileDialog.enter()
class ImageSaveDialog(ModelessDialog): name = "Save Image" buttons = ['Tips', 'Save As', Cancel] default = 'Save As' help = 'UsersGuide/print.html' provideStatus = True def fillInUI(self, master): self._ModelTrigger = None #self._SetupTrigger = None self._SizeTrigger = None self.raytrace = None # Image Size imageSetup = Tix.LabelFrame(master, label="Image Size") imageSetup.pack(fill=Tk.X, ipadx=2, ipady=2) subframe = imageSetup.frame #subframe = Tk.Frame(imageSetup.frame) #subframe.pack(fill=Tk.BOTH, expand=1) # add in conversion factor for pixels and graphics screen from chimera import tkgui win = tkgui.app.graphics res = tkgui.getScreenMMWidth() / win.winfo_screenwidth() convert['pixels'] = mm2pt(res) self.matchAspect = Tk.BooleanVar(master) self.matchAspect.set(1) self.usePrint = Tk.BooleanVar(master) self.usePrint.set(preferences.get(IMAGE_SETUP, USE_PRINT_UNITS)) import itertools row = itertools.count() self.showUsePrint = Tk.Checkbutton(subframe, indicatoron=1, variable=self.usePrint, highlightthickness=0, text=USE_PRINT_UNITS, command=self._updateUsePrint) self.showUsePrint.grid(columnspan=2, row=row.next(), sticky=Tk.W) w, h = chimera.viewer.windowSize self.units = ImageUnitsOption(subframe, row.next(), UNITS, 'pixels', self.updateImageUnits) self.iWidth = FloatOption(subframe, row.next(), 'Image width', w, self.updateImageWidth, min=1e-10) self.iHeight = FloatOption(subframe, row.next(), 'Image height', h, self.updateImageHeight, min=1e-10) matchAspect = Tk.Checkbutton(subframe, indicatoron=1, variable=self.matchAspect, highlightthickness=0, text="Maintain current aspect ratio", command=self.updateMatchAspect) matchAspect.grid(columnspan=2, row=row.next(), sticky=Tk.W) self.grow = Tk.Button(imageSetup.frame, text="Grow to Fit", command=self.Resize, state=Tk.DISABLED) fitrow = row.next() self.grow.grid(row=fitrow, column=0, padx=2, pady=2, sticky=Tk.NSEW) self.shrink = Tk.Button(imageSetup.frame, text="Shrink to Fit", command=lambda f=self.Resize: f(False), state=Tk.DISABLED) self.shrink.grid(row=fitrow, column=1, padx=2, pady=2, sticky=Tk.NSEW) #fetch = Tk.Button(imageSetup.frame, text="Get Pixels", # command=self.fetchWindowSize) #fetch.grid(row=row.next(), column=0, padx=2, pady=2, sticky=Tk.NSEW) #calc = Tk.Button(imageSetup.frame, text="Image Setup", # command=self.showImageSetupDialog) #calc.grid(row=row.next(), column=1, padx=2, pady=2, sticky=Tk.NSEW) self.printRes = FloatOption(subframe, row.next(), DPI, preferences.get(IMAGE_SETUP, DPI), self._updatePrint, min=1) # Image Information info = Tix.LabelFrame(master, label="Image Information") info.pack(fill=Tk.X) d = Tk.Label(info.frame, text="Description:") d.grid(columnspan=2, row=0, column=0, sticky=Tk.W, padx=2, pady=1) self.description = Tk.Entry(info.frame) info.frame.grid_columnconfigure(0, weight=1) info.frame.grid_columnconfigure(1, weight=1) self.description.grid(columnspan=2, row=1, column=0, sticky=Tk.EW, padx=2, pady=2) imageCredits = Tk.Button(info.frame, text="Image Credits", command=self.showImageCreditsDialog) imageCredits.grid(row=2, column=0, padx=2, pady=2) credit = Tk.Button(info.frame, text="Citing Chimera", command=lambda: help.display("credits.html")) credit.grid(row=2, column=1, padx=2, pady=2) # Image camera self.raytrace = BooleanOption(master, -1, 'Raytrace with POV-Ray', False, self._updateRaytrace) self.raytraceOptions = Tk.Button(master, text=POVRAY_SETUP, command=self.showPOVRayOptions) self.raytraceOptions.pack() self.raytraceOptions.pack_forget() self.supersample = SupersampleOption(master, -1, SUPERSAMPLE, preferences.get(IMAGE_SETUP, SUPERSAMPLE), self._updateSS) self.adjustFOV = AdjustFOVOption(master, -1, ADJUST_FOV, preferences.get(IMAGE_SETUP, ADJUST_FOV), self._updateAdjustFOV) self.printMode = _PrintModeOption(master, -1, 'Image camera mode', _PrintModeOption.SAME, self._updatePrintMode) self.lenticular = IntOption(master, -1, 'Number of lenticular images', chimera.Camera.lenticularImageCount(), self._updateLenticular, min=2, width=4) self.lenticular.forget() # switch to user's prefered units self.adjust = convert['pixels'] units = preferences.get(IMAGE_SETUP, UNITS) self._updateUsePrint() self.units.set(units) self.updateImageUnits() def map(self, event=None): self._ModelTrigger = chimera.triggers.addHandler('Model', self._computeMaxLineWidth, None) #self._SetupTrigger = chimera.triggers.addHandler(IMAGE_SETUP, # self._computeMaxLineWidth, None) self._SizeTrigger = chimera.triggers.addHandler( 'graphics window size', self._resetSize, None) self._computeMaxLineWidth() def unmap(self, event=None): if self._ModelTrigger: chimera.triggers.deleteHandler('Model', self._ModelTrigger) self._ModelTrigger = None #if self._SetupTrigger: # chimera.triggers.deleteHandler(IMAGE_SETUP, # self._SetupTrigger) # self._SetupTrigger = None def _computeMaxLineWidth(self, *args): if self.raytrace and self.raytrace.get(): # not relevant if raytracing self.status('', blankAfter=0) return # this should be called models are modified, when the # image size changes and when image setup parameters # change (DPI, supersampling) opengl_max = min( chimera.opengl_getFloat("max point size"), chimera.opengl_getFloat("max line width")) max_lw = max([m.lineWidth for m in chimera.openModels.list(all=True) if hasattr(m, 'lineWidth')]) # compute tile scaling factor like C++ code does width = self.iWidth.get() height = self.iHeight.get() horizPixels, vertPixels, supersample = \ imageArgs(self.units.get(), width, height) width, height = chimera.viewer.windowSize tileScale = float(horizPixels) / float(width) tmp = float(vertPixels) / float(height) if tmp > tileScale: tileScale = tmp tileScale *= supersample opengl_max /= tileScale if max_lw > opengl_max: color = 'red' else: color = 'black' self.status('effective maximum line width is %g' % opengl_max, color=color, blankAfter=0) #def Print(self): # self.Cancel() # image, options = self.getImage() # filename = tempfile.mktemp() # image.save(filename, **options) # cmd = preferences.get(PAGE_SETUP, PRINTER_CMD) # cmd = re.sub('%s', "'" + filename + "'", cmd) # os.system(cmd) # os.unlink(filename) def SaveAs(self): # now save the image self.Cancel() printMode = self.printMode.get() raytrace = self.raytrace.get() if printMode == _PrintModeOption.SAME: printMode = None if not chimera.nogui and raytrace and chimera.viewer.clipping: dialog = ClipWarning() if not dialog.run(chimera.tkgui.app): return saveImage(None, self.iWidth.get(), self.iHeight.get(), units=self.units.get(), master=self.uiMaster(), description=self.description.get().strip(), printMode=printMode, raytrace=raytrace) def Tips(self): import help help.display(self.help + "#tips") def Resize(self, larger=True): vw, vh = chimera.viewer.windowSize iw = self.iWidth.get() ih = self.iHeight.get() vaspect = vw / float(vh) iaspect = iw / float(ih) from chimera import tkgui top = tkgui.app.winfo_toplevel() if larger: if vaspect < iaspect: w = int(vw * iaspect / vaspect + 0.5) if w != vw: top.wm_geometry('') tkgui.app.graphics.config(width=w) elif vaspect > iaspect: h = int(vh * vaspect / iaspect + 0.5) if h != vh: top.wm_geometry('') tkgui.app.graphics.config(height=h) else: if vaspect < iaspect: h = int(vh * vaspect / iaspect + 0.5) if h != vh: top.wm_geometry('') tkgui.app.graphics.config(height=h) elif vaspect > iaspect: w = int(vw * iaspect / vaspect + 0.5) if w != vw: top.wm_geometry('') tkgui.app.graphics.config(width=w) def fetchWindowSize(self): w, h = chimera.viewer.windowSize self.units.set('pixels') self.updateImageUnits() self.iWidth.set(w) self.iHeight.set(h) def _updateRaytrace(self, option): raytrace = option.get() if raytrace: self.printMode.forget() self.lenticular.forget() self.supersample.forget() self.raytraceOptions.pack() else: self.raytraceOptions.pack_forget() self.printMode.manage() self.supersample.manage() self._updatePrintMode(self.printMode) self._computeMaxLineWidth() def _updatePrintMode(self, option): printMode = option.get() if printMode == 'lenticular': self.lenticular.manage() else: self.lenticular.forget() def _updateLenticular(self, option): count = option.get() chimera.Camera.setLenticularImageCount(count) def updateMatchAspect(self, *args): if self.matchAspect.get(): self.grow.config(state=Tk.DISABLED) self.shrink.config(state=Tk.DISABLED) self.Resize() else: self.grow.config(state=Tk.NORMAL) self.shrink.config(state=Tk.NORMAL) def updateImageUnits(self, *args): units = self.units.get() if units == 'pixels': self.printRes.disable() self.adjustFOV.disable() else: self.printRes.enable() self.adjustFOV.enable() if units != preferences.get(IMAGE_SETUP, UNITS): preferences.set(IMAGE_SETUP, UNITS, units) try: adjust = convert[units] except KeyError: adjust = -1 if adjust == self.adjust: return if self.adjust != -1 and adjust != -1: factor = self.adjust / adjust w = self.iWidth.get() * factor self.iWidth.set(w) h = self.iHeight.get() * factor self.iHeight.set(h) if adjust == -1: # entering pixel mode w, h = chimera.viewer.windowSize self.iWidth.set(w) self.iHeight.set(h) elif self.adjust == -1: pass # leaving pixel mode, sanity check #w, h = paper_types[preferences.get(PAGE_SETUP, PAPER_TYPE)] #if self.iWidth.get() > w: # self.iWidth.set(w) #if self.iHeight.get() > h: # self.iHeight.set(h) self.adjust = adjust self._computeMaxLineWidth() def updateImageWidth(self, option): # adjust height to compensate for new width if self.matchAspect.get(): iWidth = option.get() w, h = chimera.viewer.windowSize self.iHeight.set(iWidth * h / w) self._computeMaxLineWidth() def updateImageHeight(self, option): # adjust width to compensate for new height if self.matchAspect.get(): iHeight = option.get() w, h = chimera.viewer.windowSize self.iWidth.set(iHeight * w / h) self._computeMaxLineWidth() def _resetSize(self, triggerName, myData, sizes): width, height, mmwidth, mmheight = sizes units = self.units.get() if units == 'pixels': self.iWidth.set(width) self.iHeight.set(height) else: adjust = convert['millimeters'] / convert[units] self.iWidth.set(mmwidth * adjust) self.iHeight.set(mmheight * adjust) self._computeMaxLineWidth() def _updateUsePrint(self): usePrint = self.usePrint.get() preferences.set(IMAGE_SETUP, USE_PRINT_UNITS, usePrint) if not usePrint: values = ['pixels'] else: values = convert.keys() try: values.remove('pixels') except ValueError: pass values.sort() self.units.values = values self.units.remakeMenu() if usePrint: self.units.set('inches') else: self.units.set('pixels') self.updateImageUnits() if not usePrint: self.fetchWindowSize() def _updatePrint(self, option): res = option.get() preferences.set(IMAGE_SETUP, DPI, res) def _updateAdjustFOV(self, option): adjust = option.get() preferences.set(IMAGE_SETUP, ADJUST_FOV, adjust) def _updateSS(self, option): ss = option.get() preferences.set(IMAGE_SETUP, SUPERSAMPLE, ss) self._computeMaxLineWidth() #def showImageSetupDialog(self, *args): # import dialogs # d = dialogs.display("preferences") # d.setCategoryMenu(IMAGE_SETUP) def showImageCreditsDialog(self, *args): import dialogs d = dialogs.display("preferences") d.setCategoryMenu(IMAGE_CREDITS) def showPOVRayOptions(self, *args): import dialogs d = dialogs.display("preferences") d.setCategoryMenu(POVRAY_SETUP)
def fillInUI(self, master): self._ModelTrigger = None #self._SetupTrigger = None self._SizeTrigger = None self.raytrace = None # Image Size imageSetup = Tix.LabelFrame(master, label="Image Size") imageSetup.pack(fill=Tk.X, ipadx=2, ipady=2) subframe = imageSetup.frame #subframe = Tk.Frame(imageSetup.frame) #subframe.pack(fill=Tk.BOTH, expand=1) # add in conversion factor for pixels and graphics screen from chimera import tkgui win = tkgui.app.graphics res = tkgui.getScreenMMWidth() / win.winfo_screenwidth() convert['pixels'] = mm2pt(res) self.matchAspect = Tk.BooleanVar(master) self.matchAspect.set(1) self.usePrint = Tk.BooleanVar(master) self.usePrint.set(preferences.get(IMAGE_SETUP, USE_PRINT_UNITS)) import itertools row = itertools.count() self.showUsePrint = Tk.Checkbutton(subframe, indicatoron=1, variable=self.usePrint, highlightthickness=0, text=USE_PRINT_UNITS, command=self._updateUsePrint) self.showUsePrint.grid(columnspan=2, row=row.next(), sticky=Tk.W) w, h = chimera.viewer.windowSize self.units = ImageUnitsOption(subframe, row.next(), UNITS, 'pixels', self.updateImageUnits) self.iWidth = FloatOption(subframe, row.next(), 'Image width', w, self.updateImageWidth, min=1e-10) self.iHeight = FloatOption(subframe, row.next(), 'Image height', h, self.updateImageHeight, min=1e-10) matchAspect = Tk.Checkbutton(subframe, indicatoron=1, variable=self.matchAspect, highlightthickness=0, text="Maintain current aspect ratio", command=self.updateMatchAspect) matchAspect.grid(columnspan=2, row=row.next(), sticky=Tk.W) self.grow = Tk.Button(imageSetup.frame, text="Grow to Fit", command=self.Resize, state=Tk.DISABLED) fitrow = row.next() self.grow.grid(row=fitrow, column=0, padx=2, pady=2, sticky=Tk.NSEW) self.shrink = Tk.Button(imageSetup.frame, text="Shrink to Fit", command=lambda f=self.Resize: f(False), state=Tk.DISABLED) self.shrink.grid(row=fitrow, column=1, padx=2, pady=2, sticky=Tk.NSEW) #fetch = Tk.Button(imageSetup.frame, text="Get Pixels", # command=self.fetchWindowSize) #fetch.grid(row=row.next(), column=0, padx=2, pady=2, sticky=Tk.NSEW) #calc = Tk.Button(imageSetup.frame, text="Image Setup", # command=self.showImageSetupDialog) #calc.grid(row=row.next(), column=1, padx=2, pady=2, sticky=Tk.NSEW) self.printRes = FloatOption(subframe, row.next(), DPI, preferences.get(IMAGE_SETUP, DPI), self._updatePrint, min=1) # Image Information info = Tix.LabelFrame(master, label="Image Information") info.pack(fill=Tk.X) d = Tk.Label(info.frame, text="Description:") d.grid(columnspan=2, row=0, column=0, sticky=Tk.W, padx=2, pady=1) self.description = Tk.Entry(info.frame) info.frame.grid_columnconfigure(0, weight=1) info.frame.grid_columnconfigure(1, weight=1) self.description.grid(columnspan=2, row=1, column=0, sticky=Tk.EW, padx=2, pady=2) imageCredits = Tk.Button(info.frame, text="Image Credits", command=self.showImageCreditsDialog) imageCredits.grid(row=2, column=0, padx=2, pady=2) credit = Tk.Button(info.frame, text="Citing Chimera", command=lambda: help.display("credits.html")) credit.grid(row=2, column=1, padx=2, pady=2) # Image camera self.raytrace = BooleanOption(master, -1, 'Raytrace with POV-Ray', False, self._updateRaytrace) self.raytraceOptions = Tk.Button(master, text=POVRAY_SETUP, command=self.showPOVRayOptions) self.raytraceOptions.pack() self.raytraceOptions.pack_forget() self.supersample = SupersampleOption(master, -1, SUPERSAMPLE, preferences.get(IMAGE_SETUP, SUPERSAMPLE), self._updateSS) self.adjustFOV = AdjustFOVOption(master, -1, ADJUST_FOV, preferences.get(IMAGE_SETUP, ADJUST_FOV), self._updateAdjustFOV) self.printMode = _PrintModeOption(master, -1, 'Image camera mode', _PrintModeOption.SAME, self._updatePrintMode) self.lenticular = IntOption(master, -1, 'Number of lenticular images', chimera.Camera.lenticularImageCount(), self._updateLenticular, min=2, width=4) self.lenticular.forget() # switch to user's prefered units self.adjust = convert['pixels'] units = preferences.get(IMAGE_SETUP, UNITS) self._updateUsePrint() self.units.set(units) self.updateImageUnits()
class ClusterStarter(ModelessDialog): title = "Get Clustering Parameters" def __init__(self, movie): self.movie = movie movie.subdialogs.append(self) ModelessDialog.__init__(self) def fillInUI(self, parent): from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption Tkinter.Label(parent, text="Cluster trajectory", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.useSel = BooleanOption( parent, 4, "Cluster based on " "current selection, if any", True, None) self.ignoreBulk = BooleanOption(parent, 5, "Ignore solvent/" "ions", True, None) self.ignoreHyds = BooleanOption(parent, 6, "Ignore hydrogens", True, None) def Apply(self): startFrame = self.startFrame.get() stride = self.stride.get() endFrame = self.endFrame.get() if endFrame <= startFrame: self.enter() raise UserError("Start frame must be less" " than end frame") if startFrame < self.movie.startFrame \ or endFrame > self.movie.endFrame: self.enter() raise UserError("Start or end frame outside" " of trajectory") ClusterDialog(self.movie, startFrame, self.stride.get(), endFrame, self.useSel.get(), self.ignoreBulk.get(), self.ignoreHyds.get())