Esempio n. 1
0
class SeqPickerDialog(ModelessDialog):
    title = 'Show Model Sequence'
    buttons = ('Show', 'Close')
    default = 'Show'
    keepShown = 'Show'
    name = "model sequence chooser"
    help = "ContributedSoftware/multalignviewer/multalignviewer.html#individual"

    def fillInUI(self, parent):
        from chimera.widgets import MoleculeChainScrolledListBox
        self.molListBox = MoleculeChainScrolledListBox(
            parent,
            listbox_selectmode="extended",
            labelpos="w",
            # some fancy footwork so that double click honors
            # the "keep shown" dialog setting
            dblclickcommand=lambda *args: getattr(self, 'Show')(),
            label_text="Show sequence for:")
        self.molListBox.grid(row=0, column=0, sticky="news")
        parent.rowconfigure(0, weight=1)
        parent.columnconfigure(0, weight=1)

    def Apply(self):
        from base import seqCmd
        seqCmd(self.molListBox.getvalue())
Esempio n. 2
0
 def fillInUI(self, parent):
     from chimera.widgets import MoleculeChainScrolledListBox
     self.molListBox = MoleculeChainScrolledListBox(
         parent,
         listbox_selectmode="extended",
         labelpos="w",
         # some fancy footwork so that double click honors
         # the "keep shown" dialog setting
         dblclickcommand=lambda *args: getattr(self, 'Show')(),
         label_text="Show sequence for:")
     self.molListBox.grid(row=0, column=0, sticky="news")
     parent.rowconfigure(0, weight=1)
     parent.columnconfigure(0, weight=1)
	def fillInUI(self, parent):
		self.notebook = Pmw.NoteBook(parent)
		self.notebook.pack(fill="both", expand=True)
		page = self.notebook.add("Molecules")
		self.molChooser = MoleculeScrolledListBox(page,
					listbox_selectmode="extended",
					autoselect="single")
		self.molChooser.pack(fill="both", expand=True)
		page = self.notebook.add("Chains")
		self.chainChooser = MoleculeChainScrolledListBox(page,
					listbox_selectmode="extended",
					autoselect="single")
		self.chainChooser.pack(fill="both", expand=True)
		titles = self.Servers.keys()
		titles.sort()
		self.serverChooser = Pmw.OptionMenu(parent,
					labelpos="w",
					label_text="Compute:",
					items=titles,
					command=self._changeServer)
		self.serverChooser.pack(fill="x", expand=False)
		self.paramHolder = Tkinter.Frame(parent, padx=10, pady=2)
		self.paramHolder.pack(fill="x", expand=False)
		self.paramFrames = {}
		for name, val in self.Servers.iteritems():
			self.paramFrames[name] = val[2](self, self.paramHolder)
		self.propertyName = Pmw.EntryField(parent,
					labelpos="w",
					label_text="As attribute:",
					value=self.Servers[titles[0]][0],
					validate=self._validatePropName)
		self.propertyName.pack(fill="x", expand=False)
		self.outputOptions = Pmw.RadioSelect(parent,
					pady=0,
					buttontype="checkbutton",
					orient="vertical")
		self.outputOptions.pack(fill="x", expand=False)
		self.outputOptions.add("rba",
					text="Open Render/Select by Attribute")
		self.outputOptions.add("save",
					text="Save server output to file")
		self.outputOptions.add("show",
					text="Show server output in browser")
		self.outputOptions.setvalue(["rba"])
		self._changeServer(titles[0])
Esempio n. 4
0
	def fillInUI(self, parent):
		from chimera.widgets import MoleculeChainScrolledListBox
		self.molListBox = MoleculeChainScrolledListBox(parent,
			listbox_selectmode="extended", labelpos="w",
			# some fancy footwork so that double click honors
			# the "keep shown" dialog setting
			dblclickcommand=lambda *args: getattr(self, 'Show')(),
			label_text="Show sequence for:")
		self.molListBox.grid(row=0, column=0, sticky="news")
		parent.rowconfigure(0, weight=1)
		parent.columnconfigure(0, weight=1)
Esempio n. 5
0
class SeqPickerDialog(ModelessDialog):
	title = 'Show Model Sequence'
	buttons = ('Show', 'Close')
	default = 'Show'
	keepShown = 'Show'
	name = "model sequence chooser"
	help = "ContributedSoftware/multalignviewer/multalignviewer.html#individual"

	def fillInUI(self, parent):
		from chimera.widgets import MoleculeChainScrolledListBox
		self.molListBox = MoleculeChainScrolledListBox(parent,
			listbox_selectmode="extended", labelpos="w",
			# some fancy footwork so that double click honors
			# the "keep shown" dialog setting
			dblclickcommand=lambda *args: getattr(self, 'Show')(),
			label_text="Show sequence for:")
		self.molListBox.grid(row=0, column=0, sticky="news")
		parent.rowconfigure(0, weight=1)
		parent.columnconfigure(0, weight=1)

	def Apply(self):
		from base import seqCmd
		seqCmd(self.molListBox.getvalue())
