Exemple #1
0
    def body(self, guiFrame):

        self.geometry('700x400')

        guiFrame.grid_columnconfigure(0, weight=1)
        guiFrame.grid_rowconfigure(0, weight=1)

        interfaceGroups, interfaceGroupDict = self.getInterfaceGroups()

        if len(interfaceGroups) > 1:
            mainFrame = TabbedFrame(guiFrame,
                                    options=interfaceGroups,
                                    grid=(0, 0))
            frames = mainFrame.frames
        else:
            mainFrame = Frame(guiFrame, grid=(0, 0))
            frames = [mainFrame]

        for n, interfaceGroup in enumerate(interfaceGroups):
            frame = frames[n]

            interfaceObjects = interfaceGroupDict[interfaceGroup]
            for interfaceObject in interfaceObjects:
                self.makeInterfaceWidget(frame, interfaceObject)

        texts = ('Ok', 'Cancel')
        commands = (self.setupRun, self.cancelRun)
        buttonList = ButtonList(guiFrame,
                                texts=texts,
                                commands=commands,
                                grid=(1, 0))
Exemple #2
0
    def body(self):

        frame = self.frame

        self.resultsResidueNumber = 1

        frame.expandGrid(5, 0)

        resultTopFrame = LabelFrame(frame, text='Which results to show')
        resultTopFrame.grid(row=0, column=0, sticky='ew')

        self.resultsResidueNumber = 3

        texts = [' < ']
        commands = [self.resultsPrevResidue]
        self.resultsPreviousButton = ButtonList(resultTopFrame,
                                                commands=commands,
                                                texts=texts)
        self.resultsPreviousButton.grid(row=0, column=1, sticky='nsew')

        tipText = 'The Number of the residue in the sequence to display results for'
        self.resultsResidueNumberEntry = IntEntry(
            resultTopFrame,
            grid=(0, 2),
            width=7,
            text=3,
            returnCallback=self.resultsUpdateAfterEntry,
            tipText=tipText)
        #self.resultsResidueNumberEntry.bind('<Leave>', self.resultsUpdateAfterEntry, '+')

        texts = [' > ']
        commands = [self.resultsNextResidue]
        self.resultsNextButton = ButtonList(resultTopFrame,
                                            commands=commands,
                                            texts=texts)
        self.resultsNextButton.grid(row=0, column=3, sticky='nsew')

        selectCcpCodes = ['residue'] + AMINO_ACIDS
        self.resultsSelectedCcpCode = 'residue'

        tipText = 'Instead of going through the sequence residue by residue, jump directly to next amino acid of a specific type.'
        resultsSelectCcpCodeLabel = Label(
            resultTopFrame,
            text='Directly jump to previous/next:',
            grid=(0, 4))
        self.resultsSelectCcpCodePulldown = PulldownList(
            resultTopFrame,
            callback=self.resultsChangeSelectedCcpCode,
            texts=selectCcpCodes,
            index=selectCcpCodes.index(self.resultsSelectedCcpCode),
            grid=(0, 5),
            tipText=tipText)

        self.selectedSolution = 1

        runLabel = Label(resultTopFrame, text='run:')
        runLabel.grid(row=0, column=6)

        texts = [' < ']
        commands = [self.resultsPrevSolution]
        self.resultsPreviousSolutionButton = ButtonList(resultTopFrame,
                                                        commands=commands,
                                                        texts=texts)
        self.resultsPreviousSolutionButton.grid(row=0, column=7, sticky='nsew')

        tipText = 'If you ran the algorithm more than once, you can select the solution given by the different runs.'
        self.resultsSolutionNumberEntry = IntEntry(
            resultTopFrame,
            grid=(0, 8),
            width=7,
            text=1,
            returnCallback=self.solutionUpdateAfterEntry,
            tipText=tipText)
        #self.resultsSolutionNumberEntry.bind('<Leave>', self.solutionUpdateAfterEntry, '+')

        texts = [' > ']
        commands = [self.resultsNextSolution]
        self.resultsNextSolutionButton = ButtonList(resultTopFrame,
                                                    commands=commands,
                                                    texts=texts)
        self.resultsNextSolutionButton.grid(row=0, column=9, sticky='nsew')

        self.energyLabel = Label(resultTopFrame, text='energy:')
        self.energyLabel.grid(row=0, column=10)

        texts = ['template for puzzling']
        commands = [self.adoptSolution]
        self.adoptButton = ButtonList(resultTopFrame,
                                      commands=commands,
                                      texts=texts)
        self.adoptButton.grid(row=0, column=11, sticky='nsew')

        # LabelFrame(frame, text='Spin Systems')
        resultsSecondFrame = Frame(frame)
        resultsSecondFrame.grid(row=2, column=0, sticky='nsew')

        resultsSecondFrame.grid_columnconfigure(0, weight=1)
        resultsSecondFrame.grid_columnconfigure(1, weight=1)
        resultsSecondFrame.grid_columnconfigure(2, weight=1)
        resultsSecondFrame.grid_columnconfigure(3, weight=1)
        resultsSecondFrame.grid_columnconfigure(4, weight=1)

        headingList = ['#', '%']

        tipTexts = [
            'Spinsystem number {} indicates serial of the spinsystem. If the spinsystem was already assigned to a residue, the residue number is shown aswell',
            'percentage of the solutions that connected this spinsystem to this residue'
        ]

        editWidgets = [None, None, None]

        self.displayResultsTables = []
        self.residueLabels = []

        for i in range(5):

            label = Label(resultsSecondFrame, text='residue')
            label.grid(row=0, column=i)

            #editGetCallbacks = [createCallbackFunction(i)]*3

            displayResultsTable = ScrolledMatrix(
                resultsSecondFrame,
                headingList=headingList,
                multiSelect=False,
                tipTexts=tipTexts,
                callback=self.selectSpinSystemForTable,
                passSelfToCallback=True)

            displayResultsTable.grid(row=2, column=i, sticky='nsew')
            displayResultsTable.sortDown = False

            self.residueLabels.append(label)
            self.displayResultsTables.append(displayResultsTable)

        # LabelFrame(frame, text='Sequence Fragment')
        resultsFirstFrame = Frame(resultsSecondFrame)
        resultsFirstFrame.grid(row=1, column=0, sticky='ew', columnspan=5)

        resultsFirstFrame.grid_rowconfigure(0, weight=1)
        resultsFirstFrame.grid_rowconfigure(1, weight=1)
        resultsFirstFrame.grid_columnconfigure(0, weight=1)

        texts = [
            ' res 1 ', ' links ', ' res 2 ', ' links ', ' res 3 ', ' links ',
            ' res 4 ', ' links ', ' res 5 '
        ]
        commands = [
            lambda: self.selectRelativeResidue(1, True),
            lambda: self.selectLink(1, True),
            lambda: self.selectRelativeResidue(2, True),
            lambda: self.selectLink(2, True),
            lambda: self.selectRelativeResidue(3, True),
            lambda: self.selectLink(3, True),
            lambda: self.selectRelativeResidue(4, True),
            lambda: self.selectLink(4, True),
            lambda: self.selectRelativeResidue(5, True)
        ]
        self.sequenceButtons = ButtonList(resultsFirstFrame,
                                          commands=commands,
                                          texts=texts)
        self.sequenceButtons.grid(row=0, column=0, sticky='nsew')

        for n, button in enumerate(self.sequenceButtons.buttons):

            if n % 2:

                button.grid(column=n, sticky='ns')

                self.sequenceButtons.grid_columnconfigure(n, weight=0)

            else:

                self.sequenceButtons.grid_columnconfigure(n, uniform=2)

        spacer = Spacer(resultsFirstFrame)
        spacer.grid(row=1, column=0, sticky='nsew')

        texts = [
            ' res 1 ', ' links ', ' res 2 ', ' links ', ' res 3 ', ' links ',
            ' res 4 ', ' links ', ' res 5 '
        ]
        commands = commands = [
            lambda: self.selectRelativeResidue(1, False),
            lambda: self.selectLink(1, False),
            lambda: self.selectRelativeResidue(2, False),
            lambda: self.selectLink(2, False),
            lambda: self.selectRelativeResidue(3, False),
            lambda: self.selectLink(3, False),
            lambda: self.selectRelativeResidue(4, False),
            lambda: self.selectLink(4, False),
            lambda: self.selectRelativeResidue(5, False)
        ]
        self.sequenceButtonsB = ButtonList(resultsFirstFrame,
                                           commands=commands,
                                           texts=texts)
        self.sequenceButtonsB.grid(row=2, column=0, sticky='nsew')

        for n, button in enumerate(self.sequenceButtonsB.buttons):

            if n % 2:

                button.grid(column=n, sticky='ns')

                self.sequenceButtonsB.grid_columnconfigure(n, weight=0)

            else:

                self.sequenceButtonsB.grid_columnconfigure(n, uniform=2)

        frame.grid_rowconfigure(3, weight=2)

        resultsThirdFrame = Frame(frame)
        resultsThirdFrame.grid(row=3, column=0, sticky='nsew')

        resultsThirdFrame.grid_rowconfigure(0, weight=1)
        resultsThirdFrame.grid_columnconfigure(0, weight=1)

        tabbedFrameB = TabbedFrame(resultsThirdFrame,
                                   options=['Peaks', 'Spin System'],
                                   callback=self.toggleTab,
                                   grid=(0, 0))
        #self.tabbedFrameB = tabbedFrame

        PeakFrame, SpinSystemFrame = tabbedFrameB.frames

        SpinSystemFrame.grid_rowconfigure(0, weight=1)
        PeakFrame.grid_rowconfigure(1, weight=1)

        SpinSystemFrame.grid_columnconfigure(0, weight=1)
        PeakFrame.grid_columnconfigure(0, weight=1)

        headingList = [
            'residue', 'assigned to in project', 'user defined sequence',
            'selected annealing result', '%'
        ]

        tipTexts = [None, None, None, None, None]

        editWidgets = [None, None, None, None, None]

        editGetCallbacks = [None, None, None, None, None]

        editSetCallbacks = [None, None, None, None, None]

        self.spinSysTable = ScrolledMatrix(SpinSystemFrame,
                                           headingList=headingList,
                                           editWidgets=editWidgets,
                                           multiSelect=False,
                                           editGetCallbacks=editGetCallbacks,
                                           editSetCallbacks=editSetCallbacks,
                                           tipTexts=tipTexts)
        self.spinSysTable.grid(row=0, column=0, sticky='nsew')

        buttonFrameinPeakFrame = Frame(PeakFrame)
        buttonFrameinPeakFrame.grid(sticky='ew')

        self.findButton = Button(
            buttonFrameinPeakFrame,
            text=' Go to Peak ',
            borderwidth=1,
            padx=2,
            pady=1,
            command=self.findPeak,
            tipText='Locate the currently selected peak in the specified window'
        )

        self.findButton.grid(row=0, column=0, sticky='e')

        label = Label(buttonFrameinPeakFrame, text='in window:')

        label.grid(row=0, column=1, sticky='w')

        self.windowPulldown = PulldownList(
            buttonFrameinPeakFrame,
            callback=self.selectWindowPane,
            tipText='Choose the spectrum window for locating peaks or strips')

        self.windowPulldown.grid(row=0, column=2, sticky='w')

        self.assignSelectedPeaksButton = Button(
            buttonFrameinPeakFrame,
            text='Assign Resonances to Peak(s)',
            borderwidth=1,
            padx=2,
            pady=1,
            command=self.assignSelectedPeaks,
            tipText=
            'Assign resonances to peak dimensions, this of course only works when the peak is found in the spectrum.'
        )

        self.assignSelectedPeaksButton.grid(row=0, column=3, sticky='ew')

        self.assignSelectedSpinSystemsToResiduesButton = Button(
            buttonFrameinPeakFrame,
            text='Assign Spinsystems to Residues',
            borderwidth=1,
            padx=2,
            pady=1,
            command=self.assignSelectedSpinSystemsToResidues,
            tipText='Assign spinsystems to residues')

        self.assignSelectedSpinSystemsToResiduesButton.grid(row=0,
                                                            column=4,
                                                            sticky='ew')

        headingList = [
            '#', 'spectrum', 'Dim1', 'Dim2', 'Dim3', 'c.s. dim1', 'c.s. dim2',
            'c.s. dim3', 'colabelling'
        ]

        tipTexts = [
            'Peak number, only present when the peak was actually found in the spectrum.',
            'Name of the spectrum',
            'Name of atomSet measured in this dimension. Dimension number corresponds to Ref Exp Dim as indicated by going in the main menu to Experiment-->Experiments-->Experiment Type',
            'Name of atomSet measured in this dimension. Dimension number corresponds to Ref Exp Dim as indicated by going in the main menu to Experiment-->Experiments-->Experiment Type',
            'Name of atomSet measured in this dimension. Dimension number corresponds to Ref Exp Dim as indicated by going in the main menu to Experiment-->Experiments-->Experiment Type',
            'Chemical Shift', 'Chemical Shift', 'Chemical Shift',
            'Colabbeling fraction over all nuclei that are on the magnetization transfer pathway during the experiment that gave rise to the peak, including visited nuclei that were not measured in any of the peak dimensions'
        ]

        #editWidgets = [None, None, None, None, None, None, None, None, None]

        editGetCallbacks = [
            None, None, None, None, None, None, None, None, None
        ]

        #editGetCallbacks = [self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak]

        editSetCallbacks = [
            None, None, None, None, None, None, None, None, None
        ]

        self.displayPeakTable = ScrolledMatrix(PeakFrame,
                                               headingList=headingList,
                                               multiSelect=True,
                                               tipTexts=tipTexts)
        #editWidgets=editWidgets, multiSelect=True,
        # editGetCallbacks=editGetCallbacks,
        # editSetCallbacks=editSetCallbacks,
        # tipTexts=tipTexts)
        self.displayPeakTable.grid(row=1, column=0, sticky='nsew')

        self.windowPane = None
        self.updateWindows()
Exemple #3
0
    def body(self, guiFrame):

        self.geometry('450x500')

        guiFrame.grid_rowconfigure(0, weight=1)
        guiFrame.grid_columnconfigure(0, weight=1)

        options = ['Peak Separator', 'Advanced Settings']

        tabbedFrame = TabbedFrame(guiFrame, options=options)
        tabbedFrame.grid(row=0, column=0, sticky='nsew')

        buttons = UtilityButtonList(tabbedFrame.sideFrame,
                                    helpUrl=self.help_url)
        buttons.grid(row=0, column=0, sticky='e')

        self.tabbedFrame = tabbedFrame
        frameA, frameB = tabbedFrame.frames

        #
        # FrameA : Main Settings
        #

        frameA.grid_columnconfigure(1, weight=1)
        row = 0  # Label row

        row += 1
        div = LabelDivider(frameA, text='Peak Separator Parameters')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')

        row += 1
        label = Label(frameA, text='Min. number of peaks:')
        label.grid(row=row, column=0, sticky='w')
        self.minPeaksEntry = IntEntry(frameA, returnCallback=self.applyChange, width=10, \
              tipText='Minimum number of peaks to find (must be > 0)')
        self.minPeaksEntry.grid(row=row, column=1, sticky='n')
        self.minPeaksEntry.bind('<Leave>', self.applyChange, '+')

        row += 1
        label = Label(frameA, text='Max. number of peaks:')
        label.grid(row=row, column=0, sticky='w')
        self.maxPeaksEntry = IntEntry(frameA, returnCallback=self.applyChange, width=10, \
              tipText='Maximum number of peaks to find (0 is unlimited - not recommended)')
        self.maxPeaksEntry.grid(row=row, column=1, sticky='n')
        self.maxPeaksEntry.bind('<Leave>', self.applyChange, '+')

        row += 1
        label = Label(frameA, text='Only pick positive peaks:')
        label.grid(row=row, column=0, sticky='w')
        entries = ['False', 'True']
        self.posPeaksButtons = RadioButtons(
            frameA,
            entries=entries,
            select_callback=self.applyChange,
            direction='horizontal',
            tipTexts=[
                'Search for both positive and negative intensity peaks',
                'Limit search to only positive peaks'
            ])
        self.posPeaksButtons.grid(row=row, column=1, sticky='n')

        row += 1
        label = Label(frameA, text='Peak Model:')
        label.grid(row=row, column=0, sticky='w')
        ### G/L Mixture works, but volume calculation involves Gamma function
        # entries = ['Gaussian', 'Lorentzian', 'G/L Mixture']
        entries = ['Gaussian', 'Lorentzian']
        self.shapeButtons = RadioButtons(
            frameA,
            entries=entries,
            select_callback=self.applyChange,
            direction='horizontal',
            tipTexts=[
                'Choose a Gaussian model peak shape to fit to peaks',
                'Choose a Lorentzian model peak shape to fit to peaks'
            ])
        self.shapeButtons.grid(row=row, column=1, sticky='n')

        row += 1
        div = LabelDivider(frameA,
                           text='Region',
                           tipText='Region that search will limit itself to')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')

        row += 1
        label = Label(frameA, text='Peak List:')
        label.grid(row=row, column=0, sticky='nw')
        self.peakListPulldown = PulldownList(
            frameA,
            callback=self.setManuallyPickPeakList,
            tipText='Select which peak list new peaks are to be added to')
        self.peakListPulldown.grid(row=row, column=1, sticky='nw')

        # tricky scrolled matrix
        row += 1
        self.regionTable = None
        frameA.grid_rowconfigure(row, weight=1)
        headings = ('dim.', 'start (ppm)', 'end (ppm)', 'actual size')

        self.editDimEntry = IntEntry(self,
                                     returnCallback=self.applyChange,
                                     width=5,
                                     tipText='Dimension number')
        self.editStartEntry = FloatEntry(self,
                                         returnCallback=self.applyChange,
                                         width=5,
                                         tipText='Search area lower bound')
        self.editEndEntry = FloatEntry(self,
                                       returnCallback=self.applyChange,
                                       width=5,
                                       tipText='Search area upper bound')

        editWidgets = [
            self.editDimEntry, self.editStartEntry, self.editEndEntry, None
        ]

        editGetCallbacks = [None, None, None, None]
        editSetCallbacks = [None, None, None, None]

        self.regionTable = ScrolledMatrix(frameA,
                                          headingList=headings,
                                          multiSelect=False,
                                          editWidgets=editWidgets,
                                          editGetCallbacks=editGetCallbacks,
                                          editSetCallbacks=editSetCallbacks,
                                          initialRows=5)

        self.regionTable.grid(row=row, column=0, columnspan=2, sticky='nsew')

        # Run Button
        row += 1
        texts = ['Add Region']
        commands = [self.updateFromRegion]
        self.addResetButtons = ButtonList(
            frameA,
            texts=texts,
            commands=commands,
            tipTexts=['Add selected specrtral region'])
        self.addResetButtons.grid(row=row, column=0, columnspan=2, sticky='ew')

        row += 1
        texts = ['Separate Peaks']
        commands = [self.runPeakSeparator]
        self.runButton = ButtonList(frameA,
                                    texts=texts,
                                    commands=commands,
                                    expands=True,
                                    tipTexts=['Run peak search now'])
        self.runButton.grid(row=row, column=0, columnspan=2, sticky='nsew')

        #
        # FrameB : Further Settings
        #

        frameB.grid_columnconfigure(0, weight=1)

        row = 0

        div = LabelDivider(frameB, text='Rate:')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')
        row += 1

        label = Label(frameB, text='Rate of MCMC step size change')
        label.grid(row=row, column=0, columnspan=1, sticky='w')

        self.rateEntry = FloatEntry(frameB, returnCallback=self.applyChange, width=10, \
              tipText='Rate effects speed of run, smaller values take longer but may produce better results')
        self.rateEntry.grid(row=row, column=1, sticky='n')
        self.rateEntry.bind('<Leave>', self.applyChange, '+')
        self.rateEntry.set(self.params.rate)

        # tricky scrolled matrix for line width
        row += 2
        div = LabelDivider(frameB, text='Line Width (Hz):')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')

        row += 1
        label = Label(frameB, text="Descr.")
        label.grid(row=row, rowspan=2, column=0, sticky='w')

        row += 1
        self.lineWidthTable = None
        frameB.grid_rowconfigure(row, weight=1)
        lineWidthHeadings = ('dim.', 'min. σ (Hz)', 'max. σ (Hz)')

        self.editMinSigmaEntry = FloatEntry(self,
                                            returnCallback=self.applyChange,
                                            width=5,
                                            tipText='Minimum line width (Hz)')
        self.editMaxSigmaEntry = FloatEntry(self,
                                            returnCallback=self.applyChange,
                                            width=5,
                                            tipText='Maximum line width (Hz)')

        # self.editDimEntry is also from regionTable
        initialWidthRows = 4

        editLineWidthWidgets = [
            None, self.editMinSigmaEntry, self.editMaxSigmaEntry
        ]
        editLineWidthGetCallbacks = [None, self.getSigmaMin, self.getSigmaMax]
        editLineWidthSetCallbacks = [None, self.setSigmaMin, self.setSigmaMax]

        self.lineWidthTable = ScrolledMatrix(
            frameB,
            headingList=lineWidthHeadings,
            multiSelect=False,
            editWidgets=editLineWidthWidgets,
            editGetCallbacks=editLineWidthGetCallbacks,
            editSetCallbacks=editLineWidthSetCallbacks,
            initialRows=initialWidthRows)

        self.lineWidthTable.grid(row=row,
                                 column=0,
                                 columnspan=2,
                                 sticky='nsew')

        # option to 'repick' exisiting peak list
        row += initialWidthRows
        div = LabelDivider(frameB, text='(optional - repick entire peak list)')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')
        row += 1

        self.repickListPulldown = PulldownList(
            frameB,
            callback=self.setRePickPeakList,
            tipText=
            'Select which peak list to repick (new peaks will be put into a new peak list)'
        )
        self.repickListPulldown.grid(row=row, column=0, sticky='nw')

        texts = ['Repick Peak List']
        commands = [self.runRepickPeaks]
        self.runButton = ButtonList(
            frameB,
            texts=texts,
            commands=commands,
            expands=True,
            tipTexts=['Repick selected peak list into a new peak list.'])
        self.runButton.grid(row=row, column=1, columnspan=1, sticky='nsew')

        row += 1
        div = LabelDivider(frameB)
        row += 1
        texts = ['Separate Peaks']
        commands = [self.runPeakSeparator]
        self.runButton = ButtonList(frameB,
                                    texts=texts,
                                    commands=commands,
                                    expands=True,
                                    tipTexts=['Run peak search now'])
        self.runButton.grid(row=row, column=0, columnspan=2, sticky='nsew')

        self.setWidgetEntries()

        self.administerNotifiers(self.registerNotify)
