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
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