Example #1
0
    def __init__(self, parent, guiParent, *args, **kw):

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

        self.guiParent = guiParent
        self.aliasing = 0
        self.peakDim = None
        self.contrib = None
        self.component = None
        self.structure = None
        self.resonances = []
        self.jCouplings = []

        headingList = ['#', 'Name', 'Delta', 'Shift', 'SD', 'Dist']
        self.scrolledMatrix = ScrolledMatrix(self,
                                             initialRows=5,
                                             headingList=headingList,
                                             tipTexts=TIP_TEXTS,
                                             callback=self.setCurrentResonance,
                                             highlightType=None)

        row = 0
        self.scrolledMatrix.grid(row=row,
                                 column=0,
                                 columnspan=2,
                                 sticky='nsew',
                                 padx=1)
        self.grid_rowconfigure(row, weight=1)

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

        self.update(None, None)
Example #2
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()
Example #3
0
    def body(self, guiParent):

        self.geometry('600x300')

        guiParent.grid_columnconfigure(1, weight=1)

        url = ''
        if self.server:
            url = self.server.url
        label = Label(guiParent, text='Server location: %s' % url)
        label.grid(row=0, column=0, sticky='w', columnspan=2)

        label = Label(guiParent,
                      text='Installation root: %s%s' %
                      (self.installRoot, os.sep))
        label.grid(row=1, column=0, sticky='w', columnspan=2)

        editWidgets = [None] * 5
        editGetCallbacks = [None, self.toggleSelected, None, None, None]
        editSetCallbacks = [None] * 5

        guiParent.grid_rowconfigure(2, weight=1)
        headingList = [
            'File', 'Install?', 'Date', 'Relative Path', 'Priority', 'Comments'
        ]
        self.scrolledMatrix = ScrolledMatrix(guiParent,
                                             headingList=headingList,
                                             highlightType=0,
                                             editWidgets=editWidgets,
                                             callback=self.selectCell,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks)

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

        if self.exitOnClose:
            txt = 'Quit'
            cmd = sys.exit
        else:
            txt = 'Close'
            cmd = self.close

        texts = ['Refresh List', 'Select All', 'Install Selected', txt]
        commands = [self.updateFiles, self.selectAll, self.install, cmd]
        self.buttonList = ButtonList(guiParent,
                                     texts=texts,
                                     commands=commands,
                                     expands=True)
        self.buttonList.grid(row=3, column=0, columnspan=2, sticky='ew')

        if self.server:
            for fileUpdate in self.server.fileUpdates:
                fileUpdate.isSelected = False

        #self.update()
        # need self.updateFiles, not just self.update
        # because otherwise the 2.0.5 to 2.0.6 upgrades do not work
        # (self.server not set on first pass so need call to updateFiles here)
        self.updateFiles()
Example #4
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()
    def body(self, guiFrame):
        '''Describes where all the GUI element are.'''

        self.geometry('400x500')
        guiFrame.expandGrid(0, 0)
        tableFrame = Frame(guiFrame)
        tableFrame.grid(
            row=0,
            column=0,
            sticky='nsew',
        )
        tableFrame.expandGrid(0, 0)
        buttonFrame = Frame(guiFrame)
        buttonFrame.grid(
            row=1,
            column=0,
            sticky='nsew',
        )
        headingList = ['Spinsystem Number', 'Assignment', 'Residue Type Probs']
        self.table = ScrolledMatrix(tableFrame,
                                    headingList=headingList,
                                    callback=self.updateSpinSystemSelection,
                                    multiSelect=True)
        self.table.grid(row=0, column=0, sticky='nsew')
        texts = ['Add Prob']
        commands = [self.addProb]
        self.AddProbButton = ButtonList(buttonFrame,
                                        commands=commands,
                                        texts=texts)
        self.AddProbButton.grid(row=0, column=0, sticky='nsew')
        texts = ['Remove Prob']
        commands = [self.removeProb]
        self.AddProbButton = ButtonList(buttonFrame,
                                        commands=commands,
                                        texts=texts)
        self.AddProbButton.grid(row=0, column=2, sticky='nsew')
        selectCcpCodes = sorted(self.chemCompDict.keys())
        tipText = 'select ccpCode'
        self.selectCcpCodePulldown = PulldownList(buttonFrame,
                                                  texts=selectCcpCodes,
                                                  grid=(0, 1),
                                                  tipText=tipText)

        selectCcpCodes = ['All Residue Types']

        tipText = 'select ccpCode'
        self.selectCcpCodeRemovePulldown = PulldownList(buttonFrame,
                                                        texts=selectCcpCodes,
                                                        index=0,
                                                        grid=(0, 3),
                                                        tipText=tipText)
        self.updateTable()
Example #6
0
    def body(self, guiFrame):

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

        frame = LabelFrame(guiFrame, text='Options')
        frame.grid(row=0,column=0,sticky='ew')
        frame.grid_columnconfigure(5, weight=1)

        # Choose type of symmetry set to define or change (if allready present in the model)
        self.molLabel = Label(frame, text='Symmetry Operator:')
        self.molLabel.grid(row=0,column=2,sticky='w')
        self.symmCodePulldown = PulldownMenu(frame, callback=self.setSymmCode, entries=['NCS','C2','C3','C5'], do_initial_callback=False)
        self.symmCodePulldown.grid(row=0,column=3,sticky='w')

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

        self.molSysPulldown   = PulldownMenu(self, callback=self.setMolSystem, do_initial_callback=False)
        self.chainSelect      = MultiWidget(self, CheckButton, callback=self.setChains, minRows=0, useImages=False)
        self.segStartEntry    = IntEntry(self, returnCallback=self.setSegStart, width=6)
        self.segLengthEntry   = IntEntry(self, returnCallback=self.setSegLength, width=6)

        headings = ['#','Symmetry\noperator','Mol System','Chains','Start\nresidue','Segment\nlength']  
        editWidgets      = [None, None, self.molSysPulldown, self.chainSelect, self.segStartEntry, self.segLengthEntry] 
        editGetCallbacks = [None, None, self.getMolSystem, self.getChains, self.getSegStart, self.getSegLength]
        editSetCallbacks = [None, self.setSymmCode, self.setMolSystem, self.setChains, self.setSegStart, self.setSegLength]
        
        self.symmetryMatrix = ScrolledMatrix(frame,headingList=headings,
                                             callback=self.selectSymmetry,
                                             editWidgets=editWidgets,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks)
        self.symmetryMatrix.grid(row=0,column=0,sticky='nsew')

        texts = ['Add Symmetry Set','Remove Symmetry Set']
        commands = [self.addSymmetrySet,self.removeSymmetrySet]
        self.buttonList = createDismissHelpButtonList(guiFrame, texts=texts, commands=commands, expands=True)
        self.buttonList.grid(row=2,column=0,sticky='ew')
        
        self.updateMolPartners()
        self.notify(self.registerNotify)

        #Temporary report of parameters
        print self.molSystem
        print self.molecules
        print self.symmetrySet
        print self.symmetryOp
        print self.symmetryCode
Example #7
0
  def body(self, guiParent):

    guiParent.grid_columnconfigure(1,weight=1)
    row = 0

    file_types = [  FileType('Python', ['*.py']), FileType('All', ['*']) ]
    self.file_select = FileSelect(guiParent, file_types=file_types,
                                  single_callback=self.chooseFile,
                                  double_callback=self.chooseFile)
    self.file_select.grid(row=row, column=0, columnspan=2, sticky='nsew')
    
    row = row + 1
    headingList=('Function',)
    self.scrolledMatrix = ScrolledMatrix(guiParent, initialRows=4,
                            headingList=headingList, callback=self.selectFunction)
    self.scrolledMatrix.grid(row=row, column=0, columnspan=2, sticky='nsew')
    guiParent.grid_rowconfigure(row,weight=1)

    row = row + 1
    self.moduleLabel1 = Label(guiParent, text='Module: ')
    self.moduleLabel1.grid(row=row, column=0, sticky='nw')
    self.moduleLabel2 = Label(guiParent, text=' ')
    self.moduleLabel2.grid(row=row, column=1, sticky='nw')

    row = row + 1
    self.functionLabel1 = Label(guiParent, text='Function: ')
    self.functionLabel1.grid(row=row, column=0, sticky='nw')
    self.functionLabel2 = Label(guiParent, text=' ')
    self.functionLabel2.grid(row=row, column=1, sticky='nw')

    row = row + 1
    self.nameLabel = Label(guiParent, text='Name: ')
    self.nameLabel.grid(row=row, column=0, sticky='nw')
    self.nameEntry = Entry(guiParent, text=' ', width=40)
    self.nameEntry.grid(row=row, column=1, sticky='nw')

    row = row + 1
    texts = [ 'Load Macro' ]
    commands = [ self.loadMacro ]
    buttons = UtilityButtonList(guiParent, texts=texts,
                                commands=commands, helpUrl=self.help_url)
    buttons.grid(row=row, column=0, columnspan=2, sticky='ew')
    
    self.loadButton = buttons.buttons[0]
    self.loadButton.disable()
    
    self.path     = None
    self.module   = None
    self.function = None
Example #8
0
 def body(self, master):
   
   textMatrix = self.getTextMatrix(self.objects)
       
   self.label = Label(self,text='Select %s ' % self.objectName)
   self.label.grid(row=0,column=0,sticky='nw')
   
   self.scrolledMatrix = ScrolledMatrix(self, initialRows=10,
                           headingList=self.headingList, 
                           callback=self.selectCell,
                           objectList=self.objects, textMatrix=textMatrix)
   self.scrolledMatrix.grid(row=1,column=0,sticky='nsew')
   self.grid_rowconfigure   (0, weight=0)
   self.grid_rowconfigure   (1, weight=1)
   self.grid_columnconfigure(0, weight=1)
 
   self.protocol('WM_DELETE_WINDOW', self.close)
    def body(self):
        '''Sets up the body of this view.'''

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

        headingList = [
            '#', 'Spectrum', 'Peak List', 'use?', 'labelling scheme'
        ]

        tipTexts = [
            'Row number', 'spectrum name', 'which peak list to use',
            'use this spectrum?',
            'Which labelling scheme belongs to this spectrum?'
        ]

        self.autoLabellingPulldown = PulldownList(self.guiParent,
                                                  self.setAutoLabellingScheme)
        self.autoPeakListPulldown = PulldownList(self.guiParent,
                                                 self.setAutoPeakList)

        editWidgets = [
            None, None, self.autoPeakListPulldown, None,
            self.autoLabellingPulldown
        ]

        editGetCallbacks = [
            None, None, self.getAutoPeakLists, self.changeUse,
            self.getAutoLabellingSchemes
        ]

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

        self.displayTable = ScrolledMatrix(frame,
                                           headingList=headingList,
                                           callback=self.selectAutoSpec,
                                           editWidgets=editWidgets,
                                           multiSelect=False,
                                           editGetCallbacks=editGetCallbacks,
                                           editSetCallbacks=editSetCallbacks,
                                           tipTexts=tipTexts)
        self.displayTable.grid(row=2, column=0, sticky='nsew')
Example #10
0
  def body(self, guiFrame):

    guiFrame.grid_rowconfigure(0, weight=1)
    guiFrame.grid_columnconfigure(0, weight=1)
  
    row = 0 
    frame = LabelFrame(guiFrame, text='Matched Peak Groups')
    frame.grid_rowconfigure(0, weight=1)
    frame.grid_columnconfigure(0, weight=1)
    frame.grid(row=row, sticky='nsew')
    
    headingList, tipTexts = self.getHeadingList()
    self.scrolledMatrix = ScrolledMatrix(frame, initialRows=15, multiSelect=True, 
                                        headingList=headingList, tipTexts=tipTexts,
                                        grid=(0,0), gridSpan=(1,3))
 
    tipTexts = ['Remove the selected peak groups from the table',
                'Show 1D positional ruler lines for the selected groups',
                'Remove any ruler lines previously added for peak group',
                'Display selected peak groups within strips of selected window']
    texts = ['Remove\nGroups','Show\nRulers',
             'Delete\nRulers','Display Groups\nIn Strips']
    commands = [self.removeGroups,self.addRulers,
                self.removeRulers,self.stripGroups]
    self.buttons = ButtonList(frame, texts=texts, commands=commands, tipTexts=tipTexts)
    self.buttons.grid(row=1, column=0, sticky='ew')
    
    tipText = 'Selects the spectrum window in which to display strips & ruler lines'
    label = Label(frame, text='Target window:', grid=(1,1))
    self.windowPulldown = PulldownList(frame, callback=None,
                                       grid=(1,2), tipText=tipText)
    
    row+= 1
    bottomButtons = UtilityButtonList(guiFrame, helpUrl=self.help_url, expands=True, doClone=False)
    bottomButtons.grid(row = row, sticky = 'ew')

    self.update()

    for func in ('__init__', 'delete', 'setName'):
      self.registerNotify(self.updateWindowsAfter, 'ccpnmr.Analysis.SpectrumWindow', func)
Example #11
0
  def body(self, guiFrame):
    
    x = self.parent.winfo_rootx() + 50
    y = self.parent.winfo_rooty() + 50
    location = '500x400+%d+%d' % (x, y)
    self.geometry(location)
    
    guiFrame.expandGrid(1,0)
    
    textMatrix = self.getTextMatrix(self.objects)
        
    self.label = Label(guiFrame, text='Select a %s ' % self.objectName, grid=(0,0))
    
    self.scrolledMatrix = ScrolledMatrix(guiFrame, initialRows=10,
                                         headingList=self.headingList,
                                         callback=self.selectCell,
                                         objectList=self.objects,
                                         textMatrix=textMatrix,
                                         grid=(1,0))

    
    self.protocol('WM_DELETE_WINDOW', self.close)
Example #12
0
    def __init__(self,
                 parent,
                 metaclass,
                 objects=None,
                 includeNumber=True,
                 *args,
                 **kw):

        self.metaclass = metaclass
        self.includeNumber = includeNumber

        headings = []
        if (includeNumber):
            headings.append('Number')

        self.keyList = keyList = getKeyList(metaclass)
        for key in keyList:
            attr = key[-1]
            s = attr.name
            if (len(key) > 1):
                if (type(key[-2]) == type(0)):
                    role = key[-3]
                    n = key[-2]
                    t = '%s[%d]' % (role.otherClass.name, n)
                else:
                    role = key[-2]
                    t = role.otherClass.name
            else:
                t = metaclass.name
            headings.append('%s\n%s' % (t, s))

        ScrolledMatrix.__init__(self,
                                parent,
                                headingList=headings,
                                *args,
                                **kw)

        self.setObjects(objects)
Example #13
0
    def __init__(self, guiParent, dataText, dataObjects, dataValues, **kw):

        dataValueDict = {}
        for n, dataObject in enumerate(dataObjects):
            dataValueDict[dataObject] = dataValues[n]
        self.dataValueDict = dataValueDict
        self.isUsedSet = set()  # default is that none selected

        editWidgets = 2 * [None]
        editSetCallbacks = 2 * [None]
        editGetCallbacks = [None, self.toggleIsUsed]
        headings = [dataText, 'Is Used?']

        ScrolledMatrix.__init__(self,
                                guiParent,
                                headingList=headings,
                                objectList=dataObjects,
                                editWidgets=editWidgets,
                                editGetCallbacks=editGetCallbacks,
                                editSetCallbacks=editSetCallbacks,
                                **kw)

        self.doUpdate()
    def body(self, guiFrame):
        '''Describes where all the GUI element are.'''

        self.geometry('400x500')
        guiFrame.expandGrid(0, 0)
        tableFrame = Frame(guiFrame)
        tableFrame.grid(row=0, column=0, sticky='nsew', )
        tableFrame.expandGrid(0, 0)
        buttonFrame = Frame(guiFrame)
        buttonFrame.grid(row=1, column=0, sticky='nsew', )
        headingList = ['Spinsystem Number', 'Assignment', 'Residue Type Probs']
        self.table = ScrolledMatrix(tableFrame, headingList=headingList,
                                    callback=self.updateSpinSystemSelection,
                                    multiSelect=True)
        self.table.grid(row=0, column=0, sticky='nsew')
        texts = ['Add Prob']
        commands = [self.addProb]
        self.AddProbButton = ButtonList(buttonFrame, commands=commands,
                                        texts=texts)
        self.AddProbButton.grid(row=0, column=0, sticky='nsew')
        texts = ['Remove Prob']
        commands = [self.removeProb]
        self.AddProbButton = ButtonList(buttonFrame, commands=commands,
                                        texts=texts)
        self.AddProbButton.grid(row=0, column=2, sticky='nsew')
        selectCcpCodes = sorted(self.chemCompDict.keys())
        tipText = 'select ccpCode'
        self.selectCcpCodePulldown = PulldownList(buttonFrame,
                                                  texts=selectCcpCodes,
                                                  grid=(0, 1),
                                                  tipText=tipText)

        selectCcpCodes = ['All Residue Types']

        tipText = 'select ccpCode'
        self.selectCcpCodeRemovePulldown = PulldownList(buttonFrame,
                                                        texts=selectCcpCodes,
                                                        index=0,
                                                        grid=(0, 3),
                                                        tipText=tipText)
        self.updateTable()
    def body(self):
        '''Sets up the body of this view.'''

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

        headingList = [
            '#', 'Spectrum', 'Peak List', 'use?', 'labelling scheme']

        tipTexts = ['Row number', 'spectrum name',
                    'which peak list to use',
                    'use this spectrum?',
                    'Which labelling scheme belongs to this spectrum?']

        self.autoLabellingPulldown = PulldownList(
            self.guiParent, self.setAutoLabellingScheme)
        self.autoPeakListPulldown = PulldownList(
            self.guiParent, self.setAutoPeakList)

        editWidgets = [None, None, self.autoPeakListPulldown,
                       None, self.autoLabellingPulldown]

        editGetCallbacks = [None, None, self.getAutoPeakLists,
                            self.changeUse, self.getAutoLabellingSchemes]

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

        self.displayTable = ScrolledMatrix(frame, headingList=headingList,
                                           callback=self.selectAutoSpec,
                                           editWidgets=editWidgets,
                                           multiSelect=False,
                                           editGetCallbacks=editGetCallbacks,
                                           editSetCallbacks=editSetCallbacks,
                                           tipTexts=tipTexts)
        self.displayTable.grid(row=2, column=0, sticky='nsew')