Exemple #4
0
class RelaxationAnalysisPopup(BasePopup):

  def __init__(self, parent, *args, **kw):
    
    self.guiParent = parent
    self.t1List = None
    self.t2List = None
    self.noeList = None
    self.waiting = False
   
    BasePopup.__init__(self, parent, title="Relaxation Analyses", **kw)

    periodicTable = self.project.currentChemElementStore
    
    nitrogen = periodicTable.findFirstChemElement(elementSymbol='N')
    hydrogen = periodicTable.findFirstChemElement(elementSymbol='H')

  def body(self, guiFrame):

    self.geometry('700x840')
    
    guiFrame.expandGrid(1,0)
    
    # Top frame
    
    frame = Frame(guiFrame, grid=(0,0))
    frame.expandGrid(None,8)
    
    label = Label(frame, text=u' %s List:' % T1, grid=(0,0))
    self.t1Pulldown = PulldownList(frame, callback=self.selectT1List, grid=(0,1))
    
    label = Label(frame, text=u'  %s List:' % T2, grid=(0,2))
    self.t2Pulldown = PulldownList(frame, callback=self.selectT2List, grid=(0,3))
    
    label = Label(frame, text='  NOE List:', grid=(0,4))
    self.noePulldown = PulldownList(frame, callback=self.selectNoeList, grid=(0,5))
 
    label = Label(frame, text='  Spectrometer Freq (MHz):', grid=(0,6))
    self.sfEntry = FloatEntry(frame, grid=(0,7), text=600.00, width=6)

    UtilityButtonList(frame, grid=(0,9), sticky='e')
    
    # Tabs
    
    options = [u'%s vs %s Scatter' % (T1, T2),
               u'%s,%s & NOE Graphs' % (T1, T2) ,
               u'%s/%s Graph' % (T1, T2),
               u'%s Estimate Graph' % S2,
               'Options']
    self.tabbedFrame = TabbedFrame(guiFrame, options=options,
                                   callback=self.toggleTab, grid=(1,0))
    frameA, frameD, frameC, frameE, frameB = self.tabbedFrame.frames

    # T1 vs T2 Graph

    frameA.expandGrid(0,0)
 
    self.t1t2Graph = T1VersesT2Plot(frameA, grid=(0,0))

    # T1 & T2 Graph

    frameD.expandGrid(0,0)
    frameD.expandGrid(1,0)
    frameD.expandGrid(2,0)
 
    self.t1Graph = MeasurementPlot(frameD, T1, grid=(0,0))
    self.t2Graph = MeasurementPlot(frameD, T2, grid=(1,0))
    self.noeGraph = NoePlot(frameD, 'NOE', grid=(2,0))

    # T1 over T2 Graph

    frameC.expandGrid(0,0)
 
    self.t1t2GraphB = T1OverT2Plot(frameC, grid=(0,0))
    
    # Order params graph
    
    frameE.expandGrid(0,0)
    frameE.expandGrid(1,0)
    frameE.expandGrid(2,0)
    
    self.s2Graph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % S2,
                                 xLabel='Residue number', yLabel=S2,
                                 width=500, height=150, graphType='histogram', 
                                 xGrid=True, yGrid=False, grid=(0,0),
                                 dataColors=['#0000A0','#808000'],
                                 dataNames=['Isotropic',])

    self.teGraph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % Te,
                                 xLabel='Residue number', yLabel=u'%s (ps)' % Te,
                                 width=500, height=150, graphType='histogram',
                                 xGrid=True, yGrid=False, grid=(1,0),
                                 dataColors=['#008000',])
                                 
    self.rexGraph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % 'Rex',
                                  xLabel='Residue number', yLabel='Rex',
                                  width=500, height=150, graphType='histogram',
                                  xGrid=True, yGrid=False, grid=(2,0),
                                  dataColors=['#900000',])
    
    # Options
    
    frameB.expandGrid(4,2)
    
    frame = LabelFrame(frameB, text='Physical Params', grid=(0,0))
    frame.expandGrid(None,3)
   
    label = Label(frame, text=u'N-H bond length (\u00C5)', grid=(0,0))
    self.lenNhEntry = FloatEntry(frame, text=1.015, grid=(0,1), width=8)

    label = Label(frame, text=u'Internal correlation\ntime, \u03C4e (ps)', grid=(1,0))
    self.ictEntry = FloatEntry(frame, text=50.0, grid=(1,1), width=8)
    
    label = Label(frame, text=u'15N Chemical Shift\nAnisotopy,\u0394N (ppm)',
                  grid=(2,0))
    self.csaNEntry = FloatEntry(frame, text=-160.0, grid=(2,1), width=8)
    
    frame = LabelFrame(frameB, text=u'%s vs %s Scatter' % (T1, T2), grid=(1,0))
    
    label = Label(frame, text='Max cluster difference (ms):', grid=(0,0))
    self.clusterDictEntry = FloatEntry(frame, text=20.0, grid=(0,1), width=8)    

    label = Label(frame, text='Min cluster size:', grid=(1,0))
    self.clusterSizeEntry = FloatEntry(frame, text=5, grid=(1,1), width=8)    

    label = Label(frame, text=u'Min graph %s (ms):' % T1, grid=(2,0))
    self.minT1Entry = FloatEntry(frame, text=300.0, grid=(2,1), width=8)    

    label = Label(frame, text=u'Max graph %s (ms):' % T1, grid=(3,0))
    self.maxT1Entry = FloatEntry(frame, text=1000.0, grid=(3,1), width=8)    

    label = Label(frame, text=u'Min graph %s (ms):' % T2, grid=(4,0))
    self.minT2Entry = FloatEntry(frame, text=0.0, grid=(4,1), width=8)    

    label = Label(frame, text=u'Max graph %s (ms):' % T2, grid=(5,0))
    self.maxT2Entry = FloatEntry(frame, text=600.0, grid=(5,1), width=8)    
    
    frame = LabelFrame(frameB, text=u'%s Contours' % S2, grid=(0,1))
    frame.expandGrid(4,3)

    label = Label(frame, text='(Order Parameter Lines)',
                  grid=(0,0), gridSpan=(1,2))

    label = Label(frame, text='Min value:', grid=(1,0))
    self.minS2Entry = FloatEntry(frame, text=0.3, grid=(1,1), width=8)
    
    label = Label(frame, text='Max value:', grid=(2,0))
    self.maxS2Entry = FloatEntry(frame, text=1.0, grid=(2,1), width=8)
    
    label = Label(frame, text='Step:', grid=(3,0))
    self.stepS2Entry = FloatEntry(frame, text=0.1, grid=(3,1), width=8)

    frame = LabelFrame(frameB, text=u'\u03C4m Contours', grid=(1,1))
    frame.expandGrid(4,3)

    label = Label(frame, text='(Rotational Correlation Time Lines)',
                  grid=(0,0), gridSpan=(1,2))
                  
    label = Label(frame, text='Min value (ns):', grid=(1,0))
    self.minRctEntry = FloatEntry(frame, text=5.0, grid=(1,1), width=8)
    
    label = Label(frame, text='Max value (ns):', grid=(2,0))
    self.maxRctEntry = FloatEntry(frame, text=14.0, grid=(2,1), width=8)
    
    label = Label(frame, text='Step (ns):', grid=(3,0))
    self.stepRctEntry = FloatEntry(frame, text=1.0, grid=(3,1), width=8)

    # Bottom frame
 
    texts = [u'Show %s Table' % T1,u'Show %s Table' % T2, u'Estimate %s' % S2]
    commands = [self.showT1List, self.showT2List, self.mc]
    buttonList = ButtonList(guiFrame, grid=(2,0), texts=texts, commands=commands)

    # Update

    self.updateRelaxationLists()

    self.drawAfter()

    self.administerNotifiers(self.registerNotify)
  
  def open(self):
  
    self.updateRelaxationLists()
    self.drawAfter()
  
    BasePopup.open(self)
  
  def destroy(self):
  
    self.administerNotifiers(self.unregisterNotify)
    
    BasePopup.destroy(self)
  
  def getSanitisedParams(self):
  
     cDist = self.clusterDictEntry.get() or 0.0
     lenNh = max(min(self.lenNhEntry.get() or 1.015, 1.2), 0.8)
     ict = self.ictEntry.get() or 0.0
     csaN = self.csaNEntry.get() or -180.0
     
     if csaN > 0:
       csaN *= -1.0
     
     minS2 = max(min(self.minS2Entry.get() or 0.0, 0.9), 0.0)
     maxS2 = max(min(self.maxS2Entry.get() or 1.0, 1.0), 0.1)
     
     if minS2 > maxS2:
       maxS2, minS2 = minS2, maxS2
     
     stepS2 = max(self.stepS2Entry.get() or 0.1, (maxS2-minS2)/100)
     
     minRct = self.minRctEntry.get()
     maxRct = self.maxRctEntry.get()
     
     if minRct > maxRct:
       maxRct, minRct = minRct, maxRct
     
     stepRct = max(self.stepRctEntry.get() or 0.1, (maxRct-minRct)/100)
     
     cluster = max(abs(self.clusterSizeEntry.get() or 10), 1)
     
     minT1 = self.minT1Entry.get() or 300.0
     maxT1 = self.maxT1Entry.get() or 1000.0
     minT2 = self.minT2Entry.get() or 0.0
     maxT2 = self.maxT2Entry.get() or 600.0
   
     
     if minT1 < 0:
       minT1 = 0.0

     if minT2 < 0:
       minT2 = 0.0


     if maxT1 < 0:
       maxT1 = 0.0

     if maxT2 < 0:
       maxT2 = 0.0


     if minT1 > maxT1:
       minT1, maxT1 = maxT1, minT1
       
     if minT2 > maxT2:
       minT2, maxT2 = maxT2, minT2


     if minT1 == maxT1:
       maxT1 += 100
     if minT2 == maxT2:
       maxT2 += 100
     
     
     self.clusterSizeEntry.set(cluster)
     self.minT1Entry.set(minT1)
     self.maxT1Entry.set(maxT1)
     self.minT2Entry.set(minT2)
     self.maxT2Entry.set(maxT2)
     self.clusterDictEntry.set(cDist)
     self.lenNhEntry.set(lenNh)
     self.ictEntry.set(ict)
     self.csaNEntry.set(csaN)
     self.minS2Entry.set(minS2)
     self.maxS2Entry.set(maxS2)
     self.stepS2Entry.set(stepS2)
     self.minRctEntry.set(minRct)
     self.maxRctEntry.set(maxRct)
     self.stepRctEntry.set(stepRct)
     
     paramsS2 = (minS2, maxS2, stepS2)
     paramsRct = (minRct, maxRct, stepRct)
     tBounds = (minT1, maxT1, minT2, maxT2)

     return cluster, cDist, lenNh, ict, csaN,  paramsS2, paramsRct, tBounds

  def administerNotifiers(self, notifyFunc):
  
    for func in ('__init__', 'delete','setName'):
      for clazz in ('ccp.nmr.Nmr.T1List','ccp.nmr.Nmr.T2List'):
        notifyFunc(self.updateRelaxationLists,clazz, func)

    for func in ('__init__', 'delete', 'setValue'):
      notifyFunc(self.updateMeasurementAfter,'ccp.nmr.Nmr.T1', func)
      notifyFunc(self.updateMeasurementAfter,'ccp.nmr.Nmr.T2', func)

  def showT1List(self):
  
    if self.t1List:
      self.guiParent.editMeasurements(self.t1List)

  def showT2List(self):
  
    if self.t2List:
      self.guiParent.editMeasurements(self.t2List)

  def toggleTab(self, index):
  
    if index == 0:
      self.drawAfter()

  def updateMeasurementAfter(self, measurement):
  
    if measurement.parentList in (self.t1List, self.t2List):
      self.drawAfter()
  
  def updateRelaxationLists(self, obj=None):
  
    mLists = self.nmrProject.sortedMeasurementLists()
    

    # T1
    t1List = self.t1List
    t1Lists = [ml for ml in mLists if ml.className == 'T1List']

    index = 0
    names = []
    
    if t1Lists:
      if t1List not in t1Lists:
        t1List = t1Lists[0]
      
      index = t1Lists.index(t1List)
      names = [ml.name or 'List %d' % ml.serial for ml in t1Lists]
    
    else:
      t1List = None
      
    self.selectT1List(t1List)
    self.t1Pulldown.setup(names, t1Lists, index)


    # T2
    t2List = self.t2List
    t2Lists = [ml for ml in mLists if ml.className == 'T2List']
    
    index = 0
    names = []
    
    if t2Lists:
      if t2List not in t2Lists:
        t2List = t2Lists[0]
      
      index = t2Lists.index(t2List)
      names = [ml.name or 'List %d' % ml.serial for ml in t2Lists]
    
    else:
      t2List = None
      
    self.selectT2List(t2List)
    self.t2Pulldown.setup(names, t2Lists, index)
    
    
    # NOE
    noeList = self.noeList
    noeLists = [ml for ml in mLists if ml.className == 'NoeList']
    
    index = 0
    names = []
    
    if noeLists:
      if noeList not in noeLists:
        noeList = noeLists[0]
      
      index = noeLists.index(noeList)
      names = [ml.name or 'List %d' % ml.serial for ml in noeLists]
    
    else:
      noeList = None
      
    self.selectNoeList(noeList)
    self.noePulldown.setup(names, noeLists, index)


  def drawAfter(self):
  
    if self.waiting:
      return
      
    self.waiting = True
    self.after_idle(self.draw)

  def selectT1List(self, t1List):
  
    if t1List is not self.t1List:
      self.t1List = t1List
      self.sfEntry.set(t1List.sf)
      values = [m.value for m in t1List.measurements]
      values.sort()
      minVal = self.minT1Entry.get()
      maxVal = self.maxT1Entry.get()
      minVal0 = values[0]*MS_UNIT_MULTIPLIERS[t1List.unit]
      maxVal0 = values[-1]*MS_UNIT_MULTIPLIERS[t1List.unit]

      if minVal0 < minVal:
        self.minT1Entry.set(max(minVal0 - 100, 0))
      
      if maxVal0 > maxVal:
        self.maxT1Entry.set(maxVal0 + 100)
      
      self.drawAfter()
    
  
  def selectT2List(self, t2List):
  
    if t2List is not self.t2List:
      self.t2List = t2List
      self.sfEntry.set(t2List.sf)
      values = [m.value for m in t2List.measurements]
      values.sort()
      values.sort()
      minVal = self.minT2Entry.get()
      maxVal = self.maxT2Entry.get()
      minVal0 = values[0]*MS_UNIT_MULTIPLIERS[t2List.unit]
      maxVal0 = values[-1]*MS_UNIT_MULTIPLIERS[t2List.unit]

      if minVal0 < minVal:
        self.minT2Entry.set(max(minVal0 - 50, 0))
      
      if maxVal0 > maxVal:
        self.maxT2Entry.set(maxVal0 + 50)
      
      self.drawAfter()
  
  
  def selectNoeList(self, noeList):
  
    if noeList is not self.noeList:
      self.noeList = noeList
      self.sfEntry.set(noeList.sf)
      
      #self.drawAfter()

  def draw(self):
  
    params = self.getSanitisedParams()
    
    cSize, cDist, lenNh, ict, csaN, paramsS2, paramsRct, tBounds = params
 
    sf = abs(self.sfEntry.get() or 500.010)
    
    self.t1t2Graph.update(self.t1List, self.t2List, cSize, cDist, sf, lenNh,
                          ict, csaN, paramsS2, paramsRct, tBounds)
                          
    self.t1t2GraphB.update(self.t1List, self.t2List)
    
    self.t1Graph.update(self.t1List)
    self.t2Graph.update(self.t2List)
    self.noeGraph.update(self.noeList)
      
    self.waiting = False


  def mc(self):
  
    sf = abs(self.sfEntry.get() or 500.010)
    
    if not self.t1List and self.t2List:
      return
    
    chains = set([])
    t1t2Points = {}
    resonancesT1 = {}
    resonancesNoe = {}
    residueResonances = {}

    t1Unit = MS_UNIT_MULTIPLIERS[self.t1List.unit]
    t2Unit = MS_UNIT_MULTIPLIERS[self.t2List.unit]
    
    
    if self.noeList:
      for noe in self.noeList.measurements:
        for resonance in noe.resonances:
          resonancesNoe[resonance] = noe
    
    for t1 in self.t1List.measurements:
      resonancesT1[t1.resonance] = t1
       
    for t2 in self.t2List.measurements:
      resonance = t2.resonance
      if not resonance.resonanceSet:
        continue
      
      residue = resonance.resonanceSet.findFirstAtomSet().findFirstAtom().residue
      
      t1 = resonancesT1.get(resonance)
      noe = resonancesNoe.get(resonance)
      
      if t1 and noe:
        t1t2Points[residue] = 1e-3*t1Unit*t1.value, 1e-3*t2Unit*t2.value, noe.value
        chains.add(residue.chain)
        residueResonances[residue] = resonance
      
      if t1:
        t1t2Points[residue] = 1e-3*t1Unit*t1.value, 1e-3*t2Unit*t2.value, None
        chains.add(residue.chain)
        residueResonances[residue] = resonance
     
    for chain in chains:
      residues = chain.sortedResidues()
      t1Values = []
      t2Values = []
      noeValues = []
      n = len(residues)
      n2 = n-1
      jj = range(n)
      s2Best = [0.0] * n
      teBest = [0.0] * n
      rexBest = [0.0] * n
      
      print ''
      
      for residue in residues:
        t1,t2, noe = t1t2Points.get(residue, (None, None, None))
        t1Values.append(t1)
        t2Values.append(t2)
        noeValues.append(noe)
      
      t1s = [v for v in t1Values if v]
      t2s = [v for v in t2Values if v]
      noes = [v for v in noeValues if v]
      
      m = len(t1s)
      
      t1 = sum(t1s)/float(m)
      t2 = sum(t2s)/float(m)
      noe = sum(noes)/float(m)
      
      t12 = [v/t2s[i] for i, v in enumerate(t1s) if v]
      t12m = sum(t12)/float(len(t12))
      deltas = [abs(v-t12m)/t12m for v in t12]
      w = [1.0/(v*v) for v in deltas]
      
      t1 = sum([ t1s[j]*w[j] for j in range(m)])/sum(w)
      t2 = sum([ t2s[j]*w[j] for j in range(m)])/sum(w)
      
      if noes:
        noe = sum([ noes[j]*w[j] for j in range(m)])/sum(w)
      else:
        noe = None

      i, ensemble = self.fitT1T2(t1, t2, noe, sf, tmFix=None, teFix=None, s2Fix=None,
                                 tmMin=1e-9, tmMax=100e-9, teMin=1e-12, teMax=1e-10,
                                 rexFix=0.0)
      ensemble.sort()
      score, s2, te0, tm0, rex, t1t, t2t, noet = ensemble[0]
 
      data = (s2, te0*1e12, tm0*1e9, rex, t1, t1t, t2, t2t, noe or 0.0, noet,  score, i)
      print 'Mean A S2:%5.3f Te:%5.1f Tm:%5.3f Rex:%5.3f T1:%5.3f %5.3f T2:%5.3f %5.3f NOE:%5.3f %5.3f %e %6d' % data
      
      rexCheck = 999 # 1.40 * t1/t2
       
      # Prior is mean, then region 
   
      for j in jj:
        t1 = t1Values[j]
        t2 = t2Values[j]
        noe = noeValues[j]
        if t1 is None:
          continue
         
        residue = residues[j]
        print '%3d%s' %  (residue.seqCode, residue.ccpCode),
        
        i, ensemble = self.fitT1T2(t1, t2, noe, sf, tmFix=tm0, teFix=None, s2Fix=None,
                                   tmMin=tm0*0.1, tmMax=tm0*5, teMin=te0/100, teMax=te0*20,
                                   rexFix=0.0, rexMax=15.0)
        ensemble.sort()
        score, s2, te, tm, rex, t1t, t2t, noet = ensemble[0]
        
        if s2 > 0.995:
          i, ensemble = self.fitT1T2(t1, t2, noe, sf, tmFix=tm0, teFix=None, s2Fix=None,
                                     teMin=te/10, teMax=te*10,
                                     rexFix=None, rexMax=15.0)
          ensemble.sort()
          score, s2, te, tm, rex, t1t, t2t, noet = ensemble[0]
         
          
        teBest[j] = te
        s2Best[j] = s2
        rexBest[j] = rex
 
        data = (s2, te*1e12, tm*1e9, rex, t1, t1t, t2, t2t, noe or 0.0, noet, score, i)
        print 'S2:%5.3f Te:%5.1f Tm:%5.3f Rex:%5.3f T1:%5.3f %5.3f T2:%5.3f %5.3f NOE:%5.3f %5.3f %e %6d' % data

      dataSet1 = []
      dataSet2 = []
      dataSet3 = []
      for j in jj:
        residue = residues[j]
        resonance = residueResonances.get(residue)
        
        if not resonance:
          continue
        
        dataSet1.append((residue.seqCode, s2Best[j]))
        dataSet2.append((residue.seqCode, teBest[j]*1e9))
        dataSet3.append((residue.seqCode, rexBest[j]))
        
      self.s2Graph.update([dataSet1,])
      self.teGraph.update([dataSet2,])
      self.rexGraph.update([dataSet3,])
      
      self.tabbedFrame.select(3)

  def fitT1T2(self, t1, t2, noe, sf, tmFix=None, teFix=None, s2Fix=None,
              tmMin=1e-9, tmMax=100e-9, teMin=1e-12, teMax=1e-9,
              rexFix=None, rexMax=15.0, niter=10000):
    
    # Could have multiple sf
    
    rNH = 1.015
    csaN = 160*1e-6 # 160 ppm
    omegaH = sf * 2 * PI * 1e6 # Rad/s
    omegaN = omegaH * GAMMA_N/GAMMA_H
    gammaHN = GAMMA_H/GAMMA_N
     
    A = REDUCED_PERM_VACUUM * REDUCED_PLANK * GAMMA_N * GAMMA_H * 1e30 # Cubic Angstrom adjust
    A /= rNH**3.0
    A = A*A/4.0
    C = omegaN * omegaN * csaN * csaN 
    C /= 3.0
    
    # Init params
    if s2Fix is None:
      s2Start = [x*0.05 for x in range(1,20)]
    else:
      s2Start = [s2Fix,]
    
    if teFix is None:
      teStart = [x*1e-12 for x in [10,30,70,100,300,700,1000]]
    else:
      teStart = [teFix,]
    
    if tmFix is None:
      tmStart = [x*1e-9 for x in range(1,30)]
    else:
      tmStart = [tmFix,]
    
    if rexFix is None:
      rexStart = [float(x) for x in range(int(rexMax))]
    else:
      rexStart = [rexFix,]
    
    # Init ensemble of solutions
    ensemble = []
    for s2 in s2Start:
      for te in teStart:
        for tm in tmStart:
          for rex in rexStart:
             ensemble.append((None, s2, te, tm, rex))
   
    
    # Init scores
    for k, (score, s2, te, tm, rex) in enumerate(ensemble):
      jH   = getSpectralDensity(s2, tm, te, omegaH)
      jN   = getSpectralDensity(s2, tm, te, omegaN)
      jHpN = getSpectralDensity(s2, tm, te, omegaH+omegaN)
      jHmN = getSpectralDensity(s2, tm, te, omegaH-omegaN)
      j0   = getSpectralDensity(s2, tm, te, 0.0)
 
      r1 = A*( (3*jN) + (6*jHpN) + jHmN ) + C*jN
      r2 = 0.5*A*( (4*j0) + (3*jN) + (6*jHpN) + (6*jH) + jHmN ) + C*( 2*j0/3.0 + 0.5*jN ) + rex
 
      t1p = 1.0/r1
      t2p = 1.0/r2
 
 
      d1 = (t1p-t1)/t1
      d2 = (t2p-t2)/t2
 
      score = (d1*d1) + (d2*d2)
      
      if noe is None:
        noep = 0.0
        
      else:
        noep = 1.0 + ( A * gammaHN * t1 * ((6*jHpN)-jHmN) )
        dn = (noep-noe)/2.0
        score += (dn*dn) 
      
      ensemble[k] = (score, s2, te, tm, rex, t1p, t2p, noep)
      
      # Matrix
      # 
      # Pred    Jh        
      # R1
      # R2
      # NOE
      #   r = 1.0/rct + 1.0/ict 
      #   t = 1.0/r
      #   j = (s2*rct) / (1.0 + w*w*rct*rct)
      #   j += ((1.0-s2)*t) / (1.0 + w*w*t*t)
      #       
      #   return j*0.4
    
    ensemble.sort()
    ensemble = ensemble[:10]
    ensembleSize = len(ensemble)
         
    bestScore = 1e99
    
    for i in xrange(niter):
 
      f = i/float(niter)
      f = exp(-10.0*f)
      # Mutate
 
      ensemble.sort()
      prevScore, s2, te, tm, rex, t1p, t2p, noep = ensemble[-1] #Biggest is worst
 
      if ensemble[0][0] < 1e-10:
        break
 
      if not s2Fix:
        #d = ((random() + 0.618 - 1.0) * f) + 1.0
        d = ((random() - 0.382) * f) + 1.0
        s2 = max(0.0, min(1.0, s2*d))
 
      if not tmFix:
        d = ((random() - 0.382) * f) + 1.0
        tm = max(tmMin, min(tmMax, tm*d))
      
      if not teFix:
        d = ((random() - 0.382) * f) + 1.0 
        te = max(teMin, min(teMax, te*d))

      d = ((random() - 0.382) * f) + 1.0 
      rex = max(0.0, min(rexMax, rex*d))
 
      jH   = getSpectralDensity(s2, tm, te, omegaH)
      jN   = getSpectralDensity(s2, tm, te, omegaN)
      jHpN = getSpectralDensity(s2, tm, te, omegaH+omegaN)
      jHmN = getSpectralDensity(s2, tm, te, omegaH-omegaN)
      j0   = getSpectralDensity(s2, tm, te, 0.0)

      r1 = A*( (3*jN) + (6*jHpN) + jHmN ) + C*jN
      r2 = 0.5*A*( (4*j0) + (3*jN) + (6*jHpN) + (6*jH) + jHmN ) + C*( 2*j0/3.0 + 0.5*jN ) + rex
 
      t1p = 1.0/r1
      t2p = 1.0/r2
 
      d1 = (t1p-t1)/t1
      d2 = (t2p-t2)/t2
 
      score = (d1*d1) + (d2*d2)
      if noe is None:
        noep = 0.0
      else:
        noep = 1.0 + ( A * gammaHN * t1 * ((6*jHpN)-jHmN) )
        dn = (noep-noe)/2.0
        score += (dn*dn) 
      
      ratio = exp(prevScore-score)
                      
      if ratio > 1.0: # random():
        ensemble[-1] = (score, s2, te, tm, rex, t1p, t2p, noep)
      else:
        k = randint(0,ensembleSize-1)
        score, s2, te, tm, rex, t1p, t2p, noep = ensemble[k]
        ensemble[-1] = (score, s2, te, tm, rex, t1p, t2p, noep)
    
      
      if score < bestScore:
        bestScore = score
    
    #print bestScore, ', '.join(['%.3e' % x[0] for x in ensemble])
        
    return i, ensemble
