Ejemplo n.º 1
0
    def body(self, master):

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

        # get wild config iterations unless doExtraConfig=False
        frame = ScrolledFrame(master,
                              doExtraConfig=False,
                              width=600,
                              height=300)
        frame.grid(row=0, column=0, sticky=Tkinter.NSEW)
        self.parent_frame = frame.frame

        self.edit_widget = None
        self.keyList = getKeyList(self.metaclass, includeRoot=True)
        self.createWidgets()
        self.createBottomButtons(master)
        self.setObject(self.object)

        self.roleFuncs = {}
        for name in self.metaclass.roleAllNames:
            role = self.metaclass.elementDict[name]
            if (self.showRole(role)):
                # because of loop need role=role else all get bound to last role
                f = lambda obj, role=role: self.setRoleValue(role)
                self.roleFuncs[role] = f

        if (self.editMode):
            self.doRegisters()
Ejemplo n.º 2
0
class ChemCompAtomBondInfoPopup(TemporaryBasePopup):
 
  help_url = joinPath(getHelpUrlDir(),'ChemCompAtomBondInfo.html')

  def __init__(self, parent, chemCompInfo, chemCompAtoms, chemCompBonds):
   
    self.chemCompInfo = chemCompInfo
    self.chemCompAtoms = chemCompAtoms
    self.chemCompBonds = chemCompBonds
    
    self.obligatoryAtoms = []
    
    for molTypeTuple in standardBackboneAtoms.keys():
      if self.chemCompInfo[0][1] in molTypeTuple:
        for atomName in standardBackboneAtoms[molTypeTuple]:
          if atomName not in self.obligatoryAtoms:
            self.obligatoryAtoms.append(atomName)
      
    
    self.nonEntryAttributes = {
    
      'chirality':   (PulldownMenu,['R','S','unknown']),
      'waterExchangeable': (CheckButton,False)
    
    }
        
    TemporaryBasePopup.__init__(self, parent=parent, title='ChemComp atom and bond creation', modal=False, transient=True)

  def body(self, master):
      
    #
    # Popup window
    #
    
    self.columnspan = len(self.chemCompAtoms[0])

    row = 0
    label = Label(master, text= "Molecule type '%s', ccp code '%s'" % (self.chemCompInfo[0][1],self.chemCompInfo[1][1]))
    label.grid(row=row, column=0, columnspan = self.columnspan, sticky=Tkinter.EW)
    
    #
    # Warning message if necessary!
    #
    
    if self.obligatoryAtoms:
      row += 1
      
      label = Label(master, text= "Warning: have to define atoms: %s!" % string.join(self.obligatoryAtoms,', '), fg = 'red')
      label.grid(row=row, column=0, columnspan = self.columnspan, sticky=Tkinter.EW)
    
    #
    # Show top information...
    #
    
    row = row + 1
    colNum = 0
    self.frameWidth = 0
    
    for chemCompAtomInfo in self.chemCompAtoms[0]:
      
      attrName = chemCompAtomInfo[0]

      label = Label(master, text = attrName, width = len(attrName) + 2)
      label.grid(row=row, column=colNum, sticky=Tkinter.EW)
      
      self.frameWidth += len(attrName) + 2
      colNum += 1
    
    #
    # Separator
    #
    
    row += 1

    separator = Separator(master, height = 3)
    separator.setColor('black', bgColor = 'black')
    separator.grid(row = row, columnspan = self.columnspan, sticky = Tkinter.EW)
      
    #
    # Separate frame for info (have to be able to scroll)
    #
    
    row += 1
    
    # THIS BIT TELLS MASTER TO CONFIGURE WINDOW ON INSIDE WIDGET!!
    master.grid_rowconfigure(row,weight = 1)
    for i in range(self.columnspan):
      master.grid_columnconfigure(i,weight = 1)
    
    self.atomFrame = ScrolledFrame(master, width = self.frameWidth, height = 300, doExtraConfig = False)
    self.atomFrame.grid(row=row, column=0, columnspan = self.columnspan, sticky=Tkinter.NSEW)
    self.atomFrameRow = row
    self.atomFrameMaster = master

    #
    # Separator
    #
    
    row += 1

    separator = Separator(master, height = 3)
    separator.setColor('black', bgColor = 'black')
    separator.grid(row = row, columnspan = self.columnspan, sticky = Tkinter.EW)
          
    #
    # End bit...
    #
    
    row = row + 1
    texts = [ 'OK', 'Update' ]
    commands = [ self.ok, self.update ]   # This calls 'ok' in BasePopup, this then calls 'apply' in here
    buttons = createHelpButtonList(master, texts=texts, commands=commands, help_url=self.help_url)
    buttons.grid(row=row, column=0, columnspan = self.columnspan)
    
    self.setupAtomFrame()

  def setupAtomFrame(self,resetFrame = False, resetStatus = True):
    
    frameRow = 0
    self.atomWidgets = []
    
    if resetFrame:
      self.atomFrame = ScrolledFrame(self.atomFrameMaster, width = self.frameWidth, height = 300, doExtraConfig = False)
      self.atomFrame.grid(row=self.atomFrameRow, column=0, columnspan = self.columnspan, sticky=Tkinter.NSEW)    
    
    frame = self.atomFrame.frame
      
    #
    # Make fake info at top for col length...
    #
    
    colNum = 0
    
    for chemCompAtomInfo in self.chemCompAtoms[0]:
      
      attrName = chemCompAtomInfo[0]

      label = Label(frame, text = '', width = len(attrName) + 2)
      label.grid(row=frameRow, column=colNum, sticky=Tkinter.EW)
      
      colNum += 1
            
    #
    # Now atom info...
    #
    
    for chemCompAtom in self.chemCompAtoms:
      
      frameRow += 1
      colNum = 0
      
      self.atomWidgets.append([])

      for chemCompAtomInfo in chemCompAtom:

        attrName = chemCompAtomInfo[0]

        if attrName == 'bondedAtoms':

          bondedAtomText = ""
          
          for otherAtom in chemCompAtomInfo[1]:
            bondedAtomText += otherAtom[0][1] + ','
          
          label = Label(frame, text = bondedAtomText[:-1])
          label.grid(row=frameRow, column=colNum, sticky=Tkinter.EW)
            
        else:

          if attrName in self.nonEntryAttributes:

            widgetInfo = self.nonEntryAttributes[attrName]

            if widgetInfo[0] == PulldownMenu:

              self.atomWidgets[-1].append(PulldownMenu(frame, entries = widgetInfo[1], selected_index = widgetInfo[1].index(chemCompAtomInfo[1])))

            elif widgetInfo[0] == CheckButton:

              self.atomWidgets[-1].append(CheckButton(frame, selected = chemCompAtomInfo[1]))

          else:

            text = chemCompAtomInfo[1]
            if not text:
              text = ''

            self.atomWidgets[-1].append(Entry(frame, text = text, width = 5))

          self.atomWidgets[-1][-1].grid(row=frameRow, column=colNum)     
      
        colNum += 1

  def update(self):
  
    self.apply(checkAtoms = False)
    self.setupAtomFrame()

  def apply(self, checkAtoms = True):
    
    atomNames = []
    duplicateNames = []
    
    if checkAtoms:
      obligatoryAtoms = self.obligatoryAtoms[:]
  
    for atomNum in range(0,len(self.chemCompAtoms)):
    
      chemCompAtom = self.chemCompAtoms[atomNum]
      widgets = self.atomWidgets[atomNum]
      
      for widgetNum in range(0,len(widgets)):

        attrName = chemCompAtom[widgetNum][0]
        
        if attrName in self.nonEntryAttributes:

          widgetInfo = self.nonEntryAttributes[attrName]

          if widgetInfo[0] in [PulldownMenu,CheckButton]:

            value = widgets[widgetNum].getSelected()
            
            if widgetInfo[0] == CheckButton:
              if value:
                value = True
              else:
                value = False

        else:

          value = widgets[widgetNum].get()
          
          if value == '':
            value = None

        chemCompAtom[widgetNum] = (attrName,value)

        if attrName == 'name':
          
          if value in atomNames:
            if value not in duplicateNames:
              duplicateNames.append(value)
          else:
            atomNames.append(value)
          
          if checkAtoms:
            if value in obligatoryAtoms:
              obligatoryAtoms.pop(obligatoryAtoms.index(value))
    
    if duplicateNames:
      showWarning(self,"Duplicate atom names: %s - names have to be unique!" % string.join(duplicateNames,', '))
      return False
    
    if checkAtoms and obligatoryAtoms:
      showWarning(self,"Obligatory atoms: %s still missing - please rename accordingly." % string.join(obligatoryAtoms,', '))
      return False
      
    return True
