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 WindowFunctionSelect(BasePopup): help_url = joinPath(getHelpUrlDir(), 'WindowFunctionSelect.html') def __init__(self, parent, format, dim, getValue): # # General setup # self.maxArgs = 4 self.nmrPipe = 'nmrPipe' self.azara = 'azara' self.format = format self.freqDataDim = parent.freqDataDims[format][dim] self.expDimRef = parent.expDimRefs[dim] # # Window function settings (different per program) # self.windowFunctions = {} specWidth = self.freqDataDim.spectralWidthOrig # TODO: these for azara still have to change a bit... self.windowFunctions[self.azara] = [ ['sine', 'sinebell', [['Angle (deg)', 0, 'deg']]], ['sine^2', 'sinebell2', [['Angle (deg)', 0, 'deg']]], ['exponential (fixed)', 'decay', [['End value', 0.5, 'end']]], [ 'exponential', 'decay_sw', [['Line broadening (Hz)', 10, 'lb'], ['Spectral width (Hz)', specWidth, 'sw']] ], [ 'gaussian (fixed)', 'gaussian', [['Total points fraction for max', 0.25, 'frac'], ['End value', 1, 'end']] ], [ 'gaussian', 'gaussian_sw', [['Line broadening (Hz)', 10, 'lb'], ['Sharpening factor', 0.7, 'shrp'], ['Spectral width (Hz)', specWidth, 'sw']] ], [ 'inverse cosine', 'inv_cosine', [['Frequency (Hz)', 0, 'freq'], ['Spectral width (Hz)', specWidth, 'sw']] ] ] self.windowFunctions[self.nmrPipe] = [ [ 'sine', 'SP', [['Start sine at (pi)', 0, 'off'], ['End sine at (pi)', 1, 'end'], ['Sine to power', 1, 'pow']] ], ['exponential', 'EM', [['Line broadening (Hz)', 10, 'lb']]], [ 'lorentz-gauss', 'GM', [['Inverse exp width (Hz)', 0, 'g1'], ['Gaussian width (Hz)', 0, 'g2'], ['Center (0-1)', 0, 'g3']] ], [ 'gaussian', 'GMB', [['Exponential term', 0, 'lb'], ['Gaussian term', 0, 'gb']] ], [ 'trapezoid', 'TM', [['Ramp length left', 0, 't1'], ['Ramp length right', 0, 't2']] ], [ 'triangle', 'TRI', [['Point loc of apex', 0, 'loc'], ['Left edge height', 0, 'lHi'], ['Right edge height', 0, 'rHi']] ] ] # # Make list of names for pulldown menu # self.windowFuncList = [] for (winFunc, winFuncAppl, winFuncArgs) in self.windowFunctions[format]: self.windowFuncList.append(winFunc) # # Get the right window function from appldata (if there) # self.windowFunctionKeyword = 'windowFunction' self.winFuncIndex = self.getWindowFunctionIndex() # # Set defaults depending on nucleus type if no window function set # if self.winFuncIndex == -1: if format == self.nmrPipe: self.winFuncIndex = 0 if self.expDimRef.isotopeCodes[0] == '1H': # use SP '-off 0.3333 -pow 2.0' self.windowFunctions[self.nmrPipe][ self.winFuncIndex][2][0][1] = 0.3333 self.windowFunctions[self.nmrPipe][ self.winFuncIndex][2][2][1] = 2.0 else: # for non-H, use SP '-off 0.5 -pow 2.0' self.windowFunctions[self.nmrPipe][ self.winFuncIndex][2][0][1] = 0.5 self.windowFunctions[self.nmrPipe][ self.winFuncIndex][2][2][1] = 2.0 elif format == self.azara: self.winFuncIndex = 1 if self.expDimRef.isotopeCodes[0] == '1H': # use sinebell2 60 self.windowFunctions[self.azara][ self.winFuncIndex][2][0][1] = 60 else: # for non-H, use sinebell2 90 self.windowFunctions[self.azara][ self.winFuncIndex][2][0][1] = 90 # Get actual values for arguments from appldata if they exists! self.updateWindowFunctions() # Also using this to return the current window function 'string value' if not getValue: # modal = true means that it won't continue unless this one returns value BasePopup.__init__( self, parent=parent, title='Select window function', modal=False, transient=True, ) def body(self, master): # Master is the owner widget (not self.parent) - parent of the widget here # # Popup window # self.entries = [] self.labels = [] value = 0 row = 0 label = Label(master, text="Window function:") label.grid(row=row, column=0, sticky=Tkinter.EW) self.menuRow = row self.menu = PulldownMenu(master, entries=self.windowFuncList, selected_index=self.winFuncIndex) self.menu.grid(row=row, column=1, sticky=Tkinter.W, ipadx=20) self.menulabel = Label( master, text="(" + self.windowFunctions[self.format][self.winFuncIndex][1] + ")") self.menulabel.grid(row=row, column=2, sticky=Tkinter.E) # # Setup arguments - make room for four # for argIndex in range(0, self.maxArgs): row = row + 1 try: argRef = self.windowFunctions[self.format][ self.winFuncIndex][2][argIndex] argName = argRef[0] argValue = argRef[1] except: argName = None argValue = None self.labels.append(Label(master, text="%s" % argName)) self.labels[-1].grid(row=row, column=0, sticky=Tkinter.EW) self.entries.append(Entry(master, text=str(argValue))) self.entries[-1].grid(row=row, column=1, columnspan=2, sticky=Tkinter.W) if not argName: self.labels[-1].grid_forget() self.entries[-1].grid_forget() # # Add callback to menu after setup # self.menu.callback = self.updateWindow row = row + 1 texts = ['OK'] commands = [ self.ok ] # This calls 'ok' in BasePopup, this then calls 'apply' in here buttons = createDismissHelpButtonList(master, texts=texts, commands=commands, help_url=self.help_url) buttons.grid(row=row, column=0, columnspan=3) def getApplDataAndReturnString(self): keyword = self.windowFunctionKeyword returnString = self.windowFunctions[self.format][self.winFuncIndex][0] winFuncName = self.windowFunctions[self.format][self.winFuncIndex][1] for (argName, argValue, argShort ) in self.windowFunctions[self.format][self.winFuncIndex][2]: applData = self.freqDataDim.findFirstApplicationData( application=self.format, keyword=keyword + winFuncName + argShort) returnString += ' ' + argShort if not applData: returnString += ' ' + str(argValue) else: returnString += ' ' + str(applData.value) return returnString def updateWindowFunctions(self): keyword = self.windowFunctionKeyword winFuncName = self.windowFunctions[self.format][self.winFuncIndex][1] # # Update windowfunction parameters # for i in range( 0, len(self.windowFunctions[self.format][self.winFuncIndex][2])): (argName, argValue, argShort ) = self.windowFunctions[self.format][self.winFuncIndex][2][i] applData = self.freqDataDim.findFirstApplicationData( application=self.format, keyword=keyword + winFuncName + argShort) if applData: self.windowFunctions[self.format][ self.winFuncIndex][2][i][1] = str(applData.value) def setApplData(self): keyword = self.windowFunctionKeyword winFuncName = self.windowFunctions[self.format][self.winFuncIndex][1] # # Set windowfunction # applData = self.freqDataDim.findFirstApplicationData( application=self.format, keyword=keyword) if not applData: applData = createAppData(self.freqDataDim, application=self.format, keyword=keyword, value=winFuncName) else: applData.value = winFuncName # # Set windowfunction parameters # for (argName, argValue, argShort ) in self.windowFunctions[self.format][self.winFuncIndex][2]: applData = self.freqDataDim.findFirstApplicationData( application=self.format, keyword=keyword + winFuncName + argShort) if not applData: applData = createAppData(self.freqDataDim, application=self.format, keyword=keyword + winFuncName + argShort, value=str(argValue)) else: applData.value = str(argValue) def getWindowFunctionIndex(self): keyword = self.windowFunctionKeyword applData = self.freqDataDim.findFirstApplicationData( application=self.format, keyword=keyword) if applData: origWinFuncAppl = applData.value for i in range(0, len(self.windowFunctions[self.format])): (winFunc, winFuncAppl, winFuncArgs) = self.windowFunctions[self.format][i] if winFuncAppl == origWinFuncAppl: return i return -1 def updateWindow(self, *args): # # First do a value update of the current stuff? # # # Reset arguments # row = self.menuRow self.winFuncIndex = self.menu.getSelectedIndex() self.menulabel.set( "(" + self.windowFunctions[self.format][self.winFuncIndex][1] + ")") for argIndex in range(0, self.maxArgs): row = row + 1 try: argRef = self.windowFunctions[self.format][ self.winFuncIndex][2][argIndex] argName = argRef[0] argValue = argRef[1] except: argName = None argValue = None self.labels[argIndex].set(argName) self.labels[argIndex].grid(row=row, column=0, sticky=Tkinter.W) self.entries[argIndex].set(str(argValue)) self.entries[argIndex].grid(row=row, column=1, columnspan=2, sticky=Tkinter.W) if not argName: self.entries[argIndex].grid_forget() self.labels[argIndex].grid_forget() def setWindowFunctionsValues(self): self.winFuncIndex for argIndex in range( 0, len(self.windowFunctions[self.format][self.winFuncIndex][2])): argValue = returnFloat(self.entries[argIndex].get()) self.windowFunctions[self.format][ self.winFuncIndex][2][argIndex][1] = argValue def apply(self): self.winFuncIndex = self.menu.getSelectedIndex() self.setWindowFunctionsValues() self.setApplData() return True
class EditSymmetryPopup(BasePopup): def __init__(self, parent, project): self.parent = parent self.ccpnProject = project self.hProject = project.currentHaddockProject self.molPartner = None self.molecules = [] self.symmetrySet = None self.symmetryOp = None self.symmetryCode = None self.waiting = False BasePopup.__init__(self, parent=parent, title='Symmetry Operations') self.font = 'Helvetica 12' self.setFont() def body(self, guiFrame): guiFrame.grid_columnconfigure(0, weight=1) guiFrame.grid_rowconfigure(1, weight=1) frame = LabelFrame(guiFrame, text='Options') frame.grid(row=0,column=0,sticky='ew') frame.grid_columnconfigure(5, weight=1) # Choose type of symmetry set to define or change (if allready present in the model) self.molLabel = Label(frame, text='Symmetry Operator:') self.molLabel.grid(row=0,column=2,sticky='w') self.symmCodePulldown = PulldownMenu(frame, callback=self.setSymmCode, entries=['NCS','C2','C3','C5'], do_initial_callback=False) self.symmCodePulldown.grid(row=0,column=3,sticky='w') frame = LabelFrame(guiFrame, text='Symmetry Operations') frame.grid(row=1,column=0,sticky='nsew') frame.grid_columnconfigure(0, weight=1) frame.grid_rowconfigure(0, weight=1) self.molSysPulldown = PulldownMenu(self, callback=self.setMolSystem, do_initial_callback=False) self.chainSelect = MultiWidget(self, CheckButton, callback=self.setChains, minRows=0, useImages=False) self.segStartEntry = IntEntry(self, returnCallback=self.setSegStart, width=6) self.segLengthEntry = IntEntry(self, returnCallback=self.setSegLength, width=6) headings = ['#','Symmetry\noperator','Mol System','Chains','Start\nresidue','Segment\nlength'] editWidgets = [None, None, self.molSysPulldown, self.chainSelect, self.segStartEntry, self.segLengthEntry] editGetCallbacks = [None, None, self.getMolSystem, self.getChains, self.getSegStart, self.getSegLength] editSetCallbacks = [None, self.setSymmCode, self.setMolSystem, self.setChains, self.setSegStart, self.setSegLength] self.symmetryMatrix = ScrolledMatrix(frame,headingList=headings, callback=self.selectSymmetry, editWidgets=editWidgets, editGetCallbacks=editGetCallbacks, editSetCallbacks=editSetCallbacks) self.symmetryMatrix.grid(row=0,column=0,sticky='nsew') texts = ['Add Symmetry Set','Remove Symmetry Set'] commands = [self.addSymmetrySet,self.removeSymmetrySet] self.buttonList = createDismissHelpButtonList(guiFrame, texts=texts, commands=commands, expands=True) self.buttonList.grid(row=2,column=0,sticky='ew') self.updateMolPartners() self.notify(self.registerNotify) #Temporary report of parameters print self.molSystem print self.molecules print self.symmetrySet print self.symmetryOp print self.symmetryCode def getMolSystem(self, partner): """Select molecular system from list of molsystems stored in the project""" names = []; index = -1 molSystem = partner.molSystem molSystems = self.ccpnProject.sortedMolSystems() if molSystems: names = [ms.code for ms in molSystems] if molSystem not in molSystems: molSystem = molSystems[0] index = molSystems.index(molSystem) self.molSysPulldown.setup(names, index) def getChains(self, partner): names = [] values = [] molSystem = partner.molSystem if molSystem: for chain in molSystem.sortedChains(): names.append(chain.code) if not partner.chains: values.append(True) elif partner.findFirstChain(chain=chain): values.append(True) else: values.append(False) self.chainSelect.set(values=values,options=names) else: showWarning('Warning','Set Mol System or ensemble first',parent=self) self.symmetryMatrix.keyPressEscape() def getSegLength(self, symmetryOp): if symmetryOp and symmetryOp.segmentLength: self.segLengthEntry.set(symmetryOp.segmentLength) def getSegStart(self): pass def setMolSystem(self, partner, name=None): """Get all molsystems as stored in the project as list""" index = self.molSysPulldown.getSelectedIndex() molSystems = self.ccpnProject.sortedMolSystems() if molSystems: molSystem = molSystems[index] self.molPartner.molSystem = molSystem chains = molSystem.sortedChains() if (not self.molPartner.chains) and chains: setPartnerChains(self.molPartner,chains) self.updateAllAfter() def setChains(self, obj): """Get the list of chains for the selected molsystem""" if self.molPartner and self.molPartner.molSystem: if obj is not None: chains = self.molPartner.molSystem.sortedChains() values = self.chainSelect.get() chains = [chains[i] for i in range(len(values)) if values[i]] setPartnerChains(self.molPartner,chains) self.symmetryMatrix.keyPressEscape() self.updateAllAfter() def setSegLength(self, event): value = self.segLengthEntry.get() or 1 self.symmetryOp.segmentLength = value def setSegStart(self): pass def setSymmCode(self, index, name=None): self.symmetryCode = self.symmCodePulldown.getSelected() def selectSymmetry(self, obj, row, col): self.symmetryOp = obj self.updateMolSysPulldown() def notify(self, notifyFunc): for func in ('__init__', 'delete', 'setSymmetryCode','setSegmentLength'): notifyFunc(self.updateAllAfter, 'molsim.Symmetry.Symmetry', func) for func in ('__init__', 'delete','setfirstSeqId'): notifyFunc(self.updateAllAfter, 'molsim.Symmetry.Segment', func) def addSymmetrySet(self): if not self.ccpnProject.molSystems: showWarning('Warning','No molecular systems present in CCPN project',parent=self) return molSystem = self.ccpnProject.findFirstMolSystem() partner = self.hProject.newHaddockPartner(code=molSystem.code, molSystem=molSystem) setPartnerChains(partner, molSystem.chains) self.updateAllAfter() def removeSymmetrySet(self): pass def updateAllAfter(self, obj=None): if self.waiting: return else: self.waiting = True self.after_idle(self.updateSymmetries, self.updateMolPartners) def updateMolPartners(self): textMatrix = [] objectList = [] for partner in self.hProject.sortedHaddockPartners(): datum = [partner.code, self.symmetryCode, partner.molSystem.code, ','.join([c.chain.code for c in partner.chains]), partner.autoHistidinePstate and 'Yes' or 'No', partner.isDna and 'Yes' or 'No'] objectList.append(partner) textMatrix.append(datum) self.symmetryMatrix.update(objectList=objectList, textMatrix=textMatrix) self.updateMolSysPulldown() def updateMolSysPulldown(self): names = [] index = -1 partners = self.hProject.sortedHaddockPartners() if partners: if self.molPartner not in partners: self.molPartner = partners[0] names = ['Partner %s' % p.code for p in partners] index = partners.index(self.molPartner) else: self.molPartner = None self.molSysPulldown.setup(names, index) def updateSymmetries(self): textMatrix = []; objectList = [] if self.symmetrySet: for symmetryOp in self.symmetrySet.symmetries: chains = []; segments = [] length = symmetryOp.segmentLength for segment in symmetryOp.sortedSegments(): code = segment.chainCode chain = self.molSystem.findFirstChain(code=code) if chain: chains.append(code) seqId = segment.firstSeqId residue1 = chain.findFirstResidue(seqId=seqId) residue2 = chain.findFirstResidue(seqId=seqId+length-1) segments.append('%s:%d-%d' % (code,residue1.seqCode,residue2.seqCode)) datum = [symmetryOp.serial, symmetryOp.symmetryCode, length, '\n'.join(chains), '\n'.join(segments)] objectList.append(symmetryOp) textMatrix.append(datum) self.symmetryMatrix.update(objectList=objectList, textMatrix=textMatrix) self.waiting = False def destroy(self): self.notify(self.unregisterNotify) BasePopup.destroy(self)
def getSelected(self): selected_index = PulldownMenu.getSelectedIndex(self) return self.indexToBoolean[selected_index]
class AtomSelectPopup(TemporaryBasePopup): def __init__(self, parent, matchName, chemAtomList, chemAtomDict, propagateList, ccpCode, shifts, matchType='Resonance', matchInfoPopup=None, selectedIndex=4, title='Select resonance atom match', helpUrl='AtomSelect.html', headerLines=None, modal=False): self.help_url = joinPath(getHelpUrlDir(), helpUrl) # Constructor doesn't do much except call body # The parent is self.parent (parent of the popup) self.chemAtomOrSets = None self.propagate = None self.matchName = matchName self.matchType = matchType self.matchInfoPopup = matchInfoPopup self.chemAtomList = chemAtomList self.chemAtomDict = chemAtomDict self.propagateList = propagateList self.ccpCode = ccpCode self.shifts = shifts self.guiParent = parent self.headerLines = headerLines self.selectedIndex = selectedIndex # modal = true means that it won't continue unless this one returns value TemporaryBasePopup.__init__(self, parent=parent, title=title, modal=modal, transient=True) def showAllAtoms(self): self.chemAtomList = self.chemAtomDict.keys() self.chemAtomList.sort() self.menu.replace(self.chemAtomList) def body(self, master): # # Popup window # row = 0 if self.headerLines: for headerLine in self.headerLines: label = Label(master, text=headerLine) label.grid(row=row, column=0, columnspan=3, sticky=Tkinter.EW) row += 1 label = Label(master, text="Residue type '%s'" % self.ccpCode) label.grid(row=row, column=0, columnspan=3, sticky=Tkinter.EW) row = row + 1 matchNameString = "[%s]" % self.matchName if self.matchInfoPopup: label = Label(master, text="%s:" % self.matchType) label.grid(row=row, column=0, sticky=Tkinter.E) button = Tkinter.Button( master, text=matchNameString, command=lambda: self.matchInfoPopup(self, self.matchName), fg='blue') button.grid(row=row, column=1, columnspan=2) else: label = Label(master, text="%s:" % self.matchType) label.grid(row=row, column=0, sticky=Tkinter.E) label = Label(master, text=matchNameString, fg='blue') label.grid(row=row, column=1, columnspan=2) if self.shifts: row = row + 1 label = Label(master, text="(shifts: %s ppm)" % self.shifts) label.grid(row=row, column=1, columnspan=2, sticky=Tkinter.EW) row = row + 1 label = Label(master, text="Pick atom:") label.grid(row=row, column=0, sticky=Tkinter.E) self.menu = PulldownMenu(master, entries=self.chemAtomList) self.menu.grid(row=row, column=1, columnspan=2, ipadx=20) row = row + 1 label = Label(master, text="Propagate\nmapping to:") label.grid(row=row, column=0, sticky=Tkinter.E) self.propagateMenu = PulldownMenu(master, entries=self.propagateList, selected_index=self.selectedIndex) self.propagateMenu.grid(row=row, column=1, columnspan=2) row = row + 1 texts = ['OK', 'Show all atoms'] commands = [ self.ok, self.showAllAtoms ] # This calls 'ok' in BasePopup, this then calls 'apply' in here buttons = createDismissHelpButtonList(master, texts=texts, commands=commands, dismiss_text='Do not link', dismiss_cmd=self.doNotLink, help_url=self.help_url) buttons.grid(row=row, column=0, columnspan=3) def apply(self): selectionText = self.menu.getSelected() if selectionText == '<None>': return False self.chemAtomOrSets = self.chemAtomDict[selectionText] self.propagate = self.propagateMenu.getSelectedIndex() return True def doNotLink(self): self.propagate = self.propagateMenu.getSelectedIndex() self.close()
class SetupStructureCalcFrame(Frame): def __init__(self, parent, application, *args, **kw): self.parent = parent self.molSystem = None self.constraintSet = None self.application = application self.project = application.project self.waiting = False self.tableObj = None Frame.__init__(self, parent=parent, **kw) self.grid_columnconfigure(3, weight=1) label = Label(self, text='Molecular system: ') label.grid(row=0, column=0, sticky='nw') self.molSysPulldown = PulldownMenu( self, self.changeMolSystem, tipText='Select which molecular system to use in the calculation') self.molSysPulldown.grid(row=0, column=1, sticky='nw') label = Label(self, text='Constraint Set: ') label.grid(row=0, column=2, sticky='nw') self.constraintSetPulldown = PulldownMenu( self, self.changeConstraintSet, tipText='Select which set of restraints to use in the calculation') self.constraintSetPulldown.grid(row=0, column=3, sticky='nw') self.shiftListPulldown = PulldownMenu( parent, callback=self.setShiftList, do_initial_callback=False, tipText='select the shift list to use in the calculation') tipTexts = [ 'The type of ccp object used in the calculation', 'The identifier for the input data', 'A toggle whether to use the data', 'Whether to filter violated restraints', 'Whether to keep CCPN assignments (otherwise new restraint assignments will be used)', 'Whether the restraints are overly anbiguous and need refining', 'The shift list to use for shift-peak matching' ] headingList = [ 'Input Class', 'Id', 'Use?', 'Filter\nViolated', 'Keep\nAssignments?', 'Ambiguous\nProtocol', 'Shift List' ] editWidgets = [ None, None, None, None, None, None, self.shiftListPulldown ] editGetCallbacks = [ None, None, self.toggleUse, self.toggleFilterViol, self.toggleKeepAssign, self.toggleAmbig, self.getShiftList ] editSetCallbacks = [ None, None, None, None, None, None, self.setShiftList ] self.grid_rowconfigure(1, weight=1) self.scrolledMatrix = ScrolledMatrix(self, headingList=headingList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, multiSelect=True, tipTexts=tipTexts, callback=self.selectCell) self.scrolledMatrix.grid(row=1, column=0, columnspan=4, sticky='nsew') self.scrolledMatrix.doEditMarkExtraRules = self.doEditMarkExtraRules #texts = ['','',''] #commands = [None,None,None] #self.bottomButtons = ButtonList(self, texts=texts, expands=True, commands=commands) #self.bottomButtons.grid(row=2, column=0, columnspan=4, sticky='ew') self.updateMolSystems() self.updateConstraintSets() notify = self.application.registerNotify for func in ('__init__', 'delete'): notify(self.updateAfter, 'ccp.nmr.Nmr.PeakList', func) notify(self.updateConstraintSets, 'ccp.nmr.NmrConstraint.NmrConstraintStore', func) notify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem', func) notify(self.updateMolSystems, 'ccp.molecule.MolSystem.Chain', func) for func in ('__init__', 'delete', 'setName'): notify(self.updateAfter, 'ccp.nmr.Nmr.Experiment', func) notify(self.updateAfter, 'ccp.nmr.Nmr.DataSource', func) def doEditMarkExtraRules(self, obj, row, col): className = obj.className if className == 'PeakList': if col == 5: return False elif className == 'DistanceConstraintList': if col in (4, 6): return False else: if col in (4, 5, 6): return False return True def toggleUse(self, obj): bool = not obj.setupStructureCalcFrameDict['use'] obj.setupStructureCalcFrameDict['use'] = bool self.updateAfter() def toggleFilterViol(self, obj): bool = not obj.setupStructureCalcFrameDict['filter'] obj.setupStructureCalcFrameDict['filter'] = bool self.updateAfter() def toggleKeepAssign(self, obj): bool = not obj.setupStructureCalcFrameDict['preserve'] obj.setupStructureCalcFrameDict['preserve'] = bool self.updateAfter() def toggleAmbig(self, obj): bool = not obj.setupStructureCalcFrameDict['ambig'] obj.setupStructureCalcFrameDict['ambig'] = bool self.updateAfter() def selectCell(self, obj, row, col): self.tableObj = obj def getShiftList(self, peakList): names = [] index = -1 shiftLists = getShiftLists(self.project.currentNmrProject) if shiftLists: shiftList = peakList.dataSource.experiment.shiftList if shiftList not in shiftLists: shiftList = shiftLists[0] names = [sl.name or str(sl.serial) for sl in shiftLists] index = shiftLists.index(shiftList) print "getShiftList", names, index self.shiftListPulldown.setup(names, index) def setShiftList(self, index, name=None): print "setShiftList", index, name if not name: index = self.shiftListPulldown.getSelectedIndex() shiftList = getShiftLists(self.project.currentNmrProject)[index] self.tableObj.setupStructureCalcFrameDict['shiftList'] = shiftList self.updateAfter() def updateMolSystems(self, *opt): names = [] index = -1 molSystems = self.getMolSystems() if molSystems: names = [ms.code for ms in molSystems] if self.molSystem not in molSystems: self.molSystem = molSystems[0] index = molSystems.index(self.molSystem) self.molSysPulldown.setup(names, index) def getMolSystems(self): molSystems = [] if self.project: for molSystem in self.project.molSystems: if molSystem.chains: molSystems.append(molSystem) return molSystems def getTableObjects(self): objs = [] if self.project: objs = getThroughSpacePeakLists(self.project) if self.constraintSet: objs.extend(list(self.constraintSet.constraintLists)) return objs def updateConstraintSets(self, obj=None): names = [] index = -1 if self.project and self.project.currentNmrProject: constraintSets = self.project.currentNmrProject.sortedNmrConstraintStores( ) if constraintSets: if self.constraintSet not in constraintSets: self.constraintSet = constraintSets[0] names = [str(cs.serial) for cs in constraintSets] index = constraintSets.index(self.constraintSet) names.append('<None>') self.constraintSetPulldown.setup(names, index) def changeMolSystem(self, i, name): self.molSystem = self.project.findFirstMolSystem(code=name) self.updateAfter() def changeConstraintSet(self, i, name): if name == '<None>': self.constraintSet = None else: self.constraintSet = self.project.currentNmrProject.sortedNmrConstraintStores( )[i] self.updateAfter() def update(self): textMatrix = [] objectList = [] #headingList = ['Input Class','Use?','Filter\nViolated', # 'Keep\nAssignments?','Ambigous\nProtocol','Shift List'] for obj in self.getTableObjects(): if not hasattr(obj, 'setupStructureCalcFrameDict'): obj.setupStructureCalcFrameDict = dict = {} dict['use'] = True dict['filter'] = True dict['preserve'] = False dict['ambig'] = False dict['shiftList'] = None new = True else: dict = obj.setupStructureCalcFrameDict new = False className = obj.className if className == 'PeakList': spectrum = obj.dataSource experiment = spectrum.experiment shiftList = dict['shiftList'] or experiment.shiftList if shiftList: shiftListName = shiftList.name else: shiftListName = '<None>' if new and (self.molSystem not in experiment.molSystems): dict['use'] = False ident = '%s:%s:%d' % (experiment.name, spectrum.name, obj.serial) used = dict['use'] and 'Yes' or 'No' filtered = dict['filter'] and 'Yes' or 'No' preserved = dict['preserve'] and 'Yes' or 'No' ambig = None elif className == 'DistanceConstraintList': shiftListName = None if new: dict['filter'] = True dict['ambig'] = False ident = '%s:%d' % (obj.name or '', obj.serial) used = dict['use'] and 'Yes' or 'No' filtered = dict['filter'] and 'Yes' or 'No' preserved = None ambig = dict['ambig'] and 'Yes' or 'No' else: shiftListName = None if new: dict['filter'] = False dict['ambig'] = False ident = '%s:%d' % (obj.name or '', obj.serial) used = dict['use'] and 'Yes' or 'No' filtered = None preserved = None ambig = None datum = [ className, ident, used, filtered, preserved, ambig, shiftListName ] textMatrix.append(datum) objectList.append(obj) self.waiting = False self.scrolledMatrix.update(textMatrix=textMatrix, objectList=objectList) def getAriaData(self): if not self.project: showWarning('Failure', 'No active project', parent=self) return if not self.molSystem: showWarning('Failure', 'No molecular system selected', parent=self) return if len(self.molSystem.chains) > 1: code = self.molSystem.findFirstChain().code code = askString('Multiple chains', 'Enter chain code:', code, parent=self) chain = self.molSystem.findFirstChain(code=code) else: chain = self.molSystem.findFirstChain() peakData = [] dihedrals = [] ambigs = [] unambigs = [] jCouplings = [] for obj in self.scrolledMatrix.objectList: opts = obj.setupStructureCalcFrameDict if not opts['use']: continue className = obj.className key = getObjectKeyString(obj) if className == 'PeakList': shiftList = opts['shiftList'] if not shiftList: continue datum = { 'shifts': { KEY_ID: getObjectKeyString(shiftList) }, 'peaks': { KEY_ID: key }, 'use_assignments': opts['preserve'], 'trust_assigned_peaks': opts['filter'] } peakData.append(datum) elif className == 'DistanceConstraintList': if opts['ambig']: ambigs.append({ KEY_ID: key, 'filter_contributions': opts['filter'] }) else: unambigs.append({ KEY_ID: key, 'filter_contributions': opts['filter'] }) elif className == 'JCouplingConstraintList': jCouplings.append({KEY_ID: key}) elif className == 'DihedralConstraintList': dihedrals.append({KEY_ID: key}) projFileName = os.path.join(self.project.url.path, self.project.path) dict = { KEY_GENERAL: { 'project_name': self.project.name }, KEY_CCPN: { 'filename': projFileName }, KEY_MOLECULAR_SYSTEM: { KEY_ID: getObjectKeyString(chain) }, KEY_NOES: peakData, KEY_DIHEDRALS: dihedrals, KEY_DISTANCES_AMBIG: ambigs, KEY_DISTANCES_UNAMBIG: unambigs, KEY_JCOUPLINGS: jCouplings } return dict def updateAll(self): self.project = self.application.project self.updateMolSystems() self.updateConstraintSets() self.updateAfter() def updateAfter(self, obj=None): if self.waiting: return else: self.waiting = True self.after_idle(self.update) def destroy(self): notify = self.application.unregisterNotify for func in ('__init__', 'delete'): notify(self.updateAfter, 'ccp.nmr.Nmr.PeakList', func) notify(self.updateConstraintSets, 'ccp.nmr.NmrConstraint.NmrConstraintStore', func) notify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem', func) notify(self.updateMolSystems, 'ccp.molecule.MolSystem.Chain', func) for func in ('__init__', 'delete', 'setName'): notify(self.updateAfter, 'ccp.nmr.Nmr.Experiment', func) notify(self.updateAfter, 'ccp.nmr.Nmr.DataSource', func) Frame.destroy(self)