Esempio n. 6
0
class MatchMaker(ModelessDialog):
    name = "match structures"
    buttons = ('OK', 'Apply', 'Cancel')
    title = "MatchMaker"
    help = 'ContributedSoftware/matchmaker/matchmaker.html'

    def __init__(self, **kw):
        ModelessDialog.__init__(self, **kw)

    def Apply(self):
        cp = self.chainMatchVar.get()
        alg = self.seqAlgorithmMenu.getvalue()
        showSeq = self.showSeqVar.get()
        iterate = self.iterVar.get()
        computeSS = self.computeSSVar.get()
        for entry in self._entries:
            entry.invoke()
        if iterate:
            iterArg = float(self.iterEntry.getvalue())
        else:
            iterArg = None
        helixOpen, strandOpen, otherOpen = self.ssParams.getGaps()
        matrix = self.matrixMenu.getvalue()
        gapOpen = float(self.gapOpenEntry.getvalue())
        gapExtend = float(self.gapExtendEntry.getvalue())

        pairings = {}
        if cp == CP_SPECIFIC_SPECIFIC:
            matchItems = []
            for ref, menu in self.matchChainList.menus.items():
                matchItems.append((ref, menu.getvalue()))
        elif cp == CP_SPECIFIC_BEST:
            # specific chain in reference;
            # best seq-aligning chain in match model(s)
            ref = self.refChainList.getvalue()
            if not ref:
                raise UserError("Must choose a reference chain")
            matches = [
                x for x in self.matchMolList.getvalue() if x != ref.molecule
            ]
            matchItems = [ref, matches]
        elif cp == CP_BEST:
            # best seq-aligning pair of chains between
            # reference and match structure(s)
            ref = self.refMolList.getvalue()
            matches = [x for x in self.matchMolList.getvalue() if x != ref]
            matchItems = [ref, matches]

        if self.ssParams.useSSVar.get():
            ssFraction = self.ssParams.ssMixture.get()
            ssMatrix = self.ssParams.getMatrix()
        else:
            ssMatrix = ssFraction = None
        alignKw = {
            'ssFraction': ssFraction,
            'ssMatrix': ssMatrix,
            'computeSS': computeSS
        }
        try:
            matchInfo = match(cp,
                              matchItems,
                              matrix,
                              alg,
                              gapOpen,
                              gapExtend,
                              align=self._align,
                              iterate=iterArg,
                              gapOpenHelix=helixOpen,
                              gapOpenStrand=strandOpen,
                              gapOpenOther=otherOpen,
                              showAlignment=showSeq,
                              **alignKw)
        except UserError:
            self.enter()
            raise

        if not self.structSeqVar.get():
            return
        chains = set()
        for matchAtoms, refAtoms, rmsd in matchInfo:
            for r in (matchAtoms[0].residue, refAtoms[0].residue):
                for mchain in r.molecule.sequences():
                    if r in mchain.resMap:
                        chains.add(mchain)
                        break
        from StructSeqAlign import Match2Align
        m2a = Match2Align()
        m2a.chainList.setvalue(chains)

    def fillInUI(self, parent):
        self.refMolList = MoleculeScrolledListBox(
            parent,
            autoselect="single",
            labelpos="nw",
            label_text="Reference structure:")
        self.refChainList = MoleculeChainScrolledListBox(
            parent,
            labelpos="nw",
            label_text="Reference chain:",
            listbox_selectmode='extended')

        self.matchMolList = MoleculeScrolledListBox(
            parent,
            labelpos="nw",
            label_text="Structure(s) to match:",
            listbox_selectmode='extended')
        self.matchChainList = ChainMenus(parent)

        def doSync():
            if self.chainMatchVar.get() != CP_SPECIFIC_SPECIFIC:
                return
            self.matchChainList.syncUp(self.refChainList)

        self.refChainList.configure(selectioncommand=doSync)
        parent.rowconfigure(0, weight=1)
        parent.columnconfigure(0, weight=1)
        parent.columnconfigure(1, weight=1)

        seqFrame = Tkinter.Frame(parent)
        seqFrame.grid(row=1, column=0, columnspan=2, sticky="nsew")
        seqFrame.columnconfigure(0, weight=1)
        seqFrame.columnconfigure(1, weight=1)

        pairingGroup = Pmw.Group(seqFrame, tag_text="Chain pairing")
        pairingGroup.grid(row=0, column=0, columnspan=2, sticky="w", padx=2)
        pairingGroup.interior().columnconfigure(0, weight=1)

        self.chainMatchVar = Tkinter.StringVar(parent)
        self.chainMatchVar.set(prefs[CHAIN_PAIRING])

        radiobuttonInfo = [
            (CP_BEST,
             "Best-aligning pair of chains\n\tbetween reference and match structure"
             ),
            (CP_SPECIFIC_BEST,
             "Specific chain in reference structure\n\twith best-aligning chain in match structure"
             ),
            (CP_SPECIFIC_SPECIFIC,
             "Specific chain(s) in reference structure\n\twith specific chain(s) in match structure"
             ),
        ]
        for i in range(len(radiobuttonInfo)):
            val, text = radiobuttonInfo[i]
            radio = Tkinter.Radiobutton(pairingGroup.interior(),
                                        command=self._chainMatchCB,
                                        text=text,
                                        justify='left',
                                        value=val,
                                        variable=self.chainMatchVar)
            radio.grid(row=i, column=0, sticky='w')
        self._chainMatchCB()

        self.seqAlgorithmMenu = Pmw.OptionMenu(
            seqFrame,
            initialitem=prefs[SEQUENCE_ALGORITHM],
            labelpos='w',
            label_text="Alignment algorithm:",
            items=[SA_NEEDLEMAN_WUNSCH, SA_SMITH_WATERMAN])
        self.seqAlgorithmMenu.grid(row=1, column=0, sticky='w')

        matrixNames = SmithWaterman.matrices.keys()
        matrixNames.sort()
        if prefs[MATRIX] in SmithWaterman.matrices:
            initialMatrix = prefs[MATRIX]
        else:
            if defaults[MATRIX] in SmithWaterman.matrices:
                initialMatrix = defaults[MATRIX]
            else:
                initialMatrix = matrixNames[0]
            prefs[MATRIX] = initialMatrix
        self.matrixMenu = Pmw.OptionMenu(seqFrame,
                                         initialitem=initialMatrix,
                                         labelpos='w',
                                         label_text="Matrix:",
                                         items=matrixNames)
        self.matrixMenu.grid(row=1, column=1, sticky='w')

        gapFrame = Tkinter.Frame(seqFrame)
        gapFrame.grid(row=2, column=0, columnspan=2, sticky='ew')
        gapFrame.columnconfigure(0, weight=1)
        gapFrame.columnconfigure(1, weight=1)
        self.gapOpenEntry = Pmw.EntryField(gapFrame,
                                           labelpos='w',
                                           label_text="Gap opening penalty",
                                           validate='real',
                                           entry_width=2,
                                           entry_justify='right',
                                           value="%g" % (prefs[GAP_OPEN]))
        self.gapOpenEntry.grid(row=0, column=0)
        self.gapExtendEntry = Pmw.EntryField(
            gapFrame,
            labelpos='w',
            label_text="Gap extension penalty",
            validate='real',
            entry_width=2,
            entry_justify='right',
            value="%g" % (prefs[GAP_EXTEND]))
        self.gapExtendEntry.grid(row=0, column=1)
        self._entries = [self.gapOpenEntry, self.gapExtendEntry]

        self.ssParams = SSParams(seqFrame, prefs, useSSCB=self._useSSCB)
        self.ssParams.grid(row=3, column=0, columnspan=2, sticky='ew')
        self.computeSSVar = Tkinter.IntVar(parent)
        self.computeSSVar.set(prefs[COMPUTE_SS])
        self._computeSSButton = Tkinter.Checkbutton(
            seqFrame,
            text="Compute secondary structure assignments",
            variable=self.computeSSVar)
        self._computeSSGridArgs = {'row': 4, 'sticky': 'w', 'columnspan': 2}
        if self.ssParams.useSSVar.get():
            self._computeSSButton.grid(**self._computeSSGridArgs)

        self.showSeqVar = Tkinter.IntVar(parent)
        self.showSeqVar.set(prefs[SHOW_SEQUENCE])
        Tkinter.Checkbutton(seqFrame,
                            text="Show pairwise alignment(s)",
                            variable=self.showSeqVar).grid(row=5,
                                                           column=0,
                                                           sticky='w',
                                                           columnspan=2)

        matchGroup = Pmw.Group(parent, tag_text="Matching")
        matchGroup.grid(row=2, column=0, columnspan=2, sticky="nsew", padx=2)
        matchGroup.interior().columnconfigure(0, weight=1)
        self.iterVar = Tkinter.IntVar(parent)
        self.iterVar.set(prefs[ITERATE])
        Tkinter.Checkbutton(matchGroup.interior(),
                            justify="left",
                            text="Iterate by pruning long atom pairs"
                            " until no pair exceeds:",
                            variable=self.iterVar).grid(row=0,
                                                        column=0,
                                                        sticky='w')
        self.iterEntry = Pmw.EntryField(matchGroup.interior(),
                                        validate='real',
                                        entry_width=3,
                                        entry_justify="right",
                                        value="%.1f" % prefs[ITER_CUTOFF],
                                        labelpos='e',
                                        label_text="angstroms")
        self.iterEntry.grid(row=1, column=0)
        self._entries.append(self.iterEntry)

        self.structSeqVar = Tkinter.IntVar(parent)
        self.structSeqVar.set(False)
        Tkinter.Checkbutton(parent,
                            text="After superposition, compute"
                            " structure-based multiple sequence alignment",
                            variable=self.structSeqVar).grid(row=3,
                                                             sticky='w',
                                                             columnspan=2)

        f = Tkinter.Frame(parent)
        f.grid(row=4, column=0, columnspan=2, sticky='ew')
        from chimera import help
        b = Tkinter.Button(f,
                           text="Save settings",
                           pady=0,
                           command=self._saveSettings)
        b.grid(row=0, column=0)
        help.register(b, balloon="Save current settings")
        b = Tkinter.Button(f,
                           text="Reset to defaults",
                           pady=0,
                           command=self._restoreSettings)
        b.grid(row=0, column=1)
        help.register(b, balloon="Reset dialog to factory defaults")
        f.columnconfigure(0, weight=1)
        f.columnconfigure(1, weight=1)

        # set up state of gap-open entry
        self._useSSCB()

    def _align(self, ref, match, matrix, alg, gapOpen, gapExtend, ksdsspCache,
               **alignKw):
        replyobj.status(
            "test match %s %s to %s %s" %
            (ref.molecule.name, ref.name, match.molecule.name, match.name))
        return align(ref, match, matrix, alg, gapOpen, gapExtend, ksdsspCache,
                     **alignKw)

    def _chainMatchCB(self):
        matching = self.chainMatchVar.get()
        if matching == CP_SPECIFIC_SPECIFIC:
            ref = self.refChainList
            match = self.matchChainList
            ref.component("listbox").config(selectmode="extended")
            self.matchChainList.syncUp(self.refChainList)
        elif matching == CP_SPECIFIC_BEST:
            ref = self.refChainList
            match = self.matchMolList
            ref.component("listbox").config(selectmode="browse")
        else:
            ref = self.refMolList
            match = self.matchMolList
        for slave in self.uiMaster().grid_slaves(row=0):
            slave.grid_forget()
        ref.grid(row=0, column=0, sticky="nsew")
        match.grid(row=0, column=1, sticky="nsew")

    def _restoreSettings(self):
        self.ssParams.resetParams()
        self.chainMatchVar.set(defaults[CHAIN_PAIRING])
        self._chainMatchCB()
        self.seqAlgorithmMenu.setvalue(defaults[SEQUENCE_ALGORITHM])
        self.showSeqVar.set(defaults[SHOW_SEQUENCE])
        self.iterVar.set(defaults[ITERATE])
        self.computeSSVar.set(defaults[COMPUTE_SS])
        for entry in self._entries:
            entry.invoke()
        self.iterEntry.setvalue(str(defaults[ITER_CUTOFF]))
        self.ssParams.useSSVar.set(defaults[USE_SS])
        self.matrixMenu.setvalue(defaults[MATRIX])
        self.gapOpenEntry.setvalue(str(defaults[GAP_OPEN]))
        self.gapExtendEntry.setvalue(str(defaults[GAP_EXTEND]))
        self.structSeqVar.set(False)

    def _saveSettings(self):
        prefs[CHAIN_PAIRING] = self.chainMatchVar.get()
        prefs[SEQUENCE_ALGORITHM] = self.seqAlgorithmMenu.getvalue()
        prefs[SHOW_SEQUENCE] = self.showSeqVar.get()
        prefs[ITERATE] = self.iterVar.get()
        prefs[COMPUTE_SS] = self.computeSSVar.get()
        for entry in self._entries:
            entry.invoke()
        prefs[ITER_CUTOFF] = float(self.iterEntry.getvalue())
        prefs[HELIX_OPEN], prefs[STRAND_OPEN], prefs[OTHER_OPEN] = \
            self.ssParams.getGaps()
        prefs[USE_SS] = self.ssParams.useSSVar.get()
        prefs[SS_MIXTURE] = self.ssParams.ssMixture.get()
        ssMatrix = self.ssParams.getMatrix()
        if ssMatrix != prefs[SS_SCORES]:
            prefs[SS_SCORES] = ssMatrix
        prefs[MATRIX] = self.matrixMenu.getvalue()
        prefs[GAP_OPEN] = float(self.gapOpenEntry.getvalue())
        prefs[GAP_EXTEND] = float(self.gapExtendEntry.getvalue())

    def _useSSCB(self):
        if self.ssParams.useSSVar.get():
            state = 'disabled'
            self._computeSSButton.grid(**self._computeSSGridArgs)
        else:
            state = 'normal'
            self._computeSSButton.grid_forget()
        self.gapOpenEntry.configure(label_state=state, entry_state=state)