Ejemplo n.º 3
0
class SequenceChemCompSelect(BasePopup):

    help_url = joinPath(getHelpUrlDir(), 'SequenceChemCompSelect.html')

    def __init__(self, parent, project, molName, createMoleculeDict,
                 localCreateMoleculeDict):

        self.molName = molName
        self.project = project
        self.createMoleculeDict = createMoleculeDict
        self.localCreateMoleculeDict = localCreateMoleculeDict

        self.hasChanged = False

        self.molecule = self.localCreateMoleculeDict[self.molName][0]

        self.deleteText = 'Delete'
        self.okText = 'OK'
        self.startText = 'Insert at start'
        self.endText = 'Append to end'

        self.newMoleculeList = []

        for molName in self.localCreateMoleculeDict.keys():
            if molName != self.molName and not self.localCreateMoleculeDict[
                    molName][0]:
                self.newMoleculeList.append(molName)

        # modal = true means that it won't continue unless this one returns value
        BasePopup.__init__(self,
                           parent=parent,
                           title="Project '%s': " % project.name +
                           'Set chemComps for sequence',
                           modal=True,
                           transient=True)

    def body(self, master):

        self.geometry('700x500')

        #
        # Setup header
        #

        row = 0

        label = Label(master, text='Original', width=10)
        label.grid(row=row, column=0, sticky=Tkinter.EW)

        label = Label(master, text='Modify ChemCompVar', width=35)
        label.grid(row=row, column=1, sticky=Tkinter.EW)

        label = Label(master, text='Status', width=20)
        label.grid(row=row, column=2, sticky=Tkinter.EW)

        label = Label(master, text='', width=5)
        label.grid(row=row, column=3, sticky=Tkinter.EW)

        row += 1

        label = Label(master, text='code', width=10)
        label.grid(row=row, column=0, sticky=Tkinter.EW)

        label = Label(master,
                      text='ccpCode (molType): linking, descriptor',
                      width=35)
        label.grid(row=row, column=1, sticky=Tkinter.EW)

        label = Tkinter.Button(master,
                               text='Add new molecule',
                               command=self.addNewMolecule)
        label.grid(row=row, column=2)

        row += 1

        separator = Separator(master, height=3)
        separator.setColor('black', bgColor='black')
        separator.grid(row=row, columnspan=3, sticky=Tkinter.EW)

        row += 1

        # THIS BIT TELLS MASTER TO CONFIGURE WINDOW ON INSIDE WIDGET!!
        master.grid_rowconfigure(row, weight=1)
        for i in range(4):
            master.grid_columnconfigure(i, weight=1)
        self.sequenceFrame = ScrolledFrame(master,
                                           width=70,
                                           height=300,
                                           doExtraConfig=False)
        self.sequenceFrame.grid(row=row,
                                column=0,
                                columnspan=4,
                                sticky=Tkinter.NSEW)
        self.sequenceFrameRow = row
        self.sequenceFrameMaster = master

        row += 1

        separator = Separator(master, height=3)
        separator.setColor('black', bgColor='black')
        separator.grid(row=row, columnspan=3, sticky=Tkinter.EW)

        row += 1

        texts = ['Change', 'Change and quit']
        commands = [
            self.updateMolDict, self.ok
        ]  # This calls 'ok' in BasePopup, this then calls 'apply' in here
        buttons = createDismissHelpButtonList(master,
                                              texts=texts,
                                              commands=commands,
                                              dismiss_text='Cancel',
                                              help_url=self.help_url)
        buttons.grid(row=row, column=0, columnspan=3, sticky=Tkinter.EW)

        self.setupSequenceFrame()

    def setupSequenceFrame(self, resetFrame=False, resetStatus=True):

        frameRow = 0
        x = y = 0

        if resetFrame:
            self.sequenceFrame = ScrolledFrame(self.sequenceFrameMaster,
                                               width=70,
                                               height=300,
                                               doExtraConfig=False)
            self.sequenceFrame.grid(row=self.sequenceFrameRow,
                                    column=0,
                                    columnspan=4,
                                    sticky=Tkinter.NSEW)

        frame = self.sequenceFrame.frame

        #
        # Just use the first one as reference!
        #

        sequences = self.localCreateMoleculeDict[self.molName][1]
        (self.origSequence, self.origSequenceList) = sequences[0]

        if len(sequences) > 1:
            multipleSequences = True
        else:
            multipleSequences = False

        #
        # Set info...
        #

        label = Label(frame, text='', width=10)
        label.grid(row=frameRow, column=0, sticky=Tkinter.EW)

        label = Label(frame, text='', width=35)
        label.grid(row=frameRow, column=1, sticky=Tkinter.EW)

        label = Label(frame, text='', width=20)
        label.grid(row=frameRow, column=2, sticky=Tkinter.EW)

        frameRow += 1

        self.ccvButtons = []

        if resetStatus or resetFrame:
            self.statusList = []
            self.moveStatus = {}

            #
            # Set up a list of status entries
            #

            statusEntries = [self.okText, self.deleteText]

            for newMolName in self.newMoleculeList:
                for appendCode in [self.startText, self.endText]:
                    statusEntries.append('%s of %s' % (appendCode, newMolName))
                    self.moveStatus[statusEntries[-1]] = (newMolName,
                                                          appendCode)

        #
        # Start creating all the objects...
        #

        for seqIndex in range(0, len(self.origSequenceList)):

            (seqEl, ccHead, ccVar) = self.origSequenceList[seqIndex]

            #
            # Set the original sequence code info...
            #

            seqCode = seqEl.seqCode

            if hasattr(seqEl, 'code3Letter') and seqEl.code3Letter:
                seqText = seqEl.code3Letter
            else:
                seqText = seqEl.code1Letter

            label = Label(frame, text="%s-%d" % (seqText, seqCode))
            label.grid(row=frameRow, column=0, sticky=Tkinter.EW)

            #
            # Set the chemCompVar info
            #

            keywds = {}

            if ccHead:
                textCode = "%s (%s)" % (ccHead.ccpCode, ccHead.molType)

                if ccVar:
                    textCode += ": %s,%s" % (ccVar.linking, ccVar.descriptor)
                else:
                    textCode = 'Select chemCompVar for %s' % textCode
                    keywds['fg'] = 'red'

            else:
                textCode = 'Select chemCompVar'
                keywds['fg'] = 'red'

            self.ccvButtons.append(
                Tkinter.Button(frame,
                               text=textCode,
                               command=lambda seqIndex=seqIndex: self.
                               selectChemCompVar(seqIndex),
                               **keywds))
            self.ccvButtons[-1].grid(row=frameRow, column=1, sticky=Tkinter.EW)

            #
            # Set the selector...
            #

            if resetStatus or resetFrame:
                self.statusList.append(
                    PulldownMenu(frame,
                                 entries=statusEntries,
                                 label_color='red'))
                self.statusList[-1].grid(row=frameRow,
                                         column=2,
                                         sticky=Tkinter.EW)

            frameRow += 1

        return True

    def addNewMolecule(self):

        molFormat = 'newMolecule_%d'

        if not hasattr(self, 'molNames'):
            self.molNames = self.localCreateMoleculeDict.keys()

        for i in range(0, 10):
            newMolName = molFormat % (i + 1)
            if newMolName not in self.molNames and not self.project.findFirstMolecule(
                    name=newMolName):
                break

        self.molNames.append(newMolName)

        for statusPullDown in self.statusList:
            for appendCode in [self.startText, self.endText]:
                entryText = '%s of %s' % (appendCode, newMolName)
                statusPullDown.append(entryText)
                self.moveStatus[entryText] = (newMolName, appendCode)

    def updateMolDict(self):

        hasChanged = False
        actualSeqIndex = 0
        seqLength = len(self.origSequenceList)

        origSequenceList = self.origSequenceList[:]

        for seqIndex in range(0, seqLength):

            (seqEl, ccHead, ccVar) = origSequenceList[seqIndex]

            newStatus = self.statusList[seqIndex].getSelected()

            if newStatus != self.okText:

                hasChanged = True

                if self.localCreateMoleculeDict == self.createMoleculeDict:
                    self.copyCreateMoleculeDict()

                self.origSequenceList.pop(actualSeqIndex)

                if newStatus != self.deleteText:

                    (moveToMoleculeName,
                     appendCode) = self.moveStatus[newStatus]

                    if not self.localCreateMoleculeDict.has_key(
                            moveToMoleculeName):
                        self.localCreateMoleculeDict[moveToMoleculeName] = [
                            None, [(None, [])]
                        ]

                    sequences = self.localCreateMoleculeDict[
                        moveToMoleculeName][1]

                    for (tempSequence, tempSequenceList) in sequences:
                        if appendCode == self.startText:
                            tempSequenceList.insert(0, (seqEl, ccHead, ccVar))
                        elif appendCode == self.endText:
                            tempSequenceList.append((seqEl, ccHead, ccVar))

            else:
                actualSeqIndex += 1

        #
        # Check if changed and do some resets if so...
        #

        if hasChanged:
            self.hasChanged = True

            #
            # Reset the linking if appropriate
            #

            for molName in self.localCreateMoleculeDict.keys():
                if not self.localCreateMoleculeDict[molName][0]:

                    sequences = self.localCreateMoleculeDict[molName][1]

                    for (origSequence, origSequenceList) in sequences:
                        molTypes = []
                        for (seqEl, ccHead, ccVar) in origSequenceList:
                            if ccHead:
                                if ccHead.molType not in molTypes:
                                    molTypes.append(ccHead.molType)

                        if len(molTypes) == 1 and molTypes[0] != 'other':
                            seqLength = len(origSequenceList)
                            for seqIndex in range(0, seqLength):
                                (seqEl, ccHead,
                                 ccVar) = origSequenceList[seqIndex]
                                if ccVar:
                                    if seqIndex == 0:
                                        linking = 'start'

                                    elif seqIndex == seqLength - 1:
                                        linking = 'end'

                                    else:
                                        linking = 'middle'

                                    if ccVar.linking != linking:
                                        ccVar = ccHead.chemComp.findFirstChemCompVar(
                                            descriptor=ccVar.descriptor,
                                            linking=linking)
                                        if ccVar:
                                            origSequenceList[seqIndex] = (
                                                seqEl, ccHead, ccVar)

            self.setupSequenceFrame(resetFrame=True)

    def selectChemCompVar(self, seqIndex):

        hasChanged = False

        (seqEl, ccHead, ccVar) = self.origSequenceList[seqIndex]

        keywds = {}
        if ccHead:
            keywds['molTypeEntries'] = [ccHead.molType]  # TODO HAS TO CHANGE!!
            keywds['selectedChemCompHeads'] = [ccHead]
        if ccVar:
            keywds['selectLinking'] = ccVar.linking

        if hasattr(seqEl, 'code3Letter') and seqEl.code3Letter:
            keywds['origCode'] = seqEl.code3Letter
        else:
            keywds['origCode'] = seqEl.code1Letter

        popup = ChemCompSelectionPopup(self,
                                       self.project,
                                       chemCompEntries=['ChemCompVar'],
                                       **keywds)
        self.wait_window(popup)

        if popup.frame.getSelectedChemComp():

            newChemCompVar = popup.frame.getSelectedChemComp()

            if not ccVar or ccVar != newChemCompVar:
                if self.localCreateMoleculeDict == self.createMoleculeDict:
                    self.copyCreateMoleculeDict()

                self.origSequenceList[seqIndex] = (
                    seqEl, newChemCompVar.chemComp.chemCompHead,
                    newChemCompVar)
                hasChanged = True

        if hasChanged:
            self.setupSequenceFrame(resetStatus=False)
            self.hasChanged = hasChanged

    def copyCreateMoleculeDict(self):

        self.localCreateMoleculeDict = {}

        for molName in self.createMoleculeDict.keys():
            self.localCreateMoleculeDict[molName] = [
                self.createMoleculeDict[molName][0], []
            ]

            for (sequence,
                 sequenceList) in self.createMoleculeDict[molName][1]:
                self.localCreateMoleculeDict[molName][1].append(
                    (sequence, sequenceList[:]))

        sequences = self.localCreateMoleculeDict[self.molName][1]
        (self.origSequence, self.origSequenceList) = sequences[0]

    def apply(self):

        self.updateMolDict()

        return True