Exemple #5
0
class ExtendNmrFrame(Frame):
    def __init__(self, guiParent, basePopup, project=None):
        # Base popup required to handle notification of data model changes
        # e.g. new peak lists, so that the GUI can update to the latest
        # state
        self.basePopup = basePopup
        self.guiParent = guiParent

        # FIXME JMCI
        # need to work through this far more carefully
        self.project = project

        # shortcuts to this layer
        self.basePopup.frameShortcuts['Task'] = self

        # shortcuts to layer below. We should set these in the
        # initMethod methods
        self.frameShortcuts = {}

        # TODO understand what these are doing
        self.registerNotify = basePopup.registerNotify
        self.unregisterNotify = basePopup.unregisterNotify

        Frame.__init__(self, guiParent)

        self.grid_rowconfigure(1, weight=1)
        self.grid_columnconfigure(0, weight=1)

        # Logos. Code nicked from ExtendNMR GUI
        ccpnDir = getTopDirectory()

        imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images')

        # basically nicked from Extend-NMR
        softwareOpts = [
            'Test1Task', 'ARIA 2', 'Auremol', 'CING', ' ECI ', 'HADDOCK',
            ' ISD ', 'PRODECOMP'
        ]

        self.tabbedFrame = TabbedFrame(guiParent,
                                       options=softwareOpts,
                                       toggleOff=False,
                                       selected=0)
        self.tabbedFrame.grid(row=1, column=0, sticky='nsew')

        frames = self.tabbedFrame.frames

        # Logos
        ccpnDir = getTopDirectory()

        imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images')

        imageFile = os.path.join(imageDir, 'Fp6Logo.gif')
        self.fp6Logo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CingLogo.gif')
        self.cingLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AriaLogo.gif')
        self.ariaLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'IsdLogo.gif')
        self.isdLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'HaddockLogo.gif')
        self.haddockLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AuremolLogo.gif')
        self.auremolLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CcpnLogo.gif')
        self.ccpnLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'ProdecompLogo.gif')
        self.prodecompLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MddLogo.gif')
        self.mddLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'BrukerLogo.gif')
        self.brukerLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MsdLogo.gif')
        self.msdLogo = Tkinter.PhotoImage(file=imageFile)

        # don't know what this does
        self.updateFuncs = []
        self.projButtons = []

        # basically nicked from Extend-NMR
        self.initTest1(frames[0])
        self.initAria(frames[1])
        self.initAuremol(frames[2])
        self.initCing(frames[3])
        #self.initEci(frames[4])
        #self.initHaddock(frames[5])
        self.initIsd(frames[6])
        self.initProdecomp(frames[7])

    def initTest1(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        # FIXME JMCI

        # Provide the basePopup for navigation purposes right now However,
        # there is a strong case for not making the method-specific Frames
        # dependent on the master. It might therefore be better to pass
        # the critical information directly, rather than passing a
        # reference to the basePopup which can then be used to extract it
        # indirectly

        test1Frame = Test1Frame(frame, self.basePopup)
        test1Frame.grid(row=1, column=0, sticky='nsew')

        self.frameShortcuts['Test1'] = test1Frame
        #self.projButtons.extend(cingFrame.buttonBar.buttons)
        self.updateFuncs.append(test1Frame.updateAll)

    def initAria(self, frame):

        welcomeMessage = \
        """ARIA Version 2.2. Authors: Benjamin Bardiaux, Michael Habeck,
Jens Linge, Therese Malliavin, Sean O'Donoghue, Wolfgang Rieping,
and Michael Nilges.

Rieping W., Habeck M., Bardiaux B., Bernard A., Malliavin T.E.,
Nilges M.(2007) ARIA2: automated NOE assignment and data
integration in NMR structure calculation. Bioinformatics 23:381-382"""

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        canvas = Tkinter.Canvas(frame, width=700, height=114, bg='#FFFFFF')
        canvas.grid(row=0, column=0, sticky='ew')
        canvas.create_image(0, 0, anchor='nw', image=self.ariaLogo)
        canvas.create_text(250, 10, anchor='nw', text=welcomeMessage)

        ariaFrame = AriaFrame(frame, self)
        ariaFrame.grid(row=1, column=0, sticky='nsew')

        self.frameShortcuts['ARIA'] = ariaFrame
        #self.projButtons.extend(ariaFrame.buttons)
        self.updateFuncs.append(ariaFrame.updateAll)

    def initAuremol(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        auremolFrame = AuremolFrame(frame, self.project)
        auremolFrame.grid(row=0, column=0, sticky='nsew')

        self.frameShortcuts['AUREMOL'] = auremolFrame
        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(auremolFrame.updateAll)

    def initCing(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        canvas = Tkinter.Canvas(frame, width=702, height=77)
        canvas.grid(row=0, column=0)
        canvas.create_image(0, 0, anchor='nw', image=self.cingLogo)

        cingFrame = CingFrame(frame, self.project)
        cingFrame.grid(row=1, column=0, sticky='nsew')

        self.frameShortcuts['CING'] = cingFrame
        #self.projButtons.extend(cingFrame.buttonBar.buttons)
        self.updateFuncs.append(cingFrame.updateAll)

    def initEci(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)
        frame.parent = self  # For notifiers

        canvas = Tkinter.Canvas(frame, width=753, height=73, bg='#FFFFFF')
        canvas.grid(row=0, column=0)
        canvas.create_image(10, 10, anchor='nw', image=self.msdLogo)

        eciFrame = EntryCompletionFrame(frame, basePopup=self)
        eciFrame.grid(row=1, column=0, sticky='nsew')

        self.frameShortcuts['ECI'] = eciFrame
        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(eciFrame.updateAll)

    def initHaddock(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)
        frame.parent = self  # For notifiers

        canvas = Tkinter.Canvas(frame, width=753, height=92)
        canvas.grid(row=0, column=0)
        canvas.create_image(0, 0, anchor='nw', image=self.haddockLogo)

        haddockFrame = HaddockFrame(frame, self.project)
        haddockFrame.grid(row=1, column=0, sticky='nsew')

        self.frameShortcuts['HADDOCK'] = haddockFrame
        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(haddockFrame.updateAll)

    def initIsd(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        canvas = Tkinter.Canvas(frame, width=700, height=91, bg='#FFFFFF')
        canvas.grid(row=0, column=0, sticky='ew')
        canvas.create_image(0, 0, anchor='nw', image=self.isdLogo)

        isdFrame = IsdFrame(frame, self.project)
        isdFrame.grid(row=1, column=0, sticky='nsew')

        self.frameShortcuts['ISD'] = isdFrame
        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(isdFrame.updateAll)

    def initProdecomp(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        canvas = Tkinter.Canvas(frame, width=700, height=90, bg='#FFFFFF')
        canvas.grid(row=0, column=0)
        canvas.create_image(0, 0, anchor='nw', image=self.prodecompLogo)

        prodecompFrame = ProdecompFrame(frame,
                                        basePopup=self,
                                        ccpnProject=self.project)
        prodecompFrame.grid(row=1, column=0, sticky='nsew')

        self.frameShortcuts['PRODECOMP'] = prodecompFrame
        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(prodecompFrame.updateAll)

    # need to understand this method a little bit better
    def administerNotifiers(self, notifyFunc):

        for func in ('__init__', 'delete', 'setName'):
            notifyFunc(self.updateAllAfter, 'ccp.nmr.Nmr.Experiment', func)
            notifyFunc(self.updateAllAfter, 'ccp.nmr.Nmr.DataSource', func)

    def updateAllAfter(self, obj):

        self.after_idle(self.updateAll)

    def updateAll(self, project=None):

        if project:
            self.project = project
            self.nmrProject = project.currentNmrProject

            if not self.nmrProject:
                self.nmrProject = project.newNmrProject(name=project.name)

        if not self.project:
            return

    def quit(self):

        self.guiParent.parent.destroy()

    def destroy(self):

        self.administerNotifiers(self.basePopup.unregisterNotify)
        Frame.destroy(self)
Exemple #6
0
  def __init__(self, guiParent, ccpnProject=None, **kw):

    self.guiParent = guiParent
    self.project = ccpnProject
    self.spectrum = None
    self.peakMode = 0
    
    if ccpnProject:
      self.nmrProject = ccpnProject.currentNmrProject
    else:
      self.nmrProject = None
    
    Frame.__init__(self, guiParent, **kw)
  
    self.expandGrid(0,0)

    options = ['Peak Picking',] #,'About Auremol' 'NOE assignment','Homology Modelling',]
    self.tabbedFrame = TabbedFrame(self, options=options)
    self.tabbedFrame.grid(row=0,column=0,sticky='nsew')
    frameA = self.tabbedFrame.frames[0]
    
    #frameC.grid_columnconfigure(0, weight=1)
    #frameC.grid_rowconfigure(0, weight=1)
    #frameD.grid_columnconfigure(0, weight=1)
    #frameD.grid_rowconfigure(0, weight=1)
    
    #
    # Frame A
    #
    frameA.expandGrid(2,0)
    frameA.expandGrid(3,0)
    frameA.expandGrid(4,0)
    frameA.expandGrid(5,0)
    
    
    frame = Frame(frameA, grid=(0,0))
    frame.expandGrid(0,4)
    
    label = Label(frame, text='Spectrum:', grid=(0,0))
    self.spectrumPulldown = PulldownList(frame, self.changeSpectrum, grid=(0,1))
    
    label = Label(frame, text='  Use Peak Sign:', grid=(0,2))
    self.peakModePulldown = PulldownList(frame, self.changePeakMode, texts=PEAK_MODES,
                                         objects=[0,1,2], grid=(0,3))
    
    
    frame = Frame(frameA, grid=(1,0))
    frame.expandGrid(0,4)
    
    label = Label(frame, text='Integration Depth (Relative to max):', grid=(1,0))
    self.segLevelEntry = FloatEntry(frame, text=0.1, grid=(1,1), width=8)
    
    label = Label(frame, text='Threshold (Threshold only):', grid=(1,3))
    self.thresholdEntry = IntEntry(frame, text=100000, grid=(1,4), width=8)
    
    label = Label(frame, text='Keep Peaks (Adaptive only):', grid=(1,5))
    self.keepPeakEntry = IntEntry(frame, text=4000, grid=(1,6), width=8)
    
    texts = ['Threshold\nPeak Pick','Adaptive\nPeak Pick']
    commands = [self.pickThreshold, self.pickAdaptive]
    self.buttons = ButtonList(frameA, texts=texts, commands=commands,
                              grid=(2,0),  sticky='NSEW')
    
    frame = Frame(frameA, grid=(3,0))
    frame.expandGrid(0,0)
    frame = Frame(frameA, grid=(4,0))
    frame.expandGrid(0,0)
    frame = Frame(frameA, grid=(5,0))
    frame.expandGrid(0,0)
     
    #
    # About
    """
    frameB.expandGrid(4,0)

    label = Label(frameB, text='References', font='Helvetica 12 bold')
    label.grid(row=0, column=0, sticky='w')
    
    text = 
    * Gronwald W, Brunner K, Kirchhofer R, Nasser A, Trenner J, Ganslmeier B,
    Riepl H, Ried A, Scheiber J, Elsner R, Neidig K-P, Kalbitzer HR
    AUREMOL, a New Program for the Automated Structure Elucidation of Biological Macromolecules
    Bruker Reports 2004; 154/155: 11-14

    * Ried A, Gronwald W, Trenner JM, Brunner K, Neidig KP, Kalbitzer HR
    Improved simulation of NOESY spectra by RELAX-JT2 including effects of J-coupling,
    transverse relaxation and chemical shift anisotrophy
    J Biomol NMR. 2004 Oct;30(2):121-31

    * Gronwald W, Moussa S, Elsner R, Jung A, Ganslmeier B, Trenner J, Kremer W, Neidig KP, Kalbitzer HR
    Automated assignment of NOESY NMR spectra using a knowledge based method (KNOWNOE)
    J Biomol NMR. 2002 Aug;23(4):271-87

    * Gronwald W, Kirchhofer R, Gorler A, Kremer W, Ganslmeier B, Neidig KP, Kalbitzer HR
    RFAC, a program for automated NMR R-factor estimation
    J Biomol NMR. 2000 Jun;17(2):137-51
    
    label = Label(frameB, text=text)
    label.grid(row=1, column=0, sticky='w')
    """
   
    #
    # Frame C
    #

    
    #
    # Frame D
    #

  
    self.updateAll()
Exemple #7
0
  def __init__(self, guiParent, basePopup):

    self.guiParent = guiParent
    self.basePopup = basePopup

    # selection hash. This needs to be stored so that we can
    # refresh with the same criteria
    self.select = None

    # should the screen autorefresh
    self.autoRefresh = False
    
    # add this to shortcuts to ease navigation    
    self.basePopup.frameShortcuts['Tasks'] = self

    #self.registerNotify=basePopup.registerNotify
    #self.unregisterNotify=basePopup.unregisterNotify

    #self.frames = []

    # FIXME JMCI

    # This frame is specific for a single repository so we need a
    # method for identifying one from the whole set (or could have
    # subtabs)

    Frame.__init__(self, guiParent)
  
    # set up the grid

    self.grid_columnconfigure(0, weight=0, minsize=20)
    self.grid_columnconfigure(1, weight=1, minsize=30)
    self.grid_columnconfigure(2, weight=0, minsize=40)

    self.grid_rowconfigure(0, weight=0, minsize=20)
    self.grid_rowconfigure(1, weight=0, minsize=10)
    self.grid_rowconfigure(2, weight=0, minsize=0)
    self.grid_rowconfigure(3, weight=0, minsize=0)
    self.grid_rowconfigure(4, weight=0, minsize=0)
    self.grid_rowconfigure(5, weight=1, minsize=0)
    self.grid_rowconfigure(6, weight=0, minsize=10)
    self.grid_rowconfigure(7, weight=0, minsize=10)


    initial_cols = ['ID','Task','User','Status']
    self.task_matrix = ScrolledMatrix(self, headingList=initial_cols, initialRows=15,
                                      doubleCallback=self.goto_task_tab)

    # Filters for narrowing down tasks. should probably code this
    # specifically inside this package    
    #self.filter = FilterFrame(self, self.basePopup, text='Filter')
    self.filter = TaskFilterFrame(self, self.basePopup, text='Filter')

    # Frame for controlling the main client side daemon
    # seems to be a problem. add a simple button for now
    opts = ['Client','Server']
    self.daemonFrame = TabbedFrame(self, options=opts,
                                   toggleOff=False, selected=0)

    self.daemonSwitchLabel = Label(self, text= 'Task Daemon')
    self.daemonSwitch = RadioButtons(self, ['on', 'off'], select_callback=self.set_daemon, selected_index = 1)

    sel = 1
    if self.autoRefresh:
      sel = 0
    self.autoRefreshSwitchLabel = Label(self, text= 'Auto Refresh')
    self.autoRefreshSwitch = RadioButtons(self, ['on', 'off'], select_callback=self.set_refresh, selected_index = sel)

    self.label_rep = Label(self, text='', font='Helvetica16')

    # set up a loop
    self.refresh()
Exemple #8
0
  def body(self, guiFrame):
  
    guiFrame.grid_columnconfigure(0, weight=1)
    guiFrame.grid_rowconfigure(0, weight=1)

    options = ['Parameters','Restraints','Alignment Media & Tensors','About Meccano']
    tabbedFrame = TabbedFrame(guiFrame, options=options)
    tabbedFrame.grid(row=0, column=0, sticky='nsew')
    
    frameA, frameB, frameC, frameD = tabbedFrame.frames
    frameA.grid_columnconfigure(1, weight=1)
    frameA.grid_rowconfigure(13, weight=1)
    frameB.grid_columnconfigure(1, weight=1)
    frameB.grid_rowconfigure(1, weight=1)
    frameC.grid_columnconfigure(0, weight=1)
    frameC.grid_rowconfigure(1, weight=1)
    frameD.grid_columnconfigure(0, weight=1)
    frameD.grid_rowconfigure(0, weight=1)
    
    texts = ['Run MECCANO!']
    commands = [self.runMeccano]
    bottomButtons = createDismissHelpButtonList(guiFrame, texts=texts,
                                                commands=commands, expands=True)
    bottomButtons.grid(row=1, column=0, sticky='ew')

    if not Meccano:
      bottomButtons.buttons[0].disable()
  
    # Parameters
        
    row = 0
    label = Label(frameA, text='Calculation Run:')
    label.grid(row=row,column=0,sticky='w')
    self.runPulldown = PulldownList(frameA, callback=self.selectRun)
    self.runPulldown.grid(row=row,column=1,sticky='w')
    
    row += 1    
    label = Label(frameA, text='Shift List (for CO):')
    label.grid(row=row,column=0,sticky='w')
    self.shiftListPulldown = PulldownList(frameA, callback=self.selectShiftList)
    self.shiftListPulldown.grid(row=row,column=1,sticky='w')
           
    row += 1    
    label = Label(frameA, text='Keep Copy of Used Shifts:')
    label.grid(row=row,column=0,sticky='w')
    self.toggleCopyShifts = CheckButton(frameA)
    self.toggleCopyShifts.grid(row=row,column=1,sticky='w')
    self.toggleCopyShifts.set(True)
        
    row += 1    
    label = Label(frameA, text='Molecular System:')
    label.grid(row=row,column=0,sticky='w')
    self.molSystemPulldown = PulldownList(frameA, callback=self.selectMolSystem)
    self.molSystemPulldown.grid(row=row,column=1,sticky='w')
        
    row += 1    
    label = Label(frameA, text='Chain:')
    label.grid(row=row,column=0,sticky='w')
    self.chainPulldown = PulldownList(frameA, callback=self.selectChain)
    self.chainPulldown.grid(row=row,column=1,sticky='w')
    self.chainPulldown.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='First Peptide Plane:')
    label.grid(row=row,column=0,sticky='w')
    self.firstResEntry = IntEntry(frameA, text=None, width=8)
    self.firstResEntry.grid(row=row,column=1,sticky='w')
    self.firstResEntry.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='Last Peptide Plane:')
    label.grid(row=row,column=0,sticky='w')
    self.lastResEntry = IntEntry(frameA, text=None, width=8)
    self.lastResEntry.grid(row=row,column=1,sticky='w')
    self.lastResEntry.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='Max Num Optimisation Steps:')
    label.grid(row=row,column=0,sticky='w')
    self.maxOptStepEntry = IntEntry(frameA, text=500, width=8)
    self.maxOptStepEntry.grid(row=row,column=1,sticky='w')
    self.maxOptStepEntry.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='Num Optimisation Peptide Planes:')
    label.grid(row=row,column=0,sticky='w')
    self.numOptPlaneEntry = IntEntry(frameA, text=2, width=8)
    self.numOptPlaneEntry.grid(row=row,column=1,sticky='w')
    self.numOptPlaneEntry.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='Min Num Optimisation Hits:')
    label.grid(row=row,column=0,sticky='w')
    self.numOptHitsEntry = IntEntry(frameA, text=5, width=8)
    self.numOptHitsEntry.grid(row=row,column=1,sticky='w')
    self.numOptHitsEntry.bind('<Leave>', self.updateRunParams) 

    row += 1    
    label = Label(frameA, text='File Name Prefix:')
    label.grid(row=row,column=0,sticky='w')
    self.pdbFileEntry = Entry(frameA, text='Meccano', width=8)
    self.pdbFileEntry.grid(row=row,column=1,sticky='w')
    self.pdbFileEntry.bind('<Leave>', self.updateRunParams) 
           
    row += 1    
    label = Label(frameA, text='Write Output File (.out):')
    label.grid(row=row,column=0,sticky='w')
    self.toggleWriteOutFile = CheckButton(frameA)
    self.toggleWriteOutFile.grid(row=row,column=1,sticky='w')
    self.toggleWriteOutFile.set(False)
    self.toggleWriteOutFile.bind('<Leave>', self.updateRunParams) 
           
    row += 1    
    label = Label(frameA, text='Write PDB File (.pdb):')
    label.grid(row=row,column=0,sticky='w')
    self.toggleWritePdbFile = CheckButton(frameA)
    self.toggleWritePdbFile.grid(row=row,column=1,sticky='w')
    self.toggleWritePdbFile.set(True)
    self.toggleWritePdbFile.bind('<Leave>', self.updateRunParams) 
    
    if not Meccano:
      row += 1    
      label = Label(frameA, text='The Meccano executable is not available (it needs to be compiled)', fg='red')
      label.grid(row=row,column=0,columnspan=2,sticky='w')

    # Restraints
    
    label = Label(frameB, text='Constraint Set:')
    label.grid(row=0,column=0,sticky='w')
    
    self.constraintSetPulldown = PulldownList(frameB, callback=self.selectConstraintSet)
    self.constraintSetPulldown.grid(row=0,column=1,sticky='w')
    
    self.alignMediumPulldown= PulldownList(self, callback=self.setAlignMedium)
    
    headingList = ['#','List Type','Use?','Alignment\nMedium','Num\nRestraints']
    editWidgets      = [None,None,None,self.alignMediumPulldown,None]
    editGetCallbacks = [None,None,self.toggleUseRestraints,self.getAlignMedium,None]
    editSetCallbacks = [None,None,None,self.setAlignMedium,None]
    self.restraintMatrix = ScrolledMatrix(frameB,
                                          headingList=headingList,
                                          editSetCallbacks=editSetCallbacks,
                                          editGetCallbacks=editGetCallbacks, 
                                          editWidgets=editWidgets,
                                          callback=None,
                                          multiSelect=True)
    self.restraintMatrix.grid(row=1,column=0,columnspan=2,sticky='nsew')
    
    
    # Alignment Media
    
    div = LabelDivider(frameC,text='Alignment Media')
    div.grid(row=0,column=0,sticky='ew')
    
    self.mediumNameEntry = Entry(self, returnCallback=self.setMediumName)
    self.mediumDetailsEntry = Entry(self, returnCallback=self.setMediumDetails)
    
    headingList = ['#','Name','Details','Static Tensor','Dynamic Tensor']
    editWidgets      = [None, self.mediumNameEntry, self.mediumDetailsEntry, None, None]
    editGetCallbacks = [None, self.getMediumName, self.getMediumDetails, None, None]
    editSetCallbacks = [None, self.setMediumName, self.setMediumDetails, None, None]
    self.mediaMatrix = ScrolledMatrix(frameC,
                                      headingList=headingList,
                                      editSetCallbacks=editSetCallbacks,
                                      editGetCallbacks=editGetCallbacks, 
                                      editWidgets=editWidgets,
                                      callback=self.selectAlignMedium,
                                      multiSelect=True)
                                 
    self.mediaMatrix.grid(row=1,column=0,sticky='nsew')
     
    
    texts = ['Add Alignment medium','Remove Alignment Medium']
    commands = [self.addAlignMedium,self.removeAlignMedium]
    buttonList = ButtonList(frameC, texts=texts, commands=commands, expands=True)
    buttonList.grid(row=2,column=0,sticky='nsew')
    
    self.editAxialEntry = FloatEntry(self, returnCallback=self.setAxial)
    self.editRhombicEntry = FloatEntry(self, returnCallback=self.setRhombic)
    self.editAlphaEulerEntry = FloatEntry(self, returnCallback=self.setEulerAlpha)
    self.editBetaEulerEntry = FloatEntry(self, returnCallback=self.setEulerBeta)
    self.editGammaEulerEntry = FloatEntry(self, returnCallback=self.setEulerGamma)
    
    
    div = LabelDivider(frameC,text='Alignment Tensors')
    div.grid(row=3,column=0,sticky='ew')
    
    headingList = ['Type', u'Axial (\u03B6)',u'Rhombic (\u03B7)',
                   u'Euler \u03B1',u'Euler \u03B2',u'Euler \u03B3']
    editWidgets      = [None,self.editAxialEntry,
                        self.editRhombicEntry,self.editAlphaEulerEntry,
                        self.editBetaEulerEntry,self.editGammaEulerEntry]
    editSetCallbacks = [None,self.setAxial,self.setRhombic,
                        self.setEulerAlpha,self.setEulerBeta,self.setEulerGamma]
    editGetCallbacks = [None,self.getAxial,self.getRhombic,
                        self.getEulerAlpha,self.getEulerBeta,self.getEulerGamma]
                   
    self.tensorMatrix = ScrolledMatrix(frameC, maxRows=2,
                                       headingList=headingList,
                                       editSetCallbacks=editSetCallbacks,
                                       editGetCallbacks=editGetCallbacks, 
                                       editWidgets=editWidgets,
                                       callback=self.selectTensor,
                                       multiSelect=True)
                                          
    self.tensorMatrix.grid(row=4,column=0,sticky='nsew')
    
    texts = ['Add Static Tensor','Add Dynamic Tensor','Remove Tensor']
    commands = [self.addStaticTensor,self.addDynamicTensor,self.removeTensor]
    buttonList = ButtonList(frameC,texts=texts, commands=commands, expands=True)
    buttonList.grid(row=5,column=0,sticky='ew')
       
    # About
    
    label = Label(frameD, text='About Meccano...')
    label.grid(row=0,column=0,sticky='w')
  
    #
  
    self.geometry('500x400')

    self.updateShiftLists()
    self.updateMolSystems()
    self.updateResidueRanges()
    self.updateConstraintSets()
    self.updateAlignMedia()
    self.updateRuns()
Exemple #9
0
    def body(self, guiFrame):

        self.geometry('700x600')

        guiFrame.expandGrid(0, 0)

        tipTexts = [
            'A table of all of the reference isotope scheme definitions available to the project',
            'A list of the residue isotopomers that comprise the selected isotope labelling scheme',
            'A three-dimensional representation of residues and their isotopomer labelling'
        ]

        options = ['Reference Schemes', 'Isotopomers', 'Isotopomer Structure']

        tabbedFrame = TabbedFrame(guiFrame,
                                  options=options,
                                  grid=(0, 0),
                                  tipTexts=tipTexts)

        self.tabbedFrame = tabbedFrame
        frameA, frameB, frameC = tabbedFrame.frames

        #
        # Schemes
        #

        frameA.expandGrid(0, 0)

        tipTexts = [
            'A short textual code that identifies the reference isotope scheme in graphical displays',
            'The full name for the isotope scheme',
            'A detailed description of the isotope scheme including user comments',
            'The name of the CCPN data repository in which the isotope scheme is saved; "refData" is in the CCPn installation'
        ]
        headingList = ['Code', 'Name', 'Description', 'Save Location']
        self.schemeNameEntry = Entry(self,
                                     text='',
                                     returnCallback=self.setSchemeName,
                                     width=20)
        self.schemeDetailsEntry = Entry(self,
                                        text='',
                                        returnCallback=self.setSchemeDetails,
                                        width=20)
        editWidgets = [
            None, self.schemeNameEntry, self.schemeDetailsEntry, None
        ]
        editGetCallbacks = [
            None, self.getSchemeName, self.getSchemeDetails, None
        ]
        editSetCallbacks = [
            None, self.setSchemeName, self.setSchemeDetails, None
        ]

        self.schemeMatrix = ScrolledMatrix(frameA,
                                           headingList=headingList,
                                           callback=self.selectScheme,
                                           editWidgets=editWidgets,
                                           editSetCallbacks=editSetCallbacks,
                                           editGetCallbacks=editGetCallbacks,
                                           multiSelect=False,
                                           grid=(0, 0),
                                           tipTexts=tipTexts)
        self.schemeMatrix.doEditMarkExtraRules = self.schemeEditRules

        tipTexts = [
            'Make a new reference isotope scheme definition based on a copy of the scheme currently selected',
            'Delete the selected isotope scheme',
            'Make a new, blank isotope scheme'
        ]
        texts = ['Copy', 'Delete', 'New']
        commands = [self.copyScheme, self.removeScheme, self.makeNewScheme]
        self.schemeButtons = ButtonList(frameA,
                                        texts=texts,
                                        commands=commands,
                                        grid=(1, 0),
                                        tipTexts=tipTexts)

        #
        # Isotopomers
        #

        frameB.expandGrid(3, 0)

        row = 0
        frame = Frame(frameB, grid=(row, 0))
        frame.expandGrid(0, 2)

        tipText = 'Selects which of the available isotope schemes to view/edit'
        label = Label(frame, text='Reference Scheme:', grid=(0, 0))
        self.schemePulldown = PulldownList(frame,
                                           callback=self.setLabellingScheme,
                                           grid=(0, 1),
                                           tipText=tipText)
        row += 1
        div = LabelDivider(frameB, text='Isotopomers', grid=(row, 0))

        row += 1
        frame = Frame(frameB, grid=(row, 0))
        frame.expandGrid(1, 2)

        self.isotopomerFrame = frame
        self.abundanceWidget = MultiWidget(self,
                                           FloatEntry,
                                           relief='raised',
                                           borderwidth=2,
                                           callback=self.setDefaultAbundances,
                                           useImages=False)

        tipText = 'Opens a panel that allows you to set the basis/default abundances for C, H & N isotopes; used as the starting point for new isotopomer definitions'
        self.abundanceButton = Button(frame,
                                      text='Set Default\nAbundances',
                                      borderwidth=1,
                                      command=self.enterDefaultAbundances,
                                      grid=(0, 0),
                                      tipText=tipText)

        tipText = 'Sets the basis/default abundances for C, H & N isotopes to their natural abundance proportions'
        button = Button(frame,
                        text='Set Natural\nAbundance Default',
                        borderwidth=1,
                        command=self.resetDefaultAbundance,
                        grid=(0, 1),
                        sticky='ew',
                        tipText=tipText)

        label = Label(frame, text='Molecule Type:', grid=(0, 2), sticky='e')
        entries = standardResidueCcpCodes.keys()
        entries.sort()
        entries.reverse()
        tipText = 'Selects which type of bio-polymer to define residue isotopomer labelling for'
        self.molTypePulldown = PulldownList(frame,
                                            callback=self.setMolType,
                                            texts=entries,
                                            grid=(0, 3),
                                            tipText=tipText)

        row += 1
        tipTexts = [
            'The CCPN code that identifies the kind of residue the isotopomer relates to',
            'The number of the particular isotopomer (isotope pattern) within its residue type',
            'The fraction of the total residues, of its kind, that the isotopomer make up'
        ]
        headingList = ['Ccp Code', 'Variant', 'Weight']
        self.isotopomerWeightEntry = FloatEntry(
            self, text='', returnCallback=self.setIsotopomerWeight, width=6)
        editWidgets = [None, None, self.isotopomerWeightEntry]
        editGetCallbacks = [None, None, self.getIsotopomerWeight]
        editSetCallbacks = [None, None, self.setIsotopomerWeight]

        self.isotopomerMatrix = ScrolledMatrix(
            frameB,
            tipTexts=tipTexts,
            headingList=headingList,
            callback=self.selectIsotopomer,
            editWidgets=editWidgets,
            editSetCallbacks=editSetCallbacks,
            editGetCallbacks=editGetCallbacks,
            multiSelect=True,
            grid=(row, 0))
        self.isotopomerMatrix.doEditMarkExtraRules = self.isotopomerEditRules

        row += 1
        frame = Frame(frameB, grid=(row, 0), sticky='ew')
        frame.expandGrid(0, 0)

        tipTexts = [
            'Delete the selected residue isotopomers from the current isotope scheme',
            'Make a new residue isotopomer definition by copying the details of the last selected isotopomer',
            'Add a complete set of isotopomers to the isotope scheme, one for each residue type, based on the states default isotope abundances',
            'For all residue isotopomers in the scheme, set the labelling of one kind of atom (the user is prompted) to its default isotopic incorporation ',
            'Add a new residue isotopomer definition that uses the default isotopic incorporation'
        ]

        texts = [
            'Delete\nSelected', 'Copy\nSelected', 'Add Default\nAbundance Set',
            'Set Atom Type\nTo Default', 'Add\nNew:'
        ]

        commands = [
            self.removeIsotopomers, self.duplicateResidues,
            self.addDefaultIsotopomers, self.setAtomTypeDefault,
            self.addNewIsotopomer
        ]

        self.isotopomerButtons = ButtonList(frame,
                                            texts=texts,
                                            commands=commands,
                                            grid=(0, 0),
                                            tipTexts=tipTexts)
        tipText = 'Selects which kind of residue isotopomer may be added to the current isotope scheme'
        self.ccpCodePulldown = PulldownList(frame,
                                            callback=None,
                                            grid=(0, 1),
                                            sticky='e',
                                            tipText=tipText)

        row += 1
        div = LabelDivider(frameB, text='Atom Labels', grid=(row, 0))

        row += 1
        frame = Frame(frameB, grid=(row, 0))
        frame.expandGrid(1, 3)

        label = Label(frame, text='Chemical Element:', grid=(0, 0))
        tipText = 'Selects which kind of atoms to select from the selected residue isotopomer; to display isotopic incorporation in the below table'
        self.elementPulldown = PulldownList(frame,
                                            callback=self.changeChemElement,
                                            grid=(0, 1),
                                            tipText=tipText)
        self.updateChemElements()

        label = Label(frame, text='Water Exchangeable Atoms:', grid=(0, 2))
        tipText = 'Sets whether to show atoms considered as being "water exchangeable"; their isotopic labelling will rapidly equilibrate with aqueous solvent'
        self.exchangeCheck = CheckButton(frame,
                                         callback=self.updateAtomLabelsAfter,
                                         grid=(0, 3),
                                         selected=False,
                                         tipText=tipText)
        row += 1
        # Tip texts set on update
        headingList = [
            'Atom\nName', 'Weighting\n13C'
            'Weighting\n12C', '%12C', '%13C'
        ]
        self.atomLabelTupleWeightEntry = FloatEntry(
            self, text='', width=6, returnCallback=self.setAtomLabelWeight)

        self.atomsMatrix = ScrolledMatrix(frameB,
                                          headingList=headingList,
                                          callback=self.selectAtomLabel,
                                          multiSelect=True,
                                          grid=(row, 0))
        self.atomsMatrix.doEditMarkExtraRules = self.atomsEditRules

        row += 1
        tipTexts = [
            'For the selected atom sites, in the current isotopomer, set their isotopic incorporation to the default values',
            'Spread the isotopic incorporation values from the last selected atom site to all selected atoms sites'
        ]
        texts = ['Reset Selected to Default Abundance', 'Propagate Abundances']
        commands = [self.setAtomLabelsDefault, self.propagateAbundances]
        self.atomButtons = ButtonList(frameB,
                                      texts=texts,
                                      commands=commands,
                                      grid=(row, 0),
                                      tipTexts=tipTexts)

        #
        # View Frame
        #

        frameC.expandGrid(1, 0)

        row = 0
        frame = Frame(frameC, grid=(row, 0), sticky='ew')
        frame.grid_columnconfigure(3, weight=1)

        label = Label(frame, text='Residue Type:', grid=(0, 0))
        tipText = 'Selects which kind of residue, within the current isotope scheme, to show isotopomer structures for'
        self.viewCcpCodePulldown = PulldownList(
            frame,
            callback=self.selectViewCcpcode,
            grid=(0, 1),
            tipText=tipText)

        label = Label(frame, text='Isotopomer:', grid=(0, 2))
        tipText = 'Selects which kind of isotopomer (labelling pattern) to display, from the selected residue type.'
        self.viewIsotopomerPulldown = PulldownList(
            frame,
            callback=self.selectViewIsotopomer,
            grid=(0, 3),
            tipText=tipText)

        row += 1
        self.viewIsotopomerFrame = ViewIsotopomerFrame(frameC,
                                                       None,
                                                       grid=(row, 0))

        #
        # Main
        #

        tipTexts = [
            'Save all changes to the reference isotope scheme to disk; the saves ALL changes to the CCPN installation for all projects to use',
        ]
        texts = ['Save Schemes']
        commands = [self.saveSchemes]
        self.bottomButtons = UtilityButtonList(tabbedFrame.sideFrame,
                                               texts=texts,
                                               commands=commands,
                                               helpUrl=self.help_url,
                                               grid=(0, 0),
                                               sticky='e',
                                               tipTexts=tipTexts)

        self.updateChemElements()
        self.updateCcpCodes()
        self.updateSchemes()
        self.administerNotifiers(self.registerNotify)