Esempio n. 7
0
    def fillInUI(self, parent):
        self.refMolList = MoleculeScrolledListBox(
            parent,
            autoselect="single",
            labelpos="nw",
            label_text="Reference structure:")
        self.refChainList = MoleculeChainScrolledListBox(
            parent,
            labelpos="nw",
            label_text="Reference chain:",
            listbox_selectmode='extended')

        self.matchMolList = MoleculeScrolledListBox(
            parent,
            labelpos="nw",
            label_text="Structure(s) to match:",
            listbox_selectmode='extended')
        self.matchChainList = ChainMenus(parent)

        def doSync():
            if self.chainMatchVar.get() != CP_SPECIFIC_SPECIFIC:
                return
            self.matchChainList.syncUp(self.refChainList)

        self.refChainList.configure(selectioncommand=doSync)
        parent.rowconfigure(0, weight=1)
        parent.columnconfigure(0, weight=1)
        parent.columnconfigure(1, weight=1)

        seqFrame = Tkinter.Frame(parent)
        seqFrame.grid(row=1, column=0, columnspan=2, sticky="nsew")
        seqFrame.columnconfigure(0, weight=1)
        seqFrame.columnconfigure(1, weight=1)

        pairingGroup = Pmw.Group(seqFrame, tag_text="Chain pairing")
        pairingGroup.grid(row=0, column=0, columnspan=2, sticky="w", padx=2)
        pairingGroup.interior().columnconfigure(0, weight=1)

        self.chainMatchVar = Tkinter.StringVar(parent)
        self.chainMatchVar.set(prefs[CHAIN_PAIRING])

        radiobuttonInfo = [
            (CP_BEST,
             "Best-aligning pair of chains\n\tbetween reference and match structure"
             ),
            (CP_SPECIFIC_BEST,
             "Specific chain in reference structure\n\twith best-aligning chain in match structure"
             ),
            (CP_SPECIFIC_SPECIFIC,
             "Specific chain(s) in reference structure\n\twith specific chain(s) in match structure"
             ),
        ]
        for i in range(len(radiobuttonInfo)):
            val, text = radiobuttonInfo[i]
            radio = Tkinter.Radiobutton(pairingGroup.interior(),
                                        command=self._chainMatchCB,
                                        text=text,
                                        justify='left',
                                        value=val,
                                        variable=self.chainMatchVar)
            radio.grid(row=i, column=0, sticky='w')
        self._chainMatchCB()

        self.seqAlgorithmMenu = Pmw.OptionMenu(
            seqFrame,
            initialitem=prefs[SEQUENCE_ALGORITHM],
            labelpos='w',
            label_text="Alignment algorithm:",
            items=[SA_NEEDLEMAN_WUNSCH, SA_SMITH_WATERMAN])
        self.seqAlgorithmMenu.grid(row=1, column=0, sticky='w')

        matrixNames = SmithWaterman.matrices.keys()
        matrixNames.sort()
        if prefs[MATRIX] in SmithWaterman.matrices:
            initialMatrix = prefs[MATRIX]
        else:
            if defaults[MATRIX] in SmithWaterman.matrices:
                initialMatrix = defaults[MATRIX]
            else:
                initialMatrix = matrixNames[0]
            prefs[MATRIX] = initialMatrix
        self.matrixMenu = Pmw.OptionMenu(seqFrame,
                                         initialitem=initialMatrix,
                                         labelpos='w',
                                         label_text="Matrix:",
                                         items=matrixNames)
        self.matrixMenu.grid(row=1, column=1, sticky='w')

        gapFrame = Tkinter.Frame(seqFrame)
        gapFrame.grid(row=2, column=0, columnspan=2, sticky='ew')
        gapFrame.columnconfigure(0, weight=1)
        gapFrame.columnconfigure(1, weight=1)
        self.gapOpenEntry = Pmw.EntryField(gapFrame,
                                           labelpos='w',
                                           label_text="Gap opening penalty",
                                           validate='real',
                                           entry_width=2,
                                           entry_justify='right',
                                           value="%g" % (prefs[GAP_OPEN]))
        self.gapOpenEntry.grid(row=0, column=0)
        self.gapExtendEntry = Pmw.EntryField(
            gapFrame,
            labelpos='w',
            label_text="Gap extension penalty",
            validate='real',
            entry_width=2,
            entry_justify='right',
            value="%g" % (prefs[GAP_EXTEND]))
        self.gapExtendEntry.grid(row=0, column=1)
        self._entries = [self.gapOpenEntry, self.gapExtendEntry]

        self.ssParams = SSParams(seqFrame, prefs, useSSCB=self._useSSCB)
        self.ssParams.grid(row=3, column=0, columnspan=2, sticky='ew')
        self.computeSSVar = Tkinter.IntVar(parent)
        self.computeSSVar.set(prefs[COMPUTE_SS])
        self._computeSSButton = Tkinter.Checkbutton(
            seqFrame,
            text="Compute secondary structure assignments",
            variable=self.computeSSVar)
        self._computeSSGridArgs = {'row': 4, 'sticky': 'w', 'columnspan': 2}
        if self.ssParams.useSSVar.get():
            self._computeSSButton.grid(**self._computeSSGridArgs)

        self.showSeqVar = Tkinter.IntVar(parent)
        self.showSeqVar.set(prefs[SHOW_SEQUENCE])
        Tkinter.Checkbutton(seqFrame,
                            text="Show pairwise alignment(s)",
                            variable=self.showSeqVar).grid(row=5,
                                                           column=0,
                                                           sticky='w',
                                                           columnspan=2)

        matchGroup = Pmw.Group(parent, tag_text="Matching")
        matchGroup.grid(row=2, column=0, columnspan=2, sticky="nsew", padx=2)
        matchGroup.interior().columnconfigure(0, weight=1)
        self.iterVar = Tkinter.IntVar(parent)
        self.iterVar.set(prefs[ITERATE])
        Tkinter.Checkbutton(matchGroup.interior(),
                            justify="left",
                            text="Iterate by pruning long atom pairs"
                            " until no pair exceeds:",
                            variable=self.iterVar).grid(row=0,
                                                        column=0,
                                                        sticky='w')
        self.iterEntry = Pmw.EntryField(matchGroup.interior(),
                                        validate='real',
                                        entry_width=3,
                                        entry_justify="right",
                                        value="%.1f" % prefs[ITER_CUTOFF],
                                        labelpos='e',
                                        label_text="angstroms")
        self.iterEntry.grid(row=1, column=0)
        self._entries.append(self.iterEntry)

        self.structSeqVar = Tkinter.IntVar(parent)
        self.structSeqVar.set(False)
        Tkinter.Checkbutton(parent,
                            text="After superposition, compute"
                            " structure-based multiple sequence alignment",
                            variable=self.structSeqVar).grid(row=3,
                                                             sticky='w',
                                                             columnspan=2)

        f = Tkinter.Frame(parent)
        f.grid(row=4, column=0, columnspan=2, sticky='ew')
        from chimera import help
        b = Tkinter.Button(f,
                           text="Save settings",
                           pady=0,
                           command=self._saveSettings)
        b.grid(row=0, column=0)
        help.register(b, balloon="Save current settings")
        b = Tkinter.Button(f,
                           text="Reset to defaults",
                           pady=0,
                           command=self._restoreSettings)
        b.grid(row=0, column=1)
        help.register(b, balloon="Reset dialog to factory defaults")
        f.columnconfigure(0, weight=1)
        f.columnconfigure(1, weight=1)

        # set up state of gap-open entry
        self._useSSCB()
	def fillInUI(self, parent):
		row = 0
		parent.columnconfigure(0, weight=1)
		parent.rowconfigure(row, weight=1)
		self.chainList = MoleculeChainScrolledListBox(parent,
					selectioncommand=self._updateIterRef,
					listbox_selectmode='multiple')
		self.chainList.grid(row=row, column=0, sticky='nsew')
		row += 1
		mols = {}
		for chain in self.chainList.get():
			mol = chain.molecule
			if mol in mols:
				continue
			mols[mol] = chain
		self.chainList.setvalue(mols.values())
	
		f = Tkinter.Frame(parent)
		f.grid(row=row, column=0, sticky='w')
		row += 1
		self.distCutoff = FloatOption(f, 0,
			"Residue-residue distance cutoff (angstroms)",
			prefs[DIST_CUTOFF], None, balloon="""\
residues whose principal atoms are further apart
than this distance will not be aligned in the
generated sequence alignment""")
		self.distCutoff.min = 0.0

		class MatchTypeOption(SymbolicEnumOption):
			values = ["any", "all"]
			labels = ["at least one other", "all others"]
		f = Tkinter.Frame(parent)
		f.grid(row=row, column=0, sticky='w')
		row += 1
		self.matchType = MatchTypeOption(f, 0,
			"Residue aligned in column if within cutoff of",
			prefs[ANYALL], None, balloon="""\
whether a residue needs to match the distance cutoff to all other
residues in its column, or just to one residue in the column""")

		class GapCharOption(SymbolicEnumOption):
			values = [".", "-", "~"]
			labels = [". (period)", "- (dash)", "~ (tilde)"]
		f = Tkinter.Frame(parent)
		f.grid(row=row, column=0, sticky='w')
		row += 1
		self.gapChar = GapCharOption(f, 0, "Gap character",
			prefs[GAPCHAR], None, balloon="""\
character used to depict gaps in alignment""")

		self.circularVar = Tkinter.IntVar(parent)
		self.circularVar.set(prefs[CIRCULAR])
		Tkinter.Checkbutton(parent, variable=self.circularVar, text=
				"Allow for circular permutation").grid(row=row,
				column=0, sticky='w')
		row += 1

		self.iterateVar = Tkinter.IntVar(parent)
		self.iterateVar.set(prefs[ITERATE])
		Tkinter.Checkbutton(parent, command=self._iterParamsDisplay,
				text="Iterate superposition/alignment...",
				variable=self.iterateVar).grid(
				row=row, column=0, columnspan=2, sticky='w')
		row += 1
		self.iterParams = Pmw.Group(parent, hull_padx=2,
					tag_text="Iteration Parameters")
		self.iterParams.grid(row=row, column=0, columnspan=2)
		row += 1
		inside = self.iterParams.interior()
		Tkinter.Label(inside, text="Iterate alignment:").grid(
					row=0, column=0, rowspan=2, sticky='e')
		self.iterConvergeVar = Tkinter.IntVar(parent)
		self.iterConvergeVar.set(prefs[ITER_CONVERGE])
		f = Tkinter.Frame(inside)
		f.grid(row=0, column=1, sticky='w')
		Tkinter.Radiobutton(f, value=False, text="at most",
			variable=self.iterConvergeVar).grid(row=0, column=0)
		self.iterLimit = Pmw.EntryField(f, labelpos='e',
			label_text="times", validate={'min': 1,
			'validator': 'numeric'}, value=str(prefs[ITER_AMOUNT]),
			entry_width=2, entry_justify="center")
		self.iterLimit.grid(row=0, column=1)
		Tkinter.Radiobutton(inside, text="until convergence",
			value=True, variable=self.iterConvergeVar).grid(
			row=1, column=1, sticky='w')
		inside.rowconfigure(2, minsize="0.1i")
		Tkinter.Label(inside, text="Superimpose full columns:"
			).grid(row=3, rowspan=2, column=0, sticky='e')
		self.iterAllColsVar = Tkinter.IntVar(parent)
		self.iterAllColsVar.set(prefs[ITER_ALL_COLS])
		Tkinter.Radiobutton(inside, text="across entire alignment",
			value=True, variable=self.iterAllColsVar).grid(
			row=3, column=1, sticky='w')
		f = Tkinter.Frame(inside)
		f.grid(row=4, column=1, sticky='w')
		Tkinter.Radiobutton(f, text="in stretches of at least",
					variable=self.iterAllColsVar,
					value=False).grid(row=0, column=0)
		self.stretchLen = Pmw.EntryField(f, labelpos='e',
				label_text="consecutive columns",
				validate={'min': 2, 'validator': 'numeric'},
				value=str(prefs[ITER_CONSECUTIVE_COLS]),
				entry_width=1, entry_justify="center")
		self.stretchLen.grid(row=0, column=1)
		self.referenceMenu = Pmw.OptionMenu(inside, labelpos='w',
			items=Pmw.ScrolledListBox.get(self.chainList),
			label_text="Reference chain for matching:")
		self.referenceMenu.grid(row=5, column=0, columnspan=2)

		self._iterParamsDisplay()

		f = Tkinter.Frame(parent)
		f.grid(row=row, column=0, columnspan=2, sticky='ew')
		row += 1
		from chimera import help
		b = Tkinter.Button(f, text="Save settings", pady=0,
					command=self._saveSettings)
		b.grid(row=0, column=0)
		help.register(b, balloon="Save current settings")
		b = Tkinter.Button(f, text="Reset to defaults", pady=0,
					command=self._restoreSettings)
		b.grid(row=0, column=1)
		help.register(b, balloon="Reset dialog to factory defaults")
		f.columnconfigure(0, weight=1)
		f.columnconfigure(1, weight=1)
