class EditPeakFindParamsPopup(BasePopup): """ ** Peak Settings and Non-Interactive Peak Finding ** The purpose of this dialog is to allow the user to select settings for finding and integrating peaks, and also to be able to find peaks in an arbitrary region that is specified in a table rather than via a spectrum window. ** Find Parameters tab ** This can be used to specify how peak finding works. First of all, you can search for just positive peaks, just negative peaks or both, and the default is that it is just positive peaks. However, this is further filtered by what the contour levels are. If there are no positive contour levels for a given spectrum then positive peaks are not found even if this dialog says they can be, and similarly if there are no negative contour levels for a given spectrum then negative peaks are not found even if this dialog says they can be. The peak finding algorithm looks for local extrema (maximum for positive peaks and minima for negative peaks). But on a grid there are various ways to define what you mean by an extremum. Suppose you are trying to determine if point p is a maximum (similar considerations apply for minimum). You would want the intensity at all nearby points to be less than or equal to the intensity at p. You can just check points that are just +- one point from p in each dimension, or you can also check "diagonal" points. For example, if you are looking at point p = (x, y) in 2D, then the former would mean checking the four points (x-1, y), (x+1, y) (x, y-1) and (x, y+1), whereas for the latter you would also have to check (x-1, y-1), (x-1, y+1), (x+1, y-1) and (x+1, y+1). In N dimensions the "diagonal" method involves checking 3^N-1 points whereas the "non-diagonal" method involves checking only 2N points. In general the "non-diagonal" method is probably the one to use, and it is the default. Peaks are only found above (for positive peaks) or below (for negative peaks) some threshold. By default this is determined by the contour level for the spectrum. For positive peaks the threshold is the minimum positive contour level, and for negative peaks the threshold is the maximum negative contour level. However these levels can be scaled up (or down) using the "Scale relative to contour levels" option (default value 1). For example, if you have drawn the contour levels low to show a bit of noise, but do not want the noise picked as peaks, then you could select a scale of 2 (or whatever) to increase the threshold. The "Exclusion buffer around peaks" is so that in crowded regions you do not get too many peaks near one location. By default the exclusion buffer is 1 point in each dimension, but this can be increased to make the algorithm find fewer peaks. By default the peak finding only looks at the orthogonal region that is displayed in the given window where peak finding is taking place. Sometimes it looks like a peak should be found because in x, y you can see an extremum, but unless it is also an extremum in the orthogonal dimensions it is not picked. You can widen out the points being examined in the orthogonal dimensions by using the "Extra thickness in orthogonal dims" option, which is specified in points. The "Minimum drop factor" is by what factor the intensity needs to drop from its extreme value for there to be considered to be a peak. This could help remove sinc wiggle peaks, for example. The default is that the drop factor is 0, which in effect means that there is no condition. The "Volume method" is what is used to estimate the volume of peaks that are found. The default is "box sum", which just looks at a fixed size box around the peak centre and sums the intensities in that. The size of the box is set in the table in the Spectrum Widths tab. The "truncated box sum" is the same as "box sum" except that the summing stops in a given direction when (if) the intensities start increasing. The "parabolic" fit fits a quadratic equation in each dimension to the intensity at the peak centre and ad +- 1 points and then uses the equivalent Gaussian fit to estimate the volume. ** Spectrum Widths ** This can be used to specify minimum linewidths (in Hz) for there to be considered a peak to exist in the peak finding algorithm. It is also where the Boxwidth for each dimension in each spectrum is specified. ** Diagonal Exclusions ** This can be used to exclude peaks from being found in regions near the diagonal (so in homonuclear experiments). The exclusion region is specified in ppm and is independent of spectrum. ** Region Peak Find ** This can be used to find peaks non-interactively (so not having to control shift drag inside a spectrum window). The region being analysed is specified in the table. There are two types of conditions that can be specified, "include" for regions that should be included and "exclude" for regions that should be excluded. The regions are specified in ppm. The "Whole Region" button will set the selected row in the table to be the entire fundamental region of the spectrum. The "Add Region" button adds an extra row to the table, and the "Delete Region" button removes the selected row. The "Adjust Params" button goes to the Find Parameters tab. The "Find Peaks!" button does the peak finding. """ def __init__(self, parent, *args, **kw): self.spectrum = None BasePopup.__init__(self, parent=parent, title='Peak : Peak Finding', **kw) def body(self, guiFrame): self.geometry('600x350') guiFrame.expandGrid(0, 0) tipTexts = ['', '', '', ''] options = [ 'Find Parameters', 'Spectrum Widths', 'Diagonal Exclusions', 'Region Peak Find' ] tabbedFrame = TabbedFrame(guiFrame, options=options, grid=(0, 0)) frameA, frameB, frameC, frameD = tabbedFrame.frames self.tabbedFrame = tabbedFrame # Find Params frameA.expandGrid(2, 0) row = 0 label = LabelFrame(frameA, text='Extrema to search for:', grid=(row, 0), gridSpan=(1, 2)) label.expandGrid(0, 1) entries = ['positive and negative', 'positive only', 'negative only'] tipTexts = [ 'Sets whether peak picking within spectra find intensity maxima, minima or both maxima and minima', ] self.extrema_buttons = RadioButtons(label, entries=entries, select_callback=self.apply, direction='horizontal', grid=(0, 0), tipTexts=tipTexts) row += 1 label = LabelFrame(frameA, text='Nearby points to check:', grid=(row, 0), gridSpan=(1, 2)) label.expandGrid(None, 1) entries = ['+-1 in at most one dim', '+-1 allowed in any dim'] tipTexts = [ 'Sets how permissive the peak picking in when searching for intensity extrema; by adding extra points to the selected search region', ] self.adjacent_buttons = RadioButtons(label, entries=entries, select_callback=self.apply, direction='horizontal', grid=(0, 0), tipTexts=tipTexts) row += 1 labelFrame = LabelFrame(frameA, text='Other parameters:', grid=(row, 0), gridSpan=(1, 2)) labelFrame.expandGrid(5, 2) frow = 0 label = Label(labelFrame, text='Scale relative to contour levels:', grid=(frow, 0), sticky='e') tipText = 'Threshold above which peaks are picked, relative to the lowest displayed contour; 1.0 means picking exactly what is visible' self.scale_entry = FloatEntry(labelFrame, grid=(frow, 1), tipText=tipText, returnCallback=self.apply, width=10) self.scale_entry.bind('<Leave>', self.apply, '+') frow += 1 label = Label(labelFrame, text='Exclusion buffer around peaks (in points):', grid=(frow, 0), sticky='e') tipText = 'The size of the no-pick region, in data points, around existing picked peaks; eliminates duplicate picking' self.buffer_entry = IntEntry(labelFrame, returnCallback=self.apply, grid=(frow, 1), width=10, tipText=tipText) self.buffer_entry.bind('<Leave>', self.apply, '+') frow += 1 label = Label(labelFrame, text='Extra thickness in orthogonal dims (in points):', grid=(frow, 0), sticky='e') tipText = 'Sets whether to consider any additional planes (Z dimension) when calculating peak volume integrals' self.thickness_entry = IntEntry(labelFrame, returnCallback=self.apply, width=10, grid=(frow, 1), tipText=tipText) self.thickness_entry.bind('<Leave>', self.apply, '+') frow += 1 label = Label(labelFrame, text='Minimum drop factor (0.0-1.0):', grid=(frow, 0), sticky='e') tipText = '' self.drop_entry = FloatEntry(labelFrame, returnCallback=self.apply, width=10, grid=(frow, 1), tipText=tipText) self.drop_entry.bind('<Leave>', self.apply, '+') frow += 1 label = Label(labelFrame, text='Volume method:', grid=(frow, 0), sticky='e') tipText = 'Selects which method to use to calculate peak volume integrals when peaks are picked; box sizes are specified in "Spectrum Widths"' self.method_menu = PulldownList(labelFrame, texts=PeakBasic.PEAK_VOLUME_METHODS, grid=(frow, 1), callback=self.apply, tipText=tipText) # Spectrum widths frameB.expandGrid(1, 1) label = Label(frameB, text='Spectrum: ') label.grid(row=0, column=0, sticky='e') tipText = 'The spectrum which determines the widths being shown' self.expt_spectrum = PulldownList(frameB, tipText=tipText, callback=self.setSpectrumProperties) self.expt_spectrum.grid(row=0, column=1, sticky='w') self.editLinewidthEntry = FloatEntry(self, text='', returnCallback=self.setLinewidth, width=10) self.editBoxwidthEntry = FloatEntry(self, text='', returnCallback=self.setBoxwidth, width=10) tipTexts = [ 'The number of the spectrum dimension to which the settings apply', 'The nuclear isotope measures in the spectrum dimension', 'The smallest value for the linewidth of a peak for it to be picked', 'The size of the spectrum region to perform the volume integral over' ] headingList = [ 'Dimension', 'Isotope', 'Minimum Linewidth (Hz)', 'Boxwidth' ] editSetCallbacks = [None, None, self.setLinewidth, self.setBoxwidth] editGetCallbacks = [None, None, self.getLinewidth, self.getBoxwidth] editWidgets = [ None, None, self.editLinewidthEntry, self.editBoxwidthEntry ] self.spectrumMatrix = ScrolledMatrix(frameB, initialRows=6, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, headingList=headingList, callback=self.selectCell, tipTexts=tipTexts) self.spectrumMatrix.grid(row=1, column=0, columnspan=2, sticky='nsew') # Diagonal Exclusions frameC.expandGrid(0, 0) tipTexts = [ 'The isotope as measures on the axis of a spectrum window', 'The distance from the homonuclear diagonal line within which no peak picking can occur' ] self.exclusionEntry = FloatEntry(self, text='', returnCallback=self.setExclusion, width=10) headingList = ['Isotope', 'Diagonal Exclusion (ppm)'] editSetCallbacks = [None, self.setExclusion] editGetCallbacks = [None, self.getExclusion] editWidgets = [None, self.exclusionEntry] self.isotopeMatrix = ScrolledMatrix(frameC, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, headingList=headingList, grid=(0, 0), tipTexts=tipTexts) # Region peak find self.regionFindPeakList = None self.regionCondition = None self.regionConditions = [] self.regionCol = 1 row = 0 label = Label(frameD, text='Peak List: ', grid=(0, 0)) tipText = 'Selects which peak list to perform region-wide peak picking for' self.regionPeakListPulldown = PulldownList( frameD, callback=self.changeRegionPeakList, grid=(0, 1), tipText=tipText) row += 1 frameD.expandGrid(row, 1) self.regionEntry = FloatEntry(self, text='', returnCallback=self.setRegion, width=10) self.conditionMenu = PulldownList(self, texts=('include', 'exclude'), callback=self.setCondition) tipTexts = [ 'Whether to include or exclude the states region from region-wide peak picking', ] headingList = ['Condition'] editSetCallbacks = [None] editGetCallbacks = [None] editWidgets = [self.conditionMenu] self.regionFindMatrix = ScrolledMatrix( frameD, headingList=headingList, callback=self.selectRegionCell, editWidgets=editWidgets, editGetCallbacks=editGetCallbacks, editSetCallbacks=editSetCallbacks, grid=(row, 0), gridSpan=(1, 2)) row += 1 tipTexts = [ 'Sets the currently selected region row to cover the whole spectrum', 'Add a new region row, which may them be set for exclusion or inclusion when peak picking large areas', 'Remove the selected region specification', 'Go to the panel for setting the parameters that control how peaks extrema are picked', 'Using the stated regions and parameters, perform region-wide peak picking' ] texts = [ 'Whole Region', 'Add Region', 'Delete Region', 'Adjust Params', 'Find Peaks!' ] commands = [ self.wholeRegion, self.addCondition, self.deleteCondition, self.adjustParams, self.regionFindPeaks ] buttons = ButtonList(frameD, texts=texts, commands=commands, grid=(row, 0), gridSpan=(1, 2), tipTexts=tipTexts) buttons.buttons[4].config(bg='#B0FFB0') utilButtons = UtilityButtonList(tabbedFrame.sideFrame, grid=(0, 0), helpUrl=self.help_url, sticky='e') self.dataDim = None self.setParamsEntries() self.updateSpectrum() self.setIsotopeProperties() self.updateRegionPeakLists() self.administerNotifiers(self.registerNotify) def administerNotifiers(self, notifyFunc): # Many more needed here, esp on the AnalysisProject prams for func in ('__init__', 'delete', 'setName'): notifyFunc(self.updateRegionPeakLists, 'ccp.nmr.Nmr.DataSource', func) notifyFunc(self.updateRegionPeakLists, 'ccp.nmr.Nmr.Experiment', func) for func in ('__init__', 'delete'): notifyFunc(self.updateRegionPeakLists, 'ccp.nmr.Nmr.PeakList', func) for clazz in ('Experiment', 'DataSource'): for func in ('__init__', 'delete', 'setName'): notifyFunc(self.updateSpectrumTable, 'ccp.nmr.Nmr.%s' % clazz, func) for func in ('setPeakFindBoxWidth', 'setPeakFindMinLineWidth'): notifyFunc(self.updateSpectrumTable, 'ccpnmr.Analysis.AnalysisDataDim', func) def destroy(self): self.administerNotifiers(self.unregisterNotify) BasePopup.destroy(self) def updateSpectrum(self, spectrum=None): if not spectrum: spectrum = self.spectrum spectra = self.parent.getSpectra() if spectra: if spectrum not in spectra: spectrum = spectra[0] index = spectra.index(spectrum) names = ['%s:%s' % (x.experiment.name, x.name) for x in spectra] else: index = 0 names = [] self.expt_spectrum.setup(names, spectra, index) self.setSpectrumProperties(spectrum) def updateNotifier(self, *extra): self.updateSpectrum() def setLinewidth(self, *event): value = self.editLinewidthEntry.get() if value is not None: PeakFindParams.setPeakFindMinLinewidth(self.dataDim, value) self.setSpectrumProperties(self.dataDim.dataSource) def getLinewidth(self, dataDim): if dataDim: self.editLinewidthEntry.set( PeakFindParams.getPeakFindMinLinewidth(self.dataDim)) def setBoxwidth(self, *event): value = self.editBoxwidthEntry.get() if value is not None: PeakFindParams.setPeakFindBoxwidth(self.dataDim, value) self.setSpectrumProperties(self.dataDim.dataSource) def getBoxwidth(self, dataDim): if dataDim: self.editBoxwidthEntry.set( PeakFindParams.getPeakFindBoxwidth(self.dataDim)) def selectCell(self, object, row, col): self.dataDim = object def setExclusion(self, *extra): isotope = self.isotopeMatrix.currentObject if not isotope: return value = self.exclusionEntry.get() if value is not None: setIsotopeExclusion(isotope, value) self.setIsotopeProperties() def getExclusion(self, isotope): value = getIsotopeExclusion(isotope) self.exclusionEntry.set(value) def setParamsEntries(self): project = self.project params = PeakFindParams.getPeakFindParams(project) self.scale_entry.set(params['scale']) self.buffer_entry.set(params['buffer']) self.thickness_entry.set(params['thickness']) self.drop_entry.set(params['drop']) volumeMethod = params['volumeMethod'] if volumeMethod == 'parabolic fit': volumeMethod = PeakBasic.PEAK_VOLUME_METHODS[0] self.method_menu.set(params['volumeMethod']) if (params['nonadjacent']): n = 1 else: n = 0 self.adjacent_buttons.setIndex(n) have_high = params['haveHigh'] have_low = params['haveLow'] if (have_high and have_low): n = 0 elif (have_high): n = 1 else: n = 2 self.extrema_buttons.setIndex(n) def apply(self, *extra): params = {} params['scale'] = self.scale_entry.get() params['buffer'] = self.buffer_entry.get() params['thickness'] = self.thickness_entry.get() params['drop'] = self.drop_entry.get() params['volumeMethod'] = self.method_menu.getText() n = self.adjacent_buttons.getIndex() if (n == 0): nonadjacent = False else: nonadjacent = True params['nonadjacent'] = nonadjacent n = self.extrema_buttons.getIndex() if (n == 0): have_high = True have_low = True elif (n == 1): have_high = True have_low = False elif (n == 2): have_high = False have_low = True params['haveHigh'] = have_high params['haveLow'] = have_low project = self.project try: PeakFindParams.setPeakFindParams(project, params) except Implementation.ApiError, e: showError('Parameter error', e.error_msg, parent=self)
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
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 EditContourLevelsPopup(BasePopup): """ **Change Levels in Spectrum Contour Displays** This popup window is used to specify which contour levels (lines of constant intensity) are drawn for spectra within the spectrum windows of Analysis. A spectrum can have both positive and negative levels, and the user can set these on an individual basis or as a regular incremental (usually geometric) series. It should be noted that spectrum contour colours, which may be different for positive and negative levels, is set elsewhere, in the main Spectra_ table. In normal operation the user first selects the spectrum to change the contours for in the upper left pulldown menu. Although contour levels are specified for individual spectra, if there are several spectra that share the same levels (for example if they form a series of some kind) then the user may spread the contour level information from one to many via the [Propagate Contours] function within the "Display Options" of the main Spectra_ table. The user may also affect the contour levels of multiple spectra by changing the "Global scale" settings. This global scale will affect *all spectra* in the project; the scale value multiplies all of the contour levels for all spectra, although in practice it is rarely changed. Using a global scale gives the advantage of being able to specify smaller numbers for the levels. The individual contour levels for a spectrum are listed in the "positive levels" and "Negative levels" fields. They are multiplied by the global scale factor when they are used for spectrum display. The user may type in values for the levels directly into these field, or they can be filled using the "Auto contour levels" mechanism. If manual levels are specified the user should press [Apply manual Levels] when done to commit the changes and see the results. The [Apply Auto Levels] function differs in that it always applies a regular series of levels, according to the settings, and these will overwrite any manual specifications when committed; the actual levels applied are always displayed in the levels field. The setting of "Auto" levels using a series involves choosing a base level, which represents the first contour (closest to zero). This base level is usually set according to the level of noise in the spectrum. Typically it is a value just above most of the noise, so the noise is not seen, but it may be set lower in some instances to show weak signals. The base level applies to both positive and negative contour series, although for the negative side it is naturally used with negative sign. The user sets how many levels there should be in total; the subsequent levels start from the base level and move away from zero. Normally this involves a geometric series, with a constant multiplication factor applied to a value to generate the next in the series. This factor is set in the "Level multiplier", although some of the commonly used values are quickly set via the adjacent buttons. Under a few special circumstances it is helpful to have a constant difference between levels, in which case "Add levels" may be used instead of "Multiply levels". **Caveats & Tips** Often it is useful to initially setup contours using an "Auto" series, but then manually remove some of the levels. For example having all the positive levels but only the first negative level may be helpful to show where peaks are truncated. Note this system sets the levels that would be used to make any contour files (an optional way of working, especially for 4D spectra etc.). However, once contour files are made then this system will not affect the levels within the files. .. _Spectra: EditSpectrumPopup.html """ def __init__(self, parent, *args, **kw): BasePopup.__init__(self, parent=parent, title='Spectrum Contour Levels', **kw) def body(self, guiFrame): self.doUpdateForm = True self.spectrum = None guiFrame.grid_columnconfigure(1, weight=1) row = 0 specFrame = LabelFrame(guiFrame, text='Spectrum', grid=(row, 0)) tipText = 'The spectrum for which you are setting the contour levels' self.expt_spectrum = PulldownList(specFrame, grid=(0, 0), tipText=tipText, callback=self.setSpectrumDetails) tipText = 'Open the edit spectrum table to view and change other properties associated with the selected spectrum' button = Button(specFrame, text='Spectrum Properties', command=self.editProperties, borderwidth=1, grid=(1, 0), sticky='ew', tipText=tipText) globalFrame = LabelFrame(guiFrame, text='Global scale') globalFrame.grid(row=row, column=1, sticky='nsew') globalFrame.grid_columnconfigure(0, weight=1) tipText = 'The value by which all contour levels in all spectra are multiplied; to give the actual contour level in terms of the stored spectrum data' self.global_entry = FloatEntry( globalFrame, width=10, tipText=tipText, text=self.analysisProject.globalContourScale, returnCallback=self.applyAuto, grid=(0, 0), gridSpan=(1, 2), sticky='ew') tipText = 'Divide the global scaling factor by two; moving all contour for all spectra levels closer to zero' button = Button(globalFrame, borderwidth=1, text='/2', sticky='ew', tipText=tipText, command=lambda: self.changeGlobalScale(0.5), grid=(0, 2)) tipText = 'Multiple the global scaling factor by two; moving all contour for all spectra levels away from zero' button = Button(globalFrame, borderwidth=1, text='*2', sticky='ew', tipText=tipText, command=lambda: self.changeGlobalScale(2.0), grid=(0, 3)) tipText = 'Set the global contour scale for all spectra to the default of 100,000' button = Button(globalFrame, borderwidth=1, text='10^5', tipText=tipText, command=self.defaultGlobalScale, grid=(1, 0)) tipText = 'Click to decrease "-" or increase "+" the global contour scale by small amounts' frame = ValueRamp(globalFrame, callback=self.changeGlobalScale, tipText=tipText) frame.grid(row=1, column=1, columnspan=3, sticky='e') row += 1 self.autoFrame = LabelFrame(guiFrame, text='Auto contour levels') self.autoFrame.grid(row=row, column=0, columnspan=5, sticky='nsew') self.autoFrame.grid_columnconfigure(1, weight=1) frow = 0 label = Label(self.autoFrame, text='Base level:', grid=(frow, 0), sticky='e') tipText = 'The first contour level (closest to zero) for an automated series of levels: the start of a geometric or arithmetic series defining levels' self.base_entry = FloatEntry(self.autoFrame, returnCallback=self.applyAuto, width=10, grid=(frow, 1), sticky='ew', tipText=tipText) command = lambda: self.changeBaseLevel(0.5) tipText = 'Lower the base contour level so that it is half of the previous value; moving the series of contour levels closer to zero' button = Button(self.autoFrame, borderwidth=1, text='/2', tipText=tipText, command=command, grid=(frow, 2), sticky='ew') command = lambda: self.changeBaseLevel(2.0) tipText = 'Raise the base contour level so that it is double the previous value; moving the series of contour levels further from zero' button = Button(self.autoFrame, borderwidth=1, text='*2', tipText=tipText, command=command, grid=(frow, 3), sticky='ew') tipText = 'Click to decrease "-" or increase "+" the base contour level by small amounts' frame = ValueRamp(self.autoFrame, callback=self.changeBaseLevel, tipText=tipText) frame.grid(row=frow, column=4, columnspan=3, sticky='ew') frow += 1 label = Label(self.autoFrame, text='Number of levels:', grid=(frow, 0), sticky='e') #self.numberEntry = IntEntry(guiFrame, text=numberLevels, # returnCallback=self.applyAuto) tipText = 'The number of contour levels to make in the automated series' self.numberEntry = IntEntry(self.autoFrame, returnCallback=self.applyAuto, width=10, grid=(frow, 1), sticky='ew', tipText=tipText) command = lambda w=-1: self.changeNumberLevels(w) tipText = 'Decrease the number of contour levels in the series by one' button = Button(self.autoFrame, borderwidth=1, text='-1', tipText=tipText, command=command, grid=(frow, 2), sticky='ew') command = lambda w=1: self.changeNumberLevels(w) tipText = 'Increase the number of contour levels in the series by one' button = Button(self.autoFrame, borderwidth=1, text='+1', tipText=tipText, command=command, grid=(frow, 3), sticky='ew') n = 4 for w in (5, 10, 15, 20): tipText = 'Set the number of contour levels in the series to %d' % w command = lambda w=w: self.setNumberLevels(w) button = Button(self.autoFrame, borderwidth=1, text='%d' % w, command=command, grid=(frow, n), sticky='ew', tipText=tipText) n += 1 frow += 1 self.change_label = Label(self.autoFrame, text='%s:' % multiplier_text, grid=(frow, 0), sticky='e') tipText = 'The multiplication factor (or increment if adding levels) to repetitively apply to the base level to generate the series of levels' self.change_entry = FloatEntry(self.autoFrame, returnCallback=self.applyAuto, width=10, grid=(frow, 1), sticky='ew', tipText=tipText) self.change_level_buttons = [] n = 2 for w in multiplier_changes: tipText = 'Set the automated series multiplication factor or increment to %f' % w command = lambda w=w: self.setChange(w) button = Button(self.autoFrame, borderwidth=1, text=str(w), command=command, grid=(frow, n), sticky='ew', tipText=tipText) self.change_level_buttons.append(button) n += 1 frow += 1 frame = Frame(self.autoFrame, grid=(frow, 0), gridSpan=(1, 7), sticky='ew') tipTexts = [ 'Toggles whether positive contour levels from the automated series will be used. Overrides any manual settings', 'Toggles whether negative contour levels from the automated series will be used. Overrides any manual settings' ] entries = ('Positive', 'Negative') selected = (True, False) self.which_buttons = CheckButtons(frame, entries, selected=selected, select_callback=self.applyAuto, grid=(0, 0), sticky='w', tipTexts=tipTexts) tipTexts = [ 'Set the contour level generation to use a geometric series, starting from the base level and using the specified factor', 'Set the contour level generation to use an arithmetic series, starting from the base level and using the specified increment' ] entries = ('Multiply levels', 'Add levels') self.change_mode_buttons = RadioButtons( frame, entries, grid=(0, 1), sticky='ew', select_callback=self.modeChanged, tipTexts=tipTexts) row += 1 manualFrame = LabelFrame(guiFrame, text='Positive levels', grid=(row, 0), gridSpan=(1, 2)) manualFrame.expandGrid(None, 0) tipText = 'The positive contour levels that will be used for the spectrum; filled in by the automation or set/modified manually' self.posLevelsEntry = FloatEntry(manualFrame, isArray=True, width=60, returnCallback=self.applyManual, tipText=tipText, grid=(0, 0), sticky='ew') row += 1 manualFrame = LabelFrame(guiFrame, text='Negative levels', grid=(row, 0), gridSpan=(1, 2)) manualFrame.expandGrid(None, 0) tipText = 'The negative contour levels that will be used for the spectrum; filled in by the automation or set/modified manually' self.negLevelsEntry = FloatEntry(manualFrame, isArray=True, width=60, returnCallback=self.applyManual, tipText=tipText, grid=(0, 0), sticky='ew') row += 1 tipTexts = [ 'Set the spectrum contour levels, updating the display, to the automated series, ignoring any manual edits.', 'Set the spectrum contour levels, updating the display, to the values displayed in the level entry fields' ] texts = ['Apply Auto Levels', 'Apply Manual Edits'] commands = [self.applyAuto, self.applyManual] self.buttons = UtilityButtonList(guiFrame, texts=texts, commands=commands, helpUrl=self.help_url, grid=(row, 0), gridSpan=(1, 2), tipTexts=tipTexts) guiFrame.grid_rowconfigure(row, weight=1) self.curateNotifiers(self.registerNotify) self.update() def update(self, spectrum=None): if not spectrum: spectrum = self.spectrum spectra = self.parent.getSpectra() if spectra: if spectrum not in spectra: spectrum = spectra[0] index = spectra.index(spectrum) names = ['%s:%s' % (x.experiment.name, x.name) for x in spectra] else: index = 0 names = [] self.expt_spectrum.setup(names, spectra, index) self.setSpectrumDetails(spectrum) def updateNotifier(self, *extra): self.update() def open(self): self.updateForm() BasePopup.open(self) def modeChanged(self, *entry): spectrum = self.spectrum if not spectrum or spectrum.isDeleted: return analysisSpectrum = spectrum.analysisSpectrum changeMode = self.change_mode_buttons.getIndex( ) and 'add' or 'multiply' if changeMode == 'add': text = adder_text changes = adder_changes else: text = multiplier_text changes = multiplier_changes self.change_label.set('%s:' % text) n = 0 for button in self.change_level_buttons: w = changes[n] command = lambda w=w: self.setChange(w) button.config(command=command) button.setText(str(w)) n = n + 1 levelChanger = changes[2] self.doUpdateForm = False analysisSpectrum.autoLevelChanger = levelChanger analysisSpectrum.autoLevelMode = changeMode self.doUpdateForm = True self.setContourLevels() def defaultGlobalScale(self): self.global_entry.set(100000) self.applyAuto() def close(self): self.applyManual() BasePopup.close(self) def destroy(self): self.curateNotifiers(self.unregisterNotify) BasePopup.destroy(self) def curateNotifiers(self, notifyFunc): notifyFunc(self.updateContourLevels, 'ccpnmr.Analysis.AnalysisSpectrum', 'setPosLevels') notifyFunc(self.updateContourLevels, 'ccpnmr.Analysis.AnalysisSpectrum', 'setNegLevels') notifyFunc(self.updateForm, 'ccpnmr.Analysis.AnalysisSpectrum', 'setAutoLevelChanger') notifyFunc(self.updateForm, 'ccpnmr.Analysis.AnalysisSpectrum', 'setAutoLevelMode') notifyFunc(self.updateForm, 'ccpnmr.Analysis.AnalysisSpectrum', 'setAutoNumLevels') notifyFunc(self.updateForm, 'ccpnmr.Analysis.AnalysisSpectrum', 'setAutoBaseLevel') notifyFunc(self.updateForm, 'ccpnmr.Analysis.AnalysisProject', 'setGlobalContourScale') for clazz in ('Experiment', 'DataSource'): for func in ('__init__', 'delete', 'setName'): notifyFunc(self.updateNotifier, 'ccp.nmr.Nmr.%s' % clazz, func) def editProperties(self): self.parent.editSpectrum(self.spectrum) def updateForm(self, *extra): #print 'updateForm' if (not self.doUpdateForm): return self.global_entry.set(self.analysisProject.globalContourScale) spectrum = self.spectrum if spectrum and not spectrum.isDeleted: analysisSpectrum = spectrum.analysisSpectrum self.base_entry.set(analysisSpectrum.autoBaseLevel) self.numberEntry.set(analysisSpectrum.autoNumLevels) self.change_entry.set(analysisSpectrum.autoLevelChanger) if analysisSpectrum.autoLevelMode == 'add': i = 1 else: i = 0 self.change_mode_buttons.setIndex(i) def updateContourLevels(self, analysisSpectrum): spectrum = self.spectrum if spectrum and not spectrum.isDeleted: analysisSpectrum = spectrum.analysisSpectrum posLevels = list(analysisSpectrum.posLevels) negLevels = list(analysisSpectrum.negLevels) self.posLevelsEntry.set(posLevels) self.negLevelsEntry.set(negLevels) self.doUpdateForm = False updateSpectrumLevelParams(analysisSpectrum, posLevels, negLevels) self.doUpdateForm = True self.base_entry.set(analysisSpectrum.autoBaseLevel) self.numberEntry.set(analysisSpectrum.autoNumLevels) self.change_entry.set(analysisSpectrum.autoLevelChanger) self.setWhichLevels(spectrum) if analysisSpectrum.autoLevelMode == 'add': i = 1 else: i = 0 self.change_mode_buttons.setIndex(i) def setWhichLevels(self, spectrum): analysisSpectrum = spectrum.analysisSpectrum posLevels = analysisSpectrum.posLevels negLevels = analysisSpectrum.negLevels if posLevels: isSelected = True else: isSelected = False self.which_buttons.setIndexSelection(0, isSelected) if negLevels: isSelected = True else: isSelected = False self.which_buttons.setIndexSelection(1, isSelected) def setSpectrum(self, spectrum): if spectrum is not self.spectrum: self.update(spectrum) #if (spectrum and not spectrum.isDeleted): # self.setWhichLevels(spectrum) speed_scale = 6.0 speed_delay = 50 # msec def changeGlobalScale(self, multiplier): self.analysisProject.globalContourScale = multiplier * self.analysisProject.globalContourScale def changeBaseLevel(self, multiplier): spectrum = self.spectrum if (not spectrum or spectrum.isDeleted is True): return analysisSpectrum = spectrum.analysisSpectrum baseLevel = multiplier * analysisSpectrum.autoBaseLevel self.base_entry.set(baseLevel) self.doUpdateForm = False analysisSpectrum.autoBaseLevel = abs(baseLevel) self.doUpdateForm = True self.setContourLevels() def changeNumberLevels(self, change): spectrum = self.spectrum if not spectrum or spectrum.isDeleted is True: return analysisSpectrum = spectrum.analysisSpectrum numberLevels = analysisSpectrum.autoNumLevels + change self.numberEntry.set(numberLevels) self.doUpdateForm = False analysisSpectrum.autoNumLevels = numberLevels self.doUpdateForm = True self.setContourLevels() def setChange(self, levelChanger): spectrum = self.spectrum if not spectrum or spectrum.isDeleted: return self.doUpdateForm = False analysisSpectrum = spectrum.analysisSpectrum analysisSpectrum.autoLevelChanger = levelChanger self.doUpdateForm = True self.setContourLevels() def setNumberLevels(self, numberLevels): spectrum = self.spectrum if (not spectrum or spectrum.isDeleted is True): return self.doUpdateForm = False analysisSpectrum = spectrum.analysisSpectrum analysisSpectrum.autoNumLevels = numberLevels self.doUpdateForm = True self.setContourLevels() def setSpectrumDetails(self, spectrum): if spectrum is self.spectrum: return self.spectrum = spectrum if spectrum and not spectrum.isDeleted: analysisSpectrum = spectrum.analysisSpectrum posLevels = list(analysisSpectrum.posLevels) negLevels = list(analysisSpectrum.negLevels) self.posLevelsEntry.set(posLevels) self.negLevelsEntry.set(negLevels) self.doUpdateForm = False updateSpectrumLevelParams(analysisSpectrum, posLevels, negLevels) self.doUpdateForm = True self.base_entry.set(analysisSpectrum.autoBaseLevel) self.numberEntry.set(analysisSpectrum.autoNumLevels) self.change_entry.set(analysisSpectrum.autoLevelChanger) self.autoFrame.setText('Auto contour levels - %s:%s' % (spectrum.experiment.name, spectrum.name)) self.setWhichLevels(spectrum) else: self.posLevelsEntry.set('') self.negLevelsEntry.set('') self.autoFrame.setText('Auto contour levels') def setContourLevels(self): spectrum = self.spectrum if not spectrum or spectrum.isDeleted is True: return try: analysisSpectrum = spectrum.analysisSpectrum baseLevel = analysisSpectrum.autoBaseLevel numberLevels = analysisSpectrum.autoNumLevels levelChanger = analysisSpectrum.autoLevelChanger changeMode = analysisSpectrum.autoLevelMode posLevels = [] if self.which_buttons.isIndexSelected(0): posLevels.extend( calcContourLevels(baseLevel, numberLevels, levelChanger, changeMode)) negLevels = [] if self.which_buttons.isIndexSelected(1): if changeMode == 'add': levelChanger = -levelChanger negLevels.extend( calcContourLevels(-baseLevel, numberLevels, levelChanger, changeMode)) self.posLevelsEntry.set(posLevels) self.negLevelsEntry.set(negLevels) analysisSpectrum.posLevels = posLevels analysisSpectrum.negLevels = negLevels except Implementation.ApiError, e: showError('Contour levels error', e.error_msg, parent=self)