Exemple #10
0
    def body(self, guiFrame):

        self.geometry('600x700')

        self.noeMatrix = None

        self.xMol = None
        self.yMol = None

        guiFrame.expandGrid(0, 0)

        tipTexts = [
            'The main colour density matrix that displays residue-residue interaction strength',
            'Selects which peak lists to show residue-residue interactions for',
            'Selects which distance restraint lists to show residue-residue interactions for',
            'Specifies which molecular chains and residue ranges to consider on the matrix axes'
        ]
        options = [
            'Interaction Matrix', 'Peak Lists', 'Restraint Lists', 'Residues'
        ]
        tabbedFrame = TabbedFrame(guiFrame,
                                  options=options,
                                  grid=(0, 0),
                                  tipTexts=tipTexts)
        frameA, frameB, frameC, frameD = tabbedFrame.frames

        #
        # Matrix
        #

        frameA.expandGrid(0, 0)

        self.noeMatrix = NoeMatrix(frameA,
                                   borderwidth=1,
                                   relief='flat',
                                   background='darkGrey',
                                   labelAxes=False)
        self.noeMatrix.grid(row=0, column=0, sticky='nsew')
        self.noeMatrix.updateAfter()

        #
        # Peak Lists
        #

        frameB.expandGrid(0, 0)

        tipTexts = [
            'The experiment:spectrum name of the peak list that may be considered',
            'The serial number of the peak lists within its spectrum',
            'Sets whether or not the peak list will be used as a source of residue interaction information'
        ]
        headingList = ['Spectrum', 'PeakList', 'Use?']
        editWidgets = [None, None, None]
        editGetCallbacks = [None, None, self.togglePeakList]
        editSetCallbacks = [None, None, None]
        self.peakMatrix = ScrolledMatrix(frameB,
                                         headingList=headingList,
                                         editSetCallbacks=editSetCallbacks,
                                         editGetCallbacks=editGetCallbacks,
                                         editWidgets=editWidgets,
                                         multiSelect=False,
                                         grid=(0, 0),
                                         tipTexts=tipTexts)

        #
        # Restraints
        #

        frameC.expandGrid(1, 1)

        label = Label(frameC, text='Restraint Set: ', grid=(0, 0))
        tipText = 'Selects which set of restraints to select restraint connectivity information from'
        self.constraintSetPulldown = PulldownList(frameC,
                                                  self.changeConstraintSet,
                                                  grid=(0, 1),
                                                  tipText=tipText)

        tipTexts = [
            'The serial number, within the restraint set, and name of the restraint list',
            'Whether the restraint list is a Distance restraint list or an H-Bond restraint list',
            'Sets whether or not the restraint list will be used as a source of residue interaction information'
        ]
        headingList = ['List', 'Type', 'Use?']
        editWidgets = [None, None, None]
        editGetCallbacks = [None, None, self.toggleConstraintList]
        editSetCallbacks = [None, None, None]
        self.constraintMatrix = ScrolledMatrix(
            frameC,
            headingList=headingList,
            editSetCallbacks=editSetCallbacks,
            editGetCallbacks=editGetCallbacks,
            editWidgets=editWidgets,
            multiSelect=False,
            grid=(1, 0),
            tipTexts=tipTexts,
            gridSpan=(1, 2))

        #
        # Residues
        #

        frameD.expandGrid(2, 5)

        label = Label(frameD, text='X axis: ', grid=(0, 0))
        label = Label(frameD, text='Y axis: ', grid=(1, 0))

        tipText = 'Selects which molecular chain to use as the sequence along the horizontal axis of the interaction matrix'
        self.xMolPulldown = PulldownList(frameD,
                                         callback=self.changeMolX,
                                         grid=(0, 1),
                                         tipText=tipText)
        tipText = 'Selects which molecular chain to use as the sequence along the vertical axis of the interaction matrix'
        self.yMolPulldown = PulldownList(frameD,
                                         callback=self.changeMolY,
                                         grid=(1, 1),
                                         tipText=tipText)

        tipText = 'Sets the number of the first residue that appears at the start (left) of the horizontal matrix axis'
        self.xEntryStart = IntEntry(frameD,
                                    text='',
                                    returnCallback=self.setMolRanges,
                                    width=5,
                                    grid=(0, 2),
                                    tipText=tipText)
        tipText = 'Sets the number of the first residue that appears at the start (bottom) of the vertical matrix axis'
        self.yEntryStart = IntEntry(frameD,
                                    text='',
                                    returnCallback=self.setMolRanges,
                                    width=5,
                                    grid=(1, 2),
                                    tipText=tipText)

        label = Label(frameD, text=' to ', grid=(0, 3))
        label = Label(frameD, text=' to ', grid=(1, 3))

        tipText = 'Sets the number of the last residue that appears at the end (right) of the horizontal matrix axis'
        self.xEntryStop = IntEntry(frameD,
                                   text='',
                                   returnCallback=self.setMolRanges,
                                   width=5,
                                   grid=(0, 4),
                                   tipText=tipText)
        tipText = 'Sets the number of the last residue that appears at the end (top) of the vertical matrix axis'
        self.yEntryStop = IntEntry(frameD,
                                   text='',
                                   returnCallback=self.setMolRanges,
                                   width=5,
                                   grid=(1, 4),
                                   tipText=tipText)

        #
        # Main
        #

        tipTexts = [
            'Using the selected peak lists, restraint lists and residue ranges draw a colour density residue interaction matrix',
            'Zoom in on the matrix view; make the boxes larger',
            'Zoom out on the matrix view; make the boxes smaller'
        ]
        commands = [self.updateNoes, self.zoomIn, self.zoomOut]
        texts = ['Draw', '[+]', '[-]']
        bottomButtons = UtilityButtonList(tabbedFrame.sideFrame,
                                          commands=commands,
                                          texts=texts,
                                          helpUrl=self.help_url,
                                          grid=(0, 0),
                                          sticky='e',
                                          tipTexts=tipTexts)

        self.updateConstraintSets()
        self.updateMols()
        self.update()
        #self.updateNoes()

        self.administerNotifiers(self.registerNotify)
  def body(self, guiParent):
 
    self.geometry('380x250')

    analysisProject = self.analysisProject

    self.smallFont    = '-schumacher-clean-medium-r-normal--14-140-75-75-c-70-iso646.1991-irv'
    guiParent.grid_columnconfigure(0, weight=1)
    guiParent.grid_rowconfigure(0, weight=1)
    
    row = 0
    
    tipTexts = ['Options specifying how peak annotations are drawn in spectrum windows and in tables etc.',
                'Options to specify how large the peak crosses/symbols are drawn in spectrum windows',
                'Enables the user to specify special symbols to annotate peaks according to quality']
    options=['Annotation Style','Draw Size','Merit Symbols']
    tabbedFrame = TabbedFrame(guiParent, options=options,
                              grid=(row,0), tipTexts=tipTexts)
    
    frame1, frame2, frame3 = tabbedFrame.frames
    frame1.expandGrid(7,1)
    frame2.expandGrid(2,0)
    frame3.expandGrid(3,1)
    
    self.drawFrame = frame2
    
 
    # Annotations

    tipText = 'Whether to show unassigned spin system numbers like "{123}" in peak annotations; does not affect the display of full residue assignments'
    self.spinSystAnnoSelect = CheckButton(frame1, callback=self.setSpinSystAnno, grid=(0,0),
                                          selected=analysisProject.doSpinSystemAnnotations,
                                          tipText=tipText)
    spinSystAnnoLabel = Label(frame1, text='Spin System Info', grid=(0,1))

    tipText = 'Whether to show assigned atom names in peak annotations rather than resonance numbers, e.g. "21LeuH,N" or "21Leu[55],[56]"'
    self.resonanceAnnoSelect = CheckButton(frame1, callback=self.setResonanceAnno, grid=(1,0),
                                           selected=analysisProject.doAssignmentAnnotations,
                                           tipText=tipText)
    resonanceAnnoLabel = Label(frame1, text='Atom Assignment', grid=(1,1))

    tipText = 'Whether to show the molecular chain code letter in peak annotations, e.g. "21LeuH,N" or "A21LeuH,N"'
    self.chainAnnoSelect = CheckButton(frame1, callback=self.setChainAnno, grid=(2,0),
                                       selected=analysisProject.doChainAnnotations,
                                       tipText=tipText)
    chainAnnoLabel = Label(frame1, text='Chain Assignment', grid=(2,1))

    tipText = 'Whether to show the molecular system code name in peak annotations, e.g. "MS1:21LeuH,N" or "21LeuH,N"'
    self.molSysAnnoSelect = CheckButton(frame1, callback=self.setMolSysAnno, grid=(3,0),
                                       selected=analysisProject.doMolSysAnnotations,
                                       tipText=tipText)
    molSysAnnoLabel = Label(frame1, text='Molecular System', grid=(3,1))

    tipText = 'Whether to show a symbol indicating the quality of a peak; these symbols must be set in the "Merit Symbols" tab'
    self.meritAnnoSelect = CheckButton(frame1, callback=self.setMeritAnno, grid=(4,0),
                                       selected=analysisProject.doMeritAnnotations,
                                       tipText=tipText)
    meritAnnoLabel = Label(frame1, text='Merit Symbol', grid=(4,1))

    tipText = 'Whether to show the details text for a peak in spectrum windows (set in the peak tables)'
    self.detailAnnoSelect = CheckButton(frame1, callback=self.setDetailAnno, grid=(5,0),
                                        selected=analysisProject.doDetailAnnotations,
                                        tipText=tipText)
    detailAnnoLabel = Label(frame1, text='Details', grid=(5,1))

    tipText = 'Whether to ignore above settings, and use a short peak annotation using only residue numbers and one-letter codes, e.g. "21L"'
    self.simpleAnnoSelect = CheckButton(frame1, callback=self.setSimpleAnnotations,
                                        grid=(6,0), tipText=tipText,
                                        selected=analysisProject.doMinimalAnnotations)
    simpleAnnoLabel = Label(frame1, text='Minimal Annotations (overriding option)', grid=(6,1))

    tipText = 'Manually cause an update of all peak annotations; may take some time but recommended to see the immediate effect of changes'
    self.updateFullAnnoButton = Button(frame1, text='Update Full Annotations',
                                       command=self.updateAnnotations, grid=(7,0),
                                       gridSpan=(1,2), sticky='nsew', tipText=tipText)

    # Size
    
    tipText = 'The width of the displayed peak cross/symbol in screen pixels; the number of pixels from the centre point'
    self.pixel_entry = LabeledEntry(frame2, label='Number of pixels',
                                    entry=analysisProject.peakPixelSize,
                                    returnCallback=self.updatePixelSize,
                                    entry_width=8, tipText=tipText)

    tipText = 'Specifies which peak height corresponds to the specific per-isotope ppm size; actual peak symbol sizes are scaled, according to relative height (and volume)'
    self.intensity_entry = LabeledEntry(frame2, label='Height scale',
                                        entry=analysisProject.peakIntensityScale,
                                        returnCallback=self.updateIntensityScale,
                                        entry_width=8, tipText=tipText)
                                        
    tipText = 'Specifies which peak volume corresponds to the specific per-isotope ppm size; actual peak symbol sizes are scaled, according to relative volume (and height)'
    self.volume_entry = LabeledEntry(frame2, label='Volume scale',
                                     entry=analysisProject.peakVolumeScale,
                                     returnCallback=self.updateVolumeScale,
                                     entry_width=8, tipText=tipText)

    tipTexts = ['The kind of nuclear isotope, as found on the axis if a spectrum window',
                'The ppm width of the peak cross/symbol along the specific kind of isotope axis']
    headings = ['Isotope', 'Peak Size (ppm)']
    self.peakSizeEntry = FloatEntry(self, returnCallback=self.setPeakSize, width=10)
    editWidgets = [None, self.peakSizeEntry]
    editGetCallbacks = [None, self.getPeakSize]
    editSetCallbacks = [None, self.setPeakSize]
    self.peak_size_table = ScrolledMatrix(frame2, headingList=headings,
                                          initialRows=5, editWidgets=editWidgets,
                                          editGetCallbacks=editGetCallbacks,
                                          editSetCallbacks=editSetCallbacks,
                                          tipTexts=tipTexts)

    self.selected_method = None
    self.method_widgets = {}
    self.method_widgets[peak_draw_methods[0]] = [self.pixel_entry]
    self.method_widgets[peak_draw_methods[1]] = [self.peak_size_table]
    self.method_widgets[peak_draw_methods[2]] = [self.intensity_entry, self.volume_entry, self.peak_size_table]
    self.method_widgets[peak_draw_methods[3]] = [self.peak_size_table]
    self.method_widgets[peak_draw_methods[4]] = []
    self.method_widgets[peak_draw_methods[5]] = []

    selected_index = peak_draw_methods.index(analysisProject.peakDrawMethod)
    tipText = 'Selects which mode to use for determining peak cross/symbol sizes; a fixed pixel/ppm value or scaled by intensity for all peaks or just one peak list'
    self.method_menu = PulldownList(frame2, texts=peak_draw_methods, gridSpan=(1,2), 
                                    grid=(0,0), tipText=tipText,
                                    callback=self.setMethod, index=selected_index)
    
    # Merit symbol
    
    label = Label(frame3, text='Good merit (>0.66)', grid=(0,0))
    tipText = 'Although typically blank, sets a symbol to display for good quality peaks (merit value > 0.66), if the relevant option is selected in the "Annotation Style" tab'
    self.meritGoodEntry = Entry(frame3, text=analysisProject.meritAnnotationGood,
                                width=8, grid=(0,1), sticky='ew', tipText=tipText,
                                returnCallback=self.setMeritAnnotation)

    label = Label(frame3, text='Medium merit', grid=(1,0))
    tipText = 'Sets a symbol to display for mediocre quality peaks (merit value between 0.34 & 0.66), if the relevant option is selected in the "Annotation Style" tab'
    self.meritUglyEntry = Entry(frame3, text=analysisProject.meritAnnotationMediocre,
                                width=8, grid=(1,1), sticky='ew', tipText=tipText,
                                returnCallback=self.setMeritAnnotation)

    label = Label(frame3, text='Poor merit (<0.34)', grid=(2,0))
    tipText = 'Sets a symbol to display for poor quality peaks (merit value < 0.34), if the relevant option is selected in the "Annotation Style" tab'
    self.meritBadEntry  = Entry(frame3, text=analysisProject.meritAnnotationBad,
                                width=8, grid=(2,1), sticky='ew', tipText=tipText,
                                returnCallback=self.setMeritAnnotation)

    tipText = 'Commit the changes to the merit symbols; this will not automatically update the display - see the "Annotation Style" tab'
    setButton = Button(frame3, text='Set symbols', command=self.setMeritAnnotation,
                       grid=(3,0), gridSpan=(1,2), tipText=tipText, sticky='nsew')

    buttons = UtilityButtonList(tabbedFrame.sideFrame, grid=(0,0), 
                                helpUrl=self.help_url, sticky='e')

    self.updatePeakSizeTable()
    self.updateMethod()

    for func in ('__init__', 'delete', ''):                                           
      self.registerNotify(self.updatePeakSizeTable, 'ccpnmr.Analysis.AxisType', func)

    self.registerNotify(self.changedDoSpinSystemAnnotations, 'ccpnmr.Analysis.AnalysisProject', 'setDoSpinSystemAnnotations')
    self.registerNotify(self.changedDoAssignmentAnnotations, 'ccpnmr.Analysis.AnalysisProject', 'setDoAssignmentAnnotations')
    self.registerNotify(self.changedDoChainAnnotations, 'ccpnmr.Analysis.AnalysisProject', 'setDoChainAnnotations')
    self.registerNotify(self.changedPeakDrawMethod, 'ccpnmr.Analysis.AnalysisProject', 'setPeakDrawMethod')
    self.registerNotify(self.changedPeakPixelSize, 'ccpnmr.Analysis.AnalysisProject', 'setPeakPixelSize')
Exemple #12
0
    def __init__(self, parent, project, closeButton=False, *args, **kw):

        self.parent = parent
        self.project = project
        self.nmrProject = (project.currentNmrProject
                           or project.newNmrProject(name='PALES'))
        self.calcStore = None
        self.run = None
        self.inpStructure = None
        self.inpConstraintList = None
        self.workingDir = None
        self.waiting = False

        self.palesMode = None

        self.resetCalcStore()

        Frame.__init__(self, parent, *args, **kw)

        self.expandGrid(0, 0)

        options = ['Input Data', 'Extra Input', 'View Results']

        tabbedFrame = TabbedFrame(self, options=options, grid=(0, 0))
        frameA, frameX, frameB = tabbedFrame.frames
        self.tabbedFrame = tabbedFrame

        label = Label(tabbedFrame.sideFrame,
                      text='Run Number:',
                      grid=(0, 0),
                      sticky='e')

        tipText = 'Selects which calculation job or "run" is currently being viewed or edited'
        self.runPulldown = PulldownList(tabbedFrame.sideFrame,
                                        callback=self.changeRun,
                                        grid=(0, 1),
                                        sticky='e',
                                        tipText=tipText)

        tipTexts = ['Delete the current calculation run settings']
        texts = ['Delete Run']
        commands = [self.deleteRun]

        if closeButton:
            ButtonListClass = UtilityButtonList
        else:
            ButtonListClass = ButtonList

        runButtons = ButtonListClass(tabbedFrame.sideFrame,
                                     texts=texts,
                                     tipTexts=tipTexts,
                                     commands=commands,
                                     sticky='e',
                                     grid=(0, 2))

        # Input data

        frameA.expandGrid(2, 1)

        row = 0
        label = Label(frameA, text='Pales mode:', grid=(row, 0), sticky='w')
        self.palesModePulldown = PulldownList(frameA,
                                              callback=self.changePalesMode,
                                              grid=(row, 1))

        tipTexts = [
            'Make a setup for a new calculation run',
            'Make a new calculation run by copying the current one',
        ]
        texts = ['New Run', 'Copy Run']
        commands = [self.newRun, self.copyRun]

        if closeButton:
            ButtonListClass = UtilityButtonList
        else:
            ButtonListClass = ButtonList

        runButtons = ButtonList(frameA,
                                texts=texts,
                                tipTexts=tipTexts,
                                commands=commands,
                                sticky='e',
                                grid=(row, 2))
        runButtons.buttons[0].config(bg='#B0FFB0')

        row += 1
        subframe1 = LabelFrame(frameA,
                               text='Description',
                               grid=(row, 0),
                               gridSpan=(1, 3))
        subframe1.expandGrid(0, 1)
        self.modeDescription = Label(subframe1, grid=(row, 0), sticky='w')

        row += 1
        # setup generic table headings, justification and widget getters/setters

        self.inputMatrix = GenericDataMatrix(frameA, progParameters)
        self.inputMatrix.grid(row=row, column=0, columnspan=3, sticky='nsew')

        row += 1
        label = Label(frameA, text='Comments:', grid=(row, 0))
        self.detailsEntryIn = Entry(frameA,
                                    grid=(row, 1),
                                    gridSpan=(1, 2),
                                    sticky="ew")
        self.detailsEntryIn.bind('<Leave>', self.changeDetailsIn)

        row += 1
        button = Button(frameA,
                        text='Select working dir:',
                        bd=1,
                        command=self.selectWorkingDir,
                        grid=(row, 0),
                        sticky="ew")
        self.workingDirEntry = Entry(frameA,
                                     text='.',
                                     grid=(row, 1),
                                     gridSpan=(1, 2),
                                     width=48,
                                     sticky="ew",
                                     bd=1)

        row += 1
        button = Button(frameA,
                        text='Execute Pales:',
                        bd=1,
                        command=self.executePales,
                        grid=(row, 0),
                        gridSpan=(1, 3),
                        sticky="new")

        # Extra input
        # setup generic table headings, justification and widget getters/setters

        frameX.expandGrid(0, 0)

        self.extraInputMatrix = GenericDataMatrix(frameX, progParameters)
        self.extraInputMatrix.grid(row=0, column=0, sticky='nsew')

        # View Results

        frameB.expandGrid(7, 1)

        row = 0

        subframe1 = LabelFrame(frameB,
                               text='Command Options:',
                               grid=(row, 0),
                               gridSpan=(1, 4))
        #                       gridSpan=(1,2))
        subframe1.expandGrid(0, 1)
        self.palesOptionsLabel = Label(subframe1, grid=(row, 0), sticky='w')

        row += 1
        div = LabelDivider(frameB, text='Data', grid=(row, 0), gridSpan=(1, 4))

        row += 1

        self.outputMatrix = GenericDataMatrix(frameB,
                                              progParameters,
                                              initialRows=4)
        self.outputMatrix.grid(row=0, column=0, sticky='nsew')

        self.outputMatrix.grid(row=row,
                               column=0,
                               columnspan=(4),
                               sticky='nsew')

        row += 1
        button = Button(frameB,
                        text='View Selected',
                        bd=1,
                        command=self.viewPalesData,
                        grid=(row, 0),
                        gridSpan=(1, 4),
                        sticky="ew")

        row += 1
        label = Label(frameB, text='Comments:', grid=(row, 0), sticky="w")
        self.detailsEntry = Entry(frameB,
                                  grid=(row, 1),
                                  gridSpan=(1, 3),
                                  sticky="ew")
        self.detailsEntry.bind('<Leave>', self.changeDetails)

        row += 1
        subframe2 = LabelFrame(frameB,
                               text='Calculated Order Matrix:',
                               grid=(row, 0),
                               gridSpan=(1, 4))
        #subframe2.grid_columnconfigure(5, weight=1)
        subframe2.expandGrid(1, 5)
        label = Label(subframe2, text='Daxial', grid=(0, 0), sticky='ew')
        label = Label(subframe2, text='Drhombic', grid=(0, 1), sticky='ew')
        label = Label(subframe2, text='Psi', grid=(0, 2), sticky='ew')
        label = Label(subframe2, text='Phi', grid=(0, 3), sticky='ew')
        label = Label(subframe2, text='Theta', grid=(0, 4), sticky='ew')

        self.outputTensorLabels = ll = []
        for ii in range(5):
            label = Label(subframe2, text='<None>', grid=(1, ii), sticky='ew')
            ll.append(label)

        row += 1
        div = LabelDivider(frameB,
                           text='Program Output',
                           grid=(row, 0),
                           gridSpan=(1, 4),
                           sticky='sew')

        #textFrame1 = LabelFrame(frameB, text='Pales Output File', grid=(5,0),
        #                        gridSpan=(1,6), sticky='nsew')
        #textFrame1.expandGrid(0,0)

        row += 1
        self.palesOutputText = ScrolledText(frameB, xscroll=False)

        self.palesOutputText.grid(row=row,
                                  column=0,
                                  columnspan=4,
                                  sticky='nsew')

        self.updateAfter()
        self.administerNotifiers(self.parent.registerNotify)