Ejemplo n.º 4
0
class ProchiralStatusPopup(TemporaryBasePopup):

    help_url = joinPath(getHelpUrlDir(), 'ProchiralStatus.html')

    def __init__(self, parent, chainList, chainAtomSetsDict):

        self.chainList = chainList
        self.chainAtomSetsDict = chainAtomSetsDict

        self.resParentDict = {}
        self.resParentList = []

        self.resParentChainLabelDict = {}
        self.resParentChainLabelList = {}

        self.chainResonancesDict = {}

        for resParent in self.chainAtomSetsDict.keys():
            if isinstance(resParent, NmrConstraint.NmrConstraintStore):
                strucGens = resParent.structureGenerations
                strucGenSerials = [str(sg.serial) for sg in strucGens]
                strucGenLabel = string.join(strucGenSerials, ',')
                resParentLabel = "Constraint set %d (strucGens %s)" % (
                    resParent.serial, strucGenSerials)
            else:
                resParentLabel = "Nmr project %s" % resParent.name

            self.resParentDict[resParentLabel] = resParent
            self.resParentList.append(resParentLabel)

            self.chainResonancesDict[resParent] = {}

            self.resParentChainLabelDict[resParent] = {}
            self.resParentChainLabelList[resParent] = []

            for chain in self.chainList:
                self.project = chain.root
                if self.chainAtomSetsDict[resParent].has_key(
                        chain) and self.chainAtomSetsDict[resParent][chain]:
                    chainLabel = "Molecular system '%s':Chain '%s' (molecule '%s')" % (
                        chain.molSystem.code, chain.code, chain.molecule.name)
                    self.resParentChainLabelList[resParent].append(chainLabel)
                    self.resParentChainLabelDict[resParent][chainLabel] = chain

                    self.chainResonancesDict[resParent][chain] = []

        # modal = true means that it won't continue unless this one returns value
        TemporaryBasePopup.__init__(
            self,
            parent=parent,
            title="Project '%s': " % self.project.name +
            'Set status prochiral atoms/resonances',
            modal=False,
            transient=True)

    def body(self, master):

        #
        # Setup header
        #

        row = 0

        label = Label(master, text='Select the resonance list:')
        label.grid(row=row, column=0, sticky=Tkinter.EW)

        label = Label(master, text='Select the chain:')
        label.grid(row=row, column=1, sticky=Tkinter.EW)

        row += 1

        self.resParentSelect = PulldownMenu(master,
                                            entries=self.resParentList,
                                            callback=self.setupResParentList,
                                            do_initial_callback=False)
        self.resParentSelect.grid(row=row, column=0, sticky=Tkinter.EW)

        self.chainSelect = PulldownMenu(master,
                                        entries=[],
                                        callback=self.setupProchiralList,
                                        do_initial_callback=False)
        self.chainSelect.grid(row=row, column=1, sticky=Tkinter.EW)

        row += 1

        separator = Separator(master, height=3)
        separator.setColor('black', bgColor='black')
        separator.grid(row=row, columnspan=2, sticky=Tkinter.EW)

        row += 1

        # THIS BIT TELLS MASTER TO CONFIGURE WINDOW ON INSIDE WIDGET!!
        master.grid_rowconfigure(row, weight=1)
        for i in range(2):
            master.grid_columnconfigure(i, weight=1)

        self.prochiralListFrame = ScrolledFrame(master,
                                                width=200,
                                                doExtraConfig=False)
        self.prochiralListFrame.grid(row=row,
                                     column=0,
                                     columnspan=2,
                                     sticky=Tkinter.NSEW)
        self.prochiralListFrameRow = row
        self.prochiralListFrameMaster = master

        row = row + 1

        texts = ['Set all', 'Set chain']
        commands = [
            self.ok, self.setStereo
        ]  # This calls 'ok' in BasePopup, this then calls 'apply' in here
        buttons = createDismissHelpButtonList(master,
                                              texts=texts,
                                              commands=commands,
                                              dismiss_text='Exit',
                                              help_url=self.help_url)
        buttons.grid(row=row, column=0, columnspan=2, sticky=Tkinter.EW)

        self.resParentSelect.callback(0, self.resParentList[0])

    def setupResParentList(self, listIndex, resParentLabel):

        resParent = self.resParentDict[resParentLabel]
        self.resParent = resParent

        self.chainSelect.setup(self.resParentChainLabelList[self.resParent], 0)
        self.chainSelect.callback(
            0, self.resParentChainLabelList[self.resParent][0])

    def setupProchiralList(self, listIndex, chainLabel):

        chain = self.resParentChainLabelDict[self.resParent][chainLabel]
        self.chain = chain

        self.prochiralListFrame.destroy()
        self.prochiralListFrame = ScrolledFrame(self.prochiralListFrameMaster,
                                                width=200,
                                                doExtraConfig=False)
        self.prochiralListFrame.grid(row=self.prochiralListFrameRow,
                                     column=0,
                                     columnspan=2,
                                     sticky=Tkinter.NSEW)

        #
        # TODO: also handle case one resonance, two atomSets!?!?
        #

        frameRow = 0
        x = y = 0

        frame = self.prochiralListFrame.frame

        self.resonanceObjects = {}
        self.resonanceLabelDict = {}

        #
        # Reuse previous settings...
        #

        if len(self.chainResonancesDict[self.resParent][chain]) == len(
                self.chainAtomSetsDict[self.resParent][chain]):
            usePreviousSettings = True
        else:
            usePreviousSettings = False

        for i in range(0, len(self.chainAtomSetsDict[self.resParent][chain])):
            atomSetGroup = self.chainAtomSetsDict[self.resParent][chain][i]

            isStereo = False
            hasResonances = False
            isValidCase = False

            resonances = []

            if usePreviousSettings and self.chainResonancesDict[
                    self.resParent][chain][i]:

                resonances = self.chainResonancesDict[
                    self.resParent][chain][i][3]
                isStereo = self.chainResonancesDict[
                    self.resParent][chain][i][0]
                hasResonances = True
                isValidCase = True

            else:

                for atomSet in atomSetGroup:
                    resonanceSets = atomSet.sortedResonanceSets()

                    if resonanceSets:
                        hasResonances = True

                        for resonanceSet in resonanceSets:
                            for resonance in resonanceSet.sortedResonances():
                                if resonance not in resonances:
                                    resonances.append(resonance)

                        if len(resonanceSets) == 1:
                            isValidCase = True
                            if len(resonanceSet.atomSets) == 1:
                                isStereo = True

                    else:
                        # Case only one resonance but stereo assigned
                        resonances.append(0)

                if len(resonances) == 1:
                    # Case only one resonance, not stereo assigned
                    resonances.append(None)

            #
            # Set up only for valid cases
            #

            if hasResonances and isValidCase:

                if not usePreviousSettings:
                    self.chainResonancesDict[self.resParent][chain].append(
                        [isStereo, False, False, resonances])

                residue = atomSetGroup[0].findFirstAtom().residue
                ccpCode = residue.molResidue.ccpCode
                seqCode = residue.seqCode

                rowspan = 2

                checkButton = CheckButton(
                    frame,
                    selected=isStereo,
                    callback=lambda status=isStereo, fr=frameRow, item=i, setup
                    =False: self.toggleResonances(status, fr, item, setup))
                checkButton.grid(row=frameRow,
                                 rowspan=rowspan,
                                 column=0,
                                 sticky=Tkinter.EW)

                label = Label(frame, text=ccpCode, width=5)
                label.grid(row=frameRow,
                           rowspan=rowspan,
                           column=1,
                           sticky=Tkinter.E)
                label = Label(frame, text=str(seqCode), width=5)
                label.grid(row=frameRow,
                           rowspan=rowspan,
                           column=2,
                           sticky=Tkinter.W)

                #
                # Set up the atom names
                #

                for j in range(0, len(atomSetGroup)):
                    atomSet = atomSetGroup[j]
                    label = Label(frame, text=atomSet.name)
                    label.grid(row=frameRow + j,
                               column=3,
                               sticky=Tkinter.E,
                               ipadx=4)

                #
                # Set up the resonances
                #

                self.resonanceObjects[frameRow] = {
                    True: [[], []],
                    False: [[], []]
                }

                resonanceLabelList = []

                for resonance in resonances:

                    if not resonance:

                        resonanceLabel = 'unknown'

                    else:

                        if hasattr(resonance, 'shifts') and resonance.shifts:
                            shiftLabel = " (shifts: "

                            for shift in resonance.sortedShifts():
                                shiftLabel += "%.2f, " % shift.value

                            shiftLabel = shiftLabel[:-2] + ")"

                        else:
                            shiftLabel = ""

                        resonanceLabel = "'%d.%s'%s" % (
                            seqCode, resonance.name, shiftLabel)
                        self.resonanceLabelDict[resonanceLabel] = resonance

                    resonanceLabelList.append(resonanceLabel)

                separator = Separator(frame, height=1, width=30)
                separator.setColor('black', bgColor='black')
                separator.grid(row=frameRow, column=4, sticky=Tkinter.EW)
                self.resonanceObjects[frameRow][True][0].append(separator)

                separator = CrossLine(frame,
                                      height=20,
                                      width=30,
                                      canvas_bg=frame['bg'],
                                      color='dimgray')
                self.resonanceObjects[frameRow][False][0].append(separator)

                resonanceList = PulldownMenu(
                    frame,
                    entries=resonanceLabelList,
                    callback=lambda selInd=x, selItem=y, fr=frameRow, item=i:
                    self.setProchiralLabels(selInd, selItem, fr, item),
                    do_initial_callback=False,
                    label_color='red')
                resonanceList.grid(row=frameRow, column=5, sticky=Tkinter.EW)
                self.resonanceObjects[frameRow][True][0].append(resonanceList)

                resonanceLabel = Label(frame,
                                       text="%s" % resonanceLabelList[0],
                                       fg='dimgray')
                self.resonanceObjects[frameRow][False][0].append(
                    resonanceLabel)

                separator = Separator(frame, height=1, width=30)
                separator.setColor('black', bgColor='black')
                separator.grid(row=frameRow + 1, column=4)
                self.resonanceObjects[frameRow][True][1].append(separator)

                self.resonanceObjects[frameRow][False][1].append(None)

                resonanceLabel = Label(frame,
                                       text="%s" % resonanceLabelList[1],
                                       fg='red')
                resonanceLabel.grid(row=frameRow + 1,
                                    column=5,
                                    sticky=Tkinter.EW)
                self.resonanceObjects[frameRow][True][1].append(resonanceLabel)

                resonanceLabel = Label(frame,
                                       text="%s" % resonanceLabelList[1],
                                       fg='dimgray')
                self.resonanceObjects[frameRow][False][1].append(
                    resonanceLabel)

                if not isStereo:
                    checkButton.callback(isStereo, setup=True)

                separator = Separator(frame, height=1)
                separator.setColor('black', bgColor='black')
                separator.grid(row=frameRow + rowspan,
                               columnspan=6,
                               sticky=Tkinter.EW)

                frameRow += rowspan + 1

            elif not usePreviousSettings:
                self.chainResonancesDict[self.resParent][chain].append(None)

        return True

    def setProchiralLabels(self, selInd, selItem, fr, item):

        resonanceLabel = self.resonanceObjects[fr][True][0][1].entries[selInd]
        self.resonanceObjects[fr][False][0][1].set(resonanceLabel)

        selInd = not selInd
        resonanceLabel = self.resonanceObjects[fr][True][0][1].entries[selInd]
        self.resonanceObjects[fr][True][1][1].set(resonanceLabel)
        self.resonanceObjects[fr][False][1][1].set(resonanceLabel)

        self.chainResonancesDict[self.resParent][
            self.chain][item][2] = not self.chainResonancesDict[
                self.resParent][self.chain][item][2]
        self.chainResonancesDict[self.resParent][self.chain][item][3].reverse()

    def toggleResonances(self, status, frameRow, item, setup):

        if not setup:
            self.chainResonancesDict[self.resParent][
                self.chain][item][0] = status
            self.chainResonancesDict[self.resParent][
                self.chain][item][1] = not self.chainResonancesDict[
                    self.resParent][self.chain][item][1]

        for i in range(0, len(self.resonanceObjects[frameRow])):

            #
            # Remove other widgets from grid
            #

            rpds = self.resonanceObjects[frameRow][not status][i]
            for rpd in rpds:
                if rpd:
                    rpd.grid_forget()

            #
            # Set current widgets
            #

            rpds = self.resonanceObjects[frameRow][status][i]

            for j in range(0, len(rpds)):
                rpd = rpds[j]

                if rpd:
                    keywds = {}

                    if j == 1:
                        keywds['sticky'] = Tkinter.W

                    if j == 0:
                        if not status:
                            keywds['rowspan'] = 2

                    rpd.grid(row=frameRow + i, column=4 + j, **keywds)

    def setStereo(self, chain=None):

        if not chain:
            chain = self.chain

        if self.chainResonancesDict[self.resParent][chain]:
            for i in range(
                    0, len(self.chainResonancesDict[self.resParent][chain])):

                atomSetGroup = self.chainAtomSetsDict[self.resParent][chain][i]
                (stereoStatus, stereoStatusChanged, resChanged, resonances
                 ) = self.chainResonancesDict[self.resParent][chain][i]

                if stereoStatusChanged or (stereoStatus and resChanged):

                    residue = atomSetGroup[0].findFirstAtom().residue
                    ccpCode = residue.molResidue.ccpCode
                    seqCode = residue.seqCode

                    atomText = "%s/%s" % (atomSetGroup[0].name,
                                          atomSetGroup[1].name)

                    if stereoStatusChanged:
                        if stereoStatus:
                            stereoText = "non-stereospecific to stereospecific."
                        else:
                            stereoText = "stereospecific to non-stereospecific."

                        print "  Warning: Changed '%s.%d' prochiral resonances for atoms %s from %s" % (
                            ccpCode, seqCode, atomText, stereoText)
                        self.chainResonancesDict[
                            self.resParent][chain][i][1] = False
                        self.chainResonancesDict[
                            self.resParent][chain][i][2] = False

                        if stereoStatus:
                            resonanceSet = atomSetGroup[
                                0].findFirstResonanceSet()

                            if resonances[0]:
                                resonanceSet.removeAtomSet(atomSetGroup[1])

                            if resonances[1]:

                                if not resonances[0]:
                                    # Remove right atom set if only one resonance...
                                    resonanceSet.removeAtomSet(atomSetGroup[0])
                                else:
                                    # Only create a new resonance set if two resonances present!
                                    resonanceSet.removeResonance(resonances[1])

                                    if isinstance(
                                            self.resParent,
                                            NmrConstraint.NmrConstraintStore):
                                        newResonanceSet = self.resParent.newFixedResonanceSet(
                                            resonances=[resonances[1]],
                                            atomSets=[atomSetGroup[1]])
                                    else:
                                        newResonanceSet = self.resParent.newResonanceSet(
                                            resonances=[resonances[1]],
                                            atomSets=[atomSetGroup[1]])

                        else:

                            if resonances[0]:
                                resonanceSet = atomSetGroup[
                                    0].findFirstResonanceSet()
                                if resonances[1]:
                                    atomSetGroup[1].findFirstResonanceSet(
                                    ).delete()
                                    resonanceSet.addResonance(resonances[1])
                                resonanceSet.addAtomSet(atomSetGroup[1])

                            elif resonances[1]:
                                resonanceSet = atomSetGroup[1].resonanceSets[0]
                                resonanceSet.addAtomSet(atomSetGroup[0])

                    elif stereoStatus and resChanged:
                        print "  Warning: Changed resonance assignment for '%s.%d' stereospecifically assigned atoms %s." % (
                            ccpCode, seqCode, atomText)
                        self.chainResonancesDict[
                            self.resParent][chain][i][2] = False

                        resonanceSets = []

                        for i in range(0, 2):
                            if atomSetGroup[i].resonanceSets:
                                resonanceSets.append(
                                    atomSetGroup[i].findFirstResonanceSet())
                            else:
                                resonanceSets.append(None)

                        for i in range(0, 2):
                            resonanceSet = resonanceSets[i]

                            if resonanceSet:
                                resonanceSet.addAtomSet(atomSetGroup[not i])
                                resonanceSet.removeAtomSet(atomSetGroup[i])

    def apply(self):

        for chain in self.chainList:
            self.setStereo(chain=chain)

        return True