class Match2Align(ModelessDialog):
	title = "Create Alignment from Superposition"
	oneshot = True
	help = "ContributedSoftware/matchalign/matchalign.html"

	def fillInUI(self, parent):
		row = 0
		parent.columnconfigure(0, weight=1)
		parent.rowconfigure(row, weight=1)
		self.chainList = MoleculeChainScrolledListBox(parent,
					selectioncommand=self._updateIterRef,
					listbox_selectmode='multiple')
		self.chainList.grid(row=row, column=0, sticky='nsew')
		row += 1
		mols = {}
		for chain in self.chainList.get():
			mol = chain.molecule
			if mol in mols:
				continue
			mols[mol] = chain
		self.chainList.setvalue(mols.values())
	
		f = Tkinter.Frame(parent)
		f.grid(row=row, column=0, sticky='w')
		row += 1
		self.distCutoff = FloatOption(f, 0,
			"Residue-residue distance cutoff (angstroms)",
			prefs[DIST_CUTOFF], None, balloon="""\
residues whose principal atoms are further apart
than this distance will not be aligned in the
generated sequence alignment""")
		self.distCutoff.min = 0.0

		class MatchTypeOption(SymbolicEnumOption):
			values = ["any", "all"]
			labels = ["at least one other", "all others"]
		f = Tkinter.Frame(parent)
		f.grid(row=row, column=0, sticky='w')
		row += 1
		self.matchType = MatchTypeOption(f, 0,
			"Residue aligned in column if within cutoff of",
			prefs[ANYALL], None, balloon="""\
whether a residue needs to match the distance cutoff to all other
residues in its column, or just to one residue in the column""")

		class GapCharOption(SymbolicEnumOption):
			values = [".", "-", "~"]
			labels = [". (period)", "- (dash)", "~ (tilde)"]
		f = Tkinter.Frame(parent)
		f.grid(row=row, column=0, sticky='w')
		row += 1
		self.gapChar = GapCharOption(f, 0, "Gap character",
			prefs[GAPCHAR], None, balloon="""\
character used to depict gaps in alignment""")

		self.circularVar = Tkinter.IntVar(parent)
		self.circularVar.set(prefs[CIRCULAR])
		Tkinter.Checkbutton(parent, variable=self.circularVar, text=
				"Allow for circular permutation").grid(row=row,
				column=0, sticky='w')
		row += 1

		self.iterateVar = Tkinter.IntVar(parent)
		self.iterateVar.set(prefs[ITERATE])
		Tkinter.Checkbutton(parent, command=self._iterParamsDisplay,
				text="Iterate superposition/alignment...",
				variable=self.iterateVar).grid(
				row=row, column=0, columnspan=2, sticky='w')
		row += 1
		self.iterParams = Pmw.Group(parent, hull_padx=2,
					tag_text="Iteration Parameters")
		self.iterParams.grid(row=row, column=0, columnspan=2)
		row += 1
		inside = self.iterParams.interior()
		Tkinter.Label(inside, text="Iterate alignment:").grid(
					row=0, column=0, rowspan=2, sticky='e')
		self.iterConvergeVar = Tkinter.IntVar(parent)
		self.iterConvergeVar.set(prefs[ITER_CONVERGE])
		f = Tkinter.Frame(inside)
		f.grid(row=0, column=1, sticky='w')
		Tkinter.Radiobutton(f, value=False, text="at most",
			variable=self.iterConvergeVar).grid(row=0, column=0)
		self.iterLimit = Pmw.EntryField(f, labelpos='e',
			label_text="times", validate={'min': 1,
			'validator': 'numeric'}, value=str(prefs[ITER_AMOUNT]),
			entry_width=2, entry_justify="center")
		self.iterLimit.grid(row=0, column=1)
		Tkinter.Radiobutton(inside, text="until convergence",
			value=True, variable=self.iterConvergeVar).grid(
			row=1, column=1, sticky='w')
		inside.rowconfigure(2, minsize="0.1i")
		Tkinter.Label(inside, text="Superimpose full columns:"
			).grid(row=3, rowspan=2, column=0, sticky='e')
		self.iterAllColsVar = Tkinter.IntVar(parent)
		self.iterAllColsVar.set(prefs[ITER_ALL_COLS])
		Tkinter.Radiobutton(inside, text="across entire alignment",
			value=True, variable=self.iterAllColsVar).grid(
			row=3, column=1, sticky='w')
		f = Tkinter.Frame(inside)
		f.grid(row=4, column=1, sticky='w')
		Tkinter.Radiobutton(f, text="in stretches of at least",
					variable=self.iterAllColsVar,
					value=False).grid(row=0, column=0)
		self.stretchLen = Pmw.EntryField(f, labelpos='e',
				label_text="consecutive columns",
				validate={'min': 2, 'validator': 'numeric'},
				value=str(prefs[ITER_CONSECUTIVE_COLS]),
				entry_width=1, entry_justify="center")
		self.stretchLen.grid(row=0, column=1)
		self.referenceMenu = Pmw.OptionMenu(inside, labelpos='w',
			items=Pmw.ScrolledListBox.get(self.chainList),
			label_text="Reference chain for matching:")
		self.referenceMenu.grid(row=5, column=0, columnspan=2)

		self._iterParamsDisplay()

		f = Tkinter.Frame(parent)
		f.grid(row=row, column=0, columnspan=2, sticky='ew')
		row += 1
		from chimera import help
		b = Tkinter.Button(f, text="Save settings", pady=0,
					command=self._saveSettings)
		b.grid(row=0, column=0)
		help.register(b, balloon="Save current settings")
		b = Tkinter.Button(f, text="Reset to defaults", pady=0,
					command=self._restoreSettings)
		b.grid(row=0, column=1)
		help.register(b, balloon="Reset dialog to factory defaults")
		f.columnconfigure(0, weight=1)
		f.columnconfigure(1, weight=1)

	def Apply(self):
		chains = self.chainList.getvalue()
		if len(chains) < 2:
			replyobj.error("Must choose at least two chains\n")
			self.enter()
			return

		mols = {}
		for chain in chains:
			if chain.molecule in mols:
				replyobj.error(
				  "Please choose only one chain per model\n")
				self.enter()
				return
			mols[chain.molecule] = 1

		cutoff = float(self.distCutoff.get())
		matchType = self.matchType.get()
		gapChar = self.gapChar.get()
		circular = self.circularVar.get()

		from align import match2align
		from Midas import match, rmsd
		seqs = match2align(chains, cutoff, matchType, gapChar, circular)
		cols = alignedCols(seqs)
		replyobj.info("%d fully populated columns\n" % (len(cols)))
		if self.iterateVar.get():
			best = None
			iteration = 1
			refChain = self.chainList.itemMap[
					self.referenceMenu.getvalue()]
			if self.iterConvergeVar.get():
				iterLimit = None
			else:
				self.iterLimit.invoke()
				iterLimit = int(self.iterLimit.getvalue())
			if self.iterAllColsVar.get():
				stretchLen = 1
			else:
				self.stretchLen.invoke()
				stretchLen = int(self.stretchLen.getvalue())
			while True:
				refSeq = [s for s in seqs
					if s.molecule == refChain.molecule][0]
				# cull columns based on stretch len criteria
				stretch = []
				culled = []
				for col in cols:
					if not stretch or stretch[-1]+1 == col:
						stretch.append(col)
						continue
					if len(stretch) >= stretchLen:
						culled.extend(stretch)
					stretch = [col]
				if len(stretch) >= stretchLen:
					culled.extend(stretch)
				if stretchLen > 1:
					replyobj.info("%d fully populated"
						" columns in at least %d"
						" column stretches\n" % (
						len(culled), stretchLen))
				if not culled:
					break
					
				# match
				refAtoms = columnAtoms(refSeq, culled)
				for seq in seqs:
					if seq.molecule == refSeq.molecule:
						continue
					seqAtoms = columnAtoms(seq, culled)
					replyobj.info("Matching %s onto %s\n"
						% (seq.name, refSeq.name))
					match(seqAtoms, refAtoms)
				seqs = match2align(chains, cutoff, matchType,
					gapChar, circular, statusPrefix=
					"Iteration %d: " % iteration)
				cols = alignedCols(seqs)
				replyobj.info("Iteration %d: %d fully populated"
					" columns\n" % (iteration, len(cols)))
				if best == None or len(cols) > len(best):
					best = cols
				else:
					break
				if iterLimit and iteration >= iterLimit:
					break
				iteration += 1
		if len(seqs) == 2:
			mav = showAlignment(seqs, "Match of %s and %s" %
						(seqs[0].name, seqs[1].name))
		else:
			mav = showAlignment(seqs, "Match -> Align (%d models)"
								% len(seqs))
		from MultAlignViewer.MAViewer import MATCHED_REGION_INFO
		name, fill, outline = MATCHED_REGION_INFO
		mav.newRegion(name="Fully populated columns", columns=cols,
						fill=fill, outline=outline)

		if cols:
			# show pairwise RMSD matrix in fully populated columns
			matchAtoms = {}
			for seq in seqs:
				matchAtoms[seq] = columnAtoms(seq, cols)
			replyobj.info("\nEvaluating superpositions across all %d fully"
				" populated columns in the final alignment:\n"
				% len(cols))
			dsqSum = 0
			for i, s1 in enumerate(seqs):
				for s2 in seqs[i+1:]:
					v = rmsd(matchAtoms[s1], matchAtoms[s2],
									log=False)
					dsqSum += v * v
					replyobj.info("RMSD of %s with %s: %.3f\n" %
							(s1.name, s2.name, v))
			from math import sqrt
			replyobj.info("Overall RMSD: %.3f\n\n" % sqrt(2 * dsqSum /
							(len(seqs) * (len(seqs)-1))))
			mav.status("RMSDs reported in Reply Log", color="purple")
			replyobj.status("RMSDs reported in Reply Log", color="purple")
		else:
			mav.status("No fully populated columns in alignment", color="blue")

	def _iterParamsDisplay(self):
		if self.iterateVar.get():
			self.iterParams.grid()
		else:
			self.iterParams.grid_remove()

	def _restoreSettings(self):
		from prefs import defaults
		self.distCutoff.set(defaults[DIST_CUTOFF])
		self.matchType.set(defaults[ANYALL])
		self.gapChar.set(defaults[GAPCHAR])
		self.circularVar.set(defaults[CIRCULAR])
		self.iterateVar.set(defaults[ITERATE])
		self._iterParamsDisplay()
		self.iterConvergeVar.set(defaults[ITER_CONVERGE])
		self.iterLimit.setvalue(str(defaults[ITER_AMOUNT]))
		self.iterAllColsVar.set(defaults[ITER_ALL_COLS])
		self.stretchLen.setvalue(str(defaults[ITER_CONSECUTIVE_COLS]))

	def _saveSettings(self):
		prefs[DIST_CUTOFF] = float(self.distCutoff.get())
		prefs[ANYALL] = self.matchType.get()
		prefs[GAPCHAR] = self.gapChar.get()
		prefs[CIRCULAR] = self.circularVar.get()
		prefs[ITERATE] = self.iterateVar.get()
		prefs[ITER_CONVERGE] = self.iterConvergeVar.get()
		self.iterLimit.invoke()
		prefs[ITER_AMOUNT] = int(self.iterLimit.getvalue())
		prefs[ITER_ALL_COLS] = self.iterAllColsVar.get()
		self.stretchLen.invoke()
		prefs[ITER_CONSECUTIVE_COLS] = int(self.stretchLen.getvalue())

	def _updateIterRef(self, *args):
		self.referenceMenu.setitems([self.chainList.valueMap[chain]
				for chain in self.chainList.getvalue()])
