예제 #1
0
    def __init__(self,
                 parent,
                 label,
                 entry='',
                 separator=': ',
                 label_width=20,
                 entry_width=60,
                 label_anchor=Tkinter.E,
                 show='',
                 isArray=False,
                 returnCallback=None,
                 *args,
                 **kw):

        apply(Frame.__init__, (self, parent) + args, kw)

        self.grid_columnconfigure(1, weight=1)

        self.separator = separator

        text = label + separator
        self.label = Label(self,
                           text=text,
                           width=label_width,
                           anchor=label_anchor)
        self.label.grid(row=0, column=0, sticky=Tkinter.EW)

        self.entry = FloatEntry(self,
                                show=show,
                                width=entry_width,
                                isArray=isArray,
                                returnCallback=returnCallback)
        self.entry.grid(row=0, column=1, sticky=Tkinter.EW)
        self.setEntry(entry)
예제 #2
0
class LabeledFloatEntry(Frame):
    def __init__(self,
                 parent,
                 label,
                 entry='',
                 separator=': ',
                 label_width=20,
                 entry_width=60,
                 label_anchor=Tkinter.E,
                 show='',
                 isArray=False,
                 returnCallback=None,
                 *args,
                 **kw):

        apply(Frame.__init__, (self, parent) + args, kw)

        self.grid_columnconfigure(1, weight=1)

        self.separator = separator

        text = label + separator
        self.label = Label(self,
                           text=text,
                           width=label_width,
                           anchor=label_anchor)
        self.label.grid(row=0, column=0, sticky=Tkinter.EW)

        self.entry = FloatEntry(self,
                                show=show,
                                width=entry_width,
                                isArray=isArray,
                                returnCallback=returnCallback)
        self.entry.grid(row=0, column=1, sticky=Tkinter.EW)
        self.setEntry(entry)

    def getLabel(self):

        text = self.label.get()
        n = text.find(self.separator)
        if (n >= 0):
            text = text[:n]

        return text

    def setLabel(self, text=''):

        text = text + self.separator
        self.label.set(text)

    def getEntry(self):

        return self.entry.get()

    def setEntry(self, value=''):

        self.entry.set(value)
예제 #3
0
    def __init__(self,
                 parent,
                 label='',
                 world_region=None,
                 view_region=None,
                 orient=Tkinter.HORIZONTAL,
                 allow_resize=True,
                 width=20,
                 callback=None,
                 borderwidth=1,
                 show_text=True,
                 text_color='#000000',
                 text_decimals=2,
                 units_scroll=0.1,
                 pages_scroll=1.0,
                 menu_entries=None,
                 menu_callback=None,
                 min_thickness=None,
                 *args,
                 **kw):

        self.menu_entries = menu_entries
        self.myCallback = callback

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

        self.text_decimals = text_decimals

        self.label = Label(self, text=label, width=4)

        self.menu = PulldownMenu(self,
                                 callback=menu_callback,
                                 entries=menu_entries)

        self.entry = FloatEntry(self,
                                width=6,
                                returnCallback=self.adjustScrollbar)

        self.region_scrollbar = RegionScrollbar(self,
                                                world_region=world_region,
                                                view_region=view_region,
                                                orient=orient,
                                                allow_resize=allow_resize,
                                                width=width,
                                                callback=self.doCallback,
                                                borderwidth=borderwidth,
                                                show_text=show_text,
                                                text_color=text_color,
                                                text_decimals=text_decimals,
                                                units_scroll=units_scroll,
                                                pages_scroll=pages_scroll,
                                                min_thickness=min_thickness)

        self.gridAll()
예제 #4
0
    def body(self, guiFrame):

        self.geometry('500x500')
        guiFrame.grid_columnconfigure(0, weight=1)
        guiFrame.grid_rowconfigure(1, weight=1)

        frame = LabelFrame(guiFrame, text='RDC protocol settings')
        frame.grid(row=1, column=0, sticky='nsew')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        self.floatEntry = FloatEntry(self, returnCallback=self.setValue)

        headingList = ['Parameter', 'Value', 'Description']
        justifyList = ['center', 'center', 'left']
        editWidgets = [None, self.floatEntry, None]
        editGetCallbacks = [None, self.getValue, None]
        editSetCallbacks = [None, self.setValue, None]
        self.rdcMatrix = ScrolledMatrix(frame,
                                        headingList=headingList,
                                        justifyList=justifyList,
                                        editSetCallbacks=editSetCallbacks,
                                        editGetCallbacks=editGetCallbacks,
                                        editWidgets=editWidgets,
                                        multiSelect=False,
                                        initialRows=10,
                                        passSelfToCallback=True,
                                        callback=self.selectRdc)

        self.rdcMatrix.grid(row=0, column=0, sticky='nsew')
        self.rdcMatrix.refreshFunc = self.updateRdcSet

        self.updateRdcSet()
예제 #5
0
  def body(self, guiFrame):
  
    self.noeClassChoice = None
    self.spectrum = None
    self.intensEntry = FloatEntry(self, returnCallback=self.setIntens, width=5)
    self.targetEntry = FloatEntry(self, returnCallback=self.setTarget, width=5)
    self.minEntry    = FloatEntry(self, returnCallback=self.setMin,    width=5)
    self.maxEntry    = FloatEntry(self, returnCallback=self.setMax,    width=5)
   
    row = 0

    label = Label(guiFrame, text='Spectrum: ', grid=(row,0))
    tipText = ''
    self.spectrumPulldown = PulldownMenu(guiFrame,self.changeSpectrum, grid=(row,1))

    row +=1

    guiFrame.expandGrid(row, 1)

    tipTexts = ['Lower bound of this intensity category. Values are relative to reference intensity.',
                'Target restraint distance for this category',
                'Lower bound distance for this category',
                'Upper bound distance for this category']
    headingList = ['Min. NOE\nIntensity','Target\nDist','Min\nDist','Max\nDist']
    editWidgets = [self.intensEntry,self.targetEntry,self.minEntry,self.maxEntry]
    editGetCallbacks = [self.getIntens,self.getTarget,self.getMin,self.getMax]
    editSetCallbacks = [self.setIntens,self.setTarget,self.setMin,self.setMax]
    
    self.noeClassMatrix = ScrolledMatrix(guiFrame,
                                         headingList=headingList,
                                         callback=self.selectClass,
                                         tipTexts=tipTexts,
                                         editWidgets=editWidgets,
                                         editSetCallbacks=editSetCallbacks,
                                         editGetCallbacks=editGetCallbacks,
                                         deleteFunc=self.deleteClass,
                                         grid=(row,0), gridSpan=(1,2))
                                         

    row +=1

    tipTexts = ['Add a new distance restraint category',
                'Deleted selected restraint categor']
    texts = ['Add Class','Delete Class']
    commands = [self.addClass,self.deleteClass]
    self.bottomButtons = UtilityButtonList(guiFrame, doClone=False, grid=(row,0),
                                           gridSpan=(1,2), tipTexts=tipTexts,
                                           commands=commands, texts=texts)

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

    self.updateSpectra()
    self.update()
예제 #6
0
  def update(self):
  
    spec = self.peakList.dataSource.name
    expt = self.peakList.dataSource.experiment.name
    es = stringFromExperimentSpectrum(expt,spec)
    self.specLabel.set('Spectrum: '+es)
    self.listLabel.set('Peak List: List %d' % self.peakList.serial)

    numDims = self.peakList.dataSource.numDim
    self.numDims = numDims
    self.dimLabel=numDims * ['']
    self.adjustEntry=numDims * ['']
    self.adjusts=numDims * [0]
    
    for i in range(numDims):
      self.dimLabel[i] = Label(self, text = "F%d" % (i+1) )
      self.dimLabel[i].grid(row = i+2, column = 0, columnspan=1, sticky='w')
      self.adjustEntry[i] = FloatEntry(self, text = "%f" % self.adjusts[i],
                                       width=10, tipText='The referencing adjustment to add for this dimension')
      self.adjustEntry[i].grid(row = i+2, column = 1, columnspan=2, sticky='w')
      
    self.goButton     .grid(row = i+3, column = 0, columnspan=1, sticky='nsew')
    self.clearButton  .grid(row = i+3, column = 1, columnspan=1, sticky='nsew')
    self.cancelButton .grid(row = i+3, column = 2, columnspan=1, sticky='nsew')
예제 #7
0
class AssignMentTransferTab(object):
    '''the tab in the GUI where assignments
       can be transferred in bulk to the ccpn analysis
       project. A difference is made between two types
       of assignments:
           1) spin systems to residues, which also
              implies resonanceSets to atomSets.
           2) resonances to peak dimensions.
       The user is able to configure which assignments
       should be transferred to the project.

      Attributes:

          guiParent: gui object this tab is part of.

          frame: the frame in which this element lives.

          dataModel(src.cython.malandro.DataModel): dataModel
              object describing the assignment proposed by
              the algorithm.

          selectedSolution (int): The index of the solution/run
              that is used asa the template to make the assignments.

          resonanceToDimension (bool): True if resonances should
              be assigned to peak dimensions. False if not.

          spinSystemToResidue (bool): True if spin system to
              residue assignment should be carried out.

          minScore (float): The minimal score of a spin system
              assignment to a residue to be allowed
              to transfer this assignment to the project

          intra (bool): True if intra-residual peaks should be
              assigned.

          sequential (bool): True if sequential peaks should be
              assigned.

          noDiagonal (bool): If True, purely diagonal peaks are
              ignored during the transfer of assignments.

          allSpectra (bool): If True, all spectra will be assigned.
              If False, one specified spectrum will be assigned.

          spectrum (src.cython.malandro.Spectrum): The spectrum
              that should be assigned.
    '''
    def __init__(self, parent, frame):
        '''Init. args: parent: the guiElement that this
                               tab is part of.
                       frame:  the frame this part of the
                               GUI lives in.
        '''

        self.guiParent = parent
        self.frame = frame

        # Buttons and fields,
        # will be set in body():
        self.peaksCheckButton = None
        self.residuesCheckButton = None
        self.intraCheckButton = None
        self.sequentialCheckButton = None
        self.noDiagonalCheckButton = None
        self.spinSystemTypeSelect = None
        self.minScoreEntry = None
        self.solutionNumberEntry = None
        self.spectrumSelect = None
        self.spectraPullDown = None
        self.assignedResidueStrategySelect = None
        self.transferButton = None

        # Settings that determine how assignments
        # are transferred to the analysis project:
        self.minScore = 80.0
        self.dataModel = None
        self.spectrum = None
        self.selectedSolution = 1
        self.body()
        self.resonanceToDimension = True
        self.spinSystemToResidue = True
        self.intra = True
        self.sequential = True
        self.noDiagonal = True
        self.allSpectra = True
        self.spinSystemType = 0
        self.strategy = 0

    def body(self):
        '''Describes the body of this tab. It consists
           out of a number of radio buttons, check buttons
           and number entries that allow the user to
           indicate which assignments should be transferred.
        '''

        # self.frame.expandColumn(0)
        self.frame.expandGrid(8, 0)
        self.frame.expandGrid(8, 1)

        typeOfAssignmentFrame = LabelFrame(self.frame,
                                           text='type of assignment')
        typeOfAssignmentFrame.grid(row=0, column=0, sticky='nesw')
        # typeOfAssignmentFrame.expandGrid(0,5)

        peakSelectionFrame = LabelFrame(self.frame,
                                        text='which peaks to assign')
        peakSelectionFrame.grid(row=0, column=1, sticky='nesw', rowspan=2)

        spinSystemSelectionFrame = LabelFrame(self.frame,
                                              text='Which spin-systems to use')
        spinSystemSelectionFrame.grid(row=2, column=0, sticky='nesw')

        tipText = 'What to do when a residue has already a spin system assigned to it.'
        assignedResidueFrame = LabelFrame(
            self.frame,
            text='if residue already has spin-system',
            tipText=tipText)
        assignedResidueFrame.grid(row=2, column=1, sticky='nesw')

        spectrumSelectionFrame = LabelFrame(self.frame, text='spectra')
        spectrumSelectionFrame.grid(row=1, column=0, sticky='nesw')

        row = 0

        Label(typeOfAssignmentFrame,
              text='Resonances to Peak Dimensions',
              grid=(row, 0))
        self.peaksCheckButton = CheckButton(typeOfAssignmentFrame,
                                            selected=True,
                                            grid=(row, 1))

        row += 1

        Label(typeOfAssignmentFrame,
              text='SpinSystems to Residues',
              grid=(row, 0))
        self.residuesCheckButton = CheckButton(typeOfAssignmentFrame,
                                               selected=True,
                                               grid=(row, 1))

        row = 0

        Label(peakSelectionFrame, text='Intra-Residual', grid=(row, 0))
        self.intraCheckButton = CheckButton(peakSelectionFrame,
                                            selected=True,
                                            grid=(row, 1))

        row += 1

        Label(peakSelectionFrame, text='Sequential', grid=(row, 0))
        self.sequentialCheckButton = CheckButton(peakSelectionFrame,
                                                 selected=True,
                                                 grid=(row, 1))

        row += 1

        Label(peakSelectionFrame,
              text='Do not assign diagonal peaks',
              grid=(row, 0))
        self.noDiagonalCheckButton = CheckButton(peakSelectionFrame,
                                                 selected=True,
                                                 grid=(row, 1))

        entries = [
            'Only assigned spin systems',
            'All that have a score of at least: ', 'User Defined',
            'Solution number:'
        ]
        tipTexts = [
            'Only assign resonances of spin systems that already have a sequential assignment for the assignment of peak dimensions. Spin system to residue assignment is not relevant in this case.',
            'Assign all spin systems that have a score of at least a given percentage. 50% or lower is not possible, because than spin systems might have to be assigned to more than 1 residue, which is impossible.',
            "As defined in the lower row of buttons in the 'results' tab.",
            'One of the single solutions of the annealing.'
        ]
        self.spinSystemTypeSelect = RadioButtons(spinSystemSelectionFrame,
                                                 entries=entries,
                                                 grid=(0, 0),
                                                 select_callback=None,
                                                 direction=VERTICAL,
                                                 gridSpan=(4, 1),
                                                 tipTexts=tipTexts)

        tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.'
        self.minScoreEntry = FloatEntry(spinSystemSelectionFrame,
                                        grid=(1, 1),
                                        width=7,
                                        text=str(self.minScore),
                                        returnCallback=self.changeMinScore,
                                        tipText=tipText)
        self.minScoreEntry.bind('<Leave>', self.changeMinScore, '+')

        self.solutionNumberEntry = IntEntry(spinSystemSelectionFrame,
                                            grid=(3, 1),
                                            width=7,
                                            text=1,
                                            returnCallback=self.solutionUpdate,
                                            tipText=tipText)
        self.solutionNumberEntry.bind('<Leave>', self.solutionUpdate, '+')

        #self.solutionPullDown = PulldownList(spinSystemSelectionFrame, None, grid=(3,1), sticky='w')

        entries = ['all spectra', 'only:']
        tipTexts = [
            'Assign peaks in all the spectra that where selected before the annealing ran.',
            'Only assign peaks in one particular spectrum. You can of course repeat this multiple times for different spectra.'
        ]
        self.spectrumSelect = RadioButtons(spectrumSelectionFrame,
                                           entries=entries,
                                           grid=(0, 0),
                                           select_callback=None,
                                           direction=VERTICAL,
                                           gridSpan=(2, 1),
                                           tipTexts=tipTexts)

        self.spectraPullDown = PulldownList(spectrumSelectionFrame,
                                            self.changeSpectrum,
                                            grid=(1, 1),
                                            sticky='w')

        entries = [
            'skip this residue', 'de-assign old spin system from residue',
            'assign, but never merge', 'warn to merge'
        ]
        tipTexts = [
            "Don't assign the new spin system to the residue. The residue is not skipped when the old spin system does not contain any resonances",
            "De-assign old spin system from residue, unless the old spin system is a spin system without any resonances.",
            "Don't merge any spin systems, merging can be performed later if nescesary in the Resonance --> SpinSystems window.",
            "Ask to merge individually for each spin system, this might result in clicking on a lot of popups."
        ]
        self.assignedResidueStrategySelect = RadioButtons(assignedResidueFrame,
                                                          entries=entries,
                                                          grid=(0, 0),
                                                          select_callback=None,
                                                          direction=VERTICAL,
                                                          gridSpan=(2, 1),
                                                          tipTexts=tipTexts)

        texts = ['Transfer Assignments']
        commands = [self.transferAssignments]
        self.transferButton = ButtonList(self.frame,
                                         commands=commands,
                                         texts=texts)
        self.transferButton.grid(row=5, column=0, sticky='nsew', columnspan=2)

    def update(self):
        '''Update the nescesary elements in the
           tab. Is called when the algorithm
           has produced possible assignments.
           The only thing that has to be updated
           in practice in this tab is the pulldown
           with spectra.
        '''

        self.dataModel = self.guiParent.connector.results
        self.updateSpectra()

    def setDataModel(self, dataModel):
        '''Here the dataModel, which is the dataModel
           containing the suggested assignments body
           the algorithm, can be set.
        '''

        self.dataModel = dataModel
        self.update()

    def updateSpectra(self, *opt):
        '''Updates the spectra shown in the spectra
           pulldown. These are only the spectra that
           were used by the algorithm. All other spectra
           in the project are not relevant since for those
           no simulated peaks have been matched to real
           peaks.
        '''

        if not self.dataModel:

            return

        spectrum = self.spectrum

        spectra = self.dataModel.getSpectra()

        if spectra:

            names = [spectrum.name for spectrum in spectra]
            index = 0

            if self.spectrum not in spectra:

                self.spectrum = spectra[0]

            else:

                index = spectra.index(self.spectrum)

        self.spectraPullDown.setup(names, spectra, index)

    def changeSpectrum(self, spectrum):
        '''Select a spectum to be assigned.'''

        self.spectrum = spectrum

    def solutionUpdate(self, event=None, value=None):
        '''Select a solution. A solution is a
           one to one mapping of spin systems
           to residues produced by one run of
           the algorithm.
               args: event: event object, this is
                            one of the values the number
                            entry calls his callback
                            function with.
                     value: the index of the solution/run.
        '''

        if not self.dataModel:

            return

        Nsolutions = len(self.dataModel.chain.residues[0].solutions)

        if value is None:

            value = self.solutionNumberEntry.get()

        if value == self.selectedSolution:
            return
        else:
            self.selectedSolution = value
        if value < 1:
            self.solutionNumberEntry.set(1)
            self.selectedSolution = 1
        elif value > Nsolutions:
            self.selectedSolution = Nsolutions
            self.solutionNumberEntry.set(self.selectedSolution)
        else:
            self.solutionNumberEntry.set(self.selectedSolution)

    def fetchOptions(self):
        '''Fetches user set options from the gui in
           one go and stores them in their corresponding
           instance variables.
        '''

        self.resonanceToDimension = self.peaksCheckButton.get()
        self.spinSystemToResidue = self.residuesCheckButton.get()
        self.intra = self.intraCheckButton.get()
        self.sequential = self.sequentialCheckButton.get()
        self.noDiagonal = self.noDiagonalCheckButton.get()
        self.spinSystemType = self.spinSystemTypeSelect.getIndex()
        self.strategy = ['skip', 'remove', 'noMerge',
                         None][self.assignedResidueStrategySelect.getIndex()]
        self.allSpectra = [True, False][self.spectrumSelect.getIndex()]

    def changeMinScore(self, event=None):
        '''Set the minimal score for which a spin system
           to residue assignment gets transferred to the
           ccpn analysis project.
        '''

        newMinScore = self.minScoreEntry.get()

        if self.minScore != newMinScore:

            if newMinScore <= 50.0:

                self.minScore = 51.0
                self.minScoreEntry.set(51.0)

            elif newMinScore > 100.0:

                self.minScore = 100.0
                self.minScoreEntry.set(100.0)

            else:

                self.minScore = newMinScore

    def transferAssignments(self):
        '''Transfer assignments to project depending
           on the settings from the GUI.
        '''

        self.fetchOptions()

        if not self.dataModel or (not self.resonanceToDimension
                                  and not self.spinSystemToResidue):

            return

        strategy = self.strategy

        lookupSpinSystem = [
            self.getAssignedSpinSystem, self.getBestScoringSpinSystem,
            self.getUserDefinedSpinSystem, self.getSelectedSolutionSpinSystem
        ][self.spinSystemType]

        residues = self.dataModel.chain.residues

        spinSystemSequence = [lookupSpinSystem(res) for res in residues]

        ccpnSpinSystems = []
        ccpnResidues = []

        # if self.spinSystemType == 0 it means that it for sure already
        # assigned like this
        if self.spinSystemToResidue and not self.spinSystemType == 0:

            for spinSys, res in zip(spinSystemSequence, residues):

                if spinSys and res:

                    ccpnSpinSystems.append(spinSys.getCcpnResonanceGroup())
                    ccpnResidues.append(res.getCcpnResidue())

            assignSpinSystemstoResidues(ccpnSpinSystems,
                                        ccpnResidues,
                                        strategy=strategy,
                                        guiParent=self.guiParent)

        if self.resonanceToDimension:

            allSpectra = self.allSpectra

            if self.intra:

                for residue, spinSystem in zip(residues, spinSystemSequence):

                    if not spinSystem:

                        continue

                    intraLink = residue.getIntraLink(spinSystem)

                    for pl in intraLink.getPeakLinks():

                        peak = pl.getPeak()

                        if not allSpectra and peak.getSpectrum(
                        ) is not self.spectrum:

                            continue

                        if not peak:

                            continue

                        resonances = pl.getResonances()

                        if self.noDiagonal and len(
                                set(resonances)) < len(resonances):

                            continue

                        for resonance, dimension in zip(
                                resonances, peak.getDimensions()):

                            ccpnResonance = resonance.getCcpnResonance()
                            ccpnDimension = dimension.getCcpnDimension()
                            assignResToDim(ccpnDimension, ccpnResonance)

            if self.sequential:

                for residue, spinSystemA, spinSystemB in zip(
                        residues, spinSystemSequence, spinSystemSequence[1:]):

                    if not spinSystemA or not spinSystemB:

                        continue

                    link = residue.getLink(spinSystemA, spinSystemB)

                    for pl in link.getPeakLinks():

                        peak = pl.getPeak()

                        if not allSpectra and peak.getSpectrum(
                        ) is not self.spectrum:

                            continue

                        if not peak:

                            continue

                        resonances = pl.getResonances()

                        if self.noDiagonal and len(
                                set(resonances)) < len(resonances):

                            continue

                        for resonance, dimension in zip(
                                resonances, peak.getDimensions()):

                            ccpnResonance = resonance.getCcpnResonance()
                            ccpnDimension = dimension.getCcpnDimension()

                            assignResToDim(ccpnDimension, ccpnResonance)

        self.guiParent.resultsTab.update()

    def getAssignedSpinSystem(self, residue):
        '''Get the spinSystem that is assigned in the project
           to a residue.
           args:  residue (src.cython.malandro.Residue)
           return: spinSystem (src.cython.malandro.SpinSystem)
        '''

        ccpCode = residue.ccpCode
        seqCode = residue.getSeqCode()
        spinSystems = self.dataModel.getSpinSystems()[ccpCode]

        ccpnResidue = residue.getCcpnResidue()
        if ccpnResidue:
            assignedResonanceGroups = ccpnResidue.getResonanceGroups()
            if len(assignedResonanceGroups) > 1:
                print 'There is more than one spin system assigned to residue %s, did not know which one to use to assign peaks. Therefor this residue is skipped.' % (
                    seqCode)
                return

            assignedResonanceGroup = ccpnResidue.findFirstResonanceGroup()

            if assignedResonanceGroup:

                for spinSystem in spinSystems:

                    if spinSystem.getSerial() == assignedResonanceGroup.serial:
                        # Just checking to make sure, analysis project could
                        # have changed
                        if not self.skipResidue(residue, spinSystem):

                            return spinSystem

    def getBestScoringSpinSystem(self, residue):
        '''Get the spinSystem that scores the highest,
           i.e. is assigned in most of the runs to the
           given residue.
           args:  residue (src.cython.malandro.Residue)
           return: spinSystem (src.cython.malandro.SpinSystem)
        '''

        solutions = residue.solutions
        weigth = 1.0 / len(solutions)
        score, bestSpinSystem = max([
            (solutions.count(solution) * weigth * 100.0, solution)
            for solution in solutions
        ])

        if score >= self.minScore and not bestSpinSystem.getIsJoker(
        ) and not self.skipResidue(residue, bestSpinSystem):

            return bestSpinSystem

        return None

    def getUserDefinedSpinSystem(self, residue):
        '''Get the spinSystem that is defined by the user
           (probably in the resultsTab) as the correct
           assignment of the given residue.
           args:  residue (src.cython.malandro.Residue)
           return: spinSystem (src.cython.malandro.SpinSystem)
        '''

        userDefinedSpinSystem = residue.userDefinedSolution

        if userDefinedSpinSystem and not userDefinedSpinSystem.getIsJoker(
        ) and not self.skipResidue(residue, userDefinedSpinSystem):

            return userDefinedSpinSystem

        return None

    def getSelectedSolutionSpinSystem(self, residue):
        '''I a solution corresponding to one specific run
           of the algorithm is defined, return which spinSystem
           in that run got assigned to the given residue.
           args:  residue (src.cython.malandro.Residue)
           return: spinSystem (src.cython.malandro.SpinSystem)
        '''

        solutions = residue.solutions

        spinSystem = solutions[self.selectedSolution - 1]

        if not spinSystem.getIsJoker() and not self.skipResidue(
                residue, spinSystem):

            return spinSystem

        return None

    def skipResidue(self, residue, spinSystem):
        '''One strategy is to skip all residues that
           already have a spin system assignment.
           If that is the case determine whether to
           skip the given residue.
           args: residue (src.cython.malandro.Residue)
                 spinSystem (src.cython.malandro.SpinSystem)
           return: boolean, True if residue should be skipped.
        '''

        if self.strategy == 0:

            assignedGroups = residue.getCcpnResidue().getResonanceGroups()
            assignedSerials = set(
                [spinSys.serial for spinSys in assignedGroups])

            if assignedSerials and spinSystem.getSerial(
            ) not in assignedSerials:

                return True

        return False
예제 #8
0
  def body(self, guiFrame):

    self.geometry("500x500")

    self.nameEntry  = Entry(self, text='', returnCallback=self.setName,    width=12)
    self.detailsEntry = Entry(self, text='', returnCallback=self.setDetails, width=16)
    self.valueEntry = FloatEntry(self, text='', returnCallback=self.setValue, width=10)
    self.errorEntry = FloatEntry(self, text='', returnCallback=self.setError, width=8)
    
    self.conditionNamesPulldown = PulldownList(self, callback=self.setConditionName,
                                               texts=self.getConditionNames())
    self.unitPulldown = PulldownList(self, callback=self.setUnit,
                                     texts=self.getUnits())
    self.experimentPulldown = PulldownList(self, callback=self.setExperiment)

    guiFrame.grid_columnconfigure(0, weight=1)

    row = 0
    frame = Frame(guiFrame, grid=(row, 0))
    frame.expandGrid(None,0)
    div = LabelDivider(frame, text='Current Series', grid=(0, 0))
    utilButtons = UtilityButtonList(frame, helpUrl=self.help_url, grid=(0,1))

    row += 1
    frame0 = Frame(guiFrame, grid=(row, 0))
    frame0.expandGrid(0,0)
    tipTexts = ['The serial number of the experiment series, but left blank if the series as actually a pseudo-nD experiment (with a sampled non-frequency axis)',
                'The name of the experiment series, which may be a single pseudo-nD experiment',
                'The number of separate experiments (and hence spectra) present in the series',
                'The kind of quantity that varies for different experiments/planes within the NMR series, e.g. delay time, temperature, ligand concentration etc.',
                'The number of separate points, each with a separate experiment/plane and parameter value, in the series']
    headingList      = ['#','Name','Experiments','Parameter\nVaried','Num\nPoints']
    editWidgets      = [None, self.nameEntry, None, self.conditionNamesPulldown, None]
    editGetCallbacks = [None, self.getName,   None, self.getConditionName, None]
    editSetCallbacks = [None, self.setName,   None, self.setConditionName, None]
    self.seriesMatrix = ScrolledMatrix(frame0, tipTexts=tipTexts,
                                       editSetCallbacks=editSetCallbacks,
                                       editGetCallbacks=editGetCallbacks,
                                       editWidgets=editWidgets,
                                       headingList=headingList,
                                       callback=self.selectExpSeries,
                                       deleteFunc=self.deleteExpSeries,
                                       grid=(0,0), gridSpan=(None, 3))

    tipTexts = ['Make a new, blank NMR series specification in the CCPN project',
                'Delete the selected NMR series from the project, although any component experiments remain. Note you cannot delete pseudo-nD series; delete the actual experiment instead',
                'Colour the spectrum contours for each experiment in the selected series (not pseudo-nD) using a specified scheme']
    texts    = ['Add Series','Delete Series',
                'Auto Colour Spectra']
    commands = [self.addExpSeries,self.deleteExpSeries,
                self.autoColorSpectra]
                
    self.seriesButtons = ButtonList(frame0, texts=texts, commands=commands,
                                    grid=(1,0), tipTexts=tipTexts)

    label = Label(frame0, text='Scheme:', grid=(1,1))
    
    tipText = 'Selects which colour scheme to apply to the contours of (separate) experiments within an NMR series'
    self.colorSchemePulldown = PulldownList(frame0, grid=(1,2), tipText=tipText)

    row += 1
    div = LabelDivider(guiFrame, text='Experimental Parameters & Conditions', grid=(row, 0))

    row += 1
    guiFrame.grid_rowconfigure(row, weight=1)
    frame1 = Frame(guiFrame, grid=(row, 0))
    frame1.expandGrid(0,0)
    tipTexts = ['The kind of experimental parameter that is being used to define the NMR series',
                'The experiment that corresponds to the specified parameter value; can be edited from an arbitrary initial experiment',
                'The numeric value of the parameter (condition) that relates to the experiment or point in the NMR series',
                'The estimated error in value of the condition',
                'The measurement unit in which the value of the condition is represented']
    headingList      = ['Parameter','Experiment','Value','Error','Unit']
    editWidgets      = [None,self.experimentPulldown,self.valueEntry,self.errorEntry, self.unitPulldown]
    editGetCallbacks = [None,self.getExperiment,     self.getValue,  self.getError,   self.getUnit]
    editSetCallbacks = [None,self.setExperiment,     self.setValue,  self.setError,   self.setUnit]
    self.conditionPointsMatrix = ScrolledMatrix(frame1, grid=(0,0), tipTexts=tipTexts,
                                                editSetCallbacks=editSetCallbacks,
                                                editGetCallbacks=editGetCallbacks,
                                                editWidgets=editWidgets,
                                                headingList=headingList,
                                                callback=self.selectConditionPoint,
                                                deleteFunc=self.deleteConditionPoint)
    
    self.conditionPointsMatrix.doEditMarkExtraRules = self.conditionTableShow 
    tipTexts = ['Add a new point to the NMR series with an associated parameter value and experiment',
                'Remove the selected point from the series, including any associated parameter value',
                'For appropriate kinds of NMR series, set or unset a point as representing the plane to use as a reference']
    texts    = ['Add Series Point','Delete Series Point','Set/Unset Ref Plane']
    commands = [self.addConditionPoint,self.deleteConditionPoint,self.setSampledReferencePlane]
    self.conditionPointsButtons = ButtonList(frame1, texts=texts, commands=commands,
                                             tipTexts=tipTexts, grid=(1,0))
    
    self.updateAfter()
    self.updateColorSchemes()

    self.administerNotifiers(self.registerNotify)