Ejemplo n.º 5
0
class GroupChemShiftsPopup(BasePopup):

    help_url = joinPath(getHelpUrlDir(), 'GroupChemShifts.html')

    def __init__(self, parent, project):

        #
        # Info for writing file...
        #

        self.groupText = {}

        #
        # Set up molSystem information
        #

        self.project = project

        self.molSysList = list(project.sortedMolSystems())
        self.molSystems = None

        self.molSysLabelList = []
        self.molSysLabelDict = {}
        self.molSysRelationDict = {}

        molSysLabel = 'All molSystems'

        if self.setChainLabels(molSysLabel, self.molSysList):
            self.molSysLabelList.append(molSysLabel)
            self.molSysLabelDict[molSysLabel] = self.molSysList

        for molSys in self.molSysList:
            molSysLabel = '%s' % molSys.code

            if self.setChainLabels(molSysLabel, [molSys]):
                self.molSysLabelList.append(molSysLabel)
                self.molSysLabelDict[molSysLabel] = [molSys]

        if not self.molSysLabelList:
            showWarning('Warning',
                        'No chemical shift lists available! Exiting...')
            return

        #
        # Some initializing...
        #

        self.chains = None
        self.shiftList = None
        self.shiftListLabel = None
        self.results = None

        # modal = true means that it won't continue unless this one returns value
        BasePopup.__init__(self,
                           parent=parent,
                           title="Project '%s': " % project.name +
                           'Group chemical shift values',
                           modal=False,
                           transient=True)

    def setChainLabels(self, molSysLabel, molSysList):

        #
        # Set up chain information
        #

        chainLabelList = []
        chainLabelDict = {}
        chainLabelShiftListDict = {}

        self.molSysRelationDict[molSysLabel] = [
            chainLabelList, chainLabelDict, chainLabelShiftListDict
        ]

        chains = []

        for molSys in molSysList:
            chains.extend(list(molSys.sortedChains()))

        chainLabel = 'All chains'

        if self.setShiftListLabels(chainLabel, chains,
                                   self.molSysRelationDict[molSysLabel][2]):
            self.molSysRelationDict[molSysLabel][0].append(chainLabel)
            self.molSysRelationDict[molSysLabel][1][chainLabel] = chains

        for chain in chains:
            chainLabel = "'%s' (mol. '%s')" % (chain.code, chain.molecule.name)

            if self.setShiftListLabels(
                    chainLabel, [chain],
                    self.molSysRelationDict[molSysLabel][2]):
                self.molSysRelationDict[molSysLabel][0].append(chainLabel)
                self.molSysRelationDict[molSysLabel][1][chainLabel] = [chain]

        return self.molSysRelationDict[molSysLabel][0]

    def setShiftListLabels(self, chainLabel, chains, chainLabelShiftListDict):

        #
        # Set up chemical shift list information (slooooww so done at start)
        #

        shiftLists = []
        shiftListCount = {}
        resonanceTracker = []
        shiftListLabels = []
        shiftListLabelsDict = {}
        atomCount = 0

        for chain in chains:
            for residue in chain.residues:
                for atom in residue.atoms:
                    atomCount += 1
                    if atom.atomSet:
                        for resonanceSet in atom.atomSet.resonanceSets:
                            for resonance in resonanceSet.resonances:

                                if resonance in resonanceTracker:
                                    continue

                                resonanceTracker.append(resonance)

                                for shift in resonance.shifts:

                                    if shift.parentList not in shiftLists:
                                        shiftLists.append(shift.parentList)
                                        shiftListCount[shift.parentList] = 0

                                    shiftListCount[shift.parentList] += 1

        for shiftList in shiftLists:
            percentage = (shiftListCount[shift.parentList] * 100.0) / atomCount
            shiftListLabel = "%d:%s (%.1f%%)" % (shiftList.serial,
                                                 shiftList.name, percentage)
            shiftListLabels.append(shiftListLabel)
            shiftListLabelsDict[shiftListLabel] = shiftList

        chainLabelShiftListDict[chainLabel] = [
            shiftListLabels, shiftListLabelsDict
        ]

        return shiftListLabels

    def body(self, master):

        #
        # Setup header
        #

        row = 0
        self.columnSpan = 3

        label = Label(
            master,
            text=
            'Select molecular system, chains and chemical shift list to be analyzed:'
        )
        label.grid(row=row,
                   column=0,
                   columnspan=self.columnSpan,
                   sticky=Tkinter.EW)

        row += 1

        self.molSysSelect = PulldownMenu(master,
                                         entries=self.molSysLabelList,
                                         callback=self.setupChains)
        self.molSysSelect.grid(row=row, column=0, sticky=Tkinter.W)

        self.chainSelect = PulldownMenu(master,
                                        entries=self.chainLabelList,
                                        callback=self.setupShiftList)
        self.chainSelect.grid(row=row, column=1, sticky=Tkinter.W)

        self.shiftListSelect = PulldownMenu(master,
                                            entries=self.shiftListLabels,
                                            callback=self.setupPercentageFrame,
                                            do_initial_callback=False)
        self.shiftListSelect.grid(row=row, column=2, sticky=Tkinter.W)

        row += 1

        separator = Separator(master, height=3)
        separator.setColor('black', bgColor='black')
        separator.grid(row=row, columnspan=self.columnSpan, sticky=Tkinter.EW)

        row += 1

        master.grid_rowconfigure(row, weight=1)
        for i in range(self.columnSpan):
            master.grid_columnconfigure(i, weight=1)

        self.percentageFrame = ScrolledFrame(master,
                                             height=180,
                                             doExtraConfig=False)
        self.percentageFrame.grid(row=row,
                                  columnspan=self.columnSpan,
                                  sticky=Tkinter.NSEW)
        self.percentageFrameRow = row
        self.percentageFrameMaster = master

        row += 1

        separator = Separator(master, height=3)
        separator.setColor('black', bgColor='black')
        separator.grid(row=row, columnspan=self.columnSpan, sticky=Tkinter.EW)

        row += 1

        master.grid_rowconfigure(row, weight=1)
        self.resultsFrame = ScrolledFrame(master,
                                          height=180,
                                          doExtraConfig=False)
        self.resultsFrame.grid(row=row,
                               columnspan=self.columnSpan,
                               sticky=Tkinter.NSEW)
        self.resultsFrameRow = row
        self.resultsFrameMaster = master

        row += 1

        separator = Separator(master, height=3)
        separator.setColor('black', bgColor='black')
        separator.grid(row=row, columnspan=self.columnSpan, sticky=Tkinter.EW)

        row += 1

        texts = ['Recalculate', 'Write to file']
        commands = [
            self.recalc, self.writeFile
        ]  # This calls 'ok' in BasePopup, this then calls 'apply' in here
        buttons = createDismissHelpButtonList(master,
                                              texts=texts,
                                              commands=commands,
                                              dismiss_text='Exit',
                                              help_url=self.help_url)
        buttons.grid(row=row, columnspan=self.columnSpan, sticky=Tkinter.EW)

        self.shiftListSelect.callback(0, self.shiftListLabels[0])

    def setupChains(self, listIndex, molSysLabel):

        molSystems = self.molSysLabelDict[molSysLabel]

        if self.molSystems == molSystems:
            return

        self.molSystems = molSystems

        self.chainLabelList = self.molSysRelationDict[molSysLabel][0]
        self.chainLabelDict = self.molSysRelationDict[molSysLabel][1]
        self.chainLabelShiftListDict = self.molSysRelationDict[molSysLabel][2]

        if hasattr(self, 'chainSelect'):
            self.chains = None
            self.chainSelect.callback(0, self.chainLabelList[0])

    def setupShiftList(self, listIndex, chainLabel):

        chains = self.chainLabelDict[chainLabel]

        if self.chains == chains:
            return

        self.chains = chains

        #
        # Reset the pulldown menu
        #

        if hasattr(self, 'chainSelect'):
            self.chainSelect.replace(self.chainLabelList)

        #
        # Set up chemical shift lists
        #

        self.shiftListLabels = self.chainLabelShiftListDict[chainLabel][0]
        self.shiftListLabelsDict = self.chainLabelShiftListDict[chainLabel][1]

        if hasattr(self, 'percentageFrame'):
            self.shiftList = None
            self.shiftListLabel = None
            self.setupPercentageFrame(0, self.shiftListLabels[0])

    def setupPercentageFrame(self, listIndex, shiftListLabel):

        if self.shiftListLabel == shiftListLabel:
            return

        self.shiftList = self.shiftListLabelsDict[shiftListLabel]
        self.shiftListLabel = shiftListLabel

        #
        # Reset chemical shift groups...
        #

        self.shiftGroupsList = []

        for i in range(1, 10):
            shiftGroupLabel = 'Group_%s' % i
            self.shiftGroupsList.append(shiftGroupLabel)

        #
        # Reset the pulldown menu
        #

        if hasattr(self, 'shiftListSelect'):
            if hasattr(self.shiftListSelect,
                       'entries') and tuple(self.shiftListLabels) != tuple(
                           self.shiftListSelect.entries):  # HACK
                # otherwise can get infinite recursion but even with above could
                # if no self.shiftListLabels because of "None" entry in PulldownMenu
                self.shiftListSelect.replace(self.shiftListLabels)
            self.shiftListSelect.setSelected(shiftListLabel)

        #
        # Reset frame...
        #

        self.percentageFrame.destroy()
        self.percentageFrame = ScrolledFrame(self.percentageFrameMaster,
                                             height=180,
                                             doExtraConfig=False)
        self.percentageFrame.grid(row=self.percentageFrameRow,
                                  columnspan=self.columnSpan,
                                  sticky=Tkinter.NSEW)

        #
        # Recalculate results
        #

        self.results = makeChemShiftSelections(self.parent, self.chains,
                                               self.shiftList)
        resultKeys = self.results.keys()
        resultKeys.sort()

        #
        # Set up the information
        #

        frameRow = 0
        frame = self.percentageFrame.frame

        self.shiftGroupObjects = {}

        for resultKey in resultKeys:

            allAtoms = self.results[resultKey][0]
            shiftAtoms = self.results[resultKey][1]

            percentage = shiftAtoms * 100.0 / allAtoms

            label = Label(frame, text=resultKey)
            label.grid(row=frameRow, column=0, sticky=Tkinter.W)

            label = Label(frame, text="%.1f%%" % percentage)
            label.grid(row=frameRow, column=1, sticky=Tkinter.W)

            label = Label(frame, text="(%d/%d)" % (shiftAtoms, allAtoms))
            label.grid(row=frameRow, column=2, sticky=Tkinter.W)

            self.shiftGroupObjects[resultKey] = PulldownMenu(
                frame, entries=self.shiftGroupsList)
            self.shiftGroupObjects[resultKey].grid(row=frameRow,
                                                   column=3,
                                                   sticky=Tkinter.E)

            frameRow += 1

        return True

    def recalc(self):

        groups = {}
        groupsInfo = {}

        for resultKey in self.shiftGroupObjects:
            group = self.shiftGroupObjects[resultKey].getSelected()

            if not groups.has_key(group):
                groups[group] = []
                groupsInfo[group] = [0, 0]

            (allAtoms, shiftAtoms) = self.results[resultKey]
            groupsInfo[group][0] += allAtoms
            groupsInfo[group][1] += shiftAtoms

            groups[group].append(resultKey)

        #
        # Reset frame...
        #

        self.resultsFrame.destroy()
        self.resultsFrame = ScrolledFrame(self.resultsFrameMaster,
                                          height=180,
                                          doExtraConfig=False)
        self.resultsFrame.grid(row=self.resultsFrameRow,
                               columnspan=self.columnSpan,
                               sticky=Tkinter.NSEW)

        #
        # Set info in lower frame
        #

        frameRow = 0
        frame = self.resultsFrame.frame

        groupKeys = groups.keys()
        groupKeys.sort()

        self.groupText = {}

        for group in groupKeys:

            percentage = groupsInfo[group][1] * 100.0 / groupsInfo[group][0]

            label = Label(frame, text=group)
            label.grid(row=frameRow, column=0, sticky=Tkinter.W)

            label = Label(frame, text=groups[group][0])
            label.grid(row=frameRow, column=1, sticky=Tkinter.W)

            label = Label(frame, text="%.1f%%" % percentage)
            label.grid(row=frameRow, column=2, sticky=Tkinter.W)

            label = Label(frame,
                          text="(%d/%d)" %
                          (groupsInfo[group][1], groupsInfo[group][0]))
            label.grid(row=frameRow, column=3, sticky=Tkinter.W)

            self.groupText[group] = "%-10s %-20s %8.1f%% (%d/%d)%s" % (
                group, groups[group][0], percentage, groupsInfo[group][1],
                groupsInfo[group][0], newline)

            frameRow += 1

            for otherResultKey in groups[group][1:]:
                label = Label(frame, text=otherResultKey)
                label.grid(row=frameRow, column=2, sticky=Tkinter.W)

                self.groupText[group] += "%-10s %-20s%s" % ('', otherResultKey,
                                                            newline)

                frameRow += 1

        return True

    def writeFile(self):

        filePopup = FormatFilePopup(self, component='text')

        if filePopup.fileSelected:

            groupKeys = self.groupText.keys()
            groupKeys.sort()

            fout = open(filePopup.file, 'w')
            fout.write("Project: %s" % self.project.name + newline)
            fout.write("Molsystems: %s" % self.molSysSelect.getSelected() +
                       newline)
            fout.write("Chains: %s" % self.chainSelect.getSelected() + newline)
            fout.write("Shiftlist: %s" % self.shiftListSelect.getSelected() +
                       newline * 2)

            for group in groupKeys:

                fout.write(self.groupText[group])

            print "Wrote file %s..." % filePopup.file

    def apply(self):

        return True