class Interface(ModelessDialog):

	title = "Compute Surface Area and Volume"
	help = "ContributedSoftware/surfvol/surfvol.html"

	def fillInUI(self, parent):
		self.notebook = Pmw.NoteBook(parent)
		self.notebook.pack(fill="both", expand=True)
		page = self.notebook.add("Molecules")
		self.molChooser = MoleculeScrolledListBox(page,
					listbox_selectmode="extended",
					autoselect="single")
		self.molChooser.pack(fill="both", expand=True)
		page = self.notebook.add("Chains")
		self.chainChooser = MoleculeChainScrolledListBox(page,
					listbox_selectmode="extended",
					autoselect="single")
		self.chainChooser.pack(fill="both", expand=True)
		titles = self.Servers.keys()
		titles.sort()
		self.serverChooser = Pmw.OptionMenu(parent,
					labelpos="w",
					label_text="Compute:",
					items=titles,
					command=self._changeServer)
		self.serverChooser.pack(fill="x", expand=False)
		self.paramHolder = Tkinter.Frame(parent, padx=10, pady=2)
		self.paramHolder.pack(fill="x", expand=False)
		self.paramFrames = {}
		for name, val in self.Servers.iteritems():
			self.paramFrames[name] = val[2](self, self.paramHolder)
		self.propertyName = Pmw.EntryField(parent,
					labelpos="w",
					label_text="As attribute:",
					value=self.Servers[titles[0]][0],
					validate=self._validatePropName)
		self.propertyName.pack(fill="x", expand=False)
		self.outputOptions = Pmw.RadioSelect(parent,
					pady=0,
					buttontype="checkbutton",
					orient="vertical")
		self.outputOptions.pack(fill="x", expand=False)
		self.outputOptions.add("rba",
					text="Open Render/Select by Attribute")
		self.outputOptions.add("save",
					text="Save server output to file")
		self.outputOptions.add("show",
					text="Show server output in browser")
		self.outputOptions.setvalue(["rba"])
		self._changeServer(titles[0])

	def _changeServer(self, name):
		self.propertyName.setvalue(self.Servers[name][0])
		for n, (frame, parts) in self.paramFrames.iteritems():
			if n == name:
				frame.pack(fill="x", expand=True)
			else:
				frame.forget()

	def _validatePropName(self, text):
		if len(text) == 0:
			return Pmw.PARTIAL
		if text[0] not in NameFirstChar:
			return Pmw.ERROR
		for c in text[1:]:
			if c not in NameChar:
				return Pmw.ERROR
		return Pmw.OK

	def Apply(self):
		if not self.propertyName.valid():
			raise chimera.UserError(
					"Please enter valid attribute name")
		propName = self.propertyName.getvalue()
		pageName = self.notebook.getcurselection()
		if pageName == "Molecules":
			target = self.molChooser.getvalue()
		elif pageName == "Chains":
			target = self.chainChooser.getvalue()
		if not target:
			raise chimera.UserError(
					"Please select molecule or chain")
		opts = self.outputOptions.getvalue()
		rba = "rba" in opts
		save = "save" in opts
		show = "show" in opts
		serverName = self.serverChooser.getcurselection()
		f = self.Servers[serverName][1]
		parts = self.paramFrames[serverName][1]
		opts = self.Servers[serverName][3](self, parts)
		output = f(target, opts, propName, rba)
		if save:
			_save(output, show)
		elif show:
			# create temporary file and invoke browser
			from OpenSave import osTemporaryFile
			filename = osTemporaryFile(suffix=".html")
			f = open(filename, "w")
			f.write(output)
			f.close()
			import urllib
			from chimera import help
			help.display("file:" + urllib.pathname2url(filename))

	_paramMsmsParams = [
		(	"Surface probe size:",
			"msms_probe",
			( ( "1.3", "1.3" ),
			  ( "1.4", "1.4" ),
			  ( "1.5", "1.5" ),
			  ( "1.6", "1.6" ) ),
			"1.5"
		),
		(	"Atoms to use:",
			"msms_atoms",
			( ( "No Hetatms", "HETATM" ),
			  ( "Atoms + Hetatms", "ZZZZZZ" ),
			  ( "All atoms except waters", "HOH" ) ),
			"No Hetatms"
		),
	]
	_paramGersteinSurfaceParams = [
		(	"Surface probe size:",
			"surf_Gerstein_probe",
			( ( "1.3", "1.3" ),
			  ( "1.4", "1.4" ),
			  ( "1.5", "1.5" ),
			  ( "1.6", "1.6" ) ),
			"1.4"
		),
		(	"Atoms to use:",
			"surf_Gerstein_atoms",
			( ( "No Hetatms", "HETATM" ),
			  ( "Atoms + Hetatms", "ZZZZZZ" ),
			  ( "All atoms except waters", "HOH" ) ),
			"All atoms except waters"
		),
	]
	_paramGersteinVolumeParams = [
		(	"Method:",
			"vol_Gerstein_method",
			( ( "Normal Voronoi", "1" ),
			  ( "Method B", "2" ),
			  ( "Radical Plane", "3" ),
			  ( "Modified Method B", "4" ) ),
			"Method B"
		),
		(	"Radii:",
			"vol_Gerstein_radii",
			( ( "Chothia Radii", "" ),
			  ( "Richards Radii", "-RichardsRadii" ) ),
			"Chothia Radii"
		),
		(	"Atoms to use:",
			"vol_Gerstein_atoms",
			( ( "No Hetatms", "HETATM" ),
			  ( "Atoms + Hetatms", "ZZZZZZ" ),
			  ( "All atoms except waters", "HOH" ) ),
			"No Hetatms"
		),
	]
	def _paramMakeMsms(self, group):
		return self._paramMake(group, self._paramMsmsParams)
	def _paramGetMsms(self, parts):
		return self._paramGet(parts, self._paramMsmsParams)
	def _paramMakeGersteinSurface(self, group):
		return self._paramMake(group, self._paramGersteinSurfaceParams)
	def _paramGetGersteinSurface(self, parts):
		return self._paramGet(parts, self._paramGersteinSurfaceParams)
	def _paramMakeGersteinVolume(self, group):
		return self._paramMake(group, self._paramGersteinVolumeParams)
	def _paramGetGersteinVolume(self, parts):
		return self._paramGet(parts, self._paramGersteinVolumeParams)

	def _paramMake(self, parent, params):
		g = Pmw.Group(parent, tag_text="Parameters")
		parts = []
		for label, cgiTag, items, default in params:
			m = Pmw.OptionMenu(g.interior(),
					labelpos="w",
					label_text=label,
					items=[ item[0] for item in items ])
			m.setvalue(default)
			m.pack(fill="x", expand=False)
			parts.append(m)
		Pmw.alignlabels(parts)
		return g, parts
	def _paramGet(self, parts, params):
		args = []
		for i, m in enumerate(parts):
			sel = m.getvalue()
			label, cgiTag, items, default = params[i]
			for name, value in items:
				if name == sel:
					args.append((cgiTag, None, value))
					break
			else:
				raise ChimeraError("unexpected option value")
		return args

	Servers = {
		"Surface Area (MSMS)":
			(	"msmsArea",
				StrucTools.msms,
				_paramMakeMsms,
				_paramGetMsms,
			),
		"Accessible Surface (Gerstein)":
			(	"accessibleSurface",
				StrucTools.surface,
				_paramMakeGersteinSurface,
				_paramGetGersteinSurface,
			),
		"Voronoi Volume (Gerstein)":
			(	"voronoiVolume",
				StrucTools.volume,
				_paramMakeGersteinVolume,
				_paramGetGersteinVolume,
			),
	}