class editResidueTypePopup(BasePopup):
    '''
    The main popup that is shown when the macro is loaded.
    '''

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

        self.font = 'Helvetica 10'
        self.sFont = 'Helvetica %d'
        self.project = parent.project
        self.guiParent = parent
        self.chemCompDict = {}
        self.createChemCompDict()
        self.waiting = False
        BasePopup.__init__(self, parent,
                           title="Residue Type Probabilities", **kw)

    def open(self):

        self.updateAfter()
        BasePopup.open(self)

    def body(self, guiFrame):
        '''Describes where all the GUI element are.'''

        self.geometry('400x500')
        guiFrame.expandGrid(0, 0)
        tableFrame = Frame(guiFrame)
        tableFrame.grid(row=0, column=0, sticky='nsew', )
        tableFrame.expandGrid(0, 0)
        buttonFrame = Frame(guiFrame)
        buttonFrame.grid(row=1, column=0, sticky='nsew', )
        headingList = ['Spinsystem Number', 'Assignment', 'Residue Type Probs']
        self.table = ScrolledMatrix(tableFrame, headingList=headingList,
                                    callback=self.updateSpinSystemSelection,
                                    multiSelect=True)
        self.table.grid(row=0, column=0, sticky='nsew')
        texts = ['Add Prob']
        commands = [self.addProb]
        self.AddProbButton = ButtonList(buttonFrame, commands=commands,
                                        texts=texts)
        self.AddProbButton.grid(row=0, column=0, sticky='nsew')
        texts = ['Remove Prob']
        commands = [self.removeProb]
        self.AddProbButton = ButtonList(buttonFrame, commands=commands,
                                        texts=texts)
        self.AddProbButton.grid(row=0, column=2, sticky='nsew')
        selectCcpCodes = sorted(self.chemCompDict.keys())
        tipText = 'select ccpCode'
        self.selectCcpCodePulldown = PulldownList(buttonFrame,
                                                  texts=selectCcpCodes,
                                                  grid=(0, 1),
                                                  tipText=tipText)

        selectCcpCodes = ['All Residue Types']

        tipText = 'select ccpCode'
        self.selectCcpCodeRemovePulldown = PulldownList(buttonFrame,
                                                        texts=selectCcpCodes,
                                                        index=0,
                                                        grid=(0, 3),
                                                        tipText=tipText)
        self.updateTable()

    def updateSpinSystemSelection(self, obj, row, col):
        '''Called after selectin a row in the table.'''
        self.updateRemoveCcpCodePullDown()

    def updateRemoveCcpCodePullDown(self):
        '''Updates the pulldown showing all current residueTypeProbs
           for a resonanceGroup that can be removed.

        '''

        removeCcpCodes = []
        for spinSystem in self.table.currentObjects:
            removeCcpCodes.extend([typeProp.possibility.ccpCode for typeProp in spinSystem.getResidueTypeProbs()])
        removeCcpCodes = ['All Residue Types'] + list(set(removeCcpCodes))
        self.selectCcpCodeRemovePulldown.setup(texts=removeCcpCodes,
                                               objects=removeCcpCodes,
                                               index=0)

    def getSpinSystems(self):
        '''Get resonanceGroups (spin systems) in the project.'''
        return self.nmrProject.resonanceGroups

    def addProb(self):
        '''Add the residue type selected in the selectCcpCodePulldown
           as an residueTypeProb.

        '''
        ccpCode = self.selectCcpCodePulldown.object
        for spinSystem in self.table.currentObjects:
            if ccpCode not in [typeProp.possibility.ccpCode for typeProp in spinSystem.getResidueTypeProbs()]:
                chemComp = self.chemCompDict.get(ccpCode)
                spinSystem.newResidueTypeProb(possibility=chemComp)
        self.updateTable()
        self.updateRemoveCcpCodePullDown()

    def removeProb(self):
        '''Removes the residueTypeProb selected in the
           selectCcpCodeRemovePulldown from the selected resonanceGroup.

        '''
        ccpCode = self.selectCcpCodeRemovePulldown.object
        for spinSystem in self.table.currentObjects:
            residueTypeProbs = spinSystem.getResidueTypeProbs()
            for typeProb in residueTypeProbs:
                if ccpCode == 'All Residue Types' or ccpCode == typeProb.possibility.ccpCode:
                    typeProb.delete()
        self.updateTable()
        self.updateRemoveCcpCodePullDown()

    def createChemCompDict(self):
        '''Make a list of all amino acid types present in any of the
           molecular chains present in the project.

        '''
        chains = self.getChains()
        for chain in chains:
            for residue in chain.sortedResidues():
                if residue.ccpCode not in self.chemCompDict:
                    self.chemCompDict[residue.ccpCode] = residue.chemCompVar.chemComp

    def getChains(self):
        '''Get all molecular chains stored in the project.'''
        chains = []
        if self.project:
            for molSystem in self.project.sortedMolSystems():
                for chain in molSystem.sortedChains():
                    if chain.residues:
                        chains.append(chain)
        return chains

    def updateTable(self):
        '''Update the whole table.'''
        objectList = []
        data = []
        for spinSystem in self.getSpinSystems():
            objectList.append(spinSystem)
            residueTypeProbs = spinSystem.getResidueTypeProbs()
            spinSystemInfo = self.getStringDescriptionOfSpinSystem(spinSystem)
            probString = ''
            for typeProp in residueTypeProbs:
                probString += typeProp.possibility.ccpCode + ' '
            data.append([spinSystem.serial, spinSystemInfo, probString])
        self.table.update(objectList=objectList, textMatrix=data)

    def getStringDescriptionOfSpinSystem(self, spinsys):
        '''Get a simple identifier for the assignment status of a
           resonanceGroup.

        '''

        spinSystemInfo = ''
        if spinsys.residue:
            spinSystemInfo += str(spinsys.residue.seqCode) + ' ' + spinsys.residue.ccpCode
        elif spinsys.residueProbs:
            for residueProb in spinsys.residueProbs:
                res = residueProb.possibility
                spinSystemInfo += '{} {}? /'.format(res.seqCode, res.ccpCode)
            spinSystemInfo = spinSystemInfo[:-1]
        elif spinsys.ccpCode:
            spinSystemInfo += spinsys.ccpCode
        return spinSystemInfo
Example #17
0
class UpdatePopup(BasePopup, UpdateAgent):
    def __init__(self,
                 parent,
                 serverLocation=UPDATE_SERVER_LOCATION,
                 serverDirectory=UPDATE_DIRECTORY,
                 dataFile=UPDATE_DATABASE_FILE,
                 exitOnClose=False):

        self.exitOnClose = exitOnClose
        UpdateAgent.__init__(self,
                             serverLocation,
                             serverDirectory,
                             dataFile,
                             isStandAlone=exitOnClose)
        self.fileUpdate = None

        if exitOnClose:
            quitFunc = sys.exit
        else:
            quitFunc = None

        BasePopup.__init__(self,
                           parent=parent,
                           title='CcpNmr Software Updates',
                           quitFunc=quitFunc)

    def body(self, guiParent):

        self.geometry('600x300')

        guiParent.grid_columnconfigure(1, weight=1)

        url = ''
        if self.server:
            url = self.server.url
        label = Label(guiParent, text='Server location: %s' % url)
        label.grid(row=0, column=0, sticky='w', columnspan=2)

        label = Label(guiParent,
                      text='Installation root: %s%s' %
                      (self.installRoot, os.sep))
        label.grid(row=1, column=0, sticky='w', columnspan=2)

        editWidgets = [None] * 5
        editGetCallbacks = [None, self.toggleSelected, None, None, None]
        editSetCallbacks = [None] * 5

        guiParent.grid_rowconfigure(2, weight=1)
        headingList = [
            'File', 'Install?', 'Date', 'Relative Path', 'Priority', 'Comments'
        ]
        self.scrolledMatrix = ScrolledMatrix(guiParent,
                                             headingList=headingList,
                                             highlightType=0,
                                             editWidgets=editWidgets,
                                             callback=self.selectCell,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks)

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

        if self.exitOnClose:
            txt = 'Quit'
            cmd = sys.exit
        else:
            txt = 'Close'
            cmd = self.close

        texts = ['Refresh List', 'Select All', 'Install Selected', txt]
        commands = [self.updateFiles, self.selectAll, self.install, cmd]
        self.buttonList = ButtonList(guiParent,
                                     texts=texts,
                                     commands=commands,
                                     expands=True)
        self.buttonList.grid(row=3, column=0, columnspan=2, sticky='ew')

        if self.server:
            for fileUpdate in self.server.fileUpdates:
                fileUpdate.isSelected = False

        #self.update()
        # need self.updateFiles, not just self.update
        # because otherwise the 2.0.5 to 2.0.6 upgrades do not work
        # (self.server not set on first pass so need call to updateFiles here)
        self.updateFiles()

    def toggleSelected(self, fileUpdate):

        boolean = fileUpdate.isSelected

        fileUpdate.isSelected = not boolean

        self.update()

    def install(self):

        if self.server:
            self.installUpdates()
            self.updateFiles()

    def selectAll(self):

        if self.server:
            for fileUpdate in self.scrolledMatrix.objectList:
                fileUpdate.isSelected = True

        self.update()

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

        self.fileUpdate = object

    def updateButtons(self):

        buttons = self.buttonList.buttons

        if self.server:
            selected = False
            if self.server and self.server.fileUpdates:
                for fileUpdate in self.scrolledMatrix.objectList:
                    if fileUpdate.isSelected:
                        selected = True
                        break

                buttons[1].enable()
            else:
                buttons[1].disable()

            if selected:
                buttons[2].enable()
                buttons[2].config(bg='#A0FFA0')
            else:
                buttons[2].disable()
                buttons[2].config(bg=buttons[1].cget('bg'))

        else:
            for button in buttons[:-1]:
                button.disable()

    def updateFiles(self):

        if self.server:
            if not self.server.fileUpdates:
                self.server.getFileUpdates()

            for fileUpdate in self.server.fileUpdates:
                fileUpdate.isSelected = False

        self.update()

    def update(self):

        self.updateButtons()

        self.fileUpdate = None
        textMatrix = []
        objectList = []
        colorMatrix = []

        if self.server:

            for fileUpdate in self.server.fileUpdates:

                if fileUpdate.getIsUpToDate():
                    continue

                color = [None, '#A04040', None, None, None]
                yesNo = 'No'
                if fileUpdate.isSelected:
                    color = [None, '#A0FFA0', None, None, None]
                    yesNo = 'Yes'

                datum = []
                datum.append(fileUpdate.fileName)
                datum.append(yesNo)
                datum.append(fileUpdate.date)
                datum.append(fileUpdate.filePath + os.sep)
                datum.append(fileUpdate.priority)
                datum.append(fileUpdate.details)

                colorMatrix.append(color)
                textMatrix.append(datum)
                objectList.append(fileUpdate)

        self.scrolledMatrix.update(textMatrix=textMatrix,
                                   objectList=objectList,
                                   colorMatrix=colorMatrix)