Exemple #13
0
    def __init__(self, parent, basePopup, *args, **kw):

        #
        # Variable initialisation
        #

        self.fcWrapper = basePopup.fcWrapper
        self.project = basePopup.project
        self.basePopup = basePopup

        # TODO necessary?
        if self.project:
            self.nmrProject = self.project.currentNmrProject
            self.entry = self.project.currentNmrEntryStore.findFirstEntry()
            if not self.entry:
                self.entry = self.project.currentNmrEntryStore.newEntry(
                    name=self.project.name)
        else:
            self.nmrProject = None

        self.sequenceCoordinatesLoaded = False
        self.shiftsLoaded = False
        self.linkResDone = False

        self.currentShiftList = None
        self.shiftListChainPairs = []

        self.moleculeList = []
        self.moleculeDict = {}

        #
        # Frame setup
        #

        Frame.__init__(self, parent, **kw)

        self.grid_columnconfigure(1, weight=1)
        self.grid_rowconfigure(1, weight=1)

        options = ['Import', 'Deposition']

        tabbedFrame = TabbedFrame(self,
                                  options=options,
                                  callback=self.selectTab)
        tabbedFrame.grid(row=1, column=0, columnspan=2, sticky='nsew')

        self.tabbedFrame = tabbedFrame
        frameA, frameD = tabbedFrame.frames

        #
        # Main
        #

        frameA.grid_columnconfigure(0, weight=1)
        #frameA.grid_columnconfigure(1, weight=1) # Change to 2 if want 2 columns
        frameA.grid_rowconfigure(12, weight=1)
        #frameA.grid_rowconfigure(12, weight=1)

        row = 0

        div = LabelDivider(
            frameA,
            text=
            'Select the full coordinate file or a sequence file (with info for a single molecule).',
            justify='center',
            grid=(row, 0),
            gridSpan=(1, 1))

        row += 1

        self.sequenceCoordinatesImport = Button(
            frameA,
            text=self.defaultSelectText,
            command=self.importSequenceOrCoords,
            foreground=self.fontDefaultColor)
        self.sequenceCoordinatesImport.grid(row=row, column=0, sticky='ew')

        row += 1

        label = Label(frameA, text="")
        label.grid(row=row, column=0, sticky='ew')

        row += 1

        div = LabelDivider(
            frameA,
            text='Select the molecule relevant for your chemical shift file.',
            justify='center',
            grid=(row, 0),
            gridSpan=(1, 1))

        row += 1

        self.moleculeSelect = Label(
            frameA,
            text="None available yet - import valid file first",
            foreground=self.fontBadColor)
        self.moleculeSelect.grid(row=row, column=0, sticky='ew')
        self.moleculeSelectRow = row

        row += 1

        label = Label(frameA, text="")
        label.grid(row=row, column=0, sticky='ew')

        row += 1

        div = LabelDivider(
            frameA,
            text=
            'Select a chemical shift file with values only for the above molecule.',
            justify='center',
            grid=(row, 0),
            gridSpan=(1, 1))

        row += 1

        self.shiftImport = Button(frameA,
                                  text=self.defaultSelectText,
                                  command=self.importShifts,
                                  foreground=self.fontDefaultColor)
        self.shiftImport.grid(row=row, column=0, sticky='ew')

        row += 1

        label = Label(frameA, text="")
        label.grid(row=row, column=0, sticky='ew')

        row += 1

        div = LabelDivider(
            frameA,
            text='Consistency check between molecule and shift information.',
            justify='center',
            grid=(row, 0),
            gridSpan=(2, 1))

        row += 1

        self.linkResCheckInfo = Label(frameA, text='')
        self.linkResCheckInfo.grid(row=row, column=0, sticky='ew')

        row += 1

        div = Separator(frameA, grid=(row, 0), gridSpan=(1, 1))

        row += 1

        texts = ['Import new sequence', 'Import new set of shifts']
        commands = [self.resetSequenceImport, self.resetShiftImport]

        self.mainButtons = ButtonList(frameA, texts=texts, commands=commands)
        self.mainButtons.grid(row=row, column=0, columnspan=2, sticky='ew')
        self.mainButtons.buttons[0].config(foreground=self.fontDefaultColor)

        #print row

        self.frameA = frameA

        #
        # Not in use...
        #

        #frameX.grid_columnconfigure(0, weight=1)
        #frameX.grid_columnconfigure(1, weight=1)
        #frameX.grid_rowconfigure(1, weight=1)
        #frameX.grid_rowconfigure(3, weight=1)

        #
        # Deposition, is updated after each successful import run.
        #

        frameD.grid_columnconfigure(0, weight=1)
        frameD.grid_rowconfigure(5, weight=1)

        self.frameD = frameD

        row = 0

        div = LabelDivider(frameD,
                           text='Imported data.',
                           justify='center',
                           grid=(row, 0),
                           gridSpan=(1, 2))

        row += 1

        self.depositionImportText = "\nImported %d shift list(s) for a total of %d shifts.\n\nImported %d molecule(s) and %d chain(s).\n\nImported %d model(s) for a total of %d atom coordinates.\n\nLinked %.2f%% of imported NMR information to %d chain(s)."
        self.depositionImportLoc = (row, 0)

        # These used for setting text above...
        self.depositionImportNums = [0, 0, 0, 0, 0, 0, 0.0, 0]
        self.importedShiftLists = []
        self.connectedChains = []

        self.depositionImportLabel = Label(frameD,
                                           text=self.depositionImportText %
                                           tuple(self.depositionImportNums),
                                           foreground=self.fontBadColor)
        self.depositionImportLabel.grid(row=row, column=0, sticky='ew')

        row += 1

        label = Label(frameD, text="")
        label.grid(row=row, column=0, sticky='ew')

        #
        # Finalize the import part, proceed to ECI.
        #

        row += 1

        div = LabelDivider(
            frameD,
            text=
            'Import completed, save project and start Entry Completion Interface.',
            justify='center',
            grid=(row, 0),
            gridSpan=(1, 1))

        row += 1

        self.eciStart = Button(frameD,
                               text="Finalise import",
                               command=self.finaliseImport,
                               foreground=self.fontBadColor)
        self.eciStart.grid(row=row, column=0, sticky='ew')
Exemple #14
0
    def body(self, guiFrame):

        self.geometry('600x350')

        guiFrame.expandGrid(0, 0)

        options = ['Axis Units', 'Axis Types', 'Panel Types']
        tabbedFrame = TabbedFrame(guiFrame, options=options, grid=(0, 0))
        frameA, frameB, frameC = tabbedFrame.frames
        self.tabbedFrame = tabbedFrame

        #
        # Units
        #

        frameA.expandGrid(0, 0)

        tipTexts = [
            'Row number',
            'Short text name for the unit of measurement, for graphical display',
            'Whether the axis values decrease left to right & bottom to top. For example "ppm" does, but most other units do not'
        ]
        headings = ('#', 'Name', 'Is backwards?')
        self.axis_unit_table = ScrolledMatrix(frameA,
                                              headingList=headings,
                                              callback=self.selectAxisUnit,
                                              deleteFunc=self.deleteAxisUnit,
                                              tipTexts=tipTexts,
                                              grid=(0, 0))

        tipTexts = [
            'Create a new specification of a unit of measurement',
            'Delete the selected measurement unit'
        ]
        texts = ['Create', 'Delete']
        commands = [self.createAxisUnit, self.deleteAxisUnit]
        self.axis_unit_buttons = ButtonList(frameA,
                                            texts=texts,
                                            tipTexts=tipTexts,
                                            grid=(1, 0),
                                            commands=commands)

        #
        # Types
        #

        frameB.expandGrid(0, 0)

        tipTexts = [
            'Row number',
            'Name of window axis type, for graphical interface etc.',
            'Which isotopes the axis definition covers',
            'What kind of physical property is measured along the window axis',
            'Whether the axis represents discretely sampled values or a continuum of values (albeit fixed to a data grid)',
            'The upper and lower bounds for numerical values allowed on the axis',
            'The number of decimal places used to round axis values in graphical displays',
            'The relative scale for the peak symbol (i.e the "X" shape) size compared to other axes',
            'Units of measurement allowed for this kind of axis'
        ]

        headingList = ('#', 'Name', 'Isotope\ncodes', 'Measurement\nType',
                       'Dim\nSampled?', 'Region', 'Decimal\nplaces',
                       'Peak\nSize', 'Allowed\nUnits')

        self.regionEntry = FloatEntry(self,
                                      isArray=True,
                                      returnCallback=self.setRegion,
                                      width=12)
        self.decimalEntry = IntEntry(self,
                                     returnCallback=self.setDecimal,
                                     width=5)
        self.peakSizeEntry = FloatEntry(self,
                                        returnCallback=self.setPeakSize,
                                        width=5)

        editWidgets = [
            None, None, None, None, None, self.regionEntry, self.decimalEntry,
            self.peakSizeEntry, None
        ]
        editGetCallbacks = [
            None, None, None, None, None, self.getRegion, self.getDecimal,
            self.getPeakSize, self.addUnit
        ]
        editSetCallbacks = [
            None, None, None, None, None, self.setRegion, self.setDecimal,
            self.setPeakSize, None
        ]

        self.axisTypeMatrix = ScrolledMatrix(frameB,
                                             tipTexts=tipTexts,
                                             headingList=headingList,
                                             initialRows=5,
                                             grid=(0, 0),
                                             callback=self.selectAxisType,
                                             editWidgets=editWidgets,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks,
                                             deleteFunc=self.deleteAxisType)

        tipTexts = [
            'Create a new kind of axis to use in spectrum windows',
            'Delete the selected window axis type specification'
        ]
        texts = ['Create', 'Delete']
        commands = [self.createAxisType, self.deleteAxisType]
        self.axis_type_buttons = ButtonList(frameB,
                                            texts=texts,
                                            tipTexts=tipTexts,
                                            commands=commands,
                                            grid=(1, 0))

        #
        # Types
        #

        frameC.expandGrid(0, 0)

        tipTexts = [
            'Row number', 'Name of panel type specification',
            'Which kind of axis the panel is a subtype of'
        ]
        headings = ('#', 'Name', 'AxisType')
        self.panelTypeMatrix = ScrolledMatrix(frameC,
                                              tipTexts=tipTexts,
                                              headingList=headings,
                                              initialRows=5,
                                              callback=self.selectPanelType,
                                              deleteFunc=self.deletePanelType)

        self.panelTypeMatrix.grid(row=0, column=0, sticky='nsew')

        tipTexts = [
            'Add a new panel type specification (a subtype of a given kind of axis)',
            'Delete the selected panel type specification'
        ]
        texts = ['Create', 'Delete']
        commands = [self.createPanelType, self.deletePanelType]
        self.panel_type_buttons = ButtonList(frameC,
                                             texts=texts,
                                             grid=(1, 0),
                                             commands=commands,
                                             tipTexts=tipTexts)

        #
        # Main
        #

        buttons = UtilityButtonList(tabbedFrame.sideFrame,
                                    helpUrl=self.help_url,
                                    grid=(0, 0),
                                    sticky='e')

        self.updateAxisUnitTable()
        self.updateAxisTypeTable()
        self.updatePanelTypeTable()
        self.selectAxisUnit()
        self.selectAxisType()
        self.selectPanelType()
        self.administerNotifiers(self.registerNotify)