Esempio n. 11
0
	def fillInUI(self, parent):
		self.notebook = Pmw.NoteBook(parent)
		self.notebook.pack(fill="both", expand=True)
		page = self.notebook.add("Molecules")
		self.molChooser = MoleculeScrolledListBox(page,
					listbox_selectmode="extended",
					autoselect="single")
		self.molChooser.pack(fill="both", expand=True)
		page = self.notebook.add("Chains")
		self.chainChooser = MoleculeChainScrolledListBox(page,
					listbox_selectmode="extended",
					autoselect="single")
		self.chainChooser.pack(fill="both", expand=True)
		self.outputOptions = Pmw.RadioSelect(parent,
                                        pady=0,
                                        buttontype="checkbutton",
                                        orient="vertical")
                self.outputOptions.pack(fill="x", expand=False)
                self.outputOptions.add("solid", text="Solid surface (rather than mesh)")
		self.outputOptions.add("track", text="Reuse last surface (if any)")
		self.outputOptions.add("atoms", text="Select interface atoms")
                self.outputOptions.add("prune", text="Residue centroid distance pruning")
		self.outputOptions.setvalue(["solid", "track"])
		self.pruneDistance = Pmw.EntryField(parent,
					labelpos="w",
					label_text="Prune distance:",
					value="30.0",
					validate=self._validatePruneDistance)
		self.pruneDistance.pack(fill="x", expand=False)
		self.moleculeBias = Pmw.Counter(parent,
						labelpos="w",
						label_text="Molecule bias:",
						datatype="real",
						increment = 0.1,
						entryfield_value="0.5",
						entryfield_validate={'validator' : 'real',
						                     'min' : '0.0', 'max' : '1.0',
								     'separator' : '.'})
		self.moleculeBias.pack(fill="x", expand=False)

		histKw = {
			'minlabel': True,
			'maxlabel': True,
			'scaling': 'linear',
		}
		self.histogram = MarkedHistogram(parent, **histKw)
		self.histogramMarkers = self.histogram.addmarkers(activate=True,
						coordtype='relative')
                self.histogramMarkers.extend([
				((1.0, 0.0), (0.0, 0.0, 0.33, 1.0)),
				((0.0, 0.0), (1.0, 0.0, 0.0, 1.0))])
		self.histogram.pack(expand=True, fill="both")
		self._trackedPiece = None
		self._trackedModel = None
		self.models = {}
		chimera.openModels.addRemoveHandler(self._removeModel, None)
		import SimpleSession
		chimera.triggers.addHandler(SimpleSession.SAVE_SESSION,
						self.saveSession, None)
		chimera.triggers.addHandler("Molecule",
						self._moleculeChanged, None)
