class SaveLoadTab(object): """The tab that lets the user FileSelect a file to open or to save. """ 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.loadAndSaveButtons = None self.fileselectionBox = None self.body() def body(self): """Setting up the body of this view.""" frame = self.frame file_types = [FileType("pyc", ["*.pyc"])] self.fileselectionBox = FileSelect(frame, multiSelect=False, file_types=file_types) self.fileselectionBox.grid(row=0, column=0, columnspan=6, sticky="nsew") texts = ["Load", "Save"] commands = [self.loadDataFromPyc, self.saveDataToPyc] self.loadAndSaveButtons = ButtonList(frame, commands=commands, texts=texts) self.loadAndSaveButtons.grid(row=1, column=0, sticky="nsew") frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) def saveDataToPyc(self): """Save the data to the selected file.""" if self.guiParent.connector.results: fileName = self.fileselectionBox.getFile() self.guiParent.connector.saveDataToPyc(fileName) self.fileselectionBox.updateFileList() else: string = """There are no results to save, """ """the algorithm has not run yet.""" showWarning("No Results to Save", string, parent=self.guiParent) def loadDataFromPyc(self): """Load the data from the selected file.""" fileName = self.fileselectionBox.getFile() self.guiParent.connector.loadDataFromPyc(fileName) self.guiParent.resultsTab.update()
def body(self, guiParent): row = 0 self.graph = ScrolledGraph(guiParent) self.graph.grid(row=row, column=0, sticky='NSEW') row += 1 texts = ['Draw graph', 'Goodbye'] commands = [self.draw, self.destroy] buttons = ButtonList(guiParent, texts=texts, commands=commands) buttons.grid(row=row, column=0, sticky='NSEW')
def createBottomButtons(self, parent): if (self.editMode): texts = [] commands = [] if (self.metaclass.parentRole): texts.extend(['Parent', 'Siblings']) commands.extend([self.gotoParent, self.showSiblings]) if (self.metaclass.parentRole.otherClass.parentRole): texts.extend(['All']) commands.extend([self.showAll]) texts.extend(['Delete', 'Close']) commands.extend([self.deleteObject, self.close]) else: texts = ['Create', 'Cancel'] commands = [self.createObject, self.close] bottom_buttons = ButtonList(parent, texts=texts, commands=commands, direction=Tkinter.HORIZONTAL, expands=True) bottom_buttons.grid(row=2, column=0, columnspan=2, sticky=Tkinter.EW)
class AssignMentTransferTab(object): '''the tab in the GUI where assignments can be transferred in bulk to the ccpn analysis project. A difference is made between two types of assignments: 1) spin systems to residues, which also implies resonanceSets to atomSets. 2) resonances to peak dimensions. The user is able to configure which assignments should be transferred to the project. Attributes: guiParent: gui object this tab is part of. frame: the frame in which this element lives. dataModel(src.cython.malandro.DataModel): dataModel object describing the assignment proposed by the algorithm. selectedSolution (int): The index of the solution/run that is used asa the template to make the assignments. resonanceToDimension (bool): True if resonances should be assigned to peak dimensions. False if not. spinSystemToResidue (bool): True if spin system to residue assignment should be carried out. minScore (float): The minimal score of a spin system assignment to a residue to be allowed to transfer this assignment to the project intra (bool): True if intra-residual peaks should be assigned. sequential (bool): True if sequential peaks should be assigned. noDiagonal (bool): If True, purely diagonal peaks are ignored during the transfer of assignments. allSpectra (bool): If True, all spectra will be assigned. If False, one specified spectrum will be assigned. spectrum (src.cython.malandro.Spectrum): The spectrum that should be assigned. ''' def __init__(self, parent, frame): '''Init. args: parent: the guiElement that this tab is part of. frame: the frame this part of the GUI lives in. ''' self.guiParent = parent self.frame = frame # Buttons and fields, # will be set in body(): self.peaksCheckButton = None self.residuesCheckButton = None self.intraCheckButton = None self.sequentialCheckButton = None self.noDiagonalCheckButton = None self.spinSystemTypeSelect = None self.minScoreEntry = None self.solutionNumberEntry = None self.spectrumSelect = None self.spectraPullDown = None self.assignedResidueStrategySelect = None self.transferButton = None # Settings that determine how assignments # are transferred to the analysis project: self.minScore = 80.0 self.dataModel = None self.spectrum = None self.selectedSolution = 1 self.body() self.resonanceToDimension = True self.spinSystemToResidue = True self.intra = True self.sequential = True self.noDiagonal = True self.allSpectra = True self.spinSystemType = 0 self.strategy = 0 def body(self): '''Describes the body of this tab. It consists out of a number of radio buttons, check buttons and number entries that allow the user to indicate which assignments should be transferred. ''' # self.frame.expandColumn(0) self.frame.expandGrid(8, 0) self.frame.expandGrid(8, 1) typeOfAssignmentFrame = LabelFrame( self.frame, text='type of assignment') typeOfAssignmentFrame.grid(row=0, column=0, sticky='nesw') # typeOfAssignmentFrame.expandGrid(0,5) peakSelectionFrame = LabelFrame( self.frame, text='which peaks to assign') peakSelectionFrame.grid(row=0, column=1, sticky='nesw', rowspan=2) spinSystemSelectionFrame = LabelFrame(self.frame, text='Which spin-systems to use') spinSystemSelectionFrame.grid(row=2, column=0, sticky='nesw') tipText = 'What to do when a residue has already a spin system assigned to it.' assignedResidueFrame = LabelFrame(self.frame, text='if residue already has spin-system', tipText=tipText) assignedResidueFrame.grid(row=2, column=1, sticky='nesw') spectrumSelectionFrame = LabelFrame(self.frame, text='spectra') spectrumSelectionFrame.grid(row=1, column=0, sticky='nesw') row = 0 Label(typeOfAssignmentFrame, text='Resonances to Peak Dimensions', grid=(row, 0)) self.peaksCheckButton = CheckButton(typeOfAssignmentFrame, selected=True, grid=(row, 1)) row += 1 Label(typeOfAssignmentFrame, text='SpinSystems to Residues', grid=(row, 0)) self.residuesCheckButton = CheckButton( typeOfAssignmentFrame, selected=True, grid=(row, 1)) row = 0 Label(peakSelectionFrame, text='Intra-Residual', grid=(row, 0)) self.intraCheckButton = CheckButton( peakSelectionFrame, selected=True, grid=(row, 1)) row += 1 Label(peakSelectionFrame, text='Sequential', grid=(row, 0)) self.sequentialCheckButton = CheckButton( peakSelectionFrame, selected=True, grid=(row, 1)) row += 1 Label(peakSelectionFrame, text='Do not assign diagonal peaks', grid=(row, 0)) self.noDiagonalCheckButton = CheckButton( peakSelectionFrame, selected=True, grid=(row, 1)) entries = ['Only assigned spin systems', 'All that have a score of at least: ', 'User Defined', 'Solution number:'] tipTexts = ['Only assign resonances of spin systems that already have a sequential assignment for the assignment of peak dimensions. Spin system to residue assignment is not relevant in this case.', 'Assign all spin systems that have a score of at least a given percentage. 50% or lower is not possible, because than spin systems might have to be assigned to more than 1 residue, which is impossible.', "As defined in the lower row of buttons in the 'results' tab.", 'One of the single solutions of the annealing.'] self.spinSystemTypeSelect = RadioButtons(spinSystemSelectionFrame, entries=entries, grid=(0, 0), select_callback=None, direction=VERTICAL, gridSpan=(4, 1), tipTexts=tipTexts) tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.' self.minScoreEntry = FloatEntry(spinSystemSelectionFrame, grid=(1, 1), width=7, text=str(self.minScore), returnCallback=self.changeMinScore, tipText=tipText) self.minScoreEntry.bind('<Leave>', self.changeMinScore, '+') self.solutionNumberEntry = IntEntry(spinSystemSelectionFrame, grid=(3, 1), width=7, text=1, returnCallback=self.solutionUpdate, tipText=tipText) self.solutionNumberEntry.bind('<Leave>', self.solutionUpdate, '+') #self.solutionPullDown = PulldownList(spinSystemSelectionFrame, None, grid=(3,1), sticky='w') entries = ['all spectra', 'only:'] tipTexts = ['Assign peaks in all the spectra that where selected before the annealing ran.', 'Only assign peaks in one particular spectrum. You can of course repeat this multiple times for different spectra.'] self.spectrumSelect = RadioButtons(spectrumSelectionFrame, entries=entries, grid=(0, 0), select_callback=None, direction=VERTICAL, gridSpan=(2, 1), tipTexts=tipTexts) self.spectraPullDown = PulldownList(spectrumSelectionFrame, self.changeSpectrum, grid=(1, 1), sticky='w') entries = ['skip this residue', 'de-assign old spin system from residue', 'assign, but never merge', 'warn to merge'] tipTexts = ["Don't assign the new spin system to the residue. The residue is not skipped when the old spin system does not contain any resonances", "De-assign old spin system from residue, unless the old spin system is a spin system without any resonances.", "Don't merge any spin systems, merging can be performed later if nescesary in the Resonance --> SpinSystems window.", "Ask to merge individually for each spin system, this might result in clicking on a lot of popups."] self.assignedResidueStrategySelect = RadioButtons(assignedResidueFrame, entries=entries, grid=(0, 0), select_callback=None, direction=VERTICAL, gridSpan=(2, 1), tipTexts=tipTexts) texts = ['Transfer Assignments'] commands = [self.transferAssignments] self.transferButton = ButtonList( self.frame, commands=commands, texts=texts) self.transferButton.grid(row=5, column=0, sticky='nsew', columnspan=2) def update(self): '''Update the nescesary elements in the tab. Is called when the algorithm has produced possible assignments. The only thing that has to be updated in practice in this tab is the pulldown with spectra. ''' self.dataModel = self.guiParent.connector.results self.updateSpectra() def setDataModel(self, dataModel): '''Here the dataModel, which is the dataModel containing the suggested assignments body the algorithm, can be set. ''' self.dataModel = dataModel self.update() def updateSpectra(self, *opt): '''Updates the spectra shown in the spectra pulldown. These are only the spectra that were used by the algorithm. All other spectra in the project are not relevant since for those no simulated peaks have been matched to real peaks. ''' if not self.dataModel: return spectrum = self.spectrum spectra = self.dataModel.getSpectra() if spectra: names = [spectrum.name for spectrum in spectra] index = 0 if self.spectrum not in spectra: self.spectrum = spectra[0] else: index = spectra.index(self.spectrum) self.spectraPullDown.setup(names, spectra, index) def changeSpectrum(self, spectrum): '''Select a spectum to be assigned.''' self.spectrum = spectrum def solutionUpdate(self, event=None, value=None): '''Select a solution. A solution is a one to one mapping of spin systems to residues produced by one run of the algorithm. args: event: event object, this is one of the values the number entry calls his callback function with. value: the index of the solution/run. ''' if not self.dataModel: return Nsolutions = len(self.dataModel.chain.residues[0].solutions) if value is None: value = self.solutionNumberEntry.get() if value == self.selectedSolution: return else: self.selectedSolution = value if value < 1: self.solutionNumberEntry.set(1) self.selectedSolution = 1 elif value > Nsolutions: self.selectedSolution = Nsolutions self.solutionNumberEntry.set(self.selectedSolution) else: self.solutionNumberEntry.set(self.selectedSolution) def fetchOptions(self): '''Fetches user set options from the gui in one go and stores them in their corresponding instance variables. ''' self.resonanceToDimension = self.peaksCheckButton.get() self.spinSystemToResidue = self.residuesCheckButton.get() self.intra = self.intraCheckButton.get() self.sequential = self.sequentialCheckButton.get() self.noDiagonal = self.noDiagonalCheckButton.get() self.spinSystemType = self.spinSystemTypeSelect.getIndex() self.strategy = ['skip', 'remove', 'noMerge', None][ self.assignedResidueStrategySelect.getIndex()] self.allSpectra = [True, False][self.spectrumSelect.getIndex()] def changeMinScore(self, event=None): '''Set the minimal score for which a spin system to residue assignment gets transferred to the ccpn analysis project. ''' newMinScore = self.minScoreEntry.get() if self.minScore != newMinScore: if newMinScore <= 50.0: self.minScore = 51.0 self.minScoreEntry.set(51.0) elif newMinScore > 100.0: self.minScore = 100.0 self.minScoreEntry.set(100.0) else: self.minScore = newMinScore def transferAssignments(self): '''Transfer assignments to project depending on the settings from the GUI. ''' self.fetchOptions() if not self.dataModel or (not self.resonanceToDimension and not self.spinSystemToResidue): return strategy = self.strategy lookupSpinSystem = [self.getAssignedSpinSystem, self.getBestScoringSpinSystem, self.getUserDefinedSpinSystem, self.getSelectedSolutionSpinSystem][self.spinSystemType] residues = self.dataModel.chain.residues spinSystemSequence = [lookupSpinSystem(res) for res in residues] ccpnSpinSystems = [] ccpnResidues = [] # if self.spinSystemType == 0 it means that it for sure already # assigned like this if self.spinSystemToResidue and not self.spinSystemType == 0: for spinSys, res in zip(spinSystemSequence, residues): if spinSys and res: ccpnSpinSystems.append(spinSys.getCcpnResonanceGroup()) ccpnResidues.append(res.getCcpnResidue()) assignSpinSystemstoResidues(ccpnSpinSystems, ccpnResidues, strategy=strategy, guiParent=self.guiParent) if self.resonanceToDimension: allSpectra = self.allSpectra if self.intra: for residue, spinSystem in zip(residues, spinSystemSequence): if not spinSystem: continue intraLink = residue.getIntraLink(spinSystem) for pl in intraLink.getPeakLinks(): peak = pl.getPeak() if not allSpectra and peak.getSpectrum() is not self.spectrum: continue if not peak: continue resonances = pl.getResonances() if self.noDiagonal and len(set(resonances)) < len(resonances): continue for resonance, dimension in zip(resonances, peak.getDimensions()): ccpnResonance = resonance.getCcpnResonance() ccpnDimension = dimension.getCcpnDimension() assignResToDim(ccpnDimension, ccpnResonance) if self.sequential: for residue, spinSystemA, spinSystemB in zip(residues, spinSystemSequence, spinSystemSequence[1:]): if not spinSystemA or not spinSystemB: continue link = residue.getLink(spinSystemA, spinSystemB) for pl in link.getPeakLinks(): peak = pl.getPeak() if not allSpectra and peak.getSpectrum() is not self.spectrum: continue if not peak: continue resonances = pl.getResonances() if self.noDiagonal and len(set(resonances)) < len(resonances): continue for resonance, dimension in zip(resonances, peak.getDimensions()): ccpnResonance = resonance.getCcpnResonance() ccpnDimension = dimension.getCcpnDimension() assignResToDim(ccpnDimension, ccpnResonance) self.guiParent.resultsTab.update() def getAssignedSpinSystem(self, residue): '''Get the spinSystem that is assigned in the project to a residue. args: residue (src.cython.malandro.Residue) return: spinSystem (src.cython.malandro.SpinSystem) ''' ccpCode = residue.ccpCode seqCode = residue.getSeqCode() spinSystems = self.dataModel.getSpinSystems()[ccpCode] ccpnResidue = residue.getCcpnResidue() if ccpnResidue: assignedResonanceGroups = ccpnResidue.getResonanceGroups() if len(assignedResonanceGroups) > 1: print 'There is more than one spin system assigned to residue %s, did not know which one to use to assign peaks. Therefor this residue is skipped.' % (seqCode) return assignedResonanceGroup = ccpnResidue.findFirstResonanceGroup() if assignedResonanceGroup: for spinSystem in spinSystems: if spinSystem.getSerial() == assignedResonanceGroup.serial: # Just checking to make sure, analysis project could # have changed if not self.skipResidue(residue, spinSystem): return spinSystem def getBestScoringSpinSystem(self, residue): '''Get the spinSystem that scores the highest, i.e. is assigned in most of the runs to the given residue. args: residue (src.cython.malandro.Residue) return: spinSystem (src.cython.malandro.SpinSystem) ''' solutions = residue.solutions weigth = 1.0 / len(solutions) score, bestSpinSystem = max([(solutions.count(solution) * weigth * 100.0, solution) for solution in solutions]) if score >= self.minScore and not bestSpinSystem.getIsJoker() and not self.skipResidue(residue, bestSpinSystem): return bestSpinSystem return None def getUserDefinedSpinSystem(self, residue): '''Get the spinSystem that is defined by the user (probably in the resultsTab) as the correct assignment of the given residue. args: residue (src.cython.malandro.Residue) return: spinSystem (src.cython.malandro.SpinSystem) ''' userDefinedSpinSystem = residue.userDefinedSolution if userDefinedSpinSystem and not userDefinedSpinSystem.getIsJoker() and not self.skipResidue(residue, userDefinedSpinSystem): return userDefinedSpinSystem return None def getSelectedSolutionSpinSystem(self, residue): '''I a solution corresponding to one specific run of the algorithm is defined, return which spinSystem in that run got assigned to the given residue. args: residue (src.cython.malandro.Residue) return: spinSystem (src.cython.malandro.SpinSystem) ''' solutions = residue.solutions spinSystem = solutions[self.selectedSolution - 1] if not spinSystem.getIsJoker() and not self.skipResidue(residue, spinSystem): return spinSystem return None def skipResidue(self, residue, spinSystem): '''One strategy is to skip all residues that already have a spin system assignment. If that is the case determine whether to skip the given residue. args: residue (src.cython.malandro.Residue) spinSystem (src.cython.malandro.SpinSystem) return: boolean, True if residue should be skipped. ''' if self.strategy == 0: assignedGroups = residue.getCcpnResidue().getResonanceGroups() assignedSerials = set([spinSys.serial for spinSys in assignedGroups]) if assignedSerials and spinSystem.getSerial() not in assignedSerials: return True return False
class ObjectTablePopup(BasePopup): def __init__(self, parent, root, metaclass, onlyShow=False, *args, **kw): self.root = root self.metaclass = metaclass self.onlyShow = onlyShow BasePopup.__init__(self, parent, title='Browser for %s objects' % metaclass.name, location='+50+50', *args, **kw) def body(self, master): master.grid_rowconfigure(0, weight=1) master.grid_columnconfigure(0, weight=1) self.table = ObjectTable(master, self.metaclass) self.table.grid(row=0, column=0, sticky=Tkinter.NSEW) if (self.onlyShow): texts = ['Close'] commands = [self.close] else: texts = ['Ok', 'Cancel'] commands = [self.ok, self.close] self.buttons = ButtonList(master, texts=texts, commands=commands, direction=Tkinter.HORIZONTAL, expands=True) self.buttons.grid(row=1, column=0, sticky=Tkinter.EW) self.selected = None self.setObjects() self.doRegisters() def doRegisters(self): # do not need '' since dealing with keys #for func in ('', '__init__', 'delete'): for func in ('__init__', 'delete'): self.registerNotify(self.setObjects, self.metaclass.qualifiedName(), func) # unregisters dealt with by BasePopup def apply(self): selected = self.table.currentObject if (not selected): showError('No selection', "No object selected", parent=self) return False self.selected = selected return True def setObjects(self, *extra): objects = getAllObjects(self.root, self.metaclass) self.table.setObjects(objects)
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 __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()
class AssignMentTransferTab(object): '''the tab in the GUI where assignments can be transferred in bulk to the ccpn analysis project. A difference is made between two types of assignments: 1) spin systems to residues, which also implies resonanceSets to atomSets. 2) resonances to peak dimensions. The user is able to configure which assignments should be transferred to the project. Attributes: guiParent: gui object this tab is part of. frame: the frame in which this element lives. dataModel(src.cython.malandro.DataModel): dataModel object describing the assignment proposed by the algorithm. selectedSolution (int): The index of the solution/run that is used asa the template to make the assignments. resonanceToDimension (bool): True if resonances should be assigned to peak dimensions. False if not. spinSystemToResidue (bool): True if spin system to residue assignment should be carried out. minScore (float): The minimal score of a spin system assignment to a residue to be allowed to transfer this assignment to the project intra (bool): True if intra-residual peaks should be assigned. sequential (bool): True if sequential peaks should be assigned. noDiagonal (bool): If True, purely diagonal peaks are ignored during the transfer of assignments. allSpectra (bool): If True, all spectra will be assigned. If False, one specified spectrum will be assigned. spectrum (src.cython.malandro.Spectrum): The spectrum that should be assigned. ''' def __init__(self, parent, frame): '''Init. args: parent: the guiElement that this tab is part of. frame: the frame this part of the GUI lives in. ''' self.guiParent = parent self.frame = frame # Buttons and fields, # will be set in body(): self.peaksCheckButton = None self.residuesCheckButton = None self.intraCheckButton = None self.sequentialCheckButton = None self.noDiagonalCheckButton = None self.spinSystemTypeSelect = None self.minScoreEntry = None self.solutionNumberEntry = None self.spectrumSelect = None self.spectraPullDown = None self.assignedResidueStrategySelect = None self.transferButton = None # Settings that determine how assignments # are transferred to the analysis project: self.minScore = 80.0 self.dataModel = None self.spectrum = None self.selectedSolution = 1 self.body() self.resonanceToDimension = True self.spinSystemToResidue = True self.intra = True self.sequential = True self.noDiagonal = True self.allSpectra = True self.spinSystemType = 0 self.strategy = 0 def body(self): '''Describes the body of this tab. It consists out of a number of radio buttons, check buttons and number entries that allow the user to indicate which assignments should be transferred. ''' # self.frame.expandColumn(0) self.frame.expandGrid(8, 0) self.frame.expandGrid(8, 1) typeOfAssignmentFrame = LabelFrame(self.frame, text='type of assignment') typeOfAssignmentFrame.grid(row=0, column=0, sticky='nesw') # typeOfAssignmentFrame.expandGrid(0,5) peakSelectionFrame = LabelFrame(self.frame, text='which peaks to assign') peakSelectionFrame.grid(row=0, column=1, sticky='nesw', rowspan=2) spinSystemSelectionFrame = LabelFrame(self.frame, text='Which spin-systems to use') spinSystemSelectionFrame.grid(row=2, column=0, sticky='nesw') tipText = 'What to do when a residue has already a spin system assigned to it.' assignedResidueFrame = LabelFrame( self.frame, text='if residue already has spin-system', tipText=tipText) assignedResidueFrame.grid(row=2, column=1, sticky='nesw') spectrumSelectionFrame = LabelFrame(self.frame, text='spectra') spectrumSelectionFrame.grid(row=1, column=0, sticky='nesw') row = 0 Label(typeOfAssignmentFrame, text='Resonances to Peak Dimensions', grid=(row, 0)) self.peaksCheckButton = CheckButton(typeOfAssignmentFrame, selected=True, grid=(row, 1)) row += 1 Label(typeOfAssignmentFrame, text='SpinSystems to Residues', grid=(row, 0)) self.residuesCheckButton = CheckButton(typeOfAssignmentFrame, selected=True, grid=(row, 1)) row = 0 Label(peakSelectionFrame, text='Intra-Residual', grid=(row, 0)) self.intraCheckButton = CheckButton(peakSelectionFrame, selected=True, grid=(row, 1)) row += 1 Label(peakSelectionFrame, text='Sequential', grid=(row, 0)) self.sequentialCheckButton = CheckButton(peakSelectionFrame, selected=True, grid=(row, 1)) row += 1 Label(peakSelectionFrame, text='Do not assign diagonal peaks', grid=(row, 0)) self.noDiagonalCheckButton = CheckButton(peakSelectionFrame, selected=True, grid=(row, 1)) entries = [ 'Only assigned spin systems', 'All that have a score of at least: ', 'User Defined', 'Solution number:' ] tipTexts = [ 'Only assign resonances of spin systems that already have a sequential assignment for the assignment of peak dimensions. Spin system to residue assignment is not relevant in this case.', 'Assign all spin systems that have a score of at least a given percentage. 50% or lower is not possible, because than spin systems might have to be assigned to more than 1 residue, which is impossible.', "As defined in the lower row of buttons in the 'results' tab.", 'One of the single solutions of the annealing.' ] self.spinSystemTypeSelect = RadioButtons(spinSystemSelectionFrame, entries=entries, grid=(0, 0), select_callback=None, direction=VERTICAL, gridSpan=(4, 1), tipTexts=tipTexts) tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.' self.minScoreEntry = FloatEntry(spinSystemSelectionFrame, grid=(1, 1), width=7, text=str(self.minScore), returnCallback=self.changeMinScore, tipText=tipText) self.minScoreEntry.bind('<Leave>', self.changeMinScore, '+') self.solutionNumberEntry = IntEntry(spinSystemSelectionFrame, grid=(3, 1), width=7, text=1, returnCallback=self.solutionUpdate, tipText=tipText) self.solutionNumberEntry.bind('<Leave>', self.solutionUpdate, '+') #self.solutionPullDown = PulldownList(spinSystemSelectionFrame, None, grid=(3,1), sticky='w') entries = ['all spectra', 'only:'] tipTexts = [ 'Assign peaks in all the spectra that where selected before the annealing ran.', 'Only assign peaks in one particular spectrum. You can of course repeat this multiple times for different spectra.' ] self.spectrumSelect = RadioButtons(spectrumSelectionFrame, entries=entries, grid=(0, 0), select_callback=None, direction=VERTICAL, gridSpan=(2, 1), tipTexts=tipTexts) self.spectraPullDown = PulldownList(spectrumSelectionFrame, self.changeSpectrum, grid=(1, 1), sticky='w') entries = [ 'skip this residue', 'de-assign old spin system from residue', 'assign, but never merge', 'warn to merge' ] tipTexts = [ "Don't assign the new spin system to the residue. The residue is not skipped when the old spin system does not contain any resonances", "De-assign old spin system from residue, unless the old spin system is a spin system without any resonances.", "Don't merge any spin systems, merging can be performed later if nescesary in the Resonance --> SpinSystems window.", "Ask to merge individually for each spin system, this might result in clicking on a lot of popups." ] self.assignedResidueStrategySelect = RadioButtons(assignedResidueFrame, entries=entries, grid=(0, 0), select_callback=None, direction=VERTICAL, gridSpan=(2, 1), tipTexts=tipTexts) texts = ['Transfer Assignments'] commands = [self.transferAssignments] self.transferButton = ButtonList(self.frame, commands=commands, texts=texts) self.transferButton.grid(row=5, column=0, sticky='nsew', columnspan=2) def update(self): '''Update the nescesary elements in the tab. Is called when the algorithm has produced possible assignments. The only thing that has to be updated in practice in this tab is the pulldown with spectra. ''' self.dataModel = self.guiParent.connector.results self.updateSpectra() def setDataModel(self, dataModel): '''Here the dataModel, which is the dataModel containing the suggested assignments body the algorithm, can be set. ''' self.dataModel = dataModel self.update() def updateSpectra(self, *opt): '''Updates the spectra shown in the spectra pulldown. These are only the spectra that were used by the algorithm. All other spectra in the project are not relevant since for those no simulated peaks have been matched to real peaks. ''' if not self.dataModel: return spectrum = self.spectrum spectra = self.dataModel.getSpectra() if spectra: names = [spectrum.name for spectrum in spectra] index = 0 if self.spectrum not in spectra: self.spectrum = spectra[0] else: index = spectra.index(self.spectrum) self.spectraPullDown.setup(names, spectra, index) def changeSpectrum(self, spectrum): '''Select a spectum to be assigned.''' self.spectrum = spectrum def solutionUpdate(self, event=None, value=None): '''Select a solution. A solution is a one to one mapping of spin systems to residues produced by one run of the algorithm. args: event: event object, this is one of the values the number entry calls his callback function with. value: the index of the solution/run. ''' if not self.dataModel: return Nsolutions = len(self.dataModel.chain.residues[0].solutions) if value is None: value = self.solutionNumberEntry.get() if value == self.selectedSolution: return else: self.selectedSolution = value if value < 1: self.solutionNumberEntry.set(1) self.selectedSolution = 1 elif value > Nsolutions: self.selectedSolution = Nsolutions self.solutionNumberEntry.set(self.selectedSolution) else: self.solutionNumberEntry.set(self.selectedSolution) def fetchOptions(self): '''Fetches user set options from the gui in one go and stores them in their corresponding instance variables. ''' self.resonanceToDimension = self.peaksCheckButton.get() self.spinSystemToResidue = self.residuesCheckButton.get() self.intra = self.intraCheckButton.get() self.sequential = self.sequentialCheckButton.get() self.noDiagonal = self.noDiagonalCheckButton.get() self.spinSystemType = self.spinSystemTypeSelect.getIndex() self.strategy = ['skip', 'remove', 'noMerge', None][self.assignedResidueStrategySelect.getIndex()] self.allSpectra = [True, False][self.spectrumSelect.getIndex()] def changeMinScore(self, event=None): '''Set the minimal score for which a spin system to residue assignment gets transferred to the ccpn analysis project. ''' newMinScore = self.minScoreEntry.get() if self.minScore != newMinScore: if newMinScore <= 50.0: self.minScore = 51.0 self.minScoreEntry.set(51.0) elif newMinScore > 100.0: self.minScore = 100.0 self.minScoreEntry.set(100.0) else: self.minScore = newMinScore def transferAssignments(self): '''Transfer assignments to project depending on the settings from the GUI. ''' self.fetchOptions() if not self.dataModel or (not self.resonanceToDimension and not self.spinSystemToResidue): return strategy = self.strategy lookupSpinSystem = [ self.getAssignedSpinSystem, self.getBestScoringSpinSystem, self.getUserDefinedSpinSystem, self.getSelectedSolutionSpinSystem ][self.spinSystemType] residues = self.dataModel.chain.residues spinSystemSequence = [lookupSpinSystem(res) for res in residues] ccpnSpinSystems = [] ccpnResidues = [] # if self.spinSystemType == 0 it means that it for sure already # assigned like this if self.spinSystemToResidue and not self.spinSystemType == 0: for spinSys, res in zip(spinSystemSequence, residues): if spinSys and res: ccpnSpinSystems.append(spinSys.getCcpnResonanceGroup()) ccpnResidues.append(res.getCcpnResidue()) assignSpinSystemstoResidues(ccpnSpinSystems, ccpnResidues, strategy=strategy, guiParent=self.guiParent) if self.resonanceToDimension: allSpectra = self.allSpectra if self.intra: for residue, spinSystem in zip(residues, spinSystemSequence): if not spinSystem: continue intraLink = residue.getIntraLink(spinSystem) for pl in intraLink.getPeakLinks(): peak = pl.getPeak() if not allSpectra and peak.getSpectrum( ) is not self.spectrum: continue if not peak: continue resonances = pl.getResonances() if self.noDiagonal and len( set(resonances)) < len(resonances): continue for resonance, dimension in zip( resonances, peak.getDimensions()): ccpnResonance = resonance.getCcpnResonance() ccpnDimension = dimension.getCcpnDimension() assignResToDim(ccpnDimension, ccpnResonance) if self.sequential: for residue, spinSystemA, spinSystemB in zip( residues, spinSystemSequence, spinSystemSequence[1:]): if not spinSystemA or not spinSystemB: continue link = residue.getLink(spinSystemA, spinSystemB) for pl in link.getPeakLinks(): peak = pl.getPeak() if not allSpectra and peak.getSpectrum( ) is not self.spectrum: continue if not peak: continue resonances = pl.getResonances() if self.noDiagonal and len( set(resonances)) < len(resonances): continue for resonance, dimension in zip( resonances, peak.getDimensions()): ccpnResonance = resonance.getCcpnResonance() ccpnDimension = dimension.getCcpnDimension() assignResToDim(ccpnDimension, ccpnResonance) self.guiParent.resultsTab.update() def getAssignedSpinSystem(self, residue): '''Get the spinSystem that is assigned in the project to a residue. args: residue (src.cython.malandro.Residue) return: spinSystem (src.cython.malandro.SpinSystem) ''' ccpCode = residue.ccpCode seqCode = residue.getSeqCode() spinSystems = self.dataModel.getSpinSystems()[ccpCode] ccpnResidue = residue.getCcpnResidue() if ccpnResidue: assignedResonanceGroups = ccpnResidue.getResonanceGroups() if len(assignedResonanceGroups) > 1: print 'There is more than one spin system assigned to residue %s, did not know which one to use to assign peaks. Therefor this residue is skipped.' % ( seqCode) return assignedResonanceGroup = ccpnResidue.findFirstResonanceGroup() if assignedResonanceGroup: for spinSystem in spinSystems: if spinSystem.getSerial() == assignedResonanceGroup.serial: # Just checking to make sure, analysis project could # have changed if not self.skipResidue(residue, spinSystem): return spinSystem def getBestScoringSpinSystem(self, residue): '''Get the spinSystem that scores the highest, i.e. is assigned in most of the runs to the given residue. args: residue (src.cython.malandro.Residue) return: spinSystem (src.cython.malandro.SpinSystem) ''' solutions = residue.solutions weigth = 1.0 / len(solutions) score, bestSpinSystem = max([ (solutions.count(solution) * weigth * 100.0, solution) for solution in solutions ]) if score >= self.minScore and not bestSpinSystem.getIsJoker( ) and not self.skipResidue(residue, bestSpinSystem): return bestSpinSystem return None def getUserDefinedSpinSystem(self, residue): '''Get the spinSystem that is defined by the user (probably in the resultsTab) as the correct assignment of the given residue. args: residue (src.cython.malandro.Residue) return: spinSystem (src.cython.malandro.SpinSystem) ''' userDefinedSpinSystem = residue.userDefinedSolution if userDefinedSpinSystem and not userDefinedSpinSystem.getIsJoker( ) and not self.skipResidue(residue, userDefinedSpinSystem): return userDefinedSpinSystem return None def getSelectedSolutionSpinSystem(self, residue): '''I a solution corresponding to one specific run of the algorithm is defined, return which spinSystem in that run got assigned to the given residue. args: residue (src.cython.malandro.Residue) return: spinSystem (src.cython.malandro.SpinSystem) ''' solutions = residue.solutions spinSystem = solutions[self.selectedSolution - 1] if not spinSystem.getIsJoker() and not self.skipResidue( residue, spinSystem): return spinSystem return None def skipResidue(self, residue, spinSystem): '''One strategy is to skip all residues that already have a spin system assignment. If that is the case determine whether to skip the given residue. args: residue (src.cython.malandro.Residue) spinSystem (src.cython.malandro.SpinSystem) return: boolean, True if residue should be skipped. ''' if self.strategy == 0: assignedGroups = residue.getCcpnResidue().getResonanceGroups() assignedSerials = set( [spinSys.serial for spinSys in assignedGroups]) if assignedSerials and spinSystem.getSerial( ) not in assignedSerials: return True return False
def body(self, guiFrame): row = 0 col =0 # frame = Frame( guiFrame ) # frame.grid(row=row, column=col, sticky='news') self.menuBar = Menu( guiFrame) self.menuBar.grid( row=row, column=col, sticky='ew') #---------------------------------------------------------------------------------- # Project frame #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(row, weight=1) # frame = LabelFrame(guiFrame, text='Project', font=medFont) row = +1 col =0 frame = LabelFrame(guiFrame, text='Project', **labelFrameAttributes ) print '>', frame.keys() frame.grid(row=row, column=col, sticky='nsew' ) frame.grid_columnconfigure(2, weight=1) # frame.grid_rowconfigure(0, weight=1) srow = 0 self.projectOptions = ['old','new from PDB','new from CCPN','new from CYANA'] self.projOptionsSelect = RadioButtons(frame, selected_index=0, entries=self.projectOptions, direction='vertical', select_callback=self.updateGui ) self.projOptionsSelect.grid(row=srow,column=0,rowspan=len(self.projectOptions),columnspan=2, sticky='w') if self.options.name: text = self.options.name else: text='' # end if self.projEntry = Entry(frame, bd=1, text=text, returnCallback=self.updateGui) self.projEntry.grid(row=srow,column=2,columnspan=2,sticky='ew') # self.projEntry.bind('<Key>', self.updateGui) self.projEntry.bind('<Leave>', self.updateGui) projButton = Button(frame, bd=1,command=self.chooseOldProjectFile, text='browse') projButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.pdbEntry = Entry(frame, bd=1, text='') self.pdbEntry.grid(row=srow,column=2,sticky='ew') self.pdbEntry.bind('<Leave>', self.updateGui) pdbButton = Button(frame, bd=1,command=self.choosePdbFile, text='browse') pdbButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.ccpnEntry = Entry(frame, bd=1, text='') self.ccpnEntry.grid(row=srow,column=2,sticky='ew') self.ccpnEntry.bind('<Leave>', self.updateGui) ccpnButton = Button(frame, bd=1,command=self.chooseCcpnFile, text='browse') ccpnButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.cyanaEntry = Entry(frame, bd=1, text='') self.cyanaEntry.grid(row=srow,column=2,sticky='ew') self.cyanaEntry.bind('<Leave>', self.updateGui) cyanaButton = Button(frame, bd=1,command=self.chooseCyanaFile, text='browse') cyanaButton.grid(row=srow,column=3,sticky='ew') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 label = Label(frame, text='Project name:') label.grid(row=srow,column=0,sticky='nw') self.nameEntry = Entry(frame, bd=1, text='') self.nameEntry.grid(row=srow,column=2,sticky='w') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 self.openProjectButton = Button(frame, command=self.openProject, text='Open Project', **actionButtonAttributes ) self.openProjectButton.grid(row=srow,column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # status #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(1, weight=0) srow = 0 frame = LabelFrame(guiFrame, text='Status', **labelFrameAttributes) frame.grid( row=srow, column=1, sticky='wnes') self.projectStatus = Text(frame, height=11, width=70, borderwidth=0, relief='flat') self.projectStatus.grid(row=0, column=0, sticky='wen') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 self.closeProjectButton = Button(frame, command=self.closeProject, text='Close Project', **actionButtonAttributes) self.closeProjectButton.grid(row=srow,column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # Validate frame #---------------------------------------------------------------------------------- row +=1 col=0 frame = LabelFrame(guiFrame, text='Validate', **labelFrameAttributes) # frame = LabelFrame(guiFrame, text='Validate', font=medFont) frame.grid(row=row, column=col, sticky='nsew') # frame.grid_columnconfigure(2, weight=1) frame.grid_rowconfigure(0, weight=1) srow = 0 # label = Label(frame, text='validation') # label.grid(row=srow,column=0,sticky='nw') # # self.selectDoValidation = CheckButton(frame) # self.selectDoValidation.grid(row=srow, column=1,sticky='nw' ) # self.selectDoValidation.set(True) # # srow += 1 # label = Label(frame, text='') # label.grid(row=srow,column=0,sticky='nw') # # srow += 1 label = Label(frame, text='checks') label.grid(row=srow,column=0,sticky='nw') self.selectCheckAssign = CheckButton(frame) self.selectCheckAssign.grid(row=srow, column=1,sticky='nw' ) self.selectCheckAssign.set(True) label = Label(frame, text='assignments and shifts') label.grid(row=srow,column=2,sticky='nw') # srow += 1 # self.selectCheckQueen = CheckButton(frame) # self.selectCheckQueen.grid(row=srow, column=4,sticky='nw' ) # self.selectCheckQueen.set(False) # label = Label(frame, text='QUEEN') # label.grid(row=srow,column=5,sticky='nw') # # queenButton = Button(frame, bd=1,command=None, text='setup') # queenButton.grid(row=srow,column=6,sticky='ew') srow += 1 self.selectCheckResraint = CheckButton(frame) self.selectCheckResraint.grid(row=srow, column=1,sticky='nw' ) self.selectCheckResraint.set(True) label = Label(frame, text='restraints') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectCheckStructure = CheckButton(frame) self.selectCheckStructure.grid(row=srow, column=1,sticky='nw' ) self.selectCheckStructure.set(True) label = Label(frame, text='structural') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectMakeHtml = CheckButton(frame) self.selectMakeHtml.grid(row=srow, column=1,sticky='nw' ) self.selectMakeHtml.set(True) label = Label(frame, text='generate HTML') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectCheckScript = CheckButton(frame) self.selectCheckScript.grid(row=srow, column=1,sticky='nw' ) self.selectCheckScript.set(False) label = Label(frame, text='user script') label.grid(row=srow,column=0,sticky='nw') self.validScriptEntry = Entry(frame, bd=1, text='') self.validScriptEntry.grid(row=srow,column=2,columnspan=3, sticky='ew') scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') scriptButton.grid(row=srow,column=5,sticky='ew') srow += 1 label = Label(frame, text='ranges') label.grid(row=srow,column=0,sticky='nw') self.rangesEntry = Entry( frame, text='' ) self.rangesEntry.grid( row=srow, column=2, columnspan=3, sticky='ew') # self.validScriptEntry = Entry(frame, bd=1, text='') # self.validScriptEntry.grid(row=srow,column=3,sticky='ew') # # scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') # scriptButton.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Run Validation','View Results','Setup QUEEN'] commands = [self.runCing, None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands,expands=True) buttonBar.grid(row=srow, column=0, columnspan=6, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.runButton = buttonBar.buttons[0] self.viewResultButton = buttonBar.buttons[1] self.queenButton = buttonBar.buttons[2] #---------------------------------------------------------------------------------- # Miscellaneous frame #---------------------------------------------------------------------------------- row +=0 col=1 # frame = LabelFrame(guiFrame, text='Miscellaneous', font=medFont) frame = LabelFrame(guiFrame, text='Miscellaneous', **labelFrameAttributes) frame.grid(row=row, column=col, sticky='news') frame.grid_columnconfigure(2, weight=1) frame.grid_columnconfigure(4, weight=1,minsize=30) frame.grid_rowconfigure(0, weight=1) # Exports srow = 0 label = Label(frame, text='export to') label.grid(row=srow,column=0,sticky='nw') self.selectExportXeasy = CheckButton(frame) self.selectExportXeasy.grid(row=srow, column=1,sticky='nw' ) self.selectExportXeasy.set(True) label = Label(frame, text='Xeasy, Sparky, TALOS, ...') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportCcpn = CheckButton(frame) self.selectExportCcpn.grid(row=srow, column=1,sticky='nw' ) self.selectExportCcpn.set(True) label = Label(frame, text='CCPN') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportQueen = CheckButton(frame) self.selectExportQueen.grid(row=srow, column=1,sticky='nw' ) self.selectExportQueen.set(True) label = Label(frame, text='QUEEN') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportRefine = CheckButton(frame) self.selectExportRefine.grid(row=srow, column=1,sticky='nw' ) self.selectExportRefine.set(True) label = Label(frame, text='refine') label.grid(row=srow,column=2,sticky='nw') srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') # User script srow += 1 label = Label(frame, text='user script') label.grid(row=srow,column=0,sticky='nw') self.selectMiscScript = CheckButton(frame) self.selectMiscScript.grid(row=srow, column=1,sticky='nw' ) self.selectMiscScript.set(False) self.miscScriptEntry = Entry(frame, bd=1, text='') self.miscScriptEntry.grid(row=srow,column=3,sticky='ew') script2Button = Button(frame, bd=1,command=self.chooseMiscScript, text='browse') script2Button.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Export','Run Script'] commands = [None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands,expands=True) buttonBar.grid(row=srow, column=0, columnspan=5, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.exportButton = buttonBar.buttons[0] self.scriptButton = buttonBar.buttons[1] #---------------------------------------------------------------------------------- # Textarea #---------------------------------------------------------------------------------- row +=1 guiFrame.grid_rowconfigure(row, weight=1) self.outputTextBox = ScrolledText(guiFrame) self.outputTextBox.grid(row=row, column=0, columnspan=2, sticky='nsew') self.redirectConsole() #---------------------------------------------------------------------------------- # Buttons #---------------------------------------------------------------------------------- row +=1 col=0 texts = ['Quit', 'Help'] commands = [self.close, None] self.buttonBar = ButtonList(guiFrame, texts=texts, commands=commands,expands=True) self.buttonBar.grid(row=row, column=col, columnspan=2, sticky='ew') # self.openProjectButton = self.buttonBar.buttons[0] # self.closeProjectButton = self.buttonBar.buttons[1] # self.runButton = self.buttonBar.buttons[0] # self.viewResultButton = self.buttonBar.buttons[1] for button in self.buttonBar.buttons: button.config(**actionButtonAttributes)
class CloudsPopup(BasePopup): def __init__(self, parent, *args, **kw): self.guiParent = parent self.project = parent.getProject() self.waiting = 0 self.specFreq = 800.13 self.maxIter = 50 self.mixTime = 60 self.corrTime = 11.5 self.leakRate = 2.0 self.peakListDict = {} self.noesyPeakList = None self.tocsyPeakList = None self.noesy3dPeakList = None self.hsqcPeakList = None self.maxIntens = 37000000 self.resonances = None self.origResonances = None self.noesyPeaks = None self.distanceConstraintList = None self.antiDistConstraintList = None self.numClouds = 100 self.filePrefix = 'cloud_' self.cloudsFiles = [] self.adcAtomTypes = 'HN' self.structure = None # step num, initial temp, final temp, cooling steps, MD steps, MD tau, rep scale self.coolingScheme = [] self.coolingScheme.append([1, 1, 1, 3, 500, 0.001, 0]) self.coolingScheme.append([2, 80000, 4000, 19, 1000, 0.001, 0]) self.coolingScheme.append([3, 4000, 1, 5, 500, 0.001, 0]) self.coolingScheme.append([4, 15000, 1, 3, 1000, 0.001, 0]) self.coolingScheme.append([5, 1, 1, 5, 500, 0.001, 0]) self.coolingScheme.append([6, 8000, 1, 3, 1000, 0.001, 0]) self.coolingScheme.append([7, 1, 1, 5, 500, 0.001, 0]) self.coolingScheme.append([8, 3000, 25, 60, 2500, 0.001, 1]) self.coolingScheme.append([9, 25, 25, 1, 7500, 0.001, 1]) self.coolingScheme.append([10, 10, 10, 1, 7500, 0.001, 1]) self.coolingScheme.append([11, 0.01, 0.01, 1, 7500, 0.0005, 1]) self.coolingStep = None BasePopup.__init__(self, parent, title="Resonance Clouds Analysis", **kw) def body(self, guiFrame): self.specFreqEntry = IntEntry(self, text=self.specFreq, width=8, returnCallback=self.setSpecFreq) self.maxIterEntry = IntEntry(self, text=self.maxIter, width=8, returnCallback=self.setMaxIter) self.mixTimeEntry = FloatEntry(self, text=self.mixTime, width=8, returnCallback=self.setMixTime) self.corrTimeEntry = FloatEntry(self, text=self.corrTime, width=8, returnCallback=self.setCorrTime) self.leakRateEntry = FloatEntry(self, text=self.leakRate, width=8, returnCallback=self.setLeakRate) self.maxIntensEntry = IntEntry(self, text=self.maxIntens, width=8, returnCallback=self.setMaxIntens) self.mdInitTempEntry = FloatEntry(self, text='', returnCallback=self.setMdInitTemp) self.mdFinTempEntry = FloatEntry(self, text='', returnCallback=self.setMdFinTemp) self.mdCoolStepsEntry = IntEntry(self, text='', returnCallback=self.setMdCoolSteps) self.mdSimStepsEntry = IntEntry(self, text='', returnCallback=self.setMdSimSteps) self.mdTauEntry = FloatEntry(self, text='', returnCallback=self.setMdTau) self.mdRepScaleEntry = FloatEntry(self, text='', returnCallback=self.setMdRepScale) guiFrame.grid_columnconfigure(0, weight=1) row = 0 frame0 = LabelFrame(guiFrame, text='Setup peak lists') frame0.grid(row=row, column=0, sticky=Tkinter.NSEW) frame0.grid(row=row, column=0, sticky=Tkinter.NSEW) frame0.grid_columnconfigure(1, weight=1) f0row = 0 label00 = Label(frame0, text='1H-1H NOESY spectrum') label00.grid(row=f0row, column=0, sticky=Tkinter.NW) self.noesyPulldown = PulldownMenu(frame0, entries=self.getNoesys(), callback=self.setNoesy, selected_index=0, do_initial_callback=0) self.noesyPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW) f0row += 1 label01 = Label(frame0, text='15N HSQC spectrum') label01.grid(row=f0row, column=0, sticky=Tkinter.NW) self.hsqcPulldown = PulldownMenu(frame0, entries=self.getHsqcs(), callback=self.setHsqc, selected_index=0, do_initial_callback=0) self.hsqcPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW) f0row += 1 label02 = Label(frame0, text='15N HSQC TOCSY spectrum') label02.grid(row=f0row, column=0, sticky=Tkinter.NW) self.tocsyPulldown = PulldownMenu(frame0, entries=self.getTocsys(), callback=self.setTocsy, selected_index=0, do_initial_callback=0) self.tocsyPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW) f0row += 1 label02 = Label(frame0, text='15N HSQC NOESY spectrum') label02.grid(row=f0row, column=0, sticky=Tkinter.NW) self.noesy3dPulldown = PulldownMenu(frame0, entries=self.getNoesy3ds(), callback=self.setNoesy3d, selected_index=0, do_initial_callback=0) self.noesy3dPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW) f0row += 1 texts = ['Setup resonances & peaks', 'Show Peaks', 'Show resonances'] commands = [self.setupResonances, self.showPeaks, self.showResonances] self.setupButtons = ButtonList(frame0, expands=1, texts=texts, commands=commands) self.setupButtons.grid(row=f0row, column=0, columnspan=2, sticky=Tkinter.NSEW) f0row += 1 self.label03a = Label(frame0, text='Resonances found: 0') self.label03a.grid(row=f0row, column=0, sticky=Tkinter.NW) self.label03b = Label(frame0, text='NOESY peaks found: 0') self.label03b.grid(row=f0row, column=1, sticky=Tkinter.NW) row += 1 frame1 = LabelFrame(guiFrame, text='Calculate distance constraints') frame1.grid(row=row, column=0, sticky=Tkinter.NSEW) frame1.grid_columnconfigure(3, weight=1) f1row = 0 frame1.grid_rowconfigure(f1row, weight=1) data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate, self.maxIntens ] colHeadings = [ 'Spectrometer\nfrequency', 'Max\niterations', 'Mixing\ntime (ms)', 'Correl.\ntime (ns)', 'Leak\nrate', 'Max\nintensity' ] editWidgets = [ self.specFreqEntry, self.maxIterEntry, self.mixTimeEntry, self.corrTimeEntry, self.leakRateEntry, self.maxIntensEntry, ] editGetCallbacks = [ self.getSpecFreq, self.getMaxIter, self.getMixTime, self.getCorrTime, self.getLeakRate, self.getMaxIntens, ] editSetCallbacks = [ self.setSpecFreq, self.setMaxIter, self.setMixTime, self.setCorrTime, self.setLeakRate, self.setMaxIntens, ] self.midgeParamsMatrix = ScrolledMatrix( frame1, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, maxRows=1, initialCols=5, headingList=colHeadings, callback=None, objectList=[ 'None', ], textMatrix=[ data, ]) self.midgeParamsMatrix.grid(row=f1row, column=0, columnspan=4, sticky=Tkinter.NSEW) f1row += 1 label10 = Label(frame1, text='Benchmark structure') label10.grid(row=f1row, column=0, sticky=Tkinter.NW) self.structurePulldown = PulldownMenu(frame1, entries=self.getStructures(), callback=self.setStructure, selected_index=0, do_initial_callback=0) self.structurePulldown.grid(row=f1row, column=1, sticky=Tkinter.NW) label11 = Label(frame1, text='ADC atom types:') label11.grid(row=f1row, column=2, sticky=Tkinter.NW) self.adcAtomsPulldown = PulldownMenu(frame1, entries=self.getAdcAtomTypes(), callback=self.setAdcAtomTypes, selected_index=0, do_initial_callback=0) self.adcAtomsPulldown.grid(row=f1row, column=3, sticky=Tkinter.NW) f1row += 1 texts = [ 'Calculate distances', 'Show distance\nconstraints', 'Show anti-distance\nconstraints' ] commands = [ self.calculateDistances, self.showConstraints, self.showAntiConstraints ] self.midgeButtons = ButtonList(frame1, expands=1, texts=texts, commands=commands) self.midgeButtons.grid(row=f1row, column=0, columnspan=4, sticky=Tkinter.NSEW) f1row += 1 self.distConstrLabel = Label(frame1, text='Distance constraints:') self.distConstrLabel.grid(row=f1row, column=0, columnspan=2, sticky=Tkinter.NW) self.antiConstrLabel = Label(frame1, text='Anti-distance constraints:') self.antiConstrLabel.grid(row=f1row, column=2, columnspan=2, sticky=Tkinter.NW) row += 1 guiFrame.grid_rowconfigure(row, weight=1) frame2 = LabelFrame(guiFrame, text='Proton cloud molecular dynamics') frame2.grid(row=row, column=0, sticky=Tkinter.NSEW) frame2.grid_columnconfigure(1, weight=1) f2row = 0 frame2.grid_rowconfigure(f2row, weight=1) data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate ] colHeadings = [ 'Step', 'Initial temp.', 'Final temp.', 'Cooling steps', 'MD steps', 'MD tau', 'Rep. scale' ] editWidgets = [ None, self.mdInitTempEntry, self.mdFinTempEntry, self.mdCoolStepsEntry, self.mdSimStepsEntry, self.mdTauEntry, self.mdRepScaleEntry ] editGetCallbacks = [ None, self.getMdInitTemp, self.getMdFinTemp, self.getMdCoolSteps, self.getMdSimSteps, self.getMdTau, self.getMdRepScale ] editSetCallbacks = [ None, self.setMdInitTemp, self.setMdFinTemp, self.setMdCoolSteps, self.setMdSimSteps, self.setMdTau, self.setMdRepScale ] self.coolingSchemeMatrix = ScrolledMatrix( frame2, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, maxRows=9, initialRows=12, headingList=colHeadings, callback=self.selectCoolingStep, objectList=self.coolingScheme, textMatrix=self.coolingScheme) self.coolingSchemeMatrix.grid(row=f2row, column=0, columnspan=4, sticky=Tkinter.NSEW) f2row += 1 texts = ['Move earlier', 'Move later', 'Add step', 'Remove step'] commands = [ self.moveStepEarlier, self.moveStepLater, self.addCoolingStep, self.removeCoolingStep ] self.coolingSchemeButtons = ButtonList(frame2, expands=1, commands=commands, texts=texts) self.coolingSchemeButtons.grid(row=f2row, column=0, columnspan=4, sticky=Tkinter.EW) f2row += 1 label20 = Label(frame2, text='Number of clouds:') label20.grid(row=f2row, column=0, sticky=Tkinter.NW) self.numCloudsEntry = FloatEntry(frame2, text=100, returnCallback=self.setNumClouds, width=10) self.numCloudsEntry.grid(row=f2row, column=1, sticky=Tkinter.NW) label21 = Label(frame2, text='Cloud file prefix:') label21.grid(row=f2row, column=2, sticky=Tkinter.NW) self.filePrefixEntry = Entry(frame2, text='cloud_', returnCallback=self.setFilePrefix, width=10) self.filePrefixEntry.grid(row=f2row, column=3, sticky=Tkinter.NW) f2row += 1 texts = ['Start molecular dynamics', 'Show dynamics progress'] commands = [self.startMd, self.showMdProgress] self.mdButtons = ButtonList(frame2, expands=1, commands=commands, texts=texts) self.mdButtons.grid(row=f2row, column=0, columnspan=4, sticky=Tkinter.NSEW) row += 1 self.bottomButtons = createDismissHelpButtonList(guiFrame, expands=0, help_url=None) self.bottomButtons.grid(row=row, column=0, sticky=Tkinter.EW) self.setButtonStates() def getStructures(self): names = [ '<None>', ] for molSystem in self.project.sortedMolSystems(): for structure in molSystem.sortedStructureEnsembles(): names.append('%s:%d' % (molSystem.name, structure.ensembleId)) return names def setStructure(self, index, name=None): if index < 1: self.structure = None else: structures = [] for molSystem in self.project.molSystems: for structure in molSystem.structureEnsembles: structures.append(structure) self.structure = structures[index - 1] def getAdcAtomTypes(self): return ['HN', 'HN HA', 'HN HA HB'] def setAdcAtomTypes(self, index, name=None): if name is None: name = self.adcAtomsPulldown.getSelected() self.adcAtomTypes = name def startMd(self): self.setNumClouds() self.setFilePrefix() if (self.distanceConstraintList and self.antiDistConstraintList and (self.numClouds > 0) and self.filePrefix): resDict = {} for resonance in self.guiParent.project.currentNmrProject.resonances: resDict[resonance.serial] = resonance resonances = [] for constraint in self.distanceConstraintList.constraints: for item in constraint.items: for fixedResonance in item.resonances: if resDict.get( fixedResonance.resonanceSerial) is not None: resonances.append( resDict[fixedResonance.resonanceSerial]) resDict[fixedResonance.resonanceSerial] = None startMdProcess(self.numClouds, self.distanceConstraintList, resonances, self.coolingScheme, self.filePrefix) #structGen = self.distanceConstraintList.structureGeneration serials = [] for resonance in resonances: serials.append(resonance.serial) clouds = [] for i in range(self.numClouds): clouds.append('%s%3.3d.pdb' % (self.filePrefix, i)) self.guiParent.application.setValues( self.distanceConstraintList.nmrConstraintStore, 'clouds', values=clouds) self.guiParent.application.setValues( self.distanceConstraintList.nmrConstraintStore, 'cloudsResonances', values=serials) # do better than this check for creation def showMdProgress(self): n = 0 m = self.numClouds for i in range(m): pdbFileName = '%s%3.3d.pdb' % (self.filePrefix, i) if os.path.exists(pdbFileName): n += 1 p = n * 100 / float(m) text = 'Done %d of %d clouds (%1.2f)%%' % (n, m, p) showInfo('MD Progress', text) def setFilePrefix(self, text=None): if not text: text = self.filePrefixEntry.get() if text: self.filePrefix = text def setNumClouds(self, n=None, *event): if not n: n = self.numCloudsEntry.get() if n: self.numClouds = int(n) def calculateDistances(self): # setup normalisation factor intensityMax # self.maxIter # what if failure ? resDict = {} for resonance in self.project.currentNmrProject.resonances: resDict[resonance.serial] = resonance self.resonances = self.origResonances intensityFactors = [1.0 for x in range(len(self.resonances))] # optimiseRelaxation will remove unconstrained resonances self.distanceConstraintList = optimiseRelaxation( self.resonances, self.noesyPeaks, intensityMax=self.maxIntens, intensityFactors=intensityFactors, tmix=self.mixTime, sf=self.specFreq, tcor=self.corrTime, rleak=self.leakRate) constrainSpinSystems(self.distanceConstraintList) # for testing calculate distances from structure overrides any resonances: uses assigned ones #(self.distanceConstraintList, self.resonances) = self.cheatForTesting() #self.antiDistConstraintList = self.distanceConstraintList protonNumbs = {'CH3': 3, 'Haro': 2, 'HN': 1, 'H': 1} PI = 3.1415926535897931 GH = 2.6752e4 HB = 1.05459e-27 CONST = GH * GH * GH * GH * HB * HB tc = 1.0e-9 * self.corrTime wh = 2.0 * PI * self.specFreq * 1.0e6 j0 = CONST * tc j1 = CONST * tc / (1.0 + wh * wh * tc * tc) j2 = CONST * tc / (1.0 + 4.0 * wh * wh * tc * tc) #jself = 6.0*j2 + 3.0*j1 + j0 jcross = 6.0 * j2 - j0 if self.distanceConstraintList: constraintStore = self.distanceConstraintList.nmrConstraintStore dict = { 'HN': ['H'], 'HN HA': ['H', 'HA', 'HA1', 'HA2'], 'HN HA HB': ['H', 'HA', 'HA1', 'HA2', 'HB', 'HB2', 'HB3'] } self.antiDistConstraintList = makeNoeAdcs( self.resonances, self.noesyPeakList.dataSource, constraintStore, allowedAtomTypes=dict[self.adcAtomTypes]) if self.structure: N = len(self.resonances) sigmas = [[] for i in range(N)] for i in range(N): sigmas[i] = [0.0 for j in range(N)] for constraint in self.distanceConstraintList.constraints: resonances = list(constraint, findFirstItem().resonances) ri = resDict[resonances[0].resonanceSerial] rj = resDict[resonances[1].resonanceSerial] i = self.resonances.index(ri) j = self.resonances.index(rj) atomSets1 = list(ri.resonanceSet.atomSets) atomSets2 = list(rj.resonanceSet.atomSets) if atomSets1 == atomSets2: ass = list(atomSets1) atomSets1 = [ ass[0], ] atomSets2 = [ ass[-1], ] distance = getAtomSetsDistance(atomSets1, atomSets2, self.structure) r = distance * 1e-8 nhs = protonNumbs[rj.name] sigma = 0.1 * jcross * nhs / (r**6) sigmas[i][j] = sigma constraint.setDetails('Known Dist: %4.3f' % (distance)) #for constraint in self.antiDistConstraintList.constraints: # atomSets1 = list(resonances[0].resonanceSet.atomSets) # atomSets2 = list(resonances[1].resonanceSet.atomSets) # distance = getAtomSetsDistance(atomSets1, atomSets2, self.structure) # constraint.setDetails('Known Dist: %4.3f' % (distance)) fp = open('sigmas.out', 'w') for i in range(N - 1): for j in range(i + 1, N): if sigmas[i][j] != 0.0: fp.write('%3.1d %3.1d %9.2e\n' % (i, j, sigmas[i][j])) #fp.write('\n') fp.close() self.setButtonStates() def cheatForTesting(self, atomSelection='H'): """ Makes a perfect cloud from a structure. """ project = self.project structure = self.guiParent.argumentServer.getStructure() constraintStore = makeNmrConstraintStore(project) distConstraintList = NmrConstraint.DistanceConstraintList( constraintStore) chain = structure.findFirstCoodChain() structureGeneration.hydrogenResonances = [] molSystem = structure.molSystem atomSets = [] resonances = [] i = 0 for resonance in project.currentNmrProject.resonances: if resonance.isotopeCode == '1H': if resonance.resonanceSet: atomSet = resonance.resonanceSet.findFirstAtomSet() atom = atomSet.findFirstAtom() seqId = atom.residue.seqId if (seqId < 9) or (seqId > 78): continue if atom.residue.chain.molSystem is molSystem: if atomSelection == 'methyl': if len(atomSet.atoms) == 3: if atom.residue.ccpCode not in ('Ala', 'Val', 'Ile', 'Leu', 'Thr', 'Met'): continue elif atom.name != 'H': continue elif atomSelection == 'amide': if atom.name != 'H': continue if atom.name == 'H': resonance.name = 'HN' else: resonance.name = 'H' resonances.append(resonance) atomSets.append(list(resonance.resonanceSet.atomSets)) i += 1 print "Found %d atomSets" % (len(atomSets)) weight = 1 adcWeight = 1 constrDict = {} N = len(atomSets) for i in range(N - 1): atomSets0 = atomSets[i] residue0 = atomSets0[0].findFirstAtom().residue.seqId print "R", residue0 for j in range(i + 1, N): if j == i: continue atomSets1 = atomSets[j] dist = getAtomSetsDistance(atomSets0, atomSets1, structure) if not dist: continue if dist < 5.5: fixedResonance0 = getFixedResonance( constraintStore, resonances[i]) fixedResonance1 = getFixedResonance( constraintStore, resonances[j]) constrDict[i] = 1 constrDict[j] = 1 constraint = NmrConstraint.DistanceConstraint( distConstraintList, weight=weight, targetValue=dist, upperLimit=dist + (dist / 10), lowerLimit=dist - (dist / 10), error=dist / 5) item = NmrConstraint.DistanceConstraintItem( constraint, resonances=[fixedResonance0, fixedResonance1]) elif (atomSets1[0].findFirstAtom().name == 'H') and (atomSets0[0].findFirstAtom().name == 'H') and (dist > 7): #else: fixedResonance0 = getFixedResonance( constraintStore, resonances[i]) fixedResonance1 = getFixedResonance( constraintStore, resonances[j]) constrDict[i] = 1 constrDict[j] = 1 constraint = NmrConstraint.DistanceConstraint( distConstraintList, weight=adcWeight, targetValue=75, upperLimit=175, lowerLimit=5.0, error=94.5) item = NmrConstraint.DistanceConstraintItem( constraint, resonances=[fixedResonance0, fixedResonance1]) return (distConstraintList, resonances) def showConstraints(self): if self.distanceConstraintList: self.guiParent.browseConstraints( constraintList=self.distanceConstraintList) def showAntiConstraints(self): if self.antiDistConstraintList: self.guiParent.browseConstraints( constraintList=self.antiDistConstraintList) def showPeaks(self): self.guiParent.viewPeaks(peaks=self.noesyPeaks) def showResonances(self): pass #self.guiParent.viewResonances(resonances=self.resonances) def setupResonances(self): if self.noesyPeakList and self.noesy3dPeakList and self.tocsyPeakList and self.hsqcPeakList: disambiguateNoesyPeaks(self.noesyPeakList, self.noesy3dPeakList, self.tocsyPeakList, self.hsqcPeakList) (self.origResonances, self.noesyPeaks, null) = getCloudsResonanceList(self.guiParent.argumentServer, hsqcPeakList=self.hsqcPeakList, tocsy3dPeakList=self.tocsyPeakList, noesy2dPeakList=self.noesyPeakList) self.setButtonStates() def setButtonStates(self): if self.origResonances: self.label03a.set('Resonances found: %d' % (len(self.origResonances))) if self.noesyPeaks: self.label03b.set('NOESY peaks found: %d' % (len(self.noesyPeaks))) if self.noesyPeakList and self.tocsyPeakList and self.hsqcPeakList: self.setupButtons.buttons[0].enable() else: self.setupButtons.buttons[0].disable() if self.noesyPeaks: self.setupButtons.buttons[1].enable() else: self.setupButtons.buttons[1].disable() if self.origResonances: self.setupButtons.buttons[2].enable() else: self.setupButtons.buttons[2].disable() if self.noesyPeaks and self.origResonances: self.midgeButtons.buttons[0].enable() else: self.midgeButtons.buttons[0].disable() if self.distanceConstraintList: self.midgeButtons.buttons[1].enable() self.distConstrLabel.set( 'Distance constraints: %d' % len(self.distanceConstraintList.constraints)) else: self.distConstrLabel.set('Distance constraints:') self.midgeButtons.buttons[1].disable() if self.antiDistConstraintList: self.antiConstrLabel.set( 'Anti-distance constraints: %d' % len(self.antiDistConstraintList.constraints)) self.midgeButtons.buttons[2].enable() else: self.antiConstrLabel.set('Anti-distance constraints:') self.midgeButtons.buttons[2].disable() if (self.distanceConstraintList and self.antiDistConstraintList and (self.numClouds > 0) and self.filePrefix): self.mdButtons.buttons[0].enable() self.mdButtons.buttons[1].enable() else: self.mdButtons.buttons[0].disable() self.mdButtons.buttons[1].disable() def getNoesys(self): names = [] spectra = getSpectraByType(self.project, '2dNOESY') for spectrum in spectra: for peakList in spectrum.peakLists: name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.noesyPeakList: self.noesyPeakList = peakList return names def setNoesy(self, index, name=None): if not name: name = self.noesyPulldown.getSelected() self.noesyPeakList = self.peakListDict[name] self.setButtonStates() def getTocsys(self): names = [] spectra = getSpectraByType(self.project, '3dTOCSY') for spectrum in spectra: for peakList in spectrum.peakLists: name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.tocsyPeakList: self.tocsyPeakList = peakList return names def getNoesy3ds(self): names = [] spectra = getSpectraByType(self.project, '3dNOESY') for spectrum in spectra: for peakList in spectrum.peakLists: name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.noesy3dPeakList: self.noesy3dPeakList = peakList return names def setTocsy(self, index, name=None): if not name: name = self.tocsyPulldown.getSelected() self.tocsyPeakList = self.peakListDict[name] self.setButtonStates() def setNoesy3d(self, index, name=None): if not name: name = self.noesy3dPulldown.getSelected() self.noesy3dPeakList = self.peakListDict[name] self.setButtonStates() def getHsqcs(self): names = [] spectra = getSpectraByType(self.project, 'HSQC') for spectrum in spectra: for peakList in spectrum.peakLists: name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.hsqcPeakList: self.hsqcPeakList = peakList return names def setHsqc(self, index, name=None): if not name: name = self.hsqcPulldown.getSelected() self.hsqcPeakList = self.peakListDict[name] self.setButtonStates() def getMdInitTemp(self, coolingStep): self.mdInitTempEntry.set(coolingStep[1]) def getMdFinTemp(self, coolingStep): self.mdFinTempEntry.set(coolingStep[2]) def getMdCoolSteps(self, coolingStep): self.mdCoolStepsEntry.set(coolingStep[3]) def getMdSimSteps(self, coolingStep): self.mdSimStepsEntry.set(coolingStep[4]) def getMdTau(self, coolingStep): self.mdTauEntry.set(coolingStep[5]) def getMdRepScale(self, coolingStep): self.mdRepScaleEntry.set(coolingStep[6]) def setMdInitTemp(self, event): value = self.mdInitTempEntry.get() if value is not None: self.coolingStep[1] = value self.updateCoolingScheme() def setMdFinTemp(self, event): value = self.mdFinTempEntry.get() if value is not None: self.coolingStep[2] = value self.updateCoolingScheme() def setMdCoolSteps(self, event): value = self.mdCoolStepsEntry.get() if value is not None: self.coolingStep[3] = value self.updateCoolingScheme() def setMdSimSteps(self, event): value = self.mdSimStepsEntry.get() if value is not None: self.coolingStep[4] = value self.updateCoolingScheme() def setMdTau(self, event): value = self.mdTauEntry.get() if value is not None: self.coolingStep[5] = value self.updateCoolingScheme() def setMdRepScale(self, event): value = self.mdRepScaleEntry.get() if value is not None: self.coolingStep[6] = value self.updateCoolingScheme() def selectCoolingStep(self, object, row, col): self.coolingStep = object def moveStepEarlier(self): if self.coolingStep: i = self.coolingStep[0] - 1 if i > 0: coolingStep = self.coolingScheme[i - 1] coolingStep[0] = i + 1 self.coolingStep[0] = i self.coolingScheme[i - 1] = self.coolingStep self.coolingScheme[i] = coolingStep self.updateCoolingScheme() self.coolingSchemeMatrix.hilightObject(self.coolingStep) def moveStepLater(self): if self.coolingStep: i = self.coolingStep[0] - 1 if i < len(self.coolingScheme) - 1: coolingStep = self.coolingScheme[i + 1] coolingStep[0] = i + 1 self.coolingStep[0] = i + 2 self.coolingScheme[i + 1] = self.coolingStep self.coolingScheme[i] = coolingStep self.updateCoolingScheme() self.coolingSchemeMatrix.hilightObject(self.coolingStep) def addCoolingStep(self): i = len(self.coolingScheme) + 1 datum = [i, 3000, 100, 10, 2500, 0.001, 1] self.coolingScheme.append(datum) self.updateCoolingScheme() def removeCoolingStep(self): if self.coolingStep: coolingScheme = [] i = 0 for coolingStep in self.coolingScheme: if coolingStep is not self.coolingStep: i += 1 coolingStep[0] = i coolingScheme.append(coolingStep) self.coolingScheme = coolingScheme self.updateCoolingScheme() def updateCoolingScheme(self): objectList = self.coolingScheme textMatrix = self.coolingScheme self.coolingSchemeMatrix.update(objectList=objectList, textMatrix=textMatrix) def updateMidgeParams(self): data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate, self.maxIntens ] self.midgeParamsMatrix.update(textMatrix=[ data, ]) def getSpecFreq(self, obj): self.specFreqEntry.set(self.specFreq) def getMaxIter(self, obj): self.maxIterEntry.set(self.maxIter) def getMixTime(self, obj): self.mixTimeEntry.set(self.mixTime) def getCorrTime(self, obj): self.corrTimeEntry.set(self.corrTime) def getLeakRate(self, obj): self.leakRateEntry.set(self.leakRate) def getMaxIntens(self, obj): self.maxIntensEntry.set(self.maxIntens) def setSpecFreq(self, event): value = self.specFreqEntry.get() if value is not None: self.specFreq = value self.updateMidgeParams() def setMaxIter(self, event): value = self.maxIterEntry.get() if value is not None: self.maxIter = value self.updateMidgeParams() def setMixTime(self, event): value = self.mixTimeEntry.get() if value is not None: self.mixTime = value self.updateMidgeParams() def setCorrTime(self, event): value = self.corrTimeEntry.get() if value is not None: self.corrTime = value self.updateMidgeParams() def setLeakRate(self, event): value = self.leakRateEntry.get() if value is not None: self.leakRate = value self.updateMidgeParams() def setMaxIntens(self, event): value = self.maxIntensEntry.get() if value is not None: self.maxIntens = value self.updateMidgeParams() def destroy(self): BasePopup.destroy(self)
class BrowseStrucGenPopup(BasePopup): def __init__(self, parent, *args, **kw): self.guiParent = parent self.strucGen = None self.violList = None self.constrList = None self.waiting = 0 BasePopup.__init__(self, parent=parent, title="Structure Generation Runs", **kw) #self.geometry("+150+150") def body(self, guiFrame): guiFrame.grid_columnconfigure(0, weight=1) row = 0 strucGenFrame = LabelFrame(guiFrame, text='Generation Runs') strucGenFrame.grid(row=row, column=0, columnspan=1, sticky='nsew') strucGenFrame.grid_columnconfigure(0, weight=1) strucGenFrame.grid_rowconfigure(0, weight=1) guiFrame.grid_rowconfigure(row, weight=0) #self.editDetailsEntry = Entry(self,text='',returnCallback = self.setDetails, width=12) #editWidgets = [None, None, None, None, None, self.editDetailsEntry] #editGetCallbacks = [None, None, None, None, None, self.getDetails] #editSetCallbacks = [None, None, None, None, None, self.setDetails] colHeadings = [ '#', 'Constraint\nLists', 'Violation\nLists', 'Structures', 'Fixed\nAtom Sets', 'Fixes\nResonance Sets', 'Chain\nStates', 'Database\nEntries', 'Resonance\nClouds' ] editWidgets = [None, None, None, None, None, None, None, None, None] editGetCallbacks = [ None, None, None, None, None, None, None, None, None ] editSetCallbacks = [ None, None, None, None, None, None, None, None, None ] self.structGenMatrix = ScrolledMatrix( strucGenFrame, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, initialRows=3, initialCols=6, headingList=colHeadings, callback=self.selectStructGenCell, objectList=[], textMatrix=[ [], ]) self.structGenMatrix.grid(row=0, column=0, sticky='nsew') texts = ['View Structures', 'Delete'] commands = [self.viewStructures, self.deleteStrucGen] self.structGenButtons = ButtonList(strucGenFrame, texts=texts, expands=True, commands=commands) self.structGenButtons.grid(row=1, column=0, sticky='ew') row += 1 constrFrame = LabelFrame(guiFrame, text='Constraint Lists') constrFrame.grid(row=row, column=0, columnspan=1, sticky='nsew') constrFrame.grid_columnconfigure(0, weight=1) constrFrame.grid_rowconfigure(0, weight=1) guiFrame.grid_rowconfigure(row, weight=1) colHeadings = [ '#', 'Type', 'Name', 'Constraints', 'Experiments', 'Details', 'Unit' ] editWidgets = [None, None, None, None, None, None, None] editGetCallbacks = [None, None, None, None, None, None, None] editSetCallbacks = [None, None, None, None, None, None, None] self.constrListMatrix = ScrolledMatrix( constrFrame, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, initialRows=10, headingList=colHeadings, callback=self.selectConstrListCell, objectList=[], textMatrix=[ [], ]) self.constrListMatrix.grid(row=0, column=0, sticky='nsew') texts = ['View Constraints', 'Create List', 'Delete List'] commands = [ self.viewConstraints, self.createConstraints, self.deleteConstraints ] self.constrListButtons = ButtonList(constrFrame, texts=texts, expands=True, commands=commands) self.constrListButtons.grid(row=1, column=0, sticky='ew') self.constrListButtons.buttons[1].disable() row += 1 violFrame = LabelFrame(guiFrame, text='Violation Lists') violFrame.grid(row=row, column=0, columnspan=1, sticky='nsew') violFrame.grid_columnconfigure(0, weight=1) violFrame.grid_rowconfigure(0, weight=1) guiFrame.grid_rowconfigure(row, weight=1) colHeadings = [ '#', 'Violations', 'Structures', 'Details', ] editWidgets = [None, None, None, None] editGetCallbacks = [None, None, None, None] editSetCallbacks = [None, None, None, None] self.violListMatrix = ScrolledMatrix(violFrame, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, initialRows=10, headingList=colHeadings, callback=self.selectViolListCell, objectList=[], textMatrix=[ [], ]) self.violListMatrix.grid(row=0, column=0, sticky='nsew') texts = ['View Violations', 'Delete List'] commands = [self.viewViolations, self.deleteViolations] self.violListButtons = ButtonList(violFrame, texts=texts, expands=True, commands=commands) self.violListButtons.grid(row=1, column=0, sticky='ew') row += 1 self.bottomButtons = UtilityButtonList(guiFrame, helpUrl=self.help_url) self.bottomButtons.grid(row=row, column=0, columnspan=1, sticky='ew') self.update() for func in ('__init__', 'delete', 'setName', 'setDetails', 'setUnit', 'setExperiments', 'addExperiment', 'removeExperiment'): for clazz in ('ccp.nmr.Nmr.ChemShiftConstraintList', 'ccp.nmr.Nmr.DihedralConstraintList', 'ccp.nmr.Nmr.DistanceConstraintList', 'ccp.nmr.Nmr.HBondConstraintList', 'ccp.nmr.Nmr.JCouplingConstraintList', 'ccp.nmr.Nmr.RdcConstraintList'): self.registerNotify(self.updateAfter, clazz, func) for func in ( '__init__', 'delete', ): for clazz in ('ccp.nmr.Nmr.ChemShiftConstraint', 'ccp.nmr.Nmr.DihedralConstraint', 'ccp.nmr.Nmr.DistanceConstraint', 'ccp.nmr.Nmr.HBondConstraint', 'ccp.nmr.Nmr.JCouplingConstraint', 'ccp.nmr.Nmr.RdcConstraint'): self.registerNotify(self.updateAfter, clazz, func) for func in ('__init__', 'delete', 'setChainStates', 'addChainState', 'removeChainState', 'addEntry', 'removeEntry', 'setResStructures', 'addResStructure', 'setEntries', 'removeResStructure', 'setStructures', 'addStructure', 'removeStructure'): self.registerNotify(self.updateAfter, 'ccp.nmr.Nmr.StructureGeneration', func) for func in ('__init__', 'delete', 'setDetails'): for clazz in ('ccp.nmr.Nmr.ViolationList', ): self.registerNotify(self.updateAfter, clazz, func) for func in ( '__init__', 'delete', ): for clazz in ('ccp.nmr.Nmr.Violation', ): self.registerNotify(self.updateAfter, clazz, func) def open(self): self.updateAfter() BasePopup.open(self) def deleteViolations(self): if self.violList and showOkCancel( 'Confirm', 'Really delete violation list?', parent=self): self.violList.delete() self.violList = None self.violListButtons.buttons[0].disable() self.violListButtons.buttons[1].disable() def deleteConstraints(self): if self.constrList and showOkCancel( 'Confirm', 'Really delete constraint list?', parent=self): self.constrList.delete() self.constrList = None self.constrListButtons.buttons[0].disable() self.constrListButtons.buttons[2].disable() def createConstraints(self): pass def viewViolations(self): self.guiParent.browseViolations() popup = self.guiParent.popups['browse_violations'] popup.structGen = self.strucGen popup.violList = self.violList popup.updateAfter() def viewConstraints(self): self.guiParent.browseConstraints() popup = self.guiParent.popups['browse_constraints'] popup.structGen = self.strucGen popup.constrList = self.constrList popup.updateAfter() def viewStructures(self): self.guiParent.editStructures() popup = self.guiParent.popups['edit_structures'] popup.structGen = self.strucGen popup.updateAfter() def deleteStrucGen(self): if self.strucGen and showOkCancel( 'Confirm', 'Really delete structure generation run?', parent=self): self.strucGen.delete() self.strucGen = None self.constrList = None self.violist = None self.structGenButtons.buttons[0].disable() self.structGenButtons.buttons[1].disable() def selectStructGenCell(self, strucGen, row, col): self.strucGen = strucGen if strucGen: self.structGenButtons.buttons[1].enable() if len(strucGen.molStructures) > 0: self.structGenButtons.buttons[0].enable() if self.constrList and (self.constrList.structureGeneration is not self.strucGen): self.constrList = None self.updateConstrLists(self.strucGen) def selectConstrListCell(self, constrList, row, col): self.constrList = constrList if constrList: self.constrListButtons.buttons[0].enable() self.constrListButtons.buttons[2].enable() def selectViolListCell(self, violList, row, col): self.violList = violList if violList: self.violListButtons.buttons[0].enable() self.violListButtons.buttons[1].enable() def updateAfter(self, object=None): if self.waiting: return strucGen = None name = object.className if name == 'StructureGeneration': self.waiting = True self.after_idle(self.update) return elif name == 'ViolationList': strucGen = object.structureGeneration elif name == 'Violation': strucGen = object.violationList.structureGeneration elif name[-14:] == 'ConstraintList': strucGen = object.structureGeneration elif name[-10:] == 'Constraint': strucGen = object.parentList.structureGeneration if (object is None) or (strucGen is self.strucGen): self.waiting = True self.after_idle(self.update) def destroy(self): for func in ('__init__', 'delete', 'setName', 'setDetails', 'setUnit', 'setExperiments', 'addExperiment', 'removeExperiment'): for clazz in ('ccp.nmr.Nmr.ChemShiftConstraintList', 'ccp.nmr.Nmr.DihedralConstraintList', 'ccp.nmr.Nmr.DistanceConstraintList', 'ccp.nmr.Nmr.HBondConstraintList', 'ccp.nmr.Nmr.JCouplingConstraintList', 'ccp.nmr.Nmr.RdcConstraintList'): self.unregisterNotify(self.updateAfter, clazz, func) for func in ( '__init__', 'delete', ): for clazz in ('ccp.nmr.Nmr.ChemShiftConstraint', 'ccp.nmr.Nmr.DihedralConstraint', 'ccp.nmr.Nmr.DistanceConstraint', 'ccp.nmr.Nmr.HBondConstraint', 'ccp.nmr.Nmr.JCouplingConstraint', 'ccp.nmr.Nmr.RdcConstraint'): self.unregisterNotify(self.updateAfter, clazz, func) for func in ('__init__', 'delete', 'setChainStates', 'addChainState', 'removeChainState', 'addEntry', 'removeEntry', 'setResStructures', 'addResStructure', 'setEntries', 'removeResStructure', 'setStructures', 'addStructure', 'removeStructure'): self.unregisterNotify(self.updateAfter, 'ccp.nmr.Nmr.StructureGeneration', func) for func in ('__init__', 'delete', 'setDetails'): for clazz in ('ccp.nmr.Nmr.ViolationList', ): self.unregisterNotify(self.updateAfter, clazz, func) for func in ( '__init__', 'delete', ): for clazz in ('ccp.nmr.Nmr.Violation', ): self.unregisterNotify(self.updateAfter, clazz, func) BasePopup.destroy(self) def updateConstrLists(self, *opt): strucGen = self.strucGen objectList = [] textMatrix = [] if strucGen: for constraintList in strucGen.constraintLists: objectList.append(constraintList) else: textMatrix.append([]) for constrList in objectList: datum = [] expText = '' for e in constrList.experiments: if expText: expText += ' ' expText += e.name datum.append(constrList.serial) datum.append(constrList.className[0:-14]) datum.append(constrList.name) datum.append(len(constrList.constraints)) datum.append(expText) datum.append(constrList.details) datum.append(constrList.unit) textMatrix.append(datum) if self.constrList: self.constrListButtons.buttons[0].enable() self.constrListButtons.buttons[2].enable() else: self.constrListButtons.buttons[0].disable() self.constrListButtons.buttons[2].disable() self.constrListMatrix.update(objectList=objectList, textMatrix=textMatrix) def updateViolLists(self, *opt): strucGen = self.strucGen objectList = [] textMatrix = [] if strucGen: for violationList in strucGen.violationLists: objectList.append(violationList) else: textMatrix.append([]) for violationList in objectList: datum = [] datum.append(violationList.serial) datum.append(len(violationList.violations)) datum.append(len(violationList.molStructures)) datum.append(violationList.details) textMatrix.append(datum) if self.violList: self.violListButtons.buttons[0].enable() self.violListButtons.buttons[1].enable() else: self.violListButtons.buttons[0].disable() self.violListButtons.buttons[1].disable() self.violListMatrix.update(objectList=objectList, textMatrix=textMatrix) def update(self): objectList = [] textMatrix = [] project = self.project for strucGen in self.nmrProject.structureGenerations: objectList.append(strucGen) if not objectList: textMatrix.append([]) for strucGen in objectList: datum = [] datum.append(strucGen.serial) datum.append(len(strucGen.constraintLists)) datum.append(len(strucGen.violationLists)) datum.append(len(strucGen.molStructures)) datum.append(len(strucGen.fixedAtomSets)) datum.append(len(strucGen.fixedResonanceSets)) datum.append(len(strucGen.chainStates)) datum.append(len(strucGen.entries)) datum.append(len(strucGen.resStructures)) textMatrix.append(datum) if not self.strucGen: self.structGenButtons.buttons[0].disable() self.structGenButtons.buttons[1].disable() self.structGenMatrix.update(objectList=objectList, textMatrix=textMatrix) self.updateConstrLists() self.updateViolLists() self.waiting = False
class BrowsePeakGroupsPopup(BasePopup): """ **Display Groups of Peaks Linked by a Root Assignment** This popup window is used to display the results of operations in Analysis that generate grouped peaks, usually linked by virtue of a common 'root' assignment. For example a selected set of peaks may be macthed to other peaks with similar positions in a spectrum dimension, where each group corresponds to a separate C-H or N-H position. For example the right-click window menu option "Locate Peaks::Match multiple peaks" generates such groupings to find rows or columns of peaks that share chemical shifts. Whatever operation generated the groups, they are listed in ranked order in the table; best scoring at the top. The number of peaks in the group and any common assigment and position is also listed. The idea is that the groups are candidates for some searh or macthing process that the user triggered. The best scoring groups may be used to control the spectrum window display, thus displaying any peak matches, by using [Display Groups in Strips] after selecting an approprate window. This system is often used for NOESY experiments where resonances that are close in space share common sets of peak positions; they are close to the same set of other resonances. """ def __init__(self, parent, *args, **kw): self.groups = [] self.variableDim = 1 self.windowPane = None self.rulers = [] self.peakLists = [] self.orthogonalDict = {} self.parent = parent self.searchPeaks = [] BasePopup.__init__(self, parent, title= "Peak Groups", borderwidth=5, **kw) 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) def open(self): self.update() BasePopup.open(self) def updateWindowsAfter(self, opt=None): self.after_idle(self.updateWindows) def updateWindows(self): if not self.groups: self.windowPulldown.clear() return selected = self.windowPulldown.getText() groups = self.scrolledMatrix.currentObjects or self.groups self.orthogonalDict = {} windowPane = self.windowPane if windowPane and groups: meanVarPos = 0.0 for peak in groups[0][2]: meanVarPos += peak.sortedPeakDims()[self.variableDim].value meanVarPos /= float(len(groups[0][2])) xyz = [] for score, coords0, peaks in groups: peak = peaks[0] peakDims = peak.sortedPeakDims() dimMapping = getPeakDimAxisMapping(peak, self.windowPane) coords = list(coords0) coords.insert(self.variableDim, meanVarPos) posDict = {} for i, peakDim in enumerate(peakDims): posDict[peakDim] = coords[i] pos = [] for axisPanel in windowPane.sortedAxisPanels(): peakDim = dimMapping[axisPanel.label] pos.append( posDict[peakDim] ) xyz.append(pos) windowZPlanes = findOrthogonalWindows(windowPane, xyz, excludeQuery=False) for windowPosition in windowZPlanes: if windowPosition: key, pane, xyz = windowPosition self.orthogonalDict[key] = (pane, xyz) xyPlaneKeys = self.orthogonalDict.keys() xyPlaneKeys.sort() if xyPlaneKeys: index = min(self.windowPulldown.index, len(xyPlaneKeys)-1) if selected in xyPlaneKeys: index = xyPlaneKeys.index(selected) self.windowPulldown.setup(xyPlaneKeys, xyPlaneKeys, index) def removeGroups(self): groups = self.scrolledMatrix.currentObjects if groups: newGroups = [] for group in self.groups: if group not in groups: newGroups.append(group) self.update(groups=newGroups) def stripGroups(self): self.updateWindows() name = self.windowPulldown.getText() groups = self.scrolledMatrix.currentObjects if groups and name and (name != '<None>'): selected = self.windowPulldown.getText() windowPane, positions = self.orthogonalDict[selected] window = windowPane.spectrumWindow N = len(positions) msg = '%d positions selected. Really make %d strips in window %s' if N > 10 and not showOkCancel('Warning', msg % (N,N,window.name ), parent=self): return displayStrips(self.parent, positions, orthoPositions=None, spectrum=None, windowPane=windowPane) # often fails first time... self.update_idletasks() displayStrips(self.parent, positions, orthoPositions=None, spectrum=None, windowPane=windowPane) def removeRulers(self): for ruler in self.rulers: if not ruler.isDeleted: ruler.delete() self.rulers = [] def addRulers(self): groups = self.scrolledMatrix.currentObjects if groups and self.windowPane: positions = [] panelTypes = [] for peak in self.searchPeaks: peakDim = peak.sortedPeakDims()[self.variableDim] dimMapping = getPeakDimAxisMapping(peak, self.windowPane) for axisPanel in self.windowPane.axisPanels: if dimMapping[axisPanel.label] is peakDim: positions.append(peakDim.value) panelTypes.append(axisPanel.panelType) break color = '#808080' for i in range(len(positions)): ruler = createRuler(positions[i], panelTypes[i], dashLength=3, gapLength=1, color=color, remove=False) self.rulers.append(ruler) def update(self, groups=None, variableDim=None, peakLists=None, searchPeaks=None): self.removeRulers() if groups is not None: self.groups = groups if variableDim is not None: self.variableDim = variableDim if peakLists: self.peakLists = peakLists spectrum = self.peakLists[0].dataSource for spectrumWindow in self.analysisProject.spectrumWindows: for windowPane in spectrumWindow.spectrumWindowPanes: if isSpectrumInWindowPane(windowPane, spectrum): if len(windowPane.axisPanels) == len(spectrum.dataDims): self.windowPane = windowPane break self.searchPeaks = searchPeaks or [] objectList = [] textMatrix = [] for i, group in enumerate(self.groups): (score,positions,peaks) = group datum = ['%d' % (i+1), '%f' % score, '%d' % len(peaks)] annotations = [] for j in range(len(peaks[0].peakDims)): if j != self.variableDim: annotation = '' for peak in peaks: peakDims = peak.sortedPeakDims() peakDim = peakDims[j] if peakDim.annotation: if annotation and (annotation != peakDim.annotation): annotation = '*' else: annotation = peakDim.annotation annotations.append(annotation) datum.append(' '.join(annotations)) for position in positions: datum.append('%f' % position) objectList.append(group) textMatrix.append(datum) headingList, tipTexts = self.getHeadingList() self.scrolledMatrix.update(textMatrix=textMatrix, objectList=objectList, headingList=headingList, tipTexts=tipTexts) self.updateWindows() def getHeadingList(self): tipTexts = ['The ranking of the peak group, comparing its score with others', 'The match score of the peak group', 'Number of peaks within the matched peak group', 'The root (usually amide) assignment, common to peaks in a group'] headingList = ['Rank','Score','Num\npeaks','Root\nAssignment'] if self.groups: n = len( self.groups[0][2][0].peakDims ) for i in range(n): if i != self.variableDim: headingList.append( 'F%d position' % (i+1) ) tipTexts.append('Average location of the group in the F%d dimension' % (i+1)) else: headingList.extend(['F1 position','F2 position']) tipTexts.append('Average location of the group in the F1 dimension') tipTexts.append('Average location of the group in the F2 dimension') return headingList, tipTexts def destroy(self): for func in ('__init__', 'delete', 'setName'): self.unregisterNotify(self.updateWindowsAfter, 'ccpnmr.Analysis.SpectrumWindow', func) BasePopup.destroy(self)
def __init__(self, parent, objects=None, attributes=None, attributeHeadings=None, attributeLabel='Attribute', widgetClasses=None, constructorArg=None, constructorKw=None, tableHeading='Dimension', tableHeadingOffset=1, callback=None, attributeDirection=Tkinter.VERTICAL, includeResetUpdate=True, help_msg='', help_url='', *args, **kw): if (objects is None): objects = [] if (attributes is None): attributes = [] if (attributeHeadings is None): attributeHeadings = {} if (widgetClasses is None): widgetClasses = {} if (constructorArg is None): constructorArg = {} if (constructorKw is None): constructorKw = {} apply(Frame.__init__, (self, parent) + args, kw) self.ndim = len(objects) self.objects = objects self.attributes = attributes self.callback = callback topFrame = Frame(self) topFrame.grid(row=0, column=0, sticky=Tkinter.NSEW) bottomFrame = Frame(self) bottomFrame.grid(row=1, column=0, sticky=Tkinter.NSEW) if (attributeLabel): label = Label(topFrame, text=attributeLabel, relief=Tkinter.GROOVE) label.grid(row=0, column=0, sticky=Tkinter.EW) n = 0 for i in range(self.ndim): text = tableHeading + ' ' + str(i + tableHeadingOffset) label = Label(topFrame, text=text, relief=Tkinter.GROOVE) if (attributeDirection == Tkinter.VERTICAL): r = n c = i + 1 else: r = i + 1 c = n label.grid(row=r, column=c, sticky=Tkinter.EW) self.widgets = {} for attr in self.attributes: n = n + 1 text = attributeHeadings.get(attr, attr) label = Label(topFrame, text=text, relief=Tkinter.GROOVE) if (attributeDirection == Tkinter.VERTICAL): r = n c = 0 else: r = 0 c = n label.grid(row=r, column=c, sticky=Tkinter.EW) self.widgets[attr] = self.ndim * [0] for i in range(self.ndim): arg = constructorArg.get(attr, ()) kw = constructorKw.get(attr, {}) self.widgets[attr][i] = widgetClasses[attr](topFrame, *arg, **kw) if (attributeDirection == Tkinter.VERTICAL): r = n c = i + 1 else: r = i + 1 c = n self.widgets[attr][i].grid(row=r, column=c, sticky=Tkinter.EW) texts = [] commands = [] if (includeResetUpdate): texts.extend(['Reset', 'Update']) commands.extend([self.reset, self.update]) if (help_url or help_msg): import memops.gui.HelpPopup if (help_url): help_cmd = lambda top=self.parent.top, url=help_url: memops.gui.HelpPopup.showHelpUrl( top, url) else: help_cmd = lambda top=self.parent.top, message=help_msg: memops.gui.HelpPopup.showHelpText( top, message) texts.append('Help') commands.append(help_cmd) if (texts): buttons = ButtonList(bottomFrame, texts=texts, commands=commands) buttons.grid(row=0, column=0, sticky=Tkinter.EW) self.reset()
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
class CingFrame(NmrCalcRunFrame): def __init__(self, parent, application, *args, **kw): project = application.project self.nmrProject = nmrProject = application.nmrProject if project: calcStore = project.findFirstNmrCalcStore(name=APP_NAME, nmrProject=nmrProject) or \ project.newNmrCalcStore(name=APP_NAME, nmrProject=nmrProject) else: calcStore = None self.application = application self.residue = None self.structure = None self.serverCredentials = None self.iCingBaseUrl = DEFAULT_URL self.resultsUrl = None self.chain = None self.serverDone = False NmrCalcRunFrame.__init__(self, parent, project, calcStore, *args, **kw) # # # # # # New Structure Frame # # # # # self.structureTable.grid_forget() self.structureButtons.grid_forget() self.ensemblePulldown.grid_forget() self.modelButtons.grid_forget() self.modelPulldown.grid_forget() frame = self.inputTabs.frames[0] frame.grid_rowconfigure(0, weight=0) frame.grid_rowconfigure(1, weight=1) label = Label(frame, text='Ensemble: ', grid=(0, 0)) self.structurePulldown = PulldownList( frame, callback=self.changeStructure, grid=(0, 1), tipText='The structure ensemble coordinates to submit') tipTexts = [ 'Conformational model number', 'Whether analyse this model' ] headingList = ['Model', 'Use'] editWidgets = [None, None] editGetCallbacks = [None, self.toggleModel] editSetCallbacks = [ None, None, ] self.modelTable = ScrolledMatrix(frame, grid=(1, 0), gridSpan=(1, 2), callback=self.selectStructModel, multiSelect=True, tipTexts=tipTexts, editWidgets=editWidgets, initialRows=2, editGetCallbacks=editGetCallbacks, editSetCallbacks=editSetCallbacks, headingList=headingList) tipTexts = [ 'Activate the selected models so that they will be consedered in the analysis', 'Deactivate the selected models so that they will not be considered in the analysis' ] texts = ['Activate Selected', 'Inactivate Selected'] commands = [self.activateModels, self.disableModels] buttons = ButtonList(frame, texts=texts, commands=commands, grid=(2, 0), gridSpan=(1, 2), tipTexts=tipTexts) # # # # # # 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)) self.iCingBaseUrlPulldown = PulldownList( frame, texts=URLS, objects=URLS, index=0, grid=(srow, 1), tipText='Web location of iCING server to use') srow += 1 label = Label(frame, text='Results File:', grid=(srow, 0)) self.resultFileEntry = Entry( frame, bd=1, text='', grid=(srow, 1), width=50, tipText='Name of file to store compressed CING results in') self.setZipFileName() button = Button(frame, text='Choose File', bd=1, sticky='ew', command=self.chooseZipFile, grid=(srow, 2), tipText='Select file to overwrite with CING results') srow += 1 label = Label(frame, text='Results URL:', grid=(srow, 0)) self.resultUrlEntry = Entry( frame, bd=1, text='', grid=(srow, 1), width=50, tipText='Web location where CING results will be posted') button = Button(frame, text='View Results HTML', bd=1, sticky='ew', command=self.viewHtmlResults, grid=(srow, 2), tipText='Open the HTML CING results in a web browser') srow += 1 tipTexts = [ 'Submit the CCPN project to the CING server', 'Determin whether the iCING job is complete, pending or has failed', 'Remove all trace of the last submissionfrom the iCING server', 'Download the compressed CING results, including HTML' ] 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), tipTexts=tipTexts) 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, tipText='Select the molecular system chain to consider') self.chainPulldown.grid(row=0, column=1, sticky='w') headingList = ['#', 'Residue', 'Linking', 'Decriptor', 'Use?'] tipTexts = [ 'Sequence number', 'Residue type code', 'In-chain connectivity of residue', 'Protonation and steriochemical state', 'Whether to consider the residue in the analysis' ] 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, tipTexts=tipTexts, editWidgets=editWidgets, editGetCallbacks=editGetCallbacks, editSetCallbacks=editSetCallbacks, callback=self.selectResidue) self.residueMatrix.grid(row=1, column=0, columnspan=2, sticky='nsew') tipTexts = [ 'Use the selected residues in the analysis', 'Do not use the selected residues in the analysis' ] texts = ['Activate Selected', 'Inactivate Selected'] commands = [self.activateResidues, self.deactivateResidues] self.resButtons = ButtonList(frame, texts=texts, commands=commands, tipTexts=tipTexts) 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(calcStore) 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/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 structureData = self.getStructureData() if not structureData: msg = 'No structure ensemble selected' showWarning('Failure', msg, parent=self) return if not structureData.models: msg = 'No structural models selected from ensemble' showWarning('Failure', msg, parent=self) return residueData = self.getResidueData() if not (residueData and residueData.residues): 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.run.status = 'pending' 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.run.status = 'failed' 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 self.run.status = 'failed' return result = status.get(iCingRobot.RESPONSE_RESULT) if result == iCingRobot.RESPONSE_DONE: self.serverDone = True self.run.status = 'completed' 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): if self.project: zipFile = '%s_CING_report.zip' % self.project.name self.resultFileEntry.set(zipFile) else: self.resultFileEntry.set('CING_report.zip') def selectStructModel(self, model, row, col): self.model = model def selectResidue(self, residue, row, col): self.residue = residue def getResidueData(self): chain = self.chain.chain chainCode = chain.code msCode = chain.molSystem.code dataObj = self.run.findFirstData(className=RESIDUE_DATA, ioRole='input', molSystemCode=msCode, chainCode=chainCode, name=APP_NAME) if not dataObj: dataObj = self.run.newMolResidueData(molSystemCode=msCode, chainCode=chainCode, ioRole='input', name=APP_NAME) # if not dataObj.residueSeqIds: seqIds = [r.seqId for r in self.chain.sortedResidues()] dataObj.residueSeqIds = seqIds return dataObj def getStructureData(self): eId = self.structure.ensembleId msCode = self.structure.molSystem.code dataObj = self.run.findFirstData(className=STRUCTURE_DATA, molSystemCode=msCode, ensembleId=eId, ioRole='input', name=APP_NAME) if not dataObj: dataObj = self.run.newStructureEnsembleData(ioRole='input', molSystemCode=msCode, ensembleId=eId, name=APP_NAME) # if not dataObj.modelSerials: serials = [m.serial for m in self.structure.sortedModels()] dataObj.modelSerials = serials for dataObjB in self.run.findAllData(className=STRUCTURE_DATA, name=APP_NAME, ioRole='input'): if dataObjB is not dataObj: dataObjB.delete() return dataObj def deactivateResidues(self): if self.run and self.chain: dataObj = self.getResidueData() seqIds = set(dataObj.residueSeqIds) for residue in self.residueMatrix.currentObjects: seqId = residue.seqId if seqId in seqIds: seqIds.remove(seqId) seqIds = list(seqIds) seqIds.sort() dataObj.residueSeqIds = seqIds self.updateResidues() def activateResidues(self): if self.run and self.chain: for residue in self.residueMatrix.currentObjects: dataObj = self.getResidueData() seqIds = set(dataObj.residueSeqIds) for residue in self.residueMatrix.currentObjects: seqId = residue.seqId if seqId not in seqIds: seqIds.add(seqId) seqIds = list(seqIds) seqIds.sort() dataObj.residueSeqIds = seqIds self.updateResidues() def activateModels(self): if self.run and self.structure: dataObj = self.getStructureData() serials = set(dataObj.modelSerials) for model in self.modelTable.currentObjects: serial = model.serial if serial not in serials: serials.add(serial) serials = list(serials) serials.sort() dataObj.modelSerials = serials self.updateModels() def disableModels(self): if self.run and self.structure: dataObj = self.getStructureData() serials = set(dataObj.modelSerials) for model in self.modelTable.currentObjects: serial = model.serial if serial in serials: serials.remove(serial) serials = list(serials) serials.sort() dataObj.modelSerials = serials self.updateModels() def toggleModel(self, *opt): if self.model and self.run and self.structure: dataObj = self.getStructureData() serials = set(dataObj.modelSerials) serial = self.model.serial if serial in serials: serials.remove(serial) else: serials.add(serial) serials = list(serials) serials.sort() dataObj.modelSerials = serials self.updateModels() def toggleResidue(self, *opt): if self.residue and self.run: dataObj = self.getResidueData() seqIds = set(dataObj.residueSeqIds) seqId = self.residue.seqId if seqId in seqIds: seqIds.remove(seqId) else: seqIds.add(seqId) seqIds = list(seqIds) seqIds.sort() dataObj.residueSeqIds = seqIds 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: resDataObj = self.getResidueData() selectedRes = set(resDataObj.residues) chainCode = self.chain.code for residue in self.chain.sortedResidues(): msResidue = residue.residue if msResidue in selectedRes: 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: structures0 = [(s.ensembleId, s) for s in self.project.structureEnsembles] structures0.sort() for eId, structure0 in structures0: name = '%s:%s' % (structure0.molSystem.code, eId) structures.append(structure0) names.append(name) if structures: if structure not in structures: structure = structures[-1] index = structures.index(structure) if self.structure is not structure: self.changeStructure(structure) self.structurePulldown.setup(names, structures, index) def updateModels(self, obj=None): textMatrix = [] objectList = [] colorMatrix = [] if self.structure and self.run: strucDataObj = self.getStructureData() selectedSerials = set(strucDataObj.modelSerials) for model in self.structure.sortedModels(): if model.serial in selectedSerials: 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: dataObj = self.getStructureData() serials = set(dataObj.modelSerials) serials2 = set([m.serial for m in structure.models]) serials = list(serials & serials2) serials.sort() dataObj.modelSerials = serials dataObj.ensembleId = structure.ensembleId dataObj.molSystemCode = structure.molSystem.code # Could clean up residue data if required # prob OK to have haning around in case structure # changes back #for dataObj in self.run.findAllData(className=RESIDUE_DATA, # ioRole='input', # molSystemCode=msCode, # name=APP_NAME) # dataObj.delete() 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 = nmrProject = project.currentNmrProject calcStore = project.findFirstNmrCalcStore(name='CING', nmrProject=nmrProject) or \ project.newNmrCalcStore(name='CING', nmrProject=nmrProject) else: calcStore = 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(calcStore) def update(self, calcStore=None): NmrCalcRunFrame.update(self, calcStore) run = self.run urls = URLS index = 0 if run: userId = getRunTextParameter(run, iCingRobot.FORM_USER_ID) accessKey = getRunTextParameter(run, iCingRobot.FORM_ACCESS_KEY) if userId and accessKey: self.serverCredentials = [(iCingRobot.FORM_USER_ID, userId), (iCingRobot.FORM_ACCESS_KEY, accessKey)] url = getRunTextParameter(run, ICING_BASE_URL) if url: htmlUrl = getRunTextParameter(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()
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
class MidgePopup(BasePopup): def __init__(self, parent, *args, **kw): self.guiParent = parent self.project = parent.getProject() self.waiting = 0 self.specFreq = 800.13 self.maxIter = 15 self.mixTime = 60 self.corrTime = 11.5 self.leakRate = 2.0 self.ratioHD = 0.9 self.peakListDict = {} self.peakListDict3d = {} self.noesyPeakList = None self.noesy3dPeakList = None self.carbonLabel = 0 self.nitrogenLabel = 1 self.noesyPeakList1 = None self.noesyPeakList2 = None self.noesyPeakList3 = None self.noesyPeakList3d = None self.resonances = None self.noesyPeaks = None self.distanceConstraintList = None self.antiDistConstraintList = None self.adcAtomTypes = None self.structure = None BasePopup.__init__(self, parent, title="Relaxation Matrix Optimisation", **kw) def body(self, guiFrame): self.specFreqEntry = IntEntry(self, text=self.specFreq, width=8, returnCallback=self.setSpecFreq) self.maxIterEntry = IntEntry(self, text=self.maxIter, width=8, returnCallback=self.setMaxIter) self.mixTimeEntry = FloatEntry(self, text=self.mixTime, width=8, returnCallback=self.setMixTime) self.corrTimeEntry = FloatEntry(self, text=self.corrTime, width=8, returnCallback=self.setCorrTime) self.leakRateEntry = FloatEntry(self, text=self.leakRate, width=8, returnCallback=self.setLeakRate) guiFrame.grid_columnconfigure(0, weight=1) guiFrame.grid_rowconfigure(1, weight=1) row = 0 labelFrame0 = LabelFrame(guiFrame, text='Input data') labelFrame0.grid(row=row, column=0, sticky=Tkinter.NSEW) labelFrame0.grid_columnconfigure(3, weight=1) label = Label(labelFrame0, text='Assigned NOESY spectrum') label.grid(row=0, column=0, sticky=Tkinter.NW) self.noesyPulldown = PulldownMenu(labelFrame0, entries=self.getNoesys(), callback=self.setNoesy, selected_index=0, do_initial_callback=0) self.noesyPulldown.grid(row=0, column=1, sticky=Tkinter.NW) label = Label(labelFrame0, text='H/D ratio: ') label.grid(row=0, column=2, sticky=Tkinter.NW) self.ratioHDEntry = FloatEntry(labelFrame0, text=self.ratioHD, width=6) self.ratioHDEntry.grid(row=0, column=3, sticky=Tkinter.NW) label = Label(labelFrame0, text='NOESY spectrum 1:') label.grid(row=1, column=0, sticky=Tkinter.NW) self.tmix1Pulldown = PulldownMenu(labelFrame0, entries=self.getNoesys(), callback=self.setNoesy1, selected_index=-0, do_initial_callback=0) self.tmix1Pulldown.grid(row=1, column=1, sticky=Tkinter.NW) label = Label(labelFrame0, text='Tmix (ms): ') label.grid(row=1, column=2, sticky=Tkinter.NW) self.tmix1Entry = FloatEntry(labelFrame0, text=60, width=6) self.tmix1Entry.grid(row=1, column=3, sticky=Tkinter.NW) label = Label(labelFrame0, text='NOESY spectrum 2:') label.grid(row=2, column=0, sticky=Tkinter.NW) self.tmix2Pulldown = PulldownMenu(labelFrame0, entries=self.getNoesys(), callback=self.setNoesy2, selected_index=0, do_initial_callback=0) self.tmix2Pulldown.grid(row=2, column=1, sticky=Tkinter.NW) label = Label(labelFrame0, text='Tmix (ms): ') label.grid(row=2, column=2, sticky=Tkinter.NW) self.tmix2Entry = FloatEntry(labelFrame0, text=120, width=6) self.tmix2Entry.grid(row=2, column=3, sticky=Tkinter.NW) label = Label(labelFrame0, text='NOESY spectrum 3:') label.grid(row=3, column=0, sticky=Tkinter.NW) self.tmix3Pulldown = PulldownMenu(labelFrame0, entries=self.getNoesys(), callback=self.setNoesy3, selected_index=0, do_initial_callback=0) self.tmix3Pulldown.grid(row=3, column=1, sticky=Tkinter.NW) label = Label(labelFrame0, text='Tmix (ms): ') label.grid(row=3, column=2, sticky=Tkinter.NW) self.tmix3Entry = FloatEntry(labelFrame0, text=200, width=6) self.tmix3Entry.grid(row=3, column=3, sticky=Tkinter.NW) label = Label(labelFrame0, text='3D NOESY:') label.grid(row=4, column=0, sticky=Tkinter.NW) self.noesy3dPulldown = PulldownMenu(labelFrame0, entries=self.getNoesys3d(), callback=self.setNoesy3d, selected_index=0, do_initial_callback=0) self.noesy3dPulldown.grid(row=4, column=1, sticky=Tkinter.NW) label10 = Label(labelFrame0, text='Num peaks:') label10.grid(row=5, column=0, sticky=Tkinter.NW) self.numPeaksLabel = Label(labelFrame0, text='0') self.numPeaksLabel.grid(row=5, column=1, sticky=Tkinter.NW) label11 = Label(labelFrame0, text='Num resonances:') label11.grid(row=5, column=2, sticky=Tkinter.NW) self.numResonancesLabel = Label(labelFrame0, text='0') self.numResonancesLabel.grid(row=5, column=3, sticky=Tkinter.NW) row += 1 labelFrame1 = LabelFrame(guiFrame, text='Parameters') labelFrame1.grid(row=row, column=0, sticky=Tkinter.NSEW) labelFrame1.grid_columnconfigure(3, weight=1) label = Label(labelFrame1, text='15N labelled sample:') label.grid(row=0, column=0, sticky=Tkinter.NW) self.nitrogenSelect = CheckButton(labelFrame1, callback=self.setNitrogenLabel) self.nitrogenSelect.grid(row=0, column=1, sticky=Tkinter.W) self.nitrogenSelect.set(1) label = Label(labelFrame1, text='13C labelled sample:') label.grid(row=0, column=2, sticky=Tkinter.NW) self.carbonSelect = CheckButton(labelFrame1, callback=self.setCarbonLabel) self.carbonSelect.grid(row=0, column=3, sticky=Tkinter.W) self.carbonSelect.set(0) labelFrame1.grid_rowconfigure(1, weight=1) data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate ] colHeadings = [ 'Spectrometer\nfrequency', 'Max\niterations', 'Mixing\ntime (ms)', 'Correl.\ntime (ns)', 'Leak\nrate' ] editWidgets = [ self.specFreqEntry, self.maxIterEntry, self.mixTimeEntry, self.corrTimeEntry, self.leakRateEntry, ] editGetCallbacks = [ self.getSpecFreq, self.getMaxIter, self.getMixTime, self.getCorrTime, self.getLeakRate, ] editSetCallbacks = [ self.setSpecFreq, self.setMaxIter, self.setMixTime, self.setCorrTime, self.setLeakRate, ] self.midgeParamsMatrix = ScrolledMatrix( labelFrame1, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, maxRows=1, initialCols=5, headingList=colHeadings, callback=None, objectList=[ 'None', ], textMatrix=[ data, ]) self.midgeParamsMatrix.grid(row=1, column=0, columnspan=4, sticky=Tkinter.NSEW) label10 = Label(labelFrame1, text='Benchmark structure') label10.grid(row=2, column=0, sticky=Tkinter.NW) self.structurePulldown = PulldownMenu(labelFrame1, entries=self.getStructures(), callback=self.setStructure, selected_index=0, do_initial_callback=0) self.structurePulldown.grid(row=2, column=1, sticky=Tkinter.NW) label11 = Label(labelFrame1, text='ADC atom types:') label11.grid(row=2, column=2, sticky=Tkinter.NW) self.adcAtomsPulldown = PulldownMenu(labelFrame1, entries=self.getAdcAtomTypes(), callback=self.setAdcAtomTypes, selected_index=0, do_initial_callback=0) self.adcAtomsPulldown.grid(row=2, column=3, sticky=Tkinter.NW) row += 1 labelFrame2 = LabelFrame(guiFrame, text='Output') labelFrame2.grid(row=row, column=0, sticky=Tkinter.NSEW) labelFrame2.grid_columnconfigure(3, weight=1) label20 = Label(labelFrame2, text='Distance constraints:') label20.grid(row=0, column=0, sticky=Tkinter.NW) self.distConstrLabel = Label(labelFrame2, text='0') self.distConstrLabel.grid(row=0, column=1, sticky=Tkinter.NW) label21 = Label(labelFrame2, text='Anti-distance constraints:') label21.grid(row=0, column=2, sticky=Tkinter.NW) self.antiConstrLabel = Label(labelFrame2, text='0') self.antiConstrLabel.grid(row=0, column=3, sticky=Tkinter.NW) texts = [ 'Calculate distances', 'Show distance\nconstraints', 'Show anti-distance\nconstraints' ] commands = [ self.calculateDistances, self.showConstraints, self.showAntiConstraints ] self.midgeButtons = ButtonList(labelFrame2, expands=1, texts=texts, commands=commands) self.midgeButtons.grid(row=1, column=0, columnspan=4, sticky=Tkinter.NSEW) row += 1 self.bottomButtons = createDismissHelpButtonList(guiFrame, expands=0, help_url=None) self.bottomButtons.grid(row=row, column=0, columnspan=4, sticky=Tkinter.EW) self.getPeaks() self.getResonances() self.update() self.geometry('600x400') def setCarbonLabel(self, boolean): self.carbonLabel = boolean def setNitrogenLabel(self, boolean): self.nitrogenLabel = boolean def update(self): if self.resonances and ( (self.noesyPeaks and self.noesyPeakList1 and self.noesyPeakList2 and self.noesyPeakList3) or self.noesyPeakList3d): self.midgeButtons.buttons[0].enable() else: self.midgeButtons.buttons[0].disable() if self.distanceConstraintList: self.distConstrLabel.set( str(len(self.distanceConstraintList.constraints))) self.midgeButtons.buttons[1].enable() else: self.distConstrLabel.set('') self.midgeButtons.buttons[1].disable() if self.antiDistConstraintList: self.antiConstrLabel.set( str(len(self.antiDistConstraintList.constraints))) self.midgeButtons.buttons[2].enable() else: self.antiConstrLabel.set('') self.midgeButtons.buttons[2].disable() if self.resonances: self.numResonancesLabel.set(str(len(self.resonances))) else: self.numResonancesLabel.set('') if self.noesyPeaks: self.numPeaksLabel.set(str(len(self.noesyPeaks))) else: self.numPeaksLabel.set('') def getStructures(self): names = [ '<None>', ] for molSystem in self.project.sortedMolSystems(): for structure in molSystem.sortedStructureEnsembles(): names.append('%s:%d' % (molSystem.name, structure.ensembleId)) return names def setStructure(self, index, name=None): if index < 1: self.structure = None else: structures = [] for molSystem in self.project.molSystems: for structure in molSystem.structureEnsembles: structures.append(structure) self.structure = structures[index - 1] def getAdcAtomTypes(self): return ['<None>', 'HN', 'HN HA', 'HN HA HB'] def setAdcAtomTypes(self, index, name=None): if name is None: name = self.adcAtomsPulldown.getSelected() if name == '<None>': name = None self.adcAtomTypes = name def getResonances(self): resonanceDict = {} if self.noesyPeaks: for peak in self.noesyPeaks: for peakDim in peak.peakDims: for contrib in peakDim.peakDimContribs: resonanceDict[contrib.resonance] = 1 # TBD: Set resonance.name for typing self.resonances = resonanceDict.keys() def getPeaks(self): if self.noesyPeakList: self.noesyPeaks = self.noesyPeakList.sortedPeaks() def calculateDistances(self): resonances = list(self.resonances) resDict = {} for resonance in resonances: resDict[resonance.serial] = resonance ratioHD = self.ratioHDEntry.get() or self.ratioHD tmix1 = self.tmix1Entry.get() or 60 tmix2 = self.tmix2Entry.get() or 120 tmix3 = self.tmix3Entry.get() or 200 data = [(tmix1, self.noesyPeakList1), (tmix2, self.noesyPeakList2), (tmix3, self.noesyPeakList3)] data.sort() mixingTimes = [x[0] for x in data] peakLists = [x[1] for x in data] # get a clean, symmetric and normalised NOE matrix noeMatrix = getNoeMatrixFromPeaks(self.noesyPeaks, resonances, peakLists, mixingTimes, ratioHD=ratioHD, analysis=self.guiParent) # optimiseRelaxation will remove unconstrained resonances self.distanceConstraintList, resonances = optimiseRelaxation( resonances, noeMatrix, self.mixTime, self.specFreq, self.corrTime, self.leakRate, self.carbonLabel, self.nitrogenLabel, maxIter=self.maxIter) #constrainSpinSystems(self.distanceConstraintList) # for testing calculate distances from structure overrides any resonances: uses assigned ones #(self.distanceConstraintList, self.resonances) = self.cheatForTesting() #self.antiDistConstraintList = self.distanceConstraintList protonNumbs = {'CH3': 3, 'Haro': 2, 'HN': 1, 'H': 1} PI = 3.1415926535897931 GH = 2.6752e4 HB = 1.05459e-27 CONST = GH * GH * GH * GH * HB * HB tc = 1.0e-9 * self.corrTime wh = 2.0 * PI * self.specFreq * 1.0e6 j0 = CONST * tc j1 = CONST * tc / (1.0 + wh * wh * tc * tc) j2 = CONST * tc / (1.0 + 4.0 * wh * wh * tc * tc) #jself = 6.0*j2 + 3.0*j1 + j0 jcross = 6.0 * j2 - j0 if self.distanceConstraintList and self.noesyPeakList: constraintHead = self.distanceConstraintList.nmrConstraintStore if self.adcAtomTypes: adcDict = { 'HN': ['H'], 'HN HA': ['H', 'HA', 'HA1', 'HA2'], 'HN HA HB': ['H', 'HA', 'HA1', 'HA2', 'HB', 'HB2', 'HB3'] } allowedAtomTypes = adcDict[self.adcAtomTypes] print "Making ADCs" self.antiDistConstraintList = makeNoeAdcs( resonances[:], self.noesyPeakList.dataSource, constraintHead, allowedAtomTypes=allowedAtomTypes) print "Done ADCs" if self.structure: N = len(self.resonances) sigmas = [[] for i in range(N)] for i in range(N): sigmas[i] = [0.0 for j in range(N)] for constraint in self.distanceConstraintList.constraints: item = constraint.findFirstItem() resonances = list(item.resonances) ri = resDict[resonances[0].resonanceSerial] rj = resDict[resonances[1].resonanceSerial] i = self.resonances.index(ri) j = self.resonances.index(rj) atomSets1 = list(ri.resonanceSet.atomSets) atomSets2 = list(rj.resonanceSet.atomSets) if atomSets1 == atomSets2: ass = list(atomSets1) atomSets1 = [ ass[0], ] atomSets2 = [ ass[-1], ] distance = getAtomSetsDistance(atomSets1, atomSets2, self.structure) r = distance * 1e-8 nhs = protonNumbs[rj.name] sigma = 0.1 * jcross * nhs / (r**6) sigmas[i][j] = sigma constraint.setOrigData(distance) self.update() def showConstraints(self): if self.distanceConstraintList: self.guiParent.browseConstraints( constraintList=self.distanceConstraintList) def showAntiConstraints(self): if self.antiDistConstraintList: self.guiParent.browseConstraints( constraintList=self.antiDistConstraintList) def getNoesys3d(self): peakLists = getThroughSpacePeakLists(self.project) names = [ '<None>', ] for peakList in peakLists: spectrum = peakList.dataSource if spectrum.numDim != 3: continue name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict3d[name] = peakList if not self.noesyPeakList: self.noesyPeakList = peakList return names def getNoesys(self): peakLists = getThroughSpacePeakLists(self.project) names = [ '<None>', ] for peakList in peakLists: spectrum = peakList.dataSource name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.noesyPeakList: self.noesyPeakList = peakList return names def setNoesy(self, index, name=None): if not name: name = self.noesyPulldown.getSelected() if name == '<None>': self.noesyPeakList = None else: self.noesyPeakList = self.peakListDict[name] self.getPeaks() self.getResonances() self.update() def setNoesy1(self, index, name=None): if not name: name = self.tmix1Pulldown.getSelected() if name != '<None>': self.noesyPeakList1 = self.peakListDict[name] else: self.noesyPeakList1 = None self.update() def setNoesy2(self, index, name=None): if not name: name = self.tmix2Pulldown.getSelected() if name != '<None>': self.noesyPeakList2 = self.peakListDict[name] else: self.noesyPeakList2 = None self.update() def setNoesy3(self, index, name=None): if not name: name = self.tmix3Pulldown.getSelected() if name != '<None>': self.noesyPeakList3 = self.peakListDict[name] else: self.noesyPeakList3 = None self.update() def setNoesy3d(self, index, name=None): if not name: name = self.noesy3dPulldown.getSelected() if name != '<None>': self.noesyPeakList3d = self.peakListDict3d[name] self.noesyPeaks = self.noesyPeakList3d.sortedPeaks() else: self.noesyPeakList3d = None self.noesyPeaks = [] self.getResonances() self.update() def updateMidgeParams(self): data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate ] self.midgeParamsMatrix.update(textMatrix=[ data, ]) def getSpecFreq(self, obj): self.specFreqEntry.set(self.specFreq) def getMaxIter(self, obj): self.maxIterEntry.set(self.maxIter) def getMixTime(self, obj): self.mixTimeEntry.set(self.mixTime) def getCorrTime(self, obj): self.corrTimeEntry.set(self.corrTime) def getLeakRate(self, obj): self.leakRateEntry.set(self.leakRate) def setSpecFreq(self, event): value = self.specFreqEntry.get() if value is not None: self.specFreq = value self.updateMidgeParams() def setMaxIter(self, event): value = self.maxIterEntry.get() if value is not None: self.maxIter = value self.updateMidgeParams() def setMixTime(self, event): value = self.mixTimeEntry.get() if value is not None: self.mixTime = value self.updateMidgeParams() def setCorrTime(self, event): value = self.corrTimeEntry.get() if value is not None: self.corrTime = value self.updateMidgeParams() def setLeakRate(self, event): value = self.leakRateEntry.get() if value is not None: self.leakRate = value self.updateMidgeParams() def destroy(self): BasePopup.destroy(self)
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
def __init__(self, parent, dangleGui, project=None, *args, **kw): self.guiParent = parent self.dangleGui = dangleGui self.dangleDir = None self.dangleChain = None self.dangleResidue = None #self.outDir = OUTDIR self.row = None self.col = None self.project = project self.nmrProject = None self.colorScheme = 'red' self.chain = None self.shiftList = None self.dangleStore = False # Not None self.constraintSet = None self.ensemble = None Frame.__init__(self, parent=parent) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(1, weight=1) row = 0 # TOP LEFT FRAME frame = LabelFrame(self, 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') label = Label(frame, text='Max No. of Islands:') label.grid(row=0, column=4, sticky='w') sizes = range(10) texts = [str(s) for s in sizes] + [ 'Do not reject', ] self.rejectPulldown = PulldownList( frame, texts=texts, objects=sizes + [ None, ], tipText= 'Select the maximum allowed number of disontinuous prediction islands' ) self.rejectPulldown.set(DEFAULT_MAX_ISLANDS) # Actual value not index self.rejectPulldown.grid(row=0, column=5, sticky='w') label = Label(frame, text='Dangle Run:') label.grid(row=1, column=0, sticky='w') self.dangleStorePulldown = PulldownList( frame, callback=self.changeDangleStore, tipText='Select a run number to store DANGLE results within') self.dangleStorePulldown.grid(row=1, column=1, sticky='w') label = Label(frame, text='Ensemble:') label.grid(row=1, column=2, sticky='w') self.ensemblePulldown = PulldownList( frame, callback=self.changeEnsemble, tipText= 'Select the structure ensemble for superimposition of angle values on the GLE plots' ) self.ensemblePulldown.grid(row=1, column=3, sticky='w') label = Label(frame, text='Restraint Set:') label.grid(row=1, column=4, sticky='w') self.constrSetPulldown = PulldownList( frame, callback=self.changeConstraintSet, tipText= 'Select the CCPN restraint set to store DANGLE dihedral angle restraints in' ) self.constrSetPulldown.grid(row=1, column=5, sticky='w') # TOP RIGHT FRAME outerFrame = Frame(self) outerFrame.grid(row=row, column=1, rowspan=2, sticky='nsew') outerFrame.rowconfigure(0, weight=1) outerFrame.columnconfigure(0, weight=1) frame = LabelFrame(outerFrame, text='Global Likelihood Estimates') frame.grid(row=0, column=0, sticky='nsew') frame.rowconfigure(1, weight=1) frame.columnconfigure(2, weight=1) self.prevPlot = ViewRamachandranFrame(frame, relief='sunken', defaultPlot=False, width=180, height=180, bgColor=self.cget('bg'), nullColor='#000000', titleText='Previous', xTicks=False, yTicks=False, xLabel='', yLabel='', showCoords=False) self.prevPlot.grid(row=0, column=0, sticky='nsew') self.prevPlot.getPlotColor = self.getPlotColor self.nextPlot = ViewRamachandranFrame(frame, relief='sunken', defaultPlot=False, width=180, height=180, bgColor=self.cget('bg'), nullColor='#000000', titleText='Next', xTicks=False, yTicks=False, xLabel='', yLabel='', showCoords=False) self.nextPlot.grid(row=0, column=1, sticky='nsew') self.nextPlot.getPlotColor = self.getPlotColor self.plot = ViewRamachandranFrame(frame, relief='sunken', defaultPlot=False, width=360, height=360, bgColor=self.cget('bg'), nullColor='#000000') self.plot.grid(row=1, column=0, columnspan=2, sticky='nsew') self.plot.selectColor = '#FFB0B0' self.plot.getPlotColor = self.getPlotColor # BOTTOM RIGHT FRAME frame = Frame(outerFrame) frame.grid(row=1, column=0, sticky='nsew') frame.rowconfigure(0, weight=1) frame.columnconfigure(0, weight=1) texts = ('Previous', ' Next ') commands = (self.showPrevious, self.showNext) tipTexts = [ 'Show GLE plot of angle predictions for previous residue in chain', 'Show GLE plot of angle predictions for next residue in chain' ] buttonList = ButtonList(frame, texts, commands, tipTexts=tipTexts) buttonList.grid(row=0, column=0, sticky='nsew') row += 1 # BOTTOM LEFT FRAME frame = LabelFrame(self, text='Dihedral Angle Predictions') frame.grid(row=row, column=0, sticky='nsew') frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(0, weight=1) self.floatEntry = FloatEntry(self, text='', returnCallback=self.setFloatEntry, width=10, formatPlaces=9) tipTexts = [ 'Residue number in chain', 'Residue type code', 'Number of high scoring discontinuous angle predictions', 'Predicted secondary structure code', 'Predicted phi dihedral angle (CO-N-CA-CO)', 'Predicted psi dihedral angle (N-CA-CO-N)', 'Upper bound of phi angle prediction', 'Lower bound of phi angle prediction', 'Upper bound of psi angle prediction', 'Lower bound of phi angle prediction', 'Chemical shifts used in prediction' ] headingList = [ 'Res\nNum', 'Res\nType', 'No. of\nIslands', 'SS', 'Phi', 'Psi', 'Phi\nUpper', 'Phi\nLower', 'Psi\nUpper', 'Psi\nLower', 'Chemical Shifts' ] editWidgets = [ None, None, None, None, self.floatEntry, self.floatEntry, self.floatEntry, self.floatEntry, self.floatEntry, self.floatEntry ] editGetCallbacks = [ None, None, None, None, self.getFloatEntry, self.getFloatEntry, self.getFloatEntry, self.getFloatEntry, self.getFloatEntry, self.getFloatEntry ] editSetCallbacks = [ None, None, None, None, self.setFloatEntry, self.setFloatEntry, self.setFloatEntry, self.setFloatEntry, self.setFloatEntry, self.setFloatEntry ] self.predictionMatrix = ScrolledMatrix( frame, headingList=headingList, multiSelect=True, callback=self.selectCell, tipTexts=tipTexts, editWidgets=editWidgets, editGetCallbacks=editGetCallbacks, editSetCallbacks=editSetCallbacks) # doubleCallback=self.loadGLEs) self.predictionMatrix.grid(row=0, column=0, sticky='nsew') row += 1 tipTexts = [ 'Remove the predictions for the selected residues', 'Run the DANGLE method to predict dihedral angles and secondary structure', 'Delete the DANGLE results stored under the current run number', 'Store the angle predictions and bounds in a new CCPN dihedral angle restraint list', 'Store the secondary structure predictions in the CCPN project' ] texts = [ 'Clear\nSelected', 'Run Prediction!', 'Delete\nCurrent Run', 'Commit\nRestraints', 'Commit\nSecondary Structure' ] commands = [ self.clearSelected, self.runDangle, self.deleteRun, self.storeDihedralConstraints, self.storeSecondaryStructure ] self.buttonList = createDismissHelpButtonList( self, texts=texts, commands=commands, # dismiss_text='Quit', dismiss_cmd=self.dangleGui.quit, help_url=self.dangleGui.help_url, expands=True, tipTexts=tipTexts) self.buttonList.grid(row=row, column=0, columnspan=2, sticky='ew') self.buttonList.buttons[1].config(bg='#C0FFFF') self.updateProject(project) self.notify(dangleGui.registerNotify)
class CingGui(BasePopup): def __init__(self, parent, options, *args, **kw): # Fill in below variable once run generates some results self.haveResults = None # store the options self.options = options BasePopup.__init__(self, parent=parent, title='CING Setup', **kw) # self.setGeometry(850, 750, 50, 50) self.project = None # self.tk_strictMotif( True) self.updateGui() # end def __init__ def body(self, guiFrame): row = 0 col =0 # frame = Frame( guiFrame ) # frame.grid(row=row, column=col, sticky='news') self.menuBar = Menu( guiFrame) self.menuBar.grid( row=row, column=col, sticky='ew') #---------------------------------------------------------------------------------- # Project frame #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(row, weight=1) # frame = LabelFrame(guiFrame, text='Project', font=medFont) row = +1 col =0 frame = LabelFrame(guiFrame, text='Project', **labelFrameAttributes ) print '>', frame.keys() frame.grid(row=row, column=col, sticky='nsew' ) frame.grid_columnconfigure(2, weight=1) # frame.grid_rowconfigure(0, weight=1) srow = 0 self.projectOptions = ['old','new from PDB','new from CCPN','new from CYANA'] self.projOptionsSelect = RadioButtons(frame, selected_index=0, entries=self.projectOptions, direction='vertical', select_callback=self.updateGui ) self.projOptionsSelect.grid(row=srow,column=0,rowspan=len(self.projectOptions),columnspan=2, sticky='w') if self.options.name: text = self.options.name else: text='' # end if self.projEntry = Entry(frame, bd=1, text=text, returnCallback=self.updateGui) self.projEntry.grid(row=srow,column=2,columnspan=2,sticky='ew') # self.projEntry.bind('<Key>', self.updateGui) self.projEntry.bind('<Leave>', self.updateGui) projButton = Button(frame, bd=1,command=self.chooseOldProjectFile, text='browse') projButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.pdbEntry = Entry(frame, bd=1, text='') self.pdbEntry.grid(row=srow,column=2,sticky='ew') self.pdbEntry.bind('<Leave>', self.updateGui) pdbButton = Button(frame, bd=1,command=self.choosePdbFile, text='browse') pdbButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.ccpnEntry = Entry(frame, bd=1, text='') self.ccpnEntry.grid(row=srow,column=2,sticky='ew') self.ccpnEntry.bind('<Leave>', self.updateGui) ccpnButton = Button(frame, bd=1,command=self.chooseCcpnFile, text='browse') ccpnButton.grid(row=srow,column=3,sticky='ew') srow += 1 self.cyanaEntry = Entry(frame, bd=1, text='') self.cyanaEntry.grid(row=srow,column=2,sticky='ew') self.cyanaEntry.bind('<Leave>', self.updateGui) cyanaButton = Button(frame, bd=1,command=self.chooseCyanaFile, text='browse') cyanaButton.grid(row=srow,column=3,sticky='ew') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 label = Label(frame, text='Project name:') label.grid(row=srow,column=0,sticky='nw') self.nameEntry = Entry(frame, bd=1, text='') self.nameEntry.grid(row=srow,column=2,sticky='w') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 self.openProjectButton = Button(frame, command=self.openProject, text='Open Project', **actionButtonAttributes ) self.openProjectButton.grid(row=srow,column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # status #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(1, weight=0) srow = 0 frame = LabelFrame(guiFrame, text='Status', **labelFrameAttributes) frame.grid( row=srow, column=1, sticky='wnes') self.projectStatus = Text(frame, height=11, width=70, borderwidth=0, relief='flat') self.projectStatus.grid(row=0, column=0, sticky='wen') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') srow += 1 self.closeProjectButton = Button(frame, command=self.closeProject, text='Close Project', **actionButtonAttributes) self.closeProjectButton.grid(row=srow,column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # Validate frame #---------------------------------------------------------------------------------- row +=1 col=0 frame = LabelFrame(guiFrame, text='Validate', **labelFrameAttributes) # frame = LabelFrame(guiFrame, text='Validate', font=medFont) frame.grid(row=row, column=col, sticky='nsew') # frame.grid_columnconfigure(2, weight=1) frame.grid_rowconfigure(0, weight=1) srow = 0 # label = Label(frame, text='validation') # label.grid(row=srow,column=0,sticky='nw') # # self.selectDoValidation = CheckButton(frame) # self.selectDoValidation.grid(row=srow, column=1,sticky='nw' ) # self.selectDoValidation.set(True) # # srow += 1 # label = Label(frame, text='') # label.grid(row=srow,column=0,sticky='nw') # # srow += 1 label = Label(frame, text='checks') label.grid(row=srow,column=0,sticky='nw') self.selectCheckAssign = CheckButton(frame) self.selectCheckAssign.grid(row=srow, column=1,sticky='nw' ) self.selectCheckAssign.set(True) label = Label(frame, text='assignments and shifts') label.grid(row=srow,column=2,sticky='nw') # srow += 1 # self.selectCheckQueen = CheckButton(frame) # self.selectCheckQueen.grid(row=srow, column=4,sticky='nw' ) # self.selectCheckQueen.set(False) # label = Label(frame, text='QUEEN') # label.grid(row=srow,column=5,sticky='nw') # # queenButton = Button(frame, bd=1,command=None, text='setup') # queenButton.grid(row=srow,column=6,sticky='ew') srow += 1 self.selectCheckResraint = CheckButton(frame) self.selectCheckResraint.grid(row=srow, column=1,sticky='nw' ) self.selectCheckResraint.set(True) label = Label(frame, text='restraints') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectCheckStructure = CheckButton(frame) self.selectCheckStructure.grid(row=srow, column=1,sticky='nw' ) self.selectCheckStructure.set(True) label = Label(frame, text='structural') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectMakeHtml = CheckButton(frame) self.selectMakeHtml.grid(row=srow, column=1,sticky='nw' ) self.selectMakeHtml.set(True) label = Label(frame, text='generate HTML') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectCheckScript = CheckButton(frame) self.selectCheckScript.grid(row=srow, column=1,sticky='nw' ) self.selectCheckScript.set(False) label = Label(frame, text='user script') label.grid(row=srow,column=0,sticky='nw') self.validScriptEntry = Entry(frame, bd=1, text='') self.validScriptEntry.grid(row=srow,column=2,columnspan=3, sticky='ew') scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') scriptButton.grid(row=srow,column=5,sticky='ew') srow += 1 label = Label(frame, text='ranges') label.grid(row=srow,column=0,sticky='nw') self.rangesEntry = Entry( frame, text='' ) self.rangesEntry.grid( row=srow, column=2, columnspan=3, sticky='ew') # self.validScriptEntry = Entry(frame, bd=1, text='') # self.validScriptEntry.grid(row=srow,column=3,sticky='ew') # # scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') # scriptButton.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Run Validation','View Results','Setup QUEEN'] commands = [self.runCing, None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands,expands=True) buttonBar.grid(row=srow, column=0, columnspan=6, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.runButton = buttonBar.buttons[0] self.viewResultButton = buttonBar.buttons[1] self.queenButton = buttonBar.buttons[2] #---------------------------------------------------------------------------------- # Miscellaneous frame #---------------------------------------------------------------------------------- row +=0 col=1 # frame = LabelFrame(guiFrame, text='Miscellaneous', font=medFont) frame = LabelFrame(guiFrame, text='Miscellaneous', **labelFrameAttributes) frame.grid(row=row, column=col, sticky='news') frame.grid_columnconfigure(2, weight=1) frame.grid_columnconfigure(4, weight=1,minsize=30) frame.grid_rowconfigure(0, weight=1) # Exports srow = 0 label = Label(frame, text='export to') label.grid(row=srow,column=0,sticky='nw') self.selectExportXeasy = CheckButton(frame) self.selectExportXeasy.grid(row=srow, column=1,sticky='nw' ) self.selectExportXeasy.set(True) label = Label(frame, text='Xeasy, Sparky, TALOS, ...') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportCcpn = CheckButton(frame) self.selectExportCcpn.grid(row=srow, column=1,sticky='nw' ) self.selectExportCcpn.set(True) label = Label(frame, text='CCPN') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportQueen = CheckButton(frame) self.selectExportQueen.grid(row=srow, column=1,sticky='nw' ) self.selectExportQueen.set(True) label = Label(frame, text='QUEEN') label.grid(row=srow,column=2,sticky='nw') srow += 1 self.selectExportRefine = CheckButton(frame) self.selectExportRefine.grid(row=srow, column=1,sticky='nw' ) self.selectExportRefine.set(True) label = Label(frame, text='refine') label.grid(row=srow,column=2,sticky='nw') srow += 1 label = Label(frame, text='') label.grid(row=srow,column=0,sticky='nw') # User script srow += 1 label = Label(frame, text='user script') label.grid(row=srow,column=0,sticky='nw') self.selectMiscScript = CheckButton(frame) self.selectMiscScript.grid(row=srow, column=1,sticky='nw' ) self.selectMiscScript.set(False) self.miscScriptEntry = Entry(frame, bd=1, text='') self.miscScriptEntry.grid(row=srow,column=3,sticky='ew') script2Button = Button(frame, bd=1,command=self.chooseMiscScript, text='browse') script2Button.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Export','Run Script'] commands = [None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands,expands=True) buttonBar.grid(row=srow, column=0, columnspan=5, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.exportButton = buttonBar.buttons[0] self.scriptButton = buttonBar.buttons[1] #---------------------------------------------------------------------------------- # Textarea #---------------------------------------------------------------------------------- row +=1 guiFrame.grid_rowconfigure(row, weight=1) self.outputTextBox = ScrolledText(guiFrame) self.outputTextBox.grid(row=row, column=0, columnspan=2, sticky='nsew') self.redirectConsole() #---------------------------------------------------------------------------------- # Buttons #---------------------------------------------------------------------------------- row +=1 col=0 texts = ['Quit', 'Help'] commands = [self.close, None] self.buttonBar = ButtonList(guiFrame, texts=texts, commands=commands,expands=True) self.buttonBar.grid(row=row, column=col, columnspan=2, sticky='ew') # self.openProjectButton = self.buttonBar.buttons[0] # self.closeProjectButton = self.buttonBar.buttons[1] # self.runButton = self.buttonBar.buttons[0] # self.viewResultButton = self.buttonBar.buttons[1] for button in self.buttonBar.buttons: button.config(**actionButtonAttributes) # end for # end def body def getGuiOptions(self): projectName = self.projEntry.get() index = self.projOptionsSelect.getIndex() if index > 0: makeNewProject = True projectImport = None if index > 1: i = index-2 format = ['PDB','CCPN','CYANA'][i] file = [self.pdbEntry, self.ccpnEntry, self.cyanaEntry][i].get() if not file: showWarning('Failure','No %s file selected' % format) return # end if projectImport = (format, file) # end if else: # Chould also check that any old project file exists makeNewProject = False projectImport = None # end if doValidation = self.selectDoValidation.get() checks = [] if doValidation: if self.selectCheckAssign.get(): checks.append('assignments') # end if if self.selectCheckResraint.get(): checks.append('restraints') # end if if self.selectCheckStructure.get(): checks.append('structural') # end if if self.selectMakeHtml.get(): checks.append('HTML') # end if if self.selectCheckScript.get(): script = self.validScriptEntry.get() if script: checks.append( ('script',script) ) # end if # end if if self.selectCheckQueen.get(): checks.append('queen') # end if # end if exports = [] if self.selectExportXeasy.get(): exports.append('Xeasy') # end if if self.selectExportCcpn.get(): exports.append('CCPN') # end if if self.selectExportQueen.get(): exports.append('QUEEN') # end if if self.selectExportRefine.get(): exports.append('refine') # end if miscScript = None if self.selectMiscScript.get(): script = self.miscScriptEntry.get() if script: miscScript = script # end if # end if return projectName, makeNewProject, projectImport, doValidation, checks, exports, miscScript # end def getGuiOptions def runCing(self): options = self.getGuiOptions() if options: projectName, makeNewProject, projectImport, doValidation, checks, exports, miscScript = options print 'Project name:', projectName print 'Make new project?', makeNewProject print 'Import source:', projectImport print 'Do vailidation?', doValidation print 'Validation checks:', ','.join(checks) print 'Export to:', ','.join(exports) print 'User script:', miscScript # end if # end def runCing # else there was already an error message def chooseOldProjectFile(self): fileTypes = [ FileType('CING', ['project.xml']), FileType('All', ['*']) ] popup = FileSelectPopup(self, file_types = fileTypes, title = 'Select CING project file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() # dirName = popup.getDirectory() if len(fileName) > 0: # Put text into entry,name widgets dummy,name = cing.Project.rootPath(fileName) self.projEntry.configure(state='normal') self.projEntry.set(fileName) self.nameEntry.configure(state='normal') self.nameEntry.set(name) self.nameEntry.configure(state='disabled') # choose the correct radiobutton self.projOptionsSelect.setIndex(0) self.updateGui() # end if #nd if popup.destroy() # end def chooseOldProjectFile def choosePdbFile(self): fileTypes = [ FileType('PDB', ['*.pdb']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types = fileTypes, title = 'PDB file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() if len(fileName)>0: # Put text into entry widget self.pdbEntry.configure(state='normal') self.pdbEntry.set(fileName) # Put text into name widget _dir,name,dummy = nTpath( fileName ) self.nameEntry.configure(state='normal') self.nameEntry.set(name) # choose the correct radiobutton self.projOptionsSelect.setIndex(1) self.updateGui() #end if popup.destroy() # end def choosePdbFile def chooseCcpnFile(self): fileTypes = [ FileType('XML', ['*.xml']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types = fileTypes, title = 'CCPN project XML file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() if len(fileName)>0: self.pdbEntry.configure(state='normal') self.pdbEntry.set(fileName) self.projOptionsSelect.setIndex(1) _dir,name,dummy = nTpath( fileName ) self.nameEntry.set(name) #end if self.ccpnEntry.set(fileName) self.projOptionsSelect.setIndex(2) popup.destroy() # end def chooseCcpnFile def chooseCyanaFile(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types = fileTypes, title = 'CYANA fproject file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() self.cyanaEntry.set(fileName) self.projOptionsSelect.setIndex(3) popup.destroy() # end def chooseCyanaFile def chooseValidScript(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types = fileTypes, title = 'Script file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() self.validScriptEntry.set(fileName) popup.destroy() # end def chooseValidScript def chooseMiscScript(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types = fileTypes, title = 'Script file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = popup.getFile() self.miscScriptEntry.set(fileName) popup.destroy() # end def chooseMiscScript def openProject(self ): projOption = self.projOptionsSelect.get() if projOption == self.projectOptions[0]: self.openOldProject() elif projOption == self.projectOptions[1]: self.initPdb() # end if if self.project: self.project.gui = self # end if self.updateGui() #end def def openOldProject(self ): fName = self.projEntry.get() if not os.path.exists( fName ): nTerror('Error: file "%s" does not exist\n', fName) #end if if self.project: self.closeProject() # end if self.project = cing.Project.open( name=fName, status='old', verbose=False ) #end def def initPdb(self ): fName = self.pdbEntry.get() if not os.path.exists( fName ): nTerror('Error: file "%s" does not exist\n', fName) #end if self.project = cing.Project.open( self.nameEntry.get(), status='new' ) self.project.initPDB( pdbFile=fName, convention = 'PDB' ) #end def def closeProject(self): if self.project: self.project.close() # end if self.project = None self.updateGui() #end def def updateGui(self, event=None): projOption = self.projOptionsSelect.get() buttons = self.buttonBar.buttons # Disable entries for e in [self.projEntry, self.pdbEntry, self.ccpnEntry, self.cyanaEntry, self.nameEntry]: e.configure(state='disabled') #end for if projOption == self.projectOptions[0]: # Enable entries self.projEntry.configure(state='normal') if (len(self.projEntry.get()) > 0): self.openProjectButton.enable() self.runButton.enable() else: self.openProjectButton.disable() self.runButton.disable() #end if elif projOption == self.projectOptions[1]: # Enable entries self.pdbEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.pdbEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if elif projOption == self.projectOptions[2]: # Enable entries self.ccpnEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.ccpnEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if elif projOption == self.projectOptions[3]: # Enable entries self.cyanaEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.cyanaEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if self.projectStatus.clear() if not self.project: self.projectStatus.setText('No open project') self.closeProjectButton.setText('Close Project') self.closeProjectButton.disable() else: self.projectStatus.setText(self.project.format()) self.closeProjectButton.enable() self.closeProjectButton.setText(sprintf('Close Project "%s"', self.project.name)) #end if #end def def redirectConsole(self): #pipe = TextPipe(self.inputTextBox.text_area) #sys.stdin = pipe pipe = TextPipe(self.outputTextBox.text_area) sys.stdout = pipe nTmessage.stream = pipe # end def redirectConsole # sys.stderr = pipe def resetConsole(self): #sys.stdin = stdin nTmessage.stream = stdout sys.stdout = stdout sys.stderr = stderr # end def resetConsole def open(self): self.redirectConsole() BasePopup.open(self) # end def open def close(self): geometry = self.getGeometry() self.resetConsole() BasePopup.close(self) print 'close:',geometry sys.exit(0) # remove later # end def close def destroy(self): geometry = self.getGeometry() self.resetConsole() BasePopup.destroy(self) print 'destroy:',geometry sys.exit(0) # remove later
class CingGui(BasePopup): def __init__(self, parent, options, *args, **kw): # Fill in below variable once run generates some results self.haveResults = None # store the options self.options = options BasePopup.__init__(self, parent=parent, title='CING Setup', **kw) # self.setGeometry(850, 750, 50, 50) self.project = None # self.tk_strictMotif( True) self.updateGui() # end def __init__ def body(self, guiFrame): row = 0 col = 0 # frame = Frame( guiFrame ) # frame.grid(row=row, column=col, sticky='news') self.menuBar = Menu(guiFrame) self.menuBar.grid(row=row, column=col, sticky='ew') #---------------------------------------------------------------------------------- # Project frame #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(row, weight=1) # frame = LabelFrame(guiFrame, text='Project', font=medFont) row = +1 col = 0 frame = LabelFrame(guiFrame, text='Project', **labelFrameAttributes) print '>', frame.keys() frame.grid(row=row, column=col, sticky='nsew') frame.grid_columnconfigure(2, weight=1) # frame.grid_rowconfigure(0, weight=1) srow = 0 self.projectOptions = [ 'old', 'new from PDB', 'new from CCPN', 'new from CYANA' ] self.projOptionsSelect = RadioButtons(frame, selected_index=0, entries=self.projectOptions, direction='vertical', select_callback=self.updateGui) self.projOptionsSelect.grid(row=srow, column=0, rowspan=len(self.projectOptions), columnspan=2, sticky='w') if self.options.name: text = self.options.name else: text = '' # end if self.projEntry = Entry(frame, bd=1, text=text, returnCallback=self.updateGui) self.projEntry.grid(row=srow, column=2, columnspan=2, sticky='ew') # self.projEntry.bind('<Key>', self.updateGui) self.projEntry.bind('<Leave>', self.updateGui) projButton = Button(frame, bd=1, command=self.chooseOldProjectFile, text='browse') projButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.pdbEntry = Entry(frame, bd=1, text='') self.pdbEntry.grid(row=srow, column=2, sticky='ew') self.pdbEntry.bind('<Leave>', self.updateGui) pdbButton = Button(frame, bd=1, command=self.choosePdbFile, text='browse') pdbButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.ccpnEntry = Entry(frame, bd=1, text='') self.ccpnEntry.grid(row=srow, column=2, sticky='ew') self.ccpnEntry.bind('<Leave>', self.updateGui) ccpnButton = Button(frame, bd=1, command=self.chooseCcpnFile, text='browse') ccpnButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.cyanaEntry = Entry(frame, bd=1, text='') self.cyanaEntry.grid(row=srow, column=2, sticky='ew') self.cyanaEntry.bind('<Leave>', self.updateGui) cyanaButton = Button(frame, bd=1, command=self.chooseCyanaFile, text='browse') cyanaButton.grid(row=srow, column=3, sticky='ew') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 label = Label(frame, text='Project name:') label.grid(row=srow, column=0, sticky='nw') self.nameEntry = Entry(frame, bd=1, text='') self.nameEntry.grid(row=srow, column=2, sticky='w') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 self.openProjectButton = Button(frame, command=self.openProject, text='Open Project', **actionButtonAttributes) self.openProjectButton.grid(row=srow, column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # status #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(1, weight=0) srow = 0 frame = LabelFrame(guiFrame, text='Status', **labelFrameAttributes) frame.grid(row=srow, column=1, sticky='wnes') self.projectStatus = Text(frame, height=11, width=70, borderwidth=0, relief='flat') self.projectStatus.grid(row=0, column=0, sticky='wen') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 self.closeProjectButton = Button(frame, command=self.closeProject, text='Close Project', **actionButtonAttributes) self.closeProjectButton.grid(row=srow, column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # Validate frame #---------------------------------------------------------------------------------- row += 1 col = 0 frame = LabelFrame(guiFrame, text='Validate', **labelFrameAttributes) # frame = LabelFrame(guiFrame, text='Validate', font=medFont) frame.grid(row=row, column=col, sticky='nsew') # frame.grid_columnconfigure(2, weight=1) frame.grid_rowconfigure(0, weight=1) srow = 0 # label = Label(frame, text='validation') # label.grid(row=srow,column=0,sticky='nw') # # self.selectDoValidation = CheckButton(frame) # self.selectDoValidation.grid(row=srow, column=1,sticky='nw' ) # self.selectDoValidation.set(True) # # srow += 1 # label = Label(frame, text='') # label.grid(row=srow,column=0,sticky='nw') # # srow += 1 label = Label(frame, text='checks') label.grid(row=srow, column=0, sticky='nw') self.selectCheckAssign = CheckButton(frame) self.selectCheckAssign.grid(row=srow, column=1, sticky='nw') self.selectCheckAssign.set(True) label = Label(frame, text='assignments and shifts') label.grid(row=srow, column=2, sticky='nw') # srow += 1 # self.selectCheckQueen = CheckButton(frame) # self.selectCheckQueen.grid(row=srow, column=4,sticky='nw' ) # self.selectCheckQueen.set(False) # label = Label(frame, text='QUEEN') # label.grid(row=srow,column=5,sticky='nw') # # queenButton = Button(frame, bd=1,command=None, text='setup') # queenButton.grid(row=srow,column=6,sticky='ew') srow += 1 self.selectCheckResraint = CheckButton(frame) self.selectCheckResraint.grid(row=srow, column=1, sticky='nw') self.selectCheckResraint.set(True) label = Label(frame, text='restraints') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectCheckStructure = CheckButton(frame) self.selectCheckStructure.grid(row=srow, column=1, sticky='nw') self.selectCheckStructure.set(True) label = Label(frame, text='structural') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectMakeHtml = CheckButton(frame) self.selectMakeHtml.grid(row=srow, column=1, sticky='nw') self.selectMakeHtml.set(True) label = Label(frame, text='generate HTML') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectCheckScript = CheckButton(frame) self.selectCheckScript.grid(row=srow, column=1, sticky='nw') self.selectCheckScript.set(False) label = Label(frame, text='user script') label.grid(row=srow, column=0, sticky='nw') self.validScriptEntry = Entry(frame, bd=1, text='') self.validScriptEntry.grid(row=srow, column=2, columnspan=3, sticky='ew') scriptButton = Button(frame, bd=1, command=self.chooseValidScript, text='browse') scriptButton.grid(row=srow, column=5, sticky='ew') srow += 1 label = Label(frame, text='ranges') label.grid(row=srow, column=0, sticky='nw') self.rangesEntry = Entry(frame, text='') self.rangesEntry.grid(row=srow, column=2, columnspan=3, sticky='ew') # self.validScriptEntry = Entry(frame, bd=1, text='') # self.validScriptEntry.grid(row=srow,column=3,sticky='ew') # # scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') # scriptButton.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Run Validation', 'View Results', 'Setup QUEEN'] commands = [self.runCing, None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands, expands=True) buttonBar.grid(row=srow, column=0, columnspan=6, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.runButton = buttonBar.buttons[0] self.viewResultButton = buttonBar.buttons[1] self.queenButton = buttonBar.buttons[2] #---------------------------------------------------------------------------------- # Miscellaneous frame #---------------------------------------------------------------------------------- row += 0 col = 1 # frame = LabelFrame(guiFrame, text='Miscellaneous', font=medFont) frame = LabelFrame(guiFrame, text='Miscellaneous', **labelFrameAttributes) frame.grid(row=row, column=col, sticky='news') frame.grid_columnconfigure(2, weight=1) frame.grid_columnconfigure(4, weight=1, minsize=30) frame.grid_rowconfigure(0, weight=1) # Exports srow = 0 label = Label(frame, text='export to') label.grid(row=srow, column=0, sticky='nw') self.selectExportXeasy = CheckButton(frame) self.selectExportXeasy.grid(row=srow, column=1, sticky='nw') self.selectExportXeasy.set(True) label = Label(frame, text='Xeasy, Sparky, TALOS, ...') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportCcpn = CheckButton(frame) self.selectExportCcpn.grid(row=srow, column=1, sticky='nw') self.selectExportCcpn.set(True) label = Label(frame, text='CCPN') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportQueen = CheckButton(frame) self.selectExportQueen.grid(row=srow, column=1, sticky='nw') self.selectExportQueen.set(True) label = Label(frame, text='QUEEN') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportRefine = CheckButton(frame) self.selectExportRefine.grid(row=srow, column=1, sticky='nw') self.selectExportRefine.set(True) label = Label(frame, text='refine') label.grid(row=srow, column=2, sticky='nw') srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') # User script srow += 1 label = Label(frame, text='user script') label.grid(row=srow, column=0, sticky='nw') self.selectMiscScript = CheckButton(frame) self.selectMiscScript.grid(row=srow, column=1, sticky='nw') self.selectMiscScript.set(False) self.miscScriptEntry = Entry(frame, bd=1, text='') self.miscScriptEntry.grid(row=srow, column=3, sticky='ew') script2Button = Button(frame, bd=1, command=self.chooseMiscScript, text='browse') script2Button.grid(row=srow, column=4, sticky='ew') srow += 1 texts = ['Export', 'Run Script'] commands = [None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands, expands=True) buttonBar.grid(row=srow, column=0, columnspan=5, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.exportButton = buttonBar.buttons[0] self.scriptButton = buttonBar.buttons[1] #---------------------------------------------------------------------------------- # Textarea #---------------------------------------------------------------------------------- row += 1 guiFrame.grid_rowconfigure(row, weight=1) self.outputTextBox = ScrolledText(guiFrame) self.outputTextBox.grid(row=row, column=0, columnspan=2, sticky='nsew') self.redirectConsole() #---------------------------------------------------------------------------------- # Buttons #---------------------------------------------------------------------------------- row += 1 col = 0 texts = ['Quit', 'Help'] commands = [self.close, None] self.buttonBar = ButtonList(guiFrame, texts=texts, commands=commands, expands=True) self.buttonBar.grid(row=row, column=col, columnspan=2, sticky='ew') # self.openProjectButton = self.buttonBar.buttons[0] # self.closeProjectButton = self.buttonBar.buttons[1] # self.runButton = self.buttonBar.buttons[0] # self.viewResultButton = self.buttonBar.buttons[1] for button in self.buttonBar.buttons: button.config(**actionButtonAttributes) # end for # end def body def getGuiOptions(self): projectName = self.projEntry.get() index = self.projOptionsSelect.getIndex() if index > 0: makeNewProject = True projectImport = None if index > 1: i = index - 2 format = ['PDB', 'CCPN', 'CYANA'][i] file = [self.pdbEntry, self.ccpnEntry, self.cyanaEntry][i].get() if not file: showWarning('Failure', 'No %s file selected' % format) return # end if projectImport = (format, file) # end if else: # Chould also check that any old project file exists makeNewProject = False projectImport = None # end if doValidation = self.selectDoValidation.get() checks = [] if doValidation: if self.selectCheckAssign.get(): checks.append('assignments') # end if if self.selectCheckResraint.get(): checks.append('restraints') # end if if self.selectCheckStructure.get(): checks.append('structural') # end if if self.selectMakeHtml.get(): checks.append('HTML') # end if if self.selectCheckScript.get(): script = self.validScriptEntry.get() if script: checks.append(('script', script)) # end if # end if if self.selectCheckQueen.get(): checks.append('queen') # end if # end if exports = [] if self.selectExportXeasy.get(): exports.append('Xeasy') # end if if self.selectExportCcpn.get(): exports.append('CCPN') # end if if self.selectExportQueen.get(): exports.append('QUEEN') # end if if self.selectExportRefine.get(): exports.append('refine') # end if miscScript = None if self.selectMiscScript.get(): script = self.miscScriptEntry.get() if script: miscScript = script # end if # end if return projectName, makeNewProject, projectImport, doValidation, checks, exports, miscScript # end def getGuiOptions def runCing(self): options = self.getGuiOptions() if options: projectName, makeNewProject, projectImport, doValidation, checks, exports, miscScript = options print 'Project name:', projectName print 'Make new project?', makeNewProject print 'Import source:', projectImport print 'Do vailidation?', doValidation print 'Validation checks:', ','.join(checks) print 'Export to:', ','.join(exports) print 'User script:', miscScript # end if # end def runCing # else there was already an error message def chooseOldProjectFile(self): fileTypes = [FileType('CING', ['project.xml']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types=fileTypes, title='Select CING project file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() # dirName = popup.getDirectory() if len(fileName) > 0: # Put text into entry,name widgets dummy, name = cing.Project.rootPath(fileName) self.projEntry.configure(state='normal') self.projEntry.set(fileName) self.nameEntry.configure(state='normal') self.nameEntry.set(name) self.nameEntry.configure(state='disabled') # choose the correct radiobutton self.projOptionsSelect.setIndex(0) self.updateGui() # end if #nd if popup.destroy() # end def chooseOldProjectFile def choosePdbFile(self): fileTypes = [FileType('PDB', ['*.pdb']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types=fileTypes, title='PDB file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() if len(fileName) > 0: # Put text into entry widget self.pdbEntry.configure(state='normal') self.pdbEntry.set(fileName) # Put text into name widget _dir, name, dummy = nTpath(fileName) self.nameEntry.configure(state='normal') self.nameEntry.set(name) # choose the correct radiobutton self.projOptionsSelect.setIndex(1) self.updateGui() #end if popup.destroy() # end def choosePdbFile def chooseCcpnFile(self): fileTypes = [FileType('XML', ['*.xml']), FileType('All', ['*'])] popup = FileSelectPopup(self, file_types=fileTypes, title='CCPN project XML file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() if len(fileName) > 0: self.pdbEntry.configure(state='normal') self.pdbEntry.set(fileName) self.projOptionsSelect.setIndex(1) _dir, name, dummy = nTpath(fileName) self.nameEntry.set(name) #end if self.ccpnEntry.set(fileName) self.projOptionsSelect.setIndex(2) popup.destroy() # end def chooseCcpnFile def chooseCyanaFile(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types=fileTypes, title='CYANA fproject file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() self.cyanaEntry.set(fileName) self.projOptionsSelect.setIndex(3) popup.destroy() # end def chooseCyanaFile def chooseValidScript(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types=fileTypes, title='Script file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() self.validScriptEntry.set(fileName) popup.destroy() # end def chooseValidScript def chooseMiscScript(self): # Prepend default Cyana file extension below fileTypes = [ FileType('All', ['*']), ] popup = FileSelectPopup(self, file_types=fileTypes, title='Script file', dismiss_text='Cancel', selected_file_must_exist=True) fileName = popup.getFile() self.miscScriptEntry.set(fileName) popup.destroy() # end def chooseMiscScript def openProject(self): projOption = self.projOptionsSelect.get() if projOption == self.projectOptions[0]: self.openOldProject() elif projOption == self.projectOptions[1]: self.initPdb() # end if if self.project: self.project.gui = self # end if self.updateGui() #end def def openOldProject(self): fName = self.projEntry.get() if not os.path.exists(fName): nTerror('Error: file "%s" does not exist\n', fName) #end if if self.project: self.closeProject() # end if self.project = cing.Project.open(name=fName, status='old', verbose=False) #end def def initPdb(self): fName = self.pdbEntry.get() if not os.path.exists(fName): nTerror('Error: file "%s" does not exist\n', fName) #end if self.project = cing.Project.open(self.nameEntry.get(), status='new') self.project.initPDB(pdbFile=fName, convention='PDB') #end def def closeProject(self): if self.project: self.project.close() # end if self.project = None self.updateGui() #end def def updateGui(self, event=None): projOption = self.projOptionsSelect.get() buttons = self.buttonBar.buttons # Disable entries for e in [ self.projEntry, self.pdbEntry, self.ccpnEntry, self.cyanaEntry, self.nameEntry ]: e.configure(state='disabled') #end for if projOption == self.projectOptions[0]: # Enable entries self.projEntry.configure(state='normal') if (len(self.projEntry.get()) > 0): self.openProjectButton.enable() self.runButton.enable() else: self.openProjectButton.disable() self.runButton.disable() #end if elif projOption == self.projectOptions[1]: # Enable entries self.pdbEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.pdbEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if elif projOption == self.projectOptions[2]: # Enable entries self.ccpnEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.ccpnEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if elif projOption == self.projectOptions[3]: # Enable entries self.cyanaEntry.configure(state='normal') self.nameEntry.configure(state='normal') if (len(self.cyanaEntry.get()) > 0 and len(self.nameEntry.get()) > 0): buttons[0].enable() buttons[1].enable() else: buttons[0].disable() buttons[1].disable() #end if #end if self.projectStatus.clear() if not self.project: self.projectStatus.setText('No open project') self.closeProjectButton.setText('Close Project') self.closeProjectButton.disable() else: self.projectStatus.setText(self.project.format()) self.closeProjectButton.enable() self.closeProjectButton.setText( sprintf('Close Project "%s"', self.project.name)) #end if #end def def redirectConsole(self): #pipe = TextPipe(self.inputTextBox.text_area) #sys.stdin = pipe pipe = TextPipe(self.outputTextBox.text_area) sys.stdout = pipe nTmessage.stream = pipe # end def redirectConsole # sys.stderr = pipe def resetConsole(self): #sys.stdin = stdin nTmessage.stream = stdout sys.stdout = stdout sys.stderr = stderr # end def resetConsole def open(self): self.redirectConsole() BasePopup.open(self) # end def open def close(self): geometry = self.getGeometry() self.resetConsole() BasePopup.close(self) print 'close:', geometry sys.exit(0) # remove later # end def close def destroy(self): geometry = self.getGeometry() self.resetConsole() BasePopup.destroy(self) print 'destroy:', geometry sys.exit(0) # remove later
def body(self, guiFrame): guiFrame.grid_columnconfigure(0, weight=1) guiFrame.grid_rowconfigure(0, weight=1) options = ['Parameters','Restraints','Alignment Media & Tensors','About Meccano'] tabbedFrame = TabbedFrame(guiFrame, options=options) tabbedFrame.grid(row=0, column=0, sticky='nsew') frameA, frameB, frameC, frameD = tabbedFrame.frames frameA.grid_columnconfigure(1, weight=1) frameA.grid_rowconfigure(13, weight=1) frameB.grid_columnconfigure(1, weight=1) frameB.grid_rowconfigure(1, weight=1) frameC.grid_columnconfigure(0, weight=1) frameC.grid_rowconfigure(1, weight=1) frameD.grid_columnconfigure(0, weight=1) frameD.grid_rowconfigure(0, weight=1) texts = ['Run MECCANO!'] commands = [self.runMeccano] bottomButtons = createDismissHelpButtonList(guiFrame, texts=texts, commands=commands, expands=True) bottomButtons.grid(row=1, column=0, sticky='ew') if not Meccano: bottomButtons.buttons[0].disable() # Parameters row = 0 label = Label(frameA, text='Calculation Run:') label.grid(row=row,column=0,sticky='w') self.runPulldown = PulldownList(frameA, callback=self.selectRun) self.runPulldown.grid(row=row,column=1,sticky='w') row += 1 label = Label(frameA, text='Shift List (for CO):') label.grid(row=row,column=0,sticky='w') self.shiftListPulldown = PulldownList(frameA, callback=self.selectShiftList) self.shiftListPulldown.grid(row=row,column=1,sticky='w') row += 1 label = Label(frameA, text='Keep Copy of Used Shifts:') label.grid(row=row,column=0,sticky='w') self.toggleCopyShifts = CheckButton(frameA) self.toggleCopyShifts.grid(row=row,column=1,sticky='w') self.toggleCopyShifts.set(True) row += 1 label = Label(frameA, text='Molecular System:') label.grid(row=row,column=0,sticky='w') self.molSystemPulldown = PulldownList(frameA, callback=self.selectMolSystem) self.molSystemPulldown.grid(row=row,column=1,sticky='w') row += 1 label = Label(frameA, text='Chain:') label.grid(row=row,column=0,sticky='w') self.chainPulldown = PulldownList(frameA, callback=self.selectChain) self.chainPulldown.grid(row=row,column=1,sticky='w') self.chainPulldown.bind('<Leave>', self.updateRunParams) row += 1 label = Label(frameA, text='First Peptide Plane:') label.grid(row=row,column=0,sticky='w') self.firstResEntry = IntEntry(frameA, text=None, width=8) self.firstResEntry.grid(row=row,column=1,sticky='w') self.firstResEntry.bind('<Leave>', self.updateRunParams) row += 1 label = Label(frameA, text='Last Peptide Plane:') label.grid(row=row,column=0,sticky='w') self.lastResEntry = IntEntry(frameA, text=None, width=8) self.lastResEntry.grid(row=row,column=1,sticky='w') self.lastResEntry.bind('<Leave>', self.updateRunParams) row += 1 label = Label(frameA, text='Max Num Optimisation Steps:') label.grid(row=row,column=0,sticky='w') self.maxOptStepEntry = IntEntry(frameA, text=500, width=8) self.maxOptStepEntry.grid(row=row,column=1,sticky='w') self.maxOptStepEntry.bind('<Leave>', self.updateRunParams) row += 1 label = Label(frameA, text='Num Optimisation Peptide Planes:') label.grid(row=row,column=0,sticky='w') self.numOptPlaneEntry = IntEntry(frameA, text=2, width=8) self.numOptPlaneEntry.grid(row=row,column=1,sticky='w') self.numOptPlaneEntry.bind('<Leave>', self.updateRunParams) row += 1 label = Label(frameA, text='Min Num Optimisation Hits:') label.grid(row=row,column=0,sticky='w') self.numOptHitsEntry = IntEntry(frameA, text=5, width=8) self.numOptHitsEntry.grid(row=row,column=1,sticky='w') self.numOptHitsEntry.bind('<Leave>', self.updateRunParams) row += 1 label = Label(frameA, text='File Name Prefix:') label.grid(row=row,column=0,sticky='w') self.pdbFileEntry = Entry(frameA, text='Meccano', width=8) self.pdbFileEntry.grid(row=row,column=1,sticky='w') self.pdbFileEntry.bind('<Leave>', self.updateRunParams) row += 1 label = Label(frameA, text='Write Output File (.out):') label.grid(row=row,column=0,sticky='w') self.toggleWriteOutFile = CheckButton(frameA) self.toggleWriteOutFile.grid(row=row,column=1,sticky='w') self.toggleWriteOutFile.set(False) self.toggleWriteOutFile.bind('<Leave>', self.updateRunParams) row += 1 label = Label(frameA, text='Write PDB File (.pdb):') label.grid(row=row,column=0,sticky='w') self.toggleWritePdbFile = CheckButton(frameA) self.toggleWritePdbFile.grid(row=row,column=1,sticky='w') self.toggleWritePdbFile.set(True) self.toggleWritePdbFile.bind('<Leave>', self.updateRunParams) if not Meccano: row += 1 label = Label(frameA, text='The Meccano executable is not available (it needs to be compiled)', fg='red') label.grid(row=row,column=0,columnspan=2,sticky='w') # Restraints label = Label(frameB, text='Constraint Set:') label.grid(row=0,column=0,sticky='w') self.constraintSetPulldown = PulldownList(frameB, callback=self.selectConstraintSet) self.constraintSetPulldown.grid(row=0,column=1,sticky='w') self.alignMediumPulldown= PulldownList(self, callback=self.setAlignMedium) headingList = ['#','List Type','Use?','Alignment\nMedium','Num\nRestraints'] editWidgets = [None,None,None,self.alignMediumPulldown,None] editGetCallbacks = [None,None,self.toggleUseRestraints,self.getAlignMedium,None] editSetCallbacks = [None,None,None,self.setAlignMedium,None] self.restraintMatrix = ScrolledMatrix(frameB, headingList=headingList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, callback=None, multiSelect=True) self.restraintMatrix.grid(row=1,column=0,columnspan=2,sticky='nsew') # Alignment Media div = LabelDivider(frameC,text='Alignment Media') div.grid(row=0,column=0,sticky='ew') self.mediumNameEntry = Entry(self, returnCallback=self.setMediumName) self.mediumDetailsEntry = Entry(self, returnCallback=self.setMediumDetails) headingList = ['#','Name','Details','Static Tensor','Dynamic Tensor'] editWidgets = [None, self.mediumNameEntry, self.mediumDetailsEntry, None, None] editGetCallbacks = [None, self.getMediumName, self.getMediumDetails, None, None] editSetCallbacks = [None, self.setMediumName, self.setMediumDetails, None, None] self.mediaMatrix = ScrolledMatrix(frameC, headingList=headingList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, callback=self.selectAlignMedium, multiSelect=True) self.mediaMatrix.grid(row=1,column=0,sticky='nsew') texts = ['Add Alignment medium','Remove Alignment Medium'] commands = [self.addAlignMedium,self.removeAlignMedium] buttonList = ButtonList(frameC, texts=texts, commands=commands, expands=True) buttonList.grid(row=2,column=0,sticky='nsew') self.editAxialEntry = FloatEntry(self, returnCallback=self.setAxial) self.editRhombicEntry = FloatEntry(self, returnCallback=self.setRhombic) self.editAlphaEulerEntry = FloatEntry(self, returnCallback=self.setEulerAlpha) self.editBetaEulerEntry = FloatEntry(self, returnCallback=self.setEulerBeta) self.editGammaEulerEntry = FloatEntry(self, returnCallback=self.setEulerGamma) div = LabelDivider(frameC,text='Alignment Tensors') div.grid(row=3,column=0,sticky='ew') headingList = ['Type', u'Axial (\u03B6)',u'Rhombic (\u03B7)', u'Euler \u03B1',u'Euler \u03B2',u'Euler \u03B3'] editWidgets = [None,self.editAxialEntry, self.editRhombicEntry,self.editAlphaEulerEntry, self.editBetaEulerEntry,self.editGammaEulerEntry] editSetCallbacks = [None,self.setAxial,self.setRhombic, self.setEulerAlpha,self.setEulerBeta,self.setEulerGamma] editGetCallbacks = [None,self.getAxial,self.getRhombic, self.getEulerAlpha,self.getEulerBeta,self.getEulerGamma] self.tensorMatrix = ScrolledMatrix(frameC, maxRows=2, headingList=headingList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, callback=self.selectTensor, multiSelect=True) self.tensorMatrix.grid(row=4,column=0,sticky='nsew') texts = ['Add Static Tensor','Add Dynamic Tensor','Remove Tensor'] commands = [self.addStaticTensor,self.addDynamicTensor,self.removeTensor] buttonList = ButtonList(frameC,texts=texts, commands=commands, expands=True) buttonList.grid(row=5,column=0,sticky='ew') # About label = Label(frameD, text='About Meccano...') label.grid(row=0,column=0,sticky='w') # self.geometry('500x400') self.updateShiftLists() self.updateMolSystems() self.updateResidueRanges() self.updateConstraintSets() self.updateAlignMedia() self.updateRuns()
def body(self, guiFrame): row = 0 col = 0 # frame = Frame( guiFrame ) # frame.grid(row=row, column=col, sticky='news') self.menuBar = Menu(guiFrame) self.menuBar.grid(row=row, column=col, sticky='ew') #---------------------------------------------------------------------------------- # Project frame #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(row, weight=1) # frame = LabelFrame(guiFrame, text='Project', font=medFont) row = +1 col = 0 frame = LabelFrame(guiFrame, text='Project', **labelFrameAttributes) print '>', frame.keys() frame.grid(row=row, column=col, sticky='nsew') frame.grid_columnconfigure(2, weight=1) # frame.grid_rowconfigure(0, weight=1) srow = 0 self.projectOptions = [ 'old', 'new from PDB', 'new from CCPN', 'new from CYANA' ] self.projOptionsSelect = RadioButtons(frame, selected_index=0, entries=self.projectOptions, direction='vertical', select_callback=self.updateGui) self.projOptionsSelect.grid(row=srow, column=0, rowspan=len(self.projectOptions), columnspan=2, sticky='w') if self.options.name: text = self.options.name else: text = '' # end if self.projEntry = Entry(frame, bd=1, text=text, returnCallback=self.updateGui) self.projEntry.grid(row=srow, column=2, columnspan=2, sticky='ew') # self.projEntry.bind('<Key>', self.updateGui) self.projEntry.bind('<Leave>', self.updateGui) projButton = Button(frame, bd=1, command=self.chooseOldProjectFile, text='browse') projButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.pdbEntry = Entry(frame, bd=1, text='') self.pdbEntry.grid(row=srow, column=2, sticky='ew') self.pdbEntry.bind('<Leave>', self.updateGui) pdbButton = Button(frame, bd=1, command=self.choosePdbFile, text='browse') pdbButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.ccpnEntry = Entry(frame, bd=1, text='') self.ccpnEntry.grid(row=srow, column=2, sticky='ew') self.ccpnEntry.bind('<Leave>', self.updateGui) ccpnButton = Button(frame, bd=1, command=self.chooseCcpnFile, text='browse') ccpnButton.grid(row=srow, column=3, sticky='ew') srow += 1 self.cyanaEntry = Entry(frame, bd=1, text='') self.cyanaEntry.grid(row=srow, column=2, sticky='ew') self.cyanaEntry.bind('<Leave>', self.updateGui) cyanaButton = Button(frame, bd=1, command=self.chooseCyanaFile, text='browse') cyanaButton.grid(row=srow, column=3, sticky='ew') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 label = Label(frame, text='Project name:') label.grid(row=srow, column=0, sticky='nw') self.nameEntry = Entry(frame, bd=1, text='') self.nameEntry.grid(row=srow, column=2, sticky='w') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 self.openProjectButton = Button(frame, command=self.openProject, text='Open Project', **actionButtonAttributes) self.openProjectButton.grid(row=srow, column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # status #---------------------------------------------------------------------------------- # guiFrame.grid_columnconfigure(1, weight=0) srow = 0 frame = LabelFrame(guiFrame, text='Status', **labelFrameAttributes) frame.grid(row=srow, column=1, sticky='wnes') self.projectStatus = Text(frame, height=11, width=70, borderwidth=0, relief='flat') self.projectStatus.grid(row=0, column=0, sticky='wen') #Empty row srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') srow += 1 self.closeProjectButton = Button(frame, command=self.closeProject, text='Close Project', **actionButtonAttributes) self.closeProjectButton.grid(row=srow, column=0, columnspan=4, sticky='ew') #---------------------------------------------------------------------------------- # Validate frame #---------------------------------------------------------------------------------- row += 1 col = 0 frame = LabelFrame(guiFrame, text='Validate', **labelFrameAttributes) # frame = LabelFrame(guiFrame, text='Validate', font=medFont) frame.grid(row=row, column=col, sticky='nsew') # frame.grid_columnconfigure(2, weight=1) frame.grid_rowconfigure(0, weight=1) srow = 0 # label = Label(frame, text='validation') # label.grid(row=srow,column=0,sticky='nw') # # self.selectDoValidation = CheckButton(frame) # self.selectDoValidation.grid(row=srow, column=1,sticky='nw' ) # self.selectDoValidation.set(True) # # srow += 1 # label = Label(frame, text='') # label.grid(row=srow,column=0,sticky='nw') # # srow += 1 label = Label(frame, text='checks') label.grid(row=srow, column=0, sticky='nw') self.selectCheckAssign = CheckButton(frame) self.selectCheckAssign.grid(row=srow, column=1, sticky='nw') self.selectCheckAssign.set(True) label = Label(frame, text='assignments and shifts') label.grid(row=srow, column=2, sticky='nw') # srow += 1 # self.selectCheckQueen = CheckButton(frame) # self.selectCheckQueen.grid(row=srow, column=4,sticky='nw' ) # self.selectCheckQueen.set(False) # label = Label(frame, text='QUEEN') # label.grid(row=srow,column=5,sticky='nw') # # queenButton = Button(frame, bd=1,command=None, text='setup') # queenButton.grid(row=srow,column=6,sticky='ew') srow += 1 self.selectCheckResraint = CheckButton(frame) self.selectCheckResraint.grid(row=srow, column=1, sticky='nw') self.selectCheckResraint.set(True) label = Label(frame, text='restraints') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectCheckStructure = CheckButton(frame) self.selectCheckStructure.grid(row=srow, column=1, sticky='nw') self.selectCheckStructure.set(True) label = Label(frame, text='structural') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectMakeHtml = CheckButton(frame) self.selectMakeHtml.grid(row=srow, column=1, sticky='nw') self.selectMakeHtml.set(True) label = Label(frame, text='generate HTML') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectCheckScript = CheckButton(frame) self.selectCheckScript.grid(row=srow, column=1, sticky='nw') self.selectCheckScript.set(False) label = Label(frame, text='user script') label.grid(row=srow, column=0, sticky='nw') self.validScriptEntry = Entry(frame, bd=1, text='') self.validScriptEntry.grid(row=srow, column=2, columnspan=3, sticky='ew') scriptButton = Button(frame, bd=1, command=self.chooseValidScript, text='browse') scriptButton.grid(row=srow, column=5, sticky='ew') srow += 1 label = Label(frame, text='ranges') label.grid(row=srow, column=0, sticky='nw') self.rangesEntry = Entry(frame, text='') self.rangesEntry.grid(row=srow, column=2, columnspan=3, sticky='ew') # self.validScriptEntry = Entry(frame, bd=1, text='') # self.validScriptEntry.grid(row=srow,column=3,sticky='ew') # # scriptButton = Button(frame, bd=1,command=self.chooseValidScript, text='browse') # scriptButton.grid(row=srow,column=4,sticky='ew') srow += 1 texts = ['Run Validation', 'View Results', 'Setup QUEEN'] commands = [self.runCing, None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands, expands=True) buttonBar.grid(row=srow, column=0, columnspan=6, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.runButton = buttonBar.buttons[0] self.viewResultButton = buttonBar.buttons[1] self.queenButton = buttonBar.buttons[2] #---------------------------------------------------------------------------------- # Miscellaneous frame #---------------------------------------------------------------------------------- row += 0 col = 1 # frame = LabelFrame(guiFrame, text='Miscellaneous', font=medFont) frame = LabelFrame(guiFrame, text='Miscellaneous', **labelFrameAttributes) frame.grid(row=row, column=col, sticky='news') frame.grid_columnconfigure(2, weight=1) frame.grid_columnconfigure(4, weight=1, minsize=30) frame.grid_rowconfigure(0, weight=1) # Exports srow = 0 label = Label(frame, text='export to') label.grid(row=srow, column=0, sticky='nw') self.selectExportXeasy = CheckButton(frame) self.selectExportXeasy.grid(row=srow, column=1, sticky='nw') self.selectExportXeasy.set(True) label = Label(frame, text='Xeasy, Sparky, TALOS, ...') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportCcpn = CheckButton(frame) self.selectExportCcpn.grid(row=srow, column=1, sticky='nw') self.selectExportCcpn.set(True) label = Label(frame, text='CCPN') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportQueen = CheckButton(frame) self.selectExportQueen.grid(row=srow, column=1, sticky='nw') self.selectExportQueen.set(True) label = Label(frame, text='QUEEN') label.grid(row=srow, column=2, sticky='nw') srow += 1 self.selectExportRefine = CheckButton(frame) self.selectExportRefine.grid(row=srow, column=1, sticky='nw') self.selectExportRefine.set(True) label = Label(frame, text='refine') label.grid(row=srow, column=2, sticky='nw') srow += 1 label = Label(frame, text='') label.grid(row=srow, column=0, sticky='nw') # User script srow += 1 label = Label(frame, text='user script') label.grid(row=srow, column=0, sticky='nw') self.selectMiscScript = CheckButton(frame) self.selectMiscScript.grid(row=srow, column=1, sticky='nw') self.selectMiscScript.set(False) self.miscScriptEntry = Entry(frame, bd=1, text='') self.miscScriptEntry.grid(row=srow, column=3, sticky='ew') script2Button = Button(frame, bd=1, command=self.chooseMiscScript, text='browse') script2Button.grid(row=srow, column=4, sticky='ew') srow += 1 texts = ['Export', 'Run Script'] commands = [None, None] buttonBar = ButtonList(frame, texts=texts, commands=commands, expands=True) buttonBar.grid(row=srow, column=0, columnspan=5, sticky='ew') for button in buttonBar.buttons: button.config(**actionButtonAttributes) # end for self.exportButton = buttonBar.buttons[0] self.scriptButton = buttonBar.buttons[1] #---------------------------------------------------------------------------------- # Textarea #---------------------------------------------------------------------------------- row += 1 guiFrame.grid_rowconfigure(row, weight=1) self.outputTextBox = ScrolledText(guiFrame) self.outputTextBox.grid(row=row, column=0, columnspan=2, sticky='nsew') self.redirectConsole() #---------------------------------------------------------------------------------- # Buttons #---------------------------------------------------------------------------------- row += 1 col = 0 texts = ['Quit', 'Help'] commands = [self.close, None] self.buttonBar = ButtonList(guiFrame, texts=texts, commands=commands, expands=True) self.buttonBar.grid(row=row, column=col, columnspan=2, sticky='ew') # self.openProjectButton = self.buttonBar.buttons[0] # self.closeProjectButton = self.buttonBar.buttons[1] # self.runButton = self.buttonBar.buttons[0] # self.viewResultButton = self.buttonBar.buttons[1] for button in self.buttonBar.buttons: button.config(**actionButtonAttributes)
class HelpFrame(Frame): def __init__(self, parent, width=70, height=20, xscroll=False, yscroll=True, *args, **kw): apply(Frame.__init__, (self, parent) + args, kw) self.grid_columnconfigure(1, weight=1) row = 0 texts = ('back', 'forward', 'load') commands = (self.prevUrl, self.nextUrl, self.loadUrl) self.buttons = ButtonList(self, texts=texts, commands=commands) self.buttons.grid(row=row, column=0) self.url_entry = Entry(self, returnCallback=self.loadUrl) self.url_entry.grid(row=row, column=1, columnspan=2, sticky=Tkinter.EW) row = row + 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=3, sticky=Tkinter.W) self.createFindFrame(frame) row = row + 1 self.grid_rowconfigure(row, weight=1) self.help_text = ScrolledHtml(self, width=width, height=height, xscroll=xscroll, yscroll=yscroll, startUrlCallback=self.startOpenUrl, endUrlCallback=self.endOpenUrl, enterLinkCallback=self.setLinkLabel, leaveLinkCallback=self.setLinkLabel) self.help_text.grid(row=row, column=0, columnspan=3, sticky=Tkinter.NSEW) row = row + 1 self.link_label = Label(self) self.link_label.grid(row=row, column=0, columnspan=2, sticky=Tkinter.W) button = memops.gui.Util.createDismissButton(self, dismiss_cmd=self.close) button.grid(row=row, column=2) self.urls = [] self.current = -1 self.updateUrlList = True self.setButtonState() def close(self): if (self.popup): if (self.popup.modal): self.popup.do_grab() popup = self.parent while (not hasattr(popup, 'top')): popup = popup.parent popup.close() def createFindFrame(self, master): frame = Frame(master) frame.grid(row=0, column=0, sticky=Tkinter.W) arrow = ToggleArrow(frame, callback=self.toggleFindFrame) arrow.grid(row=0, column=0) button = Button(frame, text='find:', command=self.findPhrase) button.grid(row=0, column=1) self.find_entry = Entry(frame, width=20, returnCallback=self.findPhrase) self.find_entry.grid(row=0, column=2) self.find_frame = frame = Frame(master) entries = ('search forwards', 'search backwards') self.direction_buttons = PulldownMenu(frame, entries=entries) self.direction_buttons.grid(row=0, column=0, sticky=Tkinter.W, padx=5) self.forwards_entries = entries = ('wrap search', 'stop at end') self.backwards_entries = ('wrap search', 'stop at beginning') self.wrap_buttons = PulldownMenu(frame, entries=entries) self.wrap_buttons.grid(row=0, column=1, sticky=Tkinter.W, padx=5) self.direction_buttons.callback = self.setWrapText entries = ('case insensitive', 'case sensitive') self.case_buttons = PulldownMenu(frame, entries=entries) self.case_buttons.grid(row=0, column=2, sticky=Tkinter.W, padx=5) entries = ('literal search', 'regex search') self.pattern_buttons = PulldownMenu(frame, entries=entries) self.pattern_buttons.grid(row=0, column=3, sticky=Tkinter.W, padx=5) self.countVar = Tkinter.IntVar() def setWrapText(self, entry_ind, entry): if (entry_ind == 0): entries = self.forwards_entries else: entries = self.backwards_entries self.wrap_buttons.replace( entries, selected_index=self.wrap_buttons.getSelectedIndex()) def findPhrase(self, *extra): phrase = self.find_entry.get() if (not phrase): showError('No find phrase', 'Enter phrase in entry box.') return if (self.direction_buttons.getSelectedIndex() == 0): forwards = 1 backwards = 0 else: forwards = 0 backwards = 1 if (self.case_buttons.getSelectedIndex() == 0): nocase = 1 else: nocase = 0 if (self.pattern_buttons.getSelectedIndex() == 0): exact = 1 regexp = 0 else: exact = 0 regexp = 1 start = self.help_text.tag_nextrange(Tkinter.SEL, '1.0') if (start): start = start[0] if (forwards): start = '%s+1c' % start else: start = '%s-1c' % start else: start = Tkinter.CURRENT if (self.wrap_buttons.getSelectedIndex() == 0): match = self.help_text.search(phrase, start, count=self.countVar, forwards=forwards, backwards=backwards, nocase=nocase, exact=exact, regexp=regexp) elif (forwards): match = self.help_text.search(phrase, start, count=self.countVar, forwards=forwards, backwards=backwards, nocase=nocase, exact=exact, regexp=regexp, stopindex=Tkinter.END) else: match = self.help_text.search(phrase, start, count=self.countVar, forwards=forwards, backwards=backwards, nocase=nocase, exact=exact, regexp=regexp, stopindex='1.0') if (match): self.help_text.see(match) self.help_text.setSelection( match, '%s+%dc' % (match, self.countVar.get())) self.help_text.tag_config(Tkinter.SEL, background='gray70') else: showInfo('No match', 'No match found for phrase.') def toggleFindFrame(self, isClosed): if (isClosed): self.find_frame.grid_forget() else: self.find_frame.grid(row=1, column=0, sticky=Tkinter.W) def setButtonState(self): n = len(self.urls) if ((n >= 2) and (self.current > 0)): state = Tkinter.NORMAL else: state = Tkinter.DISABLED self.buttons.buttons[0].config(state=state) if ((n >= 2) and (self.current < (n - 1))): state = Tkinter.NORMAL else: state = Tkinter.DISABLED self.buttons.buttons[1].config(state=state) def setLinkLabel(self, url=''): self.link_label.set(url) def loadUrl(self, *extra): url = self.url_entry.get() if (url): if (url.find(':') == -1): if (url[:2] != '//'): url = '//' + url url = 'http:' + url self.showUrl(url, forceLoad=True) def newUrl(self, url): self.current = self.current + 1 self.urls[self.current:] = [[url, 0.0]] self.setButtonState() #print 'newUrl', self.current, self.urls def prevUrl(self): if (self.current > 0): # True if called via button (url, offset) = self.urls[self.current - 1] self.updateUrlList = False self.showUrl(url, offset=offset, allowModifyPath=False) self.updateUrlList = True self.current = self.current - 1 self.setButtonState() #print 'prevUrl', self.current, self.urls def nextUrl(self): if (self.current < (len(self.urls) - 1)): # True if called via button (url, offset) = self.urls[self.current + 1] self.updateUrlList = False self.showUrl(url, offset=offset, allowModifyPath=False) self.updateUrlList = True self.current = self.current + 1 self.setButtonState() #print 'nextUrl', self.current, self.urls def showText(self, message, popup=None): self.popup = popup if (popup): self.parent.modal = popup.modal self.help_text.setState(Tkinter.NORMAL) # so that can add text self.help_text.clear() # clear existing text self.help_text.append(message) self.help_text.setState(Tkinter.DISABLED) # make text read-only self.open() def startOpenUrl(self, yview): if (self.urls): self.urls[self.current][1] = yview[0] def endOpenUrl(self, url): #print 'endOpenUrl', url, self.updateUrlList self.url_entry.set(url) if (self.updateUrlList): self.newUrl(url) self.setLinkLabel() self.open() def showUrl(self, url, offset=None, forceLoad=False, allowModifyPath=True, popup=None): self.popup = popup if (popup): self.parent.modal = popup.modal self.help_text.openUrl(url, forceLoad=forceLoad, allowModifyPath=allowModifyPath) if (offset is not None): self.help_text.yview(Tkinter.MOVETO, str(offset))
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()
class SaveLoadTab(object): '''The tab that lets the user FileSelect a file to open or to save. ''' 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.loadAndSaveButtons = None self.fileselectionBox = None self.body() def body(self): '''Setting up the body of this view.''' frame = self.frame file_types = [FileType('pyc', ['*.pyc'])] self.fileselectionBox = FileSelect(frame, multiSelect=False, file_types=file_types) self.fileselectionBox.grid(row=0, column=0, columnspan=6, sticky='nsew') texts = ['Load', 'Save'] commands = [self.loadDataFromPyc, self.saveDataToPyc] self.loadAndSaveButtons = ButtonList(frame, commands=commands, texts=texts) self.loadAndSaveButtons.grid(row=1, column=0, sticky='nsew') frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) def saveDataToPyc(self): '''Save the data to the selected file.''' if self.guiParent.connector.results: fileName = self.fileselectionBox.getFile() self.guiParent.connector.saveDataToPyc(fileName) self.fileselectionBox.updateFileList() else: string = ('''There are no results to save, ''' '''the algorithm has not run yet.''') showWarning('No Results to Save', string, parent=self.guiParent) def loadDataFromPyc(self): '''Load the data from the selected file.''' fileName = self.fileselectionBox.getFile() self.guiParent.connector.loadDataFromPyc(fileName) self.guiParent.resultsTab.update()
class RepositoryFrame(Frame): def __init__(self, guiParent, basePopup): # Base popup required to handle notification of data model changes # e.g. new peak lists, so that the GUI can update to the latest # state self.basePopup = basePopup self.guiParent = guiParent # should the screen autorefresh self.autoRefresh = False # add this to shortcuts to ease navigation self.basePopup.frameShortcuts['Repository'] = self # get a port proxy instance # this should probably belong to the repository directly # or else should belong in a dictionary in the main gui # layer when it can be picked up easily # FIXME JMCI # need to work out how to get a number of these! loc = SharedBeanServiceLocator() self.port = loc.getSharedBean() self.registerNotify = basePopup.registerNotify self.unregisterNotify = basePopup.unregisterNotify Frame.__init__(self, guiParent) # set up the grid self.grid_columnconfigure(0, weight=0, minsize=20) self.grid_columnconfigure(1, weight=1, minsize=10) self.grid_columnconfigure(2, weight=0, minsize=20) self.grid_rowconfigure(0, weight=0, minsize=5) self.grid_rowconfigure(1, weight=0, minsize=0) self.grid_rowconfigure(2, weight=0, minsize=10) self.grid_rowconfigure(3, weight=0, minsize=10) self.grid_rowconfigure(4, weight=0, minsize=10) self.grid_rowconfigure(5, weight=1, minsize=10) self.grid_rowconfigure(6, weight=0, minsize=10) self.grid_rowconfigure(7, weight=0, minsize=10) # widgets for view when no data self.noDataWidgets = [] self.noRepLabel = Label(self, text='No repository currently selected.') self.noDataWidgets.append(self.noRepLabel) # widgets for view when current repository set self.dataWidgets = [] self.repTitle = Label(self, text='Repository:', font='Helvetica16') self.dataWidgets.append(self.repTitle) #self.repLabel = Label(self,text='All Projects in Repository') #self.dataWidgets.append(self.repLabel) self.repTree = Tree(self, doubleCallback=self.goto_project_tab) self.dataWidgets.append(self.repTree) sel = 1 if self.autoRefresh: sel = 0 self.autoRefreshSwitchLabel = Label(self, text='Auto Refresh') self.autoRefreshSwitch = RadioButtons(self, ['on', 'off'], select_callback=self.set_refresh, selected_index=sel) # need to decide whether this is static or not r_button_texts = [ 'Add to Basket', ' Import ', ' Export ', ' Refresh ', 'Properties' ] r_button_cmds = [ self.tmpCall, self.import_project, self.export_project, self.drawFrame, self.goto_project_tab ] self.rep_button_list = ButtonList(self, r_button_texts, r_button_cmds) self.dataWidgets.append(self.rep_button_list) self.filterFrame = FilterFrame(self, self.basePopup, text='Filter') self.dataWidgets.append(self.filterFrame) baskets = ('basket1', 'basket2', 'basket3') self.basketSelect = PulldownList(self, self.tmpCall, baskets) self.dataWidgets.append(self.basketSelect) basketElements = ('1ay3', '1ay7') self.basketList = ScrolledListbox(self, basketElements, 25, 18) self.dataWidgets.append(self.basketList) b_button_texts = ['Remove from Basket', 'New Basket'] b_button_cmds = [self.tmpCall, self.tmpCall] self.b_button_list = ButtonList(self, b_button_texts, b_button_cmds) self.dataWidgets.append(self.b_button_list) # draw if not automatically refreshing if sel == 1: self.drawFrame() # set up a loop self.refresh() def drawFrame(self): if self.basePopup.repList.currentRepository == None: for widget in self.dataWidgets: widget.grid_remove() self.noRepLabel.grid(row=1, column=1, sticky='n') else: self.repository = self.basePopup.repList.currentRepository for widget in self.noDataWidgets: widget.grid_remove() # Column headers # want to have a general admin panel; current repository, button to change, info # about login and so on self.repTitle.set('Repository: ' + self.repository.user + '@' + self.repository.name + ' ( ' + self.repository.connect + ' )') self.repTitle.grid(row=1, column=1, sticky='w') # self.repLabel.grid(row=2, column=1, sticky='w') # Repository block #grid and update self.repTree.grid(row=3, column=1, rowspan=3, sticky='nsew') self.updateRepTree() self.autoRefreshSwitchLabel.grid(row=6, column=1, padx=10, sticky='w') self.autoRefreshSwitch.grid(row=6, column=1, padx=10, sticky='e') # the buttons for functionality in repository area self.rep_button_list.grid(row=7, column=1, padx=3, sticky='ew') # filter frame self.filterFrame.grid(row=3, column=2, stick='nsew') # list of baskest. Will callback to change current basket self.basketSelect.grid(row=4, column=2, padx=10, stick='w') # lists projects per basket self.basketList.grid(row=5, rowspan=2, column=2, padx=10, stick='nsew') self.b_button_list.grid(row=7, column=2, padx=5, stick='ew') def openLink(self, node): tree = node.tree par = node.object # this should be associated with the repository object request = getList() # FIXME JMCI # 1. Potentially need to traverse up the node tree # 2. Currently there is bug in expansion/contraction # 3. Search needs to work off proxy method (not off # generated stubs # pass the parent name for now. may need other criteria later h1 = {'name': par.__str__()} h2 = {'project': h1} wsstr_in = WSString(h2) request._arg0 = 'org.pimslims.applet.server.ProjectVersionBean' request._arg1 = 'getListWithFields' request._arg2 = wsstr_in.str # get the response response = self.port.getList(request) # currently we just get a list of numbers. May want to send # all the fields for every object too to cut down on db calls wsstr_out = WSString(response._return) ss = wsstr_out.getStruct() for hm in ss: print 'handling ', hm, ', ', hm['status'].__str__() #if hm['status'].__str__() == 'AVAILABLE': icon = 'text-x-generic' #else: # icon='emblem-readonly' pv = par.__str__() + '::' + hm['versionTag'].__str__() obj = pv text = hm['versionTag'].__str__() callback = None tree.add(node, obj, text, icon, callback) def set_refresh(self, text): print 'setting refresh ', text if text == 'on': self.autoRefresh = True else: self.autoRefresh = False def refresh(self): if self.autoRefresh: print 'refreshing frame ', time.time() self.drawFrame() self.after(5000, self.refresh) # FIME JMCI # it would probably be a good idea to have a method that allowed # a user to unlock a given project version. Would need to check # permissions very carefully, though def unlock_project_version(self): pass def goto_project_tab(self, node=None): if node is None: # get the selected node selected_nodes = self.repTree.getSelectedNodes() # restrict the choice to one node = selected_nodes[0] # we really need to traverse the tree a lot more carefully pv = node.object.__str__() print 'GOTO PROJECT ', pv, ', ', node, ', ', node.object pat = re.compile('::') matcher = pat.search(pv, 0) name = pv[0:matcher.start()] versionTag = pv[matcher.end():] print 'GOTO PROJECT ', name, ', ', versionTag #versionTag = node.object.__str__() #name = node.parent.object.__str__() #print node.__dict__ #print node.parent.__dict__ self.basePopup.repList.currentRepository.currentProjectName = name self.basePopup.repList.currentRepository.currentVersionTag = versionTag # this is going to have to be keyed on a natural key that then # gets set into the criteria of a ws query # hack for now. build in later. Essentially, we have to handle two # cases; that of a specific projectVersion request and that of a # request on a project alone. Probably the best behaviour would be # for the project-only request to default to the latest trunk # version of the project and the most elegent way of triggering # this would probably be to have this as a property of the project # returned in the main hash from Project.getFields(). self.basePopup.tabbedFrame.select(1) if self.basePopup.frameShortcuts.has_key('Project'): self.basePopup.frameShortcuts['Project'].drawFrame() def import_project(self): # FIXME JMCI # need to preserve the current status. Take default from the # Wms layer rootDir = self.basePopup.repList.current_import_dir fileSelectPopup = FileSelectPopup(self, None, rootDir) new_project_dir = fileSelectPopup.getDirectory() self.basePopup.repList.current_import_dir = new_project_dir print 'in import project with directory', new_project_dir idx = new_project_dir.rfind('/') new_project_name = new_project_dir[idx + 1:] print 'in import project with project', new_project_name # FIXME # need to set the project version number somewhere. For now set to none # and this gets picked up and set to a default 1.1 later self.repository.import_project(new_project_name, None, new_project_dir) self.drawFrame() def export_project(self): # get the selected node selected_nodes = self.repTree.getSelectedNodes() # restrict the choice to one node = selected_nodes[0] # we really need to traverse the tree a lot more carefully name = node.parent.object.__str__() versionTag = node.object.__str__()[len(name) + 2:] # need to preserve the current status. Take a default from the # Wms layer rootDir = self.basePopup.repList.current_export_dir # This should be obtained from a query box. Hard code for now fileSelectPopup = FileSelectPopup(self, None, rootDir) exp_project_dir = fileSelectPopup.getDirectory() self.basePopup.repList.current_export_dir = exp_project_dir self.repository.export_project(name, versionTag, exp_project_dir) def disconnectRepository(self): # do we need to formally break a connection and destroy the session? # yes we probably should. # need an "are you sure" dialog box # need to protect self.repository.repList.repositories.remove(self.repository) self.grid_remove() for ff in self.guiParent.guiParent.parent.frames[0].children.values(): ff.drawFrame() def tmpCall(self): return # This will need a separate call to the WS with an additional # criterion (picking up the checkout version) def updateRepTree(self): texts = [] icons = [] parents = [] callbacks = [] objects = [] # OK, this would be a good point to access the list # this should be associated with the repository object loc = SharedBeanServiceLocator() port = loc.getSharedBean() request = getList() # these are actually static request._arg0 = 'org.pimslims.applet.server.ProjectBean' request._arg1 = 'getList' request._arg2 = '' # get the response response = port.getList(request) # this is a hack at present. It needs to be written properly wsstr = WSString(response._return) ss = wsstr.getStruct() for strg in ss: texts.append(strg) icons.append('folder') parents.append(None) objects.append(strg) callbacks.append(self.openLink) print 'UPDATE ', ss print 'UPDATE ', len(ss) if len(ss) > 0: print 'UPDATE: updating ' self.repTree.update(parents, objects, texts, icons, callbacks) def administerNotifiers(self, notifyFunc): for func in ('__init__', 'delete', 'setName'): notifyFunc(self.updateAllAfter, 'ccp.nmr.Nmr.Experiment', func) notifyFunc(self.updateAllAfter, 'ccp.nmr.Nmr.DataSource', func) def updateAllAfter(self, obj): self.after_idle(self.updateAll) def updateAll(self, project=None): return def quit(self): self.guiParent.parent.destroy() def destroy(self): self.administerNotifiers(self.basePopup.unregisterNotify) Frame.destroy(self)
class WorkflowFrame(Frame): def __init__(self, guiParent, basePopup): # Base popup required to handle notification of data model changes # e.g. new peak lists, so that the GUI can update to the latest # state self.basePopup = basePopup self.guiParent = guiParent self.basePopup.frameShortcuts['Workflow'] = self #self.registerNotify=basePopup.registerNotify #self.unregisterNotify=basePopup.unregisterNotify Frame.__init__(self, guiParent) self.grid_rowconfigure(0, weight=0) self.grid_rowconfigure(1, weight=0, minsize=100) self.grid_rowconfigure(2, weight=1) self.grid_rowconfigure(3, weight=0, minsize=30) self.grid_columnconfigure(0, weight=0) self.grid_columnconfigure(1, weight=1) self.grid_columnconfigure(2, weight=0) # build up the body. self.lcA = LinkChart(self, background='#8080B0', height=110) self.lcB = LinkChart(self, background='#8080B0') lcButtonOpts=['Load','Save','Clear','New Protocol'] lcButtonCmds=[self.tmpCall,self.tmpCall,self.tmpCall,self.tmpCall] self.lcButtons = ButtonList(self, lcButtonOpts, lcButtonCmds) # hack for now. This should come from db of meta-tasks self.expts=['Test1','Test2','ARIA','CING','ISD'] # needs custom version self.filter = FilterFrame(self, self.basePopup, text='Filter') # no bean udnerneath for now so mock up nodes self.wfTree = Tree(self, width=35) wfButtonOpts=['Load','Save'] wfButtonCmds=[self.tmpCall,self.tmpCall] self.wfButtons = ButtonList(self, wfButtonOpts, wfButtonCmds) self.drawFrame() def drawFrame(self): # hack the WF Tree for now. just get is looking OK texts=['JMCI WF 1','JMCI WF 2'] icons=[] parents=[] callbacks=[] objects=['JMCI WF 1','JMCI WF 2'] for text in texts: icons.append('list-add') callbacks.append(None) parents.append(None) self.wfTree.update(parents, objects, texts, icons, callbacks) self.lcA.grid(row=1, column=1, padx=5, pady=5, sticky='new') self.lcB.grid(row=2, column=1, padx=5, pady=5, sticky='nsew') self.lcButtons.grid(row=3, column=1, padx=5, pady=5, sticky='ew') self.filter.grid(row=1, column=2, sticky='new') self.wfTree.grid(row=2, column=2, padx=5, pady=5, sticky='nsew') self.wfButtons.grid(row=3, column=2, padx=5, pady=5, sticky='ew') self.nodes = [] x = 0 for expt in self.expts: node = PrototypeNode(self.lcA, title=expt, width=38, updateFunc=None, resizeable=False, shape='SQUARE', coords=(50+x*90, 50), object=None) x += 1 self.lcA.draw() self.lcB.draw() def tmpCall(self): pass def administerNotifiers(self, notifyFunc): for func in ('__init__','delete','setName'): notifyFunc(self.updateAllAfter, 'ccp.nmr.Nmr.Experiment', func) notifyFunc(self.updateAllAfter, 'ccp.nmr.Nmr.DataSource', func) def updateAllAfter(self, obj): self.after_idle(self.updateAll) def updateAll(self, project=None): if project: self.project = project self.nmrProject = project.currentNmrProject if not self.nmrProject: self.nmrProject = project.newNmrProject(name=project.name) if not self.project: return def quit(self): self.guiParent.parent.destroy() def destroy(self): self.administerNotifiers(self.basePopup.unregisterNotify) Frame.destroy(self)
class PeakSeparatorGui(BasePopup): """ **Separate Merged Peaks Using Peak Models** The Peak Separator code uses a Markov Chain Monte Carlo search which, using idealised peak shapes, attempts to deconvolve overlapped peak regions into their separate constituent peaks. This routine is also suitable for accurately fitting model shapes to single peaks in order to calculate precise intensities. **Options Peak Separator Parameters** *Min. Number of peaks* is by default set to one, it is not possible to set this to a value less than one. *Max. Number of peaks* is by default set to one, increasing this value allows the search routine to fit more models. The best fit may be found with fewer than the maximum number models. Higher numbers slow the routine, and setting this value to 0 allows the routine to (effectively) fit unlimited peaks. *Only pick positive peaks*. If you are not interested in negative peaks, removing the possibility of fitting negative peaks can reduce search time. *Peak Model* fits the spectra with either a Gaussian peak model or a Lorentzian peak model. **Options Region** *Peak List* choose which peak list newly picked peaks should be added to. Peaks picked using this method will have their details appended with 'PeakSepartor' so you know where they came from. *Region Table* shows which area of the current spectrum is about to be searched. *Add Region*. Once an area of spectra has been highlighted clicking this button will pass it's details on to the Peak Separator. *Reset All* will reset all search parameters. *Separate Peaks* will run the Peak Separator code with your current settings. This may take a few minutes to run, depending on the size of the spectral region being searched, the number of peaks being fitted and the speed of your machine. Please wait while this completes. After a successful Peak Separation run, the found peaks will be added to the selected peak list. These peaks intensties (volume) have been found using the peak model selected. **Advanced Settings Tab** *Rate* affects the speed of the Markov Chain Monte Carlo routine. A smaller value results in longer execution, but possibly higher quality results. The default setting is deemed sensible for the majority of runs. *Line Width* offers a finer degree of control over maximum and minimum peak widths for each dimension. The default values are *very* stupid and could do with re-checking for each experiment. *Re-Pick Entire Peak List* if you would like to use the Peak Separator to repick *every* peak in your peak list, try this option - but note that this may take a very long time! """ def __init__(self, parent, programName='Peak Separator', **kw): self.parent = parent self.programName = programName self.versionInfo = 'Version 0.2' self.help_url = 'http://www.ccpn.ac.uk/' self.window = None self.waiting = False self.rootWindow = None # just used for display - PeakSeparator will not see this self._minSigmaHz = None self._maxSigmaHz = None self.customSigma = False self.rePickPeakList = False self._sampleStartPpm = None self._sampleEndPpm = None try: self.project = parent.project except: pass self.params = PeakSeparatorParams() BasePopup.__init__(self, parent=parent, title=programName, location='+100+100', **kw) if not self.analysisProject: print '&&& init: No analysis project found ...' try: if parent.argumentServer: self.argServer = parent.argumentServer else: print '&&& init: No argument server found...' except: print '&&& init: Test' ########################################################################### def body(self, guiFrame): self.geometry('450x500') guiFrame.grid_rowconfigure(0, weight=1) guiFrame.grid_columnconfigure(0, weight=1) options = ['Peak Separator', 'Advanced Settings'] tabbedFrame = TabbedFrame(guiFrame, options=options) tabbedFrame.grid(row=0, column=0, sticky='nsew') buttons = UtilityButtonList(tabbedFrame.sideFrame, helpUrl=self.help_url) buttons.grid(row=0, column=0, sticky='e') self.tabbedFrame = tabbedFrame frameA, frameB = tabbedFrame.frames # # FrameA : Main Settings # frameA.grid_columnconfigure(1, weight=1) row = 0 # Label row row += 1 div = LabelDivider(frameA, text='Peak Separator Parameters') div.grid(row=row, column=0, columnspan=2, sticky='ew') row += 1 label = Label(frameA, text='Min. number of peaks:') label.grid(row=row, column=0, sticky='w') self.minPeaksEntry = IntEntry(frameA, returnCallback=self.applyChange, width=10, \ tipText='Minimum number of peaks to find (must be > 0)') self.minPeaksEntry.grid(row=row, column=1, sticky='n') self.minPeaksEntry.bind('<Leave>', self.applyChange, '+') row += 1 label = Label(frameA, text='Max. number of peaks:') label.grid(row=row, column=0, sticky='w') self.maxPeaksEntry = IntEntry(frameA, returnCallback=self.applyChange, width=10, \ tipText='Maximum number of peaks to find (0 is unlimited - not recommended)') self.maxPeaksEntry.grid(row=row, column=1, sticky='n') self.maxPeaksEntry.bind('<Leave>', self.applyChange, '+') row += 1 label = Label(frameA, text='Only pick positive peaks:') label.grid(row=row, column=0, sticky='w') entries = ['False', 'True'] self.posPeaksButtons = RadioButtons( frameA, entries=entries, select_callback=self.applyChange, direction='horizontal', tipTexts=[ 'Search for both positive and negative intensity peaks', 'Limit search to only positive peaks' ]) self.posPeaksButtons.grid(row=row, column=1, sticky='n') row += 1 label = Label(frameA, text='Peak Model:') label.grid(row=row, column=0, sticky='w') ### G/L Mixture works, but volume calculation involves Gamma function # entries = ['Gaussian', 'Lorentzian', 'G/L Mixture'] entries = ['Gaussian', 'Lorentzian'] self.shapeButtons = RadioButtons( frameA, entries=entries, select_callback=self.applyChange, direction='horizontal', tipTexts=[ 'Choose a Gaussian model peak shape to fit to peaks', 'Choose a Lorentzian model peak shape to fit to peaks' ]) self.shapeButtons.grid(row=row, column=1, sticky='n') row += 1 div = LabelDivider(frameA, text='Region', tipText='Region that search will limit itself to') div.grid(row=row, column=0, columnspan=2, sticky='ew') row += 1 label = Label(frameA, text='Peak List:') label.grid(row=row, column=0, sticky='nw') self.peakListPulldown = PulldownList( frameA, callback=self.setManuallyPickPeakList, tipText='Select which peak list new peaks are to be added to') self.peakListPulldown.grid(row=row, column=1, sticky='nw') # tricky scrolled matrix row += 1 self.regionTable = None frameA.grid_rowconfigure(row, weight=1) headings = ('dim.', 'start (ppm)', 'end (ppm)', 'actual size') self.editDimEntry = IntEntry(self, returnCallback=self.applyChange, width=5, tipText='Dimension number') self.editStartEntry = FloatEntry(self, returnCallback=self.applyChange, width=5, tipText='Search area lower bound') self.editEndEntry = FloatEntry(self, returnCallback=self.applyChange, width=5, tipText='Search area upper bound') editWidgets = [ self.editDimEntry, self.editStartEntry, self.editEndEntry, None ] editGetCallbacks = [None, None, None, None] editSetCallbacks = [None, None, None, None] self.regionTable = ScrolledMatrix(frameA, headingList=headings, multiSelect=False, editWidgets=editWidgets, editGetCallbacks=editGetCallbacks, editSetCallbacks=editSetCallbacks, initialRows=5) self.regionTable.grid(row=row, column=0, columnspan=2, sticky='nsew') # Run Button row += 1 texts = ['Add Region'] commands = [self.updateFromRegion] self.addResetButtons = ButtonList( frameA, texts=texts, commands=commands, tipTexts=['Add selected specrtral region']) self.addResetButtons.grid(row=row, column=0, columnspan=2, sticky='ew') row += 1 texts = ['Separate Peaks'] commands = [self.runPeakSeparator] self.runButton = ButtonList(frameA, texts=texts, commands=commands, expands=True, tipTexts=['Run peak search now']) self.runButton.grid(row=row, column=0, columnspan=2, sticky='nsew') # # FrameB : Further Settings # frameB.grid_columnconfigure(0, weight=1) row = 0 div = LabelDivider(frameB, text='Rate:') div.grid(row=row, column=0, columnspan=2, sticky='ew') row += 1 label = Label(frameB, text='Rate of MCMC step size change') label.grid(row=row, column=0, columnspan=1, sticky='w') self.rateEntry = FloatEntry(frameB, returnCallback=self.applyChange, width=10, \ tipText='Rate effects speed of run, smaller values take longer but may produce better results') self.rateEntry.grid(row=row, column=1, sticky='n') self.rateEntry.bind('<Leave>', self.applyChange, '+') self.rateEntry.set(self.params.rate) # tricky scrolled matrix for line width row += 2 div = LabelDivider(frameB, text='Line Width (Hz):') div.grid(row=row, column=0, columnspan=2, sticky='ew') row += 1 label = Label(frameB, text="Descr.") label.grid(row=row, rowspan=2, column=0, sticky='w') row += 1 self.lineWidthTable = None frameB.grid_rowconfigure(row, weight=1) lineWidthHeadings = ('dim.', 'min. σ (Hz)', 'max. σ (Hz)') self.editMinSigmaEntry = FloatEntry(self, returnCallback=self.applyChange, width=5, tipText='Minimum line width (Hz)') self.editMaxSigmaEntry = FloatEntry(self, returnCallback=self.applyChange, width=5, tipText='Maximum line width (Hz)') # self.editDimEntry is also from regionTable initialWidthRows = 4 editLineWidthWidgets = [ None, self.editMinSigmaEntry, self.editMaxSigmaEntry ] editLineWidthGetCallbacks = [None, self.getSigmaMin, self.getSigmaMax] editLineWidthSetCallbacks = [None, self.setSigmaMin, self.setSigmaMax] self.lineWidthTable = ScrolledMatrix( frameB, headingList=lineWidthHeadings, multiSelect=False, editWidgets=editLineWidthWidgets, editGetCallbacks=editLineWidthGetCallbacks, editSetCallbacks=editLineWidthSetCallbacks, initialRows=initialWidthRows) self.lineWidthTable.grid(row=row, column=0, columnspan=2, sticky='nsew') # option to 'repick' exisiting peak list row += initialWidthRows div = LabelDivider(frameB, text='(optional - repick entire peak list)') div.grid(row=row, column=0, columnspan=2, sticky='ew') row += 1 self.repickListPulldown = PulldownList( frameB, callback=self.setRePickPeakList, tipText= 'Select which peak list to repick (new peaks will be put into a new peak list)' ) self.repickListPulldown.grid(row=row, column=0, sticky='nw') texts = ['Repick Peak List'] commands = [self.runRepickPeaks] self.runButton = ButtonList( frameB, texts=texts, commands=commands, expands=True, tipTexts=['Repick selected peak list into a new peak list.']) self.runButton.grid(row=row, column=1, columnspan=1, sticky='nsew') row += 1 div = LabelDivider(frameB) row += 1 texts = ['Separate Peaks'] commands = [self.runPeakSeparator] self.runButton = ButtonList(frameB, texts=texts, commands=commands, expands=True, tipTexts=['Run peak search now']) self.runButton.grid(row=row, column=0, columnspan=2, sticky='nsew') self.setWidgetEntries() self.administerNotifiers(self.registerNotify) def administerNotifiers(self, notifyFunc): for func in ('__init__', 'delete'): notifyFunc(self.updateAfter, 'ccp.nmr.Nmr.PeakList', func) notifyFunc(self.updateAfter, 'ccp.nmr.Nmr.Experiment', 'setName') notifyFunc(self.updateAfter, 'ccp.nmr.Nmr.DataSource', 'setName') def destroy(self): self.administerNotifiers(self.unregisterNotify) BasePopup.destroy(self) ########################################################################### # update parameters from PS Region def updateFromRegion(self): if not self.params.peakList: print '&&& update from region: Need a peak list' return if (self.argServer.parent.currentRegion) == None: showError('No Region', 'Please select a peak region to be separated') return self.rePickPeakList = False getRegionParams(self.params, argServer=self.argServer) if not self.customSigma: self.initSigmaParams() self.setWidgetEntries() ########################################################################### # update parameters from PS PeakList def updateFromPeakList(self): if not self.params.peakList: print '&&& update from peakList: Need a peak list' return getPeakListParams(self.params) if not self.customSigma: self.initSigmaParams() self.setWidgetEntries() ########################################################################### # Run the C library! def runPeakSeparator(self): """ run the peak separator """ # hack for Macs - focus isn't always lost on mouse move # so bind event not always called. Shouldn't affect other OS. self.applyChange() if not self.params.peakList: print '&&& Peak list not yet set' else: # SeparatePeakRoutine(self.params, self.params.peakList, routine='pymc' ) SeparatePeakRoutine(self.params, self.params.peakList, routine='bayesys') def runRepickPeaks(self): """ Run the Peak Separator on entire chosen peak list """ # hack for Macs - focus isn't always lost on mouse move # so bind event not always called. Shouldn't affect other OS. self.applyChange() if not self.params.peakList: print '&&& Peak list not yet set' else: SeparatePeaksInPeakList(self.params) ########################################################################### def setWidgetEntries(self): ### Page One widgets self.minPeaksEntry.set(self.params.minAtoms) self.maxPeaksEntry.set(self.params.maxAtoms) if self.params.positivePeaks == 1: self.posPeaksButtons.set('True') # only pick pos peaks else: self.posPeaksButtons.set('False') # do something fancy if different shapes for each dim! n = self.params.peakShape - 3 # shape is only 3, 4, (5) self.shapeButtons.setIndex(n) if self.project is not None: self.updatePeakListList() self.updateSpectrumWindow() if self.params.sampleStart and self.params.peakList: if not self.rePickPeakList: objectList = [] textMatrix = [] if len(self.params.samplePpmStart) != self.params.Ndim: return for i in range(self.params.Ndim): dim_entry = [] dim_entry.append('%2d' % (i + 1)) dim_entry.append('%7.3f' % self.params.samplePpmStart[i]) dim_entry.append('%7.3f' % self.params.samplePpmEnd[i]) dim_entry.append('%3d' % self.params.sampleSize[i]) textMatrix.append(dim_entry) self.regionTable.update(textMatrix=textMatrix, objectList=objectList) ### Page Two widgets self.rateEntry.set(self.params.rate) if self.params.peakList and self.params.Ndim: textMatrix = [] objectList = [] for i in range(self.params.Ndim): if self.params.isFreqDim[i]: dim_entry = [] objectList.append(i) dim_entry.append('%2d' % (i + 1)) dim_entry.append('%7.3f' % self._minSigmaHz[i]) dim_entry.append('%7.3f' % self._maxSigmaHz[i]) textMatrix.append(dim_entry) self.lineWidthTable.update(textMatrix=textMatrix, objectList=objectList) def applyChange(self, *event): """ Upon change, add settings to params """ # Page One apply changes self.params.minAtoms = self.minPeaksEntry.get() self.params.maxAtoms = self.maxPeaksEntry.get() if self.posPeaksButtons.get() == 'True': # asked only pick pos peaks self.params.positivePeaks = 1 else: self.params.positivePeaks = 0 # do something fancy if different shapes for each dim! n = self.shapeButtons.getIndex() # shape is only 3, 4, (5) self.params.peakShape = n + 3 # Page Two apply changes self.params.rate = float(self.rateEntry.get()) self.updateSigmaParams() ########################################################################### # Peak list functions provide PeakSeparator some inherited params def getPeakListList(self): """ given a spectrum, get list of peak lists """ project = self.project peakLists = [] for experiment in self.nmrProject.experiments: for spectrum in experiment.dataSources: for peakList in spectrum.peakLists: peakLists.append([ '%s:%s:%d' % (experiment.name, spectrum.name, peakList.serial), peakList ]) peakLists.sort() return peakLists def updatePeakListList(self): """ set the peaklist list in the pulldown menu """ peakListData = self.getPeakListList() index = -1 names = [] peakList = self.params.peakList if peakListData: names = [x[0] for x in peakListData] peakLists = [x[1] for x in peakListData] if peakList not in peakLists: peakList = peakLists[0] index = peakLists.index(peakList) else: peakList = None peakLists = [] if peakList is not self.params.peakList: self.params.peakList = peakList self.peakListPulldown.setup(names, peakLists, index) self.repickListPulldown.setup(names, peakLists, index) def setRePickPeakList(self, peakList): """ Set the peak list to be repicked (and hit a Flag) """ self.rePickPeakList = True self.setPeakList(peakList) def setManuallyPickPeakList(self, peakList): """ Set the peak list to add new peaks to (and hit a Flag) """ self.rePickPeakList = False self.setPeakList(peakList) def setPeakList(self, peakList): """ Sets the Peak List """ if peakList is not self.params.peakList: self.params.peakList = peakList # # interrogate the peak list and get all the usefull parameters out self.updateFromPeakList() self.updateSpectrumWindow() self.setWidgetEntries() ########################################################################### # TBD I suspect this is for matching region with peak list, but may be obsolete now def getSpectrumWindowList(self): """ get list of windows which spectrum could be in """ windows = {} if self.params.peakList: views = getSpectrumViews(self.params.peakList.dataSource) for view in views: windows[view.spectrumWindowPane.spectrumWindow] = None return [[w.name, w] for w in windows.keys()] def updateSpectrumWindow(self): """ update the spectrum window """ windowData = self.getSpectrumWindowList() index = -1 names = [] window = self.rootWindow if windowData: names = [x[0] for x in windowData] windows = [x[1] for x in windowData] if window not in windows: window = windows[0] index = windows.index(window) else: window = None windows = [] if window is not self.rootWindow: self.rootWindow = window ########################################################################### # get and set sigma stuff def setSigmaMin(self, dim): value = self.editMinSigmaEntry.get() self._minSigmaHz[dim] = value # dont go and re-write users settings self.customSigma = True # make sure changes are in params object self.updateSigmaParams(dim) self.setWidgetEntries() def getSigmaMin(self, dim): if dim is not None: self.editMinSigmaEntry.set(self._minSigmaHz[dim]) def setSigmaMax(self, dim): value = self.editMaxSigmaEntry.get() self._maxSigmaHz[dim] = value # dont go and re-write users settings self.customSigma = True # make sure changes are in params object self.updateSigmaParams(dim) self.setWidgetEntries() def getSigmaMax(self, dim): if dim is not None: self.editMaxSigmaEntry.set(self._maxSigmaHz[dim]) def updateSigmaParams(self, dim=None): """ updateSigmaParams Just updates the parameters (params obj) for sigma values. If dim is None, do this for each dim """ dataDimRefs = self.params.dataDimRefs if not dataDimRefs: return if not self.params.minSigma or len( self.params.minSigma) != self.params.Ndim: self.params.minSigma = [0.] * self.params.Ndim if not self.params.maxSigma or len( self.params.maxSigma) != self.params.Ndim: self.params.maxSigma = [0.] * self.params.Ndim def updateSigmaParam(dim, dataDimRefs): """ Convert and update sigma for dim """ if self.params.isFreqDim[dim]: # note factor of two! self.params.minSigma[dim] = self.rHz2pnt( self._minSigmaHz[dim], dataDimRefs[dim]) / 2. self.params.maxSigma[dim] = self.rHz2pnt( self._maxSigmaHz[dim], dataDimRefs[dim]) / 2. else: self.params.minSigma[dim] = 1.0 self.params.maxSigma[dim] = 1.0 if dim: updateSigmaParam(dim, dataDimRefs) else: for dim in range(self.params.Ndim): updateSigmaParam(dim, dataDimRefs) # utility functions for sigma values def pnt2rHz(self, point, dataDimRef): """ Point to relative Hz frequency relative to frequency at Zeroeth point Necessary when (for example) looking for width of peak in Hz """ assert point, dataDimRef sigmaBase = pnt2hz(0, dataDimRef) sigmaHz = pnt2hz(point, dataDimRef) return abs(sigmaHz - sigmaBase) def rHz2pnt(self, freq, dataDimRef): """ Relative Hz to point frequency relative to frequency at Zeroeth point Necessary when (for example) looking for width of peak in Hz """ assert freq, dataDimRef sigmaBase = hz2pnt(0, dataDimRef) sigmaPoint = hz2pnt(freq, dataDimRef) return abs(sigmaPoint - sigmaBase) def initSigmaParams(self): """ Set some initial default values for sigma """ self._minSigmaHz = [] self._maxSigmaHz = [] if self.params.Ndim: for dim in range(self.params.Ndim): self._minSigmaHz.append(6.) self._maxSigmaHz.append(28.) ########################################################################### def updateAll(self): self.updateSpectrumWindow() self.updatePeakListList() self.waiting = False def updateAfter(self, obj=None): if self.waiting: return else: self.waiting = True self.after_idle(self.updateAll)
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)
class DataFileImportFrame(Frame): """ TODO: should I also ask for sample conditions info with chemical shifts? Or do in ECI - possible? Check! """ # TODO should go where? email = '*****@*****.**' defaultSelectText = "Select file." fontOkColor = 'green3' fontCheckColor = 'orange3' fontBadColor = 'red3' fontDefaultColor = 'black' def __init__(self, parent, basePopup, *args, **kw): # # Variable initialisation # self.fcWrapper = basePopup.fcWrapper self.project = basePopup.project self.basePopup = basePopup # TODO necessary? if self.project: self.nmrProject = self.project.currentNmrProject self.entry = self.project.currentNmrEntryStore.findFirstEntry() if not self.entry: self.entry = self.project.currentNmrEntryStore.newEntry( name=self.project.name) else: self.nmrProject = None self.sequenceCoordinatesLoaded = False self.shiftsLoaded = False self.linkResDone = False self.currentShiftList = None self.shiftListChainPairs = [] self.moleculeList = [] self.moleculeDict = {} # # Frame setup # Frame.__init__(self, parent, **kw) self.grid_columnconfigure(1, weight=1) self.grid_rowconfigure(1, weight=1) options = ['Import', 'Deposition'] tabbedFrame = TabbedFrame(self, options=options, callback=self.selectTab) tabbedFrame.grid(row=1, column=0, columnspan=2, sticky='nsew') self.tabbedFrame = tabbedFrame frameA, frameD = tabbedFrame.frames # # Main # frameA.grid_columnconfigure(0, weight=1) #frameA.grid_columnconfigure(1, weight=1) # Change to 2 if want 2 columns frameA.grid_rowconfigure(12, weight=1) #frameA.grid_rowconfigure(12, weight=1) row = 0 div = LabelDivider( frameA, text= 'Select the full coordinate file or a sequence file (with info for a single molecule).', justify='center', grid=(row, 0), gridSpan=(1, 1)) row += 1 self.sequenceCoordinatesImport = Button( frameA, text=self.defaultSelectText, command=self.importSequenceOrCoords, foreground=self.fontDefaultColor) self.sequenceCoordinatesImport.grid(row=row, column=0, sticky='ew') row += 1 label = Label(frameA, text="") label.grid(row=row, column=0, sticky='ew') row += 1 div = LabelDivider( frameA, text='Select the molecule relevant for your chemical shift file.', justify='center', grid=(row, 0), gridSpan=(1, 1)) row += 1 self.moleculeSelect = Label( frameA, text="None available yet - import valid file first", foreground=self.fontBadColor) self.moleculeSelect.grid(row=row, column=0, sticky='ew') self.moleculeSelectRow = row row += 1 label = Label(frameA, text="") label.grid(row=row, column=0, sticky='ew') row += 1 div = LabelDivider( frameA, text= 'Select a chemical shift file with values only for the above molecule.', justify='center', grid=(row, 0), gridSpan=(1, 1)) row += 1 self.shiftImport = Button(frameA, text=self.defaultSelectText, command=self.importShifts, foreground=self.fontDefaultColor) self.shiftImport.grid(row=row, column=0, sticky='ew') row += 1 label = Label(frameA, text="") label.grid(row=row, column=0, sticky='ew') row += 1 div = LabelDivider( frameA, text='Consistency check between molecule and shift information.', justify='center', grid=(row, 0), gridSpan=(2, 1)) row += 1 self.linkResCheckInfo = Label(frameA, text='') self.linkResCheckInfo.grid(row=row, column=0, sticky='ew') row += 1 div = Separator(frameA, grid=(row, 0), gridSpan=(1, 1)) row += 1 texts = ['Import new sequence', 'Import new set of shifts'] commands = [self.resetSequenceImport, self.resetShiftImport] self.mainButtons = ButtonList(frameA, texts=texts, commands=commands) self.mainButtons.grid(row=row, column=0, columnspan=2, sticky='ew') self.mainButtons.buttons[0].config(foreground=self.fontDefaultColor) #print row self.frameA = frameA # # Not in use... # #frameX.grid_columnconfigure(0, weight=1) #frameX.grid_columnconfigure(1, weight=1) #frameX.grid_rowconfigure(1, weight=1) #frameX.grid_rowconfigure(3, weight=1) # # Deposition, is updated after each successful import run. # frameD.grid_columnconfigure(0, weight=1) frameD.grid_rowconfigure(5, weight=1) self.frameD = frameD row = 0 div = LabelDivider(frameD, text='Imported data.', justify='center', grid=(row, 0), gridSpan=(1, 2)) row += 1 self.depositionImportText = "\nImported %d shift list(s) for a total of %d shifts.\n\nImported %d molecule(s) and %d chain(s).\n\nImported %d model(s) for a total of %d atom coordinates.\n\nLinked %.2f%% of imported NMR information to %d chain(s)." self.depositionImportLoc = (row, 0) # These used for setting text above... self.depositionImportNums = [0, 0, 0, 0, 0, 0, 0.0, 0] self.importedShiftLists = [] self.connectedChains = [] self.depositionImportLabel = Label(frameD, text=self.depositionImportText % tuple(self.depositionImportNums), foreground=self.fontBadColor) self.depositionImportLabel.grid(row=row, column=0, sticky='ew') row += 1 label = Label(frameD, text="") label.grid(row=row, column=0, sticky='ew') # # Finalize the import part, proceed to ECI. # row += 1 div = LabelDivider( frameD, text= 'Import completed, save project and start Entry Completion Interface.', justify='center', grid=(row, 0), gridSpan=(1, 1)) row += 1 self.eciStart = Button(frameD, text="Finalise import", command=self.finaliseImport, foreground=self.fontBadColor) self.eciStart.grid(row=row, column=0, sticky='ew') def finaliseImport(self): if not self.depositionImportNums[6]: showWarning('Failure', 'Need connected molecule and shift information first') return if showYesNo( "Save project and continue annotation", "Are you sure you want to save this project and continue?", parent=self): if self.depositionImportNums[5] or showYesNo( "No coordinates", "No coordinates are available - are you sure you want to continue?", parent=self): showInfo("Project name", "Your project will be saved in the %s directory." % self.project.name, parent=self) self.project.saveModified() #userData = self.project.findFirstRepository(name='userData') #currentPath = userData.url.path #currentProjectName = self.project.name #projectDir = os.path.join(currentPath,currentProjectName) eci = EntryCompletionGui(self.basePopup.root) eci.initProject(self.project) # # File type determination and import # def createFileTypes(self, dataTypes): fileTypes = [FileType('all', ['*'])] for dataType in dataTypes: formatNames = fileTypeDict[dataType].keys() formatNames.sort() for formatName in formatNames: if formatName in self.fcWrapper.formatNameLists[dataType]: fileTypes.append( FileType(formatName, fileTypeDict[dataType][formatName])) return fileTypes def getFileName(self, title, fileTypes): fileSelectPopup = FileSelectPopup( self, file_types=fileTypes, title=title, dismiss_text='Cancel', selected_file_must_exist=True, multiSelect=False, ) self.fileName = fileSelectPopup.getFile() if not self.fileName: showWarning('Failure', 'Please select an existing file.', parent=self) return False return True def importSequenceOrCoords(self): dataTypes = ['sequence', 'coordinates'] fileTypes = self.createFileTypes(dataTypes) if self.getFileName('Import sequence or coordinate file', fileTypes): formatNameSuggestions = {} for dataType in dataTypes: tmpList = self.fcWrapper.determineFormatNamesForFile( dataType, self.fileName) if tmpList: formatNameSuggestions[dataType] = tmpList if not formatNameSuggestions: showWarning( 'Failure', 'This file cannot be read by this software.\nPlease send the file with an explanation to %s.' % self.email, parent=self) return False # # Let user select if multiple options, otherwise take default # if len(formatNameSuggestions) == 1 and len(formatNameSuggestions[ formatNameSuggestions.keys()[0]]) == 1: dataType = formatNameSuggestions.keys()[0] formatName = formatNameSuggestions[dataType][0] if not showYesNo( 'File type detected', 'Reading as %s file in %s format. Is this correct?' % (dataType, formatName), parent=self): showWarning( 'Failure', 'This file cannot be read by this software.\nPlease send the file with an explanation to %s.' % self.email, parent=self) return False else: # # Create a selection (hopefully user-understandable) # selectionList = [] selectionDict = {} for dataType in dataTypes: dataTypeString = dataType if formatNameSuggestions.has_key(dataType): formatNames = formatNameSuggestions[dataType] formatNames.sort() for formatName in formatNames: selectionString = "%s file in %s format." % ( dataTypeString, formatName) selectionList.append(selectionString) selectionDict[selectionString] = (dataType, formatName) interaction = SelectionListPopup(self, selectionList, title='File format selection', text='This is a:', selectionDict=selectionDict, dismissButton=True, modal=True) # # Check if anything was selected... # dataType = formatName = None if interaction.isSelected: (dataType, formatName) = interaction.selection else: showWarning( 'Failure', 'This file cannot by read without a format selection.\nIf the correct format is not available, please send the file with an explanation to %s' % self.email, parent=self) return False # # Now read the file, need to do some field updates! # (fileRead, fileInformation) = self.fcWrapper.readFile( dataType, formatName, self.fileName) if not fileRead: showWarning( 'Failure', 'This file cannot be read by this software:%s\nPlease send the file with an explanation to %s.' % (fileInformation, self.email), parent=self) return False (conversionInfo, conversionSuccess) = ( self.fcWrapper.formatConversion.conversionInfo, self.fcWrapper.formatConversion.conversionSuccess) if not conversionSuccess: showWarning( 'Failure', 'This file was read by the software but contains invalid information.\nPlease send the file with an explanation to %s.' % self.email, parent=self) return False # # Set info if import worked OK # conversionLines = conversionInfo.split(": ") showInfo("Import coordinate and/or sequence information", ":\n".join(conversionLines), parent=self) if dataType == 'sequence': chains = self.fcWrapper.importReturns[dataType] models = [] elif dataType == 'coordinates': models = self.fcWrapper.importReturns[dataType] chains = [ cChain.chain for cChain in models[0].structureEnsemble.coordChains ] self.sequenceCoordinatesImport.setText( self.fileName) # TODO change color or something? self.sequenceCoordinatesImport.configure( foreground=self.fontOkColor) self.sequenceCoordinatesLoaded = True # # Reset to list selector for further use # moleculeName = None for chain in chains: if chain in self.moleculeDict.values(): continue numResidues = len(chain.residues) if numResidues == 1: residueText = "%s residue" % chain.findFirstResidue( ).ccpCode else: residueText = "%d residues" % numResidues moleculeName = "%s (chain '%s', %s)" % ( chain.molecule.name, chain.code, residueText) self.moleculeList.append(moleculeName) self.moleculeDict[moleculeName] = chain self.moleculeList.sort() self.moleculeSelect.destroy() if len(chains) == 1 and moleculeName: selectedIndex = self.moleculeList.index(moleculeName) else: selectedIndex = 0 self.moleculeSelect = PulldownList(self.frameA, texts=self.moleculeList, index=selectedIndex, sticky='ew') self.moleculeSelect.grid(row=self.moleculeSelectRow, column=0) # # Now update Deposition tab # molecules = [] for chain in chains: if not chain.molecule in molecules: molecules.append(chain.molecule) numCoords = 0 for model in models: numCoords += len(model.coords) self.updateDepositionImportLabel(molecules=len(molecules), chains=len(chains), models=len(models), coordinates=numCoords) # Add the molSystem to the entry! if chains and not chains[0].molSystem == self.entry.molSystem: self.entry.molSystem = chains[0].molSystem self.updateAll() def importShifts(self): currentChain = self.getCurrentChain() if not currentChain: showWarning( 'Failure', 'Please first read in a sequence or coordinate file and select the molecule relevant for this shift list.', parent=self) return elif self.currentShiftList: shiftListChainPair = (self.currentShiftList, currentChain) if shiftListChainPair in self.shiftListChainPairs: showWarning( 'Failure', "You already read in chemical shifts for this chain.\nPlease read in related shifts for the other chain(s), if present, or press the 'Import new set of shifts' button to read in a new set of shifts.", parent=self) return dataType = 'shifts' fileTypes = self.createFileTypes([dataType]) if self.getFileName('Import chemical shift file', fileTypes): formatNameSuggestions = self.fcWrapper.determineFormatNamesForFile( dataType, self.fileName) if not formatNameSuggestions: showWarning( 'Failure', 'This file cannot be read by this software.\nPlease send the file with an explanation to %s.' % self.email, parent=self) return False # # Let user select if multiple options, otherwise take default # if len(formatNameSuggestions) == 1: formatName = formatNameSuggestions[0] if not showYesNo( 'File type detected', 'Reading as a chemical shift file in %s format. Is this correct?' % formatName, parent=self): showWarning( 'Failure', 'This file cannot be read by this software.\nPlease send the file with an explanation to %s.' % self.email, parent=self) return False else: # # Create a selection (hopefully user-understandable) # selectionList = [] selectionDict = {} formatNameSuggestions.sort() for formatName in formatNameSuggestions: selectionString = "chemical shift file in %s format." % ( formatName) selectionList.append(selectionString) selectionDict[selectionString] = formatName interaction = SelectionListPopup(self, selectionList, title='File format selection', text='This is a:', selectionDict=selectionDict, dismissButton=True, modal=True) # # Check if anything was selected... # formatName = None if interaction.isSelected: formatName = interaction.selection else: showWarning( 'Failure', 'This file cannot by read without a format selection.\nIf the correct format is not available, please send the file with an explanation to %s' % self.email, parent=self) return False # # Now read the file, need to do some field updates! Also make sure to re-use shift list for other molecules... # (fileRead, fileInformation) = self.fcWrapper.readFile( dataType, formatName, self.fileName, addKeywords={'measurementList': self.currentShiftList}) if not fileRead: showWarning( 'Failure', 'This file cannot be read by this software:%s\nPlease send the file with an explanation to %s.' % (fileInformation, self.email), parent=self) return False (conversionInfo, conversionSuccess) = ( self.fcWrapper.formatConversion.conversionInfo, self.fcWrapper.formatConversion.conversionSuccess) if not conversionSuccess: showWarning( 'Failure', 'This file was read by the software but contains invalid information.\nPlease send the file with an explanation to %s.' % self.email, parent=self) return False # # Set info if import worked OK # conversionLines = conversionInfo.split(": ") showInfo("Import chemical shift information", ":\n".join(conversionLines), parent=self) self.shiftImport.setText( self.fileName) # TODO change color or something? self.shiftImport.configure(foreground=self.fontOkColor) self.shiftsLoaded = True self.shiftsFormatName = formatName shiftList = self.fcWrapper.importReturns[dataType] if not self.currentShiftList: self.currentShiftList = shiftList self.shiftListChainPairs.append( (self.currentShiftList, currentChain)) self.updateDepositionImportLabel(shiftList=shiftList) if not shiftList in self.entry.measurementLists: print shiftList self.entry.addMeasurementList(shiftList) print self.entry.measurementLists self.updateAll() # # Updaters # def selectTab(self, index): funcsDict = { 0: (self.updateMain, ), 1: (self.updateCoordinates, ), 2: (self.updateDeposition, ) } for func in funcsDict[index]: func() def updateMain(self): pass def updateCoordinates(self): pass def updateDeposition(self): pass def updateAll(self): self.selectTab(self.tabbedFrame.selected) if self.sequenceCoordinatesLoaded and self.shiftsLoaded: if showYesNo( 'Connect shifts to sequence', 'You have to check whether the chemical shift information matches the sequence. Do you want to this now?', parent=self): self.connectShiftsSequence() self.waiting = False def getCurrentChain(self): if len(self.moleculeList) == 1: chain = self.moleculeDict.values()[0] else: try: moleculeSelected = self.moleculeSelect.getText() chain = self.moleculeDict[moleculeSelected] except: chain = None return chain def connectShiftsSequence(self): if not self.linkResDone: changeResetColor = False # # Get chain mapping and run linkResonances # chain = self.getCurrentChain() forceChainMappings = self.fcWrapper.linkResonancesToSequence( chain=chain) self.fcWrapper.formatConversion.linkResonances( forceChainMappings=forceChainMappings, guiParent=self) # # Get information about the linking process # # TODO Should only have an nmrProject (no restraint import, should be included?) # In any case, is always the LAST info in numResonancesLinked info numResonancesLinked = self.fcWrapper.formatConversion.numResonancesLinked (origLinked, origUnlinked, linked, unlinked) = (numResonancesLinked['origLinked'][-1], numResonancesLinked['origUnlinked'][-1], numResonancesLinked['linked'][-1], numResonancesLinked['unlinked'][-1]) # # Track number of new resonances, and reset for new import # if self.fcWrapper.formatConversion.allResonancesLinked: status = 'All information matches (for all imports).' foreground = self.fontOkColor changeResetColor = True else: if origUnlinked - unlinked == self.fcWrapper.numNewResonances: status = 'All information matches (for this import)' foreground = self.fontOkColor changeResetColor = True else: if origUnlinked != unlinked: status = 'Not all information matches (for this and/or another import).' foreground = self.fontCheckColor changeResetColor = True else: status = 'No information matches (for this import).' foreground = self.fontBadColor otherUnlinked = (origUnlinked - self.fcWrapper.numNewResonances) notLinked = unlinked - otherUnlinked status += "\nUnable to link %d out of %d imported shifts (%.2f%%)." % ( notLinked, self.fcWrapper.numNewResonances, (notLinked * 100.0) / self.fcWrapper.numNewResonances) self.linkResCheckInfo.set("Status: %s" % status) self.linkResCheckInfo.config(foreground=foreground) self.linkResDone = True # # Change the color of the reset button to indicate OK to do next one # if changeResetColor: self.mainButtons.buttons[0].config(foreground=self.fontOkColor) self.updateDepositionImportLabel( shiftList=None, percentageLinked=(linked * 100.0 / (unlinked + linked)), connectedChain=chain) def updateDepositionImportLabel(self, shiftList=None, molecules=0, chains=0, models=0, coordinates=0, percentageLinked=None, connectedChain=None): if shiftList and shiftList not in self.importedShiftLists: self.importedShiftLists.append(shiftList) self.depositionImportNums[0] += 1 shifts = 0 for shiftList in self.importedShiftLists: shifts += len(shiftList.measurements) self.depositionImportNums[1] += shifts self.depositionImportNums[2] += molecules self.depositionImportNums[3] += chains self.depositionImportNums[4] += models self.depositionImportNums[5] += coordinates if percentageLinked != None: self.depositionImportNums[6] = percentageLinked if connectedChain and connectedChain not in self.connectedChains: self.depositionImportNums[7] += 1 self.connectedChains.append(connectedChain) self.depositionImportLabel.destroy() finalForeground = self.fontBadColor if self.depositionImportNums[0] == 0 and self.depositionImportNums[ 2] == 0: # Nothing imported foreground = self.fontBadColor elif self.depositionImportNums[6]: # Linked shifts available - TODO base this on % of shifts linked? foreground = self.fontOkColor if self.depositionImportNums[5]: finalForeground = self.fontOkColor else: finalForeground = self.fontCheckColor else: # Intermediate state foreground = self.fontCheckColor self.depositionImportLabel = Label(self.frameD, text=self.depositionImportText % tuple(self.depositionImportNums), foreground=foreground) self.depositionImportLabel.grid(row=self.depositionImportLoc[0], column=self.depositionImportLoc[1], sticky='ew') self.eciStart.configure(foreground=finalForeground) def resetSequenceImport(self): doReset = True if not self.linkResDone and self.sequenceCoordinatesLoaded and self.shiftsLoaded: if showYesNo( 'Shifts not connected to sequence', 'You have not checked whether the imported chemical shift information matches the imported sequence. Do you want to this first? If not, the last imported data will be invalid.', parent=self): self.connectShiftsSequence() doReset = False if doReset: self.mainButtons.buttons[0].config( foreground=self.fontDefaultColor) self.sequenceCoordinatesLoaded = self.shiftsLoaded = self.linkResDone = False self.sequenceCoordinatesImport.setText(self.defaultSelectText) self.sequenceCoordinatesImport.configure( foreground=self.fontDefaultColor) self.moleculeSelect.destroy() self.moleculeSelect = Label( self.frameA, text="None available yet - import valid file first", foreground=self.fontBadColor) self.moleculeSelect.grid(row=self.moleculeSelectRow, column=0, sticky='ew') self.shiftImport.setText(self.defaultSelectText) self.shiftImport.configure(foreground=self.fontDefaultColor) self.linkResCheckInfo.set("") def resetShiftImport(self): doReset = True if not self.linkResDone and self.sequenceCoordinatesLoaded and self.shiftsLoaded: if showYesNo( 'Shifts not connected to sequence', 'You have not checked whether the imported chemical shift information matches the imported sequence. Do you want to this first? If not, the last imported data will be invalid.', parent=self): self.connectShiftsSequence() doReset = False if doReset: self.mainButtons.buttons[1].config( foreground=self.fontDefaultColor) self.shiftsLoaded = self.linkResDone = False self.currentShiftList = None self.shiftImport.setText(self.defaultSelectText) self.shiftImport.configure(foreground=self.fontDefaultColor) self.linkResCheckInfo.set("") def destroy(self): Frame.destroy(self) # # Instructions # def showMainInstructions(self): popup = getPopup(self) message = """Use this tab to import the chemical shifts and the coordinate and/or sequence information for your molecular chains. The imported chemical shift file should contain information for only *one* molecular chain to make it easier to connect the molecule information to the chemical shift information. You therefore have to select a single chain for each shift list from the dropdown menu that will appear after you imported a coordinate or sequence file. For example, when using sequence files for a dimer, import the information for the chemical shifts for each chain separately: 1. Import the sequence for the first molecular chain. 2. Import a chemical shift file with shifts only for this molecular chain. 3. Reset using the 'Import new sequence' button 4. Import the sequence for the second molecular chain 5. Import a chemical shift file with shifts only for this second chain Alternatively, it is possible to read in the molecule information from a full coordinate file: 1. Import a coordinate file with all molecular information, including coordinates. 2. Select a molecular chain. 3. Import a chemical shift file with shifts only for the selected molecular chain. 4. Go back to step 2. if necessary. You can also import multiple sets of chemical shifts (e.g. for the sample in different conditions). In this case, you have to import all chemical shift information that belongs together for all molecular chains, then press the 'Import new set of shifts' button. Notes: 1. This application always creates a new CCPN project. It is not possible to import files into existing projects. 2. If your chemical shift file contains information for multiple chains, you have to edit it manually to split up the information per chain. """ showHelpText(self, message, popup=popup) def showFormats(self): popup = getPopup(self) message = """For chemical shifts, the following formats are recognised: *** Auremol *** section_sequenzdefinition _Residue_seq_code _Atom_num_code _Residue_label _Atom_name _Atom_type _Atom_alias _Atom_equivalent _Atom_CSA 1 1 MET HN H - - 8.95 1 2 MET N N - - 157.00 1 3 MET CA C - - 40.00 *** Autoassign *** AA HN N15 CO-1 CA-1 CB-1 HA-1 CO CA CB HA A31 8.14 121.4 51.3 19.6 (GS178 115.HSQC) D32 8.88 122.9 51.3 19.5 55.4 39.6 (GS271 22.HSQC) *** CNS *** do ( store1 = 53.13218 ) ( resid 78 and name CA ) do ( store1 = 0.7356673 ) ( resid 15 and name HD1# ) do ( store1 = 120.5381 ) ( resid 8 and name N ) do ( store1 = 121.1414 ) ( resid 78 and name N ) *** Cosmos *** CS_VALUES 3 C_ALA 176.6 CA_ALA 51.66 CB_ALA 17.26 END *** CSI *** # A HA CA CO CB Consensus # 1 MET 0 C 0 C NA 0 C 0 C 2 GLY 0 C 0 C NA 0 C 0 C *** MARS *** H N CO-1 CA CA-1 PR_2 8.900 123.220 170.540 55.080 54.450 PR_4 8.320 115.340 175.920 - 55.080 *** MONTE *** 1 102.544 8.211 45.853 54.925 0.000 18.069 180.112 2 103.276 8.580 45.334 54.154 0.000 35.650 175.087 3 103.997 7.407 45.165 0.000 0.000 0.000 0.000 *** NMR-STAR *** data_test save_shifts1 _Saveframe_category assigned_chemical_shifts loop_ _Atom_shift_assign_ID _Residue_seq_code _Residue_label _Atom_name _Atom_type _Chem_shift_value _Chem_shift_value_error _Chem_shift_ambiguity_code 1 1 ASP CA C 52.000 0.02 1 2 1 ASP HA H 4.220 0.02 1 stop_ save_ *** NMRVIEW *** 2.CG1 18.549 0 2.CG2 18.844 0 2.HG1# 0.800 0 2.HG2# 0.723 0 3.HG2 2.298 0 3.HG1 2.298 0 *** PIPP *** RES_ID 1 RES_TYPE MET SPIN_SYSTEM_ID 1 CA 55.9920 CB 33.1470 HA 4.1141 HB# 2.0492 HG# 2.4250 END_RES_DEF *** PISTACHIO *** 1 1 GLY C C 172.621 1.000 0 2 1 GLY CA C 44.308 1.000 0 3 2 SER N N 122.241 1.000 0 *** PRONTO *** Spin system HN HA Other: 1: Val-1 3.76 HB: 1.945, HG1: 0.770, HG2: 0.608 2: Ile-2 8.80 4.26 HB: 1.526, HG1: 1.278, HG2: 0.728, HD: 0.918 *** SHIFTX *** NUM RES HA H N CA CB C --- --- ------ ------ -------- ------- ------- -------- 2 T 4.4161 8.1749 111.0443 61.8324 70.3867 172.5362 3 Y 4.9022 9.0239 120.2106 56.0493 41.4218 173.0761 NUM RES H HA HB HB2 HB3 HD1 HD2 HD21 HD22 HD3 HE HE1 HE2 HE21 HE22 HE3 HG HG1 HG12 HG13 HG2 HG3 HZ 2 T 8.17 4.42 4.24 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.21 0.00 0.00 3 Y 9.02 4.90 0.00 2.22 2.20 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 *** SPARKY *** Group Atom Nuc Shift SDev Assignments R2 CA 13C 56.539 0.003 3 R2 CB 13C 30.808 0.009 3 *** TALOS *** VARS RESID RESNAME PHI PSI DPHI DPSI DIST COUNT CLASS FORMAT %4d %s %8.3f %8.3f %8.3f %8.3f %8.3f %2d %s 1 Q 9999.000 9999.000 0.000 0.000 0.000 0 None 2 N -85.000 124.000 23.000 28.000 85.920 10 Good ***XEASY/CYANA: 1 117.803 0.000 N 1 2 8.208 0.002 HN 1 3 56.508 0.055 CA 1 4 999.000 0.000 HA 1 5 29.451 0.004 CB 1 """ showHelpText(self, message, popup=popup)
def __init__(self, parent, initial_list=None, width=60, height=5, xscroll=True, yscroll=True, addDeleteButtons=False, selectmode=Tkinter.BROWSE, exportselection=0, select_callback=None, double_callback=None, list_background='white', *args, **kw): if (initial_list is None): initial_list = [] apply(Frame.__init__, (self, parent) + args, kw) self.selectmode = selectmode self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) listbox = Tkinter.Listbox(self, width=width, height=height, background=list_background, selectmode=selectmode, exportselection=exportselection) listbox.grid(row=0, column=0, sticky=Tkinter.NSEW) if (xscroll): xscrollbar = Tkinter.Scrollbar(self, orient=Tkinter.HORIZONTAL) xscrollbar.config(command=listbox.xview) listbox.config(xscrollcommand=xscrollbar.set) xscrollbar.grid(row=1, column=0, sticky=Tkinter.EW) if (yscroll): yscrollbar = Tkinter.Scrollbar(self, orient=Tkinter.VERTICAL) yscrollbar.config(command=listbox.yview) listbox.config(yscrollcommand=yscrollbar.set) yscrollbar.grid(row=0, column=1, sticky=Tkinter.NS) if addDeleteButtons: texts = ['Add item', 'Delete selected'] commands = [self.addItem, self.deleteItems] buttons = ButtonList(self, texts=texts, commands=commands) buttons.grid(row=1, columnspan=2, sticky=Tkinter.EW) # bind frame, not listbox, because listbox with focus has # activation which means in particular that get underlining self.bind('<Enter>', self.enterCallback) self.bind('<KeyPress>', self.keypressCallback) self.listbox = listbox self.setItems(initial_list) self.setSelectCallback(select_callback) self.setDoubleCallback(double_callback) self.size = self.listbox.size # otherwise get Frame size called
class ResultsTab(object): def __init__(self, parent, frame): self.guiParent = parent self.frame = frame self.project = parent.project self.nmrProject = parent.nmrProject self.selectedLinkA = None self.selectedLinkB = None self.selectedResidueA = None self.selectedResidueB = None self.selectedLink = None self.dataModel = self.guiParent.connector.results self.body() def body(self): frame = self.frame self.resultsResidueNumber = 1 frame.expandGrid(5, 0) resultTopFrame = LabelFrame(frame, text='Which results to show') resultTopFrame.grid(row=0, column=0, sticky='ew') self.resultsResidueNumber = 3 texts = [' < '] commands = [self.resultsPrevResidue] self.resultsPreviousButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.resultsPreviousButton.grid(row=0, column=1, sticky='nsew') tipText = 'The Number of the residue in the sequence to display results for' self.resultsResidueNumberEntry = IntEntry( resultTopFrame, grid=(0, 2), width=7, text=3, returnCallback=self.resultsUpdateAfterEntry, tipText=tipText) #self.resultsResidueNumberEntry.bind('<Leave>', self.resultsUpdateAfterEntry, '+') texts = [' > '] commands = [self.resultsNextResidue] self.resultsNextButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.resultsNextButton.grid(row=0, column=3, sticky='nsew') selectCcpCodes = ['residue'] + AMINO_ACIDS self.resultsSelectedCcpCode = 'residue' tipText = 'Instead of going through the sequence residue by residue, jump directly to next amino acid of a specific type.' resultsSelectCcpCodeLabel = Label( resultTopFrame, text='Directly jump to previous/next:', grid=(0, 4)) self.resultsSelectCcpCodePulldown = PulldownList( resultTopFrame, callback=self.resultsChangeSelectedCcpCode, texts=selectCcpCodes, index=selectCcpCodes.index(self.resultsSelectedCcpCode), grid=(0, 5), tipText=tipText) self.selectedSolution = 1 runLabel = Label(resultTopFrame, text='run:') runLabel.grid(row=0, column=6) texts = [' < '] commands = [self.resultsPrevSolution] self.resultsPreviousSolutionButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.resultsPreviousSolutionButton.grid(row=0, column=7, sticky='nsew') tipText = 'If you ran the algorithm more than once, you can select the solution given by the different runs.' self.resultsSolutionNumberEntry = IntEntry( resultTopFrame, grid=(0, 8), width=7, text=1, returnCallback=self.solutionUpdateAfterEntry, tipText=tipText) #self.resultsSolutionNumberEntry.bind('<Leave>', self.solutionUpdateAfterEntry, '+') texts = [' > '] commands = [self.resultsNextSolution] self.resultsNextSolutionButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.resultsNextSolutionButton.grid(row=0, column=9, sticky='nsew') self.energyLabel = Label(resultTopFrame, text='energy:') self.energyLabel.grid(row=0, column=10) texts = ['template for puzzling'] commands = [self.adoptSolution] self.adoptButton = ButtonList(resultTopFrame, commands=commands, texts=texts) self.adoptButton.grid(row=0, column=11, sticky='nsew') # LabelFrame(frame, text='Spin Systems') resultsSecondFrame = Frame(frame) resultsSecondFrame.grid(row=2, column=0, sticky='nsew') resultsSecondFrame.grid_columnconfigure(0, weight=1) resultsSecondFrame.grid_columnconfigure(1, weight=1) resultsSecondFrame.grid_columnconfigure(2, weight=1) resultsSecondFrame.grid_columnconfigure(3, weight=1) resultsSecondFrame.grid_columnconfigure(4, weight=1) headingList = ['#', '%'] tipTexts = [ 'Spinsystem number {} indicates serial of the spinsystem. If the spinsystem was already assigned to a residue, the residue number is shown aswell', 'percentage of the solutions that connected this spinsystem to this residue' ] editWidgets = [None, None, None] self.displayResultsTables = [] self.residueLabels = [] for i in range(5): label = Label(resultsSecondFrame, text='residue') label.grid(row=0, column=i) #editGetCallbacks = [createCallbackFunction(i)]*3 displayResultsTable = ScrolledMatrix( resultsSecondFrame, headingList=headingList, multiSelect=False, tipTexts=tipTexts, callback=self.selectSpinSystemForTable, passSelfToCallback=True) displayResultsTable.grid(row=2, column=i, sticky='nsew') displayResultsTable.sortDown = False self.residueLabels.append(label) self.displayResultsTables.append(displayResultsTable) # LabelFrame(frame, text='Sequence Fragment') resultsFirstFrame = Frame(resultsSecondFrame) resultsFirstFrame.grid(row=1, column=0, sticky='ew', columnspan=5) resultsFirstFrame.grid_rowconfigure(0, weight=1) resultsFirstFrame.grid_rowconfigure(1, weight=1) resultsFirstFrame.grid_columnconfigure(0, weight=1) texts = [ ' res 1 ', ' links ', ' res 2 ', ' links ', ' res 3 ', ' links ', ' res 4 ', ' links ', ' res 5 ' ] commands = [ lambda: self.selectRelativeResidue(1, True), lambda: self.selectLink(1, True), lambda: self.selectRelativeResidue(2, True), lambda: self.selectLink(2, True), lambda: self.selectRelativeResidue(3, True), lambda: self.selectLink(3, True), lambda: self.selectRelativeResidue(4, True), lambda: self.selectLink(4, True), lambda: self.selectRelativeResidue(5, True) ] self.sequenceButtons = ButtonList(resultsFirstFrame, commands=commands, texts=texts) self.sequenceButtons.grid(row=0, column=0, sticky='nsew') for n, button in enumerate(self.sequenceButtons.buttons): if n % 2: button.grid(column=n, sticky='ns') self.sequenceButtons.grid_columnconfigure(n, weight=0) else: self.sequenceButtons.grid_columnconfigure(n, uniform=2) spacer = Spacer(resultsFirstFrame) spacer.grid(row=1, column=0, sticky='nsew') texts = [ ' res 1 ', ' links ', ' res 2 ', ' links ', ' res 3 ', ' links ', ' res 4 ', ' links ', ' res 5 ' ] commands = commands = [ lambda: self.selectRelativeResidue(1, False), lambda: self.selectLink(1, False), lambda: self.selectRelativeResidue(2, False), lambda: self.selectLink(2, False), lambda: self.selectRelativeResidue(3, False), lambda: self.selectLink(3, False), lambda: self.selectRelativeResidue(4, False), lambda: self.selectLink(4, False), lambda: self.selectRelativeResidue(5, False) ] self.sequenceButtonsB = ButtonList(resultsFirstFrame, commands=commands, texts=texts) self.sequenceButtonsB.grid(row=2, column=0, sticky='nsew') for n, button in enumerate(self.sequenceButtonsB.buttons): if n % 2: button.grid(column=n, sticky='ns') self.sequenceButtonsB.grid_columnconfigure(n, weight=0) else: self.sequenceButtonsB.grid_columnconfigure(n, uniform=2) frame.grid_rowconfigure(3, weight=2) resultsThirdFrame = Frame(frame) resultsThirdFrame.grid(row=3, column=0, sticky='nsew') resultsThirdFrame.grid_rowconfigure(0, weight=1) resultsThirdFrame.grid_columnconfigure(0, weight=1) tabbedFrameB = TabbedFrame(resultsThirdFrame, options=['Peaks', 'Spin System'], callback=self.toggleTab, grid=(0, 0)) #self.tabbedFrameB = tabbedFrame PeakFrame, SpinSystemFrame = tabbedFrameB.frames SpinSystemFrame.grid_rowconfigure(0, weight=1) PeakFrame.grid_rowconfigure(1, weight=1) SpinSystemFrame.grid_columnconfigure(0, weight=1) PeakFrame.grid_columnconfigure(0, weight=1) headingList = [ 'residue', 'assigned to in project', 'user defined sequence', 'selected annealing result', '%' ] tipTexts = [None, None, None, None, None] editWidgets = [None, None, None, None, None] editGetCallbacks = [None, None, None, None, None] editSetCallbacks = [None, None, None, None, None] self.spinSysTable = ScrolledMatrix(SpinSystemFrame, headingList=headingList, editWidgets=editWidgets, multiSelect=False, editGetCallbacks=editGetCallbacks, editSetCallbacks=editSetCallbacks, tipTexts=tipTexts) self.spinSysTable.grid(row=0, column=0, sticky='nsew') buttonFrameinPeakFrame = Frame(PeakFrame) buttonFrameinPeakFrame.grid(sticky='ew') self.findButton = Button( buttonFrameinPeakFrame, text=' Go to Peak ', borderwidth=1, padx=2, pady=1, command=self.findPeak, tipText='Locate the currently selected peak in the specified window' ) self.findButton.grid(row=0, column=0, sticky='e') label = Label(buttonFrameinPeakFrame, text='in window:') label.grid(row=0, column=1, sticky='w') self.windowPulldown = PulldownList( buttonFrameinPeakFrame, callback=self.selectWindowPane, tipText='Choose the spectrum window for locating peaks or strips') self.windowPulldown.grid(row=0, column=2, sticky='w') self.assignSelectedPeaksButton = Button( buttonFrameinPeakFrame, text='Assign Resonances to Peak(s)', borderwidth=1, padx=2, pady=1, command=self.assignSelectedPeaks, tipText= 'Assign resonances to peak dimensions, this of course only works when the peak is found in the spectrum.' ) self.assignSelectedPeaksButton.grid(row=0, column=3, sticky='ew') self.assignSelectedSpinSystemsToResiduesButton = Button( buttonFrameinPeakFrame, text='Assign Spinsystems to Residues', borderwidth=1, padx=2, pady=1, command=self.assignSelectedSpinSystemsToResidues, tipText='Assign spinsystems to residues') self.assignSelectedSpinSystemsToResiduesButton.grid(row=0, column=4, sticky='ew') headingList = [ '#', 'spectrum', 'Dim1', 'Dim2', 'Dim3', 'c.s. dim1', 'c.s. dim2', 'c.s. dim3', 'colabelling' ] tipTexts = [ 'Peak number, only present when the peak was actually found in the spectrum.', 'Name of the spectrum', 'Name of atomSet measured in this dimension. Dimension number corresponds to Ref Exp Dim as indicated by going in the main menu to Experiment-->Experiments-->Experiment Type', 'Name of atomSet measured in this dimension. Dimension number corresponds to Ref Exp Dim as indicated by going in the main menu to Experiment-->Experiments-->Experiment Type', 'Name of atomSet measured in this dimension. Dimension number corresponds to Ref Exp Dim as indicated by going in the main menu to Experiment-->Experiments-->Experiment Type', 'Chemical Shift', 'Chemical Shift', 'Chemical Shift', 'Colabbeling fraction over all nuclei that are on the magnetization transfer pathway during the experiment that gave rise to the peak, including visited nuclei that were not measured in any of the peak dimensions' ] #editWidgets = [None, None, None, None, None, None, None, None, None] editGetCallbacks = [ None, None, None, None, None, None, None, None, None ] #editGetCallbacks = [self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak, self.selectPeak] editSetCallbacks = [ None, None, None, None, None, None, None, None, None ] self.displayPeakTable = ScrolledMatrix(PeakFrame, headingList=headingList, multiSelect=True, tipTexts=tipTexts) #editWidgets=editWidgets, multiSelect=True, # editGetCallbacks=editGetCallbacks, # editSetCallbacks=editSetCallbacks, # tipTexts=tipTexts) self.displayPeakTable.grid(row=1, column=0, sticky='nsew') self.windowPane = None self.updateWindows() def selectSpinSystemForTable(self, spinSystem, row, column, table): table_number = self.displayResultsTables.index(table) self.selectSpinSystem(table_number, spinSystem) @lockUntillResults def showResults(self): self.updateResultsTable() @lockUntillResults def selectLink(self, number, topRow): if topRow: self.selectedResidueA = None self.selectedResidueB = None self.selectedLinkA = number self.selectedLinkB = None else: self.selectedResidueA = None self.selectedResidueB = None self.selectedLinkA = None self.selectedLinkB = number self.updateButtons() self.updateLink() @lockUntillResults def selectRelativeResidue(self, number, topRow): if topRow: self.selectedResidueA = number self.selectedResidueB = None self.selectedLinkA = None self.selectedLinkB = None else: self.selectedResidueA = None self.selectedResidueB = number self.selectedLinkA = None self.selectedLinkB = None self.updateButtons() self.updateLink() def updateLink(self): ''' Checks for any selected link (self.selectedLinkA or self.selectedLinkB) and calls updatePeakTable with the correct residue Object and spinsystem Objects. ''' number = self.selectedLinkA or self.selectedLinkB or self.selectedResidueA or self.selectedResidueB if not number: self.emptyPeakTable() return dataModel = self.dataModel resNumber = self.resultsResidueNumber chain = dataModel.chain residues = chain.residues solutionNumber = self.selectedSolution - 1 if self.selectedResidueA: res = residues[resNumber - 4 + number] spinSystem = res.solutions[solutionNumber] self.selectedLink = None if res and spinSystem: self.selectedLink = res.getIntraLink(spinSystem) #self.updatePeakTableIntra(res, spinSystem) self.updateSpinSystemTable(spinSystem) elif self.selectedResidueB: res = residues[resNumber - 4 + number] spinSystem = res.userDefinedSolution self.selectedLink = None if res and spinSystem: self.selectedLink = res.getIntraLink(spinSystem) #self.updatePeakTableIntra(res, spinSystem) self.updateSpinSystemTable(spinSystem) elif self.selectedLinkA: resA = residues[resNumber - 4 + number] resB = residues[resNumber - 3 + number] spinSystemA = resA.solutions[solutionNumber] spinSystemB = resB.solutions[solutionNumber] self.selectedLink = None if resA and spinSystemA and spinSystemB: self.selectedLink = resA.getLink(spinSystemA, spinSystemB) #self.updatePeakTable(resA, spinSystemA, spinSystemB) # and resA.userDefinedSolution and resB.userDefinedSolution: elif self.selectedLinkB: resA = residues[resNumber - 4 + number] resB = residues[resNumber - 3 + number] spinSystemA = resA.userDefinedSolution spinSystemB = resB.userDefinedSolution self.selectedLink = None if resA and spinSystemA and spinSystemB: self.selectedLink = resA.getLink(spinSystemA, spinSystemB) #self.updatePeakTable(resA, spinSystemA, spinSystemB) self.updatePeakTable() def emptyPeakTable(self): self.displayPeakTable.update(objectList=[], textMatrix=[], colorMatrix=[]) def updatePeakTable(self): ''' Updates the peak table to show the peaks that are found for a sequencial pair of spinsystems A and B. If there is not a linkobject found for spinsystems A and B the table is emptied. Also sets the selected peak to None. ''' link = self.selectedLink if not link: self.emptyPeakTable() else: resA, resB = link.getResidues() spinSystemA, spinSystemB = link.getSpinSystems() data = [] objectList = [] peakLinks = link.getAllPeakLinks() if not peakLinks: self.emptyPeakTable() return maxDimenionality = max([ len(peakLink.getSimulatedPeak().getContribs()) for peakLink in peakLinks ]) for peakLink in peakLinks: serial = None realPeak = peakLink.getPeak() simPeak = peakLink.getSimulatedPeak() atomTexts = [None] * maxDimenionality chemicalShifts = [None] * maxDimenionality for simulatedPeakContrib in simPeak.getContribs(): atomName = simulatedPeakContrib.getAtomName() #ccpCode = simulatedPeakContrib.getCcpCode() dimNumber = simulatedPeakContrib.getDimNumber() if resA is simulatedPeakContrib.getResidue(): spinSystemDescription = spinSystemA.getDescription( noSerialWhenSeqCodeIsPresent=True) else: spinSystemDescription = spinSystemB.getDescription( noSerialWhenSeqCodeIsPresent=True) atomTexts[dimNumber - 1] = '%s %s' % (spinSystemDescription, atomName) if realPeak: serial = realPeak.getSerial() for dim in realPeak.getDimensions(): chemicalShifts[dim.getDimNumber() - 1] = dim.getChemicalShift() else: shiftListSerial = simPeak.getSpectrum().getShiftListSerial( ) for resonance, simulatedPeakContrib in zip( peakLink.getResonances(), simPeak.getContribs()): if resonance: chemicalShifts[simulatedPeakContrib.getDimNumber() - 1] = resonance.getChemicalShift( shiftListSerial) else: chemicalShifts[simulatedPeakContrib.getDimNumber() - 1] = '?' data.append([serial, simPeak.getSpectrum().name] + atomTexts + chemicalShifts + [simPeak.colabelling]) objectList.append(peakLink) headingList = ['#', 'spectrum'] + [ 'dim%s' % a for a in range(1, maxDimenionality + 1) ] + ['c.s. dim%s' % a for a in range(1, maxDimenionality + 1)] + ['colabbeling'] self.displayPeakTable.update(objectList=objectList, textMatrix=data, headingList=headingList) def findPeak(self): if not self.windowPane: return selectedPeakLinks = self.displayPeakTable.currentObjects if not selectedPeakLinks: self.guiParent.updateInfoText('Please select a peak first.') return if len(selectedPeakLinks) > 1: self.guiParent.updateInfoText('Can only go to one peak at a time.') return selectedPeakLink = selectedPeakLinks[0] selectedPeak = selectedPeakLink.getPeak() if selectedPeak: ccpnPeak = selectedPeak.getCcpnPeak() createPeakMark(ccpnPeak, lineWidth=2.0) windowFrame = self.windowPane.getWindowFrame() windowFrame.gotoPeak(ccpnPeak) else: simPeak = selectedPeakLink.getSimulatedPeak() spectrum = simPeak.getSpectrum() ccpnSpectrum = spectrum.getCcpnSpectrum() view = getSpectrumWindowView(self.windowPane, ccpnSpectrum) if not view: self.guiParent.updateInfoText( 'This peak cannot be displayed in the window you chose.') axisMappingByRefExpDimNumber = {} for axisMapping in view.axisMappings: refExpDimNumber = axisMapping.analysisDataDim.dataDim.expDim.refExpDim.dim axisMappingByRefExpDimNumber[refExpDimNumber] = axisMapping positionToGoTo = {} markPosition = [] axisTypes = [] for resonance, contrib in zip(selectedPeakLink.getResonances(), simPeak.getContribs()): dimNumber = contrib.getDimNumber() axisMapping = axisMappingByRefExpDimNumber.get(dimNumber) label = axisMapping.label if resonance: axisType = axisMapping.axisPanel.axisType chemicalShift = resonance.getChemicalShift() positionToGoTo[label] = chemicalShift markPosition.append(chemicalShift) axisTypes.append(axisType) # Not drawing a mark at this chemical shift, just hoovering to # the good region in the spectrum else: ccpCode = contrib.getResidue().getCcpCode() atomName = contrib.getAtomName() medianChemicalShift = self.getMedianChemicalShift( ccpCode, atomName) if medianChemicalShift: positionToGoTo[label] = medianChemicalShift if positionToGoTo: windowFrame = self.windowPane.getWindowFrame() windowFrame.gotoPosition(positionToGoTo) if markPosition: createNonPeakMark(markPosition, axisTypes) def assignSelectedPeaks(self): selectedPeakLinks = self.displayPeakTable.currentObjects for pl in selectedPeakLinks: peak = pl.getPeak() if peak: for resonance, dimension in zip(pl.getResonances(), peak.getDimensions()): ccpnResonance = resonance.getCcpnResonance() ccpnDimension = dimension.getCcpnDimension() if ccpnResonance and ccpnDimension: assignResToDim(ccpnDimension, ccpnResonance) def assignSelectedSpinSystemsToResidues(self): link = self.selectedLink if link: residues = link.getResidues() spinSystems = link.getSpinSystems() ccpnSpinSystems = [] ccpnResidues = [] for spinSys, res in zip(spinSystems, residues): if spinSys and res: ccpnSpinSystems.append(spinSys.getCcpnResonanceGroup()) ccpnResidues.append(res.getCcpnResidue()) assignSpinSystemstoResidues(ccpnSpinSystems, ccpnResidues, guiParent=self.guiParent) self.updateButtons() self.updateButtons() self.updateResultsTable() self.updatePeakTable() def getMedianChemicalShift(self, ccpCode, atomName): nmrRefStore = self.project.findFirstNmrReferenceStore( molType='protein', ccpCode=ccpCode) chemCompNmrRef = nmrRefStore.findFirstChemCompNmrRef( sourceName='RefDB') chemCompVarNmrRef = chemCompNmrRef.findFirstChemCompVarNmrRef( linking='any', descriptor='any') if chemCompVarNmrRef: chemAtomNmrRef = chemCompVarNmrRef.findFirstChemAtomNmrRef( name=atomName) if chemAtomNmrRef: distribution = chemAtomNmrRef.distribution maxIndex = max([ (value, index) for index, value in enumerate(distribution) ])[1] return chemAtomNmrRef.refValue + chemAtomNmrRef.valuePerPoint * ( maxIndex - chemAtomNmrRef.refPoint) return None def selectWindowPane(self, windowPane): if windowPane is not self.windowPane: self.windowPane = windowPane def updateWindows(self): index = 0 windowPane = None windowPanes = [] names = [] peakList = None tryWindows = WindowBasic.getActiveWindows(self.project) windowData = [] getName = WindowBasic.getWindowPaneName for window in tryWindows: for windowPane0 in window.spectrumWindowPanes: # if WindowBasic.isSpectrumInWindowPane(windowPane0, spectrum): windowData.append((getName(windowPane0), windowPane0)) windowData.sort() names = [x[0] for x in windowData] windowPanes = [x[1] for x in windowData] if windowPanes: if windowPane not in windowPanes: windowPane = windowPanes[0] index = windowPanes.index(windowPane) else: windowPane = None self.selectWindowPane(windowPane) self.windowPulldown.setup(names, windowPanes, index) def selectSpinSystem(self, number, spinSystem): res = self.dataModel.chain.residues[self.resultsResidueNumber - 3 + number] oldSpinSystemForResidue = res.userDefinedSolution if oldSpinSystemForResidue and res.getSeqCode( ) in oldSpinSystemForResidue.userDefinedSolutions: oldSpinSystemForResidue.userDefinedSolutions.remove( res.getSeqCode()) res.userDefinedSolution = spinSystem spinSystem.userDefinedSolutions.append(res.getSeqCode()) # self.updateSpinSystemTable(spinSystem) self.updateLink() self.updateButtons() def updateSpinSystemTable(self, spinSystem): if not spinSystem: self.emptySpinSystemTable() return dataModel = self.dataModel residues = dataModel.chain.residues data = [] colorMatrix = [] for residue in spinSystem.allowedResidues: oneRow = [] oneRowColor = [] string = str(residue.getSeqCode()) + ' ' + residue.getCcpCode() oneRow.append(string) resonanceGroup = spinSystem.getCcpnResonanceGroup() ccpnResidue = residue.ccpnResidue # Assigned in the project to this residue if resonanceGroup and resonanceGroup.residue and resonanceGroup.residue is ccpnResidue: oneRow.append('x') else: oneRow.append(None) # The user selected this res for this spinsystem (could be more # than one res for which this happens) if residue.getSeqCode() in spinSystem.userDefinedSolutions: oneRow.append('x') else: oneRow.append(None) if residue.solutions[self.selectedSolution - 1] == spinSystem: oneRow.append('x') else: oneRow.append(None) if spinSystem.solutions: percentage = spinSystem.solutions.count( residue.getSeqCode()) / float(len( spinSystem.solutions)) * 100.0 else: percentage = 0 oneRow.append(int(percentage + 0.5)) color = pick_color_by_percentage(percentage) oneRowColor = [color] * 5 data.append(oneRow) colorMatrix.append(oneRowColor) self.spinSysTable.update(objectList=data, textMatrix=data, colorMatrix=colorMatrix) self.spinSysTable.sortDown = False self.spinSysTable.sortLine(-1, noUpdate=True) def emptySpinSystemTable(self): self.spinSysTable.update(objectList=[], textMatrix=[], colorMatrix=[]) @lockUntillResults def adoptSolution(self): dataModel = self.dataModel selectedSolution = self.selectedSolution for res in dataModel.chain.residues: spinSystem = res.solutions[selectedSolution - 1] res.userDefinedSolution = spinSystem spinSystem.userDefinedSolutions = [res.getSeqCode()] self.updateLink() self.updateButtons() @lockUntillResults def resultsPrevSolution(self): if self.selectedSolution != 1: self.selectedSolution = self.selectedSolution - 1 self.resultsSolutionNumberEntry.set(self.selectedSolution) self.updateLink() self.updateButtons() self.updateEnergy() @lockUntillResults def resultsNextSolution(self): amountOfRepeats = len(self.dataModel.chain.residues[0].solutions) if self.selectedSolution < amountOfRepeats: self.selectedSolution = self.selectedSolution + 1 self.resultsSolutionNumberEntry.set(self.selectedSolution) self.updateLink() self.updateButtons() self.updateEnergy() @lockUntillResults def resultsPrevResidue(self): residues = self.dataModel.chain.residues #chainLength = len(residues) new_value = self.resultsResidueNumber if self.resultsSelectedCcpCode == 'residue': if self.resultsResidueNumber != 3: new_value = self.resultsResidueNumber - 1 else: for res in residues: if res.getSeqCode() == self.resultsResidueNumber: break elif res.getCcpCode() == self.resultsSelectedCcpCode: new_value = res.getSeqCode() if new_value < 3: new_value = 3 if self.resultsResidueNumber != new_value: self.resultsResidueNumber = new_value self.resultsResidueNumberEntry.set(self.resultsResidueNumber) self.updateLink() self.updateButtons() self.updateButtons() self.updateResultsTable() self.updateResidueLabels() @lockUntillResults def resultsNextResidue(self): residues = self.dataModel.chain.residues chainLength = len(residues) new_value = self.resultsResidueNumber if self.resultsSelectedCcpCode == 'residue': if self.resultsResidueNumber != chainLength - 2: new_value = self.resultsResidueNumber + 1 else: for res in residues[(self.resultsResidueNumber):]: if res.getCcpCode() == self.resultsSelectedCcpCode: new_value = res.getSeqCode() if new_value > chainLength - 2: new_value = chainLength - 2 break if self.resultsResidueNumber != new_value: self.resultsResidueNumber = new_value self.resultsResidueNumberEntry.set(self.resultsResidueNumber) self.updateLink() self.updateButtons() self.updateButtons() self.updateResultsTable() self.updateResidueLabels() def resultsChangeSelectedCcpCode(self, ccpCode): self.resultsSelectedCcpCode = ccpCode @lockUntillResults def resultsUpdateAfterEntry(self, event=None): ''' Update for entry of residue number in strip plots ''' residues = self.dataModel.chain.residues value = self.resultsResidueNumberEntry.get() if value == self.resultsResidueNumber: return else: self.resultsResidueNumber = value if value < 3: self.resultsResidueNumberEntry.set(3) self.resultsResidueNumber = 3 elif value > len(residues) - 2: self.resultsResidueNumber = len(residues) - 2 self.resultsResidueNumberEntry.set(self.resultsResidueNumber) else: self.resultsResidueNumberEntry.set(self.resultsResidueNumber) self.updateLink() self.updateButtons() self.updateButtons() self.updateResultsTable() self.updateResidueLabels() @lockUntillResults def solutionUpdateAfterEntry(self, event=None): ''' Update for entry of residue number in strip plots ''' Nsolutions = len(self.dataModel.chain.residues[0].solutions) value = self.resultsSolutionNumberEntry.get() if value == self.selectedSolution: return else: self.selectedSolution = value if value < 1: self.resultsSolutionNumberEntry.set(1) self.selectedSolution = 1 elif value > Nsolutions: self.selectedSolution = Nsolutions self.resultsSolutionNumberEntry.set(self.selectedSolution) else: self.resultsSolutionNumberEntry.set(self.selectedSolution) self.updateLink() self.updateButtons() def update(self): self.updateLink() self.updateResidueLabels() self.updateResultsTable() self.updateButtons() self.updateButtons() self.updateEnergy() def updateResultsTable(self): resNumber = self.resultsResidueNumber dataModel = self.dataModel chain = dataModel.chain residues = chain.residues resA = residues[resNumber - 3] resB = residues[resNumber - 2] resC = residues[resNumber - 1] resD = residues[resNumber] resE = residues[resNumber + 1] resList = [resA, resB, resC, resD, resE] tableList = self.displayResultsTables for res, table in zip(resList, tableList): ccpCode = res.ccpCode spinSystemsWithThisCcpCode = dataModel.getSpinSystems()[ccpCode] data = [] colorMatrix = [] objectList = [] jokers = [] realSpinSystems = [] for spinSys in spinSystemsWithThisCcpCode: if spinSys.getIsJoker(): jokers.append(spinSys) else: realSpinSystems.append(spinSys) for spinsys in realSpinSystems: oneRow = [] oneRowColor = [] # self.getStringDescriptionOfSpinSystem(spinsys) spinSystemInfo = spinsys.getDescription() oneRow.append(spinSystemInfo) assignmentPercentage = int( float(res.solutions.count(spinsys)) / len(res.solutions) * 100.0) oneRow.append(assignmentPercentage) objectList.append(spinsys) color = pick_color_by_percentage(assignmentPercentage) oneRowColor = [color, color] data.append(oneRow) colorMatrix.append(oneRowColor) if jokers: oneRow = ['Joker'] NumberOfAssignmentsToJoker = 0 for spinSys in jokers: NumberOfAssignmentsToJoker += res.solutions.count(spinSys) assignmentPercentage = int( float(NumberOfAssignmentsToJoker) / len(res.solutions) * 100.0) oneRow.append(assignmentPercentage) color = pick_color_by_percentage(assignmentPercentage) oneRowColor = [color, color] data.append(oneRow) colorMatrix.append(oneRowColor) objectList.append(jokers[0]) percentages = [datapoint[1] for datapoint in data] tableData = sorted(zip(percentages, data, objectList, colorMatrix), reverse=True) percentage, data, objectList, colorMatrix = zip(*tableData) table.update(objectList=objectList, textMatrix=data, colorMatrix=colorMatrix) def updateResidueLabels(self): resList = self.getCurrentlyDisplayedResidues() labels = self.residueLabels for residue, label in zip(resList, labels): text = str(residue.getSeqCode()) + ' ' + residue.getCcpCode() label.set(text) def updateButtons(self): self.updateButtonHighLights() self.updateResultsTopRowButtons() self.updateResultsBottomRowButtons() def updateResultsTopRowButtons(self): resList = self.getCurrentlyDisplayedResidues() buttons = self.sequenceButtons.buttons[::2] for button, res in zip(buttons, resList): spinsys = res.solutions[self.selectedSolution - 1] # str(res.getSeqCode()) + ' ' + res.getCcpCode() + ': ' + # spinsys.getDescription() # self.getStringDescriptionOfSpinSystem(spinsys) text = spinsys.getDescription(noSerialWhenSeqCodeIsPresent=False) button.config(text=text) def updateResultsBottomRowButtons(self): resList = self.getCurrentlyDisplayedResidues() buttons = self.sequenceButtonsB.buttons[::2] for button, res in zip(buttons, resList): if res.userDefinedSolution: selectedSpinSystem = res.userDefinedSolution text = selectedSpinSystem.getDescription( noSerialWhenSeqCodeIsPresent=False) if len(selectedSpinSystem.userDefinedSolutions) > 1: # The red color signals that the spinssystem is used in # more than 1 place in the sequence button.config(text=text, bg=highLightRed) else: button.config(text=text) else: # str(res.getSeqCode()) + ' ' + res.getCcpCode() + ': -' text = '-' button.config(text=text) def updateButtonHighLights(self): self.setAllButtonsToGrey() if self.selectedResidueA: buttons = [ self.sequenceButtons.buttons[0], self.sequenceButtons.buttons[2], self.sequenceButtons.buttons[4], self.sequenceButtons.buttons[6], self.sequenceButtons.buttons[8] ] buttons[self.selectedResidueA - 1].config(bg=highLightYellow) elif self.selectedResidueB: buttons = [ self.sequenceButtonsB.buttons[0], self.sequenceButtonsB.buttons[2], self.sequenceButtonsB.buttons[4], self.sequenceButtonsB.buttons[6], self.sequenceButtonsB.buttons[8] ] buttons[self.selectedResidueB - 1].config(bg=highLightYellow) elif self.selectedLinkA: buttons = [ self.sequenceButtons.buttons[1], self.sequenceButtons.buttons[3], self.sequenceButtons.buttons[5], self.sequenceButtons.buttons[7] ] buttons[self.selectedLinkA - 1].config(bg=highLightYellow) elif self.selectedLinkB: buttons = [ self.sequenceButtonsB.buttons[1], self.sequenceButtonsB.buttons[3], self.sequenceButtonsB.buttons[5], self.sequenceButtonsB.buttons[7] ] buttons[self.selectedLinkB - 1].config(bg=highLightYellow) def updateEnergy(self): text = 'energy: %s' % int( self.dataModel.getEnergy(self.selectedSolution - 1) + 0.5) self.energyLabel.set(text) self.energyLabel.update() def setAllButtonsToGrey(self): for button in self.sequenceButtons.buttons + self.sequenceButtonsB.buttons: button.config(bg='grey83') def setAllRedButtonsToGrey(self): for button in self.sequenceButtons.buttons + self.sequenceButtonsB.buttons: if button.enableFg == highLightRed: button.config(bg='grey83') def getCurrentlyDisplayedResidues(self): resNumber = self.resultsResidueNumber residues = self.dataModel.chain.residues[resNumber - 3:resNumber + 2] return residues def toggleTab(self, index): pass
class ProtocolFrame(Frame): def __init__(self, guiParent, basePopup): # Base popup required to handle notification of data model changes # e.g. new peak lists, so that the GUI can update to the latest # state self.basePopup = basePopup self.guiParent = guiParent self.basePopup.frameShortcuts['Protocol'] = self Frame.__init__(self, guiParent) self.grid_rowconfigure(0, weight=0) self.grid_rowconfigure(1, weight=0, minsize=10) self.grid_rowconfigure(2, weight=0) self.grid_rowconfigure(3, weight=1) self.grid_rowconfigure(4, weight=0, minsize=30) self.grid_rowconfigure(5, weight=0, minsize=30) self.grid_columnconfigure(0, weight=0) self.grid_columnconfigure(1, weight=1) self.grid_columnconfigure(2, weight=0) # build up the body. self.title = Label(self, font='Helvetica16') self.details = Label(self) initial_cols = ['Parameter', 'Type', 'Value'] self.pMatrix = ScrolledMatrix(self, headingList=initial_cols, initialRows=15) editButtonOpts = ['Save', 'Clear', 'New Protocol', 'New Expt Type'] editButtonCmds = [ self.tmpCall, self.tmpCall, self.tmpCall, self.tmpCall ] self.editButtons = ButtonList(self, editButtonOpts, editButtonCmds) # needs custom version self.filter = FilterFrame(self, self.basePopup, text='Filter') # no bean udnerneath for now so mock up nodes self.pTree = Tree(self, width=33) pButtonOpts1 = ['Load', 'Save'] pButtonCmds1 = [self.tmpCall, self.tmpCall] self.pButtons1 = ButtonList(self, pButtonOpts1, pButtonCmds1) pButtonOpts2 = ['New', 'Delete'] pButtonCmds2 = [self.tmpCall, self.tmpCall] self.pButtons2 = ButtonList(self, pButtonOpts2, pButtonCmds2) self.openedLinks = { 'Test 1': ['ParSet 1', 'ParSet 2'], 'Test 2': ['Std Pars', 'Big Pars', 'Little Pars'], 'ARIA': ['default', 'complex'], 'CING': ['Std'], 'ISD': ['protein', 'DNA'] } self.drawFrame() def drawFrame(self): # hack the WF Tree for now. just get is looking OK texts = ['Test 1', 'Test 2', 'ARIA', 'CING', 'ISD'] icons = [] parents = [] callbacks = [] objects = ['Test 1', 'Test 2', 'ARIA', 'CING', 'ISD'] for text in texts: icons.append('list-add') callbacks.append(self.openLink) parents.append(None) self.pTree.update(parents, objects, texts, icons, callbacks) self.title.set('Protocol: Std (ARIA)') self.title.grid(row=1, column=1, padx=5, sticky='w') self.details.set('Description: details about the exp type or protocol') self.details.grid(row=2, column=1, padx=5, sticky='nw') self.pMatrix.grid(row=3, rowspan=2, column=1, padx=5, pady=5, sticky='ew') self.editButtons.grid(row=5, column=1, padx=5, pady=5, sticky='ew') self.filter.grid(row=1, column=2, rowspan=2, sticky='new') self.pTree.grid(row=3, column=2, padx=5, pady=5, sticky='nsew') self.pButtons1.grid(row=4, column=2, padx=5, sticky='ew') self.pButtons2.grid(row=5, column=2, padx=5, sticky='ew') matrix = [] objs = [] matrix.append(['Parameter1', 'String', 'foobar']) objs.append('obj1') matrix.append(['Parameter2', 'Number', '10']) objs.append('obj2') self.pMatrix.update(objectList=objs, textMatrix=matrix) def tmpCall(self): pass def openLink(self, node): tree = node.tree par = node.object print 'opening node "', par, '"' print 'got series "', self.openedLinks[par], '"' if len(self.openedLinks[par]) > 0: for pv in self.openedLinks[par]: icon = 'folder' obj = par + '::' + pv text = pv callback = None tree.add(node, obj, text, icon, callback) def administerNotifiers(self, notifyFunc): for func in ('__init__', 'delete', 'setName'): notifyFunc(self.updateAllAfter, 'ccp.nmr.Nmr.Experiment', func) notifyFunc(self.updateAllAfter, 'ccp.nmr.Nmr.DataSource', func) def updateAllAfter(self, obj): self.after_idle(self.updateAll) def updateAll(self, project=None): if project: self.project = project self.nmrProject = project.currentNmrProject if not self.nmrProject: self.nmrProject = project.newNmrProject(name=project.name) if not self.project: return def quit(self): self.guiParent.parent.destroy() def destroy(self): self.administerNotifiers(self.basePopup.unregisterNotify) Frame.destroy(self)
class UpdateAdministratorPopup(BasePopup, UpdateAgent): def __init__(self, parent, serverLocation=UPDATE_SERVER_LOCATION, serverDirectory=UPDATE_DIRECTORY, dataFile=UPDATE_DATABASE_FILE): UpdateAgent.__init__(self, serverLocation, serverDirectory, dataFile, admin=1) self.fileTypes = [ FileType('Python', ['*.py']), FileType('C', ['*.c']), FileType('All', ['*']) ] self.fileUpdate = None BasePopup.__init__(self, parent=parent, title='CcpNmr Update Administrator', quitFunc=self.quit) def body(self, guiParent): guiParent.grid_columnconfigure(3, weight=1) self.commentsEntry = Entry(self) self.priorityEntry = IntEntry(self) row = 0 label = Label(guiParent, text='Server location:') label.grid(row=row, column=0, sticky='w') location = '' uid = '' httpDir = '' subDir = '' version = 'None' if self.server: location, uid, httpDir, subDir = self.server.identity version = self.server.version or 'None' self.serverEntry = Entry(guiParent, text=location) self.serverEntry.grid(row=row, column=1, stick='w') label = Label(guiParent, text='User ID:') label.grid(row=row, column=2, sticky='w') self.uidEntry = Entry(guiParent, text=uid) self.uidEntry.grid(row=row, column=3, stick='w') row += 1 label = Label(guiParent, text='HTTP directory:') label.grid(row=row, column=0, sticky='w') self.httpDirEntry = Entry(guiParent, text=httpDir) self.httpDirEntry.grid(row=row, column=1, stick='w') label = Label(guiParent, text='Sub-directory:') label.grid(row=row, column=2, sticky='w') self.subDirEntry = Entry(guiParent, text=subDir) self.subDirEntry.grid(row=row, column=3, stick='w') row += 1 self.localVerLabel = Label(guiParent, text='Local version: %s' % self.version) self.localVerLabel.grid(row=row, column=0, sticky='w') self.serverLabel = Label(guiParent, text='Server version: %s' % version) self.serverLabel.grid(row=row, column=2, sticky='w') row += 1 guiParent.grid_rowconfigure(row, weight=1) headingList = [ 'File', 'Location', 'Date', 'Priority', 'Comments', 'StoredAs', ] editWidgets = [ None, None, None, self.priorityEntry, self.commentsEntry ] editGetCallbacks = [ None, None, None, self.getPriority, self.getComments ] editSetCallbacks = [ None, None, None, self.setPriority, self.setComments ] self.scrolledMatrix = ScrolledMatrix(guiParent, headingList=headingList, multiSelect=True, editWidgets=editWidgets, callback=self.selectCell, editGetCallbacks=editGetCallbacks, editSetCallbacks=editSetCallbacks) self.scrolledMatrix.grid(row=row, column=0, columnspan=4, sticky='nsew') row += 1 texts = [ 'Add\nFiles', 'Remove\nFiles', 'Remove\nAll', 'Query\nServer', 'Commit\nSelected', 'Synchronise\nAll', 'Commit\nNew', 'Quit' ] commands = [ self.addFile, self.removeFile, self.removeAll, self.queryFiles, self.synchroniseSelected, self.synchroniseServer, self.updateServer, self.quit ] self.buttonList = ButtonList(guiParent, texts=texts, commands=commands, expands=1) self.buttonList.grid(row=row, column=0, columnspan=4, sticky='ew') self.update() def getPriority(self, fileUpdate): if fileUpdate: self.priorityEntry.set(fileUpdate.priority) def setPriority(self, event): i = self.priorityEntry.get() if self.fileUpdate: self.fileUpdate.priority = i self.update() def getComments(self, fileUpdate): if fileUpdate: self.commentsEntry.set(fileUpdate.details) def setComments(self, event): text = self.commentsEntry.get() if self.fileUpdate: self.fileUpdate.details = text self.update() def quit(self): self.close() self.destroy() sys.exit() def updateServer(self): if self.server: # Unly upload new updates success = self.server.setFileUpdates() self.serverLabel.set('Server version: %s' % self.server.version) if success: self.queryFiles() def synchroniseSelected(self): if self.server: selectedUpdates = self.scrolledMatrix.currentObjects if selectedUpdates: # Refresh all selected updates success = self.server.setFileUpdates( fileUpdates=selectedUpdates, refresh=True) self.serverLabel.set('Server version: %s' % self.server.version) if success: self.queryFiles() def synchroniseServer(self): if self.server: # Refresh all avaiable updates success = self.server.setFileUpdates(refresh=True) self.serverLabel.set('Server version: %s' % self.server.version) if success: self.queryFiles() def queryFiles(self): if self.server: self.server.getFileUpdates() self.update() def addFile(self): if self.server: fileSelectPopup = FileSelectPopup(self, title='Select Source File', dismiss_text='Cancel', file_types=self.fileTypes, multiSelect=True, selected_file_must_exist=True) filePaths = fileSelectPopup.file_select.getFiles() n = len(self.installRoot) for filePath in filePaths: if self.installRoot != filePath[:n]: showWarning( 'Warning', 'Install root %s not found in file path %s' % (self.installRoot, filePath)) continue filePath = filePath[n + 1:] if filePath: dirName, fileName = splitPath(filePath) if fileName[-3:] == '.py': language = 'python' else: language = 'None' fileUpdate = FileUpdate(self.server, fileName, dirName, language, isNew=True) self.update() def removeFile(self): if self.fileUpdate: self.fileUpdate.delete() self.update() def removeAll(self): if self.server: for fileUpdate in list(self.server.fileUpdates): fileUpdate.delete() self.update() def selectAll(self): if self.server: for fileUpdate in self.server.fileUpdates: fileUpdate.isSelected = 1 self.update() def selectCell(self, object, row, col): self.fileUpdate = object self.updateButtons() def updateButtons(self): buttons = self.buttonList.buttons if self.server: buttons[0].enable() buttons[3].enable() buttons[4].enable() else: buttons[0].disable() buttons[3].disable() buttons[4].disable() if self.server and self.server.fileUpdates: buttons[2].enable() else: buttons[2].disable() if self.fileUpdate: buttons[1].enable() else: buttons[1].disable() def update(self): location = self.serverEntry.get() uid = self.uidEntry.get() httpDir = self.httpDirEntry.get() subDir = self.subDirEntry.get() if self.server: if (location, uid, httpDir, subDir) != self.server.identity: self.setServer(location) self.updateButtons() self.fileUpdate = None textMatrix = [] objectList = [] colorMatrix = [] if self.server: for fileUpdate in self.server.fileUpdates: datum = [] datum.append(fileUpdate.fileName) datum.append(fileUpdate.filePath) datum.append(fileUpdate.date) datum.append(fileUpdate.priority) datum.append(fileUpdate.details) datum.append(fileUpdate.storedAs) textMatrix.append(datum) objectList.append(fileUpdate) if fileUpdate.isNew: colorMatrix.append(5 * ['#B0FFB0']) elif not fileUpdate.getIsUpToDate(): colorMatrix.append(5 * ['#FFB0B0']) else: colorMatrix.append(5 * [None]) self.scrolledMatrix.update(textMatrix=textMatrix, objectList=objectList, colorMatrix=colorMatrix)