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): 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): 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): from chimera.tkoptions import IntOption, FloatOption Tkinter.Frame.__init__(self, parent) self.nsteps = IntOption(self, 0, "Steps", 100, None) self.stepsize = FloatOption(self, 1, "Step size (A)", 0.02, None, min=0.0001, max=1.0) self.interval = IntOption(self, 2, "Update interval", 10, None) self.freeze = FreezeOption(self, 3, "Fixed atoms", base.FreezeNone, None)
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): SaveModal.fillInUI(self, parent) parent = self.clientArea parent.columnconfigure(0, weight=1) parent.columnconfigure(1, weight=1) parent = Tk.Frame(parent) parent.grid() self.quality = IntOption(parent, 0, 'JPEG quality', DEFAULT_JPEG_QUALITY, None, min=5, max=95, width=4, sticky=Tk.E) if self.millerBrowser.getFilter() != 'JPEG': self.quality.gridUnmanage()
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())
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)
class RMSD(ModalDialog): buttons = ('Cancel', 'Apply') def __init__(self, movie): self.movie = movie self.ref = None # self.ref2 = None # for an other value ModalDialog.__init__(self) def fillInUI(self, parent): import Tkinter from chimera.tkoptions import IntOption, BooleanOption, FloatOption Tkinter.Label(parent, text="Compute RMSD from a reference frame.\nThis calculation can take SEVERAL MINUTES...", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.ref = IntOption(parent, 1, "Frame of reference", startFrame, None, min=startFrame, max=endFrame, width=6) # self.ref2 = IntOption(parent, 2, "Frame of reference 2", startFrame, None, min=startFrame, max=endFrame, width=6) def Apply(self): ref = self.ref.get() # ref2 = self.ref2.get() ModalDialog.Cancel(self, value=(ref, )) # def Cancel(self): # ModalDialog.Cancel(self, value=None) def destroy(self): self.movie = None ModelessDialog.destroy(self)
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 fillInUI(self, parent): import Tkinter from chimera.tkoptions import IntOption, BooleanOption, FloatOption Tkinter.Label(parent, text="Compute RMSD from a reference frame.\nThis calculation can take SEVERAL MINUTES...", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.ref = IntOption(parent, 1, "Frame of reference", startFrame, None, min=startFrame, max=endFrame, width=6)
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 _ChooseFileDialog(SaveModal): oneshot = True title = "Save Image As" historyID = "SaveImage" def __init__(self, format=None, filterSet='normal'): if filterSet == 'normal': filters = FilenameFilters defaultFilter = DefaultFilter title = self.title historyID = self.historyID elif filterSet == 'stereo': filters = FilenameFilters + StereoFilenameFilters defaultFilter = DefaultStereoFilter title = "Save Stereo Pair As" historyID = 'SaveStereoImage' elif filterSet == 'povray': filters = RaytraceFilenameFilters defaultFilter = DefaultRaytraceFilter title = self.title historyID = self.historyID try: names = [x[0] for x in filters] f = names.index(defaultFilter) except ValueError: f = 0 self.quality = None SaveModal.__init__(self, title=title, initialfile="image", filters=filters, defaultFilter=f, setFilterCommand=self._filterChange, clientPos='s', clientSticky='ew', historyID=historyID) if format: self.millerBrowser.setFilter(format) def fillInUI(self, parent): SaveModal.fillInUI(self, parent) parent = self.clientArea parent.columnconfigure(0, weight=1) parent.columnconfigure(1, weight=1) parent = Tk.Frame(parent) parent.grid() self.quality = IntOption(parent, 0, 'JPEG quality', DEFAULT_JPEG_QUALITY, None, min=5, max=95, width=4, sticky=Tk.E) if self.millerBrowser.getFilter() != 'JPEG': self.quality.gridUnmanage() def _filterChange(self, descript): if self.quality is None: return if descript.endswith("JPEG"): self.quality.gridManage() else: self.quality.gridUnmanage()
def fillInUI(self, parent): from chimera.widgets import MoleculeScrolledListBox self.molListBox = MoleculeScrolledListBox(parent, listbox_selectmode='extended', labelpos='w', label_text="Molecules to combine/copy:") if self.initModels: self.molListBox.setvalue(self.initModels) self.molListBox.grid(row=0, column=0, columnspan=2, sticky="nsew") parent.rowconfigure(0, weight=1) parent.columnconfigure(1, weight=1) from chimera.tkoptions import StringOption, IntOption self.molNameEntry = StringOption(parent, 1, "New model's" " name", "combination", None) curIDs = set([i1 for i1, i2 in openModels.listIds()]) mid = 0 while mid in curIDs: mid += 1 self.modelID = IntOption(parent, 2, "New model's ID", mid, None) from chimera.widgets import MoleculeOptionMenu self.refMolMenu = MoleculeOptionMenu(parent, labelpos='w', label_text="Coordinate system of:", initialitem=self.initModels[0]) self.refMolMenu.grid(row=3, column=0, columnspan=2, sticky='w') import Pmw chb = self.chainHandlingButtons = Pmw.RadioSelect(parent, buttontype="radiobutton", labelpos='w', label_text="If original molecules have duplicate\n" "single-letter chain IDs, then:", orient="vertical") self.buttonTexts = ["rename them uniquely", "retain them (residues may be renumbered)"] for bt in self.buttonTexts: chb.add(bt) chb.setvalue(self.buttonTexts[0]) chb.grid(row=4, column=0, columnspan=2) import Tkinter self.closeModelsVar = Tkinter.IntVar(parent) self.closeModelsVar.set(False) Tkinter.Checkbutton(parent, text="Close source models", variable=self.closeModelsVar).grid( row=5, column=0, columnspan=2)
def fillInUI(self, parent): from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption Tkinter.Label(parent, text="Cluster trajectory", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.useSel = BooleanOption( parent, 4, "Cluster based on " "current selection, if any", True, None) self.ignoreBulk = BooleanOption(parent, 5, "Ignore solvent/" "ions", True, None) self.ignoreHyds = BooleanOption(parent, 6, "Ignore hydrogens", True, None)
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): 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 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 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 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()
def _fillLabelsPage(self, page): page.columnconfigure(0, weight=1) page.columnconfigure(1, weight=1) page.columnconfigure(2, weight=1) row = 0 from CGLtk.Table import SortableTable self.labelTable = SortableTable(page, automultilineHeaders=False) self.labelTable.addColumn("Label [(x, y) text]", self._labelListing, anchor='w') self.labelTable.addColumn("Shown", "shown", format=bool) self.labelTable.setData(self.model.labels) self.labelTable.launch(browseCmd=self._tableCB, selectMode="single") self.labelTable.grid(row=row, column=0, columnspan=3, sticky="nsew") page.rowconfigure(row, weight=1) row += 1 self.labelText = Pmw.ScrolledText(page, labelpos='w', label_text="Text", text_height=3, text_width=20, text_wrap='none', text_state='disabled', text_exportselection=False) text = self.labelText.component('text') text.bind("<<Modified>>", self._textCB) text.bind("<<Selection>>", self._updateTextAttrWidgets) self.labelText.grid(row=row, column=0, sticky='nsew', columnspan=3) page.rowconfigure(row, weight=1) row += 1 self.labelSymbolMenu = Pmw.OptionMenu( page, labelpos='w', label_text="Insert symbol:", command=self._insertSymbol, items=[ u'\N{GREEK SMALL LETTER ALPHA}', u'\N{GREEK SMALL LETTER BETA}', u'\N{GREEK SMALL LETTER GAMMA}', u'\N{GREEK SMALL LETTER DELTA}', u'\N{GREEK SMALL LETTER EPSILON}', u'\N{GREEK SMALL LETTER PI}', u'\N{GREEK SMALL LETTER PHI}', u'\N{GREEK SMALL LETTER CHI}', u'\N{GREEK SMALL LETTER PSI}', u'\N{GREEK SMALL LETTER OMEGA}', u'\N{LEFTWARDS ARROW}', u'\N{RIGHTWARDS ARROW}', u'\N{LEFT RIGHT ARROW}', u'\N{UPWARDS ARROW}', u'\N{DOWNWARDS ARROW}', u'\N{SUPERSCRIPT TWO}', u'\N{SUPERSCRIPT THREE}', u'\N{DEGREE SIGN}', u'\N{LATIN CAPITAL LETTER A WITH RING ABOVE}', "more..." ]) self.labelSymbolMenu.grid(row=row, column=0, columnspan=3) row += 1 colorHouse = Pmw.LabeledWidget(page, labelpos='w', label_text="Color") colorHouse.grid(row=row, column=0, rowspan=3) from CGLtk.color.ColorWell import ColorWell self.colorWell = ColorWell(colorHouse.interior(), color=self._contrastWithBG(), callback=self._colorCB) self.colorWell.grid() from chimera.tkoptions import IntOption self.labelFontSize = IntOption(page, row, "Font size", 24, self._labelChangeCB, startCol=1, min=1, attribute="size", width=3) row += 1 self.labelFontStyle = FontStyle(page, row, "Font style", oglFont.normal, self._labelChangeCB, startCol=1) row += 1 self.labelFontTypeface = FontTypeface(page, row, "Font typeface", FONT_TYPEFACE_VALUES[0], self._labelChangeCB, startCol=1) row += 1 if self.model.curLabel: self.changeToLabel(self.model.curLabel, force=True)
def fillInUI(self, parent): Tkinter.Label(parent, text="Collect positions of selected" " atoms over trajectory", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption, StringOption self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.doCutoff = BooleanOption( parent, 4, 'Limit data collection' ' to within cutoff distance of any "held steady" atoms', True, None) self.cutoff = FloatOption(parent, 5, "Cutoff distance", prefs[VOLUME_CUTOFF], None, width=4) self.resolution = FloatOption(parent, 6, "Volume grid spacing", prefs[VOLUME_RESOLUTION], None, min=0.0001, width=4) self.volumeName = StringOption(parent, 7, "Volume data name", self.movie.ensemble.name, None, width=20) self.byAtomType = BooleanOption( parent, 8, "Collect data" " separately for each atom type in selection", True, None, balloon="Create a volume data set for" " each type of atom type\n(sp2 oxygen, aromatic carbon," " etc.) in current selection")
def fillInUI(self, parent): from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption Tkinter.Label(parent, text="Create RMSD map of trajectory " "against itself", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.minRmsd = FloatOption(parent, 4, "Lower RMSD threshold" " (white)", prefs[RMSD_MIN], None, width=6) self.maxRmsd = FloatOption(parent, 5, "Upper RMSD threshold" " (black)", prefs[RMSD_MAX], None, width=6) self.useSel = BooleanOption( parent, 6, "Restrict map to " "current selection, if any", True, None) self.ignoreBulk = BooleanOption(parent, 7, "Ignore solvent/" "ions", True, None) self.ignoreHyds = BooleanOption(parent, 8, "Ignore hydrogens", True, None) self.recolor = BooleanOption(parent, 9, "Auto-recolor for" " contrast", prefs[RMSD_AUTOCOLOR], None)
def _fillLabelsPage(self, page): page.columnconfigure(0, weight=1) page.columnconfigure(1, weight=1) page.columnconfigure(2, weight=1) row = 0 from CGLtk.Table import SortableTable self.labelTable = SortableTable(page, automultilineHeaders=False) self.labelTable.addColumn("Label [(x, y) text]", self._labelListing, anchor='w') self.labelTable.addColumn("Shown", "shown", format=bool) self.labelTable.setData(self.model.labels) self.labelTable.launch(browseCmd=self._tableCB, selectMode="single") self.labelTable.grid(row=row, column=0, columnspan=3, sticky="nsew") page.rowconfigure(row, weight=1) row += 1 self.labelText = Pmw.ScrolledText(page, labelpos='w', label_text="Text", text_height=3, text_width=20, text_wrap='none', text_state='disabled', text_exportselection=False) text = self.labelText.component('text') text.bind("<<Modified>>", self._textCB) text.bind("<<Selection>>", self._updateTextAttrWidgets) self.labelText.grid(row=row, column=0, sticky='nsew', columnspan=3) page.rowconfigure(row, weight=1) row += 1 self.labelSymbolMenu = Pmw.OptionMenu(page, labelpos='w', label_text="Insert symbol:", command=self._insertSymbol, items=[ u'\N{GREEK SMALL LETTER ALPHA}', u'\N{GREEK SMALL LETTER BETA}', u'\N{GREEK SMALL LETTER GAMMA}', u'\N{GREEK SMALL LETTER DELTA}', u'\N{GREEK SMALL LETTER EPSILON}', u'\N{GREEK SMALL LETTER PI}', u'\N{GREEK SMALL LETTER PHI}', u'\N{GREEK SMALL LETTER CHI}', u'\N{GREEK SMALL LETTER PSI}', u'\N{GREEK SMALL LETTER OMEGA}', u'\N{LEFTWARDS ARROW}', u'\N{RIGHTWARDS ARROW}', u'\N{LEFT RIGHT ARROW}', u'\N{UPWARDS ARROW}', u'\N{DOWNWARDS ARROW}', u'\N{SUPERSCRIPT TWO}', u'\N{SUPERSCRIPT THREE}', u'\N{DEGREE SIGN}', u'\N{LATIN CAPITAL LETTER A WITH RING ABOVE}', "more..." ]) self.labelSymbolMenu.grid(row=row, column=0, columnspan=3) row += 1 colorHouse = Pmw.LabeledWidget(page, labelpos='w', label_text="Color") colorHouse.grid(row=row, column=0, rowspan=3) from CGLtk.color.ColorWell import ColorWell self.colorWell = ColorWell(colorHouse.interior(), color=self._contrastWithBG(), callback=self._colorCB) self.colorWell.grid() from chimera.tkoptions import IntOption self.labelFontSize = IntOption(page, row, "Font size", 24, self._labelChangeCB, startCol=1, min=1, attribute="size", width=3) row += 1 self.labelFontStyle = FontStyle(page, row, "Font style", oglFont.normal, self._labelChangeCB, startCol=1) row += 1 self.labelFontTypeface = FontTypeface(page, row, "Font typeface", FONT_TYPEFACE_VALUES[0], self._labelChangeCB, startCol=1) row += 1 if self.model.curLabel: self.changeToLabel(self.model.curLabel, force=True)
class ClusterStarter(ModelessDialog): title = "Get Clustering Parameters" def __init__(self, movie): self.movie = movie movie.subdialogs.append(self) ModelessDialog.__init__(self) def fillInUI(self, parent): from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption Tkinter.Label(parent, text="Cluster trajectory", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.useSel = BooleanOption( parent, 4, "Cluster based on " "current selection, if any", True, None) self.ignoreBulk = BooleanOption(parent, 5, "Ignore solvent/" "ions", True, None) self.ignoreHyds = BooleanOption(parent, 6, "Ignore hydrogens", True, None) def Apply(self): startFrame = self.startFrame.get() stride = self.stride.get() endFrame = self.endFrame.get() if endFrame <= startFrame: self.enter() raise UserError("Start frame must be less" " than end frame") if startFrame < self.movie.startFrame \ or endFrame > self.movie.endFrame: self.enter() raise UserError("Start or end frame outside" " of trajectory") ClusterDialog(self.movie, startFrame, self.stride.get(), endFrame, self.useSel.get(), self.ignoreBulk.get(), self.ignoreHyds.get())
class RecorderDialog(SaveModeless): title = "Record Animation of Trajectory" help = "ContributedSoftware/movie/movie.html#recording" default = "Record" def __init__(self, movie): self.movie = movie movie.subdialogs.append(self) from MovieRecorder import RecorderGUI formats = [] exts = [] for fmtInfo in RecorderGUI.formats: fmt, ext = fmtInfo[:2] formats.append(fmt) exts.append("." + ext) filters = [] for i, fmt in enumerate(formats): ext = exts[i] filters.append((fmt, '*' + ext, ext)) SaveModeless.__init__(self, clientPos='s', clientSticky='ew', defaultFilter=prefs[RECORDER_FORMAT], filters=filters, historyID="MD recorder") def map(self, e=None): from MovieRecorder import checkLicense if not checkLicense(): self.Close() def fillInUI(self, parent): SaveModeless.fillInUI(self, parent) self.clientArea.columnconfigure(1, weight=1) startFrame = self.movie.startFrame endFrame = self.movie.endFrame from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption, StringOption self.startFrame = IntOption(self.clientArea, 0, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(self.clientArea, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(self.clientArea, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.roundtrip = BooleanOption( self.clientArea, 4, "Encode" ' forward then backward ("roundtrip")', prefs[RECORDER_ROUNDTRIP], None, balloon="Encode the frames in forward and then reverse\n" "order so that if the movie is played as a loop\n" "the motion seems continuous") class FrameQuality(BooleanOption): labels = ["screen", "supersampled"] self.supersample = FrameQuality( self.clientArea, 5, "Frame quality", prefs[RECORDER_SUPERSAMPLE], self.supersampleCB, balloon="Whether each frame should be taken as is from\n" "the screen (fast) or redrawn at higher quality\n" "with several samples per pixel.") from chimera.printer import SupersampleOption self.samples = SupersampleOption(self.clientArea, 6, "Samples", prefs[RECORDER_SAMPLES], None) self.supersampleCB() self.raytrace = BooleanOption(self.clientArea, 7, "Raytrace" " with POV-Ray", prefs[RECORDER_RAYTRACE], None) def povOptCB(): from chimera.dialogs import display d = display("preferences") from chimera.printer import POVRAY_SETUP d.setCategoryMenu(POVRAY_SETUP) Tkinter.Button(self.clientArea, text="POV-Ray Options", pady=0, command=povOptCB).grid(row=8, column=0, columnspan=2) self.recordArgs = StringOption( self.clientArea, 9, "Additional recording options", prefs[RECORDER_RECORD_ARGS], None, balloon="Options (other than 'supersample' and 'raytrace')\n" "for recording frames as per Chimera's 'movie record'" " command") self.encodeArgs = StringOption( self.clientArea, 10, "Additional encoding options", prefs[RECORDER_ENCODE_ARGS], None, balloon="Options (other than 'mformat', 'output', and\n" "'roundtrip') for composing the frames into the\n" "final animation as per Chimera's 'movie encode'\n" "command") Tkinter.Label(self.clientArea, text="On some computers it may be necessary to make sure" " that no\nwindows occlude the main Chimera graphics" " window (even\npartially) during non-raytraced movie" " recording").grid(row=11, column=0, columnspan=2) def Apply(self): from chimera import UserError startFrame = self.startFrame.get() endFrame = self.endFrame.get() if endFrame <= startFrame: self.enter() raise UserError("Start frame must be less" " than end frame") if startFrame < self.movie.startFrame \ or endFrame > self.movie.endFrame: self.enter() raise UserError("Start or end frame outside" " of trajectory") path, format = self.getPathsAndTypes()[0] prefs[RECORDER_FORMAT] = format recordArgs = self.recordArgs.get() prefs[RECORDER_RECORD_ARGS] = recordArgs encodeArgs = self.encodeArgs.get() prefs[RECORDER_ENCODE_ARGS] = encodeArgs roundtrip = self.roundtrip.get() prefs[RECORDER_ROUNDTRIP] = roundtrip supersample = self.supersample.get() prefs[RECORDER_SUPERSAMPLE] = supersample if supersample: samples = self.samples.get() prefs[RECORDER_SAMPLES] = samples recordArgs = " ".join([recordArgs, "supersample", str(samples)]) raytrace = self.raytrace.get() prefs[RECORDER_RAYTRACE] = raytrace from MovieRecorder import RecorderGUI for ext, fmtInfo in RecorderGUI.command_formats.items(): if fmtInfo[0] == format: break recordArgs = " ".join([recordArgs, "raytrace", str(raytrace)]) reprPath = repr(path) if reprPath[0] == 'u': # strip unicode indicator reprPath = reprPath[1:] encodeArgs = " ".join([ encodeArgs, "roundtrip", str(roundtrip), "mformat", ext, "output", reprPath ]) self.movie.recordAnimation(startFrame=startFrame, endFrame=endFrame, step=self.stride.get(), recordArgs=recordArgs, encodeArgs=encodeArgs) Record = SaveModeless.Save def supersampleCB(self, *args): if self.supersample.get(): self.samples.enable() else: self.samples.disable()
class VolumeDialog(ModelessDialog): title = "Calculate Atomic Occupancy" help = "ContributedSoftware/movie/movie.html#occupancy" provideStatus = True statusPosition = "left" buttons = ('OK', 'Close') default = 'OK' def __init__(self, movie): self.movie = movie movie.subdialogs.append(self) ModelessDialog.__init__(self) def map(self, e=None): if not self.movie.holdingSteady: self.status("No atoms being held steady -- see Help", color="red") def fillInUI(self, parent): Tkinter.Label(parent, text="Collect positions of selected" " atoms over trajectory", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption, StringOption self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.doCutoff = BooleanOption( parent, 4, 'Limit data collection' ' to within cutoff distance of any "held steady" atoms', True, None) self.cutoff = FloatOption(parent, 5, "Cutoff distance", prefs[VOLUME_CUTOFF], None, width=4) self.resolution = FloatOption(parent, 6, "Volume grid spacing", prefs[VOLUME_RESOLUTION], None, min=0.0001, width=4) self.volumeName = StringOption(parent, 7, "Volume data name", self.movie.ensemble.name, None, width=20) self.byAtomType = BooleanOption( parent, 8, "Collect data" " separately for each atom type in selection", True, None, balloon="Create a volume data set for" " each type of atom type\n(sp2 oxygen, aromatic carbon," " etc.) in current selection") def Apply(self): from chimera import UserError atoms = chimera.selection.currentAtoms() if not atoms: self.enter() raise UserError("No atoms selected") startFrame = self.startFrame.get() endFrame = self.endFrame.get() if endFrame <= startFrame: self.enter() raise UserError("Start frame must be less" " than end frame") if startFrame < self.movie.startFrame \ or endFrame > self.movie.endFrame: self.enter() raise UserError("Start or end frame outside" " of trajectory") if self.doCutoff.get(): bound = prefs[VOLUME_CUTOFF] = self.cutoff.get() else: bound = None prefs[VOLUME_RESOLUTION] = self.resolution.get() step = self.stride.get() spacing = self.resolution.get() name = self.volumeName.get() atomTypes = {} if self.byAtomType.get(): for a in atoms: atomTypes.setdefault(a.idatmType, []).append(a) if len(atomTypes) > 1: for atomType, atAtoms in atomTypes.items(): self.movie.computeVolume(atAtoms, startFrame=startFrame, endFrame=endFrame, step=step, bound=bound, spacing=spacing, volumeName=name + " [" + atomType + "]") else: self.movie.computeVolume(atoms, startFrame=startFrame, endFrame=endFrame, step=step, bound=bound, spacing=spacing, volumeName=name)
class ImageSaveDialog(ModelessDialog): name = "Save Image" buttons = ['Tips', 'Save As', Cancel] default = 'Save As' help = 'UsersGuide/print.html' provideStatus = True def fillInUI(self, master): self._ModelTrigger = None #self._SetupTrigger = None self._SizeTrigger = None self.raytrace = None # Image Size imageSetup = Tix.LabelFrame(master, label="Image Size") imageSetup.pack(fill=Tk.X, ipadx=2, ipady=2) subframe = imageSetup.frame #subframe = Tk.Frame(imageSetup.frame) #subframe.pack(fill=Tk.BOTH, expand=1) # add in conversion factor for pixels and graphics screen from chimera import tkgui win = tkgui.app.graphics res = tkgui.getScreenMMWidth() / win.winfo_screenwidth() convert['pixels'] = mm2pt(res) self.matchAspect = Tk.BooleanVar(master) self.matchAspect.set(1) self.usePrint = Tk.BooleanVar(master) self.usePrint.set(preferences.get(IMAGE_SETUP, USE_PRINT_UNITS)) import itertools row = itertools.count() self.showUsePrint = Tk.Checkbutton(subframe, indicatoron=1, variable=self.usePrint, highlightthickness=0, text=USE_PRINT_UNITS, command=self._updateUsePrint) self.showUsePrint.grid(columnspan=2, row=row.next(), sticky=Tk.W) w, h = chimera.viewer.windowSize self.units = ImageUnitsOption(subframe, row.next(), UNITS, 'pixels', self.updateImageUnits) self.iWidth = FloatOption(subframe, row.next(), 'Image width', w, self.updateImageWidth, min=1e-10) self.iHeight = FloatOption(subframe, row.next(), 'Image height', h, self.updateImageHeight, min=1e-10) matchAspect = Tk.Checkbutton(subframe, indicatoron=1, variable=self.matchAspect, highlightthickness=0, text="Maintain current aspect ratio", command=self.updateMatchAspect) matchAspect.grid(columnspan=2, row=row.next(), sticky=Tk.W) self.grow = Tk.Button(imageSetup.frame, text="Grow to Fit", command=self.Resize, state=Tk.DISABLED) fitrow = row.next() self.grow.grid(row=fitrow, column=0, padx=2, pady=2, sticky=Tk.NSEW) self.shrink = Tk.Button(imageSetup.frame, text="Shrink to Fit", command=lambda f=self.Resize: f(False), state=Tk.DISABLED) self.shrink.grid(row=fitrow, column=1, padx=2, pady=2, sticky=Tk.NSEW) #fetch = Tk.Button(imageSetup.frame, text="Get Pixels", # command=self.fetchWindowSize) #fetch.grid(row=row.next(), column=0, padx=2, pady=2, sticky=Tk.NSEW) #calc = Tk.Button(imageSetup.frame, text="Image Setup", # command=self.showImageSetupDialog) #calc.grid(row=row.next(), column=1, padx=2, pady=2, sticky=Tk.NSEW) self.printRes = FloatOption(subframe, row.next(), DPI, preferences.get(IMAGE_SETUP, DPI), self._updatePrint, min=1) # Image Information info = Tix.LabelFrame(master, label="Image Information") info.pack(fill=Tk.X) d = Tk.Label(info.frame, text="Description:") d.grid(columnspan=2, row=0, column=0, sticky=Tk.W, padx=2, pady=1) self.description = Tk.Entry(info.frame) info.frame.grid_columnconfigure(0, weight=1) info.frame.grid_columnconfigure(1, weight=1) self.description.grid(columnspan=2, row=1, column=0, sticky=Tk.EW, padx=2, pady=2) imageCredits = Tk.Button(info.frame, text="Image Credits", command=self.showImageCreditsDialog) imageCredits.grid(row=2, column=0, padx=2, pady=2) credit = Tk.Button(info.frame, text="Citing Chimera", command=lambda: help.display("credits.html")) credit.grid(row=2, column=1, padx=2, pady=2) # Image camera self.raytrace = BooleanOption(master, -1, 'Raytrace with POV-Ray', False, self._updateRaytrace) self.raytraceOptions = Tk.Button(master, text=POVRAY_SETUP, command=self.showPOVRayOptions) self.raytraceOptions.pack() self.raytraceOptions.pack_forget() self.supersample = SupersampleOption(master, -1, SUPERSAMPLE, preferences.get(IMAGE_SETUP, SUPERSAMPLE), self._updateSS) self.adjustFOV = AdjustFOVOption(master, -1, ADJUST_FOV, preferences.get(IMAGE_SETUP, ADJUST_FOV), self._updateAdjustFOV) self.printMode = _PrintModeOption(master, -1, 'Image camera mode', _PrintModeOption.SAME, self._updatePrintMode) self.lenticular = IntOption(master, -1, 'Number of lenticular images', chimera.Camera.lenticularImageCount(), self._updateLenticular, min=2, width=4) self.lenticular.forget() # switch to user's prefered units self.adjust = convert['pixels'] units = preferences.get(IMAGE_SETUP, UNITS) self._updateUsePrint() self.units.set(units) self.updateImageUnits() def map(self, event=None): self._ModelTrigger = chimera.triggers.addHandler('Model', self._computeMaxLineWidth, None) #self._SetupTrigger = chimera.triggers.addHandler(IMAGE_SETUP, # self._computeMaxLineWidth, None) self._SizeTrigger = chimera.triggers.addHandler( 'graphics window size', self._resetSize, None) self._computeMaxLineWidth() def unmap(self, event=None): if self._ModelTrigger: chimera.triggers.deleteHandler('Model', self._ModelTrigger) self._ModelTrigger = None #if self._SetupTrigger: # chimera.triggers.deleteHandler(IMAGE_SETUP, # self._SetupTrigger) # self._SetupTrigger = None def _computeMaxLineWidth(self, *args): if self.raytrace and self.raytrace.get(): # not relevant if raytracing self.status('', blankAfter=0) return # this should be called models are modified, when the # image size changes and when image setup parameters # change (DPI, supersampling) opengl_max = min( chimera.opengl_getFloat("max point size"), chimera.opengl_getFloat("max line width")) max_lw = max([m.lineWidth for m in chimera.openModels.list(all=True) if hasattr(m, 'lineWidth')]) # compute tile scaling factor like C++ code does width = self.iWidth.get() height = self.iHeight.get() horizPixels, vertPixels, supersample = \ imageArgs(self.units.get(), width, height) width, height = chimera.viewer.windowSize tileScale = float(horizPixels) / float(width) tmp = float(vertPixels) / float(height) if tmp > tileScale: tileScale = tmp tileScale *= supersample opengl_max /= tileScale if max_lw > opengl_max: color = 'red' else: color = 'black' self.status('effective maximum line width is %g' % opengl_max, color=color, blankAfter=0) #def Print(self): # self.Cancel() # image, options = self.getImage() # filename = tempfile.mktemp() # image.save(filename, **options) # cmd = preferences.get(PAGE_SETUP, PRINTER_CMD) # cmd = re.sub('%s', "'" + filename + "'", cmd) # os.system(cmd) # os.unlink(filename) def SaveAs(self): # now save the image self.Cancel() printMode = self.printMode.get() raytrace = self.raytrace.get() if printMode == _PrintModeOption.SAME: printMode = None if not chimera.nogui and raytrace and chimera.viewer.clipping: dialog = ClipWarning() if not dialog.run(chimera.tkgui.app): return saveImage(None, self.iWidth.get(), self.iHeight.get(), units=self.units.get(), master=self.uiMaster(), description=self.description.get().strip(), printMode=printMode, raytrace=raytrace) def Tips(self): import help help.display(self.help + "#tips") def Resize(self, larger=True): vw, vh = chimera.viewer.windowSize iw = self.iWidth.get() ih = self.iHeight.get() vaspect = vw / float(vh) iaspect = iw / float(ih) from chimera import tkgui top = tkgui.app.winfo_toplevel() if larger: if vaspect < iaspect: w = int(vw * iaspect / vaspect + 0.5) if w != vw: top.wm_geometry('') tkgui.app.graphics.config(width=w) elif vaspect > iaspect: h = int(vh * vaspect / iaspect + 0.5) if h != vh: top.wm_geometry('') tkgui.app.graphics.config(height=h) else: if vaspect < iaspect: h = int(vh * vaspect / iaspect + 0.5) if h != vh: top.wm_geometry('') tkgui.app.graphics.config(height=h) elif vaspect > iaspect: w = int(vw * iaspect / vaspect + 0.5) if w != vw: top.wm_geometry('') tkgui.app.graphics.config(width=w) def fetchWindowSize(self): w, h = chimera.viewer.windowSize self.units.set('pixels') self.updateImageUnits() self.iWidth.set(w) self.iHeight.set(h) def _updateRaytrace(self, option): raytrace = option.get() if raytrace: self.printMode.forget() self.lenticular.forget() self.supersample.forget() self.raytraceOptions.pack() else: self.raytraceOptions.pack_forget() self.printMode.manage() self.supersample.manage() self._updatePrintMode(self.printMode) self._computeMaxLineWidth() def _updatePrintMode(self, option): printMode = option.get() if printMode == 'lenticular': self.lenticular.manage() else: self.lenticular.forget() def _updateLenticular(self, option): count = option.get() chimera.Camera.setLenticularImageCount(count) def updateMatchAspect(self, *args): if self.matchAspect.get(): self.grow.config(state=Tk.DISABLED) self.shrink.config(state=Tk.DISABLED) self.Resize() else: self.grow.config(state=Tk.NORMAL) self.shrink.config(state=Tk.NORMAL) def updateImageUnits(self, *args): units = self.units.get() if units == 'pixels': self.printRes.disable() self.adjustFOV.disable() else: self.printRes.enable() self.adjustFOV.enable() if units != preferences.get(IMAGE_SETUP, UNITS): preferences.set(IMAGE_SETUP, UNITS, units) try: adjust = convert[units] except KeyError: adjust = -1 if adjust == self.adjust: return if self.adjust != -1 and adjust != -1: factor = self.adjust / adjust w = self.iWidth.get() * factor self.iWidth.set(w) h = self.iHeight.get() * factor self.iHeight.set(h) if adjust == -1: # entering pixel mode w, h = chimera.viewer.windowSize self.iWidth.set(w) self.iHeight.set(h) elif self.adjust == -1: pass # leaving pixel mode, sanity check #w, h = paper_types[preferences.get(PAGE_SETUP, PAPER_TYPE)] #if self.iWidth.get() > w: # self.iWidth.set(w) #if self.iHeight.get() > h: # self.iHeight.set(h) self.adjust = adjust self._computeMaxLineWidth() def updateImageWidth(self, option): # adjust height to compensate for new width if self.matchAspect.get(): iWidth = option.get() w, h = chimera.viewer.windowSize self.iHeight.set(iWidth * h / w) self._computeMaxLineWidth() def updateImageHeight(self, option): # adjust width to compensate for new height if self.matchAspect.get(): iHeight = option.get() w, h = chimera.viewer.windowSize self.iWidth.set(iHeight * w / h) self._computeMaxLineWidth() def _resetSize(self, triggerName, myData, sizes): width, height, mmwidth, mmheight = sizes units = self.units.get() if units == 'pixels': self.iWidth.set(width) self.iHeight.set(height) else: adjust = convert['millimeters'] / convert[units] self.iWidth.set(mmwidth * adjust) self.iHeight.set(mmheight * adjust) self._computeMaxLineWidth() def _updateUsePrint(self): usePrint = self.usePrint.get() preferences.set(IMAGE_SETUP, USE_PRINT_UNITS, usePrint) if not usePrint: values = ['pixels'] else: values = convert.keys() try: values.remove('pixels') except ValueError: pass values.sort() self.units.values = values self.units.remakeMenu() if usePrint: self.units.set('inches') else: self.units.set('pixels') self.updateImageUnits() if not usePrint: self.fetchWindowSize() def _updatePrint(self, option): res = option.get() preferences.set(IMAGE_SETUP, DPI, res) def _updateAdjustFOV(self, option): adjust = option.get() preferences.set(IMAGE_SETUP, ADJUST_FOV, adjust) def _updateSS(self, option): ss = option.get() preferences.set(IMAGE_SETUP, SUPERSAMPLE, ss) self._computeMaxLineWidth() #def showImageSetupDialog(self, *args): # import dialogs # d = dialogs.display("preferences") # d.setCategoryMenu(IMAGE_SETUP) def showImageCreditsDialog(self, *args): import dialogs d = dialogs.display("preferences") d.setCategoryMenu(IMAGE_CREDITS) def showPOVRayOptions(self, *args): import dialogs d = dialogs.display("preferences") d.setCategoryMenu(POVRAY_SETUP)
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 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)
def _fillColorKeyPage(self, page): from chimera.tkoptions import IntOption, EnumOption, \ BooleanOption, RGBAOption f = Tkinter.Frame(page) f.grid(row=0, columnspan=2) self.numComponents = IntOption(f, 0, "Number of colors/labels", 3, self._componentsCB, min=2, width=2) self.componentsFrame = Tkinter.Frame(page) self.componentsFrame.grid(row=1, column=0, sticky="nsew", columnspan=2) page.columnconfigure(0, weight=1) self.componentsFrame.columnconfigure(1, weight=1) class ColorTreatment(EnumOption): values = ("distinct", "blended") self.colorTreatment = ColorTreatment( page, 2, "Color range depiction", "blended", self._keyChangeCB, balloon="Should colors be shown as distinct rectangles" " or as a continuous range") class LabelPosition(EnumOption): values = ("left/top", "right/bottom") self.labelPos = LabelPosition( page, 3, "Label positions", "right/bottom", self._keyChangeCB, balloon="Position of" " labels relative to color key.\nLabels always" " positioned adjacent to long side.") self.labelColor = RGBAOption( page, 4, "Label color", self._contrastWithBG(), self._keyChangeCB, balloob="Label color. If set to 'No color', use corresponding" " key color", noneOkay=True) class LabelJustification(EnumOption): values = ("left", "decimal point", "right") self.justification = LabelJustification( page, 5, "Label justification", "decimal point", self._keyChangeCB, balloon="Justification of label text" " in a vertical key layout.\nHorizontal key labels will" " always be center justified.") self.labelOffset = IntOption(page, 6, "Label offset", 0, self._keyChangeCB, width=3, balloon="Additional offset" " of labels from color bar, in pixels") self.keyFontSize = IntOption(page, 7, "Font size", 24, self._keyChangeCB, width=3) self.keyFontStyle = FontStyle(page, 8, "Font style", oglFont.normal, self._keyChangeCB) self.keyFontTypeface = FontTypeface(page, 9, "Font typeface", FONT_TYPEFACE_VALUES[0], self._keyChangeCB) self.borderColor = RGBAOption( page, 10, "Border color", None, self._keyChangeCB, balloon="Color of border" " around color key (not each individual color).\n" "If 'no color', then no border is drawn.") self.borderWidth = IntOption(page, 11, "Border width", 3, self._keyChangeCB, balloon="in pixels") self.tickMarks = BooleanOption(page, 12, "Show tick marks", False, self._keyChangeCB, balloon="Show tick marks" " pointing from key to labels") self._componentsCB(self.numComponents)
def fillInUI(self, master): self._ModelTrigger = None #self._SetupTrigger = None self._SizeTrigger = None self.raytrace = None # Image Size imageSetup = Tix.LabelFrame(master, label="Image Size") imageSetup.pack(fill=Tk.X, ipadx=2, ipady=2) subframe = imageSetup.frame #subframe = Tk.Frame(imageSetup.frame) #subframe.pack(fill=Tk.BOTH, expand=1) # add in conversion factor for pixels and graphics screen from chimera import tkgui win = tkgui.app.graphics res = tkgui.getScreenMMWidth() / win.winfo_screenwidth() convert['pixels'] = mm2pt(res) self.matchAspect = Tk.BooleanVar(master) self.matchAspect.set(1) self.usePrint = Tk.BooleanVar(master) self.usePrint.set(preferences.get(IMAGE_SETUP, USE_PRINT_UNITS)) import itertools row = itertools.count() self.showUsePrint = Tk.Checkbutton(subframe, indicatoron=1, variable=self.usePrint, highlightthickness=0, text=USE_PRINT_UNITS, command=self._updateUsePrint) self.showUsePrint.grid(columnspan=2, row=row.next(), sticky=Tk.W) w, h = chimera.viewer.windowSize self.units = ImageUnitsOption(subframe, row.next(), UNITS, 'pixels', self.updateImageUnits) self.iWidth = FloatOption(subframe, row.next(), 'Image width', w, self.updateImageWidth, min=1e-10) self.iHeight = FloatOption(subframe, row.next(), 'Image height', h, self.updateImageHeight, min=1e-10) matchAspect = Tk.Checkbutton(subframe, indicatoron=1, variable=self.matchAspect, highlightthickness=0, text="Maintain current aspect ratio", command=self.updateMatchAspect) matchAspect.grid(columnspan=2, row=row.next(), sticky=Tk.W) self.grow = Tk.Button(imageSetup.frame, text="Grow to Fit", command=self.Resize, state=Tk.DISABLED) fitrow = row.next() self.grow.grid(row=fitrow, column=0, padx=2, pady=2, sticky=Tk.NSEW) self.shrink = Tk.Button(imageSetup.frame, text="Shrink to Fit", command=lambda f=self.Resize: f(False), state=Tk.DISABLED) self.shrink.grid(row=fitrow, column=1, padx=2, pady=2, sticky=Tk.NSEW) #fetch = Tk.Button(imageSetup.frame, text="Get Pixels", # command=self.fetchWindowSize) #fetch.grid(row=row.next(), column=0, padx=2, pady=2, sticky=Tk.NSEW) #calc = Tk.Button(imageSetup.frame, text="Image Setup", # command=self.showImageSetupDialog) #calc.grid(row=row.next(), column=1, padx=2, pady=2, sticky=Tk.NSEW) self.printRes = FloatOption(subframe, row.next(), DPI, preferences.get(IMAGE_SETUP, DPI), self._updatePrint, min=1) # Image Information info = Tix.LabelFrame(master, label="Image Information") info.pack(fill=Tk.X) d = Tk.Label(info.frame, text="Description:") d.grid(columnspan=2, row=0, column=0, sticky=Tk.W, padx=2, pady=1) self.description = Tk.Entry(info.frame) info.frame.grid_columnconfigure(0, weight=1) info.frame.grid_columnconfigure(1, weight=1) self.description.grid(columnspan=2, row=1, column=0, sticky=Tk.EW, padx=2, pady=2) imageCredits = Tk.Button(info.frame, text="Image Credits", command=self.showImageCreditsDialog) imageCredits.grid(row=2, column=0, padx=2, pady=2) credit = Tk.Button(info.frame, text="Citing Chimera", command=lambda: help.display("credits.html")) credit.grid(row=2, column=1, padx=2, pady=2) # Image camera self.raytrace = BooleanOption(master, -1, 'Raytrace with POV-Ray', False, self._updateRaytrace) self.raytraceOptions = Tk.Button(master, text=POVRAY_SETUP, command=self.showPOVRayOptions) self.raytraceOptions.pack() self.raytraceOptions.pack_forget() self.supersample = SupersampleOption(master, -1, SUPERSAMPLE, preferences.get(IMAGE_SETUP, SUPERSAMPLE), self._updateSS) self.adjustFOV = AdjustFOVOption(master, -1, ADJUST_FOV, preferences.get(IMAGE_SETUP, ADJUST_FOV), self._updateAdjustFOV) self.printMode = _PrintModeOption(master, -1, 'Image camera mode', _PrintModeOption.SAME, self._updatePrintMode) self.lenticular = IntOption(master, -1, 'Number of lenticular images', chimera.Camera.lenticularImageCount(), self._updateLenticular, min=2, width=4) self.lenticular.forget() # switch to user's prefered units self.adjust = convert['pixels'] units = preferences.get(IMAGE_SETUP, UNITS) self._updateUsePrint() self.units.set(units) self.updateImageUnits()
class RmsdStarter(ModelessDialog): title = "Get RMSD Map Parameters" help = "ContributedSoftware/movie/movie.html#rmsd" def __init__(self, movie): self.movie = movie movie.subdialogs.append(self) ModelessDialog.__init__(self) def fillInUI(self, parent): from chimera.tkoptions import IntOption, BooleanOption, \ FloatOption Tkinter.Label(parent, text="Create RMSD map of trajectory " "against itself", relief="ridge", bd=4).grid(row=0, column=0, columnspan=2, sticky="ew") startFrame = self.movie.startFrame endFrame = self.movie.endFrame self.startFrame = IntOption(parent, 1, "Starting frame", startFrame, None, min=startFrame, max=endFrame, width=6) numFrames = endFrame - startFrame + 1 defStride = 1 + int(numFrames / 300) self.stride = IntOption(parent, 2, "Step size", defStride, None, min=1, max=numFrames, width=3) self.endFrame = IntOption(parent, 3, "Ending frame", endFrame, None, min=startFrame, max=endFrame, width=6) self.minRmsd = FloatOption(parent, 4, "Lower RMSD threshold" " (white)", prefs[RMSD_MIN], None, width=6) self.maxRmsd = FloatOption(parent, 5, "Upper RMSD threshold" " (black)", prefs[RMSD_MAX], None, width=6) self.useSel = BooleanOption( parent, 6, "Restrict map to " "current selection, if any", True, None) self.ignoreBulk = BooleanOption(parent, 7, "Ignore solvent/" "ions", True, None) self.ignoreHyds = BooleanOption(parent, 8, "Ignore hydrogens", True, None) self.recolor = BooleanOption(parent, 9, "Auto-recolor for" " contrast", prefs[RMSD_AUTOCOLOR], None) def Apply(self): startFrame = self.startFrame.get() stride = self.stride.get() if (len(self.movie.ensemble) - (startFrame - 1)) / stride > 1000: dlg = AskYesNoDialog("RMSD map will be %d pixels wide" " and tall. Okay?") if dlg.run(self.uiMaster()) == "no": self.enter() return endFrame = self.endFrame.get() if endFrame <= startFrame: self.enter() raise UserError("Start frame must be less" " than end frame") if startFrame < self.movie.startFrame \ or endFrame > self.movie.endFrame: self.enter() raise UserError("Start or end frame outside" " of trajectory") prefs[RMSD_MIN] = self.minRmsd.get() prefs[RMSD_MAX] = self.maxRmsd.get() prefs[RMSD_AUTOCOLOR] = self.recolor.get() RmsdMapDialog(self.movie, startFrame, self.stride.get(), endFrame, self.useSel.get(), prefs[RMSD_MIN], prefs[RMSD_MAX], self.ignoreBulk.get(), self.ignoreHyds.get(), prefs[RMSD_AUTOCOLOR])