Esempio n. 12
0
class Interface(ModelessDialog):
	title = "Compute Interface Surface"
	help = "ContributedSoftware/intersurf/intersurf.html"

	def fillInUI(self, parent):
		self.notebook = Pmw.NoteBook(parent)
		self.notebook.pack(fill="both", expand=True)
		page = self.notebook.add("Molecules")
		self.molChooser = MoleculeScrolledListBox(page,
					listbox_selectmode="extended",
					autoselect="single")
		self.molChooser.pack(fill="both", expand=True)
		page = self.notebook.add("Chains")
		self.chainChooser = MoleculeChainScrolledListBox(page,
					listbox_selectmode="extended",
					autoselect="single")
		self.chainChooser.pack(fill="both", expand=True)
		self.outputOptions = Pmw.RadioSelect(parent,
                                        pady=0,
                                        buttontype="checkbutton",
                                        orient="vertical")
                self.outputOptions.pack(fill="x", expand=False)
                self.outputOptions.add("solid", text="Solid surface (rather than mesh)")
		self.outputOptions.add("track", text="Reuse last surface (if any)")
		self.outputOptions.add("atoms", text="Select interface atoms")
                self.outputOptions.add("prune", text="Residue centroid distance pruning")
		self.outputOptions.setvalue(["solid", "track"])
		self.pruneDistance = Pmw.EntryField(parent,
					labelpos="w",
					label_text="Prune distance:",
					value="30.0",
					validate=self._validatePruneDistance)
		self.pruneDistance.pack(fill="x", expand=False)
		self.moleculeBias = Pmw.Counter(parent,
						labelpos="w",
						label_text="Molecule bias:",
						datatype="real",
						increment = 0.1,
						entryfield_value="0.5",
						entryfield_validate={'validator' : 'real',
						                     'min' : '0.0', 'max' : '1.0',
								     'separator' : '.'})
		self.moleculeBias.pack(fill="x", expand=False)

		histKw = {
			'minlabel': True,
			'maxlabel': True,
			'scaling': 'linear',
		}
		self.histogram = MarkedHistogram(parent, **histKw)
		self.histogramMarkers = self.histogram.addmarkers(activate=True,
						coordtype='relative')
                self.histogramMarkers.extend([
				((1.0, 0.0), (0.0, 0.0, 0.33, 1.0)),
				((0.0, 0.0), (1.0, 0.0, 0.0, 1.0))])
		self.histogram.pack(expand=True, fill="both")
		self._trackedPiece = None
		self._trackedModel = None
		self.models = {}
		chimera.openModels.addRemoveHandler(self._removeModel, None)
		import SimpleSession
		chimera.triggers.addHandler(SimpleSession.SAVE_SESSION,
						self.saveSession, None)
		chimera.triggers.addHandler("Molecule",
						self._moleculeChanged, None)

	def _validatePruneDistance(self, text):
		if len(text) == 0:
			return Pmw.PARTIAL
		try:
			float(text)
		except:
			return Pmw.ERROR
		return Pmw.OK

	def _show_geometry(self, vertices, triangles, vertex_colors, solid=0, track=0):
		import numpy
		varray = numpy.array(vertices, numpy.float32)
		tarray = numpy.array(triangles, numpy.int32)
		carray = numpy.array(vertex_colors, numpy.float32)

		import chimera
		if track and self._trackedPiece:
			sm = self._trackedModel
			g = self._trackedPiece
			g.geometry = varray, tarray
			g.vertexColors = carray
			if solid:
				g.displayStyle = g.Solid
			else:
				g.displayStyle = g.Mesh
		else:
			import _surface
			sm = _surface.SurfaceModel()
			g = sm.addPiece(varray, tarray, (1, 1, 1, 1))
			g.vertexColors = carray
			if solid:
				g.displayStyle = g.Solid
			else:
				g.displayStyle = g.Mesh
			sm.name = "Interface Surface"
			chimera.openModels.add([sm])
			self._trackedPiece = g
			self._trackedModel = sm
		sm.openState.xform = chimera.Xform.identity()
		self.models[sm] = (vertices, triangles, vertex_colors, solid)
		return sm, g

	def Apply(self):
		pageName = self.notebook.getcurselection()
		if pageName == "Molecules":
			target = self.molChooser.getvalue()
		elif pageName == "Chains":
			target = self.chainChooser.getvalue()
		if not target:
			raise chimera.UserError("Please select two molecules/chains")
		if len(target) != 2:
			raise chimera.UserError("Please select exactly two molecules/chains")
                opts = self.outputOptions.getvalue()
                solid = "solid" in opts
		prune = "prune" in opts
		track = "track" in opts
		selAtoms = "atoms" in opts

		if not self.moleculeBias.valid():
			raise chimera.UserError("Please enter a valid bias toward the second molecule")
		bias = float(self.moleculeBias.getvalue())
		if prune:
			if not self.pruneDistance.valid():
				raise chimera.UserError("Please enter a valid prune distance")
			pruneDistance = float(self.pruneDistance.getvalue())
		else:
			pruneDistance = 0
		self.doApply(target, solid, track, selAtoms,
				bias, prune, pruneDistance)

	def doApply(self, target, solid, track, selAtoms,
			bias, prune, pruneDistance):
		m1, m2 = target
		if prune:
			m1_list = SurfMaker.GetAtomList(m1, m2, pruneDistance)
			m2_list = SurfMaker.GetAtomList(m2, m1, pruneDistance)
		else:
			m1_list = SurfMaker.GetAtomList(m1)
			m2_list = SurfMaker.GetAtomList(m2)

		if not m1_list or not m2_list:
			raise chimera.UserError("No interface surface found")
		p = SurfMaker.UnpackIntersurfData(m1_list, m2_list)
		tetras = SurfMaker.ComputeTetrahedralization(p)
		surfPoints, surfTriangles, surfAtoms = SurfMaker.ComputeSurface(p, tetras, bias)

		surfMetric = [ getDistance(x[0], x[1]) for x in surfAtoms ]
		lo = min(surfMetric)
		hi = max(surfMetric)
		scale = hi - lo
		markers = [ (lo + m['xy'][0] * scale, m['rgba'])
				for m in self.histogramMarkers ]
		surfColors = [ getHistogramColor(x, markers)
					for x in surfMetric ] 
		self.histogramData = (lo, hi, surfMetric)
		def myMakeBars(numBins, data=self.histogramData):
			return makeBars(numBins, data)
		self.histogram["datasource"] = (lo, hi, myMakeBars)

		self._show_geometry(surfPoints, surfTriangles, surfColors, solid, track)
		if selAtoms:
			from chimera import selection
			atomSet = set([])
			for a1, a2 in surfAtoms:
				atomSet.add(a1)
				atomSet.add(a2)
			sel = selection.ItemizedSelection()
			sel.add(atomSet)
			sel.addImplied(vertices=False)
			selection.setCurrent(sel)

	def _removeModel(self, trigger, data, models):
		for m in models:
			if self._trackedModel is m:
				self._trackedModel = None
				self._trackedPiece = None
			try:
				del self.models[m]
			except KeyError:
				pass

	def _moleculeChanged(self, trigger, data, models):
		if 'activeCoordSet changed' not in models.reasons:
			return
		pageName = self.notebook.getcurselection()
		if pageName == "Molecules":
			target = self.molChooser.getvalue()
		elif pageName == "Chains":
			target = [ c.molecule for c in self.chainChooser.getvalue() ]
		else:
			return
		for m in models.modified:
			if m in target:
				break
		else:
			return
		self.Apply()

	def saveSession(self, trigger, data, file):
		isMapped = self.uiMaster().winfo_ismapped()
		if not isMapped and not self.models:
			# Not visible and no displayed surfaces
			return
		from SessionUtil import stateclasses, objecttree
		restoring_code = \