Exemple #15
0
class ApplicationPopup(BasePopup):

    help_url = 'http://www.ccpn.ac.uk'

    def __init__(self, root, programName='Ccpn Workflow Management System'):

        self.programName = programName
        self.font = DEFAULT_FONT
        # Application object needed to store application-specific data with project
        self.application = Application(name=PROGRAM_NAME)
        self.versionInfo = 'Version ' + VERSION
        self.ariaProjectFile = None

        self.username = None

        # what do these do??
        self.updateFuncs = []
        self.projButtons = []

        # may need these in the end
        self.ariaPaths = []
        self.isdPaths = []

        # FIXME JMCI

        # hard code this for now. this should be initialised from file
        # read during GUI login and then extended using the menu options

        # should set a placeholder. In fact, this placeholder will also have
        # a default user (guest) so that there is always a structure to
        # extend should the user wish to start from scratch and not log in

        self.repList = RepositoryList()
        self.currentTask = None

        # going to stick in shortcuts to frames for quick access
        self.frameShortcuts = {}

        # Application popup is a superclass of memops.editor.BasePoup
        BasePopup.__init__(self,
                           parent=root,
                           title=PROGRAM_NAME,
                           location='+100+100',
                           class_=self.application.name)

        self.setTitle(PROGRAM_NAME)

    def body(self, guiParent):

        self.geometry('700x600')

        # Ensure that the first row and column in popup expand
        guiParent.grid_rowconfigure(0, weight=1)
        guiParent.grid_columnconfigure(0, weight=1, minsize=200)
        frame = Frame(guiParent)  # Body widgets can be put in this frame
        frame.grid()

        # this is going to set up the options on the tabs. Really we need
        # stronger bookeeping between the options and the frames.  it
        # might make sense to define a master dictionary with option_name
        # => index. We can use this dictionary to build up the software
        # options and can also use it to define any refreshes etc (although
        # these would be better done through notifiers)

        softwareOpts = [
            'Repository', 'Project', 'Process', 'Client Tasks', 'Server Tasks',
            'Data Exchange', 'Workflow', 'Protocols', 'User'
        ]

        # FIXME JMCI

        # we should have a tidier tabbed frame. ned to discuss rules with
        # tjs but it would seem to make sense to have the tabs stretch
        # across the entire top of the frame. Check the existing options
        # first, though

        self.tabbedFrame = TabbedFrame(guiParent,
                                       options=softwareOpts,
                                       toggleOff=False,
                                       selected=0)
        self.tabbedFrame.grid(row=0, column=0, sticky='nsew')

        frames = self.tabbedFrame.frames

        # Logos
        ccpnDir = getTopDirectory()
        imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images')
        imageFile = os.path.join(imageDir, 'CcpnLogo.gif')
        self.ccpnLogo = Tkinter.PhotoImage(file=imageFile)

        # Dictionary to store popups opened by this application - e.g. need to close upon quit
        self.popups = {}

        # Default font
        self.font = 'Helvetica 10'

        # Closing the window from the desktop environment calls the proper quit
        self.protocol('WM_DELETE_WINDOW', self.quit)

        # jmci we are going to have to change these drastically
        self.mainMenu = Menu(self)
        self.userMenu = self.makeUserMenu()
        self.repositoryMenu = self.makeRepositoryMenu()
        self.otherMenu = self.makeOtherMenu()

        # Put the top level menu
        self.config(menu=self.mainMenu)
        self.initRepository(frames[0])
        self.initProjectFrame(frames[1])
        self.initWms(frames[2])
        self.initTasks(frames[3])
        self.initDataExch(frames[5])
        self.initWorkflow(frames[6])
        self.initProtocol(frames[7])
        self.initUserFrame(frames[8])

        self.initProject()

        if not self.project:
            for button in self.projButtons:
                button.disable()

        # the main client side daemon. This is going to run in the background
        # and control the task processing
        self.taskDaemon = TaskManager(self)
        self.taskDaemon.active = False
        self.taskDaemon.start()

    ## THE TABBED FRAMES ##

    def initRepository(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        repositoryFrame = RepositoryFrame(frame, basePopup=self)
        repositoryFrame.grid(row=1, column=0, sticky='nsew')

        self.updateFuncs.append(repositoryFrame.updateAll)

    def initProjectFrame(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        self.projectFrame = ProjectFrame(frame, basePopup=self)
        self.projectFrame.grid(row=1, column=0, sticky='nsew')

        self.updateFuncs.append(self.projectFrame.updateAll)

    def initWms(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        extendNmrFrame = ExtendNmrFrame(frame, basePopup=self)
        extendNmrFrame.grid(row=1, column=0, sticky='nsew')

        self.updateFuncs.append(extendNmrFrame.updateAll)

    def initTasks(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        tasksFrame = TasksFrame(frame, self)
        tasksFrame.grid(row=1, column=0, sticky='nsew')

        self.updateFuncs.append(tasksFrame.updateAll)

    def initDataExch(self, frame):

        row = 0
        frame.config(bg='#E6E6E6')

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        dataExchFrame = DataExchFrame(frame, basePopup=self)
        dataExchFrame.grid(row=1, column=0, sticky='nsew')

        self.updateFuncs.append(dataExchFrame.updateAll)

    def initWorkflow(self, frame):

        row = 0
        frame.config(bg='#FFFFFF')

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        workflowFrame = WorkflowFrame(frame, basePopup=self)
        workflowFrame.grid(row=1, column=0, sticky='nsew')

        self.updateFuncs.append(workflowFrame.updateAll)

    def initProtocol(self, frame):

        row = 0
        frame.config(bg='#FFFFFF')

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        protocolFrame = ProtocolFrame(frame, basePopup=self)
        protocolFrame.grid(row=1, column=0, sticky='nsew')

        self.updateFuncs.append(protocolFrame.updateAll)

    def initUserFrame(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        row = 0
        frame.config(bg='#FFFFFF')

        userFrame = UserFrame(frame, basePopup=self)
        userFrame.grid(row=1, column=0, sticky='nsew')

        self.updateFuncs.append(userFrame.updateAll)

    ## The Menu ##

    def makeUserMenu(self):
        menu = Menu(self.mainMenu, tearoff=0)
        menu.add_command(label='Log In',
                         shortcut='I',
                         command=self.openLoginPopup)
        menu.add_command(label='Log Out', shortcut='O', command=self.logout)
        menu.add_command(label='Save Profile',
                         shortcut='S',
                         command=self.tmpCall)
        menu.add_command(label='View Profile',
                         shortcut='V',
                         command=self.tmpCall)
        menu.add_command(label='Create Profile',
                         shortcut='C',
                         command=self.tmpCall)
        menu.add_command(label='Edit Profile',
                         shortcut='E',
                         command=self.tmpCall)
        self.mainMenu.add_cascade(label='User', shortcut='U', menu=menu)
        menu.options = [
            'Log In', 'Log Out', 'Save Profile', 'View Profile',
            'Create Profile', 'Edit Profile'
        ]
        return menu

    def makeRepositoryMenu(self):
        self.repMenu = Menu(self.mainMenu, tearoff=0)
        # Add various options to the menu and state the functions they call
        self.repMenu.add_command(label='Manager',
                                 shortcut='M',
                                 command=self.tmpCall)
        self.repMenu.add_command(label='Connect',
                                 shortcut='C',
                                 command=self.openRepository)

        # doesn't really work to have a disconnect; we do not have a list
        # of repositories and so would it refer to? Better to do this from
        # within the RepositoryFrame

        self.repMenu.add_command(label='Disconnect',
                                 shortcut='D',
                                 command=self.tmpCall)

        # again, this is functionality that would make sense but which it is hard to put
        # in the top level menu because it is not obvious which repository it refers
        # to

        self.repMenu.add_command(label='Import Project',
                                 shortcut='I',
                                 command=self.tmpCall)
        self.repMenu.add_command(label='Export Project',
                                 shortcut='E',
                                 command=self.tmpCall)

        # FIXME JMCI

        # the quit option needs to be tied to a dialogue box that asks whether
        # the current connection state should be saved. This will have to be
        # secured and so means that the GUI should have a login itself (beyond
        # the logins for the various resources).

        self.repMenu.add_command(label='Quit', shortcut='Q', command=self.quit)

        self.mainMenu.add_cascade(label='Repository',
                                  shortcut='R',
                                  menu=self.repMenu)
        self.repMenu.options = [
            'Connect', 'Disconnect', 'Import Project', 'Export Project', 'Quit'
        ]
        return self.repMenu

    def makeProjectMenu(self):

        # Submenu of the min menu
        menu = Menu(self.mainMenu, tearoff=0)
        # Add various options to the menu and state the functions they call
        menu.add_command(label='New', shortcut='N', command=self.newProject)
        menu.add_command(label='Open', shortcut='O', command=self.openProject)
        menu.add_command(label='Close',
                         shortcut='C',
                         command=self.closeProject)
        menu.add_command(label='Save', shortcut='S', command=self.saveProject)
        menu.add_command(label='Save As',
                         shortcut='A',
                         command=self.saveAsProject)
        menu.add_command(label='Quit', shortcut='Q', command=self.quit)
        menu.add_command(label='Version',
                         shortcut='V',
                         command=self.showVersion)
        self.mainMenu.add_cascade(label='Project', shortcut='P', menu=menu)

        menu.options = [
            'New', 'Open', 'Close', 'Save', 'Save As', 'Quit', 'Version'
        ]
        return menu

    def makeOtherMenu(self):

        # The fonts menu is a pre-created widget
        fontsMenu = FontMenu(self.mainMenu,
                             self.setFont,
                             sizes=(8, 10, 12),
                             doItalic=0,
                             doBoldItalic=0,
                             tearoff=0)

        # Submenu of the min menu
        menu = Menu(self.mainMenu, tearoff=0)
        # Only Fonts option so far
        menu.add_cascade(label='Fonts', shortcut='F', menu=fontsMenu)
        self.mainMenu.add_cascade(label='Options', shortcut='O', menu=menu)

        menu.options = [
            'Fonts',
        ]
        return menu

    def makeCcpNmrMenu(self):

        try:
            from ccpnmr.analysis.AnalysisPopup import AnalysisPopup
            haveAnalysis = True
        except ImportError:
            haveAnalysis = False

        try:
            from ccpnmr.format.gui.FormatConverter import FormatConverter
            from ccpnmr.format.gui.DataShifter import DataShifter
            haveFormatConv = True
        except ImportError:
            haveFormatConv = False

        menu = Menu(self.mainMenu, tearoff=0)

        if haveAnalysis:
            menu.add_command(label='Analysis',
                             shortcut='A',
                             command=self.ccpNmrAnalysis)
        else:
            menu.add_command(label='Analysis ** NOT INSTALLED **',
                             shortcut='A',
                             command=None)

        if haveFormatConv:
            menu.add_command(label='Format Converter',
                             shortcut='F',
                             command=self.ccpNmrFormatConverter)
            menu.add_command(label='Data Shifter',
                             shortcut='D',
                             command=self.ccpNmrDataShifter)
        else:
            menu.add_command(label='Format Converter ** NOT INSTALLED **',
                             shortcut='F',
                             command=None)
            menu.add_command(label='Data Shifter ** NOT INSTALLED **',
                             shortcut='D',
                             command=None)

        self.mainMenu.add_cascade(label='CcpNmr', shortcut='C', menu=menu)

        menu.options = ['Analysis', 'Format Converter', 'Data Shifter']
        return menu

    def ccpNmrAnalysis(self, cacheSize=64):

        from ccpnmr.analysis.AnalysisPopup import AnalysisPopup
        analysis = AnalysisPopup(self, cache_size=cacheSize, glDirect=None)
        analysis.update_idletasks()  # fast
        if self.project:
            analysis.initProject(self.project)

    def ccpNmrFormatConverter(self):

        from ccpnmr.format.gui.FormatConverter import FormatConverter
        fc = FormatConverter(self, threading=False, project=self.project)
        fc.open()
        if self.project:
            fc.initProject(self.project)

    def ccpNmrDataShifter(self):

        from ccpnmr.format.gui.DataShifter import DataShifter
        ds = DataShifter(self)
        ds.open()

    def newProject(self):

        if self.project:
            # Project already present
            if not self.closeProject():
                # If we don't close the current project do nothing
                return

        name = askString(title='Project name',
                         prompt='Enter project name:',
                         parent=self)

        if name:
            # Make the API Project object
            project = Implementation.MemopsRoot(name=name)
            nmrProject = project.newNmrProject(name=name)
            self.initProject(project)

    # placeholder method until we write code

    def tmpCall(self):

        return

    def openProject(self):

        if self.project:
            if not self.closeProject():
                return

        self.openPopup('open_project',
                       OpenProjectPopup,
                       callback=self.initProject)

    def openLoginPopup(self):

        # at the moment we do this through methods in the popup. It
        # would be much more sensible to do this through some
        # sort of callback.

        login_popup = LoginPopup(self)

        # really we want to imoblise the rest. how to do?

    def setRepository(self, rep):

        self.repList.currentRepository = rep

        if self.frameShortcuts.has_key('Repository'):
            self.frameShortcuts['Repository'].drawFrame()

        if self.frameShortcuts.has_key('Tasks'):
            self.frameShortcuts['Tasks'].drawFrame()
        #for ff in self.tabbedFrame.frames[0].children.values():
        #  ff.draw()

        #for ff in self.tabbedFrame.frames[3].children.values():
        #  ff.draw()

        for ff in self.tabbedFrame.frames[8].children.values():
            ff.draw()

    def openRepository(self):

        rep_popup = RepositoryPropertiesPopup(self)

    def closeRepository(self):

        pass

    def logout(self):

        self.setUsername(None)
        self.repList = RepositoryList()

        print 'in logout ', self.repList
        print '#########################'

        print self.tabbedFrame.frames[0].__dict__
        print '#########################'

        if self.frameShortcuts.has_key('Repository'):
            self.frameShortcuts['Repository'].drawFrame()

        #for ff in self.tabbedFrame.frames[0].children.values():
        #  ff.draw()
        for ff in self.tabbedFrame.frames[8].children.values():
            ff.draw()

    def openPopup(self, popup_name, clazz, oldStyle=False, *args, **kw):

        popup = self.popups.get(popup_name)

        if (popup):
            popup.open()
        else:
            if self.project:
                analysisProfile = self.analysisProfile
            else:
                analysisProfile = None

            if analysisProfile:
                transient = analysisProfile.transientDialogs
            else:
                transient = True

            name = popup_name

            if (oldStyle):
                popup = self.popups[popup_name] = clazz(self,
                                                        transient=transient,
                                                        *args,
                                                        **kw)
            else:
                popup = self.popups[popup_name] = clazz(self,
                                                        project=self.project,
                                                        popup_name=name,
                                                        transient=transient,
                                                        *args,
                                                        **kw)
            # above automatically opens popup

        return popup

    def closeProject(self, queryClose=True, querySave=True):

        if queryClose:
            if not showYesNo(
                    'Close project', 'Close current project?', parent=self):
                return False

        if querySave:
            if not self.checkSaving():
                return False

        self.destroyPopups()
        self.initProject()

        return True

    def saveProject(self):

        self.saveFile()

        # NBNB Rasmus 22/8/08 changed to fit AnalysisPopup (and removed 'isStored' bug)
        #if (self.project.isStored):
        #  self.saveFile()
        #else:
        #  self.askSaveFile()

    def saveAsProject(self):

        self.askSaveFile()

    def showVersion(self):

        showInfo('Version', self.versionInfo, parent=self)

    def changeFont(self, analysisProfile):

        if analysisProfile is self.analysisProfile:
            if self.font != analysisProfile.font:
                self.font = analysisProfile.font or DEFAULT_FONT
                self.setFont()

    def selectFont(self, font):  # Only called from main menu option

        if self.project:
            self.analysisProfile.font = font

    def setFont(self, font=None, popup=None):

        if font is None:
            font = self.font or DEFAULT_FONT

        else:
            self.font = font

        if not popup:
            popup = self

        childList = popup.children.values()

        classes = [
            Tkinter.Button, Tkinter.Label, Tkinter.Menu, Tkinter.Entry,
            Tkinter.Checkbutton, Tkinter.Radiobutton
        ]

        for child in childList:
            for clazz in classes:
                if isinstance(child, clazz):
                    if hasattr(child, 'font'):
                        if not child.font:
                            child.config(font=font)
                    else:
                        child.config(font=font)
                    break

            if isinstance(child, Tkinter.Frame):
                child.font = font

            elif isinstance(child, ScrolledMatrix):
                child.setFont(font)

            if hasattr(child, 'children'):
                childList.extend(child.children.values())

    def initProject(self, project=None):

        self.project = project
        if project:
            self.initTopObjects(self.project)
            self.project.application = self.application
            self.setFont()
            webBrowser = ProjectWebBrowser(self.top,
                                           popup=self,
                                           project=project)
            #self.helpButton.config(command = lambda url=self.help_url: webBrowser.open(url) )

            for i, func in enumerate(self.updateFuncs):
                func(project)

            for button in self.projButtons:
                button.enable()

            self.setupSoftware()

        else:
            for button in self.projButtons:
                button.disable()

        self.setMenuState()

    def setUsername(self, name):

        self.username = name

        print 'set username ', self.username

    # jmci FIXME

    # need to look into this carefully and analyse the possible
    # states

    def setMenuState(self):

        if self.project:
            state = Tkinter.NORMAL
        else:
            state = Tkinter.DISABLED

        # Disable bits of the project menu if there's no project
        #for option in ('Save','Save As','Close'):
        #  i = self.projectMenu.options.index(option)
        #  self.projectMenu.entryconfig(i, state=state)

        # Disable other manus if there's no project
        #for menu in [self.otherMenu,]: # Include more menus in this list
        #  for i in range(len(menu.options)):
        #    menu.entryconfig(i, state=state)

    def setupSoftware(self):

        project = self.project

        methodStore = project.currentMethodStore or \
                      project.findFirstMethodStore() or \
                      project.newMethodStore(name=project.name)

        software = methodStore.findFirstSoftware(name=PROGRAM_NAME,
                                                 version=VERSION)
        if not software:
            software = methodStore.newSoftware(name=PROGRAM_NAME,
                                               version=VERSION)

        #software.vendorName = 'PDBe & CCPN'
        #software.vendorAddress = ''
        #software.vendorWebAddress = 'http:'
        #software.details = ''

    def askSaveFile(self):

        popup = self.openPopup('save_project', SaveProjectPopup)
        popup.refresh()

    def modalAskSaveFile(self):

        popup = SaveProjectPopup(self,
                                 project=self.project,
                                 dismiss_text='Cancel Quit',
                                 modal=True)
        did_save = popup.did_save
        popup.destroy()

        return did_save

    def quitSaveProject(self):

        if (self.project.activeRepositories):
            return self.saveFile()
        else:
            return self.modalAskSaveFile()

    def destroyPopups(self):

        for key in self.popups.keys():
            popup = self.popups[key]
            popup.destroy()

        self.popups = {}

    ## WMS methods

    # should maybe merge this with setUsername

    # this will read a config file that stores user setups. How this
    # is done TBD so hack for now and just return
    def readConfig(self, userName):

        # this should return the full RepositoryList structure. In reality this
        # will parse from file. set it by hand from here for now for speed
        repList = RepositoryList(userName)

        rep1 = repList.newRepository('remote', 'localhost:8080/HalxService',
                                     'ccpn', 'remote')
        repList.currentRepository = rep1
        # should these be directory objects?
        repList.current_export_dir = '/home/jionides/work/CCPN/test_JMCI_data'
        repList.current_import_dir = '/home/jionides/work/CCPN/test_EXP_data'

        self.repList = repList

        print 'in readconfig '

        self.setRepository(rep1)

        # really should be done through notifiers
        if self.frameShortcuts.has_key('Repository'):
            self.frameShortcuts['Repository'].drawFrame()

        if self.frameShortcuts.has_key('Tasks'):
            self.frameShortcuts['Tasks'].drawFrame()

        if self.frameShortcuts.has_key('DataExch'):
            self.frameShortcuts['DataExch'].drawFrame()

        for ff in self.tabbedFrame.frames[8].children.values():
            ff.draw()

        # want to update the top menu. The idea should be to add a bar item
        # and then to list all the repositories underneath. Clicking on a given
        # repository will set the home repository as current. That seems to
        # be a good sensible way of simplifying the interface in a expected
        # way. We could, alternatively, use tabs.

        opts = {}
        self.repMenu.add('separator', **opts)

        for rep in repList.repositories:
            item = {
                'command': lambda rep=rep: self.setRepository(rep),
                'label': rep.name
            }
            self.repMenu.add('comman', **item)

        self.repMenu.config()

    ## end WMS methods

    def copyModifiedStorages(self):

        modifiedStorages = [
            storage for storage in self.project.storages if storage.isModified
        ]
        if (self.project.isModified):
            modifiedStorages.append(self.project)

        for storage in modifiedStorages:
            self.copyStorage(storage)

    def saveFile(self):

        if not self.project:
            return False

        try:
            saveProject(self.project, createFallback=True)

            print 'successfully saved project'
            return True
        except IOError, e:
            showError('Saving file', str(e), parent=self)
            return False
    def body(self, guiFrame):

        self.geometry('600x600')

        guiFrame.expandGrid(0, 0)

        tipTexts = [
            'A table of all the NMR measurement lists in the project, including shift lists, T1 lists, J-coupling lists etc.',
            'A table listing all of the individual measurements within an NMR measurement list'
        ]
        options = ['Measurement Lists', 'Measurements Table']
        tabbedFrame = TabbedFrame(guiFrame,
                                  options=options,
                                  grid=(0, 0),
                                  tipTexts=tipTexts)
        self.tabbedFrame = tabbedFrame
        frameA, frameB = tabbedFrame.frames

        # Measurement Lists

        frameA.expandGrid(1, 0)
        self.detailsEntry = Entry(self,
                                  text='',
                                  returnCallback=self.setDetails,
                                  width=12)
        self.nameEntry = Entry(self,
                               text='',
                               returnCallback=self.setName,
                               width=12)

        row = 0
        frame0 = Frame(frameA, grid=(row, 0), gridSpan=(1, 2))
        frame0.grid_columnconfigure(2, weight=1)

        label = Label(frame0, text='Experiment:', grid=(0, 0), sticky='e')

        tipText = 'Selects an experiment, if required, to restrict the measurement list table display; showing only lists which were derived using the experiment'
        self.experimentPulldown = PulldownList(frame0,
                                               callback=self.setExperiment,
                                               grid=(0, 1),
                                               tipText=tipText)

        row += 1
        tipTexts = [
            'The serial number of measurement list',
            'The type of measurement list, e.g. shift list, T1 list, J coupling list',
            'A short identifying name for the list, for graphical displays',
            'The number of measurements contained within the list',
            'The unit of measurement used for the values in the list',
            'The names of the experiments which were used to derive the measurements',
            'A user-specified textual comment for the measurement list'
        ]
        justifyList = [
            'center', 'center', 'center', 'center', 'center', 'left'
        ]
        #colHeadings      = ['List Type','Name','Size','Unit','Experiments','Other Info','Details']
        colHeadings = [
            '#', 'List Type', 'Name', 'Size', 'Unit', 'Experiments', 'Details'
        ]
        editWidgets = [
            None, None, self.nameEntry, None, None, None, None,
            self.detailsEntry
        ]
        editGetCallbacks = [
            None, None, self.getName, None, None, None, None, self.getDetails
        ]
        editSetCallbacks = [
            None, None, self.setName, None, None, None, None, self.setDetails
        ]

        self.listsMatrix = ScrolledMatrix(
            frameA,
            grid=(row, 0),
            gridSpan=(1, 2),
            justifyList=justifyList,
            editSetCallbacks=editSetCallbacks,
            editGetCallbacks=editGetCallbacks,
            editWidgets=editWidgets,
            headingList=colHeadings,
            callback=self.selectListCell,
            deleteFunc=self.deleteMeasurementList,
            tipTexts=tipTexts)

        row += 1
        tipTexts = [
            'Show a table of the individual measurements within the selected measurement list',
            'Make a new, blank chemical shift list within the project',
            'Make a synthetic chemical shift list using random coil values, adjusting protein backbone values for sequence where approprate',
            'Delete the selected measurement list'
        ]
        texts = [
            'Show Measurements', 'New Shift List',
            'Make Random Coil Shift List', 'Delete'
        ]
        commands = [
            self.showMeasurements, self.addShiftList,
            self.makeRandomCoilShiftList, self.deleteMeasurementList
        ]
        self.listButtons = ButtonList(frameA,
                                      texts=texts,
                                      commands=commands,
                                      grid=(row, 0),
                                      gridSpan=(1, 2),
                                      tipTexts=tipTexts)

        # Measurements

        self.measurementDetailsEntry = Entry(
            self, text='', returnCallback=self.setMeasurementDetails, width=12)
        self.measurementMeritEntry = FloatEntry(
            self, returnCallback=self.setMeasurementMerit, width=6)

        row = 0
        frame0 = Frame(frameB, grid=(row, 0))
        frame0.grid_columnconfigure(2, weight=1)

        label = Label(frame0,
                      text='Measurement List:',
                      grid=(0, 0),
                      sticky='e')

        tipText = 'Selects the measurement list to display measurements for'
        self.listPulldown = PulldownList(frame0,
                                         callback=self.setMeasurementList,
                                         grid=(0, 1),
                                         tipText=tipText)

        row += 1
        frameB.expandGrid(row, 0)
        tipTexts = [
            'The serial number of the measurement within its containing list',
            'The number or assignment of the NMR resonance(s) to which the measurement applies',
            'The numeric value of the NMR measurement on the specified resonance(s), and the unit of measurement',
            'The standard deviation error in the measured value',
            'The molecular chain, if any, to which the measurement relates by virtue of atom assigned resonances',
            'The isotope type(s) of the measures resonance(s)',
            'A figure-of-merit value for the measurement indicating its quality or reliability',
            'The number of peaks in the CCPN project used to take the measurement',
            'A user-defined textual comment for the measurement'
        ]
        justifyList = [
            'center', 'center', 'center', 'center', 'center', 'center',
            'center', 'center', 'center', 'left'
        ]
        colHeadings = [
            '#', 'Resonance', 'Value', 'SD', 'Chain', 'Isotope',
            'Fig of\nMerit', 'Peaks', 'Details'
        ]
        editWidgets = [
            None, None, None, None, None, None, self.measurementMeritEntry,
            None, self.measurementDetailsEntry
        ]
        editGetCallbacks = [
            None, None, None, None, None, None, self.getMeasurementMerit,
            self.showPeaks, self.getMeasurementDetails
        ]
        editSetCallbacks = [
            None, None, None, None, None, None, self.setMeasurementMerit, None,
            self.setMeasurementDetails
        ]

        self.measurementsMatrix = ScrolledMatrix(
            frameB,
            grid=(row, 0),
            multiSelect=True,
            tipTexts=tipTexts,
            justifyList=justifyList,
            editSetCallbacks=editSetCallbacks,
            editGetCallbacks=editGetCallbacks,
            editWidgets=editWidgets,
            headingList=colHeadings,
            callback=self.selectMeasurementCell)

        row += 1
        tipTexts = [
            'Show a table containing peaks that were used to derive the selected measurements',
            'For some measurement lists (currently only shift lists) manually trigger a recalculation of values',
            'Show a table containing the resonances that relate to the selected measurements',
            'Delete the selected measurement records; cannot be done for chemical shift values still ties to peaks via assignment'
        ]
        texts = ['Show Peaks', 'Recalculate', 'Show Resonances', 'Delete']
        commands = [
            self.showPeaks, self.recalculateMeasurements, self.showResonances,
            self.deleteMeasurements
        ]
        self.measurementButtons = ButtonList(frameB,
                                             texts=texts,
                                             grid=(row, 0),
                                             commands=commands,
                                             tipTexts=tipTexts)

        # Main Frame

        self.bottomButtons = UtilityButtonList(tabbedFrame.sideFrame,
                                               helpUrl=self.help_url,
                                               grid=(0, 0),
                                               gridSpan=(1, 2),
                                               sticky='e')

        self.updateMeasurementListAfter()
        self.updateMeasurementsAfter()

        self.administerNotifiers(self.registerNotify)
Exemple #17
0
    def body(self, guiParent):

        self.geometry('700x600')

        # Ensure that the first row and column in popup expand
        guiParent.grid_rowconfigure(0, weight=1)
        guiParent.grid_columnconfigure(0, weight=1, minsize=200)
        frame = Frame(guiParent)  # Body widgets can be put in this frame
        frame.grid()

        # this is going to set up the options on the tabs. Really we need
        # stronger bookeeping between the options and the frames.  it
        # might make sense to define a master dictionary with option_name
        # => index. We can use this dictionary to build up the software
        # options and can also use it to define any refreshes etc (although
        # these would be better done through notifiers)

        softwareOpts = [
            'Repository', 'Project', 'Process', 'Client Tasks', 'Server Tasks',
            'Data Exchange', 'Workflow', 'Protocols', 'User'
        ]

        # FIXME JMCI

        # we should have a tidier tabbed frame. ned to discuss rules with
        # tjs but it would seem to make sense to have the tabs stretch
        # across the entire top of the frame. Check the existing options
        # first, though

        self.tabbedFrame = TabbedFrame(guiParent,
                                       options=softwareOpts,
                                       toggleOff=False,
                                       selected=0)
        self.tabbedFrame.grid(row=0, column=0, sticky='nsew')

        frames = self.tabbedFrame.frames

        # Logos
        ccpnDir = getTopDirectory()
        imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images')
        imageFile = os.path.join(imageDir, 'CcpnLogo.gif')
        self.ccpnLogo = Tkinter.PhotoImage(file=imageFile)

        # Dictionary to store popups opened by this application - e.g. need to close upon quit
        self.popups = {}

        # Default font
        self.font = 'Helvetica 10'

        # Closing the window from the desktop environment calls the proper quit
        self.protocol('WM_DELETE_WINDOW', self.quit)

        # jmci we are going to have to change these drastically
        self.mainMenu = Menu(self)
        self.userMenu = self.makeUserMenu()
        self.repositoryMenu = self.makeRepositoryMenu()
        self.otherMenu = self.makeOtherMenu()

        # Put the top level menu
        self.config(menu=self.mainMenu)
        self.initRepository(frames[0])
        self.initProjectFrame(frames[1])
        self.initWms(frames[2])
        self.initTasks(frames[3])
        self.initDataExch(frames[5])
        self.initWorkflow(frames[6])
        self.initProtocol(frames[7])
        self.initUserFrame(frames[8])

        self.initProject()

        if not self.project:
            for button in self.projButtons:
                button.disable()

        # the main client side daemon. This is going to run in the background
        # and control the task processing
        self.taskDaemon = TaskManager(self)
        self.taskDaemon.active = False
        self.taskDaemon.start()
Exemple #18
0
    def __init__(self,
                 parent,
                 project,
                 closeButton=False,
                 tempFiles=False,
                 *args,
                 **kw):

        ###########################################################################
        # INIT VARIABLES

        self.parent = parent
        self.project = project

        try:
            self.nmrProject = (project.currentNmrProject or
                               project.newNmrProject(name='BLACKLEDGE_MODULE'))
        except:
            print '&&& Running MODULE popup from outside CCPN Analysis - debug only - no NmrCalc'
            self.nmrProject = None

        if self.nmrProject:
            self.calcStore = project.findFirstNmrCalcStore(name=MODULE, nmrProject=self.nmrProject) or \
                             project.newNmrCalcStore(name=MODULE, nmrProject=self.nmrProject)

        else:
            self.calcStore = None

        self.run = None

        self.inputStructure = None
        self.inputRdcConstraintList = None
        self.inputDistanceConstraintList = [None]
        self.inputUserDescriptionText = None

        # path to the module executable
        modPath = subprocess.Popen(
            ['which', 'module'],
            stdout=subprocess.PIPE).communicate()[0].strip()
        self.moduleExePath = modPath or '    NB. MODULE executable not found    '

        self.waiting = False

        # for debug this could be False
        if tempFiles:
            self.useTempFiles = True
        else:
            self.useTempFiles = False

        # create temp files for MODULE
        if self.useTempFiles:
            self.moduleTempDir = tempfile.mkdtemp(prefix='MODULE-')
        else:
            self.moduleTempDir = os.getcwd()

        #djo35# self.calcStore = self.resetCalcStore(name='BLACKLEDGE_MODULE')

        # END INIT OF VARIABLES
        ###########################################################################

        ###########################################################################
        # START GUI CODE

        Frame.__init__(self, parent, *args, **kw)

        self.expandGrid(0, 0)

        ## Single Frame
        # frame = Frame(self, grid=(0,0))

        # or with Tabs?
        options = ['Launch', 'Output', 'Runs']
        tabbedFrame = TabbedFrame(self, options=options, grid=(0, 0))
        frameA, frameB, frameC = tabbedFrame.frames
        self.tabbedFrame = tabbedFrame

        frameA.expandGrid(14, 2)

        row = 0
        div = LabelDivider(frameA,
                           text='MODULE Setup',
                           grid=(row, 0),
                           gridSpan=(1, 4))

        row += 1
        # allow the user to choose MODULE if either the one in PATH is incorrect or not found
        button = Button(frameA, text='Select MODULE executable:',bd=1, \
                                command=self.selectExecutable,  grid=(row,0), sticky="ew")
        self.moduleExeEntry = Entry(frameA, text=self.moduleExePath, grid=(row,1), gridSpan=(1,3), \
                                width=32, sticky="ew", bd=1)
        self.moduleExePath = self.moduleExeEntry.get()

        # separator "MODULE input"
        row += 1
        div = LabelDivider(frameA,
                           text='MODULE input',
                           grid=(row, 0),
                           gridSpan=(1, 5))

        row += 1
        label = Label(frameA, text='Structure:', grid=(row, 1))
        self.inputStructurePulldown = PulldownList(frameA, self.changeInputStructure, \
                                                        grid=(row,2))
        # self.constraintsFileEntry.bind('<Leave>', self.updateEntryParams)

        row += 1
        label = Label(frameA, text='RDC constraints:', grid=(row, 1))
        self.inputRdcConstraintsPulldown = PulldownList(frameA, self.changeInputRdcConstraintList, \
                                                        grid=(row,2))
        #self.constraintsFileEntry.bind('<Leave>', self.updateEntryParams)

        row += 1
        label = Label(frameA, text='(Optional input)', grid=(row, 0))
        label = Label(frameA, text='Distance constraints:', \
                                                        grid=(row,1))
        self.inputDistanceConstraintsPulldown = PulldownList(frameA, self.changeInputDistanceConstraintList, \
                                                        grid=(row,2))
        #self.constraintsFileEntry.bind('<Leave>', self.updateEntryParams)

        row += 1

        subFrameDepth = 4
        subframe = LabelFrame(frameA, text='MODULE User Notes (store notes about how MODULE was run here)', \
                                                        grid=(row,0), gridSpan=(1,4))
        subframe.expandGrid(subFrameDepth, 0)

        self.moduleUserText = ScrolledText(subframe)
        self.moduleUserText.grid(row=subFrameDepth,
                                 column=0,
                                 columnspan=4,
                                 sticky='nsew')

        # View Results
        row += subFrameDepth

        # row += 1
        # div = LabelDivider(frameA, text='MODULE launch', grid=(row,0), gridSpan=(1,4))

        row += 1
        button = Button(frameA, text='Run MODULE', bd=1, command=self.executeModule, \
                                                        grid=(row,0), gridSpan=(1,4), sticky="ew", bg=MODULE_GREEN)
        # grid=(row,0), gridSpan=(1,2), sticky="ew", bg=MODULE_GREEN)

        ###########################################################################
        # Frame B (tab 2) Ouput
        frameB.expandGrid(4, 1)
        row = 0

        subFrameDepth = 6
        subframe = LabelFrame(frameB, text='MODULE Output', \
                                                        grid=(row,0), gridSpan=(1,5))
        #subframe.grid_columnconfigure(2, weight=1)
        subframe.expandGrid(subFrameDepth, 0)

        self.moduleOutputText = ScrolledText(subframe)
        self.moduleOutputText.setState(state=Tkinter.DISABLED)
        self.moduleOutputText.grid(row=subFrameDepth,
                                   column=0,
                                   columnspan=4,
                                   sticky='nsew')

        # separator "MODULE input"
        row += 1
        div = LabelDivider(frameB,
                           text='MODULE RDC Back Values',
                           grid=(row, 0),
                           gridSpan=(1, 5))

        row += 1
        button = Button(frameB, text='Import MODULE Back Values file', bd=1, command=self.importModuleBackValues, \
                                                        grid=(row,0), gridSpan=(1,4), sticky="ew", bg=MODULE_BLUE)
        # grid=(row,0), gridSpan=(2,4), sticky="ew", bg=MODULE_BLUE)

        row += 1
        self.rdcOutputTable = None
        frameB.grid_rowconfigure(row, weight=1)
        headings = ('#', 'Resonances', 'Value', 'Back Value', 'Diff.', 'Error')

        editWidgets = [None, None, None, None, None, None]
        editGetCallbacks = [None, None, None, None, None, None]
        editSetCallbacks = [None, None, None, None, None, None]

        self.rdcOutputTable = ScrolledMatrix(frameB,
                                             headingList=headings,
                                             multiSelect=False,
                                             editWidgets=editWidgets,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks,
                                             initialRows=4)

        self.rdcOutputTable.grid(row=row,
                                 column=0,
                                 columnspan=4,
                                 sticky='nsew')

        row += 1
        button = Button(frameB, text='Import MODULE Structure', bd=1, command=self.importModuleStructure, \
                                                        grid=(row,0), gridSpan=(1,4), sticky="ew", bg=MODULE_BLUE)
        # grid=(row,0), gridSpan=(2,4), sticky="ew", bg=MODULE_BLUE)

        ###########################################################################
        # Frame C (tab 3) NMR Calc display bits
        frameC.expandGrid(4, 1)
        row = 0

        div = LabelDivider(frameC,
                           text='Stored MODULE Runs',
                           grid=(row, 0),
                           gridSpan=(1, 5))

        # NmrCalc Run scrolled matrix
        row += 1
        self.runTable = None
        frameC.grid_rowconfigure(row, weight=1)
        headings = ('Run ID', 'notes', 'Status')

        # self.editRunNotes = DataEntry.askString('Run Notes', 'Edit notes about Run', tipText='Notes about Run', parent=self)
        # editWidgets       = [None, self.editRunNotes, None]

        editWidgets = [None, None, None]
        editGetCallbacks = [None, None, None]
        editSetCallbacks = [None, None, None]

        self.runTable = ScrolledMatrix(frameC,
                                       headingList=headings,
                                       multiSelect=False,
                                       editWidgets=editWidgets,
                                       editGetCallbacks=editGetCallbacks,
                                       editSetCallbacks=editSetCallbacks,
                                       initialRows=4)

        self.runTable.grid(row=row, column=0, columnspan=4, sticky='nsew')

        row += 4
        tipTexts = ['Load Selected Run', 'Delete Selected Run']
        texts = ['Load Selected Run', 'Delete Selected']
        commands = [self.loadRun, self.deleteRun]
        colours = [MODULE_GREEN, MODULE_RED]
        self.runButtons = ButtonList(frameC,
                                     texts=texts,
                                     tipTexts=tipTexts,
                                     commands=commands,
                                     grid=(row, 0),
                                     gridSpan=(1, 4))
        self.runButtons.buttons[0].config(bg=MODULE_GREEN)
        self.runButtons.buttons[1].config(bg=MODULE_RED)

        ###########################################################################
        # Keep GUI up to date

        self.updateAfter()
        self.administerNotifiers(self.parent.registerNotify)
Exemple #19
0
    def body(self, guiFrame):

        self.geometry('600x350')

        guiFrame.expandGrid(0, 0)

        tipTexts = ['', '', '', '']
        options = [
            'Find Parameters', 'Spectrum Widths', 'Diagonal Exclusions',
            'Region Peak Find'
        ]
        tabbedFrame = TabbedFrame(guiFrame, options=options, grid=(0, 0))

        frameA, frameB, frameC, frameD = tabbedFrame.frames
        self.tabbedFrame = tabbedFrame

        # Find Params

        frameA.expandGrid(2, 0)

        row = 0
        label = LabelFrame(frameA,
                           text='Extrema to search for:',
                           grid=(row, 0),
                           gridSpan=(1, 2))
        label.expandGrid(0, 1)

        entries = ['positive and negative', 'positive only', 'negative only']
        tipTexts = [
            'Sets whether peak picking within spectra find intensity maxima, minima or both maxima and minima',
        ]
        self.extrema_buttons = RadioButtons(label,
                                            entries=entries,
                                            select_callback=self.apply,
                                            direction='horizontal',
                                            grid=(0, 0),
                                            tipTexts=tipTexts)

        row += 1
        label = LabelFrame(frameA,
                           text='Nearby points to check:',
                           grid=(row, 0),
                           gridSpan=(1, 2))
        label.expandGrid(None, 1)

        entries = ['+-1 in at most one dim', '+-1 allowed in any dim']
        tipTexts = [
            'Sets how permissive the peak picking in when searching for intensity extrema; by adding extra points to the selected search region',
        ]
        self.adjacent_buttons = RadioButtons(label,
                                             entries=entries,
                                             select_callback=self.apply,
                                             direction='horizontal',
                                             grid=(0, 0),
                                             tipTexts=tipTexts)

        row += 1
        labelFrame = LabelFrame(frameA,
                                text='Other parameters:',
                                grid=(row, 0),
                                gridSpan=(1, 2))
        labelFrame.expandGrid(5, 2)

        frow = 0
        label = Label(labelFrame,
                      text='Scale relative to contour levels:',
                      grid=(frow, 0),
                      sticky='e')
        tipText = 'Threshold above which peaks are picked, relative to the lowest displayed contour; 1.0 means picking exactly what is visible'
        self.scale_entry = FloatEntry(labelFrame,
                                      grid=(frow, 1),
                                      tipText=tipText,
                                      returnCallback=self.apply,
                                      width=10)
        self.scale_entry.bind('<Leave>', self.apply, '+')

        frow += 1
        label = Label(labelFrame,
                      text='Exclusion buffer around peaks (in points):',
                      grid=(frow, 0),
                      sticky='e')
        tipText = 'The size of the no-pick region, in data points, around existing picked peaks; eliminates duplicate picking'
        self.buffer_entry = IntEntry(labelFrame,
                                     returnCallback=self.apply,
                                     grid=(frow, 1),
                                     width=10,
                                     tipText=tipText)
        self.buffer_entry.bind('<Leave>', self.apply, '+')

        frow += 1
        label = Label(labelFrame,
                      text='Extra thickness in orthogonal dims (in points):',
                      grid=(frow, 0),
                      sticky='e')
        tipText = 'Sets whether to consider any additional planes (Z dimension) when calculating peak volume integrals'
        self.thickness_entry = IntEntry(labelFrame,
                                        returnCallback=self.apply,
                                        width=10,
                                        grid=(frow, 1),
                                        tipText=tipText)
        self.thickness_entry.bind('<Leave>', self.apply, '+')

        frow += 1
        label = Label(labelFrame,
                      text='Minimum drop factor (0.0-1.0):',
                      grid=(frow, 0),
                      sticky='e')
        tipText = ''
        self.drop_entry = FloatEntry(labelFrame,
                                     returnCallback=self.apply,
                                     width=10,
                                     grid=(frow, 1),
                                     tipText=tipText)
        self.drop_entry.bind('<Leave>', self.apply, '+')

        frow += 1
        label = Label(labelFrame,
                      text='Volume method:',
                      grid=(frow, 0),
                      sticky='e')
        tipText = 'Selects which method to use to calculate peak volume integrals when peaks are picked; box sizes are specified in "Spectrum Widths"'
        self.method_menu = PulldownList(labelFrame,
                                        texts=PeakBasic.PEAK_VOLUME_METHODS,
                                        grid=(frow, 1),
                                        callback=self.apply,
                                        tipText=tipText)

        # Spectrum widths

        frameB.expandGrid(1, 1)

        label = Label(frameB, text='Spectrum: ')
        label.grid(row=0, column=0, sticky='e')

        tipText = 'The spectrum which determines the widths being shown'
        self.expt_spectrum = PulldownList(frameB,
                                          tipText=tipText,
                                          callback=self.setSpectrumProperties)
        self.expt_spectrum.grid(row=0, column=1, sticky='w')

        self.editLinewidthEntry = FloatEntry(self,
                                             text='',
                                             returnCallback=self.setLinewidth,
                                             width=10)
        self.editBoxwidthEntry = FloatEntry(self,
                                            text='',
                                            returnCallback=self.setBoxwidth,
                                            width=10)
        tipTexts = [
            'The number of the spectrum dimension to which the settings apply',
            'The nuclear isotope measures in the spectrum dimension',
            'The smallest value for the linewidth of a peak for it to be picked',
            'The size of the spectrum region to perform the volume integral over'
        ]
        headingList = [
            'Dimension', 'Isotope', 'Minimum Linewidth (Hz)', 'Boxwidth'
        ]
        editSetCallbacks = [None, None, self.setLinewidth, self.setBoxwidth]
        editGetCallbacks = [None, None, self.getLinewidth, self.getBoxwidth]
        editWidgets = [
            None, None, self.editLinewidthEntry, self.editBoxwidthEntry
        ]
        self.spectrumMatrix = ScrolledMatrix(frameB,
                                             initialRows=6,
                                             editSetCallbacks=editSetCallbacks,
                                             editGetCallbacks=editGetCallbacks,
                                             editWidgets=editWidgets,
                                             headingList=headingList,
                                             callback=self.selectCell,
                                             tipTexts=tipTexts)
        self.spectrumMatrix.grid(row=1, column=0, columnspan=2, sticky='nsew')

        # Diagonal Exclusions

        frameC.expandGrid(0, 0)

        tipTexts = [
            'The isotope as measures on the axis of a spectrum window',
            'The distance from the homonuclear diagonal line within which no peak picking can occur'
        ]
        self.exclusionEntry = FloatEntry(self,
                                         text='',
                                         returnCallback=self.setExclusion,
                                         width=10)
        headingList = ['Isotope', 'Diagonal Exclusion (ppm)']
        editSetCallbacks = [None, self.setExclusion]
        editGetCallbacks = [None, self.getExclusion]
        editWidgets = [None, self.exclusionEntry]
        self.isotopeMatrix = ScrolledMatrix(frameC,
                                            editSetCallbacks=editSetCallbacks,
                                            editGetCallbacks=editGetCallbacks,
                                            editWidgets=editWidgets,
                                            headingList=headingList,
                                            grid=(0, 0),
                                            tipTexts=tipTexts)

        # Region peak find

        self.regionFindPeakList = None
        self.regionCondition = None
        self.regionConditions = []
        self.regionCol = 1

        row = 0

        label = Label(frameD, text='Peak List: ', grid=(0, 0))
        tipText = 'Selects which peak list to perform region-wide peak picking for'
        self.regionPeakListPulldown = PulldownList(
            frameD,
            callback=self.changeRegionPeakList,
            grid=(0, 1),
            tipText=tipText)

        row += 1
        frameD.expandGrid(row, 1)

        self.regionEntry = FloatEntry(self,
                                      text='',
                                      returnCallback=self.setRegion,
                                      width=10)
        self.conditionMenu = PulldownList(self,
                                          texts=('include', 'exclude'),
                                          callback=self.setCondition)

        tipTexts = [
            'Whether to include or exclude the states region from region-wide peak picking',
        ]
        headingList = ['Condition']
        editSetCallbacks = [None]
        editGetCallbacks = [None]
        editWidgets = [self.conditionMenu]
        self.regionFindMatrix = ScrolledMatrix(
            frameD,
            headingList=headingList,
            callback=self.selectRegionCell,
            editWidgets=editWidgets,
            editGetCallbacks=editGetCallbacks,
            editSetCallbacks=editSetCallbacks,
            grid=(row, 0),
            gridSpan=(1, 2))

        row += 1
        tipTexts = [
            'Sets the currently selected region row to cover the whole spectrum',
            'Add a new region row, which may them be set for exclusion or inclusion when peak picking large areas',
            'Remove the selected region specification',
            'Go to the panel for setting the parameters that control how peaks extrema are picked',
            'Using the stated regions and parameters, perform region-wide peak picking'
        ]
        texts = [
            'Whole Region', 'Add Region', 'Delete Region', 'Adjust Params',
            'Find Peaks!'
        ]
        commands = [
            self.wholeRegion, self.addCondition, self.deleteCondition,
            self.adjustParams, self.regionFindPeaks
        ]

        buttons = ButtonList(frameD,
                             texts=texts,
                             commands=commands,
                             grid=(row, 0),
                             gridSpan=(1, 2),
                             tipTexts=tipTexts)
        buttons.buttons[4].config(bg='#B0FFB0')

        utilButtons = UtilityButtonList(tabbedFrame.sideFrame,
                                        grid=(0, 0),
                                        helpUrl=self.help_url,
                                        sticky='e')

        self.dataDim = None
        self.setParamsEntries()
        self.updateSpectrum()
        self.setIsotopeProperties()
        self.updateRegionPeakLists()

        self.administerNotifiers(self.registerNotify)
Exemple #20
0
class ApplicationPopup(AnalysisPopup):

    help_url = 'http://www.ccpn.ac.uk'

    allowedCallbackFuncnames = ('init', 'save', 'close')

    def __init__(self, root, programName='Extend-NMR Interface'):

        self.font = DEFAULT_FONT
        # Application object needed to store application-specific data with project
        self.application = Application(name=PROGRAM_NAME)
        self.versionInfo = 'Version' + VERSION
        self.ariaProjectFile = None
        self.doneAnalysisInfo = False

        self.updateFuncs = []
        self.projButtons = []

        self.ariaPaths = []
        self.isdPaths = []

        AnalysisPopup.__init__(self, root)

        self.program_name = PROGRAM_NAME
        self.setTitle(PROGRAM_NAME)

    def printAnalysisCommandLineInfo(self, event):

        if not self.doneAnalysisInfo:
            Analysis.printCommandLineInfo(self)
            self.doneAnalysisInfo = True

    def printCommandLineInfo(self):

        print """
 For program documentation see:
 http://www.extend-nmr.eu   
    """

    def body(self, guiParent):

        self.menus = {}
        self.menu_items = {}

        self.fixedActiveMenus = {}

        self.popups = {}

        self.callbacksDict = {}

        self.selected_objects = []

        self.menubar = menubar = Menu(guiParent)

        self.font = DEFAULT_FONT

        self.setProjectMenu()
        #

        menu = Menu(self.menubar, tearoff=0)
        menu.bind('<Button>', self.printAnalysisCommandLineInfo)
        self.menubar.add_cascade(label='CcpNmr Analysis',
                                 shortcut='C',
                                 menu=menu)
        self.menubar.add_command(label='FormatConverter',
                                 shortcut='F',
                                 command=self.runFormatConverter)

        self.menubar = menu
        self.initProject()
        self.setPeaksMenu()
        self.setMoleculeMenu()
        self.setAssignMenu()
        self.setResonanceMenu()
        self.setDataMenu()
        self.setStructureMenu()
        self.setChartMenu()
        self.setMacroMenu()
        self.setOtherMenu()
        self.setMenuState()  # need to do it again because of OtherMenu state

        # Help Submenu

        helpMenu = Menu(self.menubar, tearoff=0)
        helpMenu.add_command(label='Version',
                             shortcut='V',
                             command=self.showVersion)
        helpMenu.add_command(label='About',
                             shortcut='A',
                             command=self.showAbout)
        helpMenu.add_command(label='Help', shortcut='H', command=self.showHelp)

        menu.add_separator()
        menu.add_command(label='CCPN Updates',
                         shortcut='U',
                         image=self.iconRefresh,
                         compound='left',
                         command=self.updateAnalysis,
                         tipText='Get any new patches and updates to CcpNmr')
        menu.add_cascade(label='CCPN Help',
                         shortcut='H',
                         image=self.iconHelp,
                         compound='left',
                         menu=helpMenu)

        self.config(menu=menubar)

        # Ensure that the first row and column in popup expand
        guiParent.grid_rowconfigure(0, weight=1)
        guiParent.grid_columnconfigure(0, weight=1, minsize=200)
        frame = Frame(guiParent)  # Body widgets can be put in this frame
        frame.grid()

        softwareOpts = [
            'Extend-NMR', 'ARIA 2', 'Auremol', 'CING', ' ECI ', 'HADDOCK',
            ' ISD ', 'PRODECOMP'
        ]

        self.tabbedFrame = TabbedFrame(guiParent,
                                       options=softwareOpts,
                                       toggleOff=False,
                                       selected=0,
                                       callback=self.toggleTab)
        self.tabbedFrame.grid(row=0, column=0, sticky='nsew')

        frames = self.tabbedFrame.frames

        # Logos
        ccpnDir = getTopDirectory()

        imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images')

        imageFile = os.path.join(imageDir, 'Fp6Logo.gif')
        self.fp6Logo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CingLogo.gif')
        self.cingLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AriaLogo.gif')
        self.ariaLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'IsdLogo.gif')
        self.isdLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'HaddockLogo.gif')
        self.haddockLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AuremolLogo.gif')
        self.auremolLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CcpnLogo.gif')
        self.ccpnLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'ProdecompLogo.gif')
        self.prodecompLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MddLogo.gif')
        self.mddLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'BrukerLogo.gif')
        self.brukerLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MsdLogo.gif')
        self.msdLogo = Tkinter.PhotoImage(file=imageFile)

        self.initExtendNmr(frames[0])

        self.initAria(frames[1])

        self.initAuremol(frames[2])

        self.initCing(frames[3])

        self.initEci(frames[4])

        self.initHaddock(frames[5])

        self.initIsd(frames[6])

        self.initProdecomp(frames[7])

        self.initProject(self.project)

        if not self.project:
            for button in self.projButtons:
                button.disable()

        self.geometry('680x670')

    def setProjectMenu(self):
        ProjectMenu = 'Project'

        # Imports submenu

        importsMenu = Menu(self.menubar, tearoff=False)
        importsMenu.add_command(label='Via Format Converter',
                                shortcut='F',
                                command=self.runFormatConverter)
        importsMenu.add_command(label='NMR-STAR 2.1.1',
                                command=self.importNmrStar211)
        importsMenu.add_command(label='NMR-STAR 3.1',
                                shortcut='N',
                                command=self.importNmrStar31)
        importsMenu.add_command(label='PDB 3.20',
                                shortcut='P',
                                command=self.importPdb)
        importsMenu.add_command(label='Coordinates (PDB-style)',
                                shortcut='C',
                                command=self.importCoordinates)

        # Preferences submenu

        fontsMenu = FontMenu(self.menubar,
                             self.selectFont,
                             sizes=(8, 10, 12),
                             doItalic=False,
                             doBoldItalic=False,
                             tearoff=0)

        prefsMenu = Menu(self.menubar, tearoff=False)
        prefsMenu.add_cascade(
            label='Fonts',
            shortcut='F',
            image=self.iconFont,
            compound='left',
            menu=fontsMenu,
            tipText='Select font to use in the graphical interface')
        prefsMenu.add_command(label='Colour Schemes',
                              image=self.iconTable,
                              compound='left',
                              shortcut='C',
                              tipText='Edit and create colour schemes',
                              command=self.editColorSchemes)
        prefsMenu.add_command(
            label='Residue Codes',
            image=self.iconTable,
            compound='left',
            shortcut='R',
            tipText=
            'User-specified codes that override the standard residue names',
            command=self.editResidueCodes)
        prefsMenu.add_command(label='User Options',
                              image=self.iconTable,
                              compound='left',
                              shortcut='U',
                              tipText='General options for Analysis behaviour',
                              command=self.editProfiles)

        #

        menu = Menu(self.menubar, tearoff=0)
        menu.add_command(
            label='New',
            shortcut='N',
            image=self.iconNewWindow,
            compound='left',
            command=self.newProject,
            tipText='Create a new, blank CCPN project (closes any open project)'
        )
        menu.add_command(
            label='Open Project',
            shortcut='O',
            image=self.iconOpen,
            compound='left',
            command=self.openProject,
            tipText=
            'Open a new CCPN project by selecting a project directory on disk')
        menu.add_command(
            label='Open Spectra',
            shortcut='p',
            image=self.iconOpenFile,
            compound='left',
            command=self.openSpectrum,
            tipText=
            'Open spectrum data fom disk, creating a default CCPN project if needed'
        )
        menu.add_command(label='Save',
                         shortcut='S',
                         image=self.iconSave,
                         compound='left',
                         command=self.saveProject,
                         tipText='Save the current CCPN project on disk')
        menu.add_command(
            label='Save As',
            shortcut='A',
            image=self.iconSaveAs,
            compound='left',
            command=self.saveAsProject,
            tipText=
            'Save the current CCPN project under a different name (project directory)'
        )
        menu.add_cascade(label='Import',
                         shortcut='I',
                         image=self.iconImport,
                         compound='left',
                         menu=importsMenu)
        menu.add_command(label='Close',
                         shortcut='C',
                         image=self.iconClose,
                         compound='left',
                         command=self.closeProject,
                         tipText='Close the current CCPN project')
        menu.add_command(
            label='Quit',
            shortcut='Q',
            image=self.iconQuit,
            compound='left',
            command=self.quit,
            tipText='Quit Extend-NMR, closing any open CCPN project')
        menu.add_separator()
        menu.add_cascade(label='Preferences',
                         shortcut='P',
                         image=self.iconPrefs,
                         compound='left',
                         menu=prefsMenu)
        menu.add_command(
            label='Validate',
            shortcut='V',
            image=self.iconTool,
            compound='left',
            command=self.validateProject,
            tipText=
            'Check the current CCPN project for data model consistency errors')
        menu.add_command(
            label='Backup',
            shortcut='B',
            image=self.iconTool,
            compound='left',
            command=self.backupProject,
            tipText='Setup options for automated backup of CCPN project data')
        menu.add_command(
            label='Archive',
            shortcut='r',
            image=self.iconTool,
            compound='left',
            command=self.archiveProject,
            tipText=
            'Save the current CCPN project in an archived form, e.g. tar gzipped'
        )

        self.menubar.add_cascade(label=ProjectMenu, shortcut='j', menu=menu)
        self.menus[ProjectMenu] = menu
        self.menu_items[ProjectMenu] = [
            'New',
            'Open Project',
            'Open Spectra',
            'Save',
            'Save As',
            'Import',
            'Close',
            'Quit',
            'Preferences',
            'Validate',
            'Backup',
            'Archive',
        ]

        # Menus that area ctive in absence of a project
        #for ii in (0,1,2,7,13,15):
        for ii in (
                0,
                1,
                2,
                7,
        ):
            self.fixedActiveMenus[(ProjectMenu, ii)] = True

    def setPopupGeometries(self):

        for key in self.popups.keys():
            popup = self.popups[key]
            if not key.startswith(window_popup_prefix):  # bit of a hack
                not self.setPopupGeometry(popup, key)

    def toggleTab(self, index):

        if (index > 0) and not self.project:
            showWarning('Warning', 'No active project', parent=self)
            self.tabbedFrame.select(0)
            return

        frame = self.tabbedFrame.frames[index]
        if hasattr(frame, 'printOutDocString'):
            print frame.printOutDocString
            # only print it once
            del frame.printOutDocString

    def initCing(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        canvas = Tkinter.Canvas(frame, width=702, height=77)
        canvas.grid(row=0, column=0, sticky='ew')
        canvas.create_image(0, 0, anchor='nw', image=self.cingLogo)

        cingFrame = CingFrame(frame, self)
        cingFrame.grid(row=1, column=0, sticky='nsew')

        #self.projButtons.extend(cingFrame.buttonBar.buttons)
        self.updateFuncs.append(cingFrame.updateAll)

    def initProdecomp(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)
        frame.configure(bg='#FFFFFF')

        canvas = Tkinter.Canvas(frame, width=1024, height=90, bg='#FFFFFF')
        canvas.grid(row=0, column=0, sticky='ew')
        canvas.create_image(0, 0, anchor='nw', image=self.prodecompLogo)

        prodecompFrame = ProdecompFrame(frame,
                                        basePopup=self,
                                        ccpnProject=self.project)
        prodecompFrame.grid(row=1, column=0, sticky='nsew')

        # set printOutDocString:
        frame.printOutDocString = prodecompFrame.printOutDocString

        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(prodecompFrame.updateAll)

    def initAuremol(self, frame):

        frame.expandGrid(1, 0)

        refText = """Gronwald W, Brunner K, Kirchhofer R, Nasser A, Trenner J, Ganslmeier B,
Riepl H, Ried A, Scheiber J, Elsner R, Neidig K-P, Kalbitzer HR

AUREMOL, a New Program for the Automated Structure Elucidation of
Biological Macromolecules. Bruker Reports 2004; 154/155: 11-14
    """

        canvas = Tkinter.Canvas(frame, width=700, height=160, bg='#FFFFFF')
        canvas.grid(row=0, column=0, sticky='ew')
        canvas.create_image(12, 12, anchor='nw', image=self.auremolLogo)
        canvas.create_text(200, 10, anchor='nw', text=refText)

        auremolFrame = AuremolFrame(frame, self.project, grid=(1, 0))

        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(auremolFrame.updateAll)

    def initEci(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)
        frame.parent = self  # For notifiers
        frame.configure(bg='#FFFFFF')

        canvas = Tkinter.Canvas(frame,
                                width=800,
                                height=73,
                                bd=3,
                                bg='#FFFFFF')
        canvas.grid(row=0, column=0, sticky='ew')
        canvas.create_image(10, 10, anchor='nw', image=self.msdLogo)

        eciFrame = EntryCompletionFrame(frame, basePopup=self)
        eciFrame.grid(row=1, column=0, sticky='nsew')

        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(eciFrame.updateAll)

    def initHaddock(self, frame):

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)
        frame.parent = self  # For notifiers

        canvas = Tkinter.Canvas(frame, width=753, height=92)
        canvas.grid(row=0, column=0, sticky='ew')
        canvas.create_image(0, 0, anchor='nw', image=self.haddockLogo)

        haddockFrame = HaddockFrame(frame, self.project)
        haddockFrame.grid(row=1, column=0, sticky='nsew')

        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(haddockFrame.updateAll)

    def initIsd(self, frame):

        global isd

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        frame.configure(bg='#FFFFFF')

        canvas = Tkinter.Canvas(frame,
                                width=800,
                                height=91,
                                bd=3,
                                bg='#FFFFFF')
        canvas.grid(row=0, column=0, sticky='ew', padx=0)
        canvas.create_image(0, 0, anchor='nw', image=self.isdLogo)

        isdFrame = IsdFrame(frame, self.project)
        isdFrame.grid(row=1, column=0, sticky='nsew')

        self.isd = isdFrame
        isd = self.isd

        #self.projButtons.extend(isdFrame.buttons)
        self.updateFuncs.append(isdFrame.updateAll)

    def initExtendNmr(self, frame):

        row = 0
        frame.config(bd=5)
        canvas = Tkinter.Canvas(frame,
                                width=640,
                                height=600,
                                bg='#FFFFFF',
                                bd=5)
        canvas.grid(row=row, column=0, sticky='nsew')
        canvas.create_image(15, 15, anchor='nw', image=self.fp6Logo)
        canvas.create_image(330, 15, anchor='nw', image=self.prodecompLogo)
        canvas.create_image(330, 115, anchor='nw', image=self.mddLogo)
        canvas.create_image(20, 200, anchor='nw', image=self.ccpnLogo)
        canvas.create_image(230, 220, anchor='nw', image=self.msdLogo)
        canvas.create_image(450, 200, anchor='nw', image=self.brukerLogo)
        canvas.create_image(5, 310, anchor='nw', image=self.isdLogo)
        canvas.create_image(230, 300, anchor='nw', image=self.ariaLogo)
        canvas.create_image(450, 290, anchor='nw', image=self.auremolLogo)
        canvas.create_image(5, 420, anchor='nw', image=self.haddockLogo)
        canvas.create_image(5, 520, anchor='nw', image=self.cingLogo)

        #row += 1
        #l1 = Label(frame, text='Welcome to the Extend NMR suite')
        #l1.grid(row=row, column=0, sticky='ew')

    def initAria(self, frame):

        welcomeMessage = \
        """ARIA Version 2.3. Authors: Benjamin Bardiaux, Michael Habeck,
Jens Linge, Therese Malliavin, Sean O'Donoghue, Wolfgang Rieping,
and Michael Nilges.

Rieping W., Habeck M., Bardiaux B., Bernard A., Malliavin T.E.,
Nilges M.(2007) ARIA2: automated NOE assignment and data
integration in NMR structure calculation. Bioinformatics 23:381-382"""

        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(1, weight=1)

        canvas = Tkinter.Canvas(frame, width=700, height=114, bg='#FFFFFF')
        canvas.grid(row=0, column=0, sticky='ew')
        canvas.create_image(0, 0, anchor='nw', image=self.ariaLogo)
        canvas.create_text(250, 10, anchor='nw', text=welcomeMessage)

        ariaFrame = AriaFrame(frame, self)
        ariaFrame.grid(row=1, column=0, sticky='nsew')

        self.projButtons.extend(ariaFrame.buttons)
        self.updateFuncs.append(ariaFrame.updateAll)

    def openPopup(self, popup_name, clazz, oldStyle=False, *args, **kw):

        popup = self.popups.get(popup_name)

        if (popup):
            popup.open()
        else:
            if self.project:
                analysisProfile = self.analysisProfile
            else:
                analysisProfile = None

            if analysisProfile:
                if popup_name.startswith(window_popup_prefix):  # bit of a hack
                    transient = analysisProfile.transientWindows
                else:
                    transient = analysisProfile.transientDialogs
            else:
                transient = True

            name = popup_name

            if (oldStyle):
                popup = self.popups[popup_name] = clazz(self,
                                                        transient=transient,
                                                        *args,
                                                        **kw)
            else:
                popup = self.popups[popup_name] = clazz(self,
                                                        project=self.project,
                                                        popup_name=name,
                                                        transient=transient,
                                                        *args,
                                                        **kw)
            # above automatically opens popup

        return popup

    def initProject(self, project=None):

        AnalysisPopup.initProject(self, project, False)

        self.project = project
        if project:
            for i, func in enumerate(self.updateFuncs):
                func(project)

            for button in self.projButtons:
                button.enable()

        else:
            for button in self.projButtons:
                button.disable()

    def setupSoftware(self):

        return

        project = self.project

        methodStore = project.currentMethodStore or \
                      project.findFirstMethodStore() or \
                      project.newMethodStore(name=project.name)

        software = methodStore.findFirstSoftware(name=PROGRAM_NAME,
                                                 version=VERSION)
        if not software:
            software = methodStore.newSoftware(name=PROGRAM_NAME,
                                               version=VERSION)

        software.task = 'data pipeline'
        software.vendorName = 'The Extend-NMR Project'
        #software.vendorAddress = ''
        software.vendorWebAddress = 'http://www.extend-nmr.eu'
Exemple #21
0
  def body(self, guiFrame):

    self.geometry('600x350')

    project = self.project
    analysisProject = self.analysisProject

    guiFrame.grid_columnconfigure(1, weight=1)

    row = 0
    frame = Frame(guiFrame, grid=(0,0))
    label = Label(frame, text=' Window:', grid=(0,0))
    self.windowPulldown = PulldownList(frame, grid=(0,1),
                                      tipText='The window that will be printed out',
                                      callback=self.selectWindow)
                                      
    tipTexts = ['For the window pulldown, show all of the spectrum windows in the current project, irrespective of the active group',
                'For the window pulldown, show only spectrum windows that are in the currently active window group']
    self.whichWindows = RadioButtons(frame, grid=(0,2),
                                     entries=ACTIVE_OPTIONS, tipTexts=tipTexts,
                                     select_callback=self.updateWindows)
    
    texts = [ 'Save Print File' ]
    tipTexts = [ 'Save the printout to the specified file' ]
    commands = [ self.saveFile ]
    buttons = UtilityButtonList(guiFrame, helpUrl=self.help_url, grid=(row,2),
                                commands=commands, texts=texts, tipTexts=tipTexts)
    self.buttons = buttons
    buttons.buttons[0].config(bg='#B0FFB0')
    
    row += 1
    guiFrame.grid_rowconfigure(row, weight=1)
    options = ['Options', 'Spectra', 'Peak Lists', 'Region']
    tipTexts = ['Optional settings for spectra', 'Optional settings for peak lists', 'Optional settings for the region']
    tabbedFrame = TabbedFrame(guiFrame, options=options, tipTexts=tipTexts)
    tabbedFrame.grid(row=row, column=0, columnspan=3, sticky='nsew')
    self.tabbedFrame = tabbedFrame

    optionFrame, spectrumFrame, peakListFrame, regionFrame = tabbedFrame.frames

    optionFrame.expandGrid(0, 0)
    getOption = lambda key, defaultValue: PrintBasic.getPrintOption(analysisProject, key, defaultValue)
    setOption = lambda key, value: PrintBasic.setPrintOption(analysisProject, key, value)
    self.printFrame = PrintFrame(optionFrame, getOption=getOption,
                                 grid=(0,0), gridSpan=(1,1),
                                 setOption=setOption, haveTicks=True,
                                 doOutlineBox=False)

    spectrumFrame.expandGrid(0, 0)
    frame = Frame(spectrumFrame, grid=(0,0), gridSpan=(1,1))
    frame.expandGrid(1,0)

    self.overrideSpectrum = CheckButton(frame,
       text='Use below settings when printing',
       tipText='Use below settings when printing instead of the window values',
       grid=(0,0), sticky='w')

    tipText = 'Change the settings of the selected spectra back to their window values'
    button = Button(frame, text='Reset Selected', tipText=tipText,
                    command=self.resetSelected, grid=(0,1), sticky='e')

    self.posColorPulldown = PulldownList(self, callback=self.setPosColor)
    self.negColorPulldown = PulldownList(self, callback=self.setNegColor)
    headings = ['Spectrum', 'Pos. Contours\nDrawn', 'Neg. Contours\nDrawn', 'Positive\nColours', 'Negative\nColours']
    tipTexts = ['Spectrum in window', 'Whether the positive contours should be drawn', 'Whether the negative contours should be drawn',
      'Colour scheme for positive contours (can be a single colour)', 'Colour scheme for negative contours (can be a single colour)']

    editWidgets      = [ None, None, None, self.posColorPulldown, self.negColorPulldown]
    editGetCallbacks = [ None, self.togglePos, self.toggleNeg, self.getPosColor, self.getNegColor]
    editSetCallbacks = [ None, None, None, self.setPosColor, self.setNegColor]
    self.spectrumTable = ScrolledMatrix(frame, headingList=headings,
                                        tipTexts=tipTexts,
                                        multiSelect=True,
                                        editWidgets=editWidgets,
                                        editGetCallbacks=editGetCallbacks,
                                        editSetCallbacks=editSetCallbacks,
                                        grid=(1,0), gridSpan=(1,2))

    peakListFrame.expandGrid(0, 0)
    frame = Frame(peakListFrame, grid=(0,0), gridSpan=(1,3))
    frame.expandGrid(1,0)

    self.overridePeakList = CheckButton(frame,
       text='Use below settings when printing',
       tipText='Use below settings when printing instead of the window values',
       grid=(0,0))

    tipText = 'Change the settings of the selected peak lists back to their window values'
    button = Button(frame, text='Reset Selected', tipText=tipText,
                    command=self.resetSelected, grid=(0,1), sticky='e')

    colors = Color.standardColors
    self.peakColorPulldown = PulldownList(self, callback=self.setPeakColor,
                                        texts=[c.name for c in colors],
                                        objects=[c.hex for c in colors],
                                        colors=[c.hex for c in colors])
    headings = [ 'Peak List', 'Symbols Drawn', 'Peak Font', 'Peak Colour']
    self.fontMenu = FontList(self, mode='Print', extraTexts=[no_peak_text])
    editWidgets      = [ None, None, self.fontMenu, self.peakColorPulldown]
    editGetCallbacks = [ None, self.togglePeaks, self.getPeakFont, self.getPeakColor ]
    editSetCallbacks = [ None, None, self.setPeakFont, self.setPeakColor ]
    self.peakListTable = ScrolledMatrix(frame, headingList=headings,
                                        multiSelect=True,
                                        editWidgets=editWidgets,
                                        editGetCallbacks=editGetCallbacks,
                                        editSetCallbacks=editSetCallbacks,
                                        grid=(1,0), gridSpan=(1,2))

    regionFrame.expandGrid(0, 0)
    frame = Frame(regionFrame, grid=(0,0), gridSpan=(1,3))
    frame.expandGrid(3,0)
    tipText = 'Use the specified override region when printing rather than the window values'
    self.overrideButton = CheckButton(frame, text='Use override region when printing',
                                      tipText=tipText,
                                      callback=self.toggledOverride, grid=(0,0))

    tipTexts = ('Use min and max to specify override region', 'Use center and width to specify override region')
    self.use_entry = USE_ENTRIES[0]
    self.useButtons = RadioButtons(frame, entries=USE_ENTRIES,
                                      tipTexts=tipTexts,
                                      select_callback=self.changedUseEntry,
                                      grid=(1,0))

    texts = ('Set Region from Window', 'Set Center from Window', 'Set Width from Window')
    tipTexts = ('Set the override region to be the current window region',
                'Set the center of the override region to be the center of the current window region',
                'Set the width of the override region to be the width of the current window region')
    commands = (self.setRegionFromWindow, self.setCenterFromWindow, self.setWidthFromWindow)
    self.setRegionButton = ButtonList(frame, texts=texts,
                                      tipTexts=tipTexts,
                                      commands=commands, grid=(2,0))

    self.minRegionWidget = FloatEntry(self, returnCallback=self.setMinRegion, width=10)
    self.maxRegionWidget = FloatEntry(self, returnCallback=self.setMaxRegion, width=10)
    headings = MIN_MAX_HEADINGS
    editWidgets      = [ None, None, self.minRegionWidget, self.maxRegionWidget ]
    editGetCallbacks = [ None, None, self.getMinRegion,    self.getMaxRegion ]
    editSetCallbacks = [ None, None, self.setMinRegion,    self.setMaxRegion ]
    self.regionTable = RegionScrolledMatrix(frame, headingList=headings,
                                            editWidgets=editWidgets,
                                            editGetCallbacks=editGetCallbacks,
                                            editSetCallbacks=editSetCallbacks,
                                            grid=(3,0))

    self.updateWindows()
    self.updateAfter()
    
    self.administerNotifiers(self.registerNotify)
Exemple #22
0
    def body(self, guiParent):

        self.menus = {}
        self.menu_items = {}

        self.fixedActiveMenus = {}

        self.popups = {}

        self.callbacksDict = {}

        self.selected_objects = []

        self.menubar = menubar = Menu(guiParent)

        self.font = DEFAULT_FONT

        self.setProjectMenu()
        #

        menu = Menu(self.menubar, tearoff=0)
        menu.bind('<Button>', self.printAnalysisCommandLineInfo)
        self.menubar.add_cascade(label='CcpNmr Analysis',
                                 shortcut='C',
                                 menu=menu)
        self.menubar.add_command(label='FormatConverter',
                                 shortcut='F',
                                 command=self.runFormatConverter)

        self.menubar = menu
        self.initProject()
        self.setPeaksMenu()
        self.setMoleculeMenu()
        self.setAssignMenu()
        self.setResonanceMenu()
        self.setDataMenu()
        self.setStructureMenu()
        self.setChartMenu()
        self.setMacroMenu()
        self.setOtherMenu()
        self.setMenuState()  # need to do it again because of OtherMenu state

        # Help Submenu

        helpMenu = Menu(self.menubar, tearoff=0)
        helpMenu.add_command(label='Version',
                             shortcut='V',
                             command=self.showVersion)
        helpMenu.add_command(label='About',
                             shortcut='A',
                             command=self.showAbout)
        helpMenu.add_command(label='Help', shortcut='H', command=self.showHelp)

        menu.add_separator()
        menu.add_command(label='CCPN Updates',
                         shortcut='U',
                         image=self.iconRefresh,
                         compound='left',
                         command=self.updateAnalysis,
                         tipText='Get any new patches and updates to CcpNmr')
        menu.add_cascade(label='CCPN Help',
                         shortcut='H',
                         image=self.iconHelp,
                         compound='left',
                         menu=helpMenu)

        self.config(menu=menubar)

        # Ensure that the first row and column in popup expand
        guiParent.grid_rowconfigure(0, weight=1)
        guiParent.grid_columnconfigure(0, weight=1, minsize=200)
        frame = Frame(guiParent)  # Body widgets can be put in this frame
        frame.grid()

        softwareOpts = [
            'Extend-NMR', 'ARIA 2', 'Auremol', 'CING', ' ECI ', 'HADDOCK',
            ' ISD ', 'PRODECOMP'
        ]

        self.tabbedFrame = TabbedFrame(guiParent,
                                       options=softwareOpts,
                                       toggleOff=False,
                                       selected=0,
                                       callback=self.toggleTab)
        self.tabbedFrame.grid(row=0, column=0, sticky='nsew')

        frames = self.tabbedFrame.frames

        # Logos
        ccpnDir = getTopDirectory()

        imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images')

        imageFile = os.path.join(imageDir, 'Fp6Logo.gif')
        self.fp6Logo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CingLogo.gif')
        self.cingLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AriaLogo.gif')
        self.ariaLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'IsdLogo.gif')
        self.isdLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'HaddockLogo.gif')
        self.haddockLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AuremolLogo.gif')
        self.auremolLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CcpnLogo.gif')
        self.ccpnLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'ProdecompLogo.gif')
        self.prodecompLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MddLogo.gif')
        self.mddLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'BrukerLogo.gif')
        self.brukerLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MsdLogo.gif')
        self.msdLogo = Tkinter.PhotoImage(file=imageFile)

        self.initExtendNmr(frames[0])

        self.initAria(frames[1])

        self.initAuremol(frames[2])

        self.initCing(frames[3])

        self.initEci(frames[4])

        self.initHaddock(frames[5])

        self.initIsd(frames[6])

        self.initProdecomp(frames[7])

        self.initProject(self.project)

        if not self.project:
            for button in self.projButtons:
                button.disable()

        self.geometry('680x670')
Exemple #23
0
  def body(self, guiFrame):

    self.geometry('700x700')
   
    guiFrame.expandGrid(0,0)
    
    options = ['Peak Lists & Settings','Peak Intensity Comparison']
    tabbedFrame = TabbedFrame(guiFrame, options=options, callback=self.changeTab)
    tabbedFrame.grid(row=0, column=0, sticky='nsew')
    self.tabbedFrame = tabbedFrame
    frameA, frameB = tabbedFrame.frames

    row = 0
    frameA.grid_columnconfigure(1, weight=1)
    frameA.grid_columnconfigure(3, weight=1)
    frameA.grid_columnconfigure(5, weight=1)
    frameA.grid_rowconfigure(5, weight=1)

    tipText = 'Number of reference peaks (no saturation)'
    self.peaksALabel = Label(frameA, text='Number of Ref Peaks: ', tipText=tipText)
    self.peaksALabel.grid(row=1,column=0,columnspan=2,sticky='w')

    tipText = 'Number of NOE saturation peaks'
    self.peaksBLabel = Label(frameA, text='Number of Sat Peaks: ', tipText=tipText)
    self.peaksBLabel.grid(row=1,column=2,columnspan=2,sticky='w')

    tipText = 'Number of peaks in assigned list'
    self.peaksCLabel = Label(frameA, text='Number of Assign Peaks: ', tipText=tipText)
    self.peaksCLabel.grid(row=1,column=4,columnspan=2,sticky='w')
    
    tipText = 'Selects which peak list is considered the NOE intensity reference (no saturation)'
    specALabel = Label(frameA, text='Ref Peak List: ')
    specALabel.grid(row=0,column=0,sticky='w')
    self.specAPulldown = PulldownList(frameA, callback=self.setRefPeakList, tipText=tipText)
    self.specAPulldown.grid(row=0,column=1,sticky='w')

    tipText = 'Selects which peak list is considered as NOE saturated.'
    specBLabel = Label(frameA, text='Sat Peak List: ')
    specBLabel.grid(row=0,column=2,sticky='w')
    self.specBPulldown = PulldownList(frameA, callback=self.setSatPeakList, tipText=tipText)
    self.specBPulldown.grid(row=0,column=3,sticky='w')

    tipText = 'Selects a peak list with assignments to use as a positional reference'
    specCLabel = Label(frameA, text='Assignment Peak List: ')
    specCLabel.grid(row=0,column=4,sticky='w')
    self.specCPulldown = PulldownList(frameA, callback=self.setAssignPeakList, tipText=tipText)
    self.specCPulldown.grid(row=0,column=5,sticky='w')

    frame0a = Frame(frameA)
    frame0a.grid(row=2,column=0,columnspan=6,sticky='nsew')
    frame0a.grid_columnconfigure(9, weight=1)
    
    tipText = '1H ppm tolerance for matching assigned peaks to reference & NOE saturation peaks'
    tolHLabel   = Label(frame0a, text='Tolerances: 1H')
    tolHLabel.grid(row=0,column=0,sticky='w')
    self.tolHEntry = FloatEntry(frame0a,text='0.02', width=6, tipText=tipText)
    self.tolHEntry .grid(row=0,column=1,sticky='w')  

    tipText = '15N ppm tolerance for matching assigned peaks to reference & NOE saturation peaks'
    tolNLabel   = Label(frame0a, text=' 15N')
    tolNLabel .grid(row=0,column=2,sticky='w')   
    self.tolNEntry = FloatEntry(frame0a,text='0.1', width=6, tipText=tipText)
    self.tolNEntry .grid(row=0,column=3,sticky='w')   

    tipText = 'Whether to peak new peaks in reference & NOE saturated lists (at assignment locations)'
    label = Label(frame0a, text=' Pick new peaks?', grid=(0,4)) 
    self.pickPeaksSelect = CheckButton(frame0a, tipText=tipText,
                                       grid=(0,5), selected=True)

    tipText = 'Whether to assign peaks in the peaks in the reference & NOE saturation lists, if not already assigned'
    label = Label(frame0a, text=' Assign peaks?')
    label.grid(row=0,column=6,sticky='w')   
    self.assignSelect = CheckButton(frame0a, tipText=tipText)
    self.assignSelect.set(1)
    self.assignSelect.grid(row=0,column=7,sticky='w')    

    tipText = 'Whether to consider peak height or volume in the heteronuclear NOE calculation'
    intensLabel = Label(frame0a, text=' Intensity Type:')
    intensLabel .grid(row=0,column=8,sticky='w')   
    self.intensPulldown = PulldownList(frame0a, texts=['height','volume'],
                                       callback=self.setIntensityType,
                                       tipText=tipText)
    self.intensPulldown.grid(row=0,column=9,sticky='w')    

    divider = LabelDivider(frameA, text='Peaks', grid=(3,0),
                           gridSpan=(1,6))

    tipTexts = ['Show the selected intensity reference peaks in the below table',
                'Show the selected NOE saturation peaks in the below table',
                'Show the selected assigned peak list in the below table',
                'Show the displayed peaks in a separate peak table, where assignments etc. may be adjusted']
    texts    = ['Show Ref Peaks','Show Sat Peaks',
                'Show Assign Peaks', 'Separate Peak Table']
    commands = [self.viewRefPeakList, self.viewSatPeakList,
                self.viewAssignPeakList, self.viewSeparatePeakTable]
    self.viewPeaksButtons = ButtonList(frameA, expands=True, tipTexts=tipTexts,
                                       texts=texts, commands=commands)
    self.viewPeaksButtons.grid(row=4,column=0,columnspan=6,sticky='nsew')

    self.peakTable = PeakTableFrame(frameA, self.guiParent, grid=(5,0),
                                    gridSpan=(1,6))
    self.peakTable.bottomButtons1.grid_forget()
    self.peakTable.bottomButtons2.grid_forget()
    #self.peakTable.topFrame.grid_forget()
    self.peakTable.topFrame.grid(row=2, column=0, sticky='ew')
    # Next tab

    frameB.expandGrid(0,0)
    
    tipTexts = ['Row number',
                'Assignment annotation for NOE saturation peak',
                'Assignment annotation for reference peak (no saturation)',
                '1H chemical shift of NOE saturation peak',
                '1H chemical shift of reference peak',
                '15N chemical shift of NOE saturation peak',
                '15N chemical shift of reference peak',
                'The separation between compared peaks: square root of the sum of ppm differences squared',
                'The intensity if the NOE saturation peak',
                'The intensity of the reference peak (no saturation)',
                'Ratio of peak intensities: saturated over reference',
                'Residue(s) for reference peak']
    colHeadings      = ['#','Sat Peak','Ref Peak','1H shift A',
                        '1H shift B','15N shift A','15N shift B',
                        'Closeness\nScore','Intensity A','Intensity B',
                        'Intensity\nRatio','Residue']
    self.scrolledMatrix = ScrolledMatrix(frameB, multiSelect=True, 
                                         headingList=colHeadings,
                                         callback=self.selectCell,
                                         tipTexts=tipTexts,
                                         grid=(0,0),
                                         deleteFunc=self.removePair)

    tipTexts = ['Force a manual update of the table; pair-up NOE saturation and reference peaks according to assigned peak positions',
                'Remove the selected rows of peak pairs',
                'Show peaks corresponding to the selected row in a table',
                'Save the Heteronuclear NOE values in the CCPN project as a data list']
    texts    = ['Refresh Table','Remove Pairs',
                'Show Peak Pair','Create Hetero NOE List']
    commands = [self.matchPeaks,self.removePair,
                self.showPeakPair,self.makeNoeList]
    self.pairButtons = ButtonList(frameB, tipTexts=tipTexts, grid=(1,0),
                                  texts=texts, commands=commands)


    bottomButtons = UtilityButtonList(tabbedFrame.sideFrame, helpUrl=self.help_url)
    bottomButtons.grid(row=0, column=0, sticky='e')
    
    self.updatePulldowns()
    self.updateAfter()

    self.administerNotifiers(self.registerNotify)
  def body(self, guiFrame):
    
    self.geometry("775x500")
    guiFrame.expandGrid(0,0)
    
    options = ['1D Graphs','Amino Acid CA CB']
    tipTexts = ['Simple graphs of how chemical shift values are distributed for a given atom type',
                'Density plots of alpha a & beta carbon shift distributions for common amnio acids']
    tabbedFrame = TabbedFrame(guiFrame, options=options, grid=(0,0), tipTexts=tipTexts)
    frameA, frameB = tabbedFrame.frames
    
    # # # # # # #  1D GRAPHS  # # # # # # # 
    
 
    row = 0
     
    MolType = self.project.metaclass.metaObjFromQualName('ccp.molecule.ChemComp.MolType')
    molTypes = MolType.enumeration
    molTypes.remove('other')
    molTypes.remove('carbohydrate')
   
    self.molType = 'protein'
    
    ccpCodes = self.getCcpCodes(self.molType) or [None,]
    self.ccpCode = 'Ala'
    
    self.atomType = ATOM_TYPES[0]
    
    self.atomNamesDict = {}
    self.chemAtomNmrRefs = self.getCcpCodeData(self.ccpCode, atomType=self.atomType)
    
    
    tipText = 'Which of the common bio-polymer types to show data for'
    self.molTypeLabel     = Label(frameA, text = 'Molecule Type:', grid=(row,0))
    self.molTypePulldown  = PulldownList(frameA, callback=self.changeMolType,
                                         texts=molTypes, grid=(row,1), tipText=tipText)

    tipText = 'Which residue code to show chemical shift distributions for'
    self.ccpCodeLabel     = Label(frameA, text = 'Residue Code:', grid=(row,2))
    self.ccpCodePulldown  = PulldownList(frameA, callback=self.changeCcpCode, texts=ccpCodes,
                                         index=ccpCodes.index(self.ccpCode), 
                                         grid=(row,3), tipText=tipText)

    tipText = 'Whether to show distributions for hydrogen atoms or other atoms'
    self.atomTypeLabel    = Label(frameA, text = 'Atom Type:', grid=(row,4))
    self.atomTypePulldown = PulldownList(frameA, callback=self.changeAtomType,
                                         texts=ATOM_TYPES, tipText=tipText,
                                         grid=(row,5))

    row += 1

    tipText = 'The selection of atom name to display distributions for'
    self.atomSelector = PartitionedSelector(frameA, self.toggleAtom,
                                            tipText=tipText, maxRowObjects=20)
    self.atomSelector.grid(row=row, column=0, columnspan=6, sticky='ew')

    row += 1

    frameA.expandGrid(row,5)
    self.scrolledGraph = ScrolledGraph(frameA, symbolSize=2, reverseX=True, width=650,
                                       height=300, title='Chemical shift distribution',
                                       xLabel='Chemical shift', yLabel='proportion',
                                       motionCallback=self.updateCrosshairs)
    self.scrolledGraph.grid(row=row, column=0, columnspan=6, sticky='nsew')
    
    # # # # # # #  PROTEIN CA CB   # # # # # # # 
    
    frameB.expandGrid(0,0)
    matrix, ppms = self.getCaCbMatrix()
    title = 'Amino Acid CA & CB Chemical Shifts'
    self.cacbMatrix = ScrolledDensityMatrix(frameB, matrix=matrix, boxSize=14,
                                            title=title,
                                            xLabels=ppms, yLabels=AMINO_ACIDS,
                                            borderColor='grey', zoom=1.0,
                                            labelAxes=True, barPlot=False,
                                            doLegend=False, grid=(0,0))
    
    sdm = self.cacbMatrix
    font = sdm.boldFont
    
    x0, y0 = (470,370)
    sdm.canvas.create_rectangle(x0+170,y0-6,x0+182,y0+6,fill='#4040A0',
                                outline=sdm.borderColor, width=1)
    sdm.canvas.create_text(x0+200, y0, text='CA', font=font)
    sdm.canvas.create_rectangle(x0+220,y0-6,x0+232,y0+6,fill='#A04040',
                                outline=sdm.borderColor, width=1)
    sdm.canvas.create_text(x0+250, y0, text='CB', font=font)
    sdm.canvas.create_text(x0, y0, text='13C PPM +/- 0.5', font=font)
    
    # # # # # # #  M A I N   # # # # # # # 
    
    tipText = 'Whether to use chemical shift data from the BMRB (unfiltered) or RefDB sets'
    label = Label(tabbedFrame.sideFrame, text='Source Database:', grid=(0,0), sticky='e')
    index = SOURCE_NAMES.index(self.sourceName)
    self.sourcePulldown = PulldownList(tabbedFrame.sideFrame, self.changeSource,
                                       texts=SOURCE_NAMES, index=index, 
                                       grid=(0,1), sticky='e', tipText=tipText)

    self.bottomButtons = UtilityButtonList(tabbedFrame.sideFrame, expands=True,
                                           helpUrl=self.help_url, sticky='e',
                                           grid=(0,2))
                                               
    self.waiting = False
    self.updateAfter()

    for func in ('__init__', 'delete'):
      self.registerNotify(self.updateAfter, 'ccp.nmr.NmrReference.NmrReferenceStore', func)
Exemple #25
0
    def __init__(self, guiParent, basePopup, project=None):
        # Base popup required to handle notification of data model changes
        # e.g. new peak lists, so that the GUI can update to the latest
        # state
        self.basePopup = basePopup
        self.guiParent = guiParent

        # FIXME JMCI
        # need to work through this far more carefully
        self.project = project

        # shortcuts to this layer
        self.basePopup.frameShortcuts['Task'] = self

        # shortcuts to layer below. We should set these in the
        # initMethod methods
        self.frameShortcuts = {}

        # TODO understand what these are doing
        self.registerNotify = basePopup.registerNotify
        self.unregisterNotify = basePopup.unregisterNotify

        Frame.__init__(self, guiParent)

        self.grid_rowconfigure(1, weight=1)
        self.grid_columnconfigure(0, weight=1)

        # Logos. Code nicked from ExtendNMR GUI
        ccpnDir = getTopDirectory()

        imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images')

        # basically nicked from Extend-NMR
        softwareOpts = [
            'Test1Task', 'ARIA 2', 'Auremol', 'CING', ' ECI ', 'HADDOCK',
            ' ISD ', 'PRODECOMP'
        ]

        self.tabbedFrame = TabbedFrame(guiParent,
                                       options=softwareOpts,
                                       toggleOff=False,
                                       selected=0)
        self.tabbedFrame.grid(row=1, column=0, sticky='nsew')

        frames = self.tabbedFrame.frames

        # Logos
        ccpnDir = getTopDirectory()

        imageDir = os.path.join(ccpnDir, 'python', 'extendNmr', 'images')

        imageFile = os.path.join(imageDir, 'Fp6Logo.gif')
        self.fp6Logo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CingLogo.gif')
        self.cingLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AriaLogo.gif')
        self.ariaLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'IsdLogo.gif')
        self.isdLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'HaddockLogo.gif')
        self.haddockLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'AuremolLogo.gif')
        self.auremolLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'CcpnLogo.gif')
        self.ccpnLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'ProdecompLogo.gif')
        self.prodecompLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MddLogo.gif')
        self.mddLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'BrukerLogo.gif')
        self.brukerLogo = Tkinter.PhotoImage(file=imageFile)
        imageFile = os.path.join(imageDir, 'MsdLogo.gif')
        self.msdLogo = Tkinter.PhotoImage(file=imageFile)

        # don't know what this does
        self.updateFuncs = []
        self.projButtons = []

        # basically nicked from Extend-NMR
        self.initTest1(frames[0])
        self.initAria(frames[1])
        self.initAuremol(frames[2])
        self.initCing(frames[3])
        #self.initEci(frames[4])
        #self.initHaddock(frames[5])
        self.initIsd(frames[6])
        self.initProdecomp(frames[7])
Exemple #26
0
  def body(self, guiFrame):

    self.geometry('700x840')
    
    guiFrame.expandGrid(1,0)
    
    # Top frame
    
    frame = Frame(guiFrame, grid=(0,0))
    frame.expandGrid(None,8)
    
    label = Label(frame, text=u' %s List:' % T1, grid=(0,0))
    self.t1Pulldown = PulldownList(frame, callback=self.selectT1List, grid=(0,1))
    
    label = Label(frame, text=u'  %s List:' % T2, grid=(0,2))
    self.t2Pulldown = PulldownList(frame, callback=self.selectT2List, grid=(0,3))
    
    label = Label(frame, text='  NOE List:', grid=(0,4))
    self.noePulldown = PulldownList(frame, callback=self.selectNoeList, grid=(0,5))
 
    label = Label(frame, text='  Spectrometer Freq (MHz):', grid=(0,6))
    self.sfEntry = FloatEntry(frame, grid=(0,7), text=600.00, width=6)

    UtilityButtonList(frame, grid=(0,9), sticky='e')
    
    # Tabs
    
    options = [u'%s vs %s Scatter' % (T1, T2),
               u'%s,%s & NOE Graphs' % (T1, T2) ,
               u'%s/%s Graph' % (T1, T2),
               u'%s Estimate Graph' % S2,
               'Options']
    self.tabbedFrame = TabbedFrame(guiFrame, options=options,
                                   callback=self.toggleTab, grid=(1,0))
    frameA, frameD, frameC, frameE, frameB = self.tabbedFrame.frames

    # T1 vs T2 Graph

    frameA.expandGrid(0,0)
 
    self.t1t2Graph = T1VersesT2Plot(frameA, grid=(0,0))

    # T1 & T2 Graph

    frameD.expandGrid(0,0)
    frameD.expandGrid(1,0)
    frameD.expandGrid(2,0)
 
    self.t1Graph = MeasurementPlot(frameD, T1, grid=(0,0))
    self.t2Graph = MeasurementPlot(frameD, T2, grid=(1,0))
    self.noeGraph = NoePlot(frameD, 'NOE', grid=(2,0))

    # T1 over T2 Graph

    frameC.expandGrid(0,0)
 
    self.t1t2GraphB = T1OverT2Plot(frameC, grid=(0,0))
    
    # Order params graph
    
    frameE.expandGrid(0,0)
    frameE.expandGrid(1,0)
    frameE.expandGrid(2,0)
    
    self.s2Graph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % S2,
                                 xLabel='Residue number', yLabel=S2,
                                 width=500, height=150, graphType='histogram', 
                                 xGrid=True, yGrid=False, grid=(0,0),
                                 dataColors=['#0000A0','#808000'],
                                 dataNames=['Isotropic',])

    self.teGraph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % Te,
                                 xLabel='Residue number', yLabel=u'%s (ps)' % Te,
                                 width=500, height=150, graphType='histogram',
                                 xGrid=True, yGrid=False, grid=(1,0),
                                 dataColors=['#008000',])
                                 
    self.rexGraph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % 'Rex',
                                  xLabel='Residue number', yLabel='Rex',
                                  width=500, height=150, graphType='histogram',
                                  xGrid=True, yGrid=False, grid=(2,0),
                                  dataColors=['#900000',])
    
    # Options
    
    frameB.expandGrid(4,2)
    
    frame = LabelFrame(frameB, text='Physical Params', grid=(0,0))
    frame.expandGrid(None,3)
   
    label = Label(frame, text=u'N-H bond length (\u00C5)', grid=(0,0))
    self.lenNhEntry = FloatEntry(frame, text=1.015, grid=(0,1), width=8)

    label = Label(frame, text=u'Internal correlation\ntime, \u03C4e (ps)', grid=(1,0))
    self.ictEntry = FloatEntry(frame, text=50.0, grid=(1,1), width=8)
    
    label = Label(frame, text=u'15N Chemical Shift\nAnisotopy,\u0394N (ppm)',
                  grid=(2,0))
    self.csaNEntry = FloatEntry(frame, text=-160.0, grid=(2,1), width=8)
    
    frame = LabelFrame(frameB, text=u'%s vs %s Scatter' % (T1, T2), grid=(1,0))
    
    label = Label(frame, text='Max cluster difference (ms):', grid=(0,0))
    self.clusterDictEntry = FloatEntry(frame, text=20.0, grid=(0,1), width=8)    

    label = Label(frame, text='Min cluster size:', grid=(1,0))
    self.clusterSizeEntry = FloatEntry(frame, text=5, grid=(1,1), width=8)    

    label = Label(frame, text=u'Min graph %s (ms):' % T1, grid=(2,0))
    self.minT1Entry = FloatEntry(frame, text=300.0, grid=(2,1), width=8)    

    label = Label(frame, text=u'Max graph %s (ms):' % T1, grid=(3,0))
    self.maxT1Entry = FloatEntry(frame, text=1000.0, grid=(3,1), width=8)    

    label = Label(frame, text=u'Min graph %s (ms):' % T2, grid=(4,0))
    self.minT2Entry = FloatEntry(frame, text=0.0, grid=(4,1), width=8)    

    label = Label(frame, text=u'Max graph %s (ms):' % T2, grid=(5,0))
    self.maxT2Entry = FloatEntry(frame, text=600.0, grid=(5,1), width=8)    
    
    frame = LabelFrame(frameB, text=u'%s Contours' % S2, grid=(0,1))
    frame.expandGrid(4,3)

    label = Label(frame, text='(Order Parameter Lines)',
                  grid=(0,0), gridSpan=(1,2))

    label = Label(frame, text='Min value:', grid=(1,0))
    self.minS2Entry = FloatEntry(frame, text=0.3, grid=(1,1), width=8)
    
    label = Label(frame, text='Max value:', grid=(2,0))
    self.maxS2Entry = FloatEntry(frame, text=1.0, grid=(2,1), width=8)
    
    label = Label(frame, text='Step:', grid=(3,0))
    self.stepS2Entry = FloatEntry(frame, text=0.1, grid=(3,1), width=8)

    frame = LabelFrame(frameB, text=u'\u03C4m Contours', grid=(1,1))
    frame.expandGrid(4,3)

    label = Label(frame, text='(Rotational Correlation Time Lines)',
                  grid=(0,0), gridSpan=(1,2))
                  
    label = Label(frame, text='Min value (ns):', grid=(1,0))
    self.minRctEntry = FloatEntry(frame, text=5.0, grid=(1,1), width=8)
    
    label = Label(frame, text='Max value (ns):', grid=(2,0))
    self.maxRctEntry = FloatEntry(frame, text=14.0, grid=(2,1), width=8)
    
    label = Label(frame, text='Step (ns):', grid=(3,0))
    self.stepRctEntry = FloatEntry(frame, text=1.0, grid=(3,1), width=8)

    # Bottom frame
 
    texts = [u'Show %s Table' % T1,u'Show %s Table' % T2, u'Estimate %s' % S2]
    commands = [self.showT1List, self.showT2List, self.mc]
    buttonList = ButtonList(guiFrame, grid=(2,0), texts=texts, commands=commands)

    # Update

    self.updateRelaxationLists()

    self.drawAfter()

    self.administerNotifiers(self.registerNotify)