예제 #9
0
class CloudHomologueAssignPopup(BasePopup):

  def __init__(self, parent, *args, **kw):

    self.guiParent = parent
    self.project   = parent.getProject()
    self.molSystem = None
    self.chain     = None
    self.assignment = None
    self.scores     = []

    BasePopup.__init__(self, parent, title="Cloud Threader", **kw)
  
  def body(self, guiFrame):

    guiFrame.grid_columnconfigure(3, weight=1)
    
    row = 0
    label = Label(guiFrame, text='Molecular system: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.molSysPulldown = PulldownMenu(guiFrame, self.changeMolSystem, selected_index=-1, do_initial_callback=0)
    self.molSysPulldown.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Clouds files: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.filenameEntry = Entry(guiFrame,text='perfect00.pdb')
    self.filenameEntry.grid(row=row, column=3, sticky=Tkinter.NW)


    row += 1
    label = Label(guiFrame, text='Chain: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.chainPulldown = PulldownMenu(guiFrame, self.changeChain, selected_index=-1, do_initial_callback=0)
    self.chainPulldown.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Thread steps: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.numStepsEntry = IntEntry(guiFrame,text=3000)
    self.numStepsEntry.grid(row=row, column=3, sticky=Tkinter.NW)
    row += 1

    label = Label(guiFrame, text='Homologue PDB file: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.pdbEntry = Entry(guiFrame,text='')
    self.pdbEntry.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Dist. Threshold: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.distEntry = FloatEntry(guiFrame,text=3.0)
    self.distEntry.grid(row=row, column=3, sticky=Tkinter.NW)

    row += 1

    label = Label(guiFrame, text='Global score: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.globalScoreLabel = Label(guiFrame, text='')
    self.globalScoreLabel.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Assignment Threshold: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.thresholdEntry = FloatEntry(guiFrame,text=-4.5)
    self.thresholdEntry.grid(row=row, column=3, sticky=Tkinter.NW)

    row += 1
    guiFrame.grid_rowconfigure(row, weight=1)
    self.graph = ScrolledGraph(guiFrame, width=300, height=200)
    self.graph.grid(row=row, column=0, columnspan=4, sticky = Tkinter.NSEW)

    row += 1
    texts    = ['Run','Assign!']
    commands = [self.run, self.assignSpinSystems]
    bottomButtons = createDismissHelpButtonList(guiFrame,texts=texts,commands=commands,expands=0,help_url=None)
    bottomButtons.grid(row=row, column=0, columnspan=4, sticky=Tkinter.EW)
    self.assignButton = bottomButtons.buttons[1]

    for func in ('__init__','delete'):
      Implementation.registerNotify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem', func)
      Implementation.registerNotify(self.updateChains, 'ccp.molecule.MolSystem.Chain', func)
    
    self.updateMolSystems()
    self.updateChains()

  def update(self):
  
    if self.assignment and self.scores:
      self.assignButton.enable()
    else:
      self.assignButton.disable()  

  def run(self):
  
    if self.chain:
      pattern = self.filenameEntry.get()
      nSteps  = self.numStepsEntry.get() or 4000
      pdbFile = self.pdbEntry.get()
      dist    =  self.distEntry.get() or 3.0
      pgb     = ProgressBar(self, text='Searching', total=nSteps)
      files   = getFileNamesFromPattern(pattern , '.')
      if not files:
        return
      clouds  = getCloudsFromFile(files, self.chain.root)
       
      score, self.scores, self.assignment = cloudHomologueAssign(self.chain, clouds, pdbFile, dist, nSteps, self.graph, pgb)
 
      pgb.destroy()
      self.globalScoreLabel.set(str(score))
      self.update()

  def assignSpinSystems(self):
   
    if self.assignment and self.scores:
      if showWarning('Query','Are you sure?'):
        threshold = self.thresholdEntry.get() or -4.0
        i = 0
 
        for residue in self.assignment.keys():
          if self.scores[residue] > threshold:
            spinSystem = self.assignment[residue]
            assignSpinSystemResidue(spinSystem,residue=None)
 
        for residue in self.assignment.keys():
          if self.scores[residue] > threshold:
            i += 1
            spinSystem = self.assignment[residue]
            assignSpinSystemResidue(spinSystem,residue=residue)
      
      showWarning('Done','%d residues assigned' % i)
      
  def getMolSystems(self):
  
    names = []
    for molSystem in self.project.molSystems:
      if molSystem.chains:
        names.append( '%s' % (molSystem.code) )
    return names


  def changeMolSystem(self, i, name):
  
    self.molSystem = self.project.findFirstMolSystem(code=name)


  def updateMolSystems(self, *opt):
  
    names = self.getMolSystems()
    if names:
      if not self.molSystem:
        self.molSystem = self.project.findFirstMolSystem(code=names[0])
      self.molSysPulldown.setup(names, names.index(self.molSystem.code))


  def getChains(self):
  
    chains = []
    if self.molSystem:
      for chain in self.molSystem.chains:
        chains.append( [chain.code, chain] )
	
    return chains


  def changeChain(self, i, name=None):
    
    if not name:
      i = self.chainPulldown.selected_index
    
    chains = self.getChains()
    if chains:
      self.chain = chains[i][1]
    
    
  def updateChains(self, *chain):
  
    chains = self.getChains()
 
    if chains:
      names = [x[0] for x in chains]
      if (not self.chain) or (self.chain.code not in names):
        self.chain = chains[0][1]
      self.chainPulldown.setup(names, names.index(self.chain.code) )

    self.update()

  def destroy(self):

    for func in ('__init__','delete'):
      Implementation.unregisterNotify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem', func)
      Implementation.unregisterNotify(self.updateChains, 'ccp.molecule.MolSystem.Chain', func)

    BasePopup.destroy(self)
예제 #10
0
    def body(self):
        '''Describes the body of this tab. It consists
           out of a number of radio buttons, check buttons
           and number entries that allow the user to
           indicate which assignments should be transferred.
        '''

        # self.frame.expandColumn(0)
        self.frame.expandGrid(8, 0)
        self.frame.expandGrid(8, 1)

        typeOfAssignmentFrame = LabelFrame(
            self.frame, text='type of assignment')
        typeOfAssignmentFrame.grid(row=0, column=0, sticky='nesw')
        # typeOfAssignmentFrame.expandGrid(0,5)

        peakSelectionFrame = LabelFrame(
            self.frame, text='which peaks to assign')
        peakSelectionFrame.grid(row=0, column=1, sticky='nesw', rowspan=2)

        spinSystemSelectionFrame = LabelFrame(self.frame,
                                              text='Which spin-systems to use')
        spinSystemSelectionFrame.grid(row=2, column=0, sticky='nesw')

        tipText = 'What to do when a residue has already a spin system assigned to it.'
        assignedResidueFrame = LabelFrame(self.frame,
                                          text='if residue already has spin-system',
                                          tipText=tipText)
        assignedResidueFrame.grid(row=2, column=1, sticky='nesw')

        spectrumSelectionFrame = LabelFrame(self.frame, text='spectra')
        spectrumSelectionFrame.grid(row=1, column=0, sticky='nesw')

        row = 0

        Label(typeOfAssignmentFrame,
              text='Resonances to Peak Dimensions',
              grid=(row, 0))
        self.peaksCheckButton = CheckButton(typeOfAssignmentFrame,
                                            selected=True,
                                            grid=(row, 1))

        row += 1

        Label(typeOfAssignmentFrame,
              text='SpinSystems to Residues',
              grid=(row, 0))
        self.residuesCheckButton = CheckButton(
            typeOfAssignmentFrame, selected=True, grid=(row, 1))

        row = 0

        Label(peakSelectionFrame, text='Intra-Residual', grid=(row, 0))
        self.intraCheckButton = CheckButton(
            peakSelectionFrame, selected=True, grid=(row, 1))

        row += 1

        Label(peakSelectionFrame, text='Sequential', grid=(row, 0))
        self.sequentialCheckButton = CheckButton(
            peakSelectionFrame, selected=True, grid=(row, 1))

        row += 1

        Label(peakSelectionFrame,
              text='Do not assign diagonal peaks',
              grid=(row, 0))
        self.noDiagonalCheckButton = CheckButton(
            peakSelectionFrame, selected=True, grid=(row, 1))

        entries = ['Only assigned spin systems',
                   'All that have a score of at least: ',
                   'User Defined',
                   'Solution number:']
        tipTexts = ['Only assign resonances of spin systems that already have a sequential assignment for the assignment of peak dimensions. Spin system to residue assignment is not relevant in this case.',
                    'Assign all spin systems that have a score of at least a given percentage. 50% or lower is not possible, because than spin systems might have to be assigned to more than 1 residue, which is impossible.',
                    "As defined in the lower row of buttons in the 'results' tab.",
                    'One of the single solutions of the annealing.']
        self.spinSystemTypeSelect = RadioButtons(spinSystemSelectionFrame,
                                                 entries=entries, grid=(0, 0),
                                                 select_callback=None,
                                                 direction=VERTICAL,
                                                 gridSpan=(4, 1),
                                                 tipTexts=tipTexts)

        tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.'
        self.minScoreEntry = FloatEntry(spinSystemSelectionFrame,
                                        grid=(1, 1), width=7,
                                        text=str(self.minScore),
                                        returnCallback=self.changeMinScore,
                                        tipText=tipText)
        self.minScoreEntry.bind('<Leave>', self.changeMinScore, '+')

        self.solutionNumberEntry = IntEntry(spinSystemSelectionFrame,
                                            grid=(3, 1), width=7, text=1,
                                            returnCallback=self.solutionUpdate,
                                            tipText=tipText)
        self.solutionNumberEntry.bind('<Leave>', self.solutionUpdate, '+')

        #self.solutionPullDown = PulldownList(spinSystemSelectionFrame, None, grid=(3,1), sticky='w')

        entries = ['all spectra', 'only:']
        tipTexts = ['Assign peaks in all the spectra that where selected before the annealing ran.',
                    'Only assign peaks in one particular spectrum. You can of course repeat this multiple times for different spectra.']
        self.spectrumSelect = RadioButtons(spectrumSelectionFrame,
                                           entries=entries,
                                           grid=(0, 0),
                                           select_callback=None,
                                           direction=VERTICAL,
                                           gridSpan=(2, 1), tipTexts=tipTexts)

        self.spectraPullDown = PulldownList(spectrumSelectionFrame,
                                            self.changeSpectrum,
                                            grid=(1, 1), sticky='w')

        entries = ['skip this residue',
                   'de-assign old spin system from residue',
                   'assign, but never merge',
                   'warn to merge']
        tipTexts = ["Don't assign the new spin system to the residue. The residue is not skipped when the old spin system does not contain any resonances",
                    "De-assign old spin system from residue, unless the old spin system is a spin system without any resonances.",
                    "Don't merge any spin systems, merging can be performed later if nescesary in the Resonance --> SpinSystems window.",
                    "Ask to merge individually for each spin system, this might result in clicking on a lot of popups."]
        self.assignedResidueStrategySelect = RadioButtons(assignedResidueFrame,
                                                          entries=entries,
                                                          grid=(0, 0),
                                                          select_callback=None,
                                                          direction=VERTICAL,
                                                          gridSpan=(2, 1),
                                                          tipTexts=tipTexts)

        texts = ['Transfer Assignments']
        commands = [self.transferAssignments]
        self.transferButton = ButtonList(
            self.frame, commands=commands, texts=texts)
        self.transferButton.grid(row=5, column=0, sticky='nsew', columnspan=2)
예제 #11
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)
예제 #12
0
  def body(self, mainFrame):

    mainFrame.grid_columnconfigure(1, weight=1, minsize=100)
    mainFrame.config(borderwidth=5, relief='solid')

    row = 0
    label = Label(mainFrame, text="Frame (with sub-widgets):")
    label.grid(row=row, column=0, sticky=Tkinter.E)

    frame = Frame(mainFrame, relief='raised', border=2, background='#8080D0')
    # Frame expands East-West
    frame.grid(row=row, column=1, sticky=Tkinter.EW)
    # Last column expands => Widgets pusted to the West
    frame.grid_columnconfigure(3, weight=1)
    
    # Label is within the sub frame
    label = Label(frame, text='label ')
    label.grid(row=0, column=0, sticky=Tkinter.W)
    
    entry = Entry(frame, text='Entry', returnCallback=self.showWarning)
    entry.grid(row=0, column=1, sticky=Tkinter.W)
    
    self.check = CheckButton(frame, text='Checkbutton', selected=True, callback=self.updateObjects)
    self.check.grid(row=0, column=2, sticky=Tkinter.W)
    
    # stick a button to the East wall
    button = Button(frame, text='Button', command=self.pressButton)
    button.grid(row=0, column=3, sticky=Tkinter.E)
  
    row += 1
    label = Label(mainFrame, text="Text:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    self.textWindow = Text(mainFrame, text='Initial Text\n', width=60, height=5)
    self.textWindow.grid(row=row, column=1, sticky=Tkinter.NSEW)
    
    row += 1
    label = Label(mainFrame, text="CheckButtons:")
    label.grid(row=row, column=0, sticky=Tkinter.E)

    entries = ['Alpha','Beta','Gamma','Delta']
    selected = entries[2:]
    self.checkButtons = CheckButtons(mainFrame, entries, selected=selected,select_callback=self.changedCheckButtons)
    self.checkButtons.grid(row=row, column=1, sticky=Tkinter.W)
  
    row += 1
    label = Label(mainFrame, text="PartitionedSelector:")
    label.grid(row=row, column=0, sticky=Tkinter.E)

    labels   = ['Bool','Int','Float','String']
    objects  = [type(0),type(1),type(1.0),type('a')]
    selected = [type('a')]
    self.partitionedSelector= PartitionedSelector(mainFrame, labels=labels,
                                                  objects=objects,
                                                  colors = ['red','yellow','green','#000080'],
                                                  callback=self.toggleSelector,selected=selected)
    self.partitionedSelector.grid(row=row, column=1, sticky=Tkinter.EW)

    row += 1
    label = Label(mainFrame, text="PulldownMenu")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    
    entries = ['Frodo','Pipin','Merry','Sam','Bill','Gandalf','Strider','Gimli','Legolas']
    self.pulldownMenu = PulldownMenu(mainFrame, callback=self.selectPulldown,
                                     entries=entries, selected_index=2,
                                     do_initial_callback=False)
    self.pulldownMenu.grid(row=row, column=1, sticky=Tkinter.W)

    row += 1
    label = Label(mainFrame, text="RadioButtons in a\nScrolledFrame.frame:")
    label.grid(row=row, column=0, sticky=Tkinter.EW)
    
    frame = ScrolledFrame(mainFrame, yscroll = False, doExtraConfig = True, width=100)
    frame.grid(row=row, column=1, sticky=Tkinter.EW)
    frame.grid_columnconfigure(0, weight=1)

    self.radioButtons = RadioButtons(frame.frame, entries=entries,
                                     select_callback=self.checkRadioButtons,
                                     selected_index=1, relief='groove')
    self.radioButtons.grid(row=0, column=0, sticky=Tkinter.W)
    
    row += 1
    label = Label(mainFrame, text="LabelFrame with\nToggleLabels inside:")
    label.grid(row=row, column=0, sticky=Tkinter.E)

    labelFrame = LabelFrame(mainFrame, text='Frame Title')
    labelFrame.grid(row=row, column=1, sticky=Tkinter.NSEW)
    labelFrame.grid_rowconfigure(0, weight=1)
    labelFrame.grid_columnconfigure(3, weight=1)
    
        
    self.toggleLabel1 = ToggleLabel(labelFrame, text='ScrolledMatrix', callback=self.toggleFrame1)
    self.toggleLabel1.grid(row=0, column=0, sticky=Tkinter.W)
    self.toggleLabel1.arrowOn()

    self.toggleLabel2 = ToggleLabel(labelFrame, text='ScrolledGraph', callback=self.toggleFrame2)
    self.toggleLabel2.grid(row=0, column=1, sticky=Tkinter.W)

    self.toggleLabel3 = ToggleLabel(labelFrame, text='ScrolledCanvas', callback=self.toggleFrame3)
    self.toggleLabel3.grid(row=0, column=2, sticky=Tkinter.W)
    
    row += 1
    mainFrame.grid_rowconfigure(row, weight=1)

    label = Label(mainFrame, text="changing/shrinking frames:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    
    self.toggleRow = row
    self.toggleFrame = Frame(mainFrame)
    self.toggleFrame.grid(row=row, column=1, sticky=Tkinter.NSEW)
    self.toggleFrame.grid_rowconfigure(0, weight=1)
    self.toggleFrame.grid_columnconfigure(0, weight=1)
    
    # option 1
    
    self.intEntry = IntEntry(self, returnCallback = self.setNumber, width=8)
    
    self.multiWidget = MultiWidget(self, Entry, options=None, 
                                  values=None, callback=self.setKeywords,
                                  minRows=3, maxRows=5)

    editWidgets      = [None, None, self.intEntry,  self.multiWidget]
    editGetCallbacks = [None, None, self.getNumber, self.getKeywords]
    editSetCallbacks = [None, None, self.setNumber, self.setKeywords]
    
    headingList = ['Name','Color','Number','Keywords']
    self.scrolledMatrix = ScrolledMatrix(self.toggleFrame, headingList=headingList,
                                         editSetCallbacks=editSetCallbacks,
                                         editGetCallbacks=editGetCallbacks,
                                         editWidgets=editWidgets,
                                         callback=self.selectObject,
                                         multiSelect=False) 
                                         
    self.scrolledMatrix.grid(row=0, column=0, sticky=Tkinter.NSEW)

    # option 2
    self.scrolledGraph = ScrolledGraph(self.toggleFrame, width=400,
                                       height=300, symbolSize=5,
                                       symbols=['square','circle'],
                                       dataColors=['#000080','#800000'],
                                       lineWidths=[0,1] )

    self.scrolledGraph.setZoom(1.3)

    dataSet1 = [[0,0],[1,1],[2,4],[3,9],[4,16],[5,25]]
    dataSet2 = [[0,0],[1,3],[2,6],[3,9],[4,12],[5,15]]
    self.scrolledGraph.update(dataSets=[dataSet1,dataSet2],
                              xLabel = 'X axis label',
                              yLabel = 'Y axis label',
                              title  = 'Main Title')
    self.scrolledGraph.draw()

    # option 3
    self.scrolledCanvas = ScrolledCanvas(self.toggleFrame,relief = 'groove', borderwidth = 2, resizeCallback=None)
    canvas = self.scrolledCanvas.canvas
    font   = 'Helvetica 10'
    box    = canvas.create_rectangle(10,10,150,200, outline='grey', fill='grey90')
    line   = canvas.create_line(0,0,200,200,fill='#800000', width=2)
    text   = canvas.create_text(120,50, text='Text', font=font, fill='black')
    circle = canvas.create_oval(30,30,50,50,outline='#008000',fill='#404040',width=3)
     
    row += 1
    label = Label(mainFrame, text="FloatEntry:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    self.floatEntry = FloatEntry(mainFrame, text=3.14159265, returnCallback=self.floatEntryReturn)
    self.floatEntry.grid(row=row, column=1, sticky=Tkinter.W)
    
     
    row += 1
    label = Label(mainFrame, text="Scale:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    self.scale = Scale(mainFrame, from_=10, to=90, value=50, orient=Tkinter.HORIZONTAL)
    self.scale.grid(row=row, column=1, sticky=Tkinter.W)

    row += 1
    label = Label(mainFrame, text="Value Ramp:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    self.valueRamp = ValueRamp(mainFrame, self.valueRampCallback, speed = 1.5, delay = 50)
    self.valueRamp.grid(row=row, column=1, sticky=Tkinter.W)
  

    row += 1
    label = Label(mainFrame, text="ButtonList:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    
    texts    = ['Select File','Close','Quit']
    commands = [self.selectFile, self.close, self.quit]
    bottomButtons = ButtonList(mainFrame, texts=texts, commands=commands, expands=True) 
    bottomButtons.grid(row=row, column=1, sticky=Tkinter.EW)
  
    self.protocol('WM_DELETE_WINDOW', self.quit)
예제 #13
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)
예제 #14
0
class EditNoeClassesPopup(BasePopup):

  def __init__(self, parent, *args, **kw):

    self.guiParent = parent
    BasePopup.__init__(self, parent=parent, title='NOE Distance Classes', **kw)

  def body(self, guiFrame):
  
    self.noeClassChoice = None
    self.spectrum = None
    self.intensEntry = FloatEntry(self, returnCallback=self.setIntens, width=5)
    self.targetEntry = FloatEntry(self, returnCallback=self.setTarget, width=5)
    self.minEntry    = FloatEntry(self, returnCallback=self.setMin,    width=5)
    self.maxEntry    = FloatEntry(self, returnCallback=self.setMax,    width=5)
   
    row = 0

    label = Label(guiFrame, text='Spectrum: ', grid=(row,0))
    tipText = ''
    self.spectrumPulldown = PulldownMenu(guiFrame,self.changeSpectrum, grid=(row,1))

    row +=1

    guiFrame.expandGrid(row, 1)

    tipTexts = ['Lower bound of this intensity category. Values are relative to reference intensity.',
                'Target restraint distance for this category',
                'Lower bound distance for this category',
                'Upper bound distance for this category']
    headingList = ['Min. NOE\nIntensity','Target\nDist','Min\nDist','Max\nDist']
    editWidgets = [self.intensEntry,self.targetEntry,self.minEntry,self.maxEntry]
    editGetCallbacks = [self.getIntens,self.getTarget,self.getMin,self.getMax]
    editSetCallbacks = [self.setIntens,self.setTarget,self.setMin,self.setMax]
    
    self.noeClassMatrix = ScrolledMatrix(guiFrame,
                                         headingList=headingList,
                                         callback=self.selectClass,
                                         tipTexts=tipTexts,
                                         editWidgets=editWidgets,
                                         editSetCallbacks=editSetCallbacks,
                                         editGetCallbacks=editGetCallbacks,
                                         deleteFunc=self.deleteClass,
                                         grid=(row,0), gridSpan=(1,2))
                                         

    row +=1

    tipTexts = ['Add a new distance restraint category',
                'Deleted selected restraint categor']
    texts = ['Add Class','Delete Class']
    commands = [self.addClass,self.deleteClass]
    self.bottomButtons = UtilityButtonList(guiFrame, doClone=False, grid=(row,0),
                                           gridSpan=(1,2), tipTexts=tipTexts,
                                           commands=commands, texts=texts)

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

    self.updateSpectra()
    self.update()

  def open(self):
  
    self.updateSpectra()
    self.update()
    BasePopup.open(self)

  def updateSpectra(self, *opt):
    
    spectra = self.getSpectra()
    if not spectra:
      return
    
    names = [self.getSpectrumName(x) for x in spectra]
    if (not self.spectrum) or (self.spectrum not in spectra):
      self.spectrum = spectra[0]
    
    self.spectrumPulldown.setup(names, names.index(self.getSpectrumName(self.spectrum)) )
    
    self.update()

  def changeSpectrum(self, i, name):
  
    self.spectrum = self.getSpectra()[i]
    self.update()

  def getSpectrumName(self,spectrum):
  
    name = '%s:%s' % (spectrum.experiment.name,spectrum.name)
    return name
  
  def getSpectra(self):
  
    spectra = set()
    peakLists = getThroughSpacePeakLists(self.nmrProject)
    
    for peakList in peakLists:
      spectra.add(peakList.dataSource)
 
    spectra = list(spectra)
    spectra.sort()
 
    return spectra
    
  def selectClass(self, noeClass, row, col):
  
    if noeClass:
      self.noeClassChoice = (row, noeClass)
      
    if len(self.noeClassMatrix.objectList) > 1:
      self.bottomButtons.buttons[1].enable()
    else:
      self.bottomButtons.buttons[1].disable()

  def addClass(self):
  
    if self.spectrum:
      noeClass = [0.0,6.0,0.0,6.0]
 
      noeClasses = getIntensityDistanceTable(self.spectrum)
      noeClasses.append(noeClass)
      setSpectrumNoeDistanceClasses(self.spectrum, noeClasses)

      self.update()
  
  def deleteClass(self, *event):
    
    if self.spectrum:
      noeClasses = getIntensityDistanceTable(self.spectrum)

      if self.noeClassChoice and (self.noeClassChoice[1] in noeClasses):
        if len(noeClasses) > 1:
          (i,noeClass) = self.noeClassChoice
          noeClasses.remove(noeClass)
          self.noeClassChoice = None
          setSpectrumNoeDistanceClasses(self.spectrum, noeClasses)
          self.update()
    
  def setIntens(self, event):
  
    if self.noeClassChoice:
      val = self.intensEntry.get() or 0.0
      self.noeClassChoice[1][0] = val
      
    self.updateClass()
  
  def getIntens(self, row):
  
    if row:
      self.intensEntry.set(row[0])
  
  def setTarget(self, event):
  
    if self.noeClassChoice:
      val = self.targetEntry.get() or 0.0
      self.noeClassChoice[1][1] = val
      
    self.updateClass()
  
  def getTarget(self, row):
  
    if row:
      self.targetEntry.set(row[1])
  
  def setMin(self, event):
  
    if self.noeClassChoice:
      val = self.minEntry.get() or 0.0
      self.noeClassChoice[1][2] = val
      
    self.updateClass()
  
  def getMin(self, row):
  
    if row:
      self.minEntry.set(row[2])
  
  def setMax(self, event):
  
    if self.noeClassChoice:
      val = self.maxEntry.get() or 0.0
      self.noeClassChoice[1][3] = val
      
    self.updateClass()
  
  def getMax(self, row):
  
    if row:
      self.maxEntry.set(row[3])
    
  def getClasses(self):
  
    noeClasses = []
    if self.spectrum:
      noeClasses = getIntensityDistanceTable(self.spectrum)

    if noeClasses:
      for i in range(len(noeClasses)):
        (intens,target,minimum,maximum) = noeClasses[i]

        if minimum > maximum:
          (minimum,maximum) = (maximum,minimum)
        minimum = min(target, minimum)
        maximum = max(target, maximum)
        intens  = max(intens, 0.0)
        
        noeClasses[i] = [intens,target,minimum,maximum]
      noeClasses.sort()
      noeClasses.reverse()
    
    else:
      noeClasses = []
      if self.spectrum:
        # default
        noeClasses = getIntensityDistanceTable(self.spectrum)
      
    return noeClasses
    
  def updateClass(self):
  
    if self.spectrum and self.noeClassChoice:
      (i, noeClass) = self.noeClassChoice
      noeClasses = getIntensityDistanceTable(self.spectrum)
      noeClasses[i] = noeClass
      setSpectrumNoeDistanceClasses(self.spectrum, noeClasses)
      self.update()
    
  def update(self):


    textMatrix = []
    objectList = self.getClasses()
    
    if self.spectrum:
      if self.noeClassChoice and (len(objectList) > 1):
        self.bottomButtons.buttons[1].enable()
      else:
        self.bottomButtons.buttons[1].disable()
      self.bottomButtons.buttons[0].enable()
    else:
      self.bottomButtons.buttons[0].disable()
      self.bottomButtons.buttons[1].disable()
      
    for (intens,target,minimum,maximum) in objectList:
      datum = []
      datum.append(intens)
      datum.append(target)
      datum.append(minimum)
      datum.append(maximum)
      textMatrix.append(datum)
    
    self.noeClassMatrix.update(objectList=objectList,textMatrix=textMatrix)
    
    if self.spectrum:
      setSpectrumNoeDistanceClasses(self.spectrum,objectList)
  
  def destroy(self):

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

    BasePopup.destroy(self)
예제 #15
0
    def body(self, guiParent):

        self.geometry("+150+150")

        guiParent.grid_columnconfigure(0, weight=1)
        self.master_frame = guiParent

        units = ('ppm', 'point', 'Hz')

        self.unit = 'ppm'

        self.specLabel = Label(guiParent,
                               fg=self.titleColor,
                               grid=(0, 0),
                               sticky='ew')

        self.peakLabel = Label(guiParent, grid=(0, 1), sticky='ew')

        self.unit_frame = frame = Frame(guiParent,
                                        grid=(1, 1),
                                        gridSpan=(1, 2))

        self.unitLabel = Label(frame, text='Current units: ', grid=(0, 0))
        tipText = 'Selects which unit of measurement to display peak dimension positions with'
        self.unitSelect = PulldownList(frame,
                                       callback=self.changeUnit,
                                       texts=units,
                                       grid=(0, 1),
                                       tipText=tipText)

        self.heightLabel = Label(guiParent,
                                 text='Height',
                                 borderwidth=2,
                                 relief='groove')
        tipText = 'Sets the peak height; the value of the spectrum point intensity (albeit often interpolated)'
        self.heightEntry = FloatEntry(guiParent,
                                      borderwidth=1,
                                      tipText=tipText)
        self.volumeLabel = Label(guiParent,
                                 text='Volume',
                                 borderwidth=2,
                                 relief='groove')
        tipText = 'Sets the peak volume integral; normally a summation of data point values'
        self.volumeEntry = FloatEntry(guiParent,
                                      borderwidth=1,
                                      tipText=tipText)
        self.detailLabel = Label(guiParent,
                                 text='Details',
                                 borderwidth=2,
                                 relief='groove')
        tipText = 'A user-configurable textual comment for the peak, which appears an tables and occasionally on spectrum displays'
        self.detailEntry = Entry(guiParent, borderwidth=1, tipText=tipText)

        tipTexts = [
            'Commits the specified values to update the peak and closes the popup',
        ]
        texts = ['Update']
        commands = [self.commit]
        self.buttons = UtilityButtonList(guiParent,
                                         texts=texts,
                                         commands=commands,
                                         doClone=False,
                                         helpUrl=self.help_url,
                                         tipTexts=tipTexts)
예제 #16
0
    def body(self, guiFrame):

        self.specFreqEntry = IntEntry(self,
                                      text=self.specFreq,
                                      width=8,
                                      returnCallback=self.setSpecFreq)
        self.maxIterEntry = IntEntry(self,
                                     text=self.maxIter,
                                     width=8,
                                     returnCallback=self.setMaxIter)
        self.mixTimeEntry = FloatEntry(self,
                                       text=self.mixTime,
                                       width=8,
                                       returnCallback=self.setMixTime)
        self.corrTimeEntry = FloatEntry(self,
                                        text=self.corrTime,
                                        width=8,
                                        returnCallback=self.setCorrTime)
        self.leakRateEntry = FloatEntry(self,
                                        text=self.leakRate,
                                        width=8,
                                        returnCallback=self.setLeakRate)
        self.maxIntensEntry = IntEntry(self,
                                       text=self.maxIntens,
                                       width=8,
                                       returnCallback=self.setMaxIntens)

        self.mdInitTempEntry = FloatEntry(self,
                                          text='',
                                          returnCallback=self.setMdInitTemp)
        self.mdFinTempEntry = FloatEntry(self,
                                         text='',
                                         returnCallback=self.setMdFinTemp)
        self.mdCoolStepsEntry = IntEntry(self,
                                         text='',
                                         returnCallback=self.setMdCoolSteps)
        self.mdSimStepsEntry = IntEntry(self,
                                        text='',
                                        returnCallback=self.setMdSimSteps)
        self.mdTauEntry = FloatEntry(self,
                                     text='',
                                     returnCallback=self.setMdTau)
        self.mdRepScaleEntry = FloatEntry(self,
                                          text='',
                                          returnCallback=self.setMdRepScale)

        guiFrame.grid_columnconfigure(0, weight=1)

        row = 0
        frame0 = LabelFrame(guiFrame, text='Setup peak lists')
        frame0.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame0.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame0.grid_columnconfigure(1, weight=1)

        f0row = 0
        label00 = Label(frame0, text='1H-1H NOESY spectrum')
        label00.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.noesyPulldown = PulldownMenu(frame0,
                                          entries=self.getNoesys(),
                                          callback=self.setNoesy,
                                          selected_index=0,
                                          do_initial_callback=0)
        self.noesyPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW)

        f0row += 1
        label01 = Label(frame0, text='15N HSQC spectrum')
        label01.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.hsqcPulldown = PulldownMenu(frame0,
                                         entries=self.getHsqcs(),
                                         callback=self.setHsqc,
                                         selected_index=0,
                                         do_initial_callback=0)
        self.hsqcPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW)

        f0row += 1
        label02 = Label(frame0, text='15N HSQC TOCSY spectrum')
        label02.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.tocsyPulldown = PulldownMenu(frame0,
                                          entries=self.getTocsys(),
                                          callback=self.setTocsy,
                                          selected_index=0,
                                          do_initial_callback=0)
        self.tocsyPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW)

        f0row += 1
        label02 = Label(frame0, text='15N HSQC NOESY spectrum')
        label02.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.noesy3dPulldown = PulldownMenu(frame0,
                                            entries=self.getNoesy3ds(),
                                            callback=self.setNoesy3d,
                                            selected_index=0,
                                            do_initial_callback=0)
        self.noesy3dPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW)

        f0row += 1
        texts = ['Setup resonances & peaks', 'Show Peaks', 'Show resonances']
        commands = [self.setupResonances, self.showPeaks, self.showResonances]
        self.setupButtons = ButtonList(frame0,
                                       expands=1,
                                       texts=texts,
                                       commands=commands)
        self.setupButtons.grid(row=f0row,
                               column=0,
                               columnspan=2,
                               sticky=Tkinter.NSEW)

        f0row += 1
        self.label03a = Label(frame0, text='Resonances found: 0')
        self.label03a.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.label03b = Label(frame0, text='NOESY peaks found: 0')
        self.label03b.grid(row=f0row, column=1, sticky=Tkinter.NW)

        row += 1
        frame1 = LabelFrame(guiFrame, text='Calculate distance constraints')
        frame1.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame1.grid_columnconfigure(3, weight=1)

        f1row = 0
        frame1.grid_rowconfigure(f1row, weight=1)
        data = [
            self.specFreq, self.maxIter, self.mixTime, self.corrTime,
            self.leakRate, self.maxIntens
        ]
        colHeadings = [
            'Spectrometer\nfrequency', 'Max\niterations', 'Mixing\ntime (ms)',
            'Correl.\ntime (ns)', 'Leak\nrate', 'Max\nintensity'
        ]
        editWidgets = [
            self.specFreqEntry,
            self.maxIterEntry,
            self.mixTimeEntry,
            self.corrTimeEntry,
            self.leakRateEntry,
            self.maxIntensEntry,
        ]
        editGetCallbacks = [
            self.getSpecFreq,
            self.getMaxIter,
            self.getMixTime,
            self.getCorrTime,
            self.getLeakRate,
            self.getMaxIntens,
        ]
        editSetCallbacks = [
            self.setSpecFreq,
            self.setMaxIter,
            self.setMixTime,
            self.setCorrTime,
            self.setLeakRate,
            self.setMaxIntens,
        ]
        self.midgeParamsMatrix = ScrolledMatrix(
            frame1,
            editSetCallbacks=editSetCallbacks,
            editGetCallbacks=editGetCallbacks,
            editWidgets=editWidgets,
            maxRows=1,
            initialCols=5,
            headingList=colHeadings,
            callback=None,
            objectList=[
                'None',
            ],
            textMatrix=[
                data,
            ])
        self.midgeParamsMatrix.grid(row=f1row,
                                    column=0,
                                    columnspan=4,
                                    sticky=Tkinter.NSEW)

        f1row += 1
        label10 = Label(frame1, text='Benchmark structure')
        label10.grid(row=f1row, column=0, sticky=Tkinter.NW)
        self.structurePulldown = PulldownMenu(frame1,
                                              entries=self.getStructures(),
                                              callback=self.setStructure,
                                              selected_index=0,
                                              do_initial_callback=0)
        self.structurePulldown.grid(row=f1row, column=1, sticky=Tkinter.NW)

        label11 = Label(frame1, text='ADC atom types:')
        label11.grid(row=f1row, column=2, sticky=Tkinter.NW)
        self.adcAtomsPulldown = PulldownMenu(frame1,
                                             entries=self.getAdcAtomTypes(),
                                             callback=self.setAdcAtomTypes,
                                             selected_index=0,
                                             do_initial_callback=0)
        self.adcAtomsPulldown.grid(row=f1row, column=3, sticky=Tkinter.NW)

        f1row += 1
        texts = [
            'Calculate distances', 'Show distance\nconstraints',
            'Show anti-distance\nconstraints'
        ]
        commands = [
            self.calculateDistances, self.showConstraints,
            self.showAntiConstraints
        ]
        self.midgeButtons = ButtonList(frame1,
                                       expands=1,
                                       texts=texts,
                                       commands=commands)
        self.midgeButtons.grid(row=f1row,
                               column=0,
                               columnspan=4,
                               sticky=Tkinter.NSEW)

        f1row += 1
        self.distConstrLabel = Label(frame1, text='Distance constraints:')
        self.distConstrLabel.grid(row=f1row,
                                  column=0,
                                  columnspan=2,
                                  sticky=Tkinter.NW)
        self.antiConstrLabel = Label(frame1, text='Anti-distance constraints:')
        self.antiConstrLabel.grid(row=f1row,
                                  column=2,
                                  columnspan=2,
                                  sticky=Tkinter.NW)

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)
        frame2 = LabelFrame(guiFrame, text='Proton cloud molecular dynamics')
        frame2.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame2.grid_columnconfigure(1, weight=1)

        f2row = 0
        frame2.grid_rowconfigure(f2row, weight=1)
        data = [
            self.specFreq, self.maxIter, self.mixTime, self.corrTime,
            self.leakRate
        ]
        colHeadings = [
            'Step', 'Initial temp.', 'Final temp.', 'Cooling steps',
            'MD steps', 'MD tau', 'Rep. scale'
        ]
        editWidgets = [
            None, self.mdInitTempEntry, self.mdFinTempEntry,
            self.mdCoolStepsEntry, self.mdSimStepsEntry, self.mdTauEntry,
            self.mdRepScaleEntry
        ]
        editGetCallbacks = [
            None, self.getMdInitTemp, self.getMdFinTemp, self.getMdCoolSteps,
            self.getMdSimSteps, self.getMdTau, self.getMdRepScale
        ]
        editSetCallbacks = [
            None, self.setMdInitTemp, self.setMdFinTemp, self.setMdCoolSteps,
            self.setMdSimSteps, self.setMdTau, self.setMdRepScale
        ]
        self.coolingSchemeMatrix = ScrolledMatrix(
            frame2,
            editSetCallbacks=editSetCallbacks,
            editGetCallbacks=editGetCallbacks,
            editWidgets=editWidgets,
            maxRows=9,
            initialRows=12,
            headingList=colHeadings,
            callback=self.selectCoolingStep,
            objectList=self.coolingScheme,
            textMatrix=self.coolingScheme)
        self.coolingSchemeMatrix.grid(row=f2row,
                                      column=0,
                                      columnspan=4,
                                      sticky=Tkinter.NSEW)

        f2row += 1
        texts = ['Move earlier', 'Move later', 'Add step', 'Remove step']
        commands = [
            self.moveStepEarlier, self.moveStepLater, self.addCoolingStep,
            self.removeCoolingStep
        ]
        self.coolingSchemeButtons = ButtonList(frame2,
                                               expands=1,
                                               commands=commands,
                                               texts=texts)
        self.coolingSchemeButtons.grid(row=f2row,
                                       column=0,
                                       columnspan=4,
                                       sticky=Tkinter.EW)

        f2row += 1
        label20 = Label(frame2, text='Number of clouds:')
        label20.grid(row=f2row, column=0, sticky=Tkinter.NW)
        self.numCloudsEntry = FloatEntry(frame2,
                                         text=100,
                                         returnCallback=self.setNumClouds,
                                         width=10)
        self.numCloudsEntry.grid(row=f2row, column=1, sticky=Tkinter.NW)
        label21 = Label(frame2, text='Cloud file prefix:')
        label21.grid(row=f2row, column=2, sticky=Tkinter.NW)
        self.filePrefixEntry = Entry(frame2,
                                     text='cloud_',
                                     returnCallback=self.setFilePrefix,
                                     width=10)
        self.filePrefixEntry.grid(row=f2row, column=3, sticky=Tkinter.NW)

        f2row += 1
        texts = ['Start molecular dynamics', 'Show dynamics progress']
        commands = [self.startMd, self.showMdProgress]
        self.mdButtons = ButtonList(frame2,
                                    expands=1,
                                    commands=commands,
                                    texts=texts)
        self.mdButtons.grid(row=f2row,
                            column=0,
                            columnspan=4,
                            sticky=Tkinter.NSEW)

        row += 1
        self.bottomButtons = createDismissHelpButtonList(guiFrame,
                                                         expands=0,
                                                         help_url=None)
        self.bottomButtons.grid(row=row, column=0, sticky=Tkinter.EW)

        self.setButtonStates()
예제 #17
0
class CloudsPopup(BasePopup):
    def __init__(self, parent, *args, **kw):

        self.guiParent = parent
        self.project = parent.getProject()
        self.waiting = 0
        self.specFreq = 800.13
        self.maxIter = 50
        self.mixTime = 60
        self.corrTime = 11.5
        self.leakRate = 2.0
        self.peakListDict = {}
        self.noesyPeakList = None
        self.tocsyPeakList = None
        self.noesy3dPeakList = None
        self.hsqcPeakList = None
        self.maxIntens = 37000000

        self.resonances = None
        self.origResonances = None
        self.noesyPeaks = None
        self.distanceConstraintList = None
        self.antiDistConstraintList = None
        self.numClouds = 100
        self.filePrefix = 'cloud_'
        self.cloudsFiles = []
        self.adcAtomTypes = 'HN'
        self.structure = None

        # step num, initial temp, final temp, cooling steps, MD steps, MD tau, rep scale
        self.coolingScheme = []
        self.coolingScheme.append([1, 1, 1, 3, 500, 0.001, 0])
        self.coolingScheme.append([2, 80000, 4000, 19, 1000, 0.001, 0])
        self.coolingScheme.append([3, 4000, 1, 5, 500, 0.001, 0])
        self.coolingScheme.append([4, 15000, 1, 3, 1000, 0.001, 0])
        self.coolingScheme.append([5, 1, 1, 5, 500, 0.001, 0])
        self.coolingScheme.append([6, 8000, 1, 3, 1000, 0.001, 0])
        self.coolingScheme.append([7, 1, 1, 5, 500, 0.001, 0])
        self.coolingScheme.append([8, 3000, 25, 60, 2500, 0.001, 1])
        self.coolingScheme.append([9, 25, 25, 1, 7500, 0.001, 1])
        self.coolingScheme.append([10, 10, 10, 1, 7500, 0.001, 1])
        self.coolingScheme.append([11, 0.01, 0.01, 1, 7500, 0.0005, 1])

        self.coolingStep = None

        BasePopup.__init__(self,
                           parent,
                           title="Resonance Clouds Analysis",
                           **kw)

    def body(self, guiFrame):

        self.specFreqEntry = IntEntry(self,
                                      text=self.specFreq,
                                      width=8,
                                      returnCallback=self.setSpecFreq)
        self.maxIterEntry = IntEntry(self,
                                     text=self.maxIter,
                                     width=8,
                                     returnCallback=self.setMaxIter)
        self.mixTimeEntry = FloatEntry(self,
                                       text=self.mixTime,
                                       width=8,
                                       returnCallback=self.setMixTime)
        self.corrTimeEntry = FloatEntry(self,
                                        text=self.corrTime,
                                        width=8,
                                        returnCallback=self.setCorrTime)
        self.leakRateEntry = FloatEntry(self,
                                        text=self.leakRate,
                                        width=8,
                                        returnCallback=self.setLeakRate)
        self.maxIntensEntry = IntEntry(self,
                                       text=self.maxIntens,
                                       width=8,
                                       returnCallback=self.setMaxIntens)

        self.mdInitTempEntry = FloatEntry(self,
                                          text='',
                                          returnCallback=self.setMdInitTemp)
        self.mdFinTempEntry = FloatEntry(self,
                                         text='',
                                         returnCallback=self.setMdFinTemp)
        self.mdCoolStepsEntry = IntEntry(self,
                                         text='',
                                         returnCallback=self.setMdCoolSteps)
        self.mdSimStepsEntry = IntEntry(self,
                                        text='',
                                        returnCallback=self.setMdSimSteps)
        self.mdTauEntry = FloatEntry(self,
                                     text='',
                                     returnCallback=self.setMdTau)
        self.mdRepScaleEntry = FloatEntry(self,
                                          text='',
                                          returnCallback=self.setMdRepScale)

        guiFrame.grid_columnconfigure(0, weight=1)

        row = 0
        frame0 = LabelFrame(guiFrame, text='Setup peak lists')
        frame0.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame0.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame0.grid_columnconfigure(1, weight=1)

        f0row = 0
        label00 = Label(frame0, text='1H-1H NOESY spectrum')
        label00.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.noesyPulldown = PulldownMenu(frame0,
                                          entries=self.getNoesys(),
                                          callback=self.setNoesy,
                                          selected_index=0,
                                          do_initial_callback=0)
        self.noesyPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW)

        f0row += 1
        label01 = Label(frame0, text='15N HSQC spectrum')
        label01.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.hsqcPulldown = PulldownMenu(frame0,
                                         entries=self.getHsqcs(),
                                         callback=self.setHsqc,
                                         selected_index=0,
                                         do_initial_callback=0)
        self.hsqcPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW)

        f0row += 1
        label02 = Label(frame0, text='15N HSQC TOCSY spectrum')
        label02.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.tocsyPulldown = PulldownMenu(frame0,
                                          entries=self.getTocsys(),
                                          callback=self.setTocsy,
                                          selected_index=0,
                                          do_initial_callback=0)
        self.tocsyPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW)

        f0row += 1
        label02 = Label(frame0, text='15N HSQC NOESY spectrum')
        label02.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.noesy3dPulldown = PulldownMenu(frame0,
                                            entries=self.getNoesy3ds(),
                                            callback=self.setNoesy3d,
                                            selected_index=0,
                                            do_initial_callback=0)
        self.noesy3dPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW)

        f0row += 1
        texts = ['Setup resonances & peaks', 'Show Peaks', 'Show resonances']
        commands = [self.setupResonances, self.showPeaks, self.showResonances]
        self.setupButtons = ButtonList(frame0,
                                       expands=1,
                                       texts=texts,
                                       commands=commands)
        self.setupButtons.grid(row=f0row,
                               column=0,
                               columnspan=2,
                               sticky=Tkinter.NSEW)

        f0row += 1
        self.label03a = Label(frame0, text='Resonances found: 0')
        self.label03a.grid(row=f0row, column=0, sticky=Tkinter.NW)
        self.label03b = Label(frame0, text='NOESY peaks found: 0')
        self.label03b.grid(row=f0row, column=1, sticky=Tkinter.NW)

        row += 1
        frame1 = LabelFrame(guiFrame, text='Calculate distance constraints')
        frame1.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame1.grid_columnconfigure(3, weight=1)

        f1row = 0
        frame1.grid_rowconfigure(f1row, weight=1)
        data = [
            self.specFreq, self.maxIter, self.mixTime, self.corrTime,
            self.leakRate, self.maxIntens
        ]
        colHeadings = [
            'Spectrometer\nfrequency', 'Max\niterations', 'Mixing\ntime (ms)',
            'Correl.\ntime (ns)', 'Leak\nrate', 'Max\nintensity'
        ]
        editWidgets = [
            self.specFreqEntry,
            self.maxIterEntry,
            self.mixTimeEntry,
            self.corrTimeEntry,
            self.leakRateEntry,
            self.maxIntensEntry,
        ]
        editGetCallbacks = [
            self.getSpecFreq,
            self.getMaxIter,
            self.getMixTime,
            self.getCorrTime,
            self.getLeakRate,
            self.getMaxIntens,
        ]
        editSetCallbacks = [
            self.setSpecFreq,
            self.setMaxIter,
            self.setMixTime,
            self.setCorrTime,
            self.setLeakRate,
            self.setMaxIntens,
        ]
        self.midgeParamsMatrix = ScrolledMatrix(
            frame1,
            editSetCallbacks=editSetCallbacks,
            editGetCallbacks=editGetCallbacks,
            editWidgets=editWidgets,
            maxRows=1,
            initialCols=5,
            headingList=colHeadings,
            callback=None,
            objectList=[
                'None',
            ],
            textMatrix=[
                data,
            ])
        self.midgeParamsMatrix.grid(row=f1row,
                                    column=0,
                                    columnspan=4,
                                    sticky=Tkinter.NSEW)

        f1row += 1
        label10 = Label(frame1, text='Benchmark structure')
        label10.grid(row=f1row, column=0, sticky=Tkinter.NW)
        self.structurePulldown = PulldownMenu(frame1,
                                              entries=self.getStructures(),
                                              callback=self.setStructure,
                                              selected_index=0,
                                              do_initial_callback=0)
        self.structurePulldown.grid(row=f1row, column=1, sticky=Tkinter.NW)

        label11 = Label(frame1, text='ADC atom types:')
        label11.grid(row=f1row, column=2, sticky=Tkinter.NW)
        self.adcAtomsPulldown = PulldownMenu(frame1,
                                             entries=self.getAdcAtomTypes(),
                                             callback=self.setAdcAtomTypes,
                                             selected_index=0,
                                             do_initial_callback=0)
        self.adcAtomsPulldown.grid(row=f1row, column=3, sticky=Tkinter.NW)

        f1row += 1
        texts = [
            'Calculate distances', 'Show distance\nconstraints',
            'Show anti-distance\nconstraints'
        ]
        commands = [
            self.calculateDistances, self.showConstraints,
            self.showAntiConstraints
        ]
        self.midgeButtons = ButtonList(frame1,
                                       expands=1,
                                       texts=texts,
                                       commands=commands)
        self.midgeButtons.grid(row=f1row,
                               column=0,
                               columnspan=4,
                               sticky=Tkinter.NSEW)

        f1row += 1
        self.distConstrLabel = Label(frame1, text='Distance constraints:')
        self.distConstrLabel.grid(row=f1row,
                                  column=0,
                                  columnspan=2,
                                  sticky=Tkinter.NW)
        self.antiConstrLabel = Label(frame1, text='Anti-distance constraints:')
        self.antiConstrLabel.grid(row=f1row,
                                  column=2,
                                  columnspan=2,
                                  sticky=Tkinter.NW)

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)
        frame2 = LabelFrame(guiFrame, text='Proton cloud molecular dynamics')
        frame2.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame2.grid_columnconfigure(1, weight=1)

        f2row = 0
        frame2.grid_rowconfigure(f2row, weight=1)
        data = [
            self.specFreq, self.maxIter, self.mixTime, self.corrTime,
            self.leakRate
        ]
        colHeadings = [
            'Step', 'Initial temp.', 'Final temp.', 'Cooling steps',
            'MD steps', 'MD tau', 'Rep. scale'
        ]
        editWidgets = [
            None, self.mdInitTempEntry, self.mdFinTempEntry,
            self.mdCoolStepsEntry, self.mdSimStepsEntry, self.mdTauEntry,
            self.mdRepScaleEntry
        ]
        editGetCallbacks = [
            None, self.getMdInitTemp, self.getMdFinTemp, self.getMdCoolSteps,
            self.getMdSimSteps, self.getMdTau, self.getMdRepScale
        ]
        editSetCallbacks = [
            None, self.setMdInitTemp, self.setMdFinTemp, self.setMdCoolSteps,
            self.setMdSimSteps, self.setMdTau, self.setMdRepScale
        ]
        self.coolingSchemeMatrix = ScrolledMatrix(
            frame2,
            editSetCallbacks=editSetCallbacks,
            editGetCallbacks=editGetCallbacks,
            editWidgets=editWidgets,
            maxRows=9,
            initialRows=12,
            headingList=colHeadings,
            callback=self.selectCoolingStep,
            objectList=self.coolingScheme,
            textMatrix=self.coolingScheme)
        self.coolingSchemeMatrix.grid(row=f2row,
                                      column=0,
                                      columnspan=4,
                                      sticky=Tkinter.NSEW)

        f2row += 1
        texts = ['Move earlier', 'Move later', 'Add step', 'Remove step']
        commands = [
            self.moveStepEarlier, self.moveStepLater, self.addCoolingStep,
            self.removeCoolingStep
        ]
        self.coolingSchemeButtons = ButtonList(frame2,
                                               expands=1,
                                               commands=commands,
                                               texts=texts)
        self.coolingSchemeButtons.grid(row=f2row,
                                       column=0,
                                       columnspan=4,
                                       sticky=Tkinter.EW)

        f2row += 1
        label20 = Label(frame2, text='Number of clouds:')
        label20.grid(row=f2row, column=0, sticky=Tkinter.NW)
        self.numCloudsEntry = FloatEntry(frame2,
                                         text=100,
                                         returnCallback=self.setNumClouds,
                                         width=10)
        self.numCloudsEntry.grid(row=f2row, column=1, sticky=Tkinter.NW)
        label21 = Label(frame2, text='Cloud file prefix:')
        label21.grid(row=f2row, column=2, sticky=Tkinter.NW)
        self.filePrefixEntry = Entry(frame2,
                                     text='cloud_',
                                     returnCallback=self.setFilePrefix,
                                     width=10)
        self.filePrefixEntry.grid(row=f2row, column=3, sticky=Tkinter.NW)

        f2row += 1
        texts = ['Start molecular dynamics', 'Show dynamics progress']
        commands = [self.startMd, self.showMdProgress]
        self.mdButtons = ButtonList(frame2,
                                    expands=1,
                                    commands=commands,
                                    texts=texts)
        self.mdButtons.grid(row=f2row,
                            column=0,
                            columnspan=4,
                            sticky=Tkinter.NSEW)

        row += 1
        self.bottomButtons = createDismissHelpButtonList(guiFrame,
                                                         expands=0,
                                                         help_url=None)
        self.bottomButtons.grid(row=row, column=0, sticky=Tkinter.EW)

        self.setButtonStates()

    def getStructures(self):

        names = [
            '<None>',
        ]
        for molSystem in self.project.sortedMolSystems():
            for structure in molSystem.sortedStructureEnsembles():
                names.append('%s:%d' % (molSystem.name, structure.ensembleId))

        return names

    def setStructure(self, index, name=None):

        if index < 1:
            self.structure = None
        else:
            structures = []
            for molSystem in self.project.molSystems:
                for structure in molSystem.structureEnsembles:
                    structures.append(structure)

            self.structure = structures[index - 1]

    def getAdcAtomTypes(self):

        return ['HN', 'HN HA', 'HN HA HB']

    def setAdcAtomTypes(self, index, name=None):

        if name is None:
            name = self.adcAtomsPulldown.getSelected()

        self.adcAtomTypes = name

    def startMd(self):

        self.setNumClouds()
        self.setFilePrefix()
        if (self.distanceConstraintList and self.antiDistConstraintList
                and (self.numClouds > 0) and self.filePrefix):

            resDict = {}
            for resonance in self.guiParent.project.currentNmrProject.resonances:
                resDict[resonance.serial] = resonance

            resonances = []
            for constraint in self.distanceConstraintList.constraints:
                for item in constraint.items:
                    for fixedResonance in item.resonances:
                        if resDict.get(
                                fixedResonance.resonanceSerial) is not None:
                            resonances.append(
                                resDict[fixedResonance.resonanceSerial])
                            resDict[fixedResonance.resonanceSerial] = None

            startMdProcess(self.numClouds, self.distanceConstraintList,
                           resonances, self.coolingScheme, self.filePrefix)

            #structGen = self.distanceConstraintList.structureGeneration

            serials = []
            for resonance in resonances:
                serials.append(resonance.serial)
            clouds = []
            for i in range(self.numClouds):
                clouds.append('%s%3.3d.pdb' % (self.filePrefix, i))
            self.guiParent.application.setValues(
                self.distanceConstraintList.nmrConstraintStore,
                'clouds',
                values=clouds)
            self.guiParent.application.setValues(
                self.distanceConstraintList.nmrConstraintStore,
                'cloudsResonances',
                values=serials)

            # do better than this check for creation

    def showMdProgress(self):

        n = 0
        m = self.numClouds
        for i in range(m):
            pdbFileName = '%s%3.3d.pdb' % (self.filePrefix, i)
            if os.path.exists(pdbFileName):
                n += 1

        p = n * 100 / float(m)
        text = 'Done %d of %d clouds (%1.2f)%%' % (n, m, p)
        showInfo('MD Progress', text)

    def setFilePrefix(self, text=None):

        if not text:
            text = self.filePrefixEntry.get()

        if text:
            self.filePrefix = text

    def setNumClouds(self, n=None, *event):

        if not n:
            n = self.numCloudsEntry.get()

        if n:
            self.numClouds = int(n)

    def calculateDistances(self):

        # setup normalisation factor intensityMax

        # self.maxIter
        # what if failure ?

        resDict = {}
        for resonance in self.project.currentNmrProject.resonances:
            resDict[resonance.serial] = resonance

        self.resonances = self.origResonances
        intensityFactors = [1.0 for x in range(len(self.resonances))]

        # optimiseRelaxation will remove unconstrained resonances
        self.distanceConstraintList = optimiseRelaxation(
            self.resonances,
            self.noesyPeaks,
            intensityMax=self.maxIntens,
            intensityFactors=intensityFactors,
            tmix=self.mixTime,
            sf=self.specFreq,
            tcor=self.corrTime,
            rleak=self.leakRate)

        constrainSpinSystems(self.distanceConstraintList)
        # for testing calculate distances from structure overrides any resonances: uses assigned ones
        #(self.distanceConstraintList, self.resonances) = self.cheatForTesting()
        #self.antiDistConstraintList = self.distanceConstraintList
        protonNumbs = {'CH3': 3, 'Haro': 2, 'HN': 1, 'H': 1}

        PI = 3.1415926535897931
        GH = 2.6752e4
        HB = 1.05459e-27
        CONST = GH * GH * GH * GH * HB * HB
        tc = 1.0e-9 * self.corrTime
        wh = 2.0 * PI * self.specFreq * 1.0e6
        j0 = CONST * tc
        j1 = CONST * tc / (1.0 + wh * wh * tc * tc)
        j2 = CONST * tc / (1.0 + 4.0 * wh * wh * tc * tc)
        #jself = 6.0*j2 + 3.0*j1 + j0
        jcross = 6.0 * j2 - j0

        if self.distanceConstraintList:
            constraintStore = self.distanceConstraintList.nmrConstraintStore

            dict = {
                'HN': ['H'],
                'HN HA': ['H', 'HA', 'HA1', 'HA2'],
                'HN HA HB': ['H', 'HA', 'HA1', 'HA2', 'HB', 'HB2', 'HB3']
            }

            self.antiDistConstraintList = makeNoeAdcs(
                self.resonances,
                self.noesyPeakList.dataSource,
                constraintStore,
                allowedAtomTypes=dict[self.adcAtomTypes])

            if self.structure:

                N = len(self.resonances)
                sigmas = [[] for i in range(N)]
                for i in range(N):
                    sigmas[i] = [0.0 for j in range(N)]

                for constraint in self.distanceConstraintList.constraints:
                    resonances = list(constraint, findFirstItem().resonances)

                    ri = resDict[resonances[0].resonanceSerial]
                    rj = resDict[resonances[1].resonanceSerial]
                    i = self.resonances.index(ri)
                    j = self.resonances.index(rj)
                    atomSets1 = list(ri.resonanceSet.atomSets)
                    atomSets2 = list(rj.resonanceSet.atomSets)
                    if atomSets1 == atomSets2:
                        ass = list(atomSets1)
                        atomSets1 = [
                            ass[0],
                        ]
                        atomSets2 = [
                            ass[-1],
                        ]

                    distance = getAtomSetsDistance(atomSets1, atomSets2,
                                                   self.structure)
                    r = distance * 1e-8
                    nhs = protonNumbs[rj.name]
                    sigma = 0.1 * jcross * nhs / (r**6)
                    sigmas[i][j] = sigma

                    constraint.setDetails('Known Dist: %4.3f' % (distance))
                    #for constraint in self.antiDistConstraintList.constraints:
                    #  atomSets1 = list(resonances[0].resonanceSet.atomSets)
                    #  atomSets2 = list(resonances[1].resonanceSet.atomSets)
                    #  distance = getAtomSetsDistance(atomSets1, atomSets2, self.structure)
                    #  constraint.setDetails('Known Dist: %4.3f' % (distance))

                fp = open('sigmas.out', 'w')
                for i in range(N - 1):
                    for j in range(i + 1, N):
                        if sigmas[i][j] != 0.0:
                            fp.write('%3.1d  %3.1d   %9.2e\n' %
                                     (i, j, sigmas[i][j]))
                    #fp.write('\n')
                fp.close()

        self.setButtonStates()

    def cheatForTesting(self, atomSelection='H'):
        """ Makes a perfect cloud from a structure. """

        project = self.project
        structure = self.guiParent.argumentServer.getStructure()

        constraintStore = makeNmrConstraintStore(project)
        distConstraintList = NmrConstraint.DistanceConstraintList(
            constraintStore)

        chain = structure.findFirstCoodChain()
        structureGeneration.hydrogenResonances = []

        molSystem = structure.molSystem
        atomSets = []
        resonances = []
        i = 0
        for resonance in project.currentNmrProject.resonances:

            if resonance.isotopeCode == '1H':

                if resonance.resonanceSet:

                    atomSet = resonance.resonanceSet.findFirstAtomSet()
                    atom = atomSet.findFirstAtom()
                    seqId = atom.residue.seqId
                    if (seqId < 9) or (seqId > 78):
                        continue

                    if atom.residue.chain.molSystem is molSystem:

                        if atomSelection == 'methyl':
                            if len(atomSet.atoms) == 3:
                                if atom.residue.ccpCode not in ('Ala', 'Val',
                                                                'Ile', 'Leu',
                                                                'Thr', 'Met'):
                                    continue
                            elif atom.name != 'H':
                                continue

                        elif atomSelection == 'amide':
                            if atom.name != 'H':
                                continue

                        if atom.name == 'H':
                            resonance.name = 'HN'
                        else:
                            resonance.name = 'H'

                        resonances.append(resonance)
                        atomSets.append(list(resonance.resonanceSet.atomSets))
                        i += 1

        print "Found %d atomSets" % (len(atomSets))
        weight = 1
        adcWeight = 1
        constrDict = {}
        N = len(atomSets)
        for i in range(N - 1):
            atomSets0 = atomSets[i]
            residue0 = atomSets0[0].findFirstAtom().residue.seqId
            print "R", residue0

            for j in range(i + 1, N):
                if j == i:
                    continue
                atomSets1 = atomSets[j]

                dist = getAtomSetsDistance(atomSets0, atomSets1, structure)
                if not dist:
                    continue

                if dist < 5.5:
                    fixedResonance0 = getFixedResonance(
                        constraintStore, resonances[i])
                    fixedResonance1 = getFixedResonance(
                        constraintStore, resonances[j])
                    constrDict[i] = 1
                    constrDict[j] = 1
                    constraint = NmrConstraint.DistanceConstraint(
                        distConstraintList,
                        weight=weight,
                        targetValue=dist,
                        upperLimit=dist + (dist / 10),
                        lowerLimit=dist - (dist / 10),
                        error=dist / 5)
                    item = NmrConstraint.DistanceConstraintItem(
                        constraint,
                        resonances=[fixedResonance0, fixedResonance1])

                elif (atomSets1[0].findFirstAtom().name
                      == 'H') and (atomSets0[0].findFirstAtom().name
                                   == 'H') and (dist > 7):
                    #else:
                    fixedResonance0 = getFixedResonance(
                        constraintStore, resonances[i])
                    fixedResonance1 = getFixedResonance(
                        constraintStore, resonances[j])
                    constrDict[i] = 1
                    constrDict[j] = 1
                    constraint = NmrConstraint.DistanceConstraint(
                        distConstraintList,
                        weight=adcWeight,
                        targetValue=75,
                        upperLimit=175,
                        lowerLimit=5.0,
                        error=94.5)
                    item = NmrConstraint.DistanceConstraintItem(
                        constraint,
                        resonances=[fixedResonance0, fixedResonance1])

        return (distConstraintList, resonances)

    def showConstraints(self):

        if self.distanceConstraintList:
            self.guiParent.browseConstraints(
                constraintList=self.distanceConstraintList)

    def showAntiConstraints(self):

        if self.antiDistConstraintList:
            self.guiParent.browseConstraints(
                constraintList=self.antiDistConstraintList)

    def showPeaks(self):

        self.guiParent.viewPeaks(peaks=self.noesyPeaks)

    def showResonances(self):

        pass
        #self.guiParent.viewResonances(resonances=self.resonances)

    def setupResonances(self):

        if self.noesyPeakList and self.noesy3dPeakList and self.tocsyPeakList and self.hsqcPeakList:

            disambiguateNoesyPeaks(self.noesyPeakList, self.noesy3dPeakList,
                                   self.tocsyPeakList, self.hsqcPeakList)

            (self.origResonances, self.noesyPeaks,
             null) = getCloudsResonanceList(self.guiParent.argumentServer,
                                            hsqcPeakList=self.hsqcPeakList,
                                            tocsy3dPeakList=self.tocsyPeakList,
                                            noesy2dPeakList=self.noesyPeakList)
            self.setButtonStates()

    def setButtonStates(self):

        if self.origResonances:
            self.label03a.set('Resonances found: %d' %
                              (len(self.origResonances)))

        if self.noesyPeaks:
            self.label03b.set('NOESY peaks found: %d' % (len(self.noesyPeaks)))

        if self.noesyPeakList and self.tocsyPeakList and self.hsqcPeakList:
            self.setupButtons.buttons[0].enable()
        else:
            self.setupButtons.buttons[0].disable()

        if self.noesyPeaks:
            self.setupButtons.buttons[1].enable()
        else:
            self.setupButtons.buttons[1].disable()

        if self.origResonances:
            self.setupButtons.buttons[2].enable()
        else:
            self.setupButtons.buttons[2].disable()

        if self.noesyPeaks and self.origResonances:
            self.midgeButtons.buttons[0].enable()
        else:
            self.midgeButtons.buttons[0].disable()

        if self.distanceConstraintList:
            self.midgeButtons.buttons[1].enable()
            self.distConstrLabel.set(
                'Distance constraints: %d' %
                len(self.distanceConstraintList.constraints))
        else:
            self.distConstrLabel.set('Distance constraints:')
            self.midgeButtons.buttons[1].disable()

        if self.antiDistConstraintList:
            self.antiConstrLabel.set(
                'Anti-distance constraints: %d' %
                len(self.antiDistConstraintList.constraints))
            self.midgeButtons.buttons[2].enable()
        else:
            self.antiConstrLabel.set('Anti-distance constraints:')
            self.midgeButtons.buttons[2].disable()

        if (self.distanceConstraintList and self.antiDistConstraintList
                and (self.numClouds > 0) and self.filePrefix):
            self.mdButtons.buttons[0].enable()
            self.mdButtons.buttons[1].enable()
        else:
            self.mdButtons.buttons[0].disable()
            self.mdButtons.buttons[1].disable()

    def getNoesys(self):

        names = []
        spectra = getSpectraByType(self.project, '2dNOESY')
        for spectrum in spectra:
            for peakList in spectrum.peakLists:
                name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name,
                                     peakList.serial)
                names.append(name)
                self.peakListDict[name] = peakList
                if not self.noesyPeakList:
                    self.noesyPeakList = peakList

        return names

    def setNoesy(self, index, name=None):

        if not name:
            name = self.noesyPulldown.getSelected()

        self.noesyPeakList = self.peakListDict[name]
        self.setButtonStates()

    def getTocsys(self):

        names = []
        spectra = getSpectraByType(self.project, '3dTOCSY')
        for spectrum in spectra:
            for peakList in spectrum.peakLists:
                name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name,
                                     peakList.serial)
                names.append(name)
                self.peakListDict[name] = peakList
                if not self.tocsyPeakList:
                    self.tocsyPeakList = peakList

        return names

    def getNoesy3ds(self):

        names = []
        spectra = getSpectraByType(self.project, '3dNOESY')
        for spectrum in spectra:
            for peakList in spectrum.peakLists:
                name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name,
                                     peakList.serial)
                names.append(name)
                self.peakListDict[name] = peakList
                if not self.noesy3dPeakList:
                    self.noesy3dPeakList = peakList

        return names

    def setTocsy(self, index, name=None):

        if not name:
            name = self.tocsyPulldown.getSelected()

        self.tocsyPeakList = self.peakListDict[name]
        self.setButtonStates()

    def setNoesy3d(self, index, name=None):

        if not name:
            name = self.noesy3dPulldown.getSelected()

        self.noesy3dPeakList = self.peakListDict[name]
        self.setButtonStates()

    def getHsqcs(self):

        names = []
        spectra = getSpectraByType(self.project, 'HSQC')
        for spectrum in spectra:
            for peakList in spectrum.peakLists:
                name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name,
                                     peakList.serial)
                names.append(name)
                self.peakListDict[name] = peakList
                if not self.hsqcPeakList:
                    self.hsqcPeakList = peakList

        return names

    def setHsqc(self, index, name=None):

        if not name:
            name = self.hsqcPulldown.getSelected()

        self.hsqcPeakList = self.peakListDict[name]
        self.setButtonStates()

    def getMdInitTemp(self, coolingStep):

        self.mdInitTempEntry.set(coolingStep[1])

    def getMdFinTemp(self, coolingStep):

        self.mdFinTempEntry.set(coolingStep[2])

    def getMdCoolSteps(self, coolingStep):

        self.mdCoolStepsEntry.set(coolingStep[3])

    def getMdSimSteps(self, coolingStep):

        self.mdSimStepsEntry.set(coolingStep[4])

    def getMdTau(self, coolingStep):

        self.mdTauEntry.set(coolingStep[5])

    def getMdRepScale(self, coolingStep):

        self.mdRepScaleEntry.set(coolingStep[6])

    def setMdInitTemp(self, event):

        value = self.mdInitTempEntry.get()
        if value is not None:
            self.coolingStep[1] = value

        self.updateCoolingScheme()

    def setMdFinTemp(self, event):

        value = self.mdFinTempEntry.get()
        if value is not None:
            self.coolingStep[2] = value

        self.updateCoolingScheme()

    def setMdCoolSteps(self, event):

        value = self.mdCoolStepsEntry.get()
        if value is not None:
            self.coolingStep[3] = value

        self.updateCoolingScheme()

    def setMdSimSteps(self, event):

        value = self.mdSimStepsEntry.get()
        if value is not None:
            self.coolingStep[4] = value

        self.updateCoolingScheme()

    def setMdTau(self, event):

        value = self.mdTauEntry.get()
        if value is not None:
            self.coolingStep[5] = value

        self.updateCoolingScheme()

    def setMdRepScale(self, event):

        value = self.mdRepScaleEntry.get()
        if value is not None:
            self.coolingStep[6] = value

        self.updateCoolingScheme()

    def selectCoolingStep(self, object, row, col):

        self.coolingStep = object

    def moveStepEarlier(self):

        if self.coolingStep:
            i = self.coolingStep[0] - 1
            if i > 0:
                coolingStep = self.coolingScheme[i - 1]
                coolingStep[0] = i + 1
                self.coolingStep[0] = i
                self.coolingScheme[i - 1] = self.coolingStep
                self.coolingScheme[i] = coolingStep

                self.updateCoolingScheme()
                self.coolingSchemeMatrix.hilightObject(self.coolingStep)

    def moveStepLater(self):

        if self.coolingStep:
            i = self.coolingStep[0] - 1
            if i < len(self.coolingScheme) - 1:
                coolingStep = self.coolingScheme[i + 1]
                coolingStep[0] = i + 1
                self.coolingStep[0] = i + 2
                self.coolingScheme[i + 1] = self.coolingStep
                self.coolingScheme[i] = coolingStep

                self.updateCoolingScheme()
                self.coolingSchemeMatrix.hilightObject(self.coolingStep)

    def addCoolingStep(self):

        i = len(self.coolingScheme) + 1
        datum = [i, 3000, 100, 10, 2500, 0.001, 1]

        self.coolingScheme.append(datum)
        self.updateCoolingScheme()

    def removeCoolingStep(self):

        if self.coolingStep:
            coolingScheme = []
            i = 0
            for coolingStep in self.coolingScheme:
                if coolingStep is not self.coolingStep:
                    i += 1
                    coolingStep[0] = i
                    coolingScheme.append(coolingStep)

            self.coolingScheme = coolingScheme
            self.updateCoolingScheme()

    def updateCoolingScheme(self):

        objectList = self.coolingScheme
        textMatrix = self.coolingScheme
        self.coolingSchemeMatrix.update(objectList=objectList,
                                        textMatrix=textMatrix)

    def updateMidgeParams(self):

        data = [
            self.specFreq, self.maxIter, self.mixTime, self.corrTime,
            self.leakRate, self.maxIntens
        ]

        self.midgeParamsMatrix.update(textMatrix=[
            data,
        ])

    def getSpecFreq(self, obj):

        self.specFreqEntry.set(self.specFreq)

    def getMaxIter(self, obj):

        self.maxIterEntry.set(self.maxIter)

    def getMixTime(self, obj):

        self.mixTimeEntry.set(self.mixTime)

    def getCorrTime(self, obj):

        self.corrTimeEntry.set(self.corrTime)

    def getLeakRate(self, obj):

        self.leakRateEntry.set(self.leakRate)

    def getMaxIntens(self, obj):

        self.maxIntensEntry.set(self.maxIntens)

    def setSpecFreq(self, event):

        value = self.specFreqEntry.get()
        if value is not None:
            self.specFreq = value

        self.updateMidgeParams()

    def setMaxIter(self, event):

        value = self.maxIterEntry.get()
        if value is not None:
            self.maxIter = value

        self.updateMidgeParams()

    def setMixTime(self, event):

        value = self.mixTimeEntry.get()
        if value is not None:
            self.mixTime = value

        self.updateMidgeParams()

    def setCorrTime(self, event):

        value = self.corrTimeEntry.get()
        if value is not None:
            self.corrTime = value

        self.updateMidgeParams()

    def setLeakRate(self, event):

        value = self.leakRateEntry.get()
        if value is not None:
            self.leakRate = value

        self.updateMidgeParams()

    def setMaxIntens(self, event):

        value = self.maxIntensEntry.get()
        if value is not None:
            self.maxIntens = value

        self.updateMidgeParams()

    def destroy(self):

        BasePopup.destroy(self)