"""
def restoreIntersurfSession(state):
	import SimpleSession
	from Intersurf import Intersurf
	SimpleSession.registerAfterModelsCB(Intersurf.restoreSession, state)
risArgs = (%s)
try:
	restoreIntersurfSession(risArgs)
except:
	reportRestoreError("Error restoring Intersurf extension")
"""
		pageName = self.notebook.getcurselection()
		chosenMolecules = self.molChooser.getcurselection()
		chosenChains = self.chainChooser.getcurselection()
                opts = self.outputOptions.getvalue()
		pruneDistance = self.pruneDistance.getvalue()
		bias = self.moleculeBias.getvalue()
		if isinstance(self.histogram["datasource"], basestring):
			histogramData = self.histogram["datasource"]
		else:
			histogramData = self.histogramData
		markerValues = []
		markers, selectedMarker = self.histogram.currentmarkerinfo()
		if markers:
			for m in markers:
				markerValues.append((m["xy"], m["rgba"]))
		ms = stateclasses.Model_State()
		modelData = []
		trackedIndex = -1
		n = 0
		for m, v in self.models.iteritems():
			if self._trackedModel is m:
				trackedIndex = n
			ms.state_from_model(m)
			bt = objecttree.instance_tree_to_basic_tree(ms)
			modelData.append((v, bt))
			n += 1
		state = (pageName, chosenMolecules, chosenChains, opts,
				pruneDistance, bias,
				histogramData, markerValues,
				modelData, trackedIndex, isMapped)
		file.write(restoring_code % repr(state))

	def restoreSession(self, state):
		from SessionUtil import stateclasses, objecttree
		if len(state) == 10:
			(pageName, chosenMolecules, chosenChains, opts,
				pruneDistance, bias,
				dataSource, markerValues,
				modelData, trackedIndex) = state
			if modelData:
				isMapped = True
			else:
				isMapped = False
		else:
			(pageName, chosenMolecules, chosenChains, opts,
				pruneDistance, bias,
				histogramData, markerValues,
				modelData, trackedIndex, isMapped) = state
		# Call get method to make sure items are updated
		self.molChooser.get()
		self.molChooser.setvalue(chosenMolecules)
		self.chainChooser.get()
		self.chainChooser.setvalue(chosenChains)
		self.notebook.selectpage(pageName)
		self.outputOptions.setvalue(list(opts))
		self.pruneDistance.setvalue(pruneDistance)
		self.moleculeBias.setvalue(bias)
		if isinstance(histogramData, basestring):
			dataSource = histogramData
		else:
			lo, hi, surfMetric = histogramData
			self.histogramData = (lo, hi, surfMetric)
			def myMakeBars(numBins, data=self.histogramData):
				return makeBars(numBins, data)
			dataSource = (lo, hi, myMakeBars)
		self.histogram["datasource"] = dataSource
		if markerValues:
			oldMarkers = self.histogram.currentmarkerinfo()[0]
			newMarkers = self.histogram.addmarkers()
			newMarkers.extend(markerValues)
			self.histogram.deletemarkers(oldMarkers)
			self.histogramMarkers = newMarkers
		trackedModel = None
		trackedPiece = None
		nameToClass = {
			"Model_State": stateclasses.Model_State,
			"Xform_State": stateclasses.Xform_State,
		}
		for n, mState in enumerate(modelData):
			if len(mState) == 2:
				v, bt = mState
			else:
				v = mState
				bt = None
			sm, g = self._show_geometry(*v)
			if trackedIndex == n:
				trackedModel = sm
				trackedPiece = g
			if bt is not None:
				ms = objecttree.basic_tree_to_instance_tree(bt,
							nameToClass)
				ms.restore_state(sm)
		if trackedModel:
			self._trackedModel = trackedModel
			self._trackedPiece = trackedPiece
		if not isMapped:
			self.Close()