Example #18
0
class NewWindowPopup(BasePopup):
    """
  **Create New Windows to Display Spectra**
  
  This tool is used to make new windows for the graphical display of spectra,
  which will usually be as contours. It is notable that some spectrum windows
  will be made automatically when spectra are loaded if there is no existing
  appropriate window to display a spectrum. However, making new spectrum windows
  allows the user to specialise different windows for different tasks and gives
  complete freedom as to which types of axis go in which direction. For example
  the user may wish to make a new window so that a spectrum can be viewed from
  an orthogonal, rotated aspect.

  A new spectrum window is made by first considering whether it is similar to
  any existing windows. If so, then the user selects the appropriate template
  window to base the new one upon. The user then chooses a name for the window
  via the "New window name" field, although the name may be changed after the
  window is created. Usually the user does not need to consider the "Strips"
  section, but if required the new window can be created with starting strips
  and orthogonal sub-divisions (although these are not permanent). After setting
  the required axes and spectrum visibility, as described below, the user clicks
  on [Create Window!] to actually make the new spectrum display window.

  **Axes**

  The number and type of axes for the new window are chosen using the pulldown
  menus in the "Axes" section. The idea is that the user chooses which NMR
  isotopes should appear on the X, Y, & Z axes. Naturally, X and Y axes must
  always be set to something, to represent the plane of the screen, but the Z
  axes are optional. If not required, a Z axis may be set to "None" to indicate
  that it will not be used. Up to four Z axes may be specified, labelled as
  "z1", "z2" etc., and these represent extra dimensions orthogonal to the plane
  of the  screen, which are often conceptualised as depth axes.
  
  It should be noted that the Y axis type may be set to "value", which refers to
  a spectrum intensity axis, rather than an NMR isotope axis. Setting the Y axis
  to "value" and only having the X axis set to an isotope is used to create
  windows that can show 1D spectra. Such value axes can also be used for 2D and
  higher dimensionality spectra, to show the data as an intensity graph (a
  "slice") rather than as contours.

  **Spectra**

  The lower "Viewed Spectra" section lists all of the spectra within the project
  that may be shown by a window with the selected axes. All spectra with
  isotopes in their data dimensions that match the isotope types of the window
  axes can potentially be displayed. This system also allows for displayed 
  spectra to have fewer dimensions than the axes has windows, as long as at
  least the X and Y axes are present. For example a 2D H-N spectrum can be
  shown in a 3D H-N-H window, but not a 3D H-H-N.

  For spectra that have more than one data dimension of the same isotope, then
  which data dimension goes with which window axis is not always known to
  Analysis. Where there is ambiguity, this system will simply map the spectrum
  data dimensions in order to the next matching window axis. If this mapping
  turns out to be wrong, then it may be changed at any time via the main
  _Windows settings; toggling the "Dim. Mapping" of the "Spectrum & Peak List
  Mappings" tab.
  
  For the spectra listed in the lower table, which may be placed in the new
  window, the user has control over whether the spectra actually will appear.
  Firstly the user can change the "Visible?" column, either via a double-click
  or by using the appropriate lower buttons. By default spectra are set as not
  being visible in new windows, and the user toggles the ones that should be
  seen to "Yes". This basic spectrum visibility can readily be changed by the
  toggle buttons that appear in the "toolbar" at the top of the spectrum
  display, so the "Visible?" setting here is only about what initially appears. 

  The "In Toolbar?" setting of a spectrum is a way of allowing the user to state
  that a spectrum should never appear in the window, and not even allow it to be
  toggled on later via the toolbar at the top of the windows. This is a way of
  reducing clutter, and allows certain windows to be used for particular subsets
  of spectra. For example the user may wish to put the spectra for a temperature
  series in one window, but not in other windows used for resonance assignment
  where they would get in the way. The "In Toolbar" setting can be changed
  after a window has been made, but only via the main Windows_ settings popup.

  .. _Windows: EditWindowPopup.html

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

        self.visibleSpectra = parent.visibleSpectra
        self.toolbarSpectra = parent.toolbarSpectra
        self.waiting = False
        self.window = None

        BasePopup.__init__(self,
                           parent=parent,
                           title='Window : New Window',
                           **kw)

    def body(self, guiFrame):

        guiFrame.grid_columnconfigure(2, weight=1)

        row = 0
        label = Label(guiFrame, text='Template window: ', grid=(row, 0))
        tipText = 'Selects which window to use as the basis for making a new spectrum window; sets the axis types accordingly'
        self.window_list = PulldownList(guiFrame,
                                        grid=(row, 1),
                                        callback=self.setAxisTypes,
                                        tipText=tipText)
        frame = LabelFrame(guiFrame,
                           text='Strips',
                           grid=(row, 2),
                           gridSpan=(2, 1))
        buttons = UtilityButtonList(guiFrame,
                                    doClone=False,
                                    helpUrl=self.help_url,
                                    grid=(row, 3))

        row += 1
        label = Label(guiFrame, text='New window name: ', grid=(row, 0))
        tipText = 'A short name to identify the spectrum window, which will appear in the graphical interface'
        self.nameEntry = Entry(guiFrame,
                               width=16,
                               grid=(row, 1),
                               tipText=tipText)

        row += 1

        label = Label(frame, text='Columns: ', grid=(0, 0))
        tipText = 'The number of vertical strips/dividers to initially make in the spectrum window'
        self.cols_menu = PulldownList(frame,
                                      objects=STRIP_NUMS,
                                      grid=(0, 1),
                                      texts=[str(x) for x in STRIP_NUMS],
                                      tipText=tipText)

        label = Label(frame, text='Rows: ', grid=(0, 2))
        tipText = 'The number of horizontal strips/dividers to initially make in the spectrum window'
        self.rows_menu = PulldownList(frame,
                                      objects=STRIP_NUMS,
                                      grid=(0, 3),
                                      texts=[str(x) for x in STRIP_NUMS],
                                      tipText=tipText)
        row += 1
        div = LabelDivider(guiFrame,
                           text='Axes',
                           grid=(row, 0),
                           gridSpan=(1, 4))

        row += 1
        self.axis_lists = {}
        frame = Frame(guiFrame, grid=(row, 0), gridSpan=(1, 4))

        col = 0
        self.axisTypes = {}
        self.axisTypesIncludeNone = {}
        for label in AXIS_LABELS:
            self.axisTypes[label] = None
            w = Label(frame, text=' ' + label)
            w.grid(row=0, column=col, sticky='w')
            col += 1

            if label in ('x', 'y'):
                includeNone = False
                tipText = 'Sets the kind of measurement (typically ppm for a given isotope) that will be used along the window %s axis' % label
            else:
                includeNone = True
                tipText = 'Where required, sets the kind of measurement (typically ppm for a given isotope) that will be used along the window %s axis' % label
            self.axisTypesIncludeNone[label] = includeNone

            getAxisTypes = lambda label=label: self.getAxisTypes(label)
            callback = lambda axisType, label=label: self.changedAxisType(
                label, axisType)
            self.axis_lists[label] = PulldownList(frame,
                                                  callback=callback,
                                                  tipText=tipText)
            self.axis_lists[label].grid(row=0, column=col, sticky='w')
            col += 1

        frame.grid_columnconfigure(col, weight=1)

        row += 1
        div = LabelDivider(guiFrame,
                           text='Viewed Spectra',
                           grid=(row, 0),
                           gridSpan=(1, 4))

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)

        editWidgets = [None, None, None, None]
        editGetCallbacks = [None, self.toggleVisible, self.toggleToolbar, None]
        editSetCallbacks = [None, None, None, None]
        tipTexts = [
            'The "experiment:spectrum" name for the spectrum that may be viewed in the new window, given the axis selections',
            'Sets whether the spectrum contours will be visible in the new window',
            'Sets whether the spectrum appears at all in the window; if not in the toolbar it cannot be displayed',
            'The number of peak lists the spectrum contains'
        ]
        headingList = ['Spectrum', 'Visible?', 'In Toolbar?', 'Peak Lists']

        self.scrolledMatrix = ScrolledMatrix(guiFrame,
                                             headingList=headingList,
                                             editWidgets=editWidgets,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks,
                                             multiSelect=True,
                                             grid=(row, 0),
                                             gridSpan=(1, 4),
                                             tipTexts=tipTexts)

        row += 1
        tipTexts = [
            'Creates a new spectrum window with the specified parameters',
            'Sets the contours of the selected spectra to be visible when the new window is made',
            'Sets the contours of the selected spectra to not be displayed when the new window is made',
            'Sets the selected spectra as absent from the window toolbar, and thus not displayable at all'
        ]
        texts = [
            'Create Window!', 'Selected\nVisible', 'Selected\nNot Visible',
            'Selected\nNot In Toolbar'
        ]
        commands = [
            self.ok, self.setSelectedDisplay, self.setSelectedHide,
            self.setSelectedAbsent
        ]
        buttonList = ButtonList(guiFrame,
                                texts=texts,
                                grid=(row, 0),
                                commands=commands,
                                gridSpan=(1, 4),
                                tipTexts=tipTexts)
        buttonList.buttons[0].config(bg='#B0FFB0')

        self.updateAxisTypes()
        self.updateWindow()
        self.updateWindowName()

        self.administerNotifiers(self.registerNotify)
        self.updateAfter()

    def administerNotifiers(self, notifyFunc):

        self.registerNotify(self.updateWindowName,
                            'ccpnmr.Analysis.SpectrumWindow', '__init__')

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

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

        for func in ('__init__', 'delete', 'setName', 'addSpectrumWindowGroup',
                     'removeSpectrumWindowGroup', 'setSpectrumWindowGroups'):
            notifyFunc(self.updateWindow, 'ccpnmr.Analysis.SpectrumWindow',
                       func)

        for func in ('addSpectrumWindow', 'removeSpectrumWindow',
                     'setSpectrumWindows'):
            notifyFunc(self.updateWindow,
                       'ccpnmr.Analysis.SpectrumWindowGroup', func)

        for func in ('__init__', 'delete', 'setName'):
            notifyFunc(self.updateAxisTypes, 'ccpnmr.Analysis.AxisType', func)


# Set visible contours, on commit, according to selection
#   Get hold of spectrumWindowView ASAP

    def destroy(self):

        self.administerNotifiers(self.unregisterNotify)

        BasePopup.destroy(self)

    def getSpectra(self):

        spectrumIsotopes = {}

        spectra = []
        for experiment in self.nmrProject.sortedExperiments():
            name = experiment.name

            for spectrum in experiment.sortedDataSources():
                spectrumIsotopes[spectrum] = []
                spectra.append(['%s:%s' % (name, spectrum.name), spectrum])

                for dataDim in spectrum.dataDims:
                    dimTypes = []

                    if dataDim.className != 'SampledDataDim':
                        for dataDimRef in dataDim.dataDimRefs:
                            expDimRef = dataDimRef.expDimRef
                            isotopes = set()

                            for isotopeCode in expDimRef.isotopeCodes:
                                isotopes.add(isotopeCode)

                            dimTypes.append(
                                (expDimRef.measurementType.lower(), isotopes))
                    else:
                        dimTypes.append('sampled')

                    spectrumIsotopes[spectrum].append(dimTypes)

        axisIsotopes = {}
        for label in AXIS_LABELS:
            if label not in ('x', 'y'):
                if self.axis_lists[label].getSelectedIndex() == 0:
                    continue

            axisType = self.axis_lists[label].getObject()
            axisIsotopes[label] = (axisType.measurementType.lower(),
                                   set(axisType.isotopeCodes))

        spectraSel = []
        axes = axisIsotopes.keys()
        axes.sort()
        for name, spectrum in spectra:
            dimIsotopes = spectrumIsotopes[spectrum]

            for label in axes:
                mType, selected = axisIsotopes[label]
                if label == 'y' and mType == 'none':
                    continue  # value axis

                for i, dimTypes in enumerate(dimIsotopes):
                    for dimType in dimTypes:
                        if dimType == 'sampled':
                            if label != 'z1':
                                continue
                            axisType = self.axis_lists[label].getObject()
                            if axisType.name != 'sampled':
                                continue
                            dimIsotopes.pop(i)
                            break
                        else:
                            measurementType, isotopes = dimType
                            if (mType == measurementType) and (selected <=
                                                               isotopes):
                                dimIsotopes.pop(i)
                                break
                    else:
                        continue
                    break

                else:
                    if label in ('x', 'y'):
                        break

            else:

                if not dimIsotopes:
                    spectraSel.append([name, spectrum])

        return spectraSel

    def setSelectedAbsent(self):

        for spectrum in self.scrolledMatrix.currentObjects:
            self.visibleSpectra[spectrum] = False
            self.toolbarSpectra[spectrum] = False

        self.updateAfter()

    def setSelectedDisplay(self):

        for spectrum in self.scrolledMatrix.currentObjects:
            self.visibleSpectra[spectrum] = True
            self.toolbarSpectra[spectrum] = True

        self.updateAfter()

    def setSelectedHide(self):

        for spectrum in self.scrolledMatrix.currentObjects:
            self.visibleSpectra[spectrum] = False
            self.toolbarSpectra[spectrum] = True

        self.updateAfter()

    def toggleToolbar(self, spectrum):

        boolean = not self.toolbarSpectra.get(spectrum, True)
        self.toolbarSpectra[spectrum] = boolean

        if boolean is False:
            self.visibleSpectra[spectrum] = False

        self.updateAfter()

    def toggleVisible(self, spectrum):

        boolean = not self.visibleSpectra.get(spectrum, False)
        self.visibleSpectra[spectrum] = boolean

        if boolean:
            if not self.toolbarSpectra.get(spectrum, True):
                self.toolbarSpectra[spectrum] = True

        self.updateAfter()

    def updateAfter(self, object=None):

        if self.waiting:
            return

        else:
            self.waiting = True
            self.after_idle(self.update)

    def update(self):

        for spectrum in self.visibleSpectra.keys():
            if spectrum.isDeleted:
                del self.visibleSpectra[spectrum]

        textMatrix = []
        objectList = []
        colorMatrix = []

        for name, spectrum in self.getSpectra():
            colours = [None, None, None, None]

            if self.visibleSpectra.get(spectrum):
                colours[0] = '#60F060'
                isVisible = 'Yes'
                self.visibleSpectra[
                    spectrum] = True  # do not need this but play safe in case above if changed
            else:
                isVisible = 'No'
                self.visibleSpectra[spectrum] = False

            if self.toolbarSpectra.get(spectrum, True):
                inToolbar = 'Yes'
                self.toolbarSpectra[spectrum] = True
            else:
                colours[0] = '#600000'
                inToolbar = 'No'
                self.toolbarSpectra[spectrum] = False

            datum = [
                name, isVisible, inToolbar,
                ','.join(['%d' % pl.serial for pl in spectrum.peakLists])
            ]

            textMatrix.append(datum)
            objectList.append(spectrum)
            colorMatrix.append(colours)

        self.scrolledMatrix.update(objectList=objectList,
                                   textMatrix=textMatrix,
                                   colorMatrix=colorMatrix)

        self.waiting = False

    def updateAxisTypes(self, *extra):

        for label in AXIS_LABELS:
            names = []
            objects = []
            includeNone = self.axisTypesIncludeNone[label]

            if includeNone:
                names.append('None')
                objects.append(None)
            axisType = self.axisTypes[label]
            axisTypes = self.getAxisTypes(label)
            objects.extend(axisTypes)

            if axisTypes:
                if axisType not in objects:
                    axisType = objects[0]
                index = objects.index(axisType)
                names.extend([x.name for x in axisTypes])

            else:
                index = 0

            self.axis_lists[label].setup(names, objects, index)
            self.changedAxisType(label, axisType)

    def changedAxisType(self, label, axisType):

        if axisType is not self.axisTypes[label]:
            self.axisTypes[label] = axisType

        self.updateAfter()

    def updateWindow(self, *extra):

        window = self.window
        windows = self.parent.getWindows()
        if windows:
            if window not in windows:
                window = windows[0]
            index = windows.index(window)
            names = [x.name for x in windows]
        else:
            index = 0
            names = []

        self.window_list.setup(names, windows, index)
        self.setAxisTypes(window)

    def updateWindowName(self, *extra):

        self.nameEntry.set(WindowBasic.defaultWindowName(self.project))

    def getAxisTypes(self, label):

        axisTypes = self.parent.getAxisTypes()

        if label == 'z1':
            axisTypes = [
                axisType for axisType in axisTypes
                if axisType.name == 'sampled' or not axisType.isSampled
            ]
        else:
            axisTypes = [
                axisType for axisType in axisTypes if not axisType.isSampled
            ]

        if label != 'y':
            axisTypes = [
                at for at in axisTypes
                if at.name != WindowBasic.VALUE_AXIS_NAME
            ]

        return axisTypes

    def setAxisTypes(self, window):

        project = self.project
        if not project:
            return

        if window is self.window:
            return

        self.window = window
        if window:
            windowPanes = window.sortedSpectrumWindowPanes()
            if windowPanes:
                # might be empty because notifier called before windowPanes set up
                windowPane = windowPanes[0]

                for label in AXIS_LABELS:
                    axisPanel = windowPane.findFirstAxisPanel(label=label)

                    if axisPanel and axisPanel.panelType \
                        and axisPanel.panelType.axisType:
                        self.axis_lists[label].setSelected(
                            axisPanel.panelType.axisType)

                    elif label not in ('x', 'y'):
                        self.axis_lists[label].setIndex(0)

            self.updateAfter()

    def apply(self):

        project = self.project
        if not project:
            return False

        name = self.nameEntry.get().strip()
        if not name:
            showError('No name', 'Need to enter name', parent=self)
            return False

        names = [
            window.name for window in self.analysisProject.spectrumWindows
        ]

        if (name in names):
            showError('Repeated name', 'Name already used', parent=self)
            return False

        axisTypes = []
        for label in AXIS_LABELS:
            if label not in ('x', 'y'):
                if self.axis_lists[label].getSelectedIndex() == 0:
                    continue

            axisType = self.axis_lists[label].getObject()
            axisTypes.append(axisType)

        ncols = self.cols_menu.getObject()
        nrows = self.rows_menu.getObject()

        window = WindowBasic.createSpectrumWindow(project,
                                                  name, [
                                                      axisTypes,
                                                  ],
                                                  ncols=ncols,
                                                  nrows=nrows)

        return True
Example #19
0
class CingFrame(NmrSimRunFrame):

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

    project = application.project
    simStore = project.findFirstNmrSimStore(application=APP_NAME) or \
               project.newNmrSimStore(application=APP_NAME, name=APP_NAME)

    self.application = application
    self.residue = None
    self.structure = None
    self.serverCredentials = None
    self.iCingBaseUrl = DEFAULT_URL
    self.resultsUrl = None
    self.chain = None
    self.nmrProject = application.nmrProject
    self.serverDone = False

    NmrSimRunFrame.__init__(self, parent, project, simStore, *args, **kw)

    # # # # # # New Structure Frame # # # # #

    self.structureFrame.grid_forget()

    tab = self.tabbedFrame.frames[0]

    frame = Frame(tab, grid=(1,0))
    frame.expandGrid(2,1)

    div = LabelDivider(frame, text='Structures', grid=(0,0), gridSpan=(1,2))

    label = Label(frame, text='Ensemble: ', grid=(1,0))
    self.structurePulldown = PulldownList(frame, callback=self.changeStructure, grid=(1,1))

    headingList = ['Model','Use']
    editWidgets      = [None,None]
    editGetCallbacks = [None,self.toggleModel]
    editSetCallbacks = [None,None,]
    self.modelTable = ScrolledMatrix(frame, grid=(2,0), gridSpan=(1,2),
                                     callback=self.selectStructModel,
                                     editWidgets=editWidgets,
                                     editGetCallbacks=editGetCallbacks,
                                     editSetCallbacks=editSetCallbacks,
                                     headingList=headingList)

    texts = ['Activate Selected','Inactivate Selected']
    commands = [self.activateModels, self.disableModels]
    buttons = ButtonList(frame, texts=texts, commands=commands, grid=(3,0), gridSpan=(1,2))


    # # # # # # Submission frame # # # # # #

    tab = self.tabbedFrame.frames[1]
    tab.expandGrid(1,0)

    frame = LabelFrame(tab, text='Server Job Submission', grid=(0,0))
    frame.expandGrid(None,2)

    srow = 0
    label = Label(frame, text='iCing URL:', grid=(srow, 0))
    urls = [DEFAULT_URL,]
    self.iCingBaseUrlPulldown = PulldownList(frame, texts=urls, objects=urls, index=0, grid=(srow,1))


    srow +=1
    label = Label(frame, text='Results File:', grid=(srow, 0))
    self.resultFileEntry = Entry(frame, bd=1, text='', grid=(srow,1), width=50)
    self.setZipFileName()
    button = Button(frame, text='Choose File', bd=1, sticky='ew',
                    command=self.chooseZipFile, grid=(srow, 2))

    srow +=1
    label = Label(frame, text='Results URL:', grid=(srow, 0))
    self.resultUrlEntry = Entry(frame, bd=1, text='', grid=(srow,1), width=50)
    button = Button(frame, text='View Results HTML', bd=1, sticky='ew',
                    command=self.viewHtmlResults, grid=(srow, 2))

    srow +=1
    texts    = ['Submit Project!', 'Check Run Status',
                'Purge Server Result', 'Download Results']
    commands = [self.runCingServer, self.checkStatus,
                self.purgeCingServer, self.downloadResults]

    self.buttonBar = ButtonList(frame, texts=texts, commands=commands,
                                grid=(srow, 0), gridSpan=(1,3))

    for button in self.buttonBar.buttons[:1]:
      button.config(bg=CING_BLUE)

    # # # # # # Residue frame # # # # # #

    frame = LabelFrame(tab, text='Residue Options', grid=(1,0))
    frame.expandGrid(1,1)

    label = Label(frame, text='Chain: ')
    label.grid(row=0,column=0,sticky='w')
    self.chainPulldown = PulldownList(frame, callback=self.changeChain)
    self.chainPulldown.grid(row=0,column=1,sticky='w')

    headingList = ['#','Residue','Linking','Decriptor','Use?']
    editWidgets      = [None,None,None,None,None]
    editGetCallbacks = [None,None,None,None,self.toggleResidue]
    editSetCallbacks = [None,None,None,None,None,]
    self.residueMatrix = ScrolledMatrix(frame,
                                        headingList=headingList,
                                        multiSelect=True,
                                        editWidgets=editWidgets,
                                        editGetCallbacks=editGetCallbacks,
                                        editSetCallbacks=editSetCallbacks,
                                        callback=self.selectResidue)
    self.residueMatrix.grid(row=1, column=0, columnspan=2, sticky = 'nsew')

    texts = ['Activate Selected','Inactivate Selected']
    commands = [self.activateResidues, self.deactivateResidues]
    self.resButtons = ButtonList(frame, texts=texts, commands=commands,)
    self.resButtons.grid(row=2, column=0, columnspan=2, sticky='ew')

    """
    # # # # # # Validate frame # # # # # #

    frame = LabelFrame(tab, text='Validation Options', grid=(2,0))
    frame.expandGrid(None,2)

    srow = 0
    self.selectCheckAssign = CheckButton(frame)
    self.selectCheckAssign.grid(row=srow, column=0,sticky='nw' )
    self.selectCheckAssign.set(True)
    label = Label(frame, text='Assignments and shifts')
    label.grid(row=srow,column=1,sticky='nw')

    srow += 1
    self.selectCheckResraint = CheckButton(frame)
    self.selectCheckResraint.grid(row=srow, column=0,sticky='nw' )
    self.selectCheckResraint.set(True)
    label = Label(frame, text='Restraints')
    label.grid(row=srow,column=1,sticky='nw')

    srow += 1
    self.selectCheckQueen = CheckButton(frame)
    self.selectCheckQueen.grid(row=srow, column=0,sticky='nw' )
    self.selectCheckQueen.set(False)
    label = Label(frame, text='QUEEN')
    label.grid(row=srow,column=1,sticky='nw')

    srow += 1
    self.selectCheckScript = CheckButton(frame)
    self.selectCheckScript.grid(row=srow, column=0,sticky='nw' )
    self.selectCheckScript.set(False)
    label = Label(frame, text='User Python script\n(overriding option)')
    label.grid(row=srow,column=1,sticky='nw')

    self.validScriptEntry = Entry(frame, bd=1, text='')
    self.validScriptEntry.grid(row=srow,column=2,sticky='ew')

    scriptButton = Button(frame, bd=1,
                          command=self.chooseValidScript,
                          text='Browse')
    scriptButton.grid(row=srow,column=3,sticky='ew')
    """

    # # # # # # # # # #

    self.update(simStore)

    self.administerNotifiers(application.registerNotify)

  def downloadResults(self):

    if not self.run:
      msg = 'No current iCing run'
      showWarning('Failure', msg, parent=self)
      return

    credentials = self.serverCredentials
    if not credentials:
      msg = 'No current iCing server job'
      showWarning('Failure', msg, parent=self)
      return

    fileName = self.resultFileEntry.get()
    if not fileName:
      msg = 'No save file specified'
      showWarning('Failure', msg, parent=self)
      return

    if os.path.exists(fileName):
      msg = 'File %s already exists. Overwite?' % fileName
      if not showOkCancel('Query', msg, parent=self):
        return

    url = self.iCingBaseUrl
    iCingUrl = self.getServerUrl(url)
    logText = iCingRobot.iCingFetch(credentials, url, iCingUrl, fileName)
    print logText

    msg = 'Results saved to file %s\n' % fileName
    msg += 'Purge results from iCing server?'
    if showYesNo('Query',msg, parent=self):
      self.purgeCingServer()


  def getServerUrl(self, baseUrl):

    iCingUrl = os.path.join(baseUrl, 'icing/serv/iCingServlet')
    return iCingUrl

  def viewHtmlResults(self):

    resultsUrl = self.resultsUrl
    if not resultsUrl:
      msg = 'No current iCing results URL'
      showWarning('Failure', msg, parent=self)
      return

    webBrowser = WebBrowser(self.application, popup=self.application)
    webBrowser.open(self.resultsUrl)


  def runCingServer(self):

    if not self.project:
      return

    run = self.run
    if not run:
      msg = 'No CING run setup'
      showWarning('Failure', msg, parent=self)
      return

    structure = self.structure
    if not structure:
      msg = 'No structure ensemble selected'
      showWarning('Failure', msg, parent=self)
      return

    ensembleText = getModelsString(run)
    if not ensembleText:
      msg = 'No structural models selected from ensemble'
      showWarning('Failure', msg, parent=self)
      return

    residueText = getResiduesString(structure)
    if not residueText:
      msg = 'No active residues selected in structure'
      showWarning('Failure', msg, parent=self)
      return

    url = self.iCingBaseUrlPulldown.getObject()
    url.strip()
    if not url:
      msg = 'No iCing server URL specified'
      showWarning('Failure', msg, parent=self)
      self.iCingBaseUrl = None
      return

    msg = 'Submit job now? You will be informed when the job is done.'
    if not showOkCancel('Confirm', msg, parent=self):
      return

    self.iCingBaseUrl = url
    iCingUrl = self.getServerUrl(url)
    self.serverCredentials, results, tarFileName = iCingRobot.iCingSetup(self.project, userId='ccpnAp', url=iCingUrl)

    if not results:
      # Message already issued on failure
      self.serverCredentials = None
      self.resultsUrl = None
      self.update()
      return

    else:
      credentials = self.serverCredentials
      os.unlink(tarFileName)

    entryId = iCingRobot.iCingProjectName(credentials, iCingUrl).get(iCingRobot.RESPONSE_RESULT)
    baseUrl, htmlUrl, logUrl, zipUrl = iCingRobot.getResultUrls(credentials, entryId, url)

    self.resultsUrl = htmlUrl

    # Save server data in this run for persistence

    setRunParameter(run, iCingRobot.FORM_USER_ID, self.serverCredentials[0][1])
    setRunParameter(run, iCingRobot.FORM_ACCESS_KEY, self.serverCredentials[1][1])
    setRunParameter(run, ICING_BASE_URL, url)
    setRunParameter(run, HTML_RESULTS_URL, htmlUrl)
    self.update()

    run.inputStructures = structure.sortedModels()

    # select residues from the structure's chain
    #iCingRobot.iCingResidueSelection(credentials, iCingUrl, residueText)

    # Select models from ensemble
    #iCingRobot.iCingEnsembleSelection(credentials, iCingUrl, ensembleText)

    # Start the actual run
    self.serverDone = False
    iCingRobot.iCingRun(credentials, iCingUrl)

    # Fetch server progress occasionally, report when done
    # this function will call itself again and again
    self.after(CHECK_INTERVAL, self.timedCheckStatus)

    self.update()

  def timedCheckStatus(self):

    if not self.serverCredentials:
      return

    if self.serverDone:
      return

    status = iCingRobot.iCingStatus(self.serverCredentials, self.getServerUrl(self.iCingBaseUrl))

    if not status:
      #something broke, already warned
      return

    result = status.get(iCingRobot.RESPONSE_RESULT)
    if result == iCingRobot.RESPONSE_DONE:
      self.serverDone = True
      msg = 'CING run is complete!'
      showInfo('Completion', msg, parent=self)
      return

    self.after(CHECK_INTERVAL, self.timedCheckStatus)

  def checkStatus(self):

    if not self.serverCredentials:
      return

    status = iCingRobot.iCingStatus(self.serverCredentials, self.getServerUrl(self.iCingBaseUrl))

    if not status:
      #something broke, already warned
      return

    result = status.get(iCingRobot.RESPONSE_RESULT)
    if result == iCingRobot.RESPONSE_DONE:
      msg = 'CING run is complete!'
      showInfo('Completion', msg, parent=self)
      self.serverDone = True
      return

    else:
      msg = 'CING job is not done.'
      showInfo('Processing', msg, parent=self)
      self.serverDone = False
      return


  def purgeCingServer(self):

    if not self.project:
      return

    if not self.run:
      msg = 'No CING run setup'
      showWarning('Failure', msg, parent=self)
      return

    if not self.serverCredentials:
      msg = 'No current iCing server job'
      showWarning('Failure', msg, parent=self)
      return

    url = self.iCingBaseUrl
    results = iCingRobot.iCingPurge(self.serverCredentials, self.getServerUrl(url))

    if results:
      showInfo('Info','iCing server results cleared')
      self.serverCredentials = None
      self.iCingBaseUrl = None
      self.serverDone = False
      deleteRunParameter(self.run, iCingRobot.FORM_USER_ID)
      deleteRunParameter(self.run, iCingRobot.FORM_ACCESS_KEY)
      deleteRunParameter(self.run, HTML_RESULTS_URL)
    else:
      showInfo('Info','Purge failed')

    self.update()

  def chooseZipFile(self):

    fileTypes = [  FileType('Zip', ['*.zip']), ]
    popup = FileSelectPopup(self, file_types=fileTypes, file=self.resultFileEntry.get(),
                            title='Results zip file location', dismiss_text='Cancel',
                            selected_file_must_exist=False)

    fileName = popup.getFile()

    if fileName:
      self.resultFileEntry.set(fileName)
    popup.destroy()

  def setZipFileName(self):

    zipFile = '%s_CING_report.zip' % self.project.name
    self.resultFileEntry.set(zipFile)

  def selectStructModel(self, model, row, col):

    self.model = model

  def selectResidue(self, residue, row, col):

    self.residue = residue

  def deactivateResidues(self):

    for residue in self.residueMatrix.currentObjects:
      residue.useInCing = False

    self.updateResidues()

  def activateResidues(self):

    for residue in self.residueMatrix.currentObjects:
      residue.useInCing = True

    self.updateResidues()

  def activateModels(self):

    if self.run:
      for model in self.modelTable.currentObjects:
        if model not in self.run.inputStructures:
          self.run.addInputStructure(model)

      self.updateModels()

  def disableModels(self):

    if self.run:
      for model in self.modelTable.currentObjects:
        if model in self.run.inputStructures:
          self.run.removeInputStructure(model)

      self.updateModels()

  def toggleModel(self, *opt):

    if self.model and self.run:
      if self.model in self.run.inputStructures:
        self.run.removeInputStructure(self.model)
      else:
        self.run.addInputStructure(self.model)

      self.updateModels()

  def toggleResidue(self, *opt):

    if self.residue:
      self.residue.useInCing = not self.residue.useInCing
      self.updateResidues()


  def updateResidues(self):

    if self.residue and (self.residue.topObject is not self.structure):
      self.residue = None

    textMatrix = []
    objectList = []
    colorMatrix = []

    if self.chain:
      chainCode = self.chain.code

      for residue in self.chain.sortedResidues():
        msResidue = residue.residue

        if not hasattr(residue, 'useInCing'):
          residue.useInCing = True

        if residue.useInCing:
          colors = [None, None, None, None, CING_BLUE]
          use = 'Yes'

        else:
          colors = [None, None, None, None, None]
          use = 'No'

        datum = [residue.seqCode,
                 msResidue.ccpCode,
                 msResidue.linking,
                 msResidue.descriptor,
                 use,]

        textMatrix.append(datum)
        objectList.append(residue)
        colorMatrix.append(colors)

    self.residueMatrix.update(objectList=objectList,
                              textMatrix=textMatrix,
                              colorMatrix=colorMatrix)


  def updateChains(self):

    index = 0
    names = []
    chains = []
    chain = self.chain

    if self.structure:
      chains = self.structure.sortedCoordChains()
      names = [chain.code for chain in chains]

      if chains:
        if chain not in chains:
          chain = chains[0]
          index = chains.index(chain)

        self.changeChain(chain)

    self.chainPulldown.setup(names, chains, index)


  def updateStructures(self):

    index = 0
    names = []
    structures = []
    structure = self.structure

    if self.run:
      model = self.run.findFirstInputStructure()
      if model:
        structure = model.structureEnsemble

      structures0 = [(s.ensembleId, s) for s in self.project.structureEnsembles]
      structures0.sort()

      for eId, structure in structures0:
        name = '%s:%s' % (structure.molSystem.code, eId)
        structures.append(structure)
        names.append(name)

    if structures:
      if structure not in structures:
        structure = structures[-1]

      index = structures.index(structure)

    self.changeStructure(structure)

    self.structurePulldown.setup(names, structures, index)


  def updateModels(self):

    textMatrix = []
    objectList = []
    colorMatrix = []

    if self.structure and self.run:
      used = self.run.inputStructures

      for model in self.structure.sortedModels():


        if model in used:
          colors = [None, CING_BLUE]
          use = 'Yes'

        else:
          colors = [None, None]
          use = 'No'

        datum = [model.serial,use]

        textMatrix.append(datum)
        objectList.append(model)
        colorMatrix.append(colors)

    self.modelTable.update(objectList=objectList,
                           textMatrix=textMatrix,
                           colorMatrix=colorMatrix)


  def changeStructure(self, structure):

    if self.project and (self.structure is not structure):
      self.project.currentEstructureEnsemble = structure
      self.structure = structure

      if self.run:
        self.run.inputStructures = structure.sortedModels()

      self.updateModels()
      self.updateChains()


  def changeChain(self, chain):

    if self.project and (self.chain is not chain):
      self.chain = chain
      self.updateResidues()

  def chooseValidScript(self):

    # Prepend default Cyana file extension below
    fileTypes = [  FileType('Python', ['*.py']), ]
    popup = FileSelectPopup(self, file_types = fileTypes,
                            title='Python file', dismiss_text='Cancel',
                            selected_file_must_exist = True)

    fileName = popup.getFile()
    self.validScriptEntry.set(fileName)
    popup.destroy()

  def updateAll(self, project=None):

    if project:
      self.project = project
      self.nmrProject = project.currentNmrProject
      simStore = project.findFirstNmrSimStore(application='CING') or \
                 project.newNmrSimStore(application='CING', name='CING')
    else:
      simStore = None

    if not self.project:
      return

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

    self.update(simStore)

  def update(self, simStore=None):

    NmrSimRunFrame.update(self, simStore)

    run = self.run
    urls = [DEFAULT_URL,]
    index = 0

    if run:
      userId = getRunParameter(run, iCingRobot.FORM_USER_ID)
      accessKey = getRunParameter(run, iCingRobot.FORM_ACCESS_KEY)
      if userId and accessKey:
        self.serverCredentials = [(iCingRobot.FORM_USER_ID, userId),
                                  (iCingRobot.FORM_ACCESS_KEY, accessKey)]

      url = getRunParameter(run, ICING_BASE_URL)
      if url:
        htmlUrl = getRunParameter(run, HTML_RESULTS_URL)
        self.iCingBaseUrl = url
        self.resultsUrl = htmlUrl # May be None

      self.resultUrlEntry.set(self.resultsUrl)

      if self.iCingBaseUrl and self.iCingBaseUrl not in urls:
        index = len(urls)
        urls.append(self.iCingBaseUrl)

    self.iCingBaseUrlPulldown.setup(urls, urls, index)

    self.updateButtons()
    self.updateStructures()
    self.updateModels()
    self.updateChains()

  def updateButtons(self, event=None):

    buttons = self.buttonBar.buttons
    if self.project and self.run:
      buttons[0].enable()

      if self.resultsUrl and self.serverCredentials:
        buttons[1].enable()
        buttons[2].enable()
        buttons[3].enable()

      else:
        buttons[1].disable()
        buttons[2].disable()
        buttons[3].disable()

    else:
      buttons[0].disable()
      buttons[1].disable()
      buttons[2].disable()
      buttons[3].disable()
Example #20
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)
Example #21
0
    def body(self, guiFrame):

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

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

        #self.scrolledGraph.setZoom(0.7)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Fitting Function:', grid=(0, 0))

        tipText = 'Selects which form of function to fit to the experimental data'
        self.methodPulldown = PulldownList(frame,
                                           self.changeMethod,
                                           grid=(0, 1),
                                           tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        tipText = 'The effective equation of the final fitted graph, incorporating all parameters'
        self.equationLabel = Label(frame,
                                   text='Equation:',
                                   grid=(0, 0),
                                   tipText=tipText)

        tipText = 'The error in the fit of the selected parameterised function to the experimental data'
        self.errorLabel = Label(frame,
                                text='Fit Error:',
                                grid=(0, 1),
                                tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Include x origin?:', grid=(0, 0))

        tipText = 'Whether to include the x=0 point in the drawing'
        self.xOriginSelect = CheckButton(frame,
                                         callback=self.draw,
                                         grid=(0, 1),
                                         selected=False,
                                         tipText=tipText)

        label = Label(frame, text='Include y origin?:', grid=(0, 2))

        tipText = 'Whether to include the y=0 point in the drawing'
        self.yOriginSelect = CheckButton(frame,
                                         callback=self.draw,
                                         grid=(0, 3),
                                         selected=False,
                                         tipText=tipText)

        label = Label(frame, text='Include y error?:', grid=(0, 4))

        tipText = 'Whether to include the y error bars in the drawing (if these exist)'
        self.yErrorSelect = CheckButton(frame,
                                        callback=self.draw,
                                        grid=(0, 5),
                                        selected=False,
                                        tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Navigation Window:', grid=(0, 0))

        tipText = 'Selects which spectrum window will be used for navigating to peak positions'
        self.windowPanePulldown = PulldownList(frame,
                                               self.changeWindow,
                                               grid=(0, 1),
                                               tipText=tipText)

        label = Label(frame, text='Follow in window?:', grid=(0, 2))

        tipText = 'Whether to navigate to the position of the reference peak (for the group), in the selected window'
        self.followSelect = CheckButton(frame,
                                        callback=self.windowPaneNavigate,
                                        grid=(0, 3),
                                        selected=False,
                                        tipText=tipText)

        label = Label(frame, text='Mark Ref Peak?:', grid=(0, 4))

        tipText = 'Whether to put a multi-dimensional cross-mark through the reference peak position, so it can be identified in spectra'
        self.markSelect = CheckButton(frame,
                                      callback=None,
                                      tipText=tipText,
                                      grid=(0, 5),
                                      selected=False)

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)
        tipTexts = [
            'The number of the data point, in order of increasing X-axis value',
            'For each point, the value of the parameter which is varied in the NMR series, e.g. T1, temperature, concentration etc.',
            'For each point, the experimental value being fitted, e.g. peak intensity of chemical shift distance',
            'The value of the best-fit function at the X-axis location',
            'The difference between the experimental (Y-axis) value and the fitted value',
            'The error in the experimental (Y-axis) value'
        ]
        headingList = ['Point', 'x', 'y', 'Fitted y', u'\u0394', 'y error']
        self.scrolledMatrix = ScrolledMatrix(guiFrame,
                                             headingList=headingList,
                                             callback=self.selectObject,
                                             tipTexts=tipTexts,
                                             grid=(row, 0))

        row += 1
        tipTexts = [
            'Remove the selected data point, optionally removing the underlying peak',
            'Show a table of spectrum peaks that correspond to the selected data point'
        ]
        texts = ['Remove Point', 'Show Peak']
        commands = [self.removePoint, self.showObject]

        if self.prevSetFunction:
            texts.append('Previous Set')
            tipTexts.append(
                'Move to the previous set of fitted values; the next group of peaks, often corresponding to a different residue or resonance'
            )
            commands.append(self.prevSet)

        if self.nextSetFunction:
            tipTexts.append(
                'Move to the next set of fitted values; the next group of peaks, often corresponding to a different residue or resonance'
            )
            texts.append('Next Set')
            commands.append(self.nextSet)

        bottomButtons = UtilityButtonList(guiFrame,
                                          texts=texts,
                                          commands=commands,
                                          helpUrl=self.help_url,
                                          tipTexts=tipTexts,
                                          grid=(row, 0),
                                          doClone=False)
        self.removeButton = bottomButtons.buttons[0]

        for func in ('__init__', 'delete', 'setName'):
            self.registerNotify(self.updateWindows,
                                'ccpnmr.Analysis.SpectrumWindow', func)

        self.update()
Example #22
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)
Example #23
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)
Example #24
0
    def body(self, guiFrame):

        self.geometry('700x500')

        guiFrame.expandGrid(1, 0)

        row = 0

        # TOP LEFT FRAME

        frame = LabelFrame(guiFrame, text='Options')
        frame.grid(row=row, column=0, sticky='nsew')
        frame.columnconfigure(5, weight=1)

        label = Label(frame, text='Chain')
        label.grid(row=0, column=0, sticky='w')
        self.chainPulldown = PulldownList(
            frame,
            callback=self.changeChain,
            tipText='Choose the molecular system chain to make predictions for'
        )
        self.chainPulldown.grid(row=0, column=1, sticky='w')

        label = Label(frame, text='Shift List')
        label.grid(row=0, column=2, sticky='w')
        self.shiftListPulldown = PulldownList(
            frame,
            callback=self.changeShiftList,
            tipText='Select the shift list to take input chemical shifts from')
        self.shiftListPulldown.grid(row=0, column=3, sticky='w')

        row += 1

        # BOTTOM LEFT FRAME

        frame = LabelFrame(guiFrame, text='Secondary Structure Predictions')
        frame.grid(row=row, column=0, sticky='nsew')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        tipTexts = ('Residue number in chain', 'Residue type code',
                    'Current stored secondary structure code',
                    'Predicted secondary structure code') + SEC_STRUC_TIPS

        headingList = ('Res\nNum', 'Res\nType', 'Current\nSS',
                       'Predicted\nSS') + SEC_STRUC_KEYS

        n = len(headingList)
        editWidgets = n * [None]
        editGetCallbacks = n * [None]
        editSetCallbacks = n * [None]

        self.predictionMatrix = ScrolledMatrix(
            frame,
            headingList=headingList,
            tipTexts=tipTexts,
            editWidgets=editWidgets,
            editGetCallbacks=editGetCallbacks,
            editSetCallbacks=editSetCallbacks)
        self.predictionMatrix.grid(row=0, column=0, sticky='nsew')

        row += 1

        tipTexts = [
            'Run the D2D method to predict secondary structure',
            'Store the secondary structure predictions in the CCPN project'
        ]

        texts = [
            'Run D2D Prediction!', 'Commit Predicted\nSecondary Structure'
        ]
        commands = [self.runD2D, self.storeSecondaryStructure]
        self.buttonList = createDismissHelpButtonList(guiFrame,
                                                      texts=texts,
                                                      commands=commands,
                                                      help_url=self.help_url,
                                                      expands=True,
                                                      tipTexts=tipTexts)
        self.buttonList.grid(row=row, column=0, columnspan=2, sticky='ew')

        self.update()

        self.notify(self.registerNotify)
class SpectrumSelectionTab(object):
    '''Class describing the tab containing a big table with
       all the spectra. The user can select which spectra from
       the project to use with the assignment algorithm. For
       each spectrum a peak list and a labelling scheme can be
       selected.
    '''

    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.specConfigList = []

        self.displayTable = None
        self.selectedAutoSpec = None
        self.autoLabellingPulldown = None
        self.autoPeakListPulldown = None

        self.body()
        self.updateSpecSelection()
        # self.setupSpectrumSettings()
        self.updateAutoMatrix()

    def body(self):
        '''Sets up the body of this view.'''

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

        headingList = [
            '#', 'Spectrum', 'Peak List', 'use?', 'labelling scheme']

        tipTexts = ['Row number', 'spectrum name',
                    'which peak list to use',
                    'use this spectrum?',
                    'Which labelling scheme belongs to this spectrum?']

        self.autoLabellingPulldown = PulldownList(
            self.guiParent, self.setAutoLabellingScheme)
        self.autoPeakListPulldown = PulldownList(
            self.guiParent, self.setAutoPeakList)

        editWidgets = [None, None, self.autoPeakListPulldown,
                       None, self.autoLabellingPulldown]

        editGetCallbacks = [None, None, self.getAutoPeakLists,
                            self.changeUse, self.getAutoLabellingSchemes]

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

        self.displayTable = ScrolledMatrix(frame, headingList=headingList,
                                           callback=self.selectAutoSpec,
                                           editWidgets=editWidgets,
                                           multiSelect=False,
                                           editGetCallbacks=editGetCallbacks,
                                           editSetCallbacks=editSetCallbacks,
                                           tipTexts=tipTexts)
        self.displayTable.grid(row=2, column=0, sticky='nsew')

    def updateSpecSelection(self):
        '''Update the list with spectrum settings.
           This function can be called to initialize
           this list or to update it when some spectra
           are added in the project.
        '''

        # TODO: also implement what has to happen
        # when spectra get deleted from the project.

        presentSpectrumSettings = set([specSetting.ccpnSpectrum for specSetting in self.specConfigList])

        for expt in self.nmrProject.sortedExperiments():
            for spec in expt.sortedDataSources():
                if spec.dataType == 'processed' and spec not in presentSpectrumSettings:

                    newSpectrumSetting = SpectrumSettings()
                    newSpectrumSetting.ccpnSpectrum = spec
                    newSpectrumSetting.peakList = spec.getActivePeakList()
                    self.specConfigList.append(newSpectrumSetting)

    def getLabellingSchemes(self):
        '''Returns all labellinSchemes in the project'''

        return [True, None, ] + self.project.sortedLabelingSchemes()

    def setAutoLabellingScheme(self, scheme):
        '''Select a labelling scheme for the
           selected spectrum.
        '''

        self.selectedAutoSpec.setupLabellingScheme(scheme)
        self.updateAutoMatrix()

    def getAutoLabellingSchemes(self, notifyScheme=None):
        '''Sets up the the pulldown lists with labelling schemes
           used for the pulldown lists.
        '''
        #names = []
        #index = 0
        #
        #scheme = self.selectedAutoSpec.labellingScheme
        #schemes = self.getLabellingSchemes()
        #
        #
        # if schemes:
        #  names = ['Automatic from sample','<None>'] + [sc.name for sc in schemes[2:]]
        #
        #  index = schemes.index(scheme)

        names = ['Automatic from sample']
        schemes = [True]
        index = 0

        self.autoLabellingPulldown.setup(names, schemes, index)

    def setAutoPeakList(self, peakList):
        '''Select a peakList for the selected spectrum.'''

        self.selectedAutoSpec.setupPeakList(peakList)

        self.updateAutoMatrix()

    def selectAutoSpec(self, obj, *args, **kwargs):
        '''Set the selection of a spectrum in the table.
           args:
               obj: (SpectrumSettings) the spectrum that
                    should be selected.
        '''

        self.selectedAutoSpec = obj

    def getAutoPeakLists(self, *args, **kwargs):
        '''Set up the the autoPeakListPulldown for the
           selected spectrum.
        '''

        names = []
        index = 0

        peakList = self.selectedAutoSpec.peakList

        peakLists = self.selectedAutoSpec.ccpnSpectrum.sortedPeakLists()

        if peakLists:
            names = [str(pl.serial) for pl in peakLists]

            index = peakLists.index(peakList)

        self.autoPeakListPulldown.setup(names, peakLists, index)

    def changeUse(self, *args):
        '''Toggle whether a spectrum is used in the
           procedure or not.
        '''

        if self.selectedAutoSpec.used is False:
            self.selectedAutoSpec.changeSpectrumUse(True)
        elif self.selectedAutoSpec.used is True:
            self.selectedAutoSpec.changeSpectrumUse(False)

        self.updateAutoMatrix()

    def updateAutoMatrix(self):
        '''Update the whole table.'''

        textMatrix = []
        colorMatrix = []

        spectra = self.specConfigList

        for i, spectrum in enumerate(spectra):

            dataSource = spectrum.ccpnSpectrum
            expt = dataSource.experiment

            name = '%s:%s' % (expt.name, dataSource.name)

            peakListName = str(spectrum.peakList.serial)

            if spectrum.labellingScheme is None:
                schemeName = 'None'

            elif spectrum.labellingScheme is True:

                schemeName = 'Automatic from sample'

            else:

                schemeName = spectrum.labellingScheme.name

            datum = [i + 1, name, peakListName,
                     spectrum.used and 'Yes' or 'No', schemeName]

            textMatrix.append(datum)

            hexColors = dataSource.analysisSpectrum.posColors
            hexColor = hexColors[int(0.7 * len(hexColors))]

            if spectrum.used:

                colorMatrix.append([hexColor,
                                    hexColor,
                                    hexColor,
                                    hexColor,
                                    hexColor])

            else:

                colorMatrix.append([hexColor, None, None, None, None])

        self.displayTable.update(textMatrix=textMatrix,
                                 objectList=spectra,
                                 colorMatrix=colorMatrix)

    def update(self, *args):
        '''update the view'''

        self.updateSpecSelection()
        self.updateAutoMatrix()
Example #26
0
  def __init__(self, parent, application, *args, **kw):

    project = application.project
    simStore = project.findFirstNmrSimStore(application=APP_NAME) or \
               project.newNmrSimStore(application=APP_NAME, name=APP_NAME)

    self.application = application
    self.residue = None
    self.structure = None
    self.serverCredentials = None
    self.iCingBaseUrl = DEFAULT_URL
    self.resultsUrl = None
    self.chain = None
    self.nmrProject = application.nmrProject
    self.serverDone = False

    NmrSimRunFrame.__init__(self, parent, project, simStore, *args, **kw)

    # # # # # # New Structure Frame # # # # #

    self.structureFrame.grid_forget()

    tab = self.tabbedFrame.frames[0]

    frame = Frame(tab, grid=(1,0))
    frame.expandGrid(2,1)

    div = LabelDivider(frame, text='Structures', grid=(0,0), gridSpan=(1,2))

    label = Label(frame, text='Ensemble: ', grid=(1,0))
    self.structurePulldown = PulldownList(frame, callback=self.changeStructure, grid=(1,1))

    headingList = ['Model','Use']
    editWidgets      = [None,None]
    editGetCallbacks = [None,self.toggleModel]
    editSetCallbacks = [None,None,]
    self.modelTable = ScrolledMatrix(frame, grid=(2,0), gridSpan=(1,2),
                                     callback=self.selectStructModel,
                                     editWidgets=editWidgets,
                                     editGetCallbacks=editGetCallbacks,
                                     editSetCallbacks=editSetCallbacks,
                                     headingList=headingList)

    texts = ['Activate Selected','Inactivate Selected']
    commands = [self.activateModels, self.disableModels]
    buttons = ButtonList(frame, texts=texts, commands=commands, grid=(3,0), gridSpan=(1,2))


    # # # # # # Submission frame # # # # # #

    tab = self.tabbedFrame.frames[1]
    tab.expandGrid(1,0)

    frame = LabelFrame(tab, text='Server Job Submission', grid=(0,0))
    frame.expandGrid(None,2)

    srow = 0
    label = Label(frame, text='iCing URL:', grid=(srow, 0))
    urls = [DEFAULT_URL,]
    self.iCingBaseUrlPulldown = PulldownList(frame, texts=urls, objects=urls, index=0, grid=(srow,1))


    srow +=1
    label = Label(frame, text='Results File:', grid=(srow, 0))
    self.resultFileEntry = Entry(frame, bd=1, text='', grid=(srow,1), width=50)
    self.setZipFileName()
    button = Button(frame, text='Choose File', bd=1, sticky='ew',
                    command=self.chooseZipFile, grid=(srow, 2))

    srow +=1
    label = Label(frame, text='Results URL:', grid=(srow, 0))
    self.resultUrlEntry = Entry(frame, bd=1, text='', grid=(srow,1), width=50)
    button = Button(frame, text='View Results HTML', bd=1, sticky='ew',
                    command=self.viewHtmlResults, grid=(srow, 2))

    srow +=1
    texts    = ['Submit Project!', 'Check Run Status',
                'Purge Server Result', 'Download Results']
    commands = [self.runCingServer, self.checkStatus,
                self.purgeCingServer, self.downloadResults]

    self.buttonBar = ButtonList(frame, texts=texts, commands=commands,
                                grid=(srow, 0), gridSpan=(1,3))

    for button in self.buttonBar.buttons[:1]:
      button.config(bg=CING_BLUE)

    # # # # # # Residue frame # # # # # #

    frame = LabelFrame(tab, text='Residue Options', grid=(1,0))
    frame.expandGrid(1,1)

    label = Label(frame, text='Chain: ')
    label.grid(row=0,column=0,sticky='w')
    self.chainPulldown = PulldownList(frame, callback=self.changeChain)
    self.chainPulldown.grid(row=0,column=1,sticky='w')

    headingList = ['#','Residue','Linking','Decriptor','Use?']
    editWidgets      = [None,None,None,None,None]
    editGetCallbacks = [None,None,None,None,self.toggleResidue]
    editSetCallbacks = [None,None,None,None,None,]
    self.residueMatrix = ScrolledMatrix(frame,
                                        headingList=headingList,
                                        multiSelect=True,
                                        editWidgets=editWidgets,
                                        editGetCallbacks=editGetCallbacks,
                                        editSetCallbacks=editSetCallbacks,
                                        callback=self.selectResidue)
    self.residueMatrix.grid(row=1, column=0, columnspan=2, sticky = 'nsew')

    texts = ['Activate Selected','Inactivate Selected']
    commands = [self.activateResidues, self.deactivateResidues]
    self.resButtons = ButtonList(frame, texts=texts, commands=commands,)
    self.resButtons.grid(row=2, column=0, columnspan=2, sticky='ew')

    """
    # # # # # # Validate frame # # # # # #

    frame = LabelFrame(tab, text='Validation Options', grid=(2,0))
    frame.expandGrid(None,2)

    srow = 0
    self.selectCheckAssign = CheckButton(frame)
    self.selectCheckAssign.grid(row=srow, column=0,sticky='nw' )
    self.selectCheckAssign.set(True)
    label = Label(frame, text='Assignments and shifts')
    label.grid(row=srow,column=1,sticky='nw')

    srow += 1
    self.selectCheckResraint = CheckButton(frame)
    self.selectCheckResraint.grid(row=srow, column=0,sticky='nw' )
    self.selectCheckResraint.set(True)
    label = Label(frame, text='Restraints')
    label.grid(row=srow,column=1,sticky='nw')

    srow += 1
    self.selectCheckQueen = CheckButton(frame)
    self.selectCheckQueen.grid(row=srow, column=0,sticky='nw' )
    self.selectCheckQueen.set(False)
    label = Label(frame, text='QUEEN')
    label.grid(row=srow,column=1,sticky='nw')

    srow += 1
    self.selectCheckScript = CheckButton(frame)
    self.selectCheckScript.grid(row=srow, column=0,sticky='nw' )
    self.selectCheckScript.set(False)
    label = Label(frame, text='User Python script\n(overriding option)')
    label.grid(row=srow,column=1,sticky='nw')

    self.validScriptEntry = Entry(frame, bd=1, text='')
    self.validScriptEntry.grid(row=srow,column=2,sticky='ew')

    scriptButton = Button(frame, bd=1,
                          command=self.chooseValidScript,
                          text='Browse')
    scriptButton.grid(row=srow,column=3,sticky='ew')
    """

    # # # # # # # # # #

    self.update(simStore)

    self.administerNotifiers(application.registerNotify)
Example #27
0
class FileSelect(Frame):
    def __init__(self,
                 parent,
                 file_types=None,
                 directory=None,
                 single_callback=None,
                 double_callback=None,
                 select_dir_callback=None,
                 change_dir_callback=None,
                 should_change_dir_callback=None,
                 prompt=None,
                 show_file=True,
                 file='',
                 multiSelect=False,
                 default_dir=None,
                 getRowColor=None,
                 getExtraCell=None,
                 extraHeadings=None,
                 extraJustifies=None,
                 displayExtra=True,
                 manualFileFilter=False,
                 extraTipTexts=None,
                 *args,
                 **kw):

        if file_types is None:
            file_types = [FileType("All", ["*"])]

        if manualFileFilter:
            self.manualFilter = FileType("Manual")
            file_types.append(self.manualFilter)
        else:
            self.manualFilter = None

        if directory is None:
            directory = normalisePath(os.getcwd())

        if extraHeadings is None:
            extraHeadings = ()
        else:
            extraHeadings = tuple(extraHeadings)

        if extraJustifies is None:
            extraJustifies = ()
        else:
            extraJustifies = tuple(extraJustifies)

        if extraHeadings or extraJustifies:
            assert len(extraHeadings) == len(extraJustifies)
            assert getExtraCell

        self.extraHeadings = extraHeadings
        self.extraJustifies = extraJustifies
        self.extraTipTexts = extraTipTexts or []
        self.displayExtra = displayExtra

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

        self.file_types = file_types
        self.fileType = file_types[0]
        self.single_callback = single_callback
        self.double_callback = double_callback
        self.select_dir_callback = select_dir_callback
        self.change_dir_callback = change_dir_callback
        self.should_change_dir_callback = should_change_dir_callback
        self.show_file = show_file
        self.directory = None
        self.historyBack = []
        self.historyFwd = []
        self.determineDir(directory)
        self.default_dir = default_dir
        self.getRowColor = getRowColor
        self.getExtraCell = getExtraCell

        self.grid_columnconfigure(0, weight=1)

        row = 0
        if prompt:
            label = Label(self, text=prompt, grid=(row, 0))
            row += 1

        self.grid_rowconfigure(row, weight=1)
        if show_file:
            headings = ('Name', 'Size', 'Date')
            justifies = ('left', 'right', 'right')
            tipTexts = [
                'Name of file, directory or link', 'Size of file in bytes',
                'Date of last modification'
            ]
        else:
            headings = ('Directory', )
            justifies = ('left', )
            tipTexts = ['Name of directory']

        self.normalHeadings = headings
        self.normalJustifies = justifies
        self.normalTipTexts = tipTexts
        headings = headings + extraHeadings
        justifies = justifies + extraJustifies
        tipTexts += [None] * len(extraHeadings)

        self.fileList = ScrolledMatrix(self,
                                       headingList=headings,
                                       justifyList=justifies,
                                       initialRows=10,
                                       callback=self.singleCallback,
                                       doubleCallback=self.doubleCallback,
                                       tipTexts=tipTexts,
                                       multiSelect=multiSelect,
                                       grid=(row, 0))

        row += 1
        tipTexts = [
            'Go to previous location in history',
            'Go forward in location history', 'Go up one directory level',
            'Go to root directory', 'Go to home directory',
            'Make a new directory', 'Refresh directory listing'
        ]

        texts = ['Back', 'Forward', 'Up', 'Top', 'Home', 'New', 'Refresh']
        commands = [
            self.backDir, self.fwdDir, self.upDir, self.topDir, self.homeDir,
            self.createDir, self.updateFileList
        ]

        if self.default_dir:
            texts.append('Default')
            commands.append(self.setDefaultDir)
            tipTexts.append('Set the current directory as the default')

        self.icons = []
        for name in ICON_NAMES:
            icon = Tkinter.PhotoImage(
                file=os.path.join(GFX_DIR, name + '.gif'))
            self.icons.append(icon)

        self.buttons = ButtonList(self,
                                  texts=texts,
                                  commands=commands,
                                  images=self.icons,
                                  grid=(row, 0),
                                  tipTexts=tipTexts)

        if show_file:
            row += 1
            self.file_entry = LabeledEntry(self,
                                           label='File name',
                                           label_width=10,
                                           entry_width=40,
                                           returnCallback=self.setSelectedFile)
            self.file_entry.grid(row=row, column=0, sticky=Tkinter.EW)
        else:
            self.file_entry = None

        row += 1
        self.directory_entry = LabeledEntry(self,
                                            label='Directory',
                                            entry=directory,
                                            label_width=10,
                                            entry_width=40,
                                            returnCallback=self.entryDir)
        self.directory_entry.grid(row=row, column=0, sticky=Tkinter.EW)

        row += 1
        subFrame = Frame(self, grid=(row, 0))
        subFrame.expandGrid(None, 6)

        if show_file:

            label = Label(subFrame, text='File type:', grid=(0, 0))

            type_labels = self.determineTypeLabels()
            self.fileType_menu = PulldownList(
                subFrame,
                callback=self.typeCallback,
                texts=type_labels,
                objects=self.file_types,
                grid=(0, 1),
                tipText='Restrict listed files to selected suffix')

        label = Label(subFrame, text=' Show hidden:', grid=(0, 2))

        self.hidden_checkbutton = CheckButton(
            subFrame,
            text='',
            selected=False,
            callback=self.updateFileList,
            grid=(0, 3),
            tipText='Show hidden files beginning with "." etc.')

        label = Label(subFrame, text='Dir path:', grid=(0, 4))

        self.pathMenu = PulldownList(
            subFrame,
            callback=self.dirCallback,
            objects=range(len(self.dirs)),
            texts=self.dirs,
            index=len(self.dirs) - 1,
            indent='  ',
            prefix=dirsep,
            grid=(0, 5),
            tipText='Directory navigation to current location')

        if show_file and self.manualFilter is not None:
            row += 1
            self.manual_filter_entry = LabeledEntry(
                self,
                label='Manual Select',
                entry=defaultFilter,
                label_width=13,
                entry_width=40,
                returnCallback=self.entryFilter,
                tipText=
                'Path specification with wildcards to select multiple files')
            self.manual_filter_entry.grid(row=row, column=0, sticky=Tkinter.EW)

        self.updateFileList()
        self.updateButtons()

        if file:
            self.setFile(file)

    def updateDisplayExtra(self, displayExtra):

        self.displayExtra = displayExtra
        self.updateFileList()

    def isRootDirectory(self, directory=''):

        if not directory:
            directory = self.directory

        if directory:
            return os.path.dirname(directory) == directory

        return True  # arbitrary

    def updateButtons(self):

        buttons = self.buttons.buttons
        isRoot = self.isRootDirectory

        if self.historyBack:
            buttons[0].enable()
        else:
            buttons[0].disable()

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

        if self.directory and not isRoot(self.directory):
            buttons[2].enable()
            buttons[3].enable()
        else:
            buttons[2].disable()
            buttons[3].disable()

        homeDir = self.getHomeDir()
        if homeDir and os.path.isdir(homeDir):
            buttons[4].enable()
        else:
            buttons[4].disable()

    def backDir(self):

        if self.historyBack:
            self.historyFwd.insert(0, self.directory)
            dirName = self.historyBack.pop()
            self.changeDir(dirName, addHistory=False)

    def fwdDir(self):

        if self.historyFwd:
            self.historyBack.append(self.directory)
            dirName = self.historyFwd.pop(0)
            self.changeDir(dirName, addHistory=False)

    def topDir(self):

        if self.directory:
            isRoot = self.isRootDirectory
            dirName = self.directory
            while not isRoot(dirName):
                dirName = joinPath(dirName, os.pardir)

            self.changeDir(dirName)

    def homeDir(self):

        homeDir = self.getHomeDir()
        if homeDir:
            self.changeDir(homeDir)

    def getHomeDir(self):

        return os.environ.get('HOME') or os.environ.get('HOMEPATH')

    def upDir(self):

        self.changeDir(joinPath(self.directory, os.pardir))

    def setDefaultDir(self):

        self.changeDir(self.default_dir)

    def createDir(self):

        from memops.gui.DataEntry import askString

        msg = 'Enter new sub-directory name'
        dirName = askString('New directory', msg, parent=self)
        if dirName:
            dirName = joinPath(self.directory, dirName)
            if os.path.exists(dirName):
                msg = 'Directory "%s" already exists' % dirName
                showError('Directory exists', msg, parent=self)
            else:
                os.mkdir(dirName)
                self.updateFileList()

    def determineTypeLabels(self):

        type_labels = []
        for t in self.file_types:
            s = t.message + ' (' + ', '.join(t.filters) + ')'
            type_labels.append(s)

        return type_labels

    def setFileTypes(self, file_types):

        self.file_types = file_types
        if self.fileType not in file_types:
            self.fileType = file_types[0]
        if self.show_file:
            ind = self.file_types.index(self.fileType)
            type_labels = self.determineTypeLabels()
            self.fileType_menu.setup(type_labels, self.file_types, ind)
            self.updateFileList()

    def determineDir(self, directory):

        directory = normalisePath(directory)

        assert os.path.isdir(directory), '"%s" is not a directory' % directory

        self.prev_directory = self.directory

        if not os.path.isabs(directory):
            if self.directory is None:  # first time around
                directory = joinPath(normalisePath(os.getcwd()), directory)
            else:
                directory = joinPath(self.directory, directory)

        self.directory = directory
        self.dirs = self.directory.split(dirsep)

    def setSelectedFile(self, *event):

        file = self.file_entry.getEntry()
        try:
            self.fileList.selectObject(file)
        except:
            showError('Some err', 'some err')

    def entryDir(self, *event):

        dirName = self.directory_entry.getEntry()
        try:
            self.changeDir(dirName)
        except:
            showError('Not a directory',
                      '"' + dirName + '" is not a directory.')

    def entryFilter(self, *event):

        filterString = self.manual_filter_entry.getEntry()
        filters = [str.strip(x) for x in filterString.split(',')]
        self.manualFilter.filters = filters
        self.fileType = self.manualFilter

        self.setFileTypes(
            self.file_types)  # to trigger update after filter change
        self.updateFileList()

        self.manual_filter_entry.setEntry(filterString)

    def changeDir(self, dirName, addHistory=True):

        if not os.path.isdir(dirName):
            return

        if self.should_change_dir_callback:
            if not self.should_change_dir_callback(dirName):
                return

        oldDir = self.directory

        self.determineDir(dirName)
        self.updateFileList()
        self.directory_entry.setEntry(self.directory)

        if self.change_dir_callback:
            self.change_dir_callback(self.directory)

        nDirs = len(self.dirs)

        self.pathMenu.setup(self.dirs, range(nDirs), index=nDirs - 1)

        if addHistory:
            if oldDir and (self.directory != oldDir):
                self.historyBack.append(oldDir)
            self.historyFwd = []

        self.updateButtons()

    def getEntryInfo(self, entry):

        file = joinPath(self.directory, entry)

        if os.path.islink(file):
            # plain arrow: u' \u2192 '
            entry = entry + u' \u21D2 ' + unicode(os.readlink(file), 'utf-8')
            size = None
            color = '#E0D0C0'

        elif os.path.isdir(file):
            if not self.isRootDirectory(entry):
                entry = entry + dirsep
            size = None
            color = '#C0D0C0'

        else:
            color = '#C0C0D0'

            if self.show_file:
                try:
                    size = str(os.path.getsize(file))
                except:
                    size = None
            else:
                size = None

        try:
            fileTime = self.fileTime(file)
        except:
            fileTime = ''

        return (entry, size, fileTime, color)

    def getDrives(self):

        if isWindowsOS():
            #import win32api
            #drives = win32api.GetLogicalDriveStrings()
            #drives = drives.split('\x00')
            #drives = [normalisePath(drive) for drive in drives if drive]
            #drives.sort()
            # 19 Mar 2012: do not use win32api because not standard
            from ctypes import windll
            import string
            drives = []
            bitmask = windll.kernel32.GetLogicalDrives()
            for letter in string.ascii_uppercase:
                if bitmask & 1:
                    drives.append(letter)
                bitmask >>= 1
            drives = [drive + ':\\' for drive in drives]
            drives = [normalisePath(drive) for drive in drives]
        else:
            drives = []

        return drives

    def updateFileList(self, *extra):

        try:
            if self.directory:
                directory = self.directory
            else:
                directory = dirsep
            entries = self.getFilterFiles(directory)
        except OSError, e:
            showError('OS Error', str(e))
            if self.prev_directory:
                self.directory = None
                self.changeDir(self.prev_directory)
            return

        if self.directory:
            if self.isRootDirectory():
                entries[:0] = [
                    drive for drive in self.getDrives()
                    if drive not in self.directory
                ]
            else:
                entries[:0] = [os.pardir
                               ]  # add parent directory at front of list

        # DJOD: Not elegant, but robust !?!
        showHidden = self.hidden_checkbutton.getSelected()
        show_ent = []
        for entry in entries:
            if not showHidden:
                if not entry.startswith('.'):
                    show_ent.append(entry)
            else:
                show_ent.append(entry)

        # if not show_ent.__contains__('.'):
        #   show_ent.append('.')

        if not show_ent.__contains__('..'):
            show_ent.insert(0, '..')

        entries = show_ent

        textMatrix = []
        colorMatrix = []
        for entryActual in entries:

            (entry, size, fileTime, color) = self.getEntryInfo(entryActual)
            fullEntry = joinPath(directory, entryActual)
            if self.getRowColor:
                color = self.getRowColor(fullEntry)

            if self.displayExtra and self.getExtraCell:
                data = self.getExtraCell(fullEntry)
                headingList = self.normalHeadings + self.extraHeadings
                justifyList = self.normalJustifies + self.extraJustifies
                tipTexts = self.normalTipTexts + self.extraTipTexts
            else:
                data = ()
                headingList = self.normalHeadings
                justifyList = self.normalJustifies
                tipTexts = self.normalTipTexts
                # in case we had sorted on a now removed line :
                self.fileList.lastSortLine = None

            if self.show_file:
                text = [entry, size, fileTime]
            else:
                text = [
                    entry,
                ]
            text = text + list(data)

            textMatrix.append(text)
            numCols = len(headingList)
            colorMatrix.append(numCols * [color])

        self.fileList.update(objectList=entries,
                             textMatrix=textMatrix,
                             colorMatrix=colorMatrix,
                             headingList=headingList,
                             justifyList=justifyList,
                             tipTexts=tipTexts)
Example #28
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)  
Example #29
0
    def __init__(self,
                 parent,
                 file_types=None,
                 directory=None,
                 single_callback=None,
                 double_callback=None,
                 select_dir_callback=None,
                 change_dir_callback=None,
                 should_change_dir_callback=None,
                 prompt=None,
                 show_file=True,
                 file='',
                 multiSelect=False,
                 default_dir=None,
                 getRowColor=None,
                 getExtraCell=None,
                 extraHeadings=None,
                 extraJustifies=None,
                 displayExtra=True,
                 manualFileFilter=False,
                 extraTipTexts=None,
                 *args,
                 **kw):

        if file_types is None:
            file_types = [FileType("All", ["*"])]

        if manualFileFilter:
            self.manualFilter = FileType("Manual")
            file_types.append(self.manualFilter)
        else:
            self.manualFilter = None

        if directory is None:
            directory = normalisePath(os.getcwd())

        if extraHeadings is None:
            extraHeadings = ()
        else:
            extraHeadings = tuple(extraHeadings)

        if extraJustifies is None:
            extraJustifies = ()
        else:
            extraJustifies = tuple(extraJustifies)

        if extraHeadings or extraJustifies:
            assert len(extraHeadings) == len(extraJustifies)
            assert getExtraCell

        self.extraHeadings = extraHeadings
        self.extraJustifies = extraJustifies
        self.extraTipTexts = extraTipTexts or []
        self.displayExtra = displayExtra

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

        self.file_types = file_types
        self.fileType = file_types[0]
        self.single_callback = single_callback
        self.double_callback = double_callback
        self.select_dir_callback = select_dir_callback
        self.change_dir_callback = change_dir_callback
        self.should_change_dir_callback = should_change_dir_callback
        self.show_file = show_file
        self.directory = None
        self.historyBack = []
        self.historyFwd = []
        self.determineDir(directory)
        self.default_dir = default_dir
        self.getRowColor = getRowColor
        self.getExtraCell = getExtraCell

        self.grid_columnconfigure(0, weight=1)

        row = 0
        if prompt:
            label = Label(self, text=prompt, grid=(row, 0))
            row += 1

        self.grid_rowconfigure(row, weight=1)
        if show_file:
            headings = ('Name', 'Size', 'Date')
            justifies = ('left', 'right', 'right')
            tipTexts = [
                'Name of file, directory or link', 'Size of file in bytes',
                'Date of last modification'
            ]
        else:
            headings = ('Directory', )
            justifies = ('left', )
            tipTexts = ['Name of directory']

        self.normalHeadings = headings
        self.normalJustifies = justifies
        self.normalTipTexts = tipTexts
        headings = headings + extraHeadings
        justifies = justifies + extraJustifies
        tipTexts += [None] * len(extraHeadings)

        self.fileList = ScrolledMatrix(self,
                                       headingList=headings,
                                       justifyList=justifies,
                                       initialRows=10,
                                       callback=self.singleCallback,
                                       doubleCallback=self.doubleCallback,
                                       tipTexts=tipTexts,
                                       multiSelect=multiSelect,
                                       grid=(row, 0))

        row += 1
        tipTexts = [
            'Go to previous location in history',
            'Go forward in location history', 'Go up one directory level',
            'Go to root directory', 'Go to home directory',
            'Make a new directory', 'Refresh directory listing'
        ]

        texts = ['Back', 'Forward', 'Up', 'Top', 'Home', 'New', 'Refresh']
        commands = [
            self.backDir, self.fwdDir, self.upDir, self.topDir, self.homeDir,
            self.createDir, self.updateFileList
        ]

        if self.default_dir:
            texts.append('Default')
            commands.append(self.setDefaultDir)
            tipTexts.append('Set the current directory as the default')

        self.icons = []
        for name in ICON_NAMES:
            icon = Tkinter.PhotoImage(
                file=os.path.join(GFX_DIR, name + '.gif'))
            self.icons.append(icon)

        self.buttons = ButtonList(self,
                                  texts=texts,
                                  commands=commands,
                                  images=self.icons,
                                  grid=(row, 0),
                                  tipTexts=tipTexts)

        if show_file:
            row += 1
            self.file_entry = LabeledEntry(self,
                                           label='File name',
                                           label_width=10,
                                           entry_width=40,
                                           returnCallback=self.setSelectedFile)
            self.file_entry.grid(row=row, column=0, sticky=Tkinter.EW)
        else:
            self.file_entry = None

        row += 1
        self.directory_entry = LabeledEntry(self,
                                            label='Directory',
                                            entry=directory,
                                            label_width=10,
                                            entry_width=40,
                                            returnCallback=self.entryDir)
        self.directory_entry.grid(row=row, column=0, sticky=Tkinter.EW)

        row += 1
        subFrame = Frame(self, grid=(row, 0))
        subFrame.expandGrid(None, 6)

        if show_file:

            label = Label(subFrame, text='File type:', grid=(0, 0))

            type_labels = self.determineTypeLabels()
            self.fileType_menu = PulldownList(
                subFrame,
                callback=self.typeCallback,
                texts=type_labels,
                objects=self.file_types,
                grid=(0, 1),
                tipText='Restrict listed files to selected suffix')

        label = Label(subFrame, text=' Show hidden:', grid=(0, 2))

        self.hidden_checkbutton = CheckButton(
            subFrame,
            text='',
            selected=False,
            callback=self.updateFileList,
            grid=(0, 3),
            tipText='Show hidden files beginning with "." etc.')

        label = Label(subFrame, text='Dir path:', grid=(0, 4))

        self.pathMenu = PulldownList(
            subFrame,
            callback=self.dirCallback,
            objects=range(len(self.dirs)),
            texts=self.dirs,
            index=len(self.dirs) - 1,
            indent='  ',
            prefix=dirsep,
            grid=(0, 5),
            tipText='Directory navigation to current location')

        if show_file and self.manualFilter is not None:
            row += 1
            self.manual_filter_entry = LabeledEntry(
                self,
                label='Manual Select',
                entry=defaultFilter,
                label_width=13,
                entry_width=40,
                returnCallback=self.entryFilter,
                tipText=
                'Path specification with wildcards to select multiple files')
            self.manual_filter_entry.grid(row=row, column=0, sticky=Tkinter.EW)

        self.updateFileList()
        self.updateButtons()

        if file:
            self.setFile(file)
class SpinSystemComparePopup(BasePopup):
    '''The popop for comparing spin systems to one another.'''

    def __init__(self, parent, *args, **kw):
        '''Init. Args: parent: guiParent.

        '''

        self.guiParent = parent
        self.spinSystem1 = None
        self.spinSystem2 = None
        self.correction = True
        self.protonatedShiftList = None
        self.deuteratedShiftList = None
        BasePopup.__init__(self, parent, title="Compare Spin Systems", **kw)
        self.waiting = False

    def open(self):

        self.updateAfter()
        BasePopup.open(self)

    def body(self, guiFrame):
        '''This method describes the outline of the body of the
           application.
               args: guiFrame: frame the body should live in.

        '''

        self.geometry('800x530')

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

        isotopeFrame = LabelFrame(guiFrame, text='Isotope Shift Correction CA and CB')
        isotopeFrame.grid(row=0, column=0, sticky='nsew')

        frameA = LabelFrame(guiFrame, text='Spin Systems')
        frameA.grid(row=1, column=0, sticky='nsew')
        frameA.grid_rowconfigure(0, weight=1)
        frameA.grid_columnconfigure(0, weight=1)
        frameA.grid_columnconfigure(1, weight=1)

        frameA1 = LabelFrame(frameA, text='Spin System 1')
        frameA1.grid(row=0, column=0, sticky='nsew')
        frameA1.grid_columnconfigure(0, weight=1)
        frameA1.grid_rowconfigure(0, weight=1)

        frameA2 = LabelFrame(frameA, text='Spin System 2')
        frameA2.grid(row=0, column=1, sticky='nsew')
        frameA2.grid_columnconfigure(0, weight=1)
        frameA2.grid_rowconfigure(0, weight=1)

        frameB = LabelFrame(guiFrame, text='Comparison')
        frameB.grid(row=2, column=0, sticky='nsew')

        frameB.grid_rowconfigure(0, weight=1)
        frameB.grid_columnconfigure(0, weight=1)
        frameB.grid_columnconfigure(1, weight=2)
        frameB.grid_columnconfigure(2, weight=1)

        frameB1 = LabelFrame(frameB, text='Unique to Spin System 1')
        frameB1.grid(row=0, column=0, sticky='nsew')
        frameB1.expandGrid(0, 0)

        frameB2 = LabelFrame(frameB, text='Intersection')
        frameB2.grid(row=0, column=1, sticky='nsew')
        frameB2.expandGrid(0, 0)

        frameB3 = LabelFrame(frameB, text='Unique to Spin System 2')
        frameB3.grid(row=0, column=2, sticky='nsew')
        frameB3.expandGrid(0, 0)

        # Settings for isotope shift correction

        shiftLists = getShiftLists(self.nmrProject)
        self.protonatedShiftList = shiftLists[0]
        self.deuteratedShiftList = shiftLists[1]
        shiftListNames = ['{}: {}'.format(shiftList.serial, shiftList.name) for shiftList in shiftLists]

        Label(isotopeFrame, text='Correct for isotope shift:', grid=(0, 0))
        self.correctCheck = CheckButton(isotopeFrame,
                                        selected=True,
                                        callback=self.setCorrection,
                                        grid=(0, 1))
        Label(isotopeFrame, text='Protonated shift list:', grid=(1, 0))
        self.protonatedPulldown = PulldownList(isotopeFrame,
                                               callback=self.setProtonatedShiftList,
                                               texts=shiftListNames,
                                               objects=shiftLists,
                                               grid=(1, 1),
                                               index=0)

        Label(isotopeFrame, text='Deuterated shift list:', grid=(2, 0))
        self.deuteratedPulldown = PulldownList(isotopeFrame,
                                               callback=self.setDeuteratedShiftList,
                                               texts=shiftListNames,
                                               objects=shiftLists,
                                               grid=(2, 1),
                                               index=1)



        # Table A1
        headingList = ['#', 'shift lists', 'Assignment']

        tipTexts = ['Spin System Serial',
                    'shift lists', 'The residue (tentatively) assigned to this spin system',
                    'The amount of spin systems that overlap with this spin system and have no violations']

        editGetCallbacks = [self.setSpinSystem1]*3
        editSetCallbacks = [None]*3
        self.tableA1 = ScrolledMatrix(frameA1, headingList=headingList,
                                      multiSelect=False,
                                      editGetCallbacks=editGetCallbacks,
                                      editSetCallbacks=editSetCallbacks,
                                      tipTexts=tipTexts)
        self.tableA1.grid(row=0, column=0, sticky='nsew')

        # Table A2
        headingList = ['#', 'shift lists', 'Assignment', 'offset']
        tipTexts = ['Spin System Serial', 'The residue (tentatively) assigned to this spin system',
                    'Root mean squared deviation of this spin system to the spin system selected in the table on the left.']
        editGetCallbacks = [self.setSpinSystem2]*4
        editSetCallbacks = [None]*4
        self.tableA2 = ScrolledMatrix(frameA2, headingList=headingList,
                                      #editWidgets=editWidgets,
                                      multiSelect=False,
                                      editGetCallbacks=editGetCallbacks,
                                      editSetCallbacks=editSetCallbacks,
                                      tipTexts=tipTexts)
        self.tableA2.grid(row=0, column=0, sticky='nsew')

        # Table B1
        headingList = ['atom', 'c.s.']
        tipTexts = ['atom', 'chemical shift']
        self.tableB1 = ScrolledMatrix(frameB1,
                                      headingList=headingList,
                                      multiSelect=False,
                                      tipTexts=tipTexts)
        self.tableB1.grid(row=0, column=0, sticky='nsew')

        # Table B 2
        headingList = ['atom', 'c.s. 1', 'c.s. 2', 'delta c.s.']
        tipTexts = ['name of the atom', 'chemical shift of atom with this name in spin system 1',
                    'chemical shift of atom with this name in spin system 2',
                    'difference between the chemical shift of spin systems 1 and 2']

        self.tableB2 = ScrolledMatrix(frameB2,
                                      headingList=headingList,
                                      tipTexts=tipTexts)
        self.tableB2.grid(row=0, column=0, sticky='nsew')

        # Table B 3
        headingList = ['atom', 'c.s.']
        tipTexts = ['atom', 'chemical shift.']
        self.tableB3 = ScrolledMatrix(frameB3,
                                      headingList=headingList,
                                      multiSelect=False,
                                      tipTexts=tipTexts)
        self.tableB3.grid(row=0, column=0, sticky='nsew')

        self.matchMatrix = {}
        self.amountOfMatchesPerSpinSystem = {}

        self.updateTableA1()

    def update(self):
        '''Updates all tables except for tableA1.

        '''

        self.updateTableA2()
        self.updateCompareTables()

    def setCorrection(self, selected):
        '''Toggles on/off whether the isotope correction should
           be applied or not.
               args:    selected: Boolean, is True if isotope
                                  correction is to be applied.

        '''
        if self.correction is not selected:
            self.correction = selected
            self.update()

    def setProtonatedShiftList(self, shiftList):
        '''Set the shift list where protonated values of
           the chemical shifts should be fetched.
               args:    shiftList: shift list with
                        protonated shifts.

        '''

        if not self.protonatedShiftList is shiftList:
            self.protonatedShiftList = shiftList
            self.update()

    def setDeuteratedShiftList(self, shiftList):
        '''Set the shift list where deuterated values of
           the chemical shifts should be fetched.
               args:    shiftList: shift list with
                        deuterated shifts.

        '''

        if not self.deuteratedShiftList is shiftList:
            self.deuteratedShiftList = shiftList
            self.update()

    def setSpinSystem1(self, spinSystem):
        '''Set the first of two spin systems that should
           be compared.
               args:    spinSystem: first of two spin systems

        '''

        if spinSystem is not self.spinSystem1:

            self.spinSystem1 = spinSystem
            self.updateTableA2()

    def setSpinSystem2(self, spinSystem):
        '''Set the second of two spin systems that should
           be compared.
               args:    spinSystem: second of two spin systems

        '''

        if spinSystem is not self.spinSystem2:

            self.spinSystem2 = spinSystem
            self.updateCompareTables()

    def updateTableA1(self):
        '''Update tableA1 where the first spin systems is picked from.

        '''

        data = []
        objectList = []
        spinSystems = self.nmrProject.resonanceGroups

        for spinSystem in spinSystems:
            objectList.append(spinSystem)
            shiftLists_string = make_shiftLists_string(find_all_shiftLists_for_resonanceGroup(spinSystem))
            data.append([spinSystem.serial,
                         shiftLists_string,
                         make_resonanceGroup_string(spinSystem)])

        self.tableA1.update(objectList=objectList, textMatrix=data)
        self.tableA1.sortLine(2)

    def updateTableA2(self):
        '''Update tableA2 where the second spin systems is picked from.

        '''

        if not self.spinSystem1:
            return

        comparisons = self.compareToSpinSystem(self.spinSystem1)

        data = []
        objectList = []
        colorMatrix = []

        for comp in comparisons:

            resonanceGroup = comp.spinSystem2

            objectList.append(resonanceGroup)
            oneRow = []
            oneRow.append(resonanceGroup.serial)
            shiftLists_string = make_shiftLists_string(find_all_shiftLists_for_resonanceGroup(resonanceGroup))
            oneRow.append(shiftLists_string)
            oneRow.append(make_resonanceGroup_string(resonanceGroup))

            if comp.deviation is None:
                oneRow.append('-')
            else:
                oneRow.append(comp.deviation)

            if comp.match:
                colorMatrix.append(['#298A08']*4)
            else:
                colorMatrix.append([None]*4)

            data.append(oneRow)


        data, objectList, colorMatrix = zip(*sorted(zip(data, objectList, colorMatrix), key=lambda x: x[0][3]))
        self.tableA2.update(objectList=objectList,
                            textMatrix=data,
                            colorMatrix=colorMatrix)

    def updateCompareTables(self):
        '''Update all tables that compare 2 spin systems. These are the
           diff tables that show resonances unique to either one of the
           spin systems and the union table, where resonance types that
           are present in both spin systems are compared by chemical shift.

        '''

        if not self.spinSystem1 or not self.spinSystem2:
            return

        spinSystemComp = self.compare2spinSystems(self.spinSystem1,
                                                  self.spinSystem2)
        self.updateUnionTable(spinSystemComp)
        self.updateDiffTables(spinSystemComp)

    def updateDiffTables(self, spinSystemComp):
        '''Update the two tables that show the resonance types that are
           unique to respectively either the first or the second spin system.
           args:    spinSystemComp:    SpinSystemComparison comparing the two
                                       selected spin systems.

        '''

        for shiftedShifts, table in [(spinSystemComp.unique_to_1, self.tableB1),
                                     (spinSystemComp.unique_to_2, self.tableB3)]:
            data = []
            for shiftedShift in shiftedShifts:

                data.append([shiftedShift.create_name(),
                             shiftedShift.create_shift_description()])

            table.update(objectList=data, textMatrix=data)

    def updateUnionTable(self, spinSystemComp):
        '''Update the table that shows the resonance types that are
           present in both spin systems.
           args:    spinSystemComp:    SpinSystemComparison comparing the two
                                       selected spin systems.

        '''

        intersectData = []
        colorMatrix = []

        for resComp in spinSystemComp.intersection:

            oneRow = [resComp.resonance_name]
            oneRow.extend(resComp.shifts_description)
            oneRow.append(resComp.delta)
            intersectData.append(oneRow)

            if resComp.match:
                colorMatrix.append(['#298A08']*4)
            else:
                colorMatrix.append([None]*4)

        self.tableB2.update(objectList=intersectData,
                            textMatrix=intersectData,
                            colorMatrix=colorMatrix)

    def compareToSpinSystem(self, spinSystem):
        '''Compare one spin system to all others.
           args:    spinSystem:    spin system
           returns: list of SpinSystemComparison objects.

        '''

        spinSystems = self.nmrProject.resonanceGroups
        comparisons = []

        for spinSystem2 in spinSystems:

            comparisons.append(self.compare2spinSystems(spinSystem,
                                                        spinSystem2))

        return comparisons

    def compare2spinSystems(self, spinSystem1, spinSystem2):
        '''Compare two spin systems to each other.
           args:    spinSystem1:    the first spin system
                    spinSystem2:    the second spin system
           returns: SpinSystemComparison object

        '''

        comp = SpinSystemComparison(spinSystem1=spinSystem1,
                                    spinSystem2=spinSystem2,
                                    isotope_correction=self.correction,
                                    protonatedShiftList=self.protonatedShiftList,
                                    deuteratedShiftList=self.deuteratedShiftList)
        return comp
Example #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
Example #32
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)
Example #33
0
class EditFitGraphPopup(BasePopup):
    """
  **Analyse Function Curve Fitting to Peak Series Data**
  
  This popup is used to display the fit of a curve, of the displayed equation
  type, to data that has been extracted for a group of spectrum peaks from an
  NMR series. Precisely which kind of data is being fitted depends on the parent
  tool that this popup window was launched from. For example, for the `Follow
  Intensity Changes`_ tool the displayed graph is of a time or frequency value
  on the "X" axis (e.g. T1) verses peak intensity. For the `Follow Shift
  Changes`_ system the plot is for the parameters of the experiment titration on
  the "X" axis (e.g concentration) verses chemical shift distance.

  The upper graph shows the peak data that was used; the blue points, and the
  points of the fitted theoretical curve; red points. The lower table lists the
  data points for all of the peaks in the group, to which the data relates.
  There will be one peak for each row of the table, and hence point on the "X"
  axis. For each data point in the table the corresponding peak from which the
  data was extracted may be located with the "Follow in window" option, using
  the stated spectrum window and making marker lines as desired. Alternatively,
  the peak may be viewed in a table with [Show Peak]

  In general operation this system is used to check how well the selected
  function curve fits the peak data. The data that is displayed comes from the
  analysis tool that launched this popup. Any outliers may be removed using
  [Remove Point] (only with good reason) or the peaks themselves may be
  corrected if something has gone awry. Given that the display is launched from
  the selection of a specific group of peaks from a popup like `Follow Shift
  Changes`_  or `Follow Intensity Changes`_ and there are usually several peak
  groups that need to be analysed, the [Previous Set] and [Next Set] buttons can
  be used to quickly jump to the next peak group and see the next curve in the
  analysis results.

  .. _`Follow Intensity Changes`: CalcRatesPopup.html
  .. _`Follow Shift Changes`: FollowShiftChangesPopup.html

  """
    def __init__(self,
                 parent,
                 dataFitting,
                 getXYfunction,
                 updateFunction,
                 xLabel,
                 yLabel,
                 showObjectFunction=None,
                 nextSetFunction=None,
                 prevSetFunction=None,
                 graphTitle='',
                 **kw):

        self.guiParent = parent
        self.getXYfunction = getXYfunction
        self.updateFunction = updateFunction
        self.nextSetFunction = nextSetFunction
        self.prevSetFunction = prevSetFunction
        self.dataFitting = dataFitting
        self.object = None
        self.xLabel = xLabel
        self.yLabel = yLabel
        self.x = []
        self.y = []
        self.yFit = []
        self.params = ()
        self.chiSq = 0
        self.method = dataFitting.fitFunction
        self.waiting = False
        self.noiseLevel = dataFitting.noiseLevel
        self.graphTitle = graphTitle
        self.windowPane = None
        self.mark = None

        BasePopup.__init__(self, parent=parent, title='Fit Graph', **kw)
        parent.protocol("WM_DELETE_WINDOW", self.close)

    def body(self, guiFrame):

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

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

        #self.scrolledGraph.setZoom(0.7)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Fitting Function:', grid=(0, 0))

        tipText = 'Selects which form of function to fit to the experimental data'
        self.methodPulldown = PulldownList(frame,
                                           self.changeMethod,
                                           grid=(0, 1),
                                           tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        tipText = 'The effective equation of the final fitted graph, incorporating all parameters'
        self.equationLabel = Label(frame,
                                   text='Equation:',
                                   grid=(0, 0),
                                   tipText=tipText)

        tipText = 'The error in the fit of the selected parameterised function to the experimental data'
        self.errorLabel = Label(frame,
                                text='Fit Error:',
                                grid=(0, 1),
                                tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Include x origin?:', grid=(0, 0))

        tipText = 'Whether to include the x=0 point in the drawing'
        self.xOriginSelect = CheckButton(frame,
                                         callback=self.draw,
                                         grid=(0, 1),
                                         selected=False,
                                         tipText=tipText)

        label = Label(frame, text='Include y origin?:', grid=(0, 2))

        tipText = 'Whether to include the y=0 point in the drawing'
        self.yOriginSelect = CheckButton(frame,
                                         callback=self.draw,
                                         grid=(0, 3),
                                         selected=False,
                                         tipText=tipText)

        label = Label(frame, text='Include y error?:', grid=(0, 4))

        tipText = 'Whether to include the y error bars in the drawing (if these exist)'
        self.yErrorSelect = CheckButton(frame,
                                        callback=self.draw,
                                        grid=(0, 5),
                                        selected=False,
                                        tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Navigation Window:', grid=(0, 0))

        tipText = 'Selects which spectrum window will be used for navigating to peak positions'
        self.windowPanePulldown = PulldownList(frame,
                                               self.changeWindow,
                                               grid=(0, 1),
                                               tipText=tipText)

        label = Label(frame, text='Follow in window?:', grid=(0, 2))

        tipText = 'Whether to navigate to the position of the reference peak (for the group), in the selected window'
        self.followSelect = CheckButton(frame,
                                        callback=self.windowPaneNavigate,
                                        grid=(0, 3),
                                        selected=False,
                                        tipText=tipText)

        label = Label(frame, text='Mark Ref Peak?:', grid=(0, 4))

        tipText = 'Whether to put a multi-dimensional cross-mark through the reference peak position, so it can be identified in spectra'
        self.markSelect = CheckButton(frame,
                                      callback=None,
                                      tipText=tipText,
                                      grid=(0, 5),
                                      selected=False)

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)
        tipTexts = [
            'The number of the data point, in order of increasing X-axis value',
            'For each point, the value of the parameter which is varied in the NMR series, e.g. T1, temperature, concentration etc.',
            'For each point, the experimental value being fitted, e.g. peak intensity of chemical shift distance',
            'The value of the best-fit function at the X-axis location',
            'The difference between the experimental (Y-axis) value and the fitted value',
            'The error in the experimental (Y-axis) value'
        ]
        headingList = ['Point', 'x', 'y', 'Fitted y', u'\u0394', 'y error']
        self.scrolledMatrix = ScrolledMatrix(guiFrame,
                                             headingList=headingList,
                                             callback=self.selectObject,
                                             tipTexts=tipTexts,
                                             grid=(row, 0))

        row += 1
        tipTexts = [
            'Remove the selected data point, optionally removing the underlying peak',
            'Show a table of spectrum peaks that correspond to the selected data point'
        ]
        texts = ['Remove Point', 'Show Peak']
        commands = [self.removePoint, self.showObject]

        if self.prevSetFunction:
            texts.append('Previous Set')
            tipTexts.append(
                'Move to the previous set of fitted values; the next group of peaks, often corresponding to a different residue or resonance'
            )
            commands.append(self.prevSet)

        if self.nextSetFunction:
            tipTexts.append(
                'Move to the next set of fitted values; the next group of peaks, often corresponding to a different residue or resonance'
            )
            texts.append('Next Set')
            commands.append(self.nextSet)

        bottomButtons = UtilityButtonList(guiFrame,
                                          texts=texts,
                                          commands=commands,
                                          helpUrl=self.help_url,
                                          tipTexts=tipTexts,
                                          grid=(row, 0),
                                          doClone=False)
        self.removeButton = bottomButtons.buttons[0]

        for func in ('__init__', 'delete', 'setName'):
            self.registerNotify(self.updateWindows,
                                'ccpnmr.Analysis.SpectrumWindow', func)

        self.update()

    def destroy(self):

        for func in ('__init__', 'delete', 'setName'):
            self.unregisterNotify(self.updateWindows,
                                  'ccpnmr.Analysis.SpectrumWindow', func)

        BasePopup.destroy(self)

    def nextSet(self):

        if self.nextSetFunction:
            self.nextSetFunction()
            self.windowPaneNavigate()

    def prevSet(self):

        if self.prevSetFunction:
            self.prevSetFunction()
            self.windowPaneNavigate()

    def windowPaneNavigate(self, event=None):

        if self.followSelect.get() and self.dataFitting:
            peaks = self.dataFitting.objects
            if self.windowPane and peaks:
                peak = peaks[int(len(peaks) / 2)]

                windowFrame = self.windowPane.getWindowFrame()
                windowFrame.gotoPeak(peak)

                if self.markSelect.get():
                    if self.mark and not self.mark.isDeleted:
                        self.mark.delete()

                    self.mark = createPeakMark(self.dataFitting.refObject)

    def getWindows(self):

        peaks = self.scrolledMatrix.objectList

        windowPanes = []
        if peaks:
            peak = peaks[0]
            project = peak.root
            spectrum = peak.peakList.dataSource
            tryWindows = getActiveWindows(project)
            for window in tryWindows:
                for windowPane in window.sortedSpectrumWindowPanes():
                    if isSpectrumInWindowPane(windowPane, spectrum):
                        windowPanes.append(windowPane)

        return windowPanes

    def changeWindow(self, windowPane):

        if windowPane is not self.windowPane:
            self.windowPane = windowPane
            self.windowPaneNavigate()

    def updateWindows(self, window=None):

        windowPanes = self.getWindows()
        index = -1
        names = [getWindowPaneName(wp) for wp in windowPanes]
        windowPane = self.windowPane

        if windowPanes:
            if windowPane not in windowPanes:
                windowPane = windowPanes[0]

            index = windowPanes.index(windowPane)

        if windowPane is not self.windowPane:
            self.windowPane = windowPane
            self.windowPaneNavigate()

        self.windowPanePulldown.setup(names, windowPanes, index)

    def showObject(self):

        if self.object and (self.object.className == 'Peak'):
            peaks = [self.object]
            self.guiParent.guiParent.viewPeaks(peaks)

    def close(self):

        BasePopup.close(self)

    def changeMethod(self, index):

        if self.dataFitting:
            self.method = index
            self.dataFitting.fitFunction = self.method

        self.updateAfter()

    def updateMethods(self, *opt):

        n = len(METHOD_NAMES)
        if self.method >= n:
            self.method = 1

        self.methodPulldown.setup(METHOD_NAMES, range(n), self.method)

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

        if object:
            self.object = object
            self.updateButtons()

    def removePoint(self):

        if self.object and (len(self.dataFitting.objects) > 2):
            self.dataFitting.objects.remove(self.object)
            if showYesNo('Query',
                         'Delete the corresponding %s?' %
                         (self.object.className),
                         parent=self):
                self.object.delete()
            self.updateAfter()

    def draw(self, *junk):

        title = '%s Function fit %s' % (self.graphTitle,
                                        METHOD_NAMES[self.method])
        dataSet1 = []
        dataSet2 = []
        useErr = self.yErrorSelect.isSelected()
        if not useErr:
            useErr = None
        for i in range(len(self.scrolledMatrix.textMatrix)):
            row = self.scrolledMatrix.textMatrix[i]
            x = row[1]
            y = row[2]
            y2 = row[3]
            err = useErr and row[5]
            dataSet1.append([x, y, err])
            dataSet2.append([x, y2])

        dataSet1.sort()
        dataSet2.sort()

        if dataSet1 and dataSet2:
            drawOriginX = self.xOriginSelect.isSelected()
            drawOriginY = self.yOriginSelect.isSelected()
            self.scrolledGraph.update(dataSets=[dataSet1, dataSet2],
                                      xLabel=self.xLabel,
                                      yLabel=self.yLabel,
                                      title=title,
                                      drawOriginX=drawOriginX,
                                      drawOriginY=drawOriginY)
            self.scrolledGraph.draw()

    def updateAfter(self, *object):

        if self.waiting:
            return
        else:
            self.waiting = True
            self.after_idle(self.update)

    def update(self,
               dataFitting=None,
               xLabel=None,
               yLabel=None,
               graphTitle=None,
               force=False):

        if (not force) and dataFitting and (self.dataFitting is dataFitting):
            if (self.method, self.xLabel, self.yLabel, self.noiseLevel) == \
               (self.dataFitting.fitFunction, xLabel, yLabel, self.dataFitting.noiseLevel):
                self.waiting = False
                return

        if dataFitting:
            self.dataFitting = dataFitting

        self.xLabel = xLabel or self.xLabel
        self.yLabel = yLabel or self.yLabel
        self.graphTitle = graphTitle or self.graphTitle

        if not self.dataFitting:
            self.waiting = False
            return
        else:
            dataFitting = self.dataFitting
            dataFitting = self.getXYfunction(dataFitting)
            if dataFitting.fitFunction is not None:
                self.method = dataFitting.fitFunction
            self.noiseLevel = dataFitting.noiseLevel or self.noiseLevel
        self.updateMethods()

        isFitted = dataFitting.fit()

        textMatrix = []
        objectList = []

        if isFitted and self.method:
            methodInfo = getFitMethodInfo()[self.method - 1]
            textFormat, indices = methodInfo[2]
            textParams = [dataFitting.parameters[i] or 0 for i in indices]
            equationText = textFormat % tuple(textParams)
            errorText = '%4f' % dataFitting.fitError

            x = dataFitting.dataX
            y = dataFitting.dataY
            yFit = dataFitting.fittedY
            N = len(x)
            err = hasattr(dataFitting, 'dataErr') and dataFitting.dataErr
            if not err:
                err = None

            # wb104: 10 Mar 2014: not sure why the below was here, it isn't needed
            #if self.method == 10:
            #  x = [sqrt(v) for v in x]

            data = [(x[i], y[i], yFit[i], y[i] - yFit[i],
                     dataFitting.objects[i], err and err[i]) for i in range(N)]
            data.sort()
            for i in range(N):
                xi, yi, yFiti, deltai, object, erri = data[i]
                textMatrix.append([i + 1, xi, yi, yFiti, deltai, erri])
                objectList.append(object)

        else:
            equationText = 'Equation: <No Fit>'
            errorText = '<None>'
            x = dataFitting.dataX
            y = dataFitting.dataY

            for i, x in enumerate(x):
                textMatrix.append([i + 1, x, y[i], None, None, None])
                objectList.append(dataFitting.objects[i])

        self.equationLabel.set('Equation: %s' % equationText)
        self.errorLabel.set('Fit Error: %s' % errorText)
        self.scrolledMatrix.update(textMatrix=textMatrix,
                                   objectList=objectList)

        self.updateWindows()
        self.updateButtons()

        self.draw()

        if self.updateFunction:
            self.updateFunction(dataFitting)

        self.waiting = False

    def updateButtons(self):

        if self.object:
            self.removeButton.enable()
        else:
            self.removeButton.disable()
Example #34
0
    def body(self, guiFrame):

        guiFrame.grid_columnconfigure(2, weight=1)

        row = 0
        label = Label(guiFrame, text='Template window: ', grid=(row, 0))
        tipText = 'Selects which window to use as the basis for making a new spectrum window; sets the axis types accordingly'
        self.window_list = PulldownList(guiFrame,
                                        grid=(row, 1),
                                        callback=self.setAxisTypes,
                                        tipText=tipText)
        frame = LabelFrame(guiFrame,
                           text='Strips',
                           grid=(row, 2),
                           gridSpan=(2, 1))
        buttons = UtilityButtonList(guiFrame,
                                    doClone=False,
                                    helpUrl=self.help_url,
                                    grid=(row, 3))

        row += 1
        label = Label(guiFrame, text='New window name: ', grid=(row, 0))
        tipText = 'A short name to identify the spectrum window, which will appear in the graphical interface'
        self.nameEntry = Entry(guiFrame,
                               width=16,
                               grid=(row, 1),
                               tipText=tipText)

        row += 1

        label = Label(frame, text='Columns: ', grid=(0, 0))
        tipText = 'The number of vertical strips/dividers to initially make in the spectrum window'
        self.cols_menu = PulldownList(frame,
                                      objects=STRIP_NUMS,
                                      grid=(0, 1),
                                      texts=[str(x) for x in STRIP_NUMS],
                                      tipText=tipText)

        label = Label(frame, text='Rows: ', grid=(0, 2))
        tipText = 'The number of horizontal strips/dividers to initially make in the spectrum window'
        self.rows_menu = PulldownList(frame,
                                      objects=STRIP_NUMS,
                                      grid=(0, 3),
                                      texts=[str(x) for x in STRIP_NUMS],
                                      tipText=tipText)
        row += 1
        div = LabelDivider(guiFrame,
                           text='Axes',
                           grid=(row, 0),
                           gridSpan=(1, 4))

        row += 1
        self.axis_lists = {}
        frame = Frame(guiFrame, grid=(row, 0), gridSpan=(1, 4))

        col = 0
        self.axisTypes = {}
        self.axisTypesIncludeNone = {}
        for label in AXIS_LABELS:
            self.axisTypes[label] = None
            w = Label(frame, text=' ' + label)
            w.grid(row=0, column=col, sticky='w')
            col += 1

            if label in ('x', 'y'):
                includeNone = False
                tipText = 'Sets the kind of measurement (typically ppm for a given isotope) that will be used along the window %s axis' % label
            else:
                includeNone = True
                tipText = 'Where required, sets the kind of measurement (typically ppm for a given isotope) that will be used along the window %s axis' % label
            self.axisTypesIncludeNone[label] = includeNone

            getAxisTypes = lambda label=label: self.getAxisTypes(label)
            callback = lambda axisType, label=label: self.changedAxisType(
                label, axisType)
            self.axis_lists[label] = PulldownList(frame,
                                                  callback=callback,
                                                  tipText=tipText)
            self.axis_lists[label].grid(row=0, column=col, sticky='w')
            col += 1

        frame.grid_columnconfigure(col, weight=1)

        row += 1
        div = LabelDivider(guiFrame,
                           text='Viewed Spectra',
                           grid=(row, 0),
                           gridSpan=(1, 4))

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)

        editWidgets = [None, None, None, None]
        editGetCallbacks = [None, self.toggleVisible, self.toggleToolbar, None]
        editSetCallbacks = [None, None, None, None]
        tipTexts = [
            'The "experiment:spectrum" name for the spectrum that may be viewed in the new window, given the axis selections',
            'Sets whether the spectrum contours will be visible in the new window',
            'Sets whether the spectrum appears at all in the window; if not in the toolbar it cannot be displayed',
            'The number of peak lists the spectrum contains'
        ]
        headingList = ['Spectrum', 'Visible?', 'In Toolbar?', 'Peak Lists']

        self.scrolledMatrix = ScrolledMatrix(guiFrame,
                                             headingList=headingList,
                                             editWidgets=editWidgets,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks,
                                             multiSelect=True,
                                             grid=(row, 0),
                                             gridSpan=(1, 4),
                                             tipTexts=tipTexts)

        row += 1
        tipTexts = [
            'Creates a new spectrum window with the specified parameters',
            'Sets the contours of the selected spectra to be visible when the new window is made',
            'Sets the contours of the selected spectra to not be displayed when the new window is made',
            'Sets the selected spectra as absent from the window toolbar, and thus not displayable at all'
        ]
        texts = [
            'Create Window!', 'Selected\nVisible', 'Selected\nNot Visible',
            'Selected\nNot In Toolbar'
        ]
        commands = [
            self.ok, self.setSelectedDisplay, self.setSelectedHide,
            self.setSelectedAbsent
        ]
        buttonList = ButtonList(guiFrame,
                                texts=texts,
                                grid=(row, 0),
                                commands=commands,
                                gridSpan=(1, 4),
                                tipTexts=tipTexts)
        buttonList.buttons[0].config(bg='#B0FFB0')

        self.updateAxisTypes()
        self.updateWindow()
        self.updateWindowName()

        self.administerNotifiers(self.registerNotify)
        self.updateAfter()
Example #35
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)
    def body(self, guiFrame):
        '''This method describes the outline of the body of the
           application.
               args: guiFrame: frame the body should live in.

        '''

        self.geometry('800x530')

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

        isotopeFrame = LabelFrame(guiFrame, text='Isotope Shift Correction CA and CB')
        isotopeFrame.grid(row=0, column=0, sticky='nsew')

        frameA = LabelFrame(guiFrame, text='Spin Systems')
        frameA.grid(row=1, column=0, sticky='nsew')
        frameA.grid_rowconfigure(0, weight=1)
        frameA.grid_columnconfigure(0, weight=1)
        frameA.grid_columnconfigure(1, weight=1)

        frameA1 = LabelFrame(frameA, text='Spin System 1')
        frameA1.grid(row=0, column=0, sticky='nsew')
        frameA1.grid_columnconfigure(0, weight=1)
        frameA1.grid_rowconfigure(0, weight=1)

        frameA2 = LabelFrame(frameA, text='Spin System 2')
        frameA2.grid(row=0, column=1, sticky='nsew')
        frameA2.grid_columnconfigure(0, weight=1)
        frameA2.grid_rowconfigure(0, weight=1)

        frameB = LabelFrame(guiFrame, text='Comparison')
        frameB.grid(row=2, column=0, sticky='nsew')

        frameB.grid_rowconfigure(0, weight=1)
        frameB.grid_columnconfigure(0, weight=1)
        frameB.grid_columnconfigure(1, weight=2)
        frameB.grid_columnconfigure(2, weight=1)

        frameB1 = LabelFrame(frameB, text='Unique to Spin System 1')
        frameB1.grid(row=0, column=0, sticky='nsew')
        frameB1.expandGrid(0, 0)

        frameB2 = LabelFrame(frameB, text='Intersection')
        frameB2.grid(row=0, column=1, sticky='nsew')
        frameB2.expandGrid(0, 0)

        frameB3 = LabelFrame(frameB, text='Unique to Spin System 2')
        frameB3.grid(row=0, column=2, sticky='nsew')
        frameB3.expandGrid(0, 0)

        # Settings for isotope shift correction

        shiftLists = getShiftLists(self.nmrProject)
        self.protonatedShiftList = shiftLists[0]
        self.deuteratedShiftList = shiftLists[1]
        shiftListNames = ['{}: {}'.format(shiftList.serial, shiftList.name) for shiftList in shiftLists]

        Label(isotopeFrame, text='Correct for isotope shift:', grid=(0, 0))
        self.correctCheck = CheckButton(isotopeFrame,
                                        selected=True,
                                        callback=self.setCorrection,
                                        grid=(0, 1))
        Label(isotopeFrame, text='Protonated shift list:', grid=(1, 0))
        self.protonatedPulldown = PulldownList(isotopeFrame,
                                               callback=self.setProtonatedShiftList,
                                               texts=shiftListNames,
                                               objects=shiftLists,
                                               grid=(1, 1),
                                               index=0)

        Label(isotopeFrame, text='Deuterated shift list:', grid=(2, 0))
        self.deuteratedPulldown = PulldownList(isotopeFrame,
                                               callback=self.setDeuteratedShiftList,
                                               texts=shiftListNames,
                                               objects=shiftLists,
                                               grid=(2, 1),
                                               index=1)



        # Table A1
        headingList = ['#', 'shift lists', 'Assignment']

        tipTexts = ['Spin System Serial',
                    'shift lists', 'The residue (tentatively) assigned to this spin system',
                    'The amount of spin systems that overlap with this spin system and have no violations']

        editGetCallbacks = [self.setSpinSystem1]*3
        editSetCallbacks = [None]*3
        self.tableA1 = ScrolledMatrix(frameA1, headingList=headingList,
                                      multiSelect=False,
                                      editGetCallbacks=editGetCallbacks,
                                      editSetCallbacks=editSetCallbacks,
                                      tipTexts=tipTexts)
        self.tableA1.grid(row=0, column=0, sticky='nsew')

        # Table A2
        headingList = ['#', 'shift lists', 'Assignment', 'offset']
        tipTexts = ['Spin System Serial', 'The residue (tentatively) assigned to this spin system',
                    'Root mean squared deviation of this spin system to the spin system selected in the table on the left.']
        editGetCallbacks = [self.setSpinSystem2]*4
        editSetCallbacks = [None]*4
        self.tableA2 = ScrolledMatrix(frameA2, headingList=headingList,
                                      #editWidgets=editWidgets,
                                      multiSelect=False,
                                      editGetCallbacks=editGetCallbacks,
                                      editSetCallbacks=editSetCallbacks,
                                      tipTexts=tipTexts)
        self.tableA2.grid(row=0, column=0, sticky='nsew')

        # Table B1
        headingList = ['atom', 'c.s.']
        tipTexts = ['atom', 'chemical shift']
        self.tableB1 = ScrolledMatrix(frameB1,
                                      headingList=headingList,
                                      multiSelect=False,
                                      tipTexts=tipTexts)
        self.tableB1.grid(row=0, column=0, sticky='nsew')

        # Table B 2
        headingList = ['atom', 'c.s. 1', 'c.s. 2', 'delta c.s.']
        tipTexts = ['name of the atom', 'chemical shift of atom with this name in spin system 1',
                    'chemical shift of atom with this name in spin system 2',
                    'difference between the chemical shift of spin systems 1 and 2']

        self.tableB2 = ScrolledMatrix(frameB2,
                                      headingList=headingList,
                                      tipTexts=tipTexts)
        self.tableB2.grid(row=0, column=0, sticky='nsew')

        # Table B 3
        headingList = ['atom', 'c.s.']
        tipTexts = ['atom', 'chemical shift.']
        self.tableB3 = ScrolledMatrix(frameB3,
                                      headingList=headingList,
                                      multiSelect=False,
                                      tipTexts=tipTexts)
        self.tableB3.grid(row=0, column=0, sticky='nsew')

        self.matchMatrix = {}
        self.amountOfMatchesPerSpinSystem = {}

        self.updateTableA1()
Example #37
0
class SecStructurePredictPopup(BasePopup):
    """
  **Predict Protein Secondary Structure**
  
  This popup window is designed to allow the prediction of secondary structure
  for a protein chain given chemical shifts, using the (external) program D2D.

  The Options to select are the Chain and the Shift List, for which the
  prediction is then made.

  The Secondary Structure Predictions table lists the residues in the chain.
  For each residue the residue number, residue type and current secondary
  structure set for that residue is given.  The remaining columns are for
  the predictions made by D2D, and of course are only filled in once D2D
  is run.  The predicted secondary structure is listed first, followed by
  the probability of that residue being Helix, Beta, Coil or PPII (the
  predicted secondary structure will be specified by the maximum of these).
  
  To run the prediction click on the "Run D2D Prediction!" button.  This
  does not store this information in the project.  To do that you have to
  click on the "Commit Predicted Secondary Structure" button.

  **Caveats & Tips**

  The predicted secondary structure cell is coloured red if the prediction
  is unreliable.  Unreliable predictions are not stored with the "Commit"
  button but all reliable ones are.  If you need to edit the secondary
  structure for a residue then use the Secondary Structure Chart:

  .. _Secondary Structure Chart: SecStructureGraphPopup.html

  **References**

  The D2D programme:

  http://www-vendruscolo.ch.cam.ac.uk/d2D/index.php

  *C. Camilloni, A. De Simone, W. Vranken and M. Vendruscolo.
  Determination of Secondary Structure Populations in Disordered States of Proteins using NMR Chemical Shifts.
  Biochemistry 2012, 51: 2224-2231
  """
    def __init__(self, parent, *args, **kw):

        self.chain = None
        self.shiftList = None
        self.predictionDict = {}

        BasePopup.__init__(self,
                           parent=parent,
                           title='Structure : Predict Secondary Structure')

    def body(self, guiFrame):

        self.geometry('700x500')

        guiFrame.expandGrid(1, 0)

        row = 0

        # TOP LEFT FRAME

        frame = LabelFrame(guiFrame, text='Options')
        frame.grid(row=row, column=0, sticky='nsew')
        frame.columnconfigure(5, weight=1)

        label = Label(frame, text='Chain')
        label.grid(row=0, column=0, sticky='w')
        self.chainPulldown = PulldownList(
            frame,
            callback=self.changeChain,
            tipText='Choose the molecular system chain to make predictions for'
        )
        self.chainPulldown.grid(row=0, column=1, sticky='w')

        label = Label(frame, text='Shift List')
        label.grid(row=0, column=2, sticky='w')
        self.shiftListPulldown = PulldownList(
            frame,
            callback=self.changeShiftList,
            tipText='Select the shift list to take input chemical shifts from')
        self.shiftListPulldown.grid(row=0, column=3, sticky='w')

        row += 1

        # BOTTOM LEFT FRAME

        frame = LabelFrame(guiFrame, text='Secondary Structure Predictions')
        frame.grid(row=row, column=0, sticky='nsew')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        tipTexts = ('Residue number in chain', 'Residue type code',
                    'Current stored secondary structure code',
                    'Predicted secondary structure code') + SEC_STRUC_TIPS

        headingList = ('Res\nNum', 'Res\nType', 'Current\nSS',
                       'Predicted\nSS') + SEC_STRUC_KEYS

        n = len(headingList)
        editWidgets = n * [None]
        editGetCallbacks = n * [None]
        editSetCallbacks = n * [None]

        self.predictionMatrix = ScrolledMatrix(
            frame,
            headingList=headingList,
            tipTexts=tipTexts,
            editWidgets=editWidgets,
            editGetCallbacks=editGetCallbacks,
            editSetCallbacks=editSetCallbacks)
        self.predictionMatrix.grid(row=0, column=0, sticky='nsew')

        row += 1

        tipTexts = [
            'Run the D2D method to predict secondary structure',
            'Store the secondary structure predictions in the CCPN project'
        ]

        texts = [
            'Run D2D Prediction!', 'Commit Predicted\nSecondary Structure'
        ]
        commands = [self.runD2D, self.storeSecondaryStructure]
        self.buttonList = createDismissHelpButtonList(guiFrame,
                                                      texts=texts,
                                                      commands=commands,
                                                      help_url=self.help_url,
                                                      expands=True,
                                                      tipTexts=tipTexts)
        self.buttonList.grid(row=row, column=0, columnspan=2, sticky='ew')

        self.update()

        self.notify(self.registerNotify)

    def destroy(self):

        self.notify(self.unregisterNotify)
        BasePopup.destroy(self)

    def notify(self, notifyfunc):

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

        for func in ('__init__', 'delete', 'setName'):
            notifyfunc(self.updateShiftListPulldown, 'ccp.nmr.Nmr.ShiftList',
                       func)

        for func in ('setSecStrucCode', ):
            notifyfunc(self.updatePredictionMatrixAfter,
                       'ccp.nmr.Nmr.ResonanceGroup', func)

    def update(self):

        self.updateShiftListPulldown()
        self.updateChainPulldown()
        self.updatePredictionMatrixAfter()

    def runD2D(self):

        chain = self.chain
        shiftList = self.shiftList

        if (not chain) or (not shiftList):
            showError('Cannot Run D2D',
                      'Please specify a chain and a shift list.',
                      parent=self)
            return

        self.predictionDict[chain] = runD2D(chain, shiftList)

        self.updatePredictionMatrix()

    def storeSecondaryStructure(self):

        if not self.chain:
            return

        getSpinSystem = self.nmrProject.findFirstResonanceGroup
        newSpinSystem = self.nmrProject.newResonanceGroup

        predDict = self.predictionDict.get(self.chain, {})

        n = 0
        for residue in predDict:
            (ssCode, isReliable, probabilityDict) = predDict[residue]

            if isReliable:
                spinSystem = getSpinSystem(residue=residue)

                if not spinSystem:
                    spinSystem = newSpinSystem(residue=residue,
                                               ccpCode=residue.ccpCode)

                spinSystem.secStrucCode = ssCode
                n += 1

        showInfo('Info',
                 'Stored secondary structure types for %d residues.' % n,
                 parent=self)

    def updatePredictionMatrixAfter(self, index=None, text=None):

        self.after_idle(self.updatePredictionMatrix)

    def updatePredictionMatrix(self):

        objectList = []
        textMatrix = []
        colorMatrix = []

        n = len(SEC_STRUC_KEYS)
        chain = self.chain
        if chain:
            predDict = self.predictionDict.get(chain, {})

            getSpinSystem = self.nmrProject.findFirstResonanceGroup
            for residue in chain.sortedResidues():
                spinSystem = getSpinSystem(residue=residue)
                currentSsCode = spinSystem and spinSystem.secStrucCode

                data = [residue.seqCode, residue.ccpCode, currentSsCode]
                colors = 3 * [None]
                if residue in predDict:
                    (ssCode, isReliable, probabilityDict) = predDict[residue]
                    data.append(ssCode)
                    if isReliable:
                        colors.append(None)
                    else:
                        colors.append('#FF3333')
                    for key in SEC_STRUC_KEYS:
                        data.append(probabilityDict[key])
                    colors.extend(n * [None])
                else:
                    data.extend((n + 1) * [None])
                    colors.extend((n + 1) * [None])

                textMatrix.append(data)
                objectList.append(residue)
                colorMatrix.append(colors)

        self.predictionMatrix.update(textMatrix=textMatrix,
                                     objectList=objectList,
                                     colorMatrix=colorMatrix)

    def changeChain(self, chain):

        if chain is not self.chain:
            self.chain = chain
            self.updatePredictionMatrixAfter()

    def changeShiftList(self, shiftList):

        if shiftList is not self.shiftList:
            self.shiftList = shiftList
            self.updatePredictionMatrixAfter()

    def updateChainPulldown(self, obj=None):

        index = 0
        names = []
        chains = []
        chain = self.chain

        for molSystem in self.project.molSystems:
            msCode = molSystem.code

            for chainA in molSystem.chains:
                residues = chainA.residues

                if not residues:
                    continue

                for residue in residues:
                    # Must have at least one protein residue
                    if residue.molType == 'protein':
                        names.append('%s:%s' % (msCode, chainA.code))
                        chains.append(chainA)
                        break

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

            index = chains.index(chain)

        else:
            chain = None

        if chain is not self.chain:
            self.chain = chain
            self.updatePredictionMatrixAfter()

        self.chainPulldown.setup(names, chains, index)

    def updateShiftListPulldown(self, obj=None):

        index = 0
        names = []
        shiftLists = getShiftLists(self.nmrProject)

        if shiftLists:
            if self.shiftList not in shiftLists:
                self.shiftList = shiftLists[0]

            index = shiftLists.index(self.shiftList)
            names = ['%s:%d' % (sl.name, sl.serial) for sl in shiftLists]

        else:
            self.shiftList = None

        self.shiftListPulldown.setup(names, shiftLists, index)
Example #38
0
  def __init__(self, parent, project, path = None,
               molTypeEntries = None, chemCompEntries = None,
               selectedChemComps = None, selectLinking = None,
               *args, **kw):

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

    self.project = project
    self.molTypeEntries = molTypeEntries
    self.chemCompEntries = chemCompEntries
    self.selectLinking = selectLinking

    if (not path):
      path = getDataPath()

    self.path = path
      
    # Check if all chemComps available locally
    self.path_allChemComps = getChemCompArchiveDataDir()
    if not os.path.exists(self.path_allChemComps):
      self.path_allChemComps = None

    self.chemCompInfoDict = {}
    self.chemCompInfoList = []
    self.chemCompDownload = False
    self.chem_comps_shown = {}

    for entry in chemCompList:
      self.chemCompClasses[entry] = getattr(ccp.api.molecule.ChemComp, entry)

    self.grid_columnconfigure(0, weight=1)

    row = 0
    
    if (molTypeEntries is None):
      headerText = "Show residues (select molecular type(s)):"
    else:
      headerText = "Show %s residues:" % (str(molTypeEntries))
    
    #
    #
    # TODO TODO: HERE need to do some niftier stuff for displaying!
    #
    #
    
    headerTextWidget = Label(self, text = headerText)
    headerTextWidget.grid(row=row, column=0, sticky=Tkinter.W)
    row = row + 1

    if (molTypeEntries is None):
      self.mol_type_buttons = CheckButtons(self, entries=molTypeList,
                                select_callback=self.updateTables)
      self.mol_type_buttons.grid(row=row, column=0, sticky=Tkinter.EW)
      row = row + 1
    else:
      self.mol_type_buttons = None

    #
    # The chemComps to display...
    #
    
    self.showLocalText = 'Show local'
    self.showWebText = 'Show available via web'
    self.display_buttons = CheckButtons(self, entries=[self.showLocalText,self.showWebText],
                                              select_callback=self.updateTables,
                                              selected = [self.showLocalText])
    self.display_buttons.grid(row=row, column=0, sticky=Tkinter.EW)
    row = row + 1

    self.grid_rowconfigure(row, weight=2)
    headings = ('number', 'show details', 'molType', 'ccpCode', 'code1Letter', 'cifCode', 'name')
    editWidgets = 7 * [ None ]
    editGetCallbacks = [ None, self.toggleShow, None, None, None, None, None ]
    editSetCallbacks = 7 * [ None ]
    self.chem_comp_table = ScrolledMatrix(self, headingList=headings,
                                  editWidgets=editWidgets,
                                  editGetCallbacks=editGetCallbacks,
                                  editSetCallbacks=editSetCallbacks)
    self.chem_comp_table.grid(row=row, column=0, sticky=Tkinter.NSEW)

    row = row + 1
    texts = [ 'Show all in details window', 'Clear details window' ]
    commands = [ self.showAll, self.showNone ]
    buttons = ButtonList(self, texts=texts, commands=commands)
    buttons.grid(row=row, column=0, sticky=Tkinter.EW)
    
    row = row + 1

    separator = Separator(self,height = 3)
    separator.setColor('black', bgColor = 'black')
    separator.grid(row=row, column=0, sticky=Tkinter.EW)

    row = row + 1
    
    headerTextWidget = Label(self, text = "Select the residue variant:")
    headerTextWidget.grid(row=row, column=0, sticky=Tkinter.W)

    row = row + 1
    if (chemCompEntries is None):
      self.chem_comp_buttons = CheckButtons(self, entries=chemCompList,
                                 selected=('ChemComp',),
                                 select_callback=self.updateChemCompVarTable)
      self.chem_comp_buttons.grid(row=row, column=0, sticky=Tkinter.EW)
      row = row + 1
    else:
      self.chem_comp_buttons = None

    self.grid_rowconfigure(row, weight=1)
    headings = ('number', 'molType', 'ccpCode', 'linking', 'descriptor', 'molecularMass', 'formula', 'nonStereoSmiles', 'stereoSmiles')
    self.chem_comp_var_table = ScrolledMatrix(self, headingList=headings)
    self.chem_comp_var_table.grid(row=row, column=0, sticky=Tkinter.NSEW)
    self.chem_comp_var_headings = headings[1:]
    
    if selectedChemComps:
      for chemComp in selectedChemComps:
        key = (chemComp.molType, chemComp.ccpCode)
        self.chem_comps_shown[key] = 1

    self.updateTables()