예제 #18
0
    def update(self, peak=None, peakList=None):

        # first destroy old labels and entries (saves grid hassles)

        for label in self.dimensionLabels:
            label.destroy()
        for entry in self.dimensionEntries:
            entry.destroy()

        # now setup required data

        if peak:
            title = 'Edit Peak'
            self.buttons.buttons[0].config(text='Update')
        else:
            title = 'Add Peak'
            self.buttons.buttons[0].config(text='Add Peak')

        self.setTitle(title)

        self.peak = peak
        self.peakList = peakList
        if not peakList:
            if peak:
                self.peakList = peak.peakList
            else:
                return

        peakList = self.peakList
        spectrum = peakList.dataSource.name
        self.numDims = peakList.dataSource.numDim
        self.posn = self.numDims * [0]
        self.dataDims = peakList.dataSource.sortedDataDims()

        if self.peak:

            serial = self.peak.serial
            dims = self.peak.sortedPeakDims()
            details = self.peak.details
            if not details:
                details = ''
            if self.peak.annotation:
                annotn = '%0.16s' % self.peak.annotation
            else:
                annotn = ''

            heightIntensity = self.peak.findFirstPeakIntensity(
                intensityType='height')
            volumeIntensity = self.peak.findFirstPeakIntensity(
                intensityType='volume')

            if heightIntensity:
                height = heightIntensity.value
            else:
                height = 0.0

            if volumeIntensity:
                volume = volumeIntensity.value
            else:
                volume = 0.0

            for i in range(self.numDims):
                peakDim = dims[i]
                dataDimRef = peakDim.dataDimRef
                if dataDimRef:
                    self.posn[i] = peakDim.position + (
                        peakDim.numAliasing * dataDimRef.dataDim.numPointsOrig)
                else:
                    self.posn[i] = peakDim.position

        else:

            dict = peakList.__dict__.get('serialDict')
            if dict is None:
                serial = 1
            else:
                serial = dict.get('peaks', 0) + 1

            height = 0.0
            volume = 0.0
            details = ''
            annotn = ''

        self.specLabel.set(
            text='Experiment: %s Spectrum: %s PeakList: %d' %
            (peakList.dataSource.experiment.name, spectrum, peakList.serial))
        self.peakLabel.set(text='Peak: %d' % serial)

        self.dimensionLabels = self.numDims * ['']
        self.dimensionEntries = self.numDims * ['']
        for i in range(self.numDims):
            pos = self.posn[i]
            if self.unit != 'point':
                dataDim = self.dataDims[i]
                if dataDim.className == 'FreqDataDim':
                    pos = unit_converter[('point', self.unit)](
                        pos, getPrimaryDataDimRef(dataDim))
            self.dimensionLabels[i] = Label(self.master_frame,
                                            text='F%d' % (i + 1),
                                            borderwidth=2,
                                            relief='groove')
            tipText = 'The peak position in dimension %d, in the specified units' % (
                i + 1)
            self.dimensionEntries[i] = FloatEntry(self.master_frame,
                                                  borderwidth=1,
                                                  text='%8.4f' % pos,
                                                  tipText=tipText)

        self.heightEntry.set(text='%f' % height)
        self.volumeEntry.set(text='%f' % volume)
        self.detailEntry.set(text=details)

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

        row = row + 1
        self.peakLabel.grid(row=row, column=0, sticky='nsew')
        self.unit_frame.grid(row=row, column=1, columnspan=2, sticky='nsew')

        for i in range(self.numDims):
            row = row + 1
            self.dimensionLabels[i].grid(row=row, column=0, sticky='nsew')
            self.dimensionEntries[i].grid(row=row,
                                          column=1,
                                          columnspan=3,
                                          sticky='e')

        row = row + 1
        self.heightLabel.grid(row=row, column=0, sticky='nsew')
        self.heightEntry.grid(row=row, column=1, columnspan=3, sticky='e')

        row = row + 1
        self.volumeLabel.grid(row=row, column=0, sticky='nsew')
        self.volumeEntry.grid(row=row, column=1, columnspan=3, sticky='e')

        row = row + 1
        self.detailLabel.grid(row=row, column=0, sticky='nsew')
        self.detailEntry.grid(row=row, column=1, columnspan=3, sticky='e')

        row = row + 1
        self.buttons.grid(row=row, column=0, columnspan=4, sticky='nsew')
예제 #19
0
class RegionSelector(Frame):
    def __init__(self,
                 parent,
                 label='',
                 world_region=None,
                 view_region=None,
                 orient=Tkinter.HORIZONTAL,
                 allow_resize=True,
                 width=20,
                 callback=None,
                 borderwidth=1,
                 show_text=True,
                 text_color='#000000',
                 text_decimals=2,
                 units_scroll=0.1,
                 pages_scroll=1.0,
                 menu_entries=None,
                 menu_callback=None,
                 min_thickness=None,
                 *args,
                 **kw):

        self.menu_entries = menu_entries
        self.myCallback = callback

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

        self.text_decimals = text_decimals

        self.label = Label(self, text=label, width=4)

        self.menu = PulldownMenu(self,
                                 callback=menu_callback,
                                 entries=menu_entries)

        self.entry = FloatEntry(self,
                                width=6,
                                returnCallback=self.adjustScrollbar)

        self.region_scrollbar = RegionScrollbar(self,
                                                world_region=world_region,
                                                view_region=view_region,
                                                orient=orient,
                                                allow_resize=allow_resize,
                                                width=width,
                                                callback=self.doCallback,
                                                borderwidth=borderwidth,
                                                show_text=show_text,
                                                text_color=text_color,
                                                text_decimals=text_decimals,
                                                units_scroll=units_scroll,
                                                pages_scroll=pages_scroll,
                                                min_thickness=min_thickness)

        self.gridAll()

    def gridAll(self):

        col = 0
        if (self.menu_entries and len(self.menu_entries) > 1):
            self.menu.grid(row=0, column=col, sticky=Tkinter.EW)
            col = col + 1
        else:
            self.menu.grid_forget()

        self.label.grid(row=0, column=col, sticky=Tkinter.EW)
        col = col + 1
        self.entry.grid(row=0, column=col, sticky=Tkinter.EW)
        self.grid_columnconfigure(col, weight=0)
        col = col + 1
        self.region_scrollbar.grid(row=0, column=col, sticky=Tkinter.NSEW)
        self.grid_columnconfigure(col, weight=1)
        col = col + 1
        self.grid_columnconfigure(col, weight=0)

    def setMinThickness(self, min_thickness):

        self.region_scrollbar.setMinThickness(min_thickness)

    def setMenuEntries(self, menu_entries):

        self.menu_entries = menu_entries
        self.menu.replace(menu_entries)
        self.gridAll()

    def getMenuEntry(self):

        return self.menu.getSelected()

    def adjustScrollbar(self, *event):

        try:
            x = float(self.entry.get())
        except:
            showError('Entry error', 'Need to enter float in scrollbar box')
            self.setEntry()
            return

        (v0, v1) = self.region_scrollbar.view_region
        d = 0.5 * (v1 - v0)

        self.region_scrollbar.setViewRegion(x - d, x + d, do_callback=True)

    def doCallback(self, view_region):

        if (self.myCallback):
            self.myCallback(view_region)

        #print 'doCallback', view_region
        self.setEntry(view_region)

    def setEntry(self, view_region=None):

        if (not view_region):
            view_region = self.region_scrollbar.view_region
        (v0, v1) = view_region
        x = 0.5 * (v0 + v1)
        s = formatDecimals(x, decimals=self.text_decimals)
        self.entry.set(s)

    def __getattr__(self, name):

        # dispatch everything not defined by RegionSelector to scrollbar widget

        try:
            return getattr(self.__dict__['region_scrollbar'], name)
        except:
            raise AttributeError, "RegionSelector instance has no attribute '%s'" % name
예제 #20
0
  def body(self, guiFrame):

    guiFrame.grid_columnconfigure(3, weight=1)
    
    row = 0
    label = Label(guiFrame, text='Molecular system: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.molSysPulldown = PulldownMenu(guiFrame, self.changeMolSystem, selected_index=-1, do_initial_callback=0)
    self.molSysPulldown.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Clouds files: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.filenameEntry = Entry(guiFrame,text='perfect00.pdb')
    self.filenameEntry.grid(row=row, column=3, sticky=Tkinter.NW)


    row += 1
    label = Label(guiFrame, text='Chain: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.chainPulldown = PulldownMenu(guiFrame, self.changeChain, selected_index=-1, do_initial_callback=0)
    self.chainPulldown.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Thread steps: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.numStepsEntry = IntEntry(guiFrame,text=3000)
    self.numStepsEntry.grid(row=row, column=3, sticky=Tkinter.NW)
    row += 1

    label = Label(guiFrame, text='Homologue PDB file: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.pdbEntry = Entry(guiFrame,text='')
    self.pdbEntry.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Dist. Threshold: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.distEntry = FloatEntry(guiFrame,text=3.0)
    self.distEntry.grid(row=row, column=3, sticky=Tkinter.NW)

    row += 1

    label = Label(guiFrame, text='Global score: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.globalScoreLabel = Label(guiFrame, text='')
    self.globalScoreLabel.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Assignment Threshold: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.thresholdEntry = FloatEntry(guiFrame,text=-4.5)
    self.thresholdEntry.grid(row=row, column=3, sticky=Tkinter.NW)

    row += 1
    guiFrame.grid_rowconfigure(row, weight=1)
    self.graph = ScrolledGraph(guiFrame, width=300, height=200)
    self.graph.grid(row=row, column=0, columnspan=4, sticky = Tkinter.NSEW)

    row += 1
    texts    = ['Run','Assign!']
    commands = [self.run, self.assignSpinSystems]
    bottomButtons = createDismissHelpButtonList(guiFrame,texts=texts,commands=commands,expands=0,help_url=None)
    bottomButtons.grid(row=row, column=0, columnspan=4, sticky=Tkinter.EW)
    self.assignButton = bottomButtons.buttons[1]

    for func in ('__init__','delete'):
      Implementation.registerNotify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem', func)
      Implementation.registerNotify(self.updateChains, 'ccp.molecule.MolSystem.Chain', func)
    
    self.updateMolSystems()
    self.updateChains()
예제 #21
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)
예제 #22
0
class PeakSeparatorGui(BasePopup):
    """
  **Separate Merged Peaks Using Peak Models**

  The Peak Separator code uses a Markov Chain Monte Carlo search which, using
  idealised peak shapes, attempts to deconvolve overlapped peak regions into 
  their separate constituent peaks.
  
  This routine is also suitable for accurately fitting model shapes to single
  peaks in order to calculate precise intensities.
  
  **Options Peak Separator Parameters**
  *Min. Number of peaks* is by default set to one, it is not possible to set 
  this to a value less than one.
  *Max. Number of peaks* is by default set to one, increasing this value allows
  the search routine to fit more models. The best fit may be found with fewer than
  the maximum number models. Higher numbers slow the routine, and setting this
  value to 0 allows the routine to (effectively) fit unlimited peaks.
  *Only pick positive peaks*. If you are not interested in negative peaks, removing
  the possibility of fitting negative peaks can reduce search time.
  *Peak Model* fits the spectra with either a Gaussian peak model or a Lorentzian
  peak model.

  **Options Region**
  *Peak List* choose which peak list newly picked peaks should be added to. Peaks
  picked using this method will have their details appended with 'PeakSepartor' 
  so you know where they came from.
  *Region Table* shows which area of the current spectrum is about to be searched.
  *Add Region*. Once an area of spectra has been highlighted clicking this button
  will pass it's details on to the Peak Separator.
  *Reset All* will reset all search parameters.
  *Separate Peaks* will run the Peak Separator code with your current settings. This
  may take a few minutes to run, depending on the size of the spectral region being
  searched, the number of peaks being fitted and the speed of your machine. Please
  wait while this completes.
  
  After a successful Peak Separation run, the found peaks will be added to the 
  selected peak list. These peaks intensties (volume) have been found using the
  peak model selected.

  **Advanced Settings Tab**
  *Rate* affects the speed of the Markov Chain Monte Carlo routine. A smaller value
  results in longer execution, but possibly higher quality results. The default 
  setting is deemed sensible for the majority of runs.
  *Line Width* offers a finer degree of control over maximum and minimum peak widths
  for each dimension. The default values are *very* stupid and could do with 
  re-checking for each experiment.
  *Re-Pick Entire Peak List* if you would like to use the Peak Separator to repick
  *every* peak in your peak list, try this option - but note that this may take
  a very long time!

  """
    def __init__(self, parent, programName='Peak Separator', **kw):

        self.parent = parent
        self.programName = programName
        self.versionInfo = 'Version 0.2'
        self.help_url = 'http://www.ccpn.ac.uk/'

        self.window = None
        self.waiting = False
        self.rootWindow = None

        # just used for display - PeakSeparator will not see this
        self._minSigmaHz = None
        self._maxSigmaHz = None

        self.customSigma = False
        self.rePickPeakList = False

        self._sampleStartPpm = None
        self._sampleEndPpm = None

        try:
            self.project = parent.project
        except:
            pass

        self.params = PeakSeparatorParams()

        BasePopup.__init__(self,
                           parent=parent,
                           title=programName,
                           location='+100+100',
                           **kw)

        if not self.analysisProject:
            print '&&& init: No analysis project found ...'
        try:
            if parent.argumentServer:
                self.argServer = parent.argumentServer
            else:
                print '&&& init: No argument server found...'
        except:
            print '&&& init: Test'

    ###########################################################################

    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)

    def administerNotifiers(self, notifyFunc):

        for func in ('__init__', 'delete'):
            notifyFunc(self.updateAfter, 'ccp.nmr.Nmr.PeakList', func)

        notifyFunc(self.updateAfter, 'ccp.nmr.Nmr.Experiment', 'setName')
        notifyFunc(self.updateAfter, 'ccp.nmr.Nmr.DataSource', 'setName')

    def destroy(self):

        self.administerNotifiers(self.unregisterNotify)
        BasePopup.destroy(self)

    ###########################################################################
    # update parameters from PS Region

    def updateFromRegion(self):

        if not self.params.peakList:
            print '&&& update from region: Need a peak list'
            return

        if (self.argServer.parent.currentRegion) == None:
            showError('No Region',
                      'Please select a peak region to be separated')
            return

        self.rePickPeakList = False

        getRegionParams(self.params, argServer=self.argServer)

        if not self.customSigma: self.initSigmaParams()

        self.setWidgetEntries()

    ###########################################################################
    # update parameters from PS PeakList

    def updateFromPeakList(self):

        if not self.params.peakList:
            print '&&& update from peakList: Need a peak list'
            return

        getPeakListParams(self.params)

        if not self.customSigma: self.initSigmaParams()

        self.setWidgetEntries()

    ###########################################################################
    # Run the C library!

    def runPeakSeparator(self):
        """ run the peak separator """

        # hack for Macs - focus isn't always lost on mouse move
        # so bind event not always called. Shouldn't affect other OS.
        self.applyChange()

        if not self.params.peakList:
            print '&&& Peak list not yet set'
        else:
            # SeparatePeakRoutine(self.params, self.params.peakList, routine='pymc' )
            SeparatePeakRoutine(self.params,
                                self.params.peakList,
                                routine='bayesys')

    def runRepickPeaks(self):
        """ Run the Peak Separator on entire chosen peak list """
        # hack for Macs - focus isn't always lost on mouse move
        # so bind event not always called. Shouldn't affect other OS.
        self.applyChange()

        if not self.params.peakList:
            print '&&& Peak list not yet set'
        else:
            SeparatePeaksInPeakList(self.params)

    ###########################################################################

    def setWidgetEntries(self):

        ### Page One widgets
        self.minPeaksEntry.set(self.params.minAtoms)
        self.maxPeaksEntry.set(self.params.maxAtoms)

        if self.params.positivePeaks == 1:
            self.posPeaksButtons.set('True')  # only pick pos peaks
        else:
            self.posPeaksButtons.set('False')

        # do something fancy if different shapes for each dim!
        n = self.params.peakShape - 3  # shape is only 3, 4, (5)
        self.shapeButtons.setIndex(n)

        if self.project is not None:
            self.updatePeakListList()
        self.updateSpectrumWindow()

        if self.params.sampleStart and self.params.peakList:

            if not self.rePickPeakList:
                objectList = []
                textMatrix = []

                if len(self.params.samplePpmStart) != self.params.Ndim: return

                for i in range(self.params.Ndim):
                    dim_entry = []
                    dim_entry.append('%2d' % (i + 1))
                    dim_entry.append('%7.3f' % self.params.samplePpmStart[i])
                    dim_entry.append('%7.3f' % self.params.samplePpmEnd[i])
                    dim_entry.append('%3d' % self.params.sampleSize[i])
                    textMatrix.append(dim_entry)

                self.regionTable.update(textMatrix=textMatrix,
                                        objectList=objectList)

        ### Page Two widgets
        self.rateEntry.set(self.params.rate)

        if self.params.peakList and self.params.Ndim:

            textMatrix = []
            objectList = []

            for i in range(self.params.Ndim):
                if self.params.isFreqDim[i]:
                    dim_entry = []
                    objectList.append(i)
                    dim_entry.append('%2d' % (i + 1))
                    dim_entry.append('%7.3f' % self._minSigmaHz[i])
                    dim_entry.append('%7.3f' % self._maxSigmaHz[i])
                    textMatrix.append(dim_entry)

            self.lineWidthTable.update(textMatrix=textMatrix,
                                       objectList=objectList)

    def applyChange(self, *event):
        """ Upon change, add settings to params """

        # Page One apply changes
        self.params.minAtoms = self.minPeaksEntry.get()
        self.params.maxAtoms = self.maxPeaksEntry.get()

        if self.posPeaksButtons.get() == 'True':  # asked only pick pos peaks
            self.params.positivePeaks = 1
        else:
            self.params.positivePeaks = 0

        # do something fancy if different shapes for each dim!
        n = self.shapeButtons.getIndex()  # shape is only 3, 4, (5)
        self.params.peakShape = n + 3

        # Page Two apply changes
        self.params.rate = float(self.rateEntry.get())

        self.updateSigmaParams()

    ###########################################################################
    # Peak list functions provide PeakSeparator some inherited params

    def getPeakListList(self):
        """ given a spectrum, get list of peak lists """
        project = self.project

        peakLists = []
        for experiment in self.nmrProject.experiments:
            for spectrum in experiment.dataSources:
                for peakList in spectrum.peakLists:
                    peakLists.append([
                        '%s:%s:%d' %
                        (experiment.name, spectrum.name, peakList.serial),
                        peakList
                    ])
        peakLists.sort()
        return peakLists

    def updatePeakListList(self):
        """ set the peaklist list in the pulldown menu """
        peakListData = self.getPeakListList()

        index = -1
        names = []
        peakList = self.params.peakList

        if peakListData:
            names = [x[0] for x in peakListData]
            peakLists = [x[1] for x in peakListData]

            if peakList not in peakLists:
                peakList = peakLists[0]

            index = peakLists.index(peakList)

        else:
            peakList = None
            peakLists = []

        if peakList is not self.params.peakList:
            self.params.peakList = peakList

        self.peakListPulldown.setup(names, peakLists, index)
        self.repickListPulldown.setup(names, peakLists, index)

    def setRePickPeakList(self, peakList):
        """ Set the peak list to be repicked (and hit a Flag) """
        self.rePickPeakList = True
        self.setPeakList(peakList)

    def setManuallyPickPeakList(self, peakList):
        """ Set the peak list to add new peaks to (and hit a Flag) """
        self.rePickPeakList = False
        self.setPeakList(peakList)

    def setPeakList(self, peakList):
        """ Sets the Peak List """
        if peakList is not self.params.peakList:
            self.params.peakList = peakList
            # # interrogate the peak list and get all the usefull parameters out
            self.updateFromPeakList()
            self.updateSpectrumWindow()
            self.setWidgetEntries()

    ###########################################################################
    # TBD I suspect this is for matching region with peak list, but may be obsolete now

    def getSpectrumWindowList(self):
        """ get list of windows which spectrum could be in """
        windows = {}
        if self.params.peakList:
            views = getSpectrumViews(self.params.peakList.dataSource)
            for view in views:
                windows[view.spectrumWindowPane.spectrumWindow] = None

        return [[w.name, w] for w in windows.keys()]

    def updateSpectrumWindow(self):
        """ update the spectrum window """
        windowData = self.getSpectrumWindowList()

        index = -1
        names = []
        window = self.rootWindow

        if windowData:
            names = [x[0] for x in windowData]
            windows = [x[1] for x in windowData]

            if window not in windows:
                window = windows[0]

            index = windows.index(window)

        else:
            window = None
            windows = []

        if window is not self.rootWindow:
            self.rootWindow = window

    ###########################################################################
    # get and set sigma stuff
    def setSigmaMin(self, dim):

        value = self.editMinSigmaEntry.get()
        self._minSigmaHz[dim] = value

        # dont go and re-write users settings
        self.customSigma = True

        # make sure changes are in params object
        self.updateSigmaParams(dim)
        self.setWidgetEntries()

    def getSigmaMin(self, dim):

        if dim is not None:
            self.editMinSigmaEntry.set(self._minSigmaHz[dim])

    def setSigmaMax(self, dim):

        value = self.editMaxSigmaEntry.get()
        self._maxSigmaHz[dim] = value

        # dont go and re-write users settings
        self.customSigma = True

        # make sure changes are in params object
        self.updateSigmaParams(dim)
        self.setWidgetEntries()

    def getSigmaMax(self, dim):

        if dim is not None:
            self.editMaxSigmaEntry.set(self._maxSigmaHz[dim])

    def updateSigmaParams(self, dim=None):
        """ updateSigmaParams Just updates the parameters (params obj) for sigma values. 
        If dim is None, do this for each dim
    """

        dataDimRefs = self.params.dataDimRefs

        if not dataDimRefs: return

        if not self.params.minSigma or len(
                self.params.minSigma) != self.params.Ndim:
            self.params.minSigma = [0.] * self.params.Ndim

        if not self.params.maxSigma or len(
                self.params.maxSigma) != self.params.Ndim:
            self.params.maxSigma = [0.] * self.params.Ndim

        def updateSigmaParam(dim, dataDimRefs):
            """ Convert and update sigma for dim """

            if self.params.isFreqDim[dim]:
                # note factor of two!
                self.params.minSigma[dim] = self.rHz2pnt(
                    self._minSigmaHz[dim], dataDimRefs[dim]) / 2.
                self.params.maxSigma[dim] = self.rHz2pnt(
                    self._maxSigmaHz[dim], dataDimRefs[dim]) / 2.
            else:
                self.params.minSigma[dim] = 1.0
                self.params.maxSigma[dim] = 1.0

        if dim:
            updateSigmaParam(dim, dataDimRefs)
        else:
            for dim in range(self.params.Ndim):
                updateSigmaParam(dim, dataDimRefs)

    # utility functions for sigma values
    def pnt2rHz(self, point, dataDimRef):
        """ Point to relative Hz frequency relative to frequency at Zeroeth point
        Necessary when (for example) looking for width of peak in Hz
    """
        assert point, dataDimRef

        sigmaBase = pnt2hz(0, dataDimRef)
        sigmaHz = pnt2hz(point, dataDimRef)

        return abs(sigmaHz - sigmaBase)

    def rHz2pnt(self, freq, dataDimRef):
        """ Relative Hz to point frequency relative to frequency at Zeroeth point
        Necessary when (for example) looking for width of peak in Hz
    """
        assert freq, dataDimRef

        sigmaBase = hz2pnt(0, dataDimRef)
        sigmaPoint = hz2pnt(freq, dataDimRef)

        return abs(sigmaPoint - sigmaBase)

    def initSigmaParams(self):
        """ Set some initial default values for sigma """

        self._minSigmaHz = []
        self._maxSigmaHz = []

        if self.params.Ndim:
            for dim in range(self.params.Ndim):
                self._minSigmaHz.append(6.)
                self._maxSigmaHz.append(28.)

    ###########################################################################

    def updateAll(self):

        self.updateSpectrumWindow()
        self.updatePeakListList()

        self.waiting = False

    def updateAfter(self, obj=None):

        if self.waiting:
            return
        else:
            self.waiting = True
            self.after_idle(self.updateAll)
예제 #23
0
class EditPeakFindParamsPopup(BasePopup):
    """
  ** Peak Settings and Non-Interactive Peak Finding **
  
  The purpose of this dialog is to allow the user to select settings for
  finding and integrating peaks, and also to be able to find peaks in an
  arbitrary region that is specified in a table rather than via a spectrum
  window.
  
  ** Find Parameters tab **

  This can be used to specify how peak finding works.

  First of all, you can search for just positive peaks, just negative
  peaks or both, and the default is that it is just positive peaks.
  However, this is further filtered by what the contour levels are.
  If there are no positive contour levels for a given spectrum then
  positive peaks are not found even if this dialog says they can be,
  and similarly if there are no negative contour levels for a given
  spectrum then negative peaks are not found even if this dialog says
  they can be.

  The peak finding algorithm looks for local extrema (maximum for
  positive peaks and minima for negative peaks).  But on a grid there
  are various ways to define what you mean by an extremum.  Suppose
  you are trying to determine if point p is a maximum (similar
  considerations apply for minimum).  You would want the intensity
  at all nearby points to be less than or equal to the intensity at p.
  You can just check points that are just +- one point from p in each
  dimension, or you can also check "diagonal" points.  For
  example, if you are looking at point p = (x, y) in 2D, then the
  former would mean checking the four points (x-1, y), (x+1, y)
  (x, y-1) and (x, y+1), whereas for the latter you would also have
  to check (x-1, y-1), (x-1, y+1), (x+1, y-1) and (x+1, y+1).  In
  N dimensions the "diagonal" method involves checking 3^N-1 points
  whereas the "non-diagonal" method involves checking only 2N points.
  In general the "non-diagonal" method is probably the one to use,
  and it is the default.

  Peaks are only found above (for positive peaks) or below (for negative
  peaks) some threshold.  By default this is determined by the contour level
  for the spectrum.  For positive peaks the threshold is the minimum
  positive contour level, and for negative peaks the threshold is the
  maximum negative contour level.  However these levels can be scaled up
  (or down) using the "Scale relative to contour levels" option (default
  value 1).  For example, if you have drawn the contour levels low to
  show a bit of noise, but do not want the noise picked as peaks, then
  you could select a scale of 2 (or whatever) to increase the threshold.

  The "Exclusion buffer around peaks" is so that in crowded regions you
  do not get too many peaks near one location.  By default the exclusion
  buffer is 1 point in each dimension, but this can be increased to make
  the algorithm find fewer peaks.

  By default the peak finding only looks at the orthogonal region that
  is displayed in the given window where peak finding is taking place.
  Sometimes it looks like a peak should be found because in x, y you
  can see an extremum, but unless it is also an extremum in the orthogonal
  dimensions it is not picked.  You can widen out the points being
  examined in the orthogonal dimensions by using the "Extra thickness in
  orthogonal dims" option, which is specified in points.

  The "Minimum drop factor" is by what factor the intensity needs to drop
  from its extreme value for there to be considered to be a peak.  This
  could help remove sinc wiggle peaks, for example.  The default is that
  the drop factor is 0, which in effect means that there is no condition.

  The "Volume method" is what is used to estimate the volume of peaks that
  are found.  The default is "box sum", which just looks at a fixed size
  box around the peak centre and sums the intensities in that.  The size
  of the box is set in the table in the Spectrum Widths tab.  The
  "truncated box sum" is the same as "box sum" except that the summing
  stops in a given direction when (if) the intensities start increasing.
  The "parabolic" fit fits a quadratic equation in each dimension to the
  intensity at the peak centre and ad +- 1 points and then uses the
  equivalent Gaussian fit to estimate the volume.

  ** Spectrum Widths **

  This can be used to specify minimum linewidths (in Hz) for there to be
  considered a peak to exist in the peak finding algorithm.  It is also
  where the Boxwidth for each dimension in each spectrum is specified.

  ** Diagonal Exclusions **

  This can be used to exclude peaks from being found in regions near
  the diagonal (so in homonuclear experiments).  The exclusion region
  is specified in ppm and is independent of spectrum.

  ** Region Peak Find **

  This can be used to find peaks non-interactively (so not having to
  control shift drag inside a spectrum window).  The region being
  analysed is specified in the table.  There are two types of conditions
  that can be specified, "include" for regions that should be included
  and "exclude" for regions that should be excluded.  The regions are
  specified in ppm.

  The "Whole Region" button will set the selected row in the table to be
  the entire fundamental region of the spectrum.

  The "Add Region" button adds an extra row to the table, and the "Delete
  Region" button removes the selected row.

  The "Adjust Params" button goes to the Find Parameters tab.

  The "Find Peaks!" button does the peak finding.

"""
    def __init__(self, parent, *args, **kw):

        self.spectrum = None

        BasePopup.__init__(self,
                           parent=parent,
                           title='Peak : Peak Finding',
                           **kw)

    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)

    def administerNotifiers(self, notifyFunc):

        # Many more needed here, esp on the AnalysisProject prams

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

        for func in ('__init__', 'delete'):
            notifyFunc(self.updateRegionPeakLists, 'ccp.nmr.Nmr.PeakList',
                       func)

        for clazz in ('Experiment', 'DataSource'):
            for func in ('__init__', 'delete', 'setName'):
                notifyFunc(self.updateSpectrumTable, 'ccp.nmr.Nmr.%s' % clazz,
                           func)

        for func in ('setPeakFindBoxWidth', 'setPeakFindMinLineWidth'):
            notifyFunc(self.updateSpectrumTable,
                       'ccpnmr.Analysis.AnalysisDataDim', func)

    def destroy(self):

        self.administerNotifiers(self.unregisterNotify)
        BasePopup.destroy(self)

    def updateSpectrum(self, spectrum=None):

        if not spectrum:
            spectrum = self.spectrum

        spectra = self.parent.getSpectra()
        if spectra:
            if spectrum not in spectra:
                spectrum = spectra[0]
            index = spectra.index(spectrum)
            names = ['%s:%s' % (x.experiment.name, x.name) for x in spectra]
        else:
            index = 0
            names = []

        self.expt_spectrum.setup(names, spectra, index)

        self.setSpectrumProperties(spectrum)

    def updateNotifier(self, *extra):

        self.updateSpectrum()

    def setLinewidth(self, *event):

        value = self.editLinewidthEntry.get()
        if value is not None:
            PeakFindParams.setPeakFindMinLinewidth(self.dataDim, value)
            self.setSpectrumProperties(self.dataDim.dataSource)

    def getLinewidth(self, dataDim):

        if dataDim:
            self.editLinewidthEntry.set(
                PeakFindParams.getPeakFindMinLinewidth(self.dataDim))

    def setBoxwidth(self, *event):

        value = self.editBoxwidthEntry.get()
        if value is not None:
            PeakFindParams.setPeakFindBoxwidth(self.dataDim, value)
            self.setSpectrumProperties(self.dataDim.dataSource)

    def getBoxwidth(self, dataDim):

        if dataDim:
            self.editBoxwidthEntry.set(
                PeakFindParams.getPeakFindBoxwidth(self.dataDim))

    def selectCell(self, object, row, col):

        self.dataDim = object

    def setExclusion(self, *extra):

        isotope = self.isotopeMatrix.currentObject
        if not isotope:
            return

        value = self.exclusionEntry.get()
        if value is not None:
            setIsotopeExclusion(isotope, value)
            self.setIsotopeProperties()

    def getExclusion(self, isotope):

        value = getIsotopeExclusion(isotope)
        self.exclusionEntry.set(value)

    def setParamsEntries(self):

        project = self.project
        params = PeakFindParams.getPeakFindParams(project)

        self.scale_entry.set(params['scale'])
        self.buffer_entry.set(params['buffer'])
        self.thickness_entry.set(params['thickness'])
        self.drop_entry.set(params['drop'])
        volumeMethod = params['volumeMethod']
        if volumeMethod == 'parabolic fit':
            volumeMethod = PeakBasic.PEAK_VOLUME_METHODS[0]
        self.method_menu.set(params['volumeMethod'])

        if (params['nonadjacent']):
            n = 1
        else:
            n = 0
        self.adjacent_buttons.setIndex(n)

        have_high = params['haveHigh']
        have_low = params['haveLow']
        if (have_high and have_low):
            n = 0
        elif (have_high):
            n = 1
        else:
            n = 2
        self.extrema_buttons.setIndex(n)

    def apply(self, *extra):

        params = {}
        params['scale'] = self.scale_entry.get()
        params['buffer'] = self.buffer_entry.get()
        params['thickness'] = self.thickness_entry.get()
        params['drop'] = self.drop_entry.get()
        params['volumeMethod'] = self.method_menu.getText()

        n = self.adjacent_buttons.getIndex()
        if (n == 0):
            nonadjacent = False
        else:
            nonadjacent = True
        params['nonadjacent'] = nonadjacent

        n = self.extrema_buttons.getIndex()
        if (n == 0):
            have_high = True
            have_low = True
        elif (n == 1):
            have_high = True
            have_low = False
        elif (n == 2):
            have_high = False
            have_low = True
        params['haveHigh'] = have_high
        params['haveLow'] = have_low

        project = self.project
        try:
            PeakFindParams.setPeakFindParams(project, params)
        except Implementation.ApiError, e:
            showError('Parameter error', e.error_msg, parent=self)
예제 #24
0
    def body(self):
        '''describes the body of this tab. It bascically consists
           of some field to fill out for the user at the top and
           a ScrolledGraph that shows the progess of the annealing
           procedure a the bottom.
        '''

        frame = self.frame

        # frame.expandGrid(13,0)
        frame.expandGrid(15, 1)
        row = 0

        text = 'Calculate Assignment Suggestions'
        command = self.runCalculations
        self.startButton = Button(frame, command=command, text=text)
        self.startButton.grid(row=row, column=0, sticky='nsew', columnspan=2)

        row += 1

        Label(frame, text='Amount of runs: ', grid=(row, 0))
        tipText = 'The amount of times the whole optimization procedure is performed, each result is safed'
        self.repeatEntry = IntEntry(frame, grid=(row, 1), width=7, text=10,
                                    returnCallback=self.updateRepeatEntry,
                                    tipText=tipText, sticky='nsew')
        self.repeatEntry.bind('<Leave>', self.updateRepeatEntry, '+')

        row += 1

        Label(frame, text='Temperature regime: ', grid=(row, 0))
        tipText = 'This list of numbers govern the temperature steps during the annealing, every number represents 1/(kb*t), where kb is the Boltzmann constant and t the temperature of one step.'
        self.tempEntry = Entry(frame, text=map(str, self.acceptanceConstantList), width=64,
                               grid=(row, 1), isArray=True, returnCallback=self.updateAcceptanceConstantList,
                               tipText=tipText, sticky='nsew')

        row += 1

        Label(frame, text='Amount of attempts per temperature:', grid=(row, 0))
        tipText = 'The amount of attempts to switch the position of two spinsystems in the sequence are performed for each temperature point'
        self.NAStepEntry = IntEntry(frame, grid=(row, 1), width=7, text=10000,
                                    returnCallback=self.updateStepEntry,
                                    tipText=tipText, sticky='nsew')
        self.NAStepEntry.bind('<Leave>', self.updateStepEntry, '+')

        row += 1

        Label(frame, text='Fraction of peaks to leave out:', grid=(row, 0))
        tipText = 'In each run a fraction of the peaks can be left out of the optimization, thereby increasing the variability in the outcome and reducing false negatives. In each run this will be different randomly chosen sub-set of all peaks. 0.1 (10%) can be a good value.'
        self.leaveOutPeaksEntry = FloatEntry(frame, grid=(row, 1), width=7, text=0.0,
                                             returnCallback=self.updateLeavePeaksOutEntry,
                                             tipText=tipText, sticky='nsew')
        self.leaveOutPeaksEntry.bind(
            '<Leave>', self.updateLeavePeaksOutEntry, '+')

        row += 1

        Label(frame, text='Minmal amino acid typing score:', grid=(row, 0))
        tipText = 'If automatic amino acid typing is selected, a cut-off value has to set. Every amino acid type that scores higher than the cut-off is taken as a possible type. This is the same score as can be found under resonance --> spin systems --> predict type. Value should be between 0 and 100'
        self.minTypeScoreEntry = FloatEntry(frame, grid=(row, 1), width=7, text=1.0,
                                            returnCallback=self.updateMinTypeScoreEntry,
                                            tipText=tipText, sticky='nsew')
        self.minTypeScoreEntry.bind(
            '<Leave>', self.updateMinTypeScoreEntry, '+')

        row += 1

        Label(frame, text='Minimal colabelling fraction:', grid=(row, 0))
        tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.'
        self.minLabelEntry = FloatEntry(frame, grid=(row, 1), width=7, text=0.1,
                                        returnCallback=self.updateMinLabelEntry,
                                        tipText=tipText, sticky='nsew')
        self.minLabelEntry.bind('<Leave>', self.updateMinLabelEntry, '+')

        row += 1

        Label(frame, text='Use sequential assignments:', grid=(row, 0))
        tipText = 'When this option is select the present sequential assignments will be kept in place'
        self.useAssignmentsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use tentative assignments:', grid=(row, 0))
        tipText = 'If a spin system has tentative assignments this can be used to narrow down the amount of possible sequential assignments.'
        self.useTentativeCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use amino acid types:', grid=(row, 0))
        tipText = 'Use amino acid types of the spin systems. If this option is not checked the spin systems are re-typed, only resonance names and frequencies are used'
        self.useTypeCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Include untyped spin systems:', grid=(row, 0))
        tipText = 'Also include spin system that have no type information. Amino acid typing will be done on the fly.'
        self.useAlsoUntypedSpinSystemsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use dimensional assignments:', grid=(row, 0))
        tipText = 'If one or more dimensions of a peak is already assigned, assume that this assignment is the only option. If not the check the program will consider all possibilities for the assignment of the dimension.'
        self.useDimensionalAssignmentsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Chain:', grid=(row, 0))
        self.molPulldown = PulldownList(
            frame, callback=self.changeMolecule, grid=(row, 1))
        self.updateChains()

        row += 1

        Label(frame, text='Residue ranges: ', grid=(row, 0))
        tipText = 'Which residues should be included. Example: "10-35, 62-100, 130".'
        self.residueRangeEntry = Entry(frame, text=None, width=64,
                                       grid=(row, 1), isArray=True, returnCallback=self.updateResidueRanges,
                                       tipText=tipText, sticky='nsew')
        self.updateResidueRanges(fromChain=True)

        row += 1

        self.energyPlot = ScrolledGraph(frame, symbolSize=2, width=600,
                                        height=200, title='Annealing',
                                        xLabel='temperature step', yLabel='energy')
        self.energyPlot.grid(row=row, column=0, columnspan=2, sticky='nsew')
예제 #25
0
class PopupTemplate(BasePopup):

  def __init__(self, parent, project=None, *args, **kw):

    self.project = project
    self.parent  = parent
    self.objects = self.getObjects()
    self.object  = None
    
    BasePopup.__init__(self, parent=parent, title='Popup Template', **kw)
                       
    self.updateObjects()

  def body(self, mainFrame):

    mainFrame.grid_columnconfigure(1, weight=1, minsize=100)
    mainFrame.config(borderwidth=5, relief='solid')

    row = 0
    label = Label(mainFrame, text="Frame (with sub-widgets):")
    label.grid(row=row, column=0, sticky=Tkinter.E)

    frame = Frame(mainFrame, relief='raised', border=2, background='#8080D0')
    # Frame expands East-West
    frame.grid(row=row, column=1, sticky=Tkinter.EW)
    # Last column expands => Widgets pusted to the West
    frame.grid_columnconfigure(3, weight=1)
    
    # Label is within the sub frame
    label = Label(frame, text='label ')
    label.grid(row=0, column=0, sticky=Tkinter.W)
    
    entry = Entry(frame, text='Entry', returnCallback=self.showWarning)
    entry.grid(row=0, column=1, sticky=Tkinter.W)
    
    self.check = CheckButton(frame, text='Checkbutton', selected=True, callback=self.updateObjects)
    self.check.grid(row=0, column=2, sticky=Tkinter.W)
    
    # stick a button to the East wall
    button = Button(frame, text='Button', command=self.pressButton)
    button.grid(row=0, column=3, sticky=Tkinter.E)
  
    row += 1
    label = Label(mainFrame, text="Text:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    self.textWindow = Text(mainFrame, text='Initial Text\n', width=60, height=5)
    self.textWindow.grid(row=row, column=1, sticky=Tkinter.NSEW)
    
    row += 1
    label = Label(mainFrame, text="CheckButtons:")
    label.grid(row=row, column=0, sticky=Tkinter.E)

    entries = ['Alpha','Beta','Gamma','Delta']
    selected = entries[2:]
    self.checkButtons = CheckButtons(mainFrame, entries, selected=selected,select_callback=self.changedCheckButtons)
    self.checkButtons.grid(row=row, column=1, sticky=Tkinter.W)
  
    row += 1
    label = Label(mainFrame, text="PartitionedSelector:")
    label.grid(row=row, column=0, sticky=Tkinter.E)

    labels   = ['Bool','Int','Float','String']
    objects  = [type(0),type(1),type(1.0),type('a')]
    selected = [type('a')]
    self.partitionedSelector= PartitionedSelector(mainFrame, labels=labels,
                                                  objects=objects,
                                                  colors = ['red','yellow','green','#000080'],
                                                  callback=self.toggleSelector,selected=selected)
    self.partitionedSelector.grid(row=row, column=1, sticky=Tkinter.EW)

    row += 1
    label = Label(mainFrame, text="PulldownMenu")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    
    entries = ['Frodo','Pipin','Merry','Sam','Bill','Gandalf','Strider','Gimli','Legolas']
    self.pulldownMenu = PulldownMenu(mainFrame, callback=self.selectPulldown,
                                     entries=entries, selected_index=2,
                                     do_initial_callback=False)
    self.pulldownMenu.grid(row=row, column=1, sticky=Tkinter.W)

    row += 1
    label = Label(mainFrame, text="RadioButtons in a\nScrolledFrame.frame:")
    label.grid(row=row, column=0, sticky=Tkinter.EW)
    
    frame = ScrolledFrame(mainFrame, yscroll = False, doExtraConfig = True, width=100)
    frame.grid(row=row, column=1, sticky=Tkinter.EW)
    frame.grid_columnconfigure(0, weight=1)

    self.radioButtons = RadioButtons(frame.frame, entries=entries,
                                     select_callback=self.checkRadioButtons,
                                     selected_index=1, relief='groove')
    self.radioButtons.grid(row=0, column=0, sticky=Tkinter.W)
    
    row += 1
    label = Label(mainFrame, text="LabelFrame with\nToggleLabels inside:")
    label.grid(row=row, column=0, sticky=Tkinter.E)

    labelFrame = LabelFrame(mainFrame, text='Frame Title')
    labelFrame.grid(row=row, column=1, sticky=Tkinter.NSEW)
    labelFrame.grid_rowconfigure(0, weight=1)
    labelFrame.grid_columnconfigure(3, weight=1)
    
        
    self.toggleLabel1 = ToggleLabel(labelFrame, text='ScrolledMatrix', callback=self.toggleFrame1)
    self.toggleLabel1.grid(row=0, column=0, sticky=Tkinter.W)
    self.toggleLabel1.arrowOn()

    self.toggleLabel2 = ToggleLabel(labelFrame, text='ScrolledGraph', callback=self.toggleFrame2)
    self.toggleLabel2.grid(row=0, column=1, sticky=Tkinter.W)

    self.toggleLabel3 = ToggleLabel(labelFrame, text='ScrolledCanvas', callback=self.toggleFrame3)
    self.toggleLabel3.grid(row=0, column=2, sticky=Tkinter.W)
    
    row += 1
    mainFrame.grid_rowconfigure(row, weight=1)

    label = Label(mainFrame, text="changing/shrinking frames:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    
    self.toggleRow = row
    self.toggleFrame = Frame(mainFrame)
    self.toggleFrame.grid(row=row, column=1, sticky=Tkinter.NSEW)
    self.toggleFrame.grid_rowconfigure(0, weight=1)
    self.toggleFrame.grid_columnconfigure(0, weight=1)
    
    # option 1
    
    self.intEntry = IntEntry(self, returnCallback = self.setNumber, width=8)
    
    self.multiWidget = MultiWidget(self, Entry, options=None, 
                                  values=None, callback=self.setKeywords,
                                  minRows=3, maxRows=5)

    editWidgets      = [None, None, self.intEntry,  self.multiWidget]
    editGetCallbacks = [None, None, self.getNumber, self.getKeywords]
    editSetCallbacks = [None, None, self.setNumber, self.setKeywords]
    
    headingList = ['Name','Color','Number','Keywords']
    self.scrolledMatrix = ScrolledMatrix(self.toggleFrame, headingList=headingList,
                                         editSetCallbacks=editSetCallbacks,
                                         editGetCallbacks=editGetCallbacks,
                                         editWidgets=editWidgets,
                                         callback=self.selectObject,
                                         multiSelect=False) 
                                         
    self.scrolledMatrix.grid(row=0, column=0, sticky=Tkinter.NSEW)

    # option 2
    self.scrolledGraph = ScrolledGraph(self.toggleFrame, width=400,
                                       height=300, symbolSize=5,
                                       symbols=['square','circle'],
                                       dataColors=['#000080','#800000'],
                                       lineWidths=[0,1] )

    self.scrolledGraph.setZoom(1.3)

    dataSet1 = [[0,0],[1,1],[2,4],[3,9],[4,16],[5,25]]
    dataSet2 = [[0,0],[1,3],[2,6],[3,9],[4,12],[5,15]]
    self.scrolledGraph.update(dataSets=[dataSet1,dataSet2],
                              xLabel = 'X axis label',
                              yLabel = 'Y axis label',
                              title  = 'Main Title')
    self.scrolledGraph.draw()

    # option 3
    self.scrolledCanvas = ScrolledCanvas(self.toggleFrame,relief = 'groove', borderwidth = 2, resizeCallback=None)
    canvas = self.scrolledCanvas.canvas
    font   = 'Helvetica 10'
    box    = canvas.create_rectangle(10,10,150,200, outline='grey', fill='grey90')
    line   = canvas.create_line(0,0,200,200,fill='#800000', width=2)
    text   = canvas.create_text(120,50, text='Text', font=font, fill='black')
    circle = canvas.create_oval(30,30,50,50,outline='#008000',fill='#404040',width=3)
     
    row += 1
    label = Label(mainFrame, text="FloatEntry:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    self.floatEntry = FloatEntry(mainFrame, text=3.14159265, returnCallback=self.floatEntryReturn)
    self.floatEntry.grid(row=row, column=1, sticky=Tkinter.W)
    
     
    row += 1
    label = Label(mainFrame, text="Scale:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    self.scale = Scale(mainFrame, from_=10, to=90, value=50, orient=Tkinter.HORIZONTAL)
    self.scale.grid(row=row, column=1, sticky=Tkinter.W)

    row += 1
    label = Label(mainFrame, text="Value Ramp:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    self.valueRamp = ValueRamp(mainFrame, self.valueRampCallback, speed = 1.5, delay = 50)
    self.valueRamp.grid(row=row, column=1, sticky=Tkinter.W)
  

    row += 1
    label = Label(mainFrame, text="ButtonList:")
    label.grid(row=row, column=0, sticky=Tkinter.E)
    
    texts    = ['Select File','Close','Quit']
    commands = [self.selectFile, self.close, self.quit]
    bottomButtons = ButtonList(mainFrame, texts=texts, commands=commands, expands=True) 
    bottomButtons.grid(row=row, column=1, sticky=Tkinter.EW)
  
    self.protocol('WM_DELETE_WINDOW', self.quit)

  def floatEntryReturn(self, event):
  
    value = self.floatEntry.get()
    self.textWindow.setText('%s\n' % value)

  def selectObject(self, object, row, col):
  
    self.object = object

  def getKeywords(self, object):
  
    if object :
      values = object.keywords
      self.multiWidget.set(values)
  
  def setKeywords(self, event):
  
    values = self.multiWidget.get()
    self.object.keywords = values
    self.updateObjects()

  def getNumber(self, object):

    if object :
      self.intEntry.set(object.quantity)

  def setNumber(self, event):

    value = self.intEntry.get()
    self.object.quantity = value
    self.updateObjects()

  def toggleFrame1(self, isHidden):
 
    if isHidden:
      self.scrolledMatrix.grid_forget()
      self.toggleFrame.grid_forget()
    else:
      self.scrolledGraph.grid_forget()
      self.scrolledCanvas.grid_forget()
      self.scrolledMatrix.grid(row=0, column=0, sticky=Tkinter.NSEW)
      self.toggleFrame.grid(row=self.toggleRow, column=1,sticky=Tkinter.NSEW)
      self.toggleLabel2.arrowOff()
      self.toggleLabel3.arrowOff()


  def toggleFrame2(self, isHidden):
 
    if isHidden:
      self.scrolledGraph.grid_forget()
      self.toggleFrame.grid_forget()
    else:
      self.scrolledMatrix.grid_forget()
      self.scrolledCanvas.grid_forget()
      self.scrolledGraph.grid(row=0, column=0, sticky=Tkinter.NSEW)
      self.toggleFrame.grid(row=self.toggleRow, column=1,sticky=Tkinter.NSEW)
      self.toggleLabel1.arrowOff()
      self.toggleLabel3.arrowOff()

  def toggleFrame3(self, isHidden):
 
    if isHidden:
      self.scrolledCanvas.grid_forget()
      self.toggleFrame.grid_forget()
    else:
      self.scrolledMatrix.grid_forget()
      self.scrolledGraph.grid_forget()
      self.scrolledCanvas.grid(row=0, column=0, sticky=Tkinter.NSEW)
      self.toggleFrame.grid(row=self.toggleRow, column=1,sticky=Tkinter.NSEW)
      self.toggleLabel1.arrowOff()
      self.toggleLabel2.arrowOff()

 
  def valueRampCallback(self, value):
  
    self.textWindow.setText('%s\n' % value)

  def checkRadioButtons(self, value):
  
    self.textWindow.setText('%s\n' % value)

  def selectPulldown(self, index, name):
  
    self.textWindow.setText('%d, %s\n' % (index, name))

  def toggleSelector(self, value):
  
    self.textWindow.setText('%s\n' % value)

  def changedCheckButtons(self, values):
  
    self.textWindow.setText(','.join(values) + '\n')

  def getObjects(self):
  
    objects = []
    
    objects.append( Fruit('Lemon',   '#FFFF00',1,keywords=['Bitter','Tangy'] ) )
    objects.append( Fruit('Orange',  '#FF8000',4 ) )
    objects.append( Fruit('Banana',  '#FFF000',5 ) )
    objects.append( Fruit('Pinapple','#FFD000',9 ) )
    objects.append( Fruit('Kiwi',    '#008000',12) )
    objects.append( Fruit('Lime',    '#00FF00',2 ) )
    objects.append( Fruit('Apple',   '#800000',5,keywords=['Crunchy'] ) )
    objects.append( Fruit('Pear',    '#408000',6 ) )
    objects.append( Fruit('Peach',   '#FFE0C0',2,keywords=['Sweet','Furry'] ) )
    objects.append( Fruit('Plumb',   '#800080',7 ) )
    
    return objects

  def updateObjects(self, event=None):

    textMatrix = []
    objectList = []
    colorMatrix = []
    
    for object in self.objects:
      datum = []
      datum.append( object.name )
      datum.append( None )
      datum.append( object.quantity )
      datum.append( ','.join(object.keywords) )
    
      colors = [None, object.color, None, None]
    
      textMatrix.append(datum)
      objectList.append(object)
      colorMatrix.append(colors)

    if self.check.get():
      self.scrolledMatrix.update(textMatrix=textMatrix, objectList=objectList)
    else:
      self.scrolledMatrix.update(textMatrix=textMatrix, objectList=objectList, colorMatrix=colorMatrix)

  def selectFile(self):

    fileSelectPopup = FileSelectPopup(self, title = 'Choose file', dismiss_text = 'Cancel',
                                      selected_file_must_exist = True)

    fileName = fileSelectPopup.getFile()

    self.textWindow.setText('File Selected: %s\n' % fileName)

  def showWarning(self, eventObject):
  
    self.textWindow.setText('Text Entry Return Pressed\n')
    showWarning('Warning Title','Warning Message')
    return

  def pressButton(self):
  
    self.textWindow.setText('Button Pressed\n')
    if showYesNo('Title','Prompt: Clear text window?'):
       self.textWindow.clear()
       
    return

  def quit(self):
  
    BasePopup.destroy(self)  
예제 #26
0
class AnnealingSettingsTab(object):
    '''This class describes the tab in the GUI where the user
       can change setting that govern the monte carlo / annleaing
       procedure. This also includes which information from the ccpn
       analysis project is used and which information is
       ignored. This includes:
           * present sequential assignments
           * tentative assignments
           * amino acid type information
           * whether to include untyped spin systems
           * assignments to peak dimensions
       ALso the chain can be selected here.
       Furthermore the user can set the temperature
       regime of the annealing, the amount of times the procedure
       is repeated to obtain statistics. The fraction of peaks
       that is left out in each run to diversify the results,
       the treshhold score for amino acid typing and the treshhold
       collabelling for a peak to be expected.
    '''

    def __init__(self, parent, frame):
        '''Init. args: parent: the guiElement that this
                               tab is part of.
                       frame:  the frame this part of the
                               GUI lives in.
        '''

        self.guiParent = parent
        self.frame = frame
        self.project = parent.project
        self.nmrProject = parent.nmrProject

        self.minIsoFrac = 0.1
        self.leavePeaksOutFraction = 0.0
        self.minTypeScore = 1.0
        self.chain = None
        self.amountOfRepeats = 10
        self.amountOfSteps = 10000
        self.acceptanceConstantList = [0.0, 0.01, 0.015, 0.022,
                                       0.033, 0.050, 0.075, 0.113,
                                       0.170, 0.256, 0.384, 0.576,
                                       0.864, 1.297, 1.946, 2.919,
                                       4.378, 6.568, 9.852, 14.77,
                                       22.16, 33.25]
        self.energyDataSets = [[]]
        self.residues = []
        self.body()

    def body(self):
        '''describes the body of this tab. It bascically consists
           of some field to fill out for the user at the top and
           a ScrolledGraph that shows the progess of the annealing
           procedure a the bottom.
        '''

        frame = self.frame

        # frame.expandGrid(13,0)
        frame.expandGrid(15, 1)
        row = 0

        text = 'Calculate Assignment Suggestions'
        command = self.runCalculations
        self.startButton = Button(frame, command=command, text=text)
        self.startButton.grid(row=row, column=0, sticky='nsew', columnspan=2)

        row += 1

        Label(frame, text='Amount of runs: ', grid=(row, 0))
        tipText = 'The amount of times the whole optimization procedure is performed, each result is safed'
        self.repeatEntry = IntEntry(frame, grid=(row, 1), width=7, text=10,
                                    returnCallback=self.updateRepeatEntry,
                                    tipText=tipText, sticky='nsew')
        self.repeatEntry.bind('<Leave>', self.updateRepeatEntry, '+')

        row += 1

        Label(frame, text='Temperature regime: ', grid=(row, 0))
        tipText = 'This list of numbers govern the temperature steps during the annealing, every number represents 1/(kb*t), where kb is the Boltzmann constant and t the temperature of one step.'
        self.tempEntry = Entry(frame, text=map(str, self.acceptanceConstantList), width=64,
                               grid=(row, 1), isArray=True, returnCallback=self.updateAcceptanceConstantList,
                               tipText=tipText, sticky='nsew')

        row += 1

        Label(frame, text='Amount of attempts per temperature:', grid=(row, 0))
        tipText = 'The amount of attempts to switch the position of two spinsystems in the sequence are performed for each temperature point'
        self.NAStepEntry = IntEntry(frame, grid=(row, 1), width=7, text=10000,
                                    returnCallback=self.updateStepEntry,
                                    tipText=tipText, sticky='nsew')
        self.NAStepEntry.bind('<Leave>', self.updateStepEntry, '+')

        row += 1

        Label(frame, text='Fraction of peaks to leave out:', grid=(row, 0))
        tipText = 'In each run a fraction of the peaks can be left out of the optimization, thereby increasing the variability in the outcome and reducing false negatives. In each run this will be different randomly chosen sub-set of all peaks. 0.1 (10%) can be a good value.'
        self.leaveOutPeaksEntry = FloatEntry(frame, grid=(row, 1), width=7, text=0.0,
                                             returnCallback=self.updateLeavePeaksOutEntry,
                                             tipText=tipText, sticky='nsew')
        self.leaveOutPeaksEntry.bind(
            '<Leave>', self.updateLeavePeaksOutEntry, '+')

        row += 1

        Label(frame, text='Minmal amino acid typing score:', grid=(row, 0))
        tipText = 'If automatic amino acid typing is selected, a cut-off value has to set. Every amino acid type that scores higher than the cut-off is taken as a possible type. This is the same score as can be found under resonance --> spin systems --> predict type. Value should be between 0 and 100'
        self.minTypeScoreEntry = FloatEntry(frame, grid=(row, 1), width=7, text=1.0,
                                            returnCallback=self.updateMinTypeScoreEntry,
                                            tipText=tipText, sticky='nsew')
        self.minTypeScoreEntry.bind(
            '<Leave>', self.updateMinTypeScoreEntry, '+')

        row += 1

        Label(frame, text='Minimal colabelling fraction:', grid=(row, 0))
        tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.'
        self.minLabelEntry = FloatEntry(frame, grid=(row, 1), width=7, text=0.1,
                                        returnCallback=self.updateMinLabelEntry,
                                        tipText=tipText, sticky='nsew')
        self.minLabelEntry.bind('<Leave>', self.updateMinLabelEntry, '+')

        row += 1

        Label(frame, text='Use sequential assignments:', grid=(row, 0))
        tipText = 'When this option is select the present sequential assignments will be kept in place'
        self.useAssignmentsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use tentative assignments:', grid=(row, 0))
        tipText = 'If a spin system has tentative assignments this can be used to narrow down the amount of possible sequential assignments.'
        self.useTentativeCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use amino acid types:', grid=(row, 0))
        tipText = 'Use amino acid types of the spin systems. If this option is not checked the spin systems are re-typed, only resonance names and frequencies are used'
        self.useTypeCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Include untyped spin systems:', grid=(row, 0))
        tipText = 'Also include spin system that have no type information. Amino acid typing will be done on the fly.'
        self.useAlsoUntypedSpinSystemsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use dimensional assignments:', grid=(row, 0))
        tipText = 'If one or more dimensions of a peak is already assigned, assume that this assignment is the only option. If not the check the program will consider all possibilities for the assignment of the dimension.'
        self.useDimensionalAssignmentsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Chain:', grid=(row, 0))
        self.molPulldown = PulldownList(
            frame, callback=self.changeMolecule, grid=(row, 1))
        self.updateChains()

        row += 1

        Label(frame, text='Residue ranges: ', grid=(row, 0))
        tipText = 'Which residues should be included. Example: "10-35, 62-100, 130".'
        self.residueRangeEntry = Entry(frame, text=None, width=64,
                                       grid=(row, 1), isArray=True, returnCallback=self.updateResidueRanges,
                                       tipText=tipText, sticky='nsew')
        self.updateResidueRanges(fromChain=True)

        row += 1

        self.energyPlot = ScrolledGraph(frame, symbolSize=2, width=600,
                                        height=200, title='Annealing',
                                        xLabel='temperature step', yLabel='energy')
        self.energyPlot.grid(row=row, column=0, columnspan=2, sticky='nsew')

    def runCalculations(self):
        '''Run all calculations. Also triggers the disabling of
           some buttons and fields.
        '''

        self.startButton.disable()
        self.disableIllegalButtonsAfterPrecalculations()
        self.guiParent.connector.runAllCalculations()
        self.startButton.configure(text='More runs')
        self.startButton.enable()

    def disableIllegalButtonsAfterPrecalculations(self):
        '''Disable buttons and field the user can not alter
           any longer after the model is set up and the
           'pre-calculations' have finished.
           This is done because this part of the calculation
           should only be run once. All settings that would
           be changed after this point will not have any influence.
        '''

        illegalButtons = [self.minTypeScoreEntry, self.minLabelEntry,
                          self.useAlsoUntypedSpinSystemsCheck, self.useAssignmentsCheck,
                          self.useTypeCheck, self.useDimensionalAssignmentsCheck,
                          self.useTentativeCheck]

        for illegalButton in illegalButtons:
            illegalButton.configure(state='disabled')

        self.molPulldown.disable()

    def getChainName(self, chain):
        '''Get the name for a chain.
               args: chain: ccpn analysis
                            chain object
               returns: chain name
        '''

        return '%s:%s (%s)' % (chain.molSystem.code, chain.code, chain.molecule.molType)

    def getChains(self):
        '''Get all chains present in the project.
               returns: list of ccpn analysis chain objects
        '''
        chains = []
        if self.project:
            for molSystem in self.project.sortedMolSystems():
                for chain in molSystem.sortedChains():
                    if chain.residues:
                        chains.append(chain)

        return chains

    def updateChains(self, *opt):
        '''Updates the list of chains if a new one is added
           to or deleted from the project. Updates the
           pull down list where a chain can be selected.
        '''

        index = 0
        texts = []
        chains = self.getChains()
        chain = self.chain

        if chains:
            if chain not in chains:
                chain = chains[0]

            texts = [self.getChainName(c) for c in chains]
            index = chains.index(chain)

        else:
            chain = None

        self.molPulldown.setup(texts, chains, index)

        if chain is not self.chain:
            self.chain = chain

    def changeMolecule(self, chain):
        '''Select a molecular chain.'''

        if chain is not self.chain:
            self.chain = chain
            self.updateResidueRanges(fromChain=True)

    def updateStepEntry(self, event=None):
        '''Update the value and entry that sets the amount of
           steps per temperature point.
        '''

        value = self.NAStepEntry.get()
        if value == self.amountOfSteps:
            return
        if value < 1:
            self.NAStepEntry.set(1)
            self.amountOfSteps = 1
        else:
            self.amountOfSteps = value
            self.NAStepEntry.set(value)

    def updateRepeatEntry(self, event=None):
        '''Update the value and entry of that sets
           the amount of times the whole annealing
           procedure is repeated in order
           to obtain statistics.
        '''

        value = self.repeatEntry.get()

        if value == self.amountOfRepeats:
            return
        if value < 1:
            self.repeatEntry.set(1)
            self.amountOfRepeats = 1
        else:
            self.amountOfRepeats = value
            self.repeatEntry.set(value)

    def updateMinTypeScoreEntry(self, event=None):
        '''Updates the value and the entry for the
           treshhold value for amino acid typing.
        '''

        value = self.minTypeScoreEntry.get()

        if value == self.minTypeScore:
            return
        if value < 0:
            self.minTypeScoreEntry.set(0.0)
            self.minTypeScore = 0.0
        elif value > 100:
            self.minTypeScoreEntry.set(100.0)
            self.minTypeScore = 100.0
        else:
            self.minTypeScoreEntry.set(value)
            self.minTypeScore = value

    def updateMinLabelEntry(self, event=None):
        '''Updates the minimum colabelling fraction
           for which a peak is expected to be present
           in the spectra.
        '''

        value = self.minLabelEntry.get()

        if value == self.minIsoFrac:
            return
        if value < 0:
            self.minIsoFrac = 0.0
            self.minLabelEntry.set(0.0)
        elif value > 1:
            self.minIsoFrac = 1.0
            self.minLabelEntry.set(1.0)
        else:
            self.minIsoFrac = value
            self.minLabelEntry.set(value)

    def updateLeavePeaksOutEntry(self, event=None):
        '''Updates the value and entry of the fraction
           of peaks that should be left out in each
           run in order to diversify the results.
        '''

        value = self.leaveOutPeaksEntry.get()

        if value == self.leavePeaksOutFraction:
            return
        if value < 0:
            self.leavePeaksOutFraction = 0.0
            self.leaveOutPeaksEntry.set(0.0)
        elif value > 1:
            self.leavePeaksOutFraction = 1.0
            self.leaveOutPeaksEntry.set(1.0)
        else:
            self.leavePeaksOutFraction = value
            self.leaveOutPeaksEntry.set(value)

    def updateAcceptanceConstantList(self, event=None):
        '''Updates the list with constants that are used
           during the monte carlo procedure to decide whether
           a changed is accepted or not.
        '''

        acList = self.tempEntry.get()
        newList = []

        for constant in acList:

            try:

                number = float(constant)
                newList.append(number)

            except ValueError:

                string = constant + \
                    ' in temperature constants is not a number.'

                showWarning('Not A Number', string, parent=self.guiParent)

                return False

        self.acceptanceConstantList = newList

        return True

    def updateResidueRanges(self, event=None, fromChain=False):

        self.residues = set()

        subRanges = self.residueRangeEntry.get()
        if not subRanges or fromChain:
            self.residues = set(self.chain.residues)
            residues = self.chain.sortedResidues()
            text = '{}-{}'.format(residues[0].seqCode, residues[-1].seqCode)
            self.residueRangeEntry.set(text=text)
            return

        for subRange in subRanges:
            indeces = subRange.split('-')
            start = int(indeces[0])
            stop = int(indeces[-1]) + 1
            for seqCode in range(start, stop):
                residue = self.chain.findFirstResidue(seqCode=seqCode)
                if not residue:
                    showWarning('Residue out of range.',
                                'There is no residue at position {}'.format(seqCode),
                                parent=self.guiParent)
                    self.residues = set()
                    return
                self.residues.add(residue)

    def addEnergyPoint(self, energy, time):
        '''Adds a point to the graph that shows the progress
           of the annealling procedure.
               args: energy: the y-value
                     time:   the x-value
        '''

        point = (time, energy * -1)

        # This means one run has finished
        if len(self.energyDataSets[-1]) / (len(self.acceptanceConstantList) + 1):

            self.energyDataSets.append([point])

        else:

            self.energyDataSets[-1].append(point)

        colors = colorSeries
        Ncolors = len(colors)
        NdataSets = len(self.energyDataSets)
        colorList = (NdataSets / Ncolors) * colors + \
            colors[:NdataSets % Ncolors]
        self.energyPlot.update(dataSets=self.energyDataSets,
                               dataColors=colorList)

        # Forcing the graph to draw, eventhough calculations
        # are still running. Only do this with high numbers of
        # steps, otherwise drawing takes longer than annealling.
        if self.amountOfSteps >= 100000:

            self.energyPlot.draw()
예제 #27
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()
예제 #28
0
class MeccanoPopup(BasePopup):

  def __init__(self, parent, project, *args, **kw):
  
    self.alignMedium = None
    self.chain = None
    self.constraint = None
    self.constraintSet = None
    self.molSystem = None
    self.project = project
    self.run = None
    self.shiftList = None
    self.tensor = None

    
    BasePopup.__init__(self, parent=parent, title='MECCANO', *args, **kw)

    self.curateNotifiers(self.registerNotify)

  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()
    
  def close(self):
  
    self.updateRunParams()
    
    BasePopup.close(self)
  
  def destroy(self):
  
    self.updateRunParams()
    self.curateNotifiers(self.unregisterNotify)
    
    BasePopup.destroy(self)
  
  def curateNotifiers(self, notifyFunc):
  
    for func in ('__init__', 'delete'):
      notifyFunc(self.updateConstraintSetsAfter, 'ccp.nmr.NmrConstraint.NmrConstraintStore', func)
    
    for func in ('__init__', 'delete','setName','setConditionState'):
      for clazz in ('ccp.nmr.NmrConstraint.CsaConstraintList',
                    'ccp.nmr.NmrConstraint.DihedralConstraintList',
                    'ccp.nmr.NmrConstraint.DistanceConstraintList',
                    'ccp.nmr.NmrConstraint.HBondConstraintList',
                    'ccp.nmr.NmrConstraint.JCouplingConstraintList',
                    'ccp.nmr.NmrConstraint.RdcConstraintList'):
        notifyFunc(self.updateConstraintListsAfter, clazz, func)
        
    for func in ('__init__', 'delete',):
      for clazz in ('ccp.nmr.NmrConstraint.CsaConstraint',
                    'ccp.nmr.NmrConstraint.DihedralConstraint',
                    'ccp.nmr.NmrConstraint.DistanceConstraint',
                    'ccp.nmr.NmrConstraint.HBondConstraint',
                    'ccp.nmr.NmrConstraint.JCouplingConstraint',
                    'ccp.nmr.NmrConstraint.RdcConstraint'):
        notifyFunc(self.updateConstraintsAfter, clazz, func)    
    
    for func in ('__init__', 'delete'):
      notifyFunc(self.updateShiftListsAfter,'ccp.nmr.Nmr.ShiftList', func)

    for func in ('__init__', 'delete'):
      notifyFunc(self.updateMolSystemsAfter,'ccp.molecule.MolSystem.MolSystem', func)

    for func in ('__init__', 'delete'):
      notifyFunc(self.updateChainsAfter,'ccp.molecule.MolSystem.Chain', func)

    for func in ('__init__', 'delete','setDynamicAlignment',
                 'setStaticAlignment','setName','setDetails'):
      notifyFunc(self.updateAlignMediaAfter,'ccp.nmr.NmrConstraint.ConditionState', func)

  def updateAlignMediaAfter(self, alignMedium):
  
     if alignMedium.nmrConstraintStore is self.constraintSet:
       self.after_idle(self.updateAlignMedia)
 
       if alignMedium is self.alignMedium:
         self.after_idle(self.updateTensors)

  def updateConstraintSetsAfter(self, constraintSet):
  
     self.after_idle(self.updateConstraintSets)

  def updateShiftListsAfter(self, shiftList):
  
     self.after_idle(self.updateShiftLists)

  def updateMolSystemsAfter(self, molSystem):
  
     self.after_idle(self.updateMolSystems)

  def updateChainsAfter(self, chain):
  
     self.after_idle(self.updateChains)
  
  def updateConstraintsAfter(self, constraint):
  
     if constraint.parent.parent is self.constraintSet:
       self.after_idle(self.updateConstraintLists)
  
  def updateConstraintListsAfter(self, constraintList):
  
     if constraintList.parent is self.constraintSet:
       self.after_idle(self.updateConstraintLists)
    
  def runMeccano(self):
    
    #
    #
    # Input checks first
    #
    #
  
    warning = ''
    if not self.molSystem:
      warning += 'No molecular system selected\n'
    
    if not self.chain:
      warning += 'No chain selected\n'
  
    if not self.constraintSet:
      warning += 'No selected constraint set\n'  
    else:
      constraintLists = [cl for cl in self.constraintSet.constraintLists if cl.useForMeccano]  
      if not constraintLists:
        warning += 'No constraint lists selected for use\n'   
 
    first, last = self.updateResidueRanges()
    if (last-first) < 2:
      warning += 'Too few peptide planes selected\n'         
  
    if warning:
      showWarning('Cannot run MECCANO','Encountered the following problems:\n' + warning)
      return
      
    if not self.run:
      self.run = self.makeSimRun()
      
    self.updateRunParams()
    
    if self.toggleCopyShifts.get() and self.shiftList:
      shiftList = self.run.findFirstOutputMeasurementList(className='ShiftList')
      
      if not shiftList:
        shiftList = self.project.currentNmrProject.newShiftList(name='Meccano Input')
        
      self.run.setOutputMeasurementLists([shiftList,])
    
      shiftDict = {}
      for shift in shiftList.shifts:
        shiftDict[shift.resonance] = shift
      
    
      for shift in self.shiftList.shifts:
        resonance = shift.resonance
        resonanceSet = resonance.resonanceSet
        
        if resonanceSet:
          atom = resonanceSet.findFirstAtomSet().findFirstAtom()
          
          if (atom.name == 'C') and (atom.residue.molResidue.molType == 'protein'):
            shift2 = shiftDict.get(resonance)
            if shift2:
              shift2.value = shift.value
              shift2.error = shift.error
              
            else:
              shiftList.newShift(resonance=resonance, value=shift.value, error=shift.error)  
    
    #
    #
    # Accumulate data from CCPN data model & GUI
    #
    #

    # Sequence

    residues = self.chain.sortedResidues()
    residueDict = {}
    
    seqData = []
    for residue in residues:
      molResidue = residue.molResidue
      
      code1Letter = molResidue.chemComp.code1Letter
      
      if not code1Letter:
        msg = 'Encountered non-standard residue type: %s'
        showWarning('Cannot run MECCANO', msg % residue.ccpCode)
        return
     
      seqCode = residue.seqCode
      seqData.append((seqCode, code1Letter))
      residueDict[seqCode] = residue.chemCompVar.chemComp.code3Letter

    # Media, RDCs & Dihedrals

    rdcLists = []
    dihedralLists = []

    for constraintList in constraintLists:
      if constraintList.className == 'RdcConsraintList':
        if constraintList.conditionState:
          rdcLists.append(constraintList)
      
      elif constraintList.className == 'DihedralConstraintList':
        dihedralLists.append(dihedralLists)
    
    f = PI_OVER_180  
    mediaData = []
    for constraintList in rdcLists:
      medium = constraintList.conditionState
      dynamicTensor = medium.dynamicAlignment
      staticTensor = medium.staticAlignment
    
      if not (dynamicTensor or staticTensor):
        continue
    
      if dynamicTensor:
        dynamicTensorData = ['Dynamic', dynamicTensor.aAxial, dynamicTensor.aRhombic,
                             f*dynamicTensor.alpha, f*dynamicTensor.beta, f*dynamicTensor.gamma]
   
      if staticTensor:
        staticTensorData = ['Static', staticTensor.aAxial, staticTensor.aRhombic,
                            f*staticTensor.alpha, f*staticTensor.beta, f*staticTensor.gamma]
      
      if not dynamicTensor:
        dynamicTensorData = staticTensorData
      
      elif not staticTensor:
        staticTensorData = dynamicTensorData
      
      rdcData = []
      for restraint in constraintList.constraints:
        items = list(restraint.items)
        
        if len(items) != 1:
          continue
          
        resonanceA, resonanceB = [fr.resonance for fr in items[0].resonances] 
        
        resonanceSetA = resonanceA.resonanceSet
        if not resonanceSetA:
          continue
        
        resonanceSetB = resonanceB.resonanceSet
        if not resonanceSetB:
          continue
        
        resNameA = getResonanceName(resonanceA)
        resNameB = getResonanceName(resonanceB)
          
        residueA = resonanceSetA.findFirstAtomSet().findFirstAtom().residue  
        residueB = resonanceSetB.findFirstAtomSet().findFirstAtom().residue  
        
        seqA = residueA.seqCode
        seqB = residueB.seqCode
        
        value = restraint.targetValue
        error = restraint.error
        
        if error is None:
          key = [resNameA,resNameB]
          key.sort()
          sigma = DEFAULT_ERRORS.get(tuple(key), 1.0)
        
        rdcData.append([seqA, resNameA, seqB, resNameB, value, error])
      
      mediaData.append((dynamicTensorData,staticTensorData,rdcData))
      
    oneTurn = 360.0
    dihedralDict = {}
    for constraintList in dihedralLists:
      for restraint in constraintList.constraints:
        items = list(restraint.items)
        
        if len(items) != 1:
          continue
        
        item = items[0]
        resonances = [fr.resonance for fr in item.resonances] 
        
        resonanceSets = [r.resonanceSet for r in resonances]
        
        if None in resonanceSets:
          continue
          
        atoms = [rs.findFirstAtomSet().findFirstAtom() for rs in resonanceSets]  
    
        atomNames = [a.name for a in atoms]
        
        if atomNames == PHI_ATOM_NAMES:
          isPhi = True
        elif atomNames == PSI_ATOM_NAMES:
          isPhi = False
        else:
          continue
    
        residue = atoms[2].residue
        
        if residue.chain is not self.chain:
          continue
        
        if isPhi:
          residuePrev = getLinkedResidue(residue, linkCode='prev')
          
          if not residuePrev:
            continue
            
          atomC0 = residuePrev.findFirstAtom(name='C')
          atomN  = residue.findFirstAtom(name='N')
          atomCa = residue.findFirstAtom(name='CA')
          atomC  = residue.findFirstAtom(name='C')
          atoms2 = [atomC0, atomN, atomCa, atomC]
          
        else:
          residueNext = getLinkedResidue(residue, linkCode='next')
          
          if not residueNext:
            continue
          
          atomN  = residue.findFirstAtom(name='N')
          atomCa = residue.findFirstAtom(name='CA')
          atomC  = residue.findFirstAtom(name='C')
          atomN2 = residueNext.findFirstAtom(name='N')
          atoms2 = [atomN, atomCa, atomC, atomN2]
          
        if atoms != atoms2:
          continue
        
        value = item.targetValue
        error = item.error
        
        if error is None:
          upper = item.upperLimit
          lower = item.lowerLimit
          
          if (upper is not None) and (lower is not None):
            dUpper = angleDifference(value, lower, oneTurn)
            dLower = angleDifference(upper, value, oneTurn)
            error  = max(dUpper, dLower)
            
          elif lower is not None:
            error = angleDifference(value, lower, oneTurn)
            
          elif upper is not None:
            error = angleDifference(upper, value, oneTurn)
            
          else:
            error = 30.0 # Arbitrary, but sensible for TALOS, DANGLE
        
        seqCode = residue.seqCode
        if not dihedralDict.has_key(seqCode):
          dihedralDict[seqCode] = [None, None, None, None] # Phi, Psi, PhiErr, PsiErr
        
        if isPhi:
          dihedralDict[seqCode][0] = value
          dihedralDict[seqCode][2] = error
        else:
          dihedralDict[seqCode][1] = value
          dihedralDict[seqCode][3] = error
          
          
    phipsiData = []
    seqCodes = dihedralDict.keys()
    seqCodes.sort()
    
    for seqCode in seqCodes:
      data = dihedralDict[seqCode]
      
      if None not in data:
        phi, psi, phiErr, psiErr = data
        phipsiData.append((seqCode, phi, psi, phiErr, psiErr))
        
    
    # User options
    
    firstPPlaneFrag = self.firstResEntry.get() or 1
    lastPPlaneFrag  = self.lastResEntry.get() or 1
    ppNbMin         = self.numOptPlaneEntry.get() or 1
    minValueBest    = self.numOptHitsEntry.get() or 2
    maxValueBest    = self.maxOptStepEntry.get() or 5

    strucData = Meccano.runFwd(firstPPlaneFrag, lastPPlaneFrag, ppNbMin,
                               minValueBest, maxValueBest, RAMACHANDRAN_DATABASE,
                               seqData, mediaData, phipsiData)
   
    if strucData:
      fileName = 'CcpnMeccanoPdb%f.pdb' % time.time()
      fileObj = open(fileName, 'w')
 
      ch = self.chain.pdbOneLetterCode.strip()
      if not ch:
        ch = self.chain.code[0].upper()
 
        i = 1
        for atomType, resNb, x, y, z in strucData:
          resType = residueDict.get(resNb, '???')
          line = PDB_FORMAT % ('ATOM',i,'%-3s' % atomType,'',resType,ch,resNb,'',x,y,z,1.0,1.0)
 
          i += 1

      fileObj.close()
      
      ensemble = getStructureFromFile(self.molSystem, fileName)
      
      
      if not self.toggleWritePdbFile.get():
        os.unlink(fileName)
         
      self.run.outputEnsemble = ensemble
      self.run = None
    
    self.updateRuns()

  def getMediumName(self, alignMedium):
  
    self.mediumNameEntry.set(alignMedium.name)
    
  def getMediumDetails(self, alignMedium):
  
    self.mediumDetailsEntry.set(alignMedium.details)
    
  def setMediumName(self, event): 

    value = self.mediumNameEntry.get()
    self.alignMedium.name = value or None
    
  def setMediumDetails(self, event): 

    value = self.mediumDetailsEntry.get()
    self.alignMedium.details = value or None
      
  def setAlignMedium(self, alignMedium):

    if self.constraintSet:
      self.constraintSet.conditionState = alignMedium
    
  def getAlignMedium(self, constraintList):

    media = self.getAlignmentMedia()
    names = [am.name for am in media]
    
    if constraintList.conditionState in media:
      index = media.index(constraintList.conditionState)
    else:
      index = 0
  
    self.alignMediumPulldown.setup(names, media, index)

  def toggleUseRestraints(self, constraintList):
 
    bool = constraintList.useForMeccano
    bool = not bool
 
    if bool and (not constraintList.conditionState) \
     and (constraintList.className == 'RdcConsraintList'):
      msg = 'Cannot use RDC restraint list for Meccano '
      msg += 'unless it is first associated with an amigment medium'
      showWarning('Warning', msg, parent=self)
    else:
      constraintList.useForMeccano = bool
      
    self.updateConstraintLists()
 
  def addStaticTensor(self):
  
    if self.alignMedium:
      tensor = Implementation.SymmTracelessMatrix(aAxial=0.0,aRhombic=0.0,
                                                  alpha=0.0,beta=0.0,
                                                  gamma=0.0)
      

      self.alignMedium.staticAlignment = tensor
 
      self.updateAlignMediaAfter(self.alignMedium)
 
  def addDynamicTensor(self):
  
    if self.alignMedium:
      tensor = Implementation.SymmTracelessMatrix(aAxial=0.0,aRhombic=0.0,
                                                  alpha=0.0,beta=0.0,
                                                  gamma=0.0)
      self.alignMedium.dynamicAlignment = tensor
      
      self.updateAlignMediaAfter(self.alignMedium)
  
  def removeTensor(self):
  
    if self.alignMedium and self.tensor:
      if self.tensor is self.alignMedium.dynamicAlignment:
        self.alignMedium.dynamicAlignment = None
        
      elif self.tensor is self.alignMedium.staticAlignment:
        self.alignMedium.staticAlignment = None
      
      self.updateAlignMediaAfter(self.alignMedium)
        
  def addAlignMedium(self):
  
    if self.constraintSet:
      medium = self.constraintSet.newConditionState()
      medium.name = 'Align Medium %d' % medium.serial   
  
  def removeAlignMedium(self):

    if self.alignMedium:
      self.alignMedium.delete()

  def updateTensor(self, aAxial=None, aRhombic=None, alpha=None, beta=None, gamma=None):
  
    aAxial   = aAxial   or self.tensor.aAxial
    aRhombic = aRhombic or self.tensor.aRhombic
    alpha    = alpha    or self.tensor.alpha
    beta     = beta     or self.tensor.beta
    gamma    = gamma    or self.tensor.gamma
    
    tensor = Implementation.SymmTracelessMatrix(aAxial=aAxial,
                                                aRhombic=aRhombic,
                                                alpha=alpha,beta=beta,
                                                gamma=gamma)
 
    if self.alignMedium:
      if self.tensor is self.alignMedium.dynamicAlignment:
        self.alignMedium.dynamicAlignment = tensor
        
      elif self.tensor is self.alignMedium.staticAlignment:
        self.alignMedium.staticAlignment = tensor
 
    self.tensor = tensor
 
  def setAxial(self, event): 
  
    value = self.editAxialEntry.get()
    self.updateTensor(aAxial=value)
    self.updateTensors()
    
  def setRhombic(self,  event): 
  
    value = self.editRhombicEntry.get()
    self.updateTensor(aRhombic=value)
    self.updateTensors()
   
  def setEulerAlpha(self,  event): 
  
    value = self.editAlphaEulerEntry.get()
    self.updateTensor(alpha=value)
    self.updateTensors()
    
  def setEulerBeta(self,  event): 
  
    value = self.editBetaEulerEntry.get()
    self.updateTensor(beta=value)
    self.updateTensors()
    
  def setEulerGamma(self,  event): 
  
    value = self.editGammaEulerEntry.get()
    self.updateTensor(gamma=value)
    self.updateTensors()

  def getAxial(self, tensor): 
  
    value = tensor.aAxial
    self.editAxialEntry.set(value)
     
  def getRhombic(self, tensor): 
  
    value = tensor.aRhombic
    self.editRhombicEntry.set(value)
     
  def getEulerAlpha(self, tensor): 
  
    value = tensor.alpha
    self.editAlphaEulerEntry.set(value)
     
  def getEulerBeta(self, tensor): 
  
    value = tensor.beta
    self.editBetaEulerEntry.set(value)
     
  def getEulerGamma(self, tensor): 
  
    value = tensor.gamma
    self.editGammaEulerEntry.set(value)
 
  def selectTensor(self, tensor, row, col):
  
    self.tensor = tensor
 
  def selectAlignMedium(self, alignMedium, row, col):
  
    self.alignMedium = alignMedium
    self.updateTensors()
 
  def getAlignmentMedia(self):
  
    if self.constraintSet:
      return self.constraintSet.sortedConditionStates()
    else:
      return []
 
  def updateAlignMedia(self):

    textMatrix = []
    objectList = []
    
    if self.constraintSet:
      objectList = self.getAlignmentMedia()
        
      for conditionState in objectList:
         
         staticTensor = None
         dyamicTensor = None
         tensor = conditionState.dynamicAlignment
         if tensor:
           vals = (tensor.aAxial, tensor.aRhombic, tensor.alpha, tensor.beta, tensor.gamma)
           dyamicTensor = u'\u03B6:%.3f \u03B7:%.3f \u03B1:%.3f \u03B2:%.3f \u03B3:%.3f ' % vals

         tensor = conditionState.staticAlignment
         if tensor:
           vals = (tensor.aAxial, tensor.aRhombic, tensor.alpha, tensor.beta, tensor.gamma)
           staticTensor = u'\u03B6:%.3f \u03B7:%.3f \u03B1:%.3f \u03B2:%.3f \u03B3:%.3f ' % vals
           
         datum = [conditionState.serial,
                  conditionState.name,
                  conditionState.details,
                  dyamicTensor,
                  staticTensor]
         textMatrix.append(datum)

         if dyamicTensor or staticTensor:
           if not self.alignMedium:
             self.alignMedium = conditionState
   
    self.mediaMatrix.update(textMatrix=textMatrix, objectList=objectList)
      
    if self.alignMedium:
      self.mediaMatrix.selectObject(self.alignMedium)
 
  def updateTensors(self):
    
    textMatrix = []
    objectList = []
    conditionState = self.alignMedium
    
    if conditionState:
    
      tensor = conditionState.dynamicAlignment
      if tensor:
        datum = ['Dynamic', tensor.aAxial, tensor.aRhombic,
                 tensor.alpha, tensor.beta, tensor.gamma]
        textMatrix.append(datum)
        objectList.append(tensor)
      
      tensor = conditionState.staticAlignment
      if tensor:
        datum = ['Static', tensor.aAxial, tensor.aRhombic,
                 tensor.alpha, tensor.beta, tensor.gamma]
        textMatrix.append(datum)
        objectList.append(tensor)

    self.tensorMatrix.update(textMatrix=textMatrix, objectList=objectList)  
 
  def getMolSystems(self):
  
    molSystems = []
    
    for molSystem in self.project.sortedMolSystems():
      if molSystem.chains:
        molSystems.append(molSystem)
        
    return molSystems    
     
     
  def updateMolSystems(self, *notifyObj):
  
    index = 0
    names = []
    
    molSystems = self.getMolSystems()
    molSystem = self.molSystem
    
    if molSystems:
      if molSystem not in molSystems:
        molSystem = molSystems[0]
      
      index = molSystems.index(molSystem)
      names = [ms.code for ms in molSystems] 
    
    else:
      self.molSystem = None
    
    if self.molSystem is not molSystem:
      if self.run:
        self.run.molSystem = molSystem
        
      self.molSystem = molSystem
      self.updateChains()
    
    self.molSystemPulldown.setup(texts=names, objects=molSystems, index=index)
    
  
  def selectMolSystem(self, molSystem):
  
    if self.molSystem is not molSystem:
      if self.run:
        self.run.molSystem = molSystem
        
      self.molSystem = molSystem
      self.updateChains()
     
     
  def updateChains(self, *notifyObj):
  
    index = 0
    names = []
    chains = []
    chain = self.chain
    
    if self.molSystem:
      chains = [c for c in self.molSystem.sortedChains() if c.residues]
    
    if chains: 
      if chain not in chains:
        chain = chains[0]
        
      index = chains.index(chain)
      names = [c.code for c in chains]
    
    if chain is not self.chain:
      self.chain = chain
      self.updateResidueRanges()
    
    self.chainPulldown.setup(texts=names, objects=chains, index=index)
     
  def selectChain(self, chain):
  
    if chain is not self.chain:
      self.chain = chain
      self.updateResidueRanges()

  def updateResidueRanges(self):
  
    first = self.firstResEntry.get()
    last = self.lastResEntry.get()
    
    if self.chain:
      residues = self.chain.sortedResidues()
      firstSeq = residues[0].seqCode
      lastSeq = residues[-2].seqCode
      
      if first < firstSeq:
        first = firstSeq
     
      if last == first:
        last = lastSeq
      
      elif last > lastSeq:
        last = lastSeq
        
      if first > last:
        last, first = first, last    
      
  
    self.firstResEntry.set(first)
    self.lastResEntry.set(last)
 
    return first, last

  def getConstraintSets(self):
  
    constraintSets = []
    nmrProject = self.project.currentNmrProject
    
    for constraintSet in nmrProject.sortedNmrConstraintStores():
      for constraintList in constraintSet.constraintLists:
        if constraintList.className not in ('ChemShiftConstraintList','somethingElse'):
          constraintSets.append(constraintSet)
          break
    
    return constraintSets
  
  def updateConstraintSets(self, *notifyObj):

    index = 0
    names = []
    constraintSets = self.getConstraintSets()
    constraintSet = self.constraintSet

    if constraintSets:
      if constraintSet not in constraintSets:
        constraintSet = constraintSets[0]
        
      index = constraintSets.index(constraintSet)
      names = ['%d' % cs.serial for cs in constraintSets]
    
    if constraintSet is not self.constraintSet:
      if self.run:
        self.run.inputConstraintStore = constraintSet
    
      self.constraintSet = constraintSet
      self.updateConstraintLists()    
    
    self.constraintSetPulldown.setup(texts=names, objects=constraintSets, index=index)

  def selectConstraintSet(self, constraintSet):
  
    if self.constraintSet is not constraintSet:
      if self.run:
        self.run.inputConstraintStore = constraintSet
        
      self.constraintSet = constraintSet
      self.updateConstraintLists() 
  
  def getConstraintLists(self):
  
    constraintLists = []
    if self.constraintSet:
      for constraintList in self.constraintSet.sortedConstraintLists():
        if constraintList.className not in ('ChemShiftConstraintList','somethingElse'):
          constraintLists.append(constraintList)
  
    return constraintLists
    
  def updateConstraintLists(self, *notifyObj):
  
    textMatrix = []
    objectList = self.getConstraintLists()
    
    for constraintList in objectList:
      if not hasattr(constraintList, 'useForMeccano'):
        if constraintList.conditionState \
         or (constraintList.className != 'RdcConstraintList'):
          bool = True
        else:
          bool = False  
      
        constraintList.useForMeccano = bool
    
      if constraintList.conditionState:
        alignMedium = constraintList.conditionState.name
      else:
        alignMedium = None
    
      datum = [constraintList.serial,
               constraintList.className[:-14],
               constraintList.useForMeccano and 'Yes' or 'No',
               alignMedium,
               len(constraintList.constraints)]
  
      textMatrix.append(datum)
  
    self.restraintMatrix.update(textMatrix=textMatrix, objectList=objectList)
  
  def selectConstraint(self, obj, row, column):
  
    if self.constraint is not obj:
      self.constraint = obj

  def getSimStore(self):
  
    simStore = self.project.findFirstNmrSimStore(name='meccano')
    if not simStore:
      simStore = self.project.newNmrSimStore(name='meccano')
    
    return simStore

  def getRuns(self):
  
    runs = [None, ]
    
    if self.molSystem and self.constraintSet:
      simStore = self.getSimStore()
      runs += simStore.sortedRuns()
    
    return runs
  
  def updateRuns(self, *notifyObj):
  
    index = 0
    names = ['<New>']
    runs = self.getRuns()
    run = self.run

    if runs:
      if run not in runs:
        run = runs[0]
    
      index = runs.index(run)
      names += [r.serial for r in runs if r]
    
    if run is not self.run:
      self.updateConstraintSets()
      self.updateMolSystems()
      self.updateShiftLists()
    
    self.runPulldown.setup(names, runs, index)
  
  def updateRunParams(self, event=None):
  
    if self.run and self.molSystem and self.constraintSet:
      simRun = self.run
      
      simRun.inputConstraintStore = self.constraintSet
      simRun.molSystem = self.molSystem
      
      if self.shiftList:
        simRun.setInputMeasurementLists([self.shiftList,])                 

      simRun.newRunParameter(code='FirstPepPlane',id=1, 
                             intValue=self.firstResEntry.get() or 0)
      simRun.newRunParameter(code='LastPepPlane' ,id=1, 
                             intValue=self.lastResEntry.get() or 0)
      simRun.newRunParameter(code='MaxOptSteps',  id=1, 
                             intValue=self.maxOptStepEntry.get() or 0)
      simRun.newRunParameter(code='NumOptPlanes', id=1, 
                             intValue=self.numOptPlaneEntry.get() or 0)
      simRun.newRunParameter(code='MinOptHits',   id=1, 
                             intValue=self.numOptHitsEntry.get() or 0)
  
  def makeSimRun(self, template=None):

    simStore = self.getSimStore()
   
    if template:
      molSystem = template.molSystem
      constraintSet = template.inputConstraintStore
      shiftList = template.findFirstInputMeasurementList(className='ShiftList')
      protocol = template.annealProtocol
    else:
      molSystem = self.molSystem
      constraintSet = self.constraintSet
      shiftList = self.shiftList
      protocol = self.annealProtocol
    
    simRun = simStore.newRun(annealProtocol=protocol,
                             molSystem=molSystem,
                             inputConstraintStore=protocol)
    
    if shiftList:
      simRun.addInputMeasurementList(shiftList)                 
    
    if template:
      for param in template.runParameters:
        simRun.newRunParameter(code=param.code,
                               id=param.id,
                               booleanValue=param.booleanValue,
                               floatValue=param.floatValue,
                               intValue=param.intValue,
                               textValue=param.textValue)
    else:
       if self.chain:
         chainCode = self.chain.code
       else:
         chaincode = 'A'
    
       simRun.newRunParameter(code='FirstPepPlane',id=1, 
                              intValue=self.firstResEntry.get() or 0)
       simRun.newRunParameter(code='LastPepPlane' ,id=1, 
                              intValue=self.lastResEntry.get() or 0)
       simRun.newRunParameter(code='MaxOptSteps',  id=1, 
                              intValue=self.maxOptStepEntry.get() or 0)
       simRun.newRunParameter(code='NumOptPlanes', id=1, 
                              intValue=self.numOptPlaneEntry.get() or 0)
       simRun.newRunParameter(code='MinOptHits',   id=1, 
                              intValue=self.numOptHitsEntry.get() or 0)
       simRun.newRunParameter(code='ChainCode',    id=1,
                              textValue=chainCode)

    return simRun
 
  def selectRun(self, simRun):
  
    if self.run is not simRun:
      if simRun:
        if simRun.outputEnsemble:
          msg  = 'Selected run has already been used to generate a structure.'
          msg += 'A new run will be setup based on the selection.'
          showWarning('Warning',msg)
          simRun = self.makeSimRun(template=simRun)
 
        molSystem = simRun.molSystem
        constraintSet = simRun.inputConstraintStore
        shiftList = simRun.findFirstInputMeasurementList(className='ShiftList')
 
        if molSystem and (self.molSystem is not molSystem):
          self.molSystem = molSystem
          self.updateMolSystems()
 
        if constraintSet and (self.constraintSet is not constraintSet):
          self.constraintSet = constraintSet
          self.updateConstraintSets()
    
        if shiftList and (self.shiftList is not shiftList): 
          self.shiftList = shiftList
          self.updateShiftLists()
        
        firstPepPlane = simRun.findFirstrunParameter(code='FirstPepPlane')
        lastPepPlane = simRun.findFirstrunParameter(code='LastPepPlane')
        maxOptSteps = simRun.findFirstrunParameter(code='MaxOptSteps')
        numOptPlanes = simRun.findFirstrunParameter(code='NumOptPlanes')
        minOptHits = simRun.findFirstrunParameter(code='MinOptHits')
        chainCode = simRun.findFirstrunParameter(code='ChainCode')

        
        if firstPepPlane is not None:
          self.firstResEntry.set(firstPepPlane.intValue or 0)
        
        if lastPepPlane is not None:
          self.lastResEntry.set(lastPepPlane.intValue or 0)
          
        if maxOptSteps is not None:
          self.maxOptStepEntry.set(maxOptSteps.intValue or 0)
            
        if numOptPlanes is not None:
          self.numOptPlaneEntry.set(numOptPlanes.intValue or 0)
          
        if minOptHits is not None:
          self.numOptHitsEntry.set(minOptHits.intValue or 0)
           
        if chainCode is not None:
          chainCode = chainCode.textValue or 'A'
          if self.molSystem:
            chain = self.molSystem.findFirsChain(code=chainCode)
 
            if chain:
              self.selectChain(chain) 
                 
      self.run = simRun

  def updateShiftLists(self, *notifyObj):
    
    index = 0
    names = []
    nmrProject = self.project.currentNmrProject
    
    shiftLists = nmrProject.findAllMeasurementLists(className='ShiftList')
    shiftLists = [(sl.serial, sl) for sl in shiftLists]
    shiftLists.sort()
    shiftLists = [x[1] for x in shiftLists]
    
    shiftList = self.shiftList

    if shiftLists:
      if shiftList not in shiftLists:
        shiftList = shiftLists[0]
    
      index = shiftLists.index(shiftList)
      names = ['%d'% sl.serial for sl in shiftLists]
    
    if shiftList is not self.shiftList:
      if self.run:
        self.run.setInputMeasurementLists([shiftList])
  
    self.shiftListPulldown.setup(texts=names, objects=shiftLists, index=index)

  def selectShiftList(self, shiftList):
  
    if shiftList is not self.shiftList:
      if self.run:
        self.run.setInputMeasurementLists([shiftList])
      
      self.shiftList = shiftList                   
예제 #29
0
class AssignMentTransferTab(object):
    '''the tab in the GUI where assignments
       can be transferred in bulk to the ccpn analysis
       project. A difference is made between two types
       of assignments:
           1) spin systems to residues, which also
              implies resonanceSets to atomSets.
           2) resonances to peak dimensions.
       The user is able to configure which assignments
       should be transferred to the project.

      Attributes:

          guiParent: gui object this tab is part of.

          frame: the frame in which this element lives.

          dataModel(src.cython.malandro.DataModel): dataModel
              object describing the assignment proposed by
              the algorithm.

          selectedSolution (int): The index of the solution/run
              that is used asa the template to make the assignments.

          resonanceToDimension (bool): True if resonances should
              be assigned to peak dimensions. False if not.

          spinSystemToResidue (bool): True if spin system to
              residue assignment should be carried out.

          minScore (float): The minimal score of a spin system
              assignment to a residue to be allowed
              to transfer this assignment to the project

          intra (bool): True if intra-residual peaks should be
              assigned.

          sequential (bool): True if sequential peaks should be
              assigned.

          noDiagonal (bool): If True, purely diagonal peaks are
              ignored during the transfer of assignments.

          allSpectra (bool): If True, all spectra will be assigned.
              If False, one specified spectrum will be assigned.

          spectrum (src.cython.malandro.Spectrum): The spectrum
              that should be assigned.
    '''

    def __init__(self, parent, frame):
        '''Init. args: parent: the guiElement that this
                               tab is part of.
                       frame:  the frame this part of the
                               GUI lives in.
        '''

        self.guiParent = parent
        self.frame = frame

        # Buttons and fields,
        # will be set in body():
        self.peaksCheckButton = None
        self.residuesCheckButton = None
        self.intraCheckButton = None
        self.sequentialCheckButton = None
        self.noDiagonalCheckButton = None
        self.spinSystemTypeSelect = None
        self.minScoreEntry = None
        self.solutionNumberEntry = None
        self.spectrumSelect = None
        self.spectraPullDown = None
        self.assignedResidueStrategySelect = None
        self.transferButton = None

        # Settings that determine how assignments
        # are transferred to the analysis project:
        self.minScore = 80.0
        self.dataModel = None
        self.spectrum = None
        self.selectedSolution = 1
        self.body()
        self.resonanceToDimension = True
        self.spinSystemToResidue = True
        self.intra = True
        self.sequential = True
        self.noDiagonal = True
        self.allSpectra = True
        self.spinSystemType = 0
        self.strategy = 0


    def body(self):
        '''Describes the body of this tab. It consists
           out of a number of radio buttons, check buttons
           and number entries that allow the user to
           indicate which assignments should be transferred.
        '''

        # self.frame.expandColumn(0)
        self.frame.expandGrid(8, 0)
        self.frame.expandGrid(8, 1)

        typeOfAssignmentFrame = LabelFrame(
            self.frame, text='type of assignment')
        typeOfAssignmentFrame.grid(row=0, column=0, sticky='nesw')
        # typeOfAssignmentFrame.expandGrid(0,5)

        peakSelectionFrame = LabelFrame(
            self.frame, text='which peaks to assign')
        peakSelectionFrame.grid(row=0, column=1, sticky='nesw', rowspan=2)

        spinSystemSelectionFrame = LabelFrame(self.frame,
                                              text='Which spin-systems to use')
        spinSystemSelectionFrame.grid(row=2, column=0, sticky='nesw')

        tipText = 'What to do when a residue has already a spin system assigned to it.'
        assignedResidueFrame = LabelFrame(self.frame,
                                          text='if residue already has spin-system',
                                          tipText=tipText)
        assignedResidueFrame.grid(row=2, column=1, sticky='nesw')

        spectrumSelectionFrame = LabelFrame(self.frame, text='spectra')
        spectrumSelectionFrame.grid(row=1, column=0, sticky='nesw')

        row = 0

        Label(typeOfAssignmentFrame,
              text='Resonances to Peak Dimensions',
              grid=(row, 0))
        self.peaksCheckButton = CheckButton(typeOfAssignmentFrame,
                                            selected=True,
                                            grid=(row, 1))

        row += 1

        Label(typeOfAssignmentFrame,
              text='SpinSystems to Residues',
              grid=(row, 0))
        self.residuesCheckButton = CheckButton(
            typeOfAssignmentFrame, selected=True, grid=(row, 1))

        row = 0

        Label(peakSelectionFrame, text='Intra-Residual', grid=(row, 0))
        self.intraCheckButton = CheckButton(
            peakSelectionFrame, selected=True, grid=(row, 1))

        row += 1

        Label(peakSelectionFrame, text='Sequential', grid=(row, 0))
        self.sequentialCheckButton = CheckButton(
            peakSelectionFrame, selected=True, grid=(row, 1))

        row += 1

        Label(peakSelectionFrame,
              text='Do not assign diagonal peaks',
              grid=(row, 0))
        self.noDiagonalCheckButton = CheckButton(
            peakSelectionFrame, selected=True, grid=(row, 1))

        entries = ['Only assigned spin systems',
                   'All that have a score of at least: ',
                   'User Defined',
                   'Solution number:']
        tipTexts = ['Only assign resonances of spin systems that already have a sequential assignment for the assignment of peak dimensions. Spin system to residue assignment is not relevant in this case.',
                    'Assign all spin systems that have a score of at least a given percentage. 50% or lower is not possible, because than spin systems might have to be assigned to more than 1 residue, which is impossible.',
                    "As defined in the lower row of buttons in the 'results' tab.",
                    'One of the single solutions of the annealing.']
        self.spinSystemTypeSelect = RadioButtons(spinSystemSelectionFrame,
                                                 entries=entries, grid=(0, 0),
                                                 select_callback=None,
                                                 direction=VERTICAL,
                                                 gridSpan=(4, 1),
                                                 tipTexts=tipTexts)

        tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.'
        self.minScoreEntry = FloatEntry(spinSystemSelectionFrame,
                                        grid=(1, 1), width=7,
                                        text=str(self.minScore),
                                        returnCallback=self.changeMinScore,
                                        tipText=tipText)
        self.minScoreEntry.bind('<Leave>', self.changeMinScore, '+')

        self.solutionNumberEntry = IntEntry(spinSystemSelectionFrame,
                                            grid=(3, 1), width=7, text=1,
                                            returnCallback=self.solutionUpdate,
                                            tipText=tipText)
        self.solutionNumberEntry.bind('<Leave>', self.solutionUpdate, '+')

        #self.solutionPullDown = PulldownList(spinSystemSelectionFrame, None, grid=(3,1), sticky='w')

        entries = ['all spectra', 'only:']
        tipTexts = ['Assign peaks in all the spectra that where selected before the annealing ran.',
                    'Only assign peaks in one particular spectrum. You can of course repeat this multiple times for different spectra.']
        self.spectrumSelect = RadioButtons(spectrumSelectionFrame,
                                           entries=entries,
                                           grid=(0, 0),
                                           select_callback=None,
                                           direction=VERTICAL,
                                           gridSpan=(2, 1), tipTexts=tipTexts)

        self.spectraPullDown = PulldownList(spectrumSelectionFrame,
                                            self.changeSpectrum,
                                            grid=(1, 1), sticky='w')

        entries = ['skip this residue',
                   'de-assign old spin system from residue',
                   'assign, but never merge',
                   'warn to merge']
        tipTexts = ["Don't assign the new spin system to the residue. The residue is not skipped when the old spin system does not contain any resonances",
                    "De-assign old spin system from residue, unless the old spin system is a spin system without any resonances.",
                    "Don't merge any spin systems, merging can be performed later if nescesary in the Resonance --> SpinSystems window.",
                    "Ask to merge individually for each spin system, this might result in clicking on a lot of popups."]
        self.assignedResidueStrategySelect = RadioButtons(assignedResidueFrame,
                                                          entries=entries,
                                                          grid=(0, 0),
                                                          select_callback=None,
                                                          direction=VERTICAL,
                                                          gridSpan=(2, 1),
                                                          tipTexts=tipTexts)

        texts = ['Transfer Assignments']
        commands = [self.transferAssignments]
        self.transferButton = ButtonList(
            self.frame, commands=commands, texts=texts)
        self.transferButton.grid(row=5, column=0, sticky='nsew', columnspan=2)

    def update(self):
        '''Update the nescesary elements in the
           tab. Is called when the algorithm
           has produced possible assignments.
           The only thing that has to be updated
           in practice in this tab is the pulldown
           with spectra.
        '''

        self.dataModel = self.guiParent.connector.results
        self.updateSpectra()

    def setDataModel(self, dataModel):
        '''Here the dataModel, which is the dataModel
           containing the suggested assignments body
           the algorithm, can be set.
        '''

        self.dataModel = dataModel
        self.update()

    def updateSpectra(self, *opt):
        '''Updates the spectra shown in the spectra
           pulldown. These are only the spectra that
           were used by the algorithm. All other spectra
           in the project are not relevant since for those
           no simulated peaks have been matched to real
           peaks.
        '''

        if not self.dataModel:

            return

        spectrum = self.spectrum

        spectra = self.dataModel.getSpectra()

        if spectra:

            names = [spectrum.name for spectrum in spectra]
            index = 0

            if self.spectrum not in spectra:

                self.spectrum = spectra[0]

            else:

                index = spectra.index(self.spectrum)

        self.spectraPullDown.setup(names, spectra, index)

    def changeSpectrum(self, spectrum):
        '''Select a spectum to be assigned.'''

        self.spectrum = spectrum

    def solutionUpdate(self, event=None, value=None):
        '''Select a solution. A solution is a
           one to one mapping of spin systems
           to residues produced by one run of
           the algorithm.
               args: event: event object, this is
                            one of the values the number
                            entry calls his callback
                            function with.
                     value: the index of the solution/run.
        '''

        if not self.dataModel:

            return

        Nsolutions = len(self.dataModel.chain.residues[0].solutions)

        if value is None:

            value = self.solutionNumberEntry.get()

        if value == self.selectedSolution:
            return
        else:
            self.selectedSolution = value
        if value < 1:
            self.solutionNumberEntry.set(1)
            self.selectedSolution = 1
        elif value > Nsolutions:
            self.selectedSolution = Nsolutions
            self.solutionNumberEntry.set(self.selectedSolution)
        else:
            self.solutionNumberEntry.set(self.selectedSolution)

    def fetchOptions(self):
        '''Fetches user set options from the gui in
           one go and stores them in their corresponding
           instance variables.
        '''

        self.resonanceToDimension = self.peaksCheckButton.get()
        self.spinSystemToResidue = self.residuesCheckButton.get()
        self.intra = self.intraCheckButton.get()
        self.sequential = self.sequentialCheckButton.get()
        self.noDiagonal = self.noDiagonalCheckButton.get()
        self.spinSystemType = self.spinSystemTypeSelect.getIndex()
        self.strategy = ['skip', 'remove', 'noMerge', None][
            self.assignedResidueStrategySelect.getIndex()]
        self.allSpectra = [True, False][self.spectrumSelect.getIndex()]

    def changeMinScore(self, event=None):
        '''Set the minimal score for which a spin system
           to residue assignment gets transferred to the
           ccpn analysis project.
        '''

        newMinScore = self.minScoreEntry.get()

        if self.minScore != newMinScore:

            if newMinScore <= 50.0:

                self.minScore = 51.0
                self.minScoreEntry.set(51.0)

            elif newMinScore > 100.0:

                self.minScore = 100.0
                self.minScoreEntry.set(100.0)

            else:

                self.minScore = newMinScore

    def transferAssignments(self):
        '''Transfer assignments to project depending
           on the settings from the GUI.
        '''

        self.fetchOptions()

        if not self.dataModel or (not self.resonanceToDimension and not self.spinSystemToResidue):

            return

        strategy = self.strategy

        lookupSpinSystem = [self.getAssignedSpinSystem,
                            self.getBestScoringSpinSystem,
                            self.getUserDefinedSpinSystem,
                            self.getSelectedSolutionSpinSystem][self.spinSystemType]

        residues = self.dataModel.chain.residues

        spinSystemSequence = [lookupSpinSystem(res) for res in residues]

        ccpnSpinSystems = []
        ccpnResidues = []

        # if self.spinSystemType == 0 it means that it for sure already
        # assigned like this
        if self.spinSystemToResidue and not self.spinSystemType == 0:

            for spinSys, res in zip(spinSystemSequence, residues):

                if spinSys and res:

                    ccpnSpinSystems.append(spinSys.getCcpnResonanceGroup())
                    ccpnResidues.append(res.getCcpnResidue())

            assignSpinSystemstoResidues(ccpnSpinSystems,
                                        ccpnResidues,
                                        strategy=strategy,
                                        guiParent=self.guiParent)

        if self.resonanceToDimension:

            allSpectra = self.allSpectra

            if self.intra:

                for residue, spinSystem in zip(residues, spinSystemSequence):

                    if not spinSystem:

                        continue

                    intraLink = residue.getIntraLink(spinSystem)

                    for pl in intraLink.getPeakLinks():

                        peak = pl.getPeak()

                        if not allSpectra and peak.getSpectrum() is not self.spectrum:

                            continue

                        if not peak:

                            continue

                        resonances = pl.getResonances()

                        if self.noDiagonal and len(set(resonances)) < len(resonances):

                            continue

                        for resonance, dimension in zip(resonances, peak.getDimensions()):

                            ccpnResonance = resonance.getCcpnResonance()
                            ccpnDimension = dimension.getCcpnDimension()
                            assignResToDim(ccpnDimension, ccpnResonance)

            if self.sequential:

                for residue, spinSystemA, spinSystemB in zip(residues,
                                                             spinSystemSequence,
                                                             spinSystemSequence[1:]):

                    if not spinSystemA or not spinSystemB:

                        continue

                    link = residue.getLink(spinSystemA, spinSystemB)

                    for pl in link.getPeakLinks():

                        peak = pl.getPeak()

                        if not allSpectra and peak.getSpectrum() is not self.spectrum:

                            continue

                        if not peak:

                            continue

                        resonances = pl.getResonances()

                        if self.noDiagonal and len(set(resonances)) < len(resonances):

                            continue

                        for resonance, dimension in zip(resonances, peak.getDimensions()):

                            ccpnResonance = resonance.getCcpnResonance()
                            ccpnDimension = dimension.getCcpnDimension()

                            assignResToDim(ccpnDimension, ccpnResonance)

        self.guiParent.resultsTab.update()

    def getAssignedSpinSystem(self, residue):
        '''Get the spinSystem that is assigned in the project
           to a residue.
           args:  residue (src.cython.malandro.Residue)
           return: spinSystem (src.cython.malandro.SpinSystem)
        '''

        ccpCode = residue.ccpCode
        seqCode = residue.getSeqCode()
        spinSystems = self.dataModel.getSpinSystems()[ccpCode]

        ccpnResidue = residue.getCcpnResidue()
        if ccpnResidue:
            assignedResonanceGroups = ccpnResidue.getResonanceGroups()
            if len(assignedResonanceGroups) > 1:
                print 'There is more than one spin system assigned to residue %s, did not know which one to use to assign peaks. Therefor this residue is skipped.' % (seqCode)
                return

            assignedResonanceGroup = ccpnResidue.findFirstResonanceGroup()

            if assignedResonanceGroup:

                for spinSystem in spinSystems:

                    if spinSystem.getSerial() == assignedResonanceGroup.serial:
                        # Just checking to make sure, analysis project could
                        # have changed
                        if not self.skipResidue(residue, spinSystem):

                            return spinSystem

    def getBestScoringSpinSystem(self, residue):
        '''Get the spinSystem that scores the highest,
           i.e. is assigned in most of the runs to the
           given residue.
           args:  residue (src.cython.malandro.Residue)
           return: spinSystem (src.cython.malandro.SpinSystem)
        '''

        solutions = residue.solutions
        weigth = 1.0 / len(solutions)
        score, bestSpinSystem = max([(solutions.count(solution) * weigth * 100.0, solution) for solution in solutions])

        if score >= self.minScore and not bestSpinSystem.getIsJoker() and not self.skipResidue(residue, bestSpinSystem):

            return bestSpinSystem

        return None

    def getUserDefinedSpinSystem(self, residue):
        '''Get the spinSystem that is defined by the user
           (probably in the resultsTab) as the correct
           assignment of the given residue.
           args:  residue (src.cython.malandro.Residue)
           return: spinSystem (src.cython.malandro.SpinSystem)
        '''

        userDefinedSpinSystem = residue.userDefinedSolution

        if userDefinedSpinSystem and not userDefinedSpinSystem.getIsJoker() and not self.skipResidue(residue, userDefinedSpinSystem):

            return userDefinedSpinSystem

        return None

    def getSelectedSolutionSpinSystem(self, residue):
        '''I a solution corresponding to one specific run
           of the algorithm is defined, return which spinSystem
           in that run got assigned to the given residue.
           args:  residue (src.cython.malandro.Residue)
           return: spinSystem (src.cython.malandro.SpinSystem)
        '''

        solutions = residue.solutions

        spinSystem = solutions[self.selectedSolution - 1]

        if not spinSystem.getIsJoker() and not self.skipResidue(residue, spinSystem):

            return spinSystem

        return None

    def skipResidue(self, residue, spinSystem):
        '''One strategy is to skip all residues that
           already have a spin system assignment.
           If that is the case determine whether to
           skip the given residue.
           args: residue (src.cython.malandro.Residue)
                 spinSystem (src.cython.malandro.SpinSystem)
           return: boolean, True if residue should be skipped.
        '''

        if self.strategy == 0:

            assignedGroups = residue.getCcpnResidue().getResonanceGroups()
            assignedSerials = set([spinSys.serial for spinSys in assignedGroups])

            if assignedSerials and spinSystem.getSerial() not in assignedSerials:

                return True

        return False
예제 #30
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()
예제 #31
0
class CalcHeteroNoePopup(BasePopup):
  """
  **Calculate Heteronuclear NOE Values From Peak Intensities**
  
  The purpose of this popup window is to calculate the heteronuclear NOE for
  amide resonances based upon a comparison of the peak intensities in spectra
  that derive from an NOE saturated experiment and an unsaturated (reference)
  experiment. The basic idea of this tool is that three peak lists are chosen,
  two of which are for heteronuclear NOE experiments (H,N axes); unsaturated
  reference and saturated, and one which is the source of assignments and peak
  locations. This last "Assignment" peak list may be the same as one of the NOE
  peak lists, but may also be entirely separate.

  The "Assignment" peak list is used to specify which peak assignments and
  locations should be used for the calculation of the heteronuclear NOE values,
  and thus can be used to specify only a subset of the resonances for
  measurement. For example, it is common to copy an HQSC peak list for use as
  the "Assignment" peak list but remove overlapped and NH2 peaks so that the NOE
  values are only calculated for separated backbone amides. The calculation
  process involves taking each of these assigned peaks and finding peaks with
  the same assignment in the NOE peak lists, or if that fails finding peaks with
  a similar position (within the stated tolerances); new peaks may be picked if
  the "Pick new peaks?" option is set.

  The first "Peak Lists & Settings" tab allows the user to choose the peak lists
  and various options that will be used in the peak-finding and NOE calculation.
  The "Peaks" table allows the peaks from each of the three peak list selections
  to be displayed when one of the "Show" buttons is clicked. The [Separate Peak
  Table] function allows these peaks to be displayed in the main, separate `Peak
  Lists`_ table, which has many more peak manipulation options. The options
  below the table may be used to locate selected peaks within the spectrum
  window displays.

  The second "Peak Intensity Comparison" tab is where the heteronuclear NOE
  values are actually calculated. Assuming that two NOE experiment peak lists
  have been chosen and that some of their peaks match the assigned peak
  positions then the peak intensities are extracted and NOE values automatically
  calculated when the tab is opened. Although, a refresh of the table can be
  forced with [Find Matching Peaks] at the bottom

  If pairs of NOE saturated and reference peaks are found then the actual
  heteronuclear NOE value is displayed as the "Intensity Ratio" in the last,
  rightmost, column of the table. To store these values as a NOE measurement
  list; so that the data can be saved in the CCPN project without need for
  recalculation, the [Create Hetero NOE List] function can be used. The results
  are then available to view at any time via the `Measurement Lists`_ table.

  **Caveats & Tips**

  Erroneous peak intensity comparisons may be removed with the [Remove Pairs]
  function, but its is common to curate the "Assign" peak list first and
  avoid tidying afterwards.

  The "Closeness score" can be used to find peak positions where the compared
  NOE peaks are unexpectedly far from one another.

  .. _`Peak Lists`: EditPeakListsPopup.html
  .. _`Measurement Lists`: EditMeasurementListsPopup.html
  
  """

  def __init__(self, parent, *args, **kw):

    self.guiParent      = parent
    self.peakPairs      = []
    self.intensityType  = 'height'
    self.selectedPair   = None
    self.assignPeakList = None
    self.refPeakList    = None
    self.satPeakList    = None
    self.displayPeakList = None
    self.waiting        = 0
  
    BasePopup.__init__(self, parent, title="Data Analysis : Heteronuclear NOE", **kw)

  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 administerNotifiers(self, notifyFunc):

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

    for func in ('__init__', 'delete','setAnnotation','setFigOfMerit'):
      notifyFunc(self.updatePeaks, 'ccp.nmr.Nmr.Peak', func)
    for func in ('setAnnotation','setPosition','setNumAliasing'):
      notifyFunc(self.updatePeakChild, 'ccp.nmr.Nmr.PeakDim', func)
    for func in ('__init__', 'delete', 'setValue'):
      notifyFunc(self.updatePeakChild, 'ccp.nmr.Nmr.PeakIntensity', func)

  def changeTab(self, index):
  
    if index == 1:
      self.matchPeaks()

  def open(self):
  
    self.updatePulldowns()
    self.updateAfter()
    BasePopup.open(self)
    
    
  def destroy(self):
  
    self.administerNotifiers(self.unregisterNotify)

    BasePopup.destroy(self)
 
  def updatePulldowns(self, *obj):

    index0 = 0
    index1 = 0
    index2 = 0
    names, peakLists = self.getPeakLists()
    
    if names:

      if self.refPeakList not in peakLists:
        self.refPeakList = peakLists[0]

      if  self.satPeakList not in peakLists:
        self.satPeakList = peakLists[0]

      if self.assignPeakList not in peakLists:
        self.assignPeakList = peakLists[0]

      index0 = peakLists.index(self.refPeakList)
      index1 = peakLists.index(self.satPeakList)
      index2 = peakLists.index(self.assignPeakList)
    
    self.specAPulldown.setup(names, peakLists, index0)
    self.specBPulldown.setup(names, peakLists, index1)
    self.specCPulldown.setup(names, peakLists, index2)

  def updatePeakChild(self,peakChild):
  
    if self.waiting:
      return
    
    self.updatePeaks(peakChild.peak)
  
  def updatePeaks(self, peak):
  
    if self.waiting:
      return
    
    if peak.peakList in (self.refPeakList,self.satPeakList,self.assignPeakList):
      if peak.isDeleted and (peak.peakList in (self.refPeakList,self.satPeakList) ):
        for peaks in self.peakPairs:
          if peak in peaks:
            self.peakPairs.remove(peaks)
            if self.selectedPair is peaks:
              self.selectedPair = None
            self.updateAfter()
            return
            
      self.updateAfter()
 
  def setIntensityType(self, intensityType):
    
    self.intensityType = intensityType
    self.updateAfter()
  
  def viewRefPeakList(self):
  
    if self.refPeakList:
      self.updatePeakTable(self.refPeakList)
   
  def viewSatPeakList(self):
  
    if self.satPeakList:
      self.updatePeakTable(self.satPeakList)
  
  def viewAssignPeakList(self):
  
    if self.assignPeakList:
      self.updatePeakTable(self.assignPeakList)
  
  def viewSeparatePeakTable(self):
  
    if self.displayPeakList:
      self.guiParent.editPeakList(peakList=self.displayPeakList)
  
  def setRefPeakList(self, refPeakList):
  
    if self.displayPeakList is self.refPeakList:
      self.updatePeakTable(refPeakList)

    self.refPeakList = refPeakList
    self.updateViewButtons()
    self.updateAfter()
  
  def setSatPeakList(self, satPeakList):
  
    if self.displayPeakList is self.satPeakList:
      self.updatePeakTable(satPeakList)
      
    self.satPeakList = satPeakList
    self.updateViewButtons()
    self.updateAfter()
  
  def setAssignPeakList(self, assignPeakList):
  
    if self.displayPeakList is self.assignPeakList:
      self.updatePeakTable(assignPeakList)
      
    self.assignPeakList = assignPeakList
    self.updateViewButtons()
    self.updateAfter()
  
  def getPeakListName(self, peakList):
  
    if peakList:
      spectrum = peakList.dataSource
      experiment = spectrum.experiment
      name = '%s:%s:%d' % (experiment.name, spectrum.name, peakList.serial)
    else:
      name = '<None>'
  
    return name
  
  def getPeakLists(self):
  
    names = []
    peakLists = []
    
    for experiment in self.nmrProject.sortedExperiments():
      for dataSource in experiment.sortedDataSources():
        if dataSource.numDim == 2:
          dimsN = findSpectrumDimsByIsotope(dataSource,'15N')
          dimsH = findSpectrumDimsByIsotope(dataSource,'1H')
          if len(dimsN) == 1 and len(dimsH) == 1:
            for peakList in dataSource.sortedPeakLists():
              name = self.getPeakListName(peakList)
              names.append( name )
              peakLists.append(peakList)
    
    return names, peakLists
  
  def showPeakPair(self):
  
    if self.selectedPair:
      self.guiParent.viewPeaks(self.selectedPair)
          
  def selectCell(self, object, row, col):
  
    self.selectedPair = object

    if self.selectedPair:
      self.pairButtons.buttons[1].enable()
      self.pairButtons.buttons[2].enable()
    else:
      self.pairButtons.buttons[1].disable()
      self.pairButtons.buttons[2].disable()
  
  def removePair(self, *event):
  
    pairs = self.scrolledMatrix.currentObjects
    
    if pairs:
      for pair in pairs:
        self.peakPairs.remove(pair)
        
      self.selectedPair = None
      self.updateAfter()
  
  def matchPeaks(self):
  
    # assign relative to reference
    
    if self.assignPeakList and self.assignPeakList.peaks and self.refPeakList and self.satPeakList:
 
      tolH = float( self.tolHEntry.get() )
      tolN = float( self.tolNEntry.get() )
      pickNewPeaks = self.pickPeaksSelect.get()
      doAssign     = self.assignSelect.get()
 
      dimH  = findSpectrumDimsByIsotope(self.assignPeakList.dataSource,'1H' )[0]
      dimHA = findSpectrumDimsByIsotope(self.refPeakList.dataSource,'1H' )[0]
      dimHB = findSpectrumDimsByIsotope(self.satPeakList.dataSource,'1H' )[0]
      dimN  = 1-dimH
      dimNA = 1-dimHA
      dimNB = 1-dimHB
 
      tolerancesA = [0,0]
      tolerancesA[dimHA] = tolH
      tolerancesA[dimNA] = tolN

      tolerancesB = [0,0]
      tolerancesB[dimHB] = tolH
      tolerancesB[dimNB] = tolN
 
      self.peakPairs = matchHnoePeaks(self.assignPeakList,self.refPeakList,
                                      self.satPeakList,tolerancesA,tolerancesB,
                                      pickNewPeaks,doAssign)
 
      self.updateAfter()
 
  def makeNoeList(self):

    if self.refPeakList is self.satPeakList:
      showWarning('Same Peak List',
                  'Ref Peak List and Sat Peak List cannot be the same',
                  parent=self)
      return

    if self.peakPairs:
      s1 = self.refPeakList.dataSource
      s2 = self.satPeakList.dataSource
      noiseRef = getSpectrumNoise(s1)
      noiseSat = getSpectrumNoise(s2)
      
      es = '%s-%s' % (s1.experiment.name,s2.experiment.name)
      if len(es) > 50:
        es = 'Expt(%d)-Expt(%d)' % (s1.experiment.serial,s2.experiment.serial)

      noeList = self.nmrProject.newNoeList(unit='None',name='Hetero NOE list for %s' % es)
      noeList.setExperiments([s1.experiment,])
      if s1.experiment is not s2.experiment:
        noeList.addExperiment( s2.experiment )
      # TBD: sf, noeValueType, refValue, refDescription
    
      resonancePairsSeen = set()
      for (peakA,peakB) in self.peakPairs: # peakA is sat
        intensA    = getPeakIntensity(peakA,self.intensityType)
        intensB    = getPeakIntensity(peakB,self.intensityType)
        value      = float(intensA)/intensB
        error      = abs(value) * sqrt((noiseSat/intensA)**2 + (noiseRef/intensB)**2)
        resonances = tuple(self.getPeakResonances(peakA))
        frozenResonances = frozenset(resonances)
        if len(resonances) < 2:
          pl = peakA.peakList
          sp = pl.dataSource
          msg = 'Skipping %s:%s:%d peak %d it has too few resonances assigned'
          data = (sp.experiment.name, sp.name, pl.serial, peakA.serial)
          showWarning('Warning',msg % data, parent=self)
        
        elif len(resonances) > 2:
          pl = peakA.peakList
          sp = pl.dataSource
          resonanceText = ' '.join([makeResonanceGuiName(r) for r in resonances])
          msg = 'Skipping %s:%s:%d peak %d it has too many resonances assigned (%s)'
          data = (sp.experiment.name, sp.name, pl.serial, peakA.serial, resonanceText)
          showWarning('Warning', msg % data, parent=self)
        
        elif frozenResonances not in resonancePairsSeen:
          resonancePairsSeen.add(frozenResonances)
          noeList.newNoe(value=value,resonances=resonances,peaks=[peakA,peakB],error=error)
          
        else:
          resonanceText = ' '.join([makeResonanceGuiName(r) for r in resonances])
          msg = 'Skipping duplicate entry for resonances %s' % resonanceText
          showWarning('Warning', msg, parent=self)

      self.parent.editMeasurements(measurementList=noeList)

  def getPeakResonances(self,peak):
  
    resonances = []
    for peakDim in peak.sortedPeakDims():
      for contrib in peakDim.sortedPeakDimContribs():
        resonances.append(contrib.resonance)
    
    return resonances

  def updateAfter(self, *opt):

    if self.waiting:
      return
    else:
      self.waiting = True
      self.after_idle(self.update)
 
  def updateViewButtons(self):
  
    if self.refPeakList:
      self.viewPeaksButtons.buttons[0].enable()
    else:
      self.viewPeaksButtons.buttons[0].disable()
  
    if self.satPeakList:
      self.viewPeaksButtons.buttons[1].enable()
    else:
      self.viewPeaksButtons.buttons[1].disable()
  
    if self.assignPeakList:
      self.viewPeaksButtons.buttons[2].enable()
    else:
      self.viewPeaksButtons.buttons[2].disable()
  
  def updatePeakTable(self, peakList):
    
    if peakList is not self.displayPeakList:
      self.displayPeakList = peakList
      self.peakTable.update(peaks=peakList.sortedPeaks())

  
  def update(self):

    if self.refPeakList:
      self.peaksALabel.set( 'Number of Ref Peaks: %d' % len(self.refPeakList.peaks) )
    else:
      self.peaksALabel.set( 'Number of Ref Peaks: %d' % 0 )
    if self.satPeakList:
      self.peaksBLabel.set( 'Number of Sat Peaks: %d' % len(self.satPeakList.peaks) )
    else:
      self.peaksBLabel.set( 'Number of Sat Peaks: %d' % 0 )
    if self.assignPeakList:
      self.peaksCLabel.set( 'Number of Assign Peaks: %d' % len(self.assignPeakList.peaks) )
    else:
      self.peaksCLabel.set( 'Number of Assign Peaks: %d' % 0 )

    if self.refPeakList and self.satPeakList and self.assignPeakList:
      if self.refPeakList is self.satPeakList:
        self.pairButtons.buttons[0].disable()
      else:
        self.pairButtons.buttons[0].enable()
    else:
      self.pairButtons.buttons[0].disable()
 
    if self.selectedPair:
      self.pairButtons.buttons[1].enable()
      self.pairButtons.buttons[2].enable()
    else:
      self.pairButtons.buttons[1].disable()
      self.pairButtons.buttons[2].disable()

    if self.peakPairs:
      self.pairButtons.buttons[3].enable()
      dsA = self.peakPairs[0][0].peakList.dataSource
      dsB = self.peakPairs[0][1].peakList.dataSource
      dimHA = findSpectrumDimsByIsotope(dsA,'1H')[0]
      dimHB = findSpectrumDimsByIsotope(dsB,'1H')[0]
      dimNA = findSpectrumDimsByIsotope(dsA,'15N')[0]
      dimNB = findSpectrumDimsByIsotope(dsB,'15N')[0]
    else:
      self.pairButtons.buttons[3].disable()
    
    objectList  = []
    textMatrix  = []

    i = 0
    for (peakA,peakB) in self.peakPairs:
      i += 1

      peakDimsA = peakA.sortedPeakDims()
      peakDimsB = peakB.sortedPeakDims()

      ppm0 = peakDimsA[dimHA].value
      ppm1 = peakDimsB[dimHB].value
      ppm2 = peakDimsA[dimNA].value
      ppm3 = peakDimsB[dimNB].value
      d0 = abs(ppm0-ppm1)
      d1 = abs(ppm2-ppm3)
      intensA = getPeakIntensity(peakA,self.intensityType)
      intensB = getPeakIntensity(peakB,self.intensityType)
      datum = []
      datum.append( i )
      datum.append( getPeakAnnotation(peakA, doPeakDims=False) )
      datum.append( getPeakAnnotation(peakB, doPeakDims=False) )
      datum.append( ppm0 )
      datum.append( ppm1 )
      datum.append( ppm2 )
      datum.append( ppm3 )
      datum.append( sqrt((d0*d0)+(d1*d1)) )
      datum.append( intensA )
      datum.append( intensB )
      if intensB:
        datum.append( float(intensA)/intensB )
      else:
        datum.append( None )
      seqCodes = ','.join(['%s' % seqCode for seqCode in getPeakSeqCodes(peakB)])
      datum.append(seqCodes)
      
      objectList.append( (peakA,peakB) )
      textMatrix.append( datum )
      
    if not objectList:
      textMatrix.append([])

    self.scrolledMatrix.update(objectList=objectList, textMatrix=textMatrix)

    self.waiting = False
예제 #32
0
    def body(self):
        '''Describes the body of this tab. It consists
           out of a number of radio buttons, check buttons
           and number entries that allow the user to
           indicate which assignments should be transferred.
        '''

        # self.frame.expandColumn(0)
        self.frame.expandGrid(8, 0)
        self.frame.expandGrid(8, 1)

        typeOfAssignmentFrame = LabelFrame(self.frame,
                                           text='type of assignment')
        typeOfAssignmentFrame.grid(row=0, column=0, sticky='nesw')
        # typeOfAssignmentFrame.expandGrid(0,5)

        peakSelectionFrame = LabelFrame(self.frame,
                                        text='which peaks to assign')
        peakSelectionFrame.grid(row=0, column=1, sticky='nesw', rowspan=2)

        spinSystemSelectionFrame = LabelFrame(self.frame,
                                              text='Which spin-systems to use')
        spinSystemSelectionFrame.grid(row=2, column=0, sticky='nesw')

        tipText = 'What to do when a residue has already a spin system assigned to it.'
        assignedResidueFrame = LabelFrame(
            self.frame,
            text='if residue already has spin-system',
            tipText=tipText)
        assignedResidueFrame.grid(row=2, column=1, sticky='nesw')

        spectrumSelectionFrame = LabelFrame(self.frame, text='spectra')
        spectrumSelectionFrame.grid(row=1, column=0, sticky='nesw')

        row = 0

        Label(typeOfAssignmentFrame,
              text='Resonances to Peak Dimensions',
              grid=(row, 0))
        self.peaksCheckButton = CheckButton(typeOfAssignmentFrame,
                                            selected=True,
                                            grid=(row, 1))

        row += 1

        Label(typeOfAssignmentFrame,
              text='SpinSystems to Residues',
              grid=(row, 0))
        self.residuesCheckButton = CheckButton(typeOfAssignmentFrame,
                                               selected=True,
                                               grid=(row, 1))

        row = 0

        Label(peakSelectionFrame, text='Intra-Residual', grid=(row, 0))
        self.intraCheckButton = CheckButton(peakSelectionFrame,
                                            selected=True,
                                            grid=(row, 1))

        row += 1

        Label(peakSelectionFrame, text='Sequential', grid=(row, 0))
        self.sequentialCheckButton = CheckButton(peakSelectionFrame,
                                                 selected=True,
                                                 grid=(row, 1))

        row += 1

        Label(peakSelectionFrame,
              text='Do not assign diagonal peaks',
              grid=(row, 0))
        self.noDiagonalCheckButton = CheckButton(peakSelectionFrame,
                                                 selected=True,
                                                 grid=(row, 1))

        entries = [
            'Only assigned spin systems',
            'All that have a score of at least: ', 'User Defined',
            'Solution number:'
        ]
        tipTexts = [
            'Only assign resonances of spin systems that already have a sequential assignment for the assignment of peak dimensions. Spin system to residue assignment is not relevant in this case.',
            'Assign all spin systems that have a score of at least a given percentage. 50% or lower is not possible, because than spin systems might have to be assigned to more than 1 residue, which is impossible.',
            "As defined in the lower row of buttons in the 'results' tab.",
            'One of the single solutions of the annealing.'
        ]
        self.spinSystemTypeSelect = RadioButtons(spinSystemSelectionFrame,
                                                 entries=entries,
                                                 grid=(0, 0),
                                                 select_callback=None,
                                                 direction=VERTICAL,
                                                 gridSpan=(4, 1),
                                                 tipTexts=tipTexts)

        tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.'
        self.minScoreEntry = FloatEntry(spinSystemSelectionFrame,
                                        grid=(1, 1),
                                        width=7,
                                        text=str(self.minScore),
                                        returnCallback=self.changeMinScore,
                                        tipText=tipText)
        self.minScoreEntry.bind('<Leave>', self.changeMinScore, '+')

        self.solutionNumberEntry = IntEntry(spinSystemSelectionFrame,
                                            grid=(3, 1),
                                            width=7,
                                            text=1,
                                            returnCallback=self.solutionUpdate,
                                            tipText=tipText)
        self.solutionNumberEntry.bind('<Leave>', self.solutionUpdate, '+')

        #self.solutionPullDown = PulldownList(spinSystemSelectionFrame, None, grid=(3,1), sticky='w')

        entries = ['all spectra', 'only:']
        tipTexts = [
            'Assign peaks in all the spectra that where selected before the annealing ran.',
            'Only assign peaks in one particular spectrum. You can of course repeat this multiple times for different spectra.'
        ]
        self.spectrumSelect = RadioButtons(spectrumSelectionFrame,
                                           entries=entries,
                                           grid=(0, 0),
                                           select_callback=None,
                                           direction=VERTICAL,
                                           gridSpan=(2, 1),
                                           tipTexts=tipTexts)

        self.spectraPullDown = PulldownList(spectrumSelectionFrame,
                                            self.changeSpectrum,
                                            grid=(1, 1),
                                            sticky='w')

        entries = [
            'skip this residue', 'de-assign old spin system from residue',
            'assign, but never merge', 'warn to merge'
        ]
        tipTexts = [
            "Don't assign the new spin system to the residue. The residue is not skipped when the old spin system does not contain any resonances",
            "De-assign old spin system from residue, unless the old spin system is a spin system without any resonances.",
            "Don't merge any spin systems, merging can be performed later if nescesary in the Resonance --> SpinSystems window.",
            "Ask to merge individually for each spin system, this might result in clicking on a lot of popups."
        ]
        self.assignedResidueStrategySelect = RadioButtons(assignedResidueFrame,
                                                          entries=entries,
                                                          grid=(0, 0),
                                                          select_callback=None,
                                                          direction=VERTICAL,
                                                          gridSpan=(2, 1),
                                                          tipTexts=tipTexts)

        texts = ['Transfer Assignments']
        commands = [self.transferAssignments]
        self.transferButton = ButtonList(self.frame,
                                         commands=commands,
                                         texts=texts)
        self.transferButton.grid(row=5, column=0, sticky='nsew', columnspan=2)
예제 #33
0
class EditExperimentSeriesPopup(BasePopup):
  """
  **Setup Experiment Series for Chemical Shift and Intensity Changes**
  
  The purpose of this popup is to setup ordered groups of experiments that are
  related by the variation in some condition or parameter, but otherwise the
  kind of experiment being run is the same. For example the user could setup
  experiments for a temperature series, ligand binding titration or relaxation
  rate measurement.

  The layout is divided into two tables. The upper table shows all of the series
  that are known to the current project and the lower table shows all of the
  experiments or planes that comprise the selected series. These series relate
  to both groups of separate experiments (and hence spectra) and also single
  experiment where one dimension is not for NMR frequency but rather a "sampled"
  dimension and thus effectively combines many experiments (e.g. for different
  T1 values) as different planes. A stack of effectively 2D experiments combined
  in this manner is typically referred to as pseudo-3D. - The experiment is 3D
  but there are only two NMR dimensions.

  Series which are stacks of planes in a single experiment entity are
  automatically detected and entered into the table once they are loaded. Series
  that are constructed from multiple, separate experiments however must be setup
  by the user. To setup a new series of this kind [Add Series] makes a new,
  empty NMR series. Next the user should change the "Parameter varied" column to
  specify what type of thing is varied between the different experiments. The
  user then adds experiments into this series with the [Add Series Point]
  function at the bottom. Once the points have been added to the series the name
  of the experiment for each point may be changed. Initially, arbitrary
  experiments appear for the series points, so these almost always have to be
  adjusted.

  Once a stacked-plane experiment or series of experiments is setup, the user
  next sets (or checks) the value of the parameter associated with each point in
  the lower table. When loading stacked-plane experiments these values may come
  though automatically, if they are present in the spectrum header or parameter
  file. Given a completed NMR series specification the user may then extract the
  relevant data from the series using one of the analysis tools like `Follow
  Intensity Changes`_ or `Follow Shift Changes`_.

  **Caveats & Tips**

  Make sure the "Parameter Varied" for a given NMR series is appropriate to the
  type of analysis being performed. Many tools that extract T1 or Kd
  measurements for example look for specific types of series.

  The "Set/Unset Ref Plane" function is only used in certain kinds of series
  such as those that use trains of CPMG pulses. 

  .. _`Follow Intensity Changes`: CalcRatesPopup.html
  .. _`Follow Shift Changes`: FollowShiftChangesPopup.html

  """

  def __init__(self, parent, *args, **kw):

    self.guiParent   = parent
    self.expSeries   = None
    self.conditionPoint   = None
    self.waiting     = 0
  
    BasePopup.__init__(self, parent, title="Experiment : NMR Series", **kw)

  def body(self, guiFrame):

    self.geometry("500x500")

    self.nameEntry  = Entry(self, text='', returnCallback=self.setName,    width=12)
    self.detailsEntry = Entry(self, text='', returnCallback=self.setDetails, width=16)
    self.valueEntry = FloatEntry(self, text='', returnCallback=self.setValue, width=10)
    self.errorEntry = FloatEntry(self, text='', returnCallback=self.setError, width=8)
    
    self.conditionNamesPulldown = PulldownList(self, callback=self.setConditionName,
                                               texts=self.getConditionNames())
    self.unitPulldown = PulldownList(self, callback=self.setUnit,
                                     texts=self.getUnits())
    self.experimentPulldown = PulldownList(self, callback=self.setExperiment)

    guiFrame.grid_columnconfigure(0, weight=1)

    row = 0
    frame = Frame(guiFrame, grid=(row, 0))
    frame.expandGrid(None,0)
    div = LabelDivider(frame, text='Current Series', grid=(0, 0))
    utilButtons = UtilityButtonList(frame, helpUrl=self.help_url, grid=(0,1))

    row += 1
    frame0 = Frame(guiFrame, grid=(row, 0))
    frame0.expandGrid(0,0)
    tipTexts = ['The serial number of the experiment series, but left blank if the series as actually a pseudo-nD experiment (with a sampled non-frequency axis)',
                'The name of the experiment series, which may be a single pseudo-nD experiment',
                'The number of separate experiments (and hence spectra) present in the series',
                'The kind of quantity that varies for different experiments/planes within the NMR series, e.g. delay time, temperature, ligand concentration etc.',
                'The number of separate points, each with a separate experiment/plane and parameter value, in the series']
    headingList      = ['#','Name','Experiments','Parameter\nVaried','Num\nPoints']
    editWidgets      = [None, self.nameEntry, None, self.conditionNamesPulldown, None]
    editGetCallbacks = [None, self.getName,   None, self.getConditionName, None]
    editSetCallbacks = [None, self.setName,   None, self.setConditionName, None]
    self.seriesMatrix = ScrolledMatrix(frame0, tipTexts=tipTexts,
                                       editSetCallbacks=editSetCallbacks,
                                       editGetCallbacks=editGetCallbacks,
                                       editWidgets=editWidgets,
                                       headingList=headingList,
                                       callback=self.selectExpSeries,
                                       deleteFunc=self.deleteExpSeries,
                                       grid=(0,0), gridSpan=(None, 3))

    tipTexts = ['Make a new, blank NMR series specification in the CCPN project',
                'Delete the selected NMR series from the project, although any component experiments remain. Note you cannot delete pseudo-nD series; delete the actual experiment instead',
                'Colour the spectrum contours for each experiment in the selected series (not pseudo-nD) using a specified scheme']
    texts    = ['Add Series','Delete Series',
                'Auto Colour Spectra']
    commands = [self.addExpSeries,self.deleteExpSeries,
                self.autoColorSpectra]
                
    self.seriesButtons = ButtonList(frame0, texts=texts, commands=commands,
                                    grid=(1,0), tipTexts=tipTexts)

    label = Label(frame0, text='Scheme:', grid=(1,1))
    
    tipText = 'Selects which colour scheme to apply to the contours of (separate) experiments within an NMR series'
    self.colorSchemePulldown = PulldownList(frame0, grid=(1,2), tipText=tipText)

    row += 1
    div = LabelDivider(guiFrame, text='Experimental Parameters & Conditions', grid=(row, 0))

    row += 1
    guiFrame.grid_rowconfigure(row, weight=1)
    frame1 = Frame(guiFrame, grid=(row, 0))
    frame1.expandGrid(0,0)
    tipTexts = ['The kind of experimental parameter that is being used to define the NMR series',
                'The experiment that corresponds to the specified parameter value; can be edited from an arbitrary initial experiment',
                'The numeric value of the parameter (condition) that relates to the experiment or point in the NMR series',
                'The estimated error in value of the condition',
                'The measurement unit in which the value of the condition is represented']
    headingList      = ['Parameter','Experiment','Value','Error','Unit']
    editWidgets      = [None,self.experimentPulldown,self.valueEntry,self.errorEntry, self.unitPulldown]
    editGetCallbacks = [None,self.getExperiment,     self.getValue,  self.getError,   self.getUnit]
    editSetCallbacks = [None,self.setExperiment,     self.setValue,  self.setError,   self.setUnit]
    self.conditionPointsMatrix = ScrolledMatrix(frame1, grid=(0,0), tipTexts=tipTexts,
                                                editSetCallbacks=editSetCallbacks,
                                                editGetCallbacks=editGetCallbacks,
                                                editWidgets=editWidgets,
                                                headingList=headingList,
                                                callback=self.selectConditionPoint,
                                                deleteFunc=self.deleteConditionPoint)
    
    self.conditionPointsMatrix.doEditMarkExtraRules = self.conditionTableShow 
    tipTexts = ['Add a new point to the NMR series with an associated parameter value and experiment',
                'Remove the selected point from the series, including any associated parameter value',
                'For appropriate kinds of NMR series, set or unset a point as representing the plane to use as a reference']
    texts    = ['Add Series Point','Delete Series Point','Set/Unset Ref Plane']
    commands = [self.addConditionPoint,self.deleteConditionPoint,self.setSampledReferencePlane]
    self.conditionPointsButtons = ButtonList(frame1, texts=texts, commands=commands,
                                             tipTexts=tipTexts, grid=(1,0))
    
    self.updateAfter()
    self.updateColorSchemes()

    self.administerNotifiers(self.registerNotify)
    
  def administerNotifiers(self, notifyFunc):

    #for func in ('__init__', 'delete','setName'):
    for func in ('__init__', 'delete','setName','setConditionNames',
                 'addConditionName','removeConditionName'):
      notifyFunc(self.updateAfter,'ccp.nmr.Nmr.NmrExpSeries', func)

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

    for func in ('__init__', 'delete'):
      notifyFunc(self.updateDataDim,'ccp.nmr.Nmr.SampledDataDim', func)

    for func in ('__init__', 'delete','setCondition','setUnit','setValue','setError'):
      notifyFunc(self.updateConditionsAfter,'ccp.nmr.Nmr.SampleCondition', func)

    for func in ('__init__', 'delete','setCondition'):
      notifyFunc(self.updateAfter,'ccp.nmr.Nmr.SampleCondition', func)
      
    for func in ('setConditionVaried', 'setPointErrors', 
                 'addPointError', 'removePointError', 
                 'setPointValues','addPointValue', 
                 'removePointValue','setUnit'): 
      notifyFunc(self.updateAfter,'ccp.nmr.Nmr.SampledDataDim', func)    

    for func in ('__init__', 'delete'):
      notifyFunc(self.updateColorSchemes,'ccpnmr.AnalysisProfile.ColorScheme', func)  

  def open(self):
  
    self.updateAfter()
    BasePopup.open(self)
  
  def updateColorSchemes(self, scheme=None):
    
    index = 0
    prevScheme = self.colorSchemePulldown.getObject()
    
    schemes = getHueSortedColorSchemes(self.analysisProfile)
    schemes = [s for s in schemes if len(s.colors) > 1]
    colors = [list(s.colors) for s in schemes]
    
    if schemes:
      names = [s.name for s in schemes]
      
      if prevScheme in schemes:
        index = schemes.index(prevScheme)
    
    else:
      names  = []
  
    self.colorSchemePulldown.setup(names, schemes, index, colors)
  
  def autoColorSpectra(self):
  
    if self.expSeries and (self.expSeries.className != 'Experiment'):
      scheme = self.colorSchemePulldown.getObject()
      
      if scheme:
        colors = scheme.colors
      else:
        colors = ['#FF0000','#00FF00','#0000FF']  
      
      cdict = getNmrExpSeriesSampleConditions(self.expSeries)
      conditionName = list(self.expSeries.conditionNames)[0]
      expList = []
       
      for sampleCondition in cdict.get(conditionName, []):
        expList.append( (sampleCondition.value, sampleCondition.parent.experiments) )
 
      expList.sort()
      m = len(expList)-1.0
      c = len(colors)-1
       
      for i, (value, experiments) in enumerate(expList):
        p = c*i/m
        j = int(p)
        
        r1, g1, b1 = Color.hexToRgb(colors[j])
        r2, g2, b2 = Color.hexToRgb(colors[min(c,j+1)])
        
        f2 = p-j
        f1 = 1.0-f2
      
        r = (r1*f1)+(r2*f2)
        g = (g1*f1)+(g2*f2)
        b = (b1*f1)+(b2*f2)

        hexColor = Color.hexRepr(r,g,b)
       
        for experiment in experiments:
          for spectrum in experiment.dataSources:
            if spectrum.dataType == 'processed':
              analysisSpec = getAnalysisSpectrum(spectrum)
              
              if analysisSpec.posColors:
                analysisSpec.posColors = [hexColor,]
              elif analysisSpec.negColors:
                analysisSpec.negColors = [hexColor,]
  
  def getUnusedExperiments(self):
  
    sampleExperiments = getSampledDimExperiments(self.nmrProject)
    
    experiments = []
    for experiment in self.nmrProject.sortedExperiments():
      if experiment in sampleExperiments:
        continue
    
      if self.expSeries and (self.expSeries.className != 'Experiment'):
        if experiment in self.expSeries.experiments:
          continue
            
      experiments.append(experiment)
    
    return experiments
  
  def conditionTableShow(self, object, row, col):
  
    if type(object) is type(()):
      dataDim, index = object
      refPlane = dataDim.analysisDataDim.refSamplePlane
      if refPlane == index:
        return False
      if col == 1:
        return False
      
    return True
  
  def setSampledReferencePlane(self):
  
    if self.expSeries and (self.expSeries.className == 'Experiment'):
      if self.conditionPoint:
        dataDim, point = self.conditionPoint
        analysisDataDim = dataDim.analysisDataDim
        refPoint = analysisDataDim.refSamplePlane
        
        if refPoint == point:
          analysisDataDim.refSamplePlane = None
        else:
          analysisDataDim.refSamplePlane = point
    
        self.updateAfter()
    
  def checkAddSampleCondition(self, experiment):

    conditionSet = getExperimentConditionSet(experiment)
    conditionName = self.expSeries.conditionNames[0]
    condDict = getNmrExpSeriesSampleConditions(self.expSeries)

    sampleConditions = condDict.get(conditionName, [])
    units = [sc.unit for sc in sampleConditions if sc.unit]

    if units:
      sortList = list(set(units))
      sortList.sort(key = lambda u:units.count(u))
      unit = sortList[-1]
    else:
      unit = CONDITION_UNITS_DICT[conditionName][0]

    condition = conditionSet.findFirstSampleCondition(condition=conditionName)
    if not condition:
      condition = conditionSet.newSampleCondition(condition=conditionName,
                                                  unit=unit, value=0.0, error=0.0)
                                                  
  def addConditionPoint(self):
  
    if self.expSeries and (self.expSeries.className != 'Experiment'):
      
      experiments = self.getUnusedExperiments()
      if not experiments:
        showWarning('Warning','No experiments available', parent=self)
        return
      
      experiment = experiments[0]
      
      if experiment not in self.expSeries.experiments:
        self.expSeries.addExperiment(experiment)
      
      self.checkAddSampleCondition(experiment)
      self.updateAfter()

  def deleteConditionPoint(self, *event):
  
    if self.conditionPoint and (self.expSeries.className != 'Experiment'):
      if showOkCancel('Confirm','Really delete series point?', parent=self):
        conditionSet = self.conditionPoint.sampleConditionSet 
        
        experiments = [e for e in conditionSet.experiments if e in self.expSeries.experiments]
        
        for experiment in experiments:
          self.expSeries.removeExperiment(experiment)

        for experiment in experiments:
          for expSeries in experiment.nmrExpSeries:
             if self.conditionPoint.condition in self.expSeries.conditionNames:
               break
          else:
            continue
          break
          
        else:    
          self.conditionPoint.delete()
          
        self.conditionPoint = None
           

  def selectConditionPoint(self, object, row, col):
  
    if object:
      self.conditionPoint = object
      self.updateButtons()

  def selectExpSeries(self, object, row, col):

    if object:
      self.expSeries = object
      self.checkExperimentConditionsConsistent()
      self.updateConditions()

  def checkExperimentConditionsConsistent(self):

    if self.expSeries.className != 'Experiment':
      for experiment in self.expSeries.experiments:
        self.checkAddSampleCondition(experiment)

  def getUnits(self):
  
    units = []
    if self.expSeries:
      if self.expSeries.className == 'Experiment':
        conditionName = getExperimentSampledDim(self.expSeries).conditionVaried
     
      else:
        conditionName = self.expSeries.conditionNames[0]
        
      units = CONDITION_UNITS_DICT.get(conditionName)
      if not units:
        units = ['?',]
    
    return units


  def getUnit(self, sampleCondition):

    index = -1
    units = self.getUnits()
    if units:
      if sampleCondition:
        if type(sampleCondition) is type(()):
          dataDim, index = sampleCondition
          unit = dataDim.unit
        else:
          unit = sampleCondition.unit
      
      if unit not in units:
        unit = units[0]
      
      index = units.index(unit)
    
    self.unitPulldown.setup(units,units,index)
  
  def setUnit(self, obj):
  
    name = self.unitPulldown.getObject()
      
    if self.conditionPoint:
      if type(self.conditionPoint) is type(()):
        dataDim, index = self.conditionPoint
        dataDim.setUnit(name)
      
      else:
        self.conditionPoint.setUnit(name)

  def getConditionNames(self):
    
    if self.expSeries and (self.expSeries.className == 'Experiment'):
      names = ['delay time','mixing time','num delays','pulsing frequency','gradient strength']
    else:
      names = CONDITION_UNITS_DICT.keys()
      names.sort()
      
    return names

  def setConditionName(self, obj):
  
    name = self.conditionNamesPulldown.getObject()
  
    if self.expSeries:
      if self.expSeries.className == 'Experiment':
        dataDim = getExperimentSampledDim(self.expSeries)
        dataDim.conditionVaried = name
        
      else:
        self.expSeries.setConditionNames([name,])

  def getConditionName(self, expSeries):
  
    index = 0
    names = self.getConditionNames()
    
    if names:
    
      if expSeries:
        if expSeries.className == 'Experiment':
          name  = getExperimentSampledDim(expSeries).conditionVaried
        else:
          name  = expSeries.conditionNames[0]
        
        if name:  
          index = names.index(name)
      
      else:
        index = 0
    
    self.conditionNamesPulldown.setup(names,names,index)

  def getName(self, expSeries):
    
    if expSeries :
      self.nameEntry.set(expSeries.name)
 
  def setName(self, event):

    text = self.nameEntry.get()
    if text and text != ' ':
      self.expSeries.setName( text )

  def getValue(self, conditionPoint):
    
    if conditionPoint:
      if type(self.conditionPoint) is type(()):
        dataDim, index = conditionPoint
        value = dataDim.pointValues[index]
        
      else:
        value = conditionPoint.value
        
      self.valueEntry.set(value)
 
  def setValue(self, event):

    value = self.valueEntry.get()
    if value is not None:
      if type(self.conditionPoint) is type(()):
        dataDim, index = self.conditionPoint
        values = list(dataDim.pointValues)
        values[index] = value
        dataDim.setPointValues(values)
        
      else:
        self.conditionPoint.setValue( value )

  def getError(self, conditionPoint):
    
    if conditionPoint:
      if type(self.conditionPoint) is type(()):
        dataDim, index = conditionPoint
        
        if index < len(dataDim.pointErrors):
          error = dataDim.pointValues[index]
        else:
          error = 0.0
      
      else:
        error = conditionPoint.error
      
      self.errorEntry.set(error)
 
  def setError(self, event):

    value = self.errorEntry.get()
    if value is not None:
      if type(self.conditionPoint) is type(()):
        dataDim, index = self.conditionPoint
        pointErrors = dataDim.pointErrors
        if pointErrors:
          values = list(pointErrors)
        else:
          values = [0.0] * dataDim.numPoints
 
        values[index] = value
        dataDim.setPointErrors(values)
        
      else:  
        self.conditionPoint.setError( value )
  
  def getDetails(self, expSeries):
    
    if expSeries :
      self.detailsEntry.set(expSeries.details)
 
  def setDetails(self, event):

    text = self.detailsEntry.get()
    if text and text != ' ':
      self.expSeries.setDetails( text )

  def addExpSeries(self):
    
    expSeries = self.nmrProject.newNmrExpSeries(conditionNames=['delay time',])

  def deleteExpSeries(self, *event):
    
    if self.expSeries and (self.expSeries.className != 'Experiment'):
      if showOkCancel('Confirm','Really delete series?', parent=self):
        self.expSeries.delete()
        self.expSeries = None
        self.conditionPoint = None

  def getExperiments(self):
        
    if self.expSeries and (self.expSeries.className == 'Experiment'):
      return [self.expSeries,]
    
    else:
      return self.nmrProject.sortedExperiments()

  def getExperiment(self, sampleCondition):

    index = 0
    names = []
    
    if self.conditionPoint and (type(self.conditionPoint) != type(())):
      index = 0
      experiment = self.conditionPoint.parent.findFirstExperiment()
      experiments = self.getUnusedExperiments()
      
      name  = experiment.name
      names = [name] + [e.name for e in experiments]
      experiments = [experiment,] + experiments
    
    self.experimentPulldown.setup(names,experiments,index)
    
  def setExperiment(self, obj):
    
    experiment = self.experimentPulldown.getObject()
       
    if self.conditionPoint and (type(self.conditionPoint) != type(())):
      conditionSet = getExperimentConditionSet(experiment)
      
      if conditionSet is not self.conditionPoint.parent:
      
        if experiment not in self.expSeries.experiments:
          self.expSeries.addExperiment(experiment)
      
        unit = self.conditionPoint.unit
        if not unit:
          unit = CONDITION_UNITS_DICT[self.expSeries.conditionNames[0]]
        
        condition = self.conditionPoint.condition
      
        experiments = set(self.expSeries.experiments)
        for experiment0 in self.conditionPoint.parent.experiments:
          if experiment0 in experiments:
            experiments.remove(experiment0)
        self.expSeries.experiments = experiments
      
        value = self.conditionPoint.value
        error = self.conditionPoint.error
        self.conditionPoint.delete()
        
        self.conditionPoint = conditionSet.findFirstSampleCondition(condition=condition)
        if self.conditionPoint:
          self.conditionPoint.unit  = unit 
          self.updateAfter()          
        else:
          self.conditionPoint = conditionSet.newSampleCondition(condition=condition,unit=unit,
                                                                value=value,error=error)

  def updateDataDim(self, sampledDataDim):
  
    experiment = sampledDataDim.dataSource.experiment
    self.updateExperiments(experiment)

  def updateExperiments(self, experiment):
    
    experiments = self.getExperiments()
    names = [e.name for e in experiments]
    self.experimentPulldown.setup(names, experiments,0)
    
    if getExperimentSampledDim(experiment):
      self.updateAfter()
  
    elif self.expSeries:
      if self.expSeries.className == 'Experiment':
        if experiment is self.expSeries:
          self.updateConditionsAfter()

      elif experiment in self.expSeries.experiments:
        self.updateConditionsAfter()
 
 
  def updateConditionsAfter(self, sampleCondition=None):


    if self.waitingConditions:
      return
    
    if sampleCondition:
      experiments = sampleCondition.sampleConditionSet.experiments
      for experiment in experiments:
         if self.expSeries.className == 'Experiment':
           if experiment is self.expSeries:
             self.waitingConditions = True
             self.after_idle(self.updateConditions)
             break
      
         elif experiment in self.expSeries.experiments:
          self.waitingConditions = True
          self.after_idle(self.updateConditions)
          break

    else:
      self.waitingConditions = True
      self.after_idle(self.updateConditions)
      
  def updateConditions(self):
  
    self.updateButtons()
    objectList = []
    textMatrix = []
    colorMatrix = []
    nCols = len(self.conditionPointsMatrix.headingList)
    defaultColors = [None] * nCols
    if self.expSeries:
      if self.expSeries.className == 'Experiment':
        dataDim     = getExperimentSampledDim(self.expSeries)
        analysisDataDim = getAnalysisDataDim(dataDim)
        conditionVaried =  dataDim.conditionVaried
        expName     = self.expSeries.name
        unit        = dataDim.unit
        pointValues = dataDim.pointValues
        pointErrors = dataDim.pointErrors
        refPlane    = analysisDataDim.refSamplePlane
        
        for i in range(dataDim.numPoints):
          if i < len(pointErrors):
            error = pointErrors[i]
          else:
            error = None  
          
          pointText = ':%3d' % (i+1)
          if i == refPlane:
            datum      = ['* Ref Plane *',
                          expName+pointText,
                          None,
                          None,
                          None]
            colorMatrix.append(['#f08080'] * nCols)
          else:
            datum      = [conditionVaried ,
                          expName+pointText,
                          pointValues[i],
                          error,
                          unit]
            colorMatrix.append(defaultColors)
 

          textMatrix.append(datum)
          objectList.append((dataDim, i))
             
      else:
        condDict = getNmrExpSeriesSampleConditions(self.expSeries)
        conditionNames = self.expSeries.conditionNames
        
        for conditionName in conditionNames:
          for sampleCondition in condDict.get(conditionName, []):
 
            datum      = [sampleCondition.condition,
                          ' '.join([e.name for e in sampleCondition.parent.experiments]),
                          sampleCondition.value,
                          sampleCondition.error,
                          sampleCondition.unit]
 
            textMatrix.append(datum)
            objectList.append(sampleCondition)
            colorMatrix.append(defaultColors)

    self.conditionPointsMatrix.update(objectList=objectList,
                                      colorMatrix=colorMatrix,
                                      textMatrix=textMatrix)
    
    self.waitingConditions = 0

  def updateAfter(self, object=None):
  
    if self.waiting:
      return
    else:
      self.waiting = True
      self.after_idle(self.update)
 
  def updateButtons(self):
  
    if self.expSeries is None:
      self.seriesButtons.buttons[1].disable()
      self.seriesButtons.buttons[2].disable()
      self.conditionPointsButtons.buttons[0].disable()
      self.conditionPointsButtons.buttons[1].disable()
      self.conditionPointsButtons.buttons[2].disable()

    elif self.expSeries.className == 'Experiment':
      self.seriesButtons.buttons[1].disable()
      self.seriesButtons.buttons[2].disable()
      self.conditionPointsButtons.buttons[0].disable()
      self.conditionPointsButtons.buttons[1].disable()
      self.conditionPointsButtons.buttons[2].enable()
    
    else:
      self.seriesButtons.buttons[1].enable()
      self.seriesButtons.buttons[2].enable()
      self.conditionPointsButtons.buttons[0].enable()
      self.conditionPointsButtons.buttons[2].disable()
      
      if self.conditionPoint is None:
        self.conditionPointsButtons.buttons[1].disable()
      else:
        self.conditionPointsButtons.buttons[1].enable()
 
 
  def update(self):
    
    self.updateButtons()
    
    objectList = []
    textMatrix = []
    for experiment in getSampledDimExperiments(self.nmrProject):
      
      getExperimentConditionSet(experiment)
      sampledDim = getExperimentSampledDim(experiment)
      datum      = [None,
                    experiment.name,
                    1,
                    sampledDim.conditionVaried,
                    sampledDim.numPoints]
 
      textMatrix.append(datum)
      objectList.append(experiment)    
    
    for expSeries in self.nmrProject.sortedNmrExpSeries():

      experiments   = expSeries.experiments
      conditionSets = len([e.sampleConditionSet for e in experiments if e.sampleConditionSet])
      
      datum      = [expSeries.serial,
                    expSeries.name or ' ',
                    len(experiments),
                    ','.join(expSeries.conditionNames),
                    conditionSets]
 
      textMatrix.append(datum)
      objectList.append(expSeries)
       
    self.seriesMatrix.update(objectList=objectList, textMatrix=textMatrix)
    self.updateConditions()

    self.waiting = False
    
  def destroy(self):

    self.administerNotifiers(self.unregisterNotify)
    BasePopup.destroy(self)
예제 #34
0
class EditPeakPopup(BasePopup):
    """
  **Edit Position, Intensity & Details for a Peak**
  
  This popup window provides an means of editing peak information as an
  alternative to editing values in the main peak tables. This popup is also used
  to specify parameters for when a new peak is explicitly added to a peak list
  using a tabular display.

  The user can specify the position of the peak's dimensions in ppm, Hz or data
  point units. Also, the user can adjust the height and volume peak intensity
  values and a textual "Details" field, ,which can carry the user's comments
  about the peak.

  When editing an existing peak, no changes are made to the peak until the
  [Update] button is pressed. Likewise for a new peak the [Add Peak] button
  commits the changes. If the popup window is closed before the changes are 
  committed then the entire editing or peak addition operation is cancelled.

  """
    def __init__(self, parent, peak=None, peakList=None, *args, **kw):

        self.titleColor = '#000080'
        self.numDims = 0
        self.peak = peak

        kw['borderwidth'] = 6
        BasePopup.__init__(self, parent=parent, title='Edit Peak', **kw)

        self.registerNotify(self.deletedPeak, 'ccp.nmr.Nmr.Peak', 'delete')

        for func in ('setAnnotation', 'setDetails', 'setFigOfMerit'):
            self.registerNotify(self.updatePeak, 'ccp.nmr.Nmr.Peak', func)
        for func in ('setAnnotation', 'setPosition', 'setNumAliasing'):
            self.registerNotify(self.updatePeak, 'ccp.nmr.Nmr.PeakDim', func)
        for func in ('__init__', 'delete', 'setValue'):
            self.registerNotify(self.updatePeak, 'ccp.nmr.Nmr.PeakIntensity',
                                func)

        self.dimensionLabels = []
        self.dimensionEntries = []
        self.update(self.peak, peakList)

    def body(self, guiParent):

        self.geometry("+150+150")

        guiParent.grid_columnconfigure(0, weight=1)
        self.master_frame = guiParent

        units = ('ppm', 'point', 'Hz')

        self.unit = 'ppm'

        self.specLabel = Label(guiParent,
                               fg=self.titleColor,
                               grid=(0, 0),
                               sticky='ew')

        self.peakLabel = Label(guiParent, grid=(0, 1), sticky='ew')

        self.unit_frame = frame = Frame(guiParent,
                                        grid=(1, 1),
                                        gridSpan=(1, 2))

        self.unitLabel = Label(frame, text='Current units: ', grid=(0, 0))
        tipText = 'Selects which unit of measurement to display peak dimension positions with'
        self.unitSelect = PulldownList(frame,
                                       callback=self.changeUnit,
                                       texts=units,
                                       grid=(0, 1),
                                       tipText=tipText)

        self.heightLabel = Label(guiParent,
                                 text='Height',
                                 borderwidth=2,
                                 relief='groove')
        tipText = 'Sets the peak height; the value of the spectrum point intensity (albeit often interpolated)'
        self.heightEntry = FloatEntry(guiParent,
                                      borderwidth=1,
                                      tipText=tipText)
        self.volumeLabel = Label(guiParent,
                                 text='Volume',
                                 borderwidth=2,
                                 relief='groove')
        tipText = 'Sets the peak volume integral; normally a summation of data point values'
        self.volumeEntry = FloatEntry(guiParent,
                                      borderwidth=1,
                                      tipText=tipText)
        self.detailLabel = Label(guiParent,
                                 text='Details',
                                 borderwidth=2,
                                 relief='groove')
        tipText = 'A user-configurable textual comment for the peak, which appears an tables and occasionally on spectrum displays'
        self.detailEntry = Entry(guiParent, borderwidth=1, tipText=tipText)

        tipTexts = [
            'Commits the specified values to update the peak and closes the popup',
        ]
        texts = ['Update']
        commands = [self.commit]
        self.buttons = UtilityButtonList(guiParent,
                                         texts=texts,
                                         commands=commands,
                                         doClone=False,
                                         helpUrl=self.help_url,
                                         tipTexts=tipTexts)

    def open(self):

        self.updatePeak()
        BasePopup.open(self)

    def updatePeak(self, object=None):

        peak = None
        if object:
            if object.className == 'Peak':
                peak = object
            elif object.className == 'PeakDim':
                peak = object.peak
            elif object.className == 'PeakIntensity':
                peak = object.peak

        if (peak is None) or (peak is self.peak):
            self.update(peak=self.peak)

    def update(self, peak=None, peakList=None):

        # first destroy old labels and entries (saves grid hassles)

        for label in self.dimensionLabels:
            label.destroy()
        for entry in self.dimensionEntries:
            entry.destroy()

        # now setup required data

        if peak:
            title = 'Edit Peak'
            self.buttons.buttons[0].config(text='Update')
        else:
            title = 'Add Peak'
            self.buttons.buttons[0].config(text='Add Peak')

        self.setTitle(title)

        self.peak = peak
        self.peakList = peakList
        if not peakList:
            if peak:
                self.peakList = peak.peakList
            else:
                return

        peakList = self.peakList
        spectrum = peakList.dataSource.name
        self.numDims = peakList.dataSource.numDim
        self.posn = self.numDims * [0]
        self.dataDims = peakList.dataSource.sortedDataDims()

        if self.peak:

            serial = self.peak.serial
            dims = self.peak.sortedPeakDims()
            details = self.peak.details
            if not details:
                details = ''
            if self.peak.annotation:
                annotn = '%0.16s' % self.peak.annotation
            else:
                annotn = ''

            heightIntensity = self.peak.findFirstPeakIntensity(
                intensityType='height')
            volumeIntensity = self.peak.findFirstPeakIntensity(
                intensityType='volume')

            if heightIntensity:
                height = heightIntensity.value
            else:
                height = 0.0

            if volumeIntensity:
                volume = volumeIntensity.value
            else:
                volume = 0.0

            for i in range(self.numDims):
                peakDim = dims[i]
                dataDimRef = peakDim.dataDimRef
                if dataDimRef:
                    self.posn[i] = peakDim.position + (
                        peakDim.numAliasing * dataDimRef.dataDim.numPointsOrig)
                else:
                    self.posn[i] = peakDim.position

        else:

            dict = peakList.__dict__.get('serialDict')
            if dict is None:
                serial = 1
            else:
                serial = dict.get('peaks', 0) + 1

            height = 0.0
            volume = 0.0
            details = ''
            annotn = ''

        self.specLabel.set(
            text='Experiment: %s Spectrum: %s PeakList: %d' %
            (peakList.dataSource.experiment.name, spectrum, peakList.serial))
        self.peakLabel.set(text='Peak: %d' % serial)

        self.dimensionLabels = self.numDims * ['']
        self.dimensionEntries = self.numDims * ['']
        for i in range(self.numDims):
            pos = self.posn[i]
            if self.unit != 'point':
                dataDim = self.dataDims[i]
                if dataDim.className == 'FreqDataDim':
                    pos = unit_converter[('point', self.unit)](
                        pos, getPrimaryDataDimRef(dataDim))
            self.dimensionLabels[i] = Label(self.master_frame,
                                            text='F%d' % (i + 1),
                                            borderwidth=2,
                                            relief='groove')
            tipText = 'The peak position in dimension %d, in the specified units' % (
                i + 1)
            self.dimensionEntries[i] = FloatEntry(self.master_frame,
                                                  borderwidth=1,
                                                  text='%8.4f' % pos,
                                                  tipText=tipText)

        self.heightEntry.set(text='%f' % height)
        self.volumeEntry.set(text='%f' % volume)
        self.detailEntry.set(text=details)

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

        row = row + 1
        self.peakLabel.grid(row=row, column=0, sticky='nsew')
        self.unit_frame.grid(row=row, column=1, columnspan=2, sticky='nsew')

        for i in range(self.numDims):
            row = row + 1
            self.dimensionLabels[i].grid(row=row, column=0, sticky='nsew')
            self.dimensionEntries[i].grid(row=row,
                                          column=1,
                                          columnspan=3,
                                          sticky='e')

        row = row + 1
        self.heightLabel.grid(row=row, column=0, sticky='nsew')
        self.heightEntry.grid(row=row, column=1, columnspan=3, sticky='e')

        row = row + 1
        self.volumeLabel.grid(row=row, column=0, sticky='nsew')
        self.volumeEntry.grid(row=row, column=1, columnspan=3, sticky='e')

        row = row + 1
        self.detailLabel.grid(row=row, column=0, sticky='nsew')
        self.detailEntry.grid(row=row, column=1, columnspan=3, sticky='e')

        row = row + 1
        self.buttons.grid(row=row, column=0, columnspan=4, sticky='nsew')

    def changeUnit(self, unit):

        posDisp = self.numDims * [None]
        for i in range(self.numDims):
            posDisp[i] = float(self.dimensionEntries[i].get())
            if self.unit != 'point':
                dataDim = self.dataDims[i]
                if dataDim.className == 'FreqDataDim':
                    posDisp[i] = unit_converter[(self.unit, 'point')](
                        posDisp[i], getPrimaryDataDimRef(dataDim))

        self.unit = unit
        if self.unit != 'point':
            for i in range(self.numDims):
                dataDim = self.dataDims[i]
                if dataDim.className == 'FreqDataDim':
                    posDisp[i] = unit_converter[('point', self.unit)](
                        posDisp[i], getPrimaryDataDimRef(dataDim))

        for i in range(self.numDims):
            value = posDisp[i]
            if value is None:
                self.dimensionEntries[i].set('None')
            else:
                self.dimensionEntries[i].set('%8.4f' % posDisp[i])

    def commit(self):

        posDisp = self.numDims * [0]

        for i in range(self.numDims):
            posDisp[i] = float(self.dimensionEntries[i].get())
            if self.unit != 'point':
                dataDim = self.dataDims[i]
                if dataDim.className == 'FreqDataDim':
                    self.posn[i] = unit_converter[(self.unit, 'point')](
                        posDisp[i], getPrimaryDataDimRef(dataDim))

            else:
                self.posn[i] = posDisp[i]

        if self.peak:
            movePeak(self.peak, self.posn)
        else:
            self.peak = pickPeak(self.peakList, self.posn)

        height = self.heightEntry.get()
        volume = self.volumeEntry.get()
        setManualPeakIntensity(self.peak, height, intensityType='height')
        setManualPeakIntensity(self.peak, volume, intensityType='volume')

        details = self.detailEntry.get() or None

        self.peak.setDetails(details)

        self.close()

    def deletedPeak(self, peak):

        if self.peak is peak:
            self.close()

    def destroy(self):

        self.unregisterNotify(self.deletedPeak, 'ccp.nmr.Nmr.Peak', 'delete')

        for func in ('setAnnotation', 'setDetails', 'setFigOfMerit'):
            self.unregisterNotify(self.updatePeak, 'ccp.nmr.Nmr.Peak', func)
        for func in ('setAnnotation', 'setPosition', 'setNumAliasing'):
            self.unregisterNotify(self.updatePeak, 'ccp.nmr.Nmr.PeakDim', func)
        for func in ('__init__', 'delete', 'setValue'):
            self.unregisterNotify(self.updatePeak, 'ccp.nmr.Nmr.PeakIntensity',
                                  func)

        BasePopup.destroy(self)