class LabeledFloatEntry(Frame): def __init__(self, parent, label, entry='', separator=': ', label_width=20, entry_width=60, label_anchor=Tkinter.E, show='', isArray=False, returnCallback=None, *args, **kw): apply(Frame.__init__, (self, parent) + args, kw) self.grid_columnconfigure(1, weight=1) self.separator = separator text = label + separator self.label = Label(self, text=text, width=label_width, anchor=label_anchor) self.label.grid(row=0, column=0, sticky=Tkinter.EW) self.entry = FloatEntry(self, show=show, width=entry_width, isArray=isArray, returnCallback=returnCallback) self.entry.grid(row=0, column=1, sticky=Tkinter.EW) self.setEntry(entry) def getLabel(self): text = self.label.get() n = text.find(self.separator) if (n >= 0): text = text[:n] return text def setLabel(self, text=''): text = text + self.separator self.label.set(text) def getEntry(self): return self.entry.get() def setEntry(self, value=''): self.entry.set(value)
class PopupTemplate(BasePopup): def __init__(self, parent, project=None, *args, **kw): self.project = project self.parent = parent self.objects = self.getObjects() self.object = None BasePopup.__init__(self, parent=parent, title='Popup Template', **kw) self.updateObjects() def body(self, mainFrame): mainFrame.grid_columnconfigure(1, weight=1, minsize=100) mainFrame.config(borderwidth=5, relief='solid') row = 0 label = Label(mainFrame, text="Frame (with sub-widgets):") label.grid(row=row, column=0, sticky=Tkinter.E) frame = Frame(mainFrame, relief='raised', border=2, background='#8080D0') # Frame expands East-West frame.grid(row=row, column=1, sticky=Tkinter.EW) # Last column expands => Widgets pusted to the West frame.grid_columnconfigure(3, weight=1) # Label is within the sub frame label = Label(frame, text='label ') label.grid(row=0, column=0, sticky=Tkinter.W) entry = Entry(frame, text='Entry', returnCallback=self.showWarning) entry.grid(row=0, column=1, sticky=Tkinter.W) self.check = CheckButton(frame, text='Checkbutton', selected=True, callback=self.updateObjects) self.check.grid(row=0, column=2, sticky=Tkinter.W) # stick a button to the East wall button = Button(frame, text='Button', command=self.pressButton) button.grid(row=0, column=3, sticky=Tkinter.E) row += 1 label = Label(mainFrame, text="Text:") label.grid(row=row, column=0, sticky=Tkinter.E) self.textWindow = Text(mainFrame, text='Initial Text\n', width=60, height=5) self.textWindow.grid(row=row, column=1, sticky=Tkinter.NSEW) row += 1 label = Label(mainFrame, text="CheckButtons:") label.grid(row=row, column=0, sticky=Tkinter.E) entries = ['Alpha','Beta','Gamma','Delta'] selected = entries[2:] self.checkButtons = CheckButtons(mainFrame, entries, selected=selected,select_callback=self.changedCheckButtons) self.checkButtons.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="PartitionedSelector:") label.grid(row=row, column=0, sticky=Tkinter.E) labels = ['Bool','Int','Float','String'] objects = [type(0),type(1),type(1.0),type('a')] selected = [type('a')] self.partitionedSelector= PartitionedSelector(mainFrame, labels=labels, objects=objects, colors = ['red','yellow','green','#000080'], callback=self.toggleSelector,selected=selected) self.partitionedSelector.grid(row=row, column=1, sticky=Tkinter.EW) row += 1 label = Label(mainFrame, text="PulldownMenu") label.grid(row=row, column=0, sticky=Tkinter.E) entries = ['Frodo','Pipin','Merry','Sam','Bill','Gandalf','Strider','Gimli','Legolas'] self.pulldownMenu = PulldownMenu(mainFrame, callback=self.selectPulldown, entries=entries, selected_index=2, do_initial_callback=False) self.pulldownMenu.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="RadioButtons in a\nScrolledFrame.frame:") label.grid(row=row, column=0, sticky=Tkinter.EW) frame = ScrolledFrame(mainFrame, yscroll = False, doExtraConfig = True, width=100) frame.grid(row=row, column=1, sticky=Tkinter.EW) frame.grid_columnconfigure(0, weight=1) self.radioButtons = RadioButtons(frame.frame, entries=entries, select_callback=self.checkRadioButtons, selected_index=1, relief='groove') self.radioButtons.grid(row=0, column=0, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="LabelFrame with\nToggleLabels inside:") label.grid(row=row, column=0, sticky=Tkinter.E) labelFrame = LabelFrame(mainFrame, text='Frame Title') labelFrame.grid(row=row, column=1, sticky=Tkinter.NSEW) labelFrame.grid_rowconfigure(0, weight=1) labelFrame.grid_columnconfigure(3, weight=1) self.toggleLabel1 = ToggleLabel(labelFrame, text='ScrolledMatrix', callback=self.toggleFrame1) self.toggleLabel1.grid(row=0, column=0, sticky=Tkinter.W) self.toggleLabel1.arrowOn() self.toggleLabel2 = ToggleLabel(labelFrame, text='ScrolledGraph', callback=self.toggleFrame2) self.toggleLabel2.grid(row=0, column=1, sticky=Tkinter.W) self.toggleLabel3 = ToggleLabel(labelFrame, text='ScrolledCanvas', callback=self.toggleFrame3) self.toggleLabel3.grid(row=0, column=2, sticky=Tkinter.W) row += 1 mainFrame.grid_rowconfigure(row, weight=1) label = Label(mainFrame, text="changing/shrinking frames:") label.grid(row=row, column=0, sticky=Tkinter.E) self.toggleRow = row self.toggleFrame = Frame(mainFrame) self.toggleFrame.grid(row=row, column=1, sticky=Tkinter.NSEW) self.toggleFrame.grid_rowconfigure(0, weight=1) self.toggleFrame.grid_columnconfigure(0, weight=1) # option 1 self.intEntry = IntEntry(self, returnCallback = self.setNumber, width=8) self.multiWidget = MultiWidget(self, Entry, options=None, values=None, callback=self.setKeywords, minRows=3, maxRows=5) editWidgets = [None, None, self.intEntry, self.multiWidget] editGetCallbacks = [None, None, self.getNumber, self.getKeywords] editSetCallbacks = [None, None, self.setNumber, self.setKeywords] headingList = ['Name','Color','Number','Keywords'] self.scrolledMatrix = ScrolledMatrix(self.toggleFrame, headingList=headingList, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, callback=self.selectObject, multiSelect=False) self.scrolledMatrix.grid(row=0, column=0, sticky=Tkinter.NSEW) # option 2 self.scrolledGraph = ScrolledGraph(self.toggleFrame, width=400, height=300, symbolSize=5, symbols=['square','circle'], dataColors=['#000080','#800000'], lineWidths=[0,1] ) self.scrolledGraph.setZoom(1.3) dataSet1 = [[0,0],[1,1],[2,4],[3,9],[4,16],[5,25]] dataSet2 = [[0,0],[1,3],[2,6],[3,9],[4,12],[5,15]] self.scrolledGraph.update(dataSets=[dataSet1,dataSet2], xLabel = 'X axis label', yLabel = 'Y axis label', title = 'Main Title') self.scrolledGraph.draw() # option 3 self.scrolledCanvas = ScrolledCanvas(self.toggleFrame,relief = 'groove', borderwidth = 2, resizeCallback=None) canvas = self.scrolledCanvas.canvas font = 'Helvetica 10' box = canvas.create_rectangle(10,10,150,200, outline='grey', fill='grey90') line = canvas.create_line(0,0,200,200,fill='#800000', width=2) text = canvas.create_text(120,50, text='Text', font=font, fill='black') circle = canvas.create_oval(30,30,50,50,outline='#008000',fill='#404040',width=3) row += 1 label = Label(mainFrame, text="FloatEntry:") label.grid(row=row, column=0, sticky=Tkinter.E) self.floatEntry = FloatEntry(mainFrame, text=3.14159265, returnCallback=self.floatEntryReturn) self.floatEntry.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="Scale:") label.grid(row=row, column=0, sticky=Tkinter.E) self.scale = Scale(mainFrame, from_=10, to=90, value=50, orient=Tkinter.HORIZONTAL) self.scale.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="Value Ramp:") label.grid(row=row, column=0, sticky=Tkinter.E) self.valueRamp = ValueRamp(mainFrame, self.valueRampCallback, speed = 1.5, delay = 50) self.valueRamp.grid(row=row, column=1, sticky=Tkinter.W) row += 1 label = Label(mainFrame, text="ButtonList:") label.grid(row=row, column=0, sticky=Tkinter.E) texts = ['Select File','Close','Quit'] commands = [self.selectFile, self.close, self.quit] bottomButtons = ButtonList(mainFrame, texts=texts, commands=commands, expands=True) bottomButtons.grid(row=row, column=1, sticky=Tkinter.EW) self.protocol('WM_DELETE_WINDOW', self.quit) def floatEntryReturn(self, event): value = self.floatEntry.get() self.textWindow.setText('%s\n' % value) def selectObject(self, object, row, col): self.object = object def getKeywords(self, object): if object : values = object.keywords self.multiWidget.set(values) def setKeywords(self, event): values = self.multiWidget.get() self.object.keywords = values self.updateObjects() def getNumber(self, object): if object : self.intEntry.set(object.quantity) def setNumber(self, event): value = self.intEntry.get() self.object.quantity = value self.updateObjects() def toggleFrame1(self, isHidden): if isHidden: self.scrolledMatrix.grid_forget() self.toggleFrame.grid_forget() else: self.scrolledGraph.grid_forget() self.scrolledCanvas.grid_forget() self.scrolledMatrix.grid(row=0, column=0, sticky=Tkinter.NSEW) self.toggleFrame.grid(row=self.toggleRow, column=1,sticky=Tkinter.NSEW) self.toggleLabel2.arrowOff() self.toggleLabel3.arrowOff() def toggleFrame2(self, isHidden): if isHidden: self.scrolledGraph.grid_forget() self.toggleFrame.grid_forget() else: self.scrolledMatrix.grid_forget() self.scrolledCanvas.grid_forget() self.scrolledGraph.grid(row=0, column=0, sticky=Tkinter.NSEW) self.toggleFrame.grid(row=self.toggleRow, column=1,sticky=Tkinter.NSEW) self.toggleLabel1.arrowOff() self.toggleLabel3.arrowOff() def toggleFrame3(self, isHidden): if isHidden: self.scrolledCanvas.grid_forget() self.toggleFrame.grid_forget() else: self.scrolledMatrix.grid_forget() self.scrolledGraph.grid_forget() self.scrolledCanvas.grid(row=0, column=0, sticky=Tkinter.NSEW) self.toggleFrame.grid(row=self.toggleRow, column=1,sticky=Tkinter.NSEW) self.toggleLabel1.arrowOff() self.toggleLabel2.arrowOff() def valueRampCallback(self, value): self.textWindow.setText('%s\n' % value) def checkRadioButtons(self, value): self.textWindow.setText('%s\n' % value) def selectPulldown(self, index, name): self.textWindow.setText('%d, %s\n' % (index, name)) def toggleSelector(self, value): self.textWindow.setText('%s\n' % value) def changedCheckButtons(self, values): self.textWindow.setText(','.join(values) + '\n') def getObjects(self): objects = [] objects.append( Fruit('Lemon', '#FFFF00',1,keywords=['Bitter','Tangy'] ) ) objects.append( Fruit('Orange', '#FF8000',4 ) ) objects.append( Fruit('Banana', '#FFF000',5 ) ) objects.append( Fruit('Pinapple','#FFD000',9 ) ) objects.append( Fruit('Kiwi', '#008000',12) ) objects.append( Fruit('Lime', '#00FF00',2 ) ) objects.append( Fruit('Apple', '#800000',5,keywords=['Crunchy'] ) ) objects.append( Fruit('Pear', '#408000',6 ) ) objects.append( Fruit('Peach', '#FFE0C0',2,keywords=['Sweet','Furry'] ) ) objects.append( Fruit('Plumb', '#800080',7 ) ) return objects def updateObjects(self, event=None): textMatrix = [] objectList = [] colorMatrix = [] for object in self.objects: datum = [] datum.append( object.name ) datum.append( None ) datum.append( object.quantity ) datum.append( ','.join(object.keywords) ) colors = [None, object.color, None, None] textMatrix.append(datum) objectList.append(object) colorMatrix.append(colors) if self.check.get(): self.scrolledMatrix.update(textMatrix=textMatrix, objectList=objectList) else: self.scrolledMatrix.update(textMatrix=textMatrix, objectList=objectList, colorMatrix=colorMatrix) def selectFile(self): fileSelectPopup = FileSelectPopup(self, title = 'Choose file', dismiss_text = 'Cancel', selected_file_must_exist = True) fileName = fileSelectPopup.getFile() self.textWindow.setText('File Selected: %s\n' % fileName) def showWarning(self, eventObject): self.textWindow.setText('Text Entry Return Pressed\n') showWarning('Warning Title','Warning Message') return def pressButton(self): self.textWindow.setText('Button Pressed\n') if showYesNo('Title','Prompt: Clear text window?'): self.textWindow.clear() return def quit(self): BasePopup.destroy(self)
class CloudsPopup(BasePopup): def __init__(self, parent, *args, **kw): self.guiParent = parent self.project = parent.getProject() self.waiting = 0 self.specFreq = 800.13 self.maxIter = 50 self.mixTime = 60 self.corrTime = 11.5 self.leakRate = 2.0 self.peakListDict = {} self.noesyPeakList = None self.tocsyPeakList = None self.noesy3dPeakList = None self.hsqcPeakList = None self.maxIntens = 37000000 self.resonances = None self.origResonances = None self.noesyPeaks = None self.distanceConstraintList = None self.antiDistConstraintList = None self.numClouds = 100 self.filePrefix = 'cloud_' self.cloudsFiles = [] self.adcAtomTypes = 'HN' self.structure = None # step num, initial temp, final temp, cooling steps, MD steps, MD tau, rep scale self.coolingScheme = [] self.coolingScheme.append([1, 1, 1, 3, 500, 0.001, 0]) self.coolingScheme.append([2, 80000, 4000, 19, 1000, 0.001, 0]) self.coolingScheme.append([3, 4000, 1, 5, 500, 0.001, 0]) self.coolingScheme.append([4, 15000, 1, 3, 1000, 0.001, 0]) self.coolingScheme.append([5, 1, 1, 5, 500, 0.001, 0]) self.coolingScheme.append([6, 8000, 1, 3, 1000, 0.001, 0]) self.coolingScheme.append([7, 1, 1, 5, 500, 0.001, 0]) self.coolingScheme.append([8, 3000, 25, 60, 2500, 0.001, 1]) self.coolingScheme.append([9, 25, 25, 1, 7500, 0.001, 1]) self.coolingScheme.append([10, 10, 10, 1, 7500, 0.001, 1]) self.coolingScheme.append([11, 0.01, 0.01, 1, 7500, 0.0005, 1]) self.coolingStep = None BasePopup.__init__(self, parent, title="Resonance Clouds Analysis", **kw) def body(self, guiFrame): self.specFreqEntry = IntEntry(self, text=self.specFreq, width=8, returnCallback=self.setSpecFreq) self.maxIterEntry = IntEntry(self, text=self.maxIter, width=8, returnCallback=self.setMaxIter) self.mixTimeEntry = FloatEntry(self, text=self.mixTime, width=8, returnCallback=self.setMixTime) self.corrTimeEntry = FloatEntry(self, text=self.corrTime, width=8, returnCallback=self.setCorrTime) self.leakRateEntry = FloatEntry(self, text=self.leakRate, width=8, returnCallback=self.setLeakRate) self.maxIntensEntry = IntEntry(self, text=self.maxIntens, width=8, returnCallback=self.setMaxIntens) self.mdInitTempEntry = FloatEntry(self, text='', returnCallback=self.setMdInitTemp) self.mdFinTempEntry = FloatEntry(self, text='', returnCallback=self.setMdFinTemp) self.mdCoolStepsEntry = IntEntry(self, text='', returnCallback=self.setMdCoolSteps) self.mdSimStepsEntry = IntEntry(self, text='', returnCallback=self.setMdSimSteps) self.mdTauEntry = FloatEntry(self, text='', returnCallback=self.setMdTau) self.mdRepScaleEntry = FloatEntry(self, text='', returnCallback=self.setMdRepScale) guiFrame.grid_columnconfigure(0, weight=1) row = 0 frame0 = LabelFrame(guiFrame, text='Setup peak lists') frame0.grid(row=row, column=0, sticky=Tkinter.NSEW) frame0.grid(row=row, column=0, sticky=Tkinter.NSEW) frame0.grid_columnconfigure(1, weight=1) f0row = 0 label00 = Label(frame0, text='1H-1H NOESY spectrum') label00.grid(row=f0row, column=0, sticky=Tkinter.NW) self.noesyPulldown = PulldownMenu(frame0, entries=self.getNoesys(), callback=self.setNoesy, selected_index=0, do_initial_callback=0) self.noesyPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW) f0row += 1 label01 = Label(frame0, text='15N HSQC spectrum') label01.grid(row=f0row, column=0, sticky=Tkinter.NW) self.hsqcPulldown = PulldownMenu(frame0, entries=self.getHsqcs(), callback=self.setHsqc, selected_index=0, do_initial_callback=0) self.hsqcPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW) f0row += 1 label02 = Label(frame0, text='15N HSQC TOCSY spectrum') label02.grid(row=f0row, column=0, sticky=Tkinter.NW) self.tocsyPulldown = PulldownMenu(frame0, entries=self.getTocsys(), callback=self.setTocsy, selected_index=0, do_initial_callback=0) self.tocsyPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW) f0row += 1 label02 = Label(frame0, text='15N HSQC NOESY spectrum') label02.grid(row=f0row, column=0, sticky=Tkinter.NW) self.noesy3dPulldown = PulldownMenu(frame0, entries=self.getNoesy3ds(), callback=self.setNoesy3d, selected_index=0, do_initial_callback=0) self.noesy3dPulldown.grid(row=f0row, column=1, sticky=Tkinter.NW) f0row += 1 texts = ['Setup resonances & peaks', 'Show Peaks', 'Show resonances'] commands = [self.setupResonances, self.showPeaks, self.showResonances] self.setupButtons = ButtonList(frame0, expands=1, texts=texts, commands=commands) self.setupButtons.grid(row=f0row, column=0, columnspan=2, sticky=Tkinter.NSEW) f0row += 1 self.label03a = Label(frame0, text='Resonances found: 0') self.label03a.grid(row=f0row, column=0, sticky=Tkinter.NW) self.label03b = Label(frame0, text='NOESY peaks found: 0') self.label03b.grid(row=f0row, column=1, sticky=Tkinter.NW) row += 1 frame1 = LabelFrame(guiFrame, text='Calculate distance constraints') frame1.grid(row=row, column=0, sticky=Tkinter.NSEW) frame1.grid_columnconfigure(3, weight=1) f1row = 0 frame1.grid_rowconfigure(f1row, weight=1) data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate, self.maxIntens ] colHeadings = [ 'Spectrometer\nfrequency', 'Max\niterations', 'Mixing\ntime (ms)', 'Correl.\ntime (ns)', 'Leak\nrate', 'Max\nintensity' ] editWidgets = [ self.specFreqEntry, self.maxIterEntry, self.mixTimeEntry, self.corrTimeEntry, self.leakRateEntry, self.maxIntensEntry, ] editGetCallbacks = [ self.getSpecFreq, self.getMaxIter, self.getMixTime, self.getCorrTime, self.getLeakRate, self.getMaxIntens, ] editSetCallbacks = [ self.setSpecFreq, self.setMaxIter, self.setMixTime, self.setCorrTime, self.setLeakRate, self.setMaxIntens, ] self.midgeParamsMatrix = ScrolledMatrix( frame1, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, maxRows=1, initialCols=5, headingList=colHeadings, callback=None, objectList=[ 'None', ], textMatrix=[ data, ]) self.midgeParamsMatrix.grid(row=f1row, column=0, columnspan=4, sticky=Tkinter.NSEW) f1row += 1 label10 = Label(frame1, text='Benchmark structure') label10.grid(row=f1row, column=0, sticky=Tkinter.NW) self.structurePulldown = PulldownMenu(frame1, entries=self.getStructures(), callback=self.setStructure, selected_index=0, do_initial_callback=0) self.structurePulldown.grid(row=f1row, column=1, sticky=Tkinter.NW) label11 = Label(frame1, text='ADC atom types:') label11.grid(row=f1row, column=2, sticky=Tkinter.NW) self.adcAtomsPulldown = PulldownMenu(frame1, entries=self.getAdcAtomTypes(), callback=self.setAdcAtomTypes, selected_index=0, do_initial_callback=0) self.adcAtomsPulldown.grid(row=f1row, column=3, sticky=Tkinter.NW) f1row += 1 texts = [ 'Calculate distances', 'Show distance\nconstraints', 'Show anti-distance\nconstraints' ] commands = [ self.calculateDistances, self.showConstraints, self.showAntiConstraints ] self.midgeButtons = ButtonList(frame1, expands=1, texts=texts, commands=commands) self.midgeButtons.grid(row=f1row, column=0, columnspan=4, sticky=Tkinter.NSEW) f1row += 1 self.distConstrLabel = Label(frame1, text='Distance constraints:') self.distConstrLabel.grid(row=f1row, column=0, columnspan=2, sticky=Tkinter.NW) self.antiConstrLabel = Label(frame1, text='Anti-distance constraints:') self.antiConstrLabel.grid(row=f1row, column=2, columnspan=2, sticky=Tkinter.NW) row += 1 guiFrame.grid_rowconfigure(row, weight=1) frame2 = LabelFrame(guiFrame, text='Proton cloud molecular dynamics') frame2.grid(row=row, column=0, sticky=Tkinter.NSEW) frame2.grid_columnconfigure(1, weight=1) f2row = 0 frame2.grid_rowconfigure(f2row, weight=1) data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate ] colHeadings = [ 'Step', 'Initial temp.', 'Final temp.', 'Cooling steps', 'MD steps', 'MD tau', 'Rep. scale' ] editWidgets = [ None, self.mdInitTempEntry, self.mdFinTempEntry, self.mdCoolStepsEntry, self.mdSimStepsEntry, self.mdTauEntry, self.mdRepScaleEntry ] editGetCallbacks = [ None, self.getMdInitTemp, self.getMdFinTemp, self.getMdCoolSteps, self.getMdSimSteps, self.getMdTau, self.getMdRepScale ] editSetCallbacks = [ None, self.setMdInitTemp, self.setMdFinTemp, self.setMdCoolSteps, self.setMdSimSteps, self.setMdTau, self.setMdRepScale ] self.coolingSchemeMatrix = ScrolledMatrix( frame2, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, maxRows=9, initialRows=12, headingList=colHeadings, callback=self.selectCoolingStep, objectList=self.coolingScheme, textMatrix=self.coolingScheme) self.coolingSchemeMatrix.grid(row=f2row, column=0, columnspan=4, sticky=Tkinter.NSEW) f2row += 1 texts = ['Move earlier', 'Move later', 'Add step', 'Remove step'] commands = [ self.moveStepEarlier, self.moveStepLater, self.addCoolingStep, self.removeCoolingStep ] self.coolingSchemeButtons = ButtonList(frame2, expands=1, commands=commands, texts=texts) self.coolingSchemeButtons.grid(row=f2row, column=0, columnspan=4, sticky=Tkinter.EW) f2row += 1 label20 = Label(frame2, text='Number of clouds:') label20.grid(row=f2row, column=0, sticky=Tkinter.NW) self.numCloudsEntry = FloatEntry(frame2, text=100, returnCallback=self.setNumClouds, width=10) self.numCloudsEntry.grid(row=f2row, column=1, sticky=Tkinter.NW) label21 = Label(frame2, text='Cloud file prefix:') label21.grid(row=f2row, column=2, sticky=Tkinter.NW) self.filePrefixEntry = Entry(frame2, text='cloud_', returnCallback=self.setFilePrefix, width=10) self.filePrefixEntry.grid(row=f2row, column=3, sticky=Tkinter.NW) f2row += 1 texts = ['Start molecular dynamics', 'Show dynamics progress'] commands = [self.startMd, self.showMdProgress] self.mdButtons = ButtonList(frame2, expands=1, commands=commands, texts=texts) self.mdButtons.grid(row=f2row, column=0, columnspan=4, sticky=Tkinter.NSEW) row += 1 self.bottomButtons = createDismissHelpButtonList(guiFrame, expands=0, help_url=None) self.bottomButtons.grid(row=row, column=0, sticky=Tkinter.EW) self.setButtonStates() def getStructures(self): names = [ '<None>', ] for molSystem in self.project.sortedMolSystems(): for structure in molSystem.sortedStructureEnsembles(): names.append('%s:%d' % (molSystem.name, structure.ensembleId)) return names def setStructure(self, index, name=None): if index < 1: self.structure = None else: structures = [] for molSystem in self.project.molSystems: for structure in molSystem.structureEnsembles: structures.append(structure) self.structure = structures[index - 1] def getAdcAtomTypes(self): return ['HN', 'HN HA', 'HN HA HB'] def setAdcAtomTypes(self, index, name=None): if name is None: name = self.adcAtomsPulldown.getSelected() self.adcAtomTypes = name def startMd(self): self.setNumClouds() self.setFilePrefix() if (self.distanceConstraintList and self.antiDistConstraintList and (self.numClouds > 0) and self.filePrefix): resDict = {} for resonance in self.guiParent.project.currentNmrProject.resonances: resDict[resonance.serial] = resonance resonances = [] for constraint in self.distanceConstraintList.constraints: for item in constraint.items: for fixedResonance in item.resonances: if resDict.get( fixedResonance.resonanceSerial) is not None: resonances.append( resDict[fixedResonance.resonanceSerial]) resDict[fixedResonance.resonanceSerial] = None startMdProcess(self.numClouds, self.distanceConstraintList, resonances, self.coolingScheme, self.filePrefix) #structGen = self.distanceConstraintList.structureGeneration serials = [] for resonance in resonances: serials.append(resonance.serial) clouds = [] for i in range(self.numClouds): clouds.append('%s%3.3d.pdb' % (self.filePrefix, i)) self.guiParent.application.setValues( self.distanceConstraintList.nmrConstraintStore, 'clouds', values=clouds) self.guiParent.application.setValues( self.distanceConstraintList.nmrConstraintStore, 'cloudsResonances', values=serials) # do better than this check for creation def showMdProgress(self): n = 0 m = self.numClouds for i in range(m): pdbFileName = '%s%3.3d.pdb' % (self.filePrefix, i) if os.path.exists(pdbFileName): n += 1 p = n * 100 / float(m) text = 'Done %d of %d clouds (%1.2f)%%' % (n, m, p) showInfo('MD Progress', text) def setFilePrefix(self, text=None): if not text: text = self.filePrefixEntry.get() if text: self.filePrefix = text def setNumClouds(self, n=None, *event): if not n: n = self.numCloudsEntry.get() if n: self.numClouds = int(n) def calculateDistances(self): # setup normalisation factor intensityMax # self.maxIter # what if failure ? resDict = {} for resonance in self.project.currentNmrProject.resonances: resDict[resonance.serial] = resonance self.resonances = self.origResonances intensityFactors = [1.0 for x in range(len(self.resonances))] # optimiseRelaxation will remove unconstrained resonances self.distanceConstraintList = optimiseRelaxation( self.resonances, self.noesyPeaks, intensityMax=self.maxIntens, intensityFactors=intensityFactors, tmix=self.mixTime, sf=self.specFreq, tcor=self.corrTime, rleak=self.leakRate) constrainSpinSystems(self.distanceConstraintList) # for testing calculate distances from structure overrides any resonances: uses assigned ones #(self.distanceConstraintList, self.resonances) = self.cheatForTesting() #self.antiDistConstraintList = self.distanceConstraintList protonNumbs = {'CH3': 3, 'Haro': 2, 'HN': 1, 'H': 1} PI = 3.1415926535897931 GH = 2.6752e4 HB = 1.05459e-27 CONST = GH * GH * GH * GH * HB * HB tc = 1.0e-9 * self.corrTime wh = 2.0 * PI * self.specFreq * 1.0e6 j0 = CONST * tc j1 = CONST * tc / (1.0 + wh * wh * tc * tc) j2 = CONST * tc / (1.0 + 4.0 * wh * wh * tc * tc) #jself = 6.0*j2 + 3.0*j1 + j0 jcross = 6.0 * j2 - j0 if self.distanceConstraintList: constraintStore = self.distanceConstraintList.nmrConstraintStore dict = { 'HN': ['H'], 'HN HA': ['H', 'HA', 'HA1', 'HA2'], 'HN HA HB': ['H', 'HA', 'HA1', 'HA2', 'HB', 'HB2', 'HB3'] } self.antiDistConstraintList = makeNoeAdcs( self.resonances, self.noesyPeakList.dataSource, constraintStore, allowedAtomTypes=dict[self.adcAtomTypes]) if self.structure: N = len(self.resonances) sigmas = [[] for i in range(N)] for i in range(N): sigmas[i] = [0.0 for j in range(N)] for constraint in self.distanceConstraintList.constraints: resonances = list(constraint, findFirstItem().resonances) ri = resDict[resonances[0].resonanceSerial] rj = resDict[resonances[1].resonanceSerial] i = self.resonances.index(ri) j = self.resonances.index(rj) atomSets1 = list(ri.resonanceSet.atomSets) atomSets2 = list(rj.resonanceSet.atomSets) if atomSets1 == atomSets2: ass = list(atomSets1) atomSets1 = [ ass[0], ] atomSets2 = [ ass[-1], ] distance = getAtomSetsDistance(atomSets1, atomSets2, self.structure) r = distance * 1e-8 nhs = protonNumbs[rj.name] sigma = 0.1 * jcross * nhs / (r**6) sigmas[i][j] = sigma constraint.setDetails('Known Dist: %4.3f' % (distance)) #for constraint in self.antiDistConstraintList.constraints: # atomSets1 = list(resonances[0].resonanceSet.atomSets) # atomSets2 = list(resonances[1].resonanceSet.atomSets) # distance = getAtomSetsDistance(atomSets1, atomSets2, self.structure) # constraint.setDetails('Known Dist: %4.3f' % (distance)) fp = open('sigmas.out', 'w') for i in range(N - 1): for j in range(i + 1, N): if sigmas[i][j] != 0.0: fp.write('%3.1d %3.1d %9.2e\n' % (i, j, sigmas[i][j])) #fp.write('\n') fp.close() self.setButtonStates() def cheatForTesting(self, atomSelection='H'): """ Makes a perfect cloud from a structure. """ project = self.project structure = self.guiParent.argumentServer.getStructure() constraintStore = makeNmrConstraintStore(project) distConstraintList = NmrConstraint.DistanceConstraintList( constraintStore) chain = structure.findFirstCoodChain() structureGeneration.hydrogenResonances = [] molSystem = structure.molSystem atomSets = [] resonances = [] i = 0 for resonance in project.currentNmrProject.resonances: if resonance.isotopeCode == '1H': if resonance.resonanceSet: atomSet = resonance.resonanceSet.findFirstAtomSet() atom = atomSet.findFirstAtom() seqId = atom.residue.seqId if (seqId < 9) or (seqId > 78): continue if atom.residue.chain.molSystem is molSystem: if atomSelection == 'methyl': if len(atomSet.atoms) == 3: if atom.residue.ccpCode not in ('Ala', 'Val', 'Ile', 'Leu', 'Thr', 'Met'): continue elif atom.name != 'H': continue elif atomSelection == 'amide': if atom.name != 'H': continue if atom.name == 'H': resonance.name = 'HN' else: resonance.name = 'H' resonances.append(resonance) atomSets.append(list(resonance.resonanceSet.atomSets)) i += 1 print "Found %d atomSets" % (len(atomSets)) weight = 1 adcWeight = 1 constrDict = {} N = len(atomSets) for i in range(N - 1): atomSets0 = atomSets[i] residue0 = atomSets0[0].findFirstAtom().residue.seqId print "R", residue0 for j in range(i + 1, N): if j == i: continue atomSets1 = atomSets[j] dist = getAtomSetsDistance(atomSets0, atomSets1, structure) if not dist: continue if dist < 5.5: fixedResonance0 = getFixedResonance( constraintStore, resonances[i]) fixedResonance1 = getFixedResonance( constraintStore, resonances[j]) constrDict[i] = 1 constrDict[j] = 1 constraint = NmrConstraint.DistanceConstraint( distConstraintList, weight=weight, targetValue=dist, upperLimit=dist + (dist / 10), lowerLimit=dist - (dist / 10), error=dist / 5) item = NmrConstraint.DistanceConstraintItem( constraint, resonances=[fixedResonance0, fixedResonance1]) elif (atomSets1[0].findFirstAtom().name == 'H') and (atomSets0[0].findFirstAtom().name == 'H') and (dist > 7): #else: fixedResonance0 = getFixedResonance( constraintStore, resonances[i]) fixedResonance1 = getFixedResonance( constraintStore, resonances[j]) constrDict[i] = 1 constrDict[j] = 1 constraint = NmrConstraint.DistanceConstraint( distConstraintList, weight=adcWeight, targetValue=75, upperLimit=175, lowerLimit=5.0, error=94.5) item = NmrConstraint.DistanceConstraintItem( constraint, resonances=[fixedResonance0, fixedResonance1]) return (distConstraintList, resonances) def showConstraints(self): if self.distanceConstraintList: self.guiParent.browseConstraints( constraintList=self.distanceConstraintList) def showAntiConstraints(self): if self.antiDistConstraintList: self.guiParent.browseConstraints( constraintList=self.antiDistConstraintList) def showPeaks(self): self.guiParent.viewPeaks(peaks=self.noesyPeaks) def showResonances(self): pass #self.guiParent.viewResonances(resonances=self.resonances) def setupResonances(self): if self.noesyPeakList and self.noesy3dPeakList and self.tocsyPeakList and self.hsqcPeakList: disambiguateNoesyPeaks(self.noesyPeakList, self.noesy3dPeakList, self.tocsyPeakList, self.hsqcPeakList) (self.origResonances, self.noesyPeaks, null) = getCloudsResonanceList(self.guiParent.argumentServer, hsqcPeakList=self.hsqcPeakList, tocsy3dPeakList=self.tocsyPeakList, noesy2dPeakList=self.noesyPeakList) self.setButtonStates() def setButtonStates(self): if self.origResonances: self.label03a.set('Resonances found: %d' % (len(self.origResonances))) if self.noesyPeaks: self.label03b.set('NOESY peaks found: %d' % (len(self.noesyPeaks))) if self.noesyPeakList and self.tocsyPeakList and self.hsqcPeakList: self.setupButtons.buttons[0].enable() else: self.setupButtons.buttons[0].disable() if self.noesyPeaks: self.setupButtons.buttons[1].enable() else: self.setupButtons.buttons[1].disable() if self.origResonances: self.setupButtons.buttons[2].enable() else: self.setupButtons.buttons[2].disable() if self.noesyPeaks and self.origResonances: self.midgeButtons.buttons[0].enable() else: self.midgeButtons.buttons[0].disable() if self.distanceConstraintList: self.midgeButtons.buttons[1].enable() self.distConstrLabel.set( 'Distance constraints: %d' % len(self.distanceConstraintList.constraints)) else: self.distConstrLabel.set('Distance constraints:') self.midgeButtons.buttons[1].disable() if self.antiDistConstraintList: self.antiConstrLabel.set( 'Anti-distance constraints: %d' % len(self.antiDistConstraintList.constraints)) self.midgeButtons.buttons[2].enable() else: self.antiConstrLabel.set('Anti-distance constraints:') self.midgeButtons.buttons[2].disable() if (self.distanceConstraintList and self.antiDistConstraintList and (self.numClouds > 0) and self.filePrefix): self.mdButtons.buttons[0].enable() self.mdButtons.buttons[1].enable() else: self.mdButtons.buttons[0].disable() self.mdButtons.buttons[1].disable() def getNoesys(self): names = [] spectra = getSpectraByType(self.project, '2dNOESY') for spectrum in spectra: for peakList in spectrum.peakLists: name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.noesyPeakList: self.noesyPeakList = peakList return names def setNoesy(self, index, name=None): if not name: name = self.noesyPulldown.getSelected() self.noesyPeakList = self.peakListDict[name] self.setButtonStates() def getTocsys(self): names = [] spectra = getSpectraByType(self.project, '3dTOCSY') for spectrum in spectra: for peakList in spectrum.peakLists: name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.tocsyPeakList: self.tocsyPeakList = peakList return names def getNoesy3ds(self): names = [] spectra = getSpectraByType(self.project, '3dNOESY') for spectrum in spectra: for peakList in spectrum.peakLists: name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.noesy3dPeakList: self.noesy3dPeakList = peakList return names def setTocsy(self, index, name=None): if not name: name = self.tocsyPulldown.getSelected() self.tocsyPeakList = self.peakListDict[name] self.setButtonStates() def setNoesy3d(self, index, name=None): if not name: name = self.noesy3dPulldown.getSelected() self.noesy3dPeakList = self.peakListDict[name] self.setButtonStates() def getHsqcs(self): names = [] spectra = getSpectraByType(self.project, 'HSQC') for spectrum in spectra: for peakList in spectrum.peakLists: name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.hsqcPeakList: self.hsqcPeakList = peakList return names def setHsqc(self, index, name=None): if not name: name = self.hsqcPulldown.getSelected() self.hsqcPeakList = self.peakListDict[name] self.setButtonStates() def getMdInitTemp(self, coolingStep): self.mdInitTempEntry.set(coolingStep[1]) def getMdFinTemp(self, coolingStep): self.mdFinTempEntry.set(coolingStep[2]) def getMdCoolSteps(self, coolingStep): self.mdCoolStepsEntry.set(coolingStep[3]) def getMdSimSteps(self, coolingStep): self.mdSimStepsEntry.set(coolingStep[4]) def getMdTau(self, coolingStep): self.mdTauEntry.set(coolingStep[5]) def getMdRepScale(self, coolingStep): self.mdRepScaleEntry.set(coolingStep[6]) def setMdInitTemp(self, event): value = self.mdInitTempEntry.get() if value is not None: self.coolingStep[1] = value self.updateCoolingScheme() def setMdFinTemp(self, event): value = self.mdFinTempEntry.get() if value is not None: self.coolingStep[2] = value self.updateCoolingScheme() def setMdCoolSteps(self, event): value = self.mdCoolStepsEntry.get() if value is not None: self.coolingStep[3] = value self.updateCoolingScheme() def setMdSimSteps(self, event): value = self.mdSimStepsEntry.get() if value is not None: self.coolingStep[4] = value self.updateCoolingScheme() def setMdTau(self, event): value = self.mdTauEntry.get() if value is not None: self.coolingStep[5] = value self.updateCoolingScheme() def setMdRepScale(self, event): value = self.mdRepScaleEntry.get() if value is not None: self.coolingStep[6] = value self.updateCoolingScheme() def selectCoolingStep(self, object, row, col): self.coolingStep = object def moveStepEarlier(self): if self.coolingStep: i = self.coolingStep[0] - 1 if i > 0: coolingStep = self.coolingScheme[i - 1] coolingStep[0] = i + 1 self.coolingStep[0] = i self.coolingScheme[i - 1] = self.coolingStep self.coolingScheme[i] = coolingStep self.updateCoolingScheme() self.coolingSchemeMatrix.hilightObject(self.coolingStep) def moveStepLater(self): if self.coolingStep: i = self.coolingStep[0] - 1 if i < len(self.coolingScheme) - 1: coolingStep = self.coolingScheme[i + 1] coolingStep[0] = i + 1 self.coolingStep[0] = i + 2 self.coolingScheme[i + 1] = self.coolingStep self.coolingScheme[i] = coolingStep self.updateCoolingScheme() self.coolingSchemeMatrix.hilightObject(self.coolingStep) def addCoolingStep(self): i = len(self.coolingScheme) + 1 datum = [i, 3000, 100, 10, 2500, 0.001, 1] self.coolingScheme.append(datum) self.updateCoolingScheme() def removeCoolingStep(self): if self.coolingStep: coolingScheme = [] i = 0 for coolingStep in self.coolingScheme: if coolingStep is not self.coolingStep: i += 1 coolingStep[0] = i coolingScheme.append(coolingStep) self.coolingScheme = coolingScheme self.updateCoolingScheme() def updateCoolingScheme(self): objectList = self.coolingScheme textMatrix = self.coolingScheme self.coolingSchemeMatrix.update(objectList=objectList, textMatrix=textMatrix) def updateMidgeParams(self): data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate, self.maxIntens ] self.midgeParamsMatrix.update(textMatrix=[ data, ]) def getSpecFreq(self, obj): self.specFreqEntry.set(self.specFreq) def getMaxIter(self, obj): self.maxIterEntry.set(self.maxIter) def getMixTime(self, obj): self.mixTimeEntry.set(self.mixTime) def getCorrTime(self, obj): self.corrTimeEntry.set(self.corrTime) def getLeakRate(self, obj): self.leakRateEntry.set(self.leakRate) def getMaxIntens(self, obj): self.maxIntensEntry.set(self.maxIntens) def setSpecFreq(self, event): value = self.specFreqEntry.get() if value is not None: self.specFreq = value self.updateMidgeParams() def setMaxIter(self, event): value = self.maxIterEntry.get() if value is not None: self.maxIter = value self.updateMidgeParams() def setMixTime(self, event): value = self.mixTimeEntry.get() if value is not None: self.mixTime = value self.updateMidgeParams() def setCorrTime(self, event): value = self.corrTimeEntry.get() if value is not None: self.corrTime = value self.updateMidgeParams() def setLeakRate(self, event): value = self.leakRateEntry.get() if value is not None: self.leakRate = value self.updateMidgeParams() def setMaxIntens(self, event): value = self.maxIntensEntry.get() if value is not None: self.maxIntens = value self.updateMidgeParams() def destroy(self): BasePopup.destroy(self)
class CloudHomologueAssignPopup(BasePopup): def __init__(self, parent, *args, **kw): self.guiParent = parent self.project = parent.getProject() self.molSystem = None self.chain = None self.assignment = None self.scores = [] BasePopup.__init__(self, parent, title="Cloud Threader", **kw) def body(self, guiFrame): guiFrame.grid_columnconfigure(3, weight=1) row = 0 label = Label(guiFrame, text='Molecular system: ') label.grid(row=row, column=0, sticky=Tkinter.NW) self.molSysPulldown = PulldownMenu(guiFrame, self.changeMolSystem, selected_index=-1, do_initial_callback=0) self.molSysPulldown.grid(row=row, column=1, sticky=Tkinter.NW) label = Label(guiFrame, text='Clouds files: ') label.grid(row=row, column=2, sticky=Tkinter.NW) self.filenameEntry = Entry(guiFrame,text='perfect00.pdb') self.filenameEntry.grid(row=row, column=3, sticky=Tkinter.NW) row += 1 label = Label(guiFrame, text='Chain: ') label.grid(row=row, column=0, sticky=Tkinter.NW) self.chainPulldown = PulldownMenu(guiFrame, self.changeChain, selected_index=-1, do_initial_callback=0) self.chainPulldown.grid(row=row, column=1, sticky=Tkinter.NW) label = Label(guiFrame, text='Thread steps: ') label.grid(row=row, column=2, sticky=Tkinter.NW) self.numStepsEntry = IntEntry(guiFrame,text=3000) self.numStepsEntry.grid(row=row, column=3, sticky=Tkinter.NW) row += 1 label = Label(guiFrame, text='Homologue PDB file: ') label.grid(row=row, column=0, sticky=Tkinter.NW) self.pdbEntry = Entry(guiFrame,text='') self.pdbEntry.grid(row=row, column=1, sticky=Tkinter.NW) label = Label(guiFrame, text='Dist. Threshold: ') label.grid(row=row, column=2, sticky=Tkinter.NW) self.distEntry = FloatEntry(guiFrame,text=3.0) self.distEntry.grid(row=row, column=3, sticky=Tkinter.NW) row += 1 label = Label(guiFrame, text='Global score: ') label.grid(row=row, column=0, sticky=Tkinter.NW) self.globalScoreLabel = Label(guiFrame, text='') self.globalScoreLabel.grid(row=row, column=1, sticky=Tkinter.NW) label = Label(guiFrame, text='Assignment Threshold: ') label.grid(row=row, column=2, sticky=Tkinter.NW) self.thresholdEntry = FloatEntry(guiFrame,text=-4.5) self.thresholdEntry.grid(row=row, column=3, sticky=Tkinter.NW) row += 1 guiFrame.grid_rowconfigure(row, weight=1) self.graph = ScrolledGraph(guiFrame, width=300, height=200) self.graph.grid(row=row, column=0, columnspan=4, sticky = Tkinter.NSEW) row += 1 texts = ['Run','Assign!'] commands = [self.run, self.assignSpinSystems] bottomButtons = createDismissHelpButtonList(guiFrame,texts=texts,commands=commands,expands=0,help_url=None) bottomButtons.grid(row=row, column=0, columnspan=4, sticky=Tkinter.EW) self.assignButton = bottomButtons.buttons[1] for func in ('__init__','delete'): Implementation.registerNotify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem', func) Implementation.registerNotify(self.updateChains, 'ccp.molecule.MolSystem.Chain', func) self.updateMolSystems() self.updateChains() def update(self): if self.assignment and self.scores: self.assignButton.enable() else: self.assignButton.disable() def run(self): if self.chain: pattern = self.filenameEntry.get() nSteps = self.numStepsEntry.get() or 4000 pdbFile = self.pdbEntry.get() dist = self.distEntry.get() or 3.0 pgb = ProgressBar(self, text='Searching', total=nSteps) files = getFileNamesFromPattern(pattern , '.') if not files: return clouds = getCloudsFromFile(files, self.chain.root) score, self.scores, self.assignment = cloudHomologueAssign(self.chain, clouds, pdbFile, dist, nSteps, self.graph, pgb) pgb.destroy() self.globalScoreLabel.set(str(score)) self.update() def assignSpinSystems(self): if self.assignment and self.scores: if showWarning('Query','Are you sure?'): threshold = self.thresholdEntry.get() or -4.0 i = 0 for residue in self.assignment.keys(): if self.scores[residue] > threshold: spinSystem = self.assignment[residue] assignSpinSystemResidue(spinSystem,residue=None) for residue in self.assignment.keys(): if self.scores[residue] > threshold: i += 1 spinSystem = self.assignment[residue] assignSpinSystemResidue(spinSystem,residue=residue) showWarning('Done','%d residues assigned' % i) def getMolSystems(self): names = [] for molSystem in self.project.molSystems: if molSystem.chains: names.append( '%s' % (molSystem.code) ) return names def changeMolSystem(self, i, name): self.molSystem = self.project.findFirstMolSystem(code=name) def updateMolSystems(self, *opt): names = self.getMolSystems() if names: if not self.molSystem: self.molSystem = self.project.findFirstMolSystem(code=names[0]) self.molSysPulldown.setup(names, names.index(self.molSystem.code)) def getChains(self): chains = [] if self.molSystem: for chain in self.molSystem.chains: chains.append( [chain.code, chain] ) return chains def changeChain(self, i, name=None): if not name: i = self.chainPulldown.selected_index chains = self.getChains() if chains: self.chain = chains[i][1] def updateChains(self, *chain): chains = self.getChains() if chains: names = [x[0] for x in chains] if (not self.chain) or (self.chain.code not in names): self.chain = chains[0][1] self.chainPulldown.setup(names, names.index(self.chain.code) ) self.update() def destroy(self): for func in ('__init__','delete'): Implementation.unregisterNotify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem', func) Implementation.unregisterNotify(self.updateChains, 'ccp.molecule.MolSystem.Chain', func) BasePopup.destroy(self)
class RegionSelector(Frame): def __init__(self, parent, label='', world_region=None, view_region=None, orient=Tkinter.HORIZONTAL, allow_resize=True, width=20, callback=None, borderwidth=1, show_text=True, text_color='#000000', text_decimals=2, units_scroll=0.1, pages_scroll=1.0, menu_entries=None, menu_callback=None, min_thickness=None, *args, **kw): self.menu_entries = menu_entries self.myCallback = callback Frame.__init__(self, parent, *args, **kw) self.text_decimals = text_decimals self.label = Label(self, text=label, width=4) self.menu = PulldownMenu(self, callback=menu_callback, entries=menu_entries) self.entry = FloatEntry(self, width=6, returnCallback=self.adjustScrollbar) self.region_scrollbar = RegionScrollbar(self, world_region=world_region, view_region=view_region, orient=orient, allow_resize=allow_resize, width=width, callback=self.doCallback, borderwidth=borderwidth, show_text=show_text, text_color=text_color, text_decimals=text_decimals, units_scroll=units_scroll, pages_scroll=pages_scroll, min_thickness=min_thickness) self.gridAll() def gridAll(self): col = 0 if (self.menu_entries and len(self.menu_entries) > 1): self.menu.grid(row=0, column=col, sticky=Tkinter.EW) col = col + 1 else: self.menu.grid_forget() self.label.grid(row=0, column=col, sticky=Tkinter.EW) col = col + 1 self.entry.grid(row=0, column=col, sticky=Tkinter.EW) self.grid_columnconfigure(col, weight=0) col = col + 1 self.region_scrollbar.grid(row=0, column=col, sticky=Tkinter.NSEW) self.grid_columnconfigure(col, weight=1) col = col + 1 self.grid_columnconfigure(col, weight=0) def setMinThickness(self, min_thickness): self.region_scrollbar.setMinThickness(min_thickness) def setMenuEntries(self, menu_entries): self.menu_entries = menu_entries self.menu.replace(menu_entries) self.gridAll() def getMenuEntry(self): return self.menu.getSelected() def adjustScrollbar(self, *event): try: x = float(self.entry.get()) except: showError('Entry error', 'Need to enter float in scrollbar box') self.setEntry() return (v0, v1) = self.region_scrollbar.view_region d = 0.5 * (v1 - v0) self.region_scrollbar.setViewRegion(x - d, x + d, do_callback=True) def doCallback(self, view_region): if (self.myCallback): self.myCallback(view_region) #print 'doCallback', view_region self.setEntry(view_region) def setEntry(self, view_region=None): if (not view_region): view_region = self.region_scrollbar.view_region (v0, v1) = view_region x = 0.5 * (v0 + v1) s = formatDecimals(x, decimals=self.text_decimals) self.entry.set(s) def __getattr__(self, name): # dispatch everything not defined by RegionSelector to scrollbar widget try: return getattr(self.__dict__['region_scrollbar'], name) except: raise AttributeError, "RegionSelector instance has no attribute '%s'" % name
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 EditPeakPopup(BasePopup): """ **Edit Position, Intensity & Details for a Peak** This popup window provides an means of editing peak information as an alternative to editing values in the main peak tables. This popup is also used to specify parameters for when a new peak is explicitly added to a peak list using a tabular display. The user can specify the position of the peak's dimensions in ppm, Hz or data point units. Also, the user can adjust the height and volume peak intensity values and a textual "Details" field, ,which can carry the user's comments about the peak. When editing an existing peak, no changes are made to the peak until the [Update] button is pressed. Likewise for a new peak the [Add Peak] button commits the changes. If the popup window is closed before the changes are committed then the entire editing or peak addition operation is cancelled. """ def __init__(self, parent, peak=None, peakList=None, *args, **kw): self.titleColor = '#000080' self.numDims = 0 self.peak = peak kw['borderwidth'] = 6 BasePopup.__init__(self, parent=parent, title='Edit Peak', **kw) self.registerNotify(self.deletedPeak, 'ccp.nmr.Nmr.Peak', 'delete') for func in ('setAnnotation', 'setDetails', 'setFigOfMerit'): self.registerNotify(self.updatePeak, 'ccp.nmr.Nmr.Peak', func) for func in ('setAnnotation', 'setPosition', 'setNumAliasing'): self.registerNotify(self.updatePeak, 'ccp.nmr.Nmr.PeakDim', func) for func in ('__init__', 'delete', 'setValue'): self.registerNotify(self.updatePeak, 'ccp.nmr.Nmr.PeakIntensity', func) self.dimensionLabels = [] self.dimensionEntries = [] self.update(self.peak, peakList) def body(self, guiParent): self.geometry("+150+150") guiParent.grid_columnconfigure(0, weight=1) self.master_frame = guiParent units = ('ppm', 'point', 'Hz') self.unit = 'ppm' self.specLabel = Label(guiParent, fg=self.titleColor, grid=(0, 0), sticky='ew') self.peakLabel = Label(guiParent, grid=(0, 1), sticky='ew') self.unit_frame = frame = Frame(guiParent, grid=(1, 1), gridSpan=(1, 2)) self.unitLabel = Label(frame, text='Current units: ', grid=(0, 0)) tipText = 'Selects which unit of measurement to display peak dimension positions with' self.unitSelect = PulldownList(frame, callback=self.changeUnit, texts=units, grid=(0, 1), tipText=tipText) self.heightLabel = Label(guiParent, text='Height', borderwidth=2, relief='groove') tipText = 'Sets the peak height; the value of the spectrum point intensity (albeit often interpolated)' self.heightEntry = FloatEntry(guiParent, borderwidth=1, tipText=tipText) self.volumeLabel = Label(guiParent, text='Volume', borderwidth=2, relief='groove') tipText = 'Sets the peak volume integral; normally a summation of data point values' self.volumeEntry = FloatEntry(guiParent, borderwidth=1, tipText=tipText) self.detailLabel = Label(guiParent, text='Details', borderwidth=2, relief='groove') tipText = 'A user-configurable textual comment for the peak, which appears an tables and occasionally on spectrum displays' self.detailEntry = Entry(guiParent, borderwidth=1, tipText=tipText) tipTexts = [ 'Commits the specified values to update the peak and closes the popup', ] texts = ['Update'] commands = [self.commit] self.buttons = UtilityButtonList(guiParent, texts=texts, commands=commands, doClone=False, helpUrl=self.help_url, tipTexts=tipTexts) def open(self): self.updatePeak() BasePopup.open(self) def updatePeak(self, object=None): peak = None if object: if object.className == 'Peak': peak = object elif object.className == 'PeakDim': peak = object.peak elif object.className == 'PeakIntensity': peak = object.peak if (peak is None) or (peak is self.peak): self.update(peak=self.peak) def update(self, peak=None, peakList=None): # first destroy old labels and entries (saves grid hassles) for label in self.dimensionLabels: label.destroy() for entry in self.dimensionEntries: entry.destroy() # now setup required data if peak: title = 'Edit Peak' self.buttons.buttons[0].config(text='Update') else: title = 'Add Peak' self.buttons.buttons[0].config(text='Add Peak') self.setTitle(title) self.peak = peak self.peakList = peakList if not peakList: if peak: self.peakList = peak.peakList else: return peakList = self.peakList spectrum = peakList.dataSource.name self.numDims = peakList.dataSource.numDim self.posn = self.numDims * [0] self.dataDims = peakList.dataSource.sortedDataDims() if self.peak: serial = self.peak.serial dims = self.peak.sortedPeakDims() details = self.peak.details if not details: details = '' if self.peak.annotation: annotn = '%0.16s' % self.peak.annotation else: annotn = '' heightIntensity = self.peak.findFirstPeakIntensity( intensityType='height') volumeIntensity = self.peak.findFirstPeakIntensity( intensityType='volume') if heightIntensity: height = heightIntensity.value else: height = 0.0 if volumeIntensity: volume = volumeIntensity.value else: volume = 0.0 for i in range(self.numDims): peakDim = dims[i] dataDimRef = peakDim.dataDimRef if dataDimRef: self.posn[i] = peakDim.position + ( peakDim.numAliasing * dataDimRef.dataDim.numPointsOrig) else: self.posn[i] = peakDim.position else: dict = peakList.__dict__.get('serialDict') if dict is None: serial = 1 else: serial = dict.get('peaks', 0) + 1 height = 0.0 volume = 0.0 details = '' annotn = '' self.specLabel.set( text='Experiment: %s Spectrum: %s PeakList: %d' % (peakList.dataSource.experiment.name, spectrum, peakList.serial)) self.peakLabel.set(text='Peak: %d' % serial) self.dimensionLabels = self.numDims * [''] self.dimensionEntries = self.numDims * [''] for i in range(self.numDims): pos = self.posn[i] if self.unit != 'point': dataDim = self.dataDims[i] if dataDim.className == 'FreqDataDim': pos = unit_converter[('point', self.unit)]( pos, getPrimaryDataDimRef(dataDim)) self.dimensionLabels[i] = Label(self.master_frame, text='F%d' % (i + 1), borderwidth=2, relief='groove') tipText = 'The peak position in dimension %d, in the specified units' % ( i + 1) self.dimensionEntries[i] = FloatEntry(self.master_frame, borderwidth=1, text='%8.4f' % pos, tipText=tipText) self.heightEntry.set(text='%f' % height) self.volumeEntry.set(text='%f' % volume) self.detailEntry.set(text=details) row = 0 self.specLabel.grid(row=row, column=0, columnspan=2, sticky='nsew') row = row + 1 self.peakLabel.grid(row=row, column=0, sticky='nsew') self.unit_frame.grid(row=row, column=1, columnspan=2, sticky='nsew') for i in range(self.numDims): row = row + 1 self.dimensionLabels[i].grid(row=row, column=0, sticky='nsew') self.dimensionEntries[i].grid(row=row, column=1, columnspan=3, sticky='e') row = row + 1 self.heightLabel.grid(row=row, column=0, sticky='nsew') self.heightEntry.grid(row=row, column=1, columnspan=3, sticky='e') row = row + 1 self.volumeLabel.grid(row=row, column=0, sticky='nsew') self.volumeEntry.grid(row=row, column=1, columnspan=3, sticky='e') row = row + 1 self.detailLabel.grid(row=row, column=0, sticky='nsew') self.detailEntry.grid(row=row, column=1, columnspan=3, sticky='e') row = row + 1 self.buttons.grid(row=row, column=0, columnspan=4, sticky='nsew') def changeUnit(self, unit): posDisp = self.numDims * [None] for i in range(self.numDims): posDisp[i] = float(self.dimensionEntries[i].get()) if self.unit != 'point': dataDim = self.dataDims[i] if dataDim.className == 'FreqDataDim': posDisp[i] = unit_converter[(self.unit, 'point')]( posDisp[i], getPrimaryDataDimRef(dataDim)) self.unit = unit if self.unit != 'point': for i in range(self.numDims): dataDim = self.dataDims[i] if dataDim.className == 'FreqDataDim': posDisp[i] = unit_converter[('point', self.unit)]( posDisp[i], getPrimaryDataDimRef(dataDim)) for i in range(self.numDims): value = posDisp[i] if value is None: self.dimensionEntries[i].set('None') else: self.dimensionEntries[i].set('%8.4f' % posDisp[i]) def commit(self): posDisp = self.numDims * [0] for i in range(self.numDims): posDisp[i] = float(self.dimensionEntries[i].get()) if self.unit != 'point': dataDim = self.dataDims[i] if dataDim.className == 'FreqDataDim': self.posn[i] = unit_converter[(self.unit, 'point')]( posDisp[i], getPrimaryDataDimRef(dataDim)) else: self.posn[i] = posDisp[i] if self.peak: movePeak(self.peak, self.posn) else: self.peak = pickPeak(self.peakList, self.posn) height = self.heightEntry.get() volume = self.volumeEntry.get() setManualPeakIntensity(self.peak, height, intensityType='height') setManualPeakIntensity(self.peak, volume, intensityType='volume') details = self.detailEntry.get() or None self.peak.setDetails(details) self.close() def deletedPeak(self, peak): if self.peak is peak: self.close() def destroy(self): self.unregisterNotify(self.deletedPeak, 'ccp.nmr.Nmr.Peak', 'delete') for func in ('setAnnotation', 'setDetails', 'setFigOfMerit'): self.unregisterNotify(self.updatePeak, 'ccp.nmr.Nmr.Peak', func) for func in ('setAnnotation', 'setPosition', 'setNumAliasing'): self.unregisterNotify(self.updatePeak, 'ccp.nmr.Nmr.PeakDim', func) for func in ('__init__', 'delete', 'setValue'): self.unregisterNotify(self.updatePeak, 'ccp.nmr.Nmr.PeakIntensity', func) BasePopup.destroy(self)
class MidgePopup(BasePopup): def __init__(self, parent, *args, **kw): self.guiParent = parent self.project = parent.getProject() self.waiting = 0 self.specFreq = 800.13 self.maxIter = 15 self.mixTime = 60 self.corrTime = 11.5 self.leakRate = 2.0 self.ratioHD = 0.9 self.peakListDict = {} self.peakListDict3d = {} self.noesyPeakList = None self.noesy3dPeakList = None self.carbonLabel = 0 self.nitrogenLabel = 1 self.noesyPeakList1 = None self.noesyPeakList2 = None self.noesyPeakList3 = None self.noesyPeakList3d = None self.resonances = None self.noesyPeaks = None self.distanceConstraintList = None self.antiDistConstraintList = None self.adcAtomTypes = None self.structure = None BasePopup.__init__(self, parent, title="Relaxation Matrix Optimisation", **kw) def body(self, guiFrame): self.specFreqEntry = IntEntry(self, text=self.specFreq, width=8, returnCallback=self.setSpecFreq) self.maxIterEntry = IntEntry(self, text=self.maxIter, width=8, returnCallback=self.setMaxIter) self.mixTimeEntry = FloatEntry(self, text=self.mixTime, width=8, returnCallback=self.setMixTime) self.corrTimeEntry = FloatEntry(self, text=self.corrTime, width=8, returnCallback=self.setCorrTime) self.leakRateEntry = FloatEntry(self, text=self.leakRate, width=8, returnCallback=self.setLeakRate) guiFrame.grid_columnconfigure(0, weight=1) guiFrame.grid_rowconfigure(1, weight=1) row = 0 labelFrame0 = LabelFrame(guiFrame, text='Input data') labelFrame0.grid(row=row, column=0, sticky=Tkinter.NSEW) labelFrame0.grid_columnconfigure(3, weight=1) label = Label(labelFrame0, text='Assigned NOESY spectrum') label.grid(row=0, column=0, sticky=Tkinter.NW) self.noesyPulldown = PulldownMenu(labelFrame0, entries=self.getNoesys(), callback=self.setNoesy, selected_index=0, do_initial_callback=0) self.noesyPulldown.grid(row=0, column=1, sticky=Tkinter.NW) label = Label(labelFrame0, text='H/D ratio: ') label.grid(row=0, column=2, sticky=Tkinter.NW) self.ratioHDEntry = FloatEntry(labelFrame0, text=self.ratioHD, width=6) self.ratioHDEntry.grid(row=0, column=3, sticky=Tkinter.NW) label = Label(labelFrame0, text='NOESY spectrum 1:') label.grid(row=1, column=0, sticky=Tkinter.NW) self.tmix1Pulldown = PulldownMenu(labelFrame0, entries=self.getNoesys(), callback=self.setNoesy1, selected_index=-0, do_initial_callback=0) self.tmix1Pulldown.grid(row=1, column=1, sticky=Tkinter.NW) label = Label(labelFrame0, text='Tmix (ms): ') label.grid(row=1, column=2, sticky=Tkinter.NW) self.tmix1Entry = FloatEntry(labelFrame0, text=60, width=6) self.tmix1Entry.grid(row=1, column=3, sticky=Tkinter.NW) label = Label(labelFrame0, text='NOESY spectrum 2:') label.grid(row=2, column=0, sticky=Tkinter.NW) self.tmix2Pulldown = PulldownMenu(labelFrame0, entries=self.getNoesys(), callback=self.setNoesy2, selected_index=0, do_initial_callback=0) self.tmix2Pulldown.grid(row=2, column=1, sticky=Tkinter.NW) label = Label(labelFrame0, text='Tmix (ms): ') label.grid(row=2, column=2, sticky=Tkinter.NW) self.tmix2Entry = FloatEntry(labelFrame0, text=120, width=6) self.tmix2Entry.grid(row=2, column=3, sticky=Tkinter.NW) label = Label(labelFrame0, text='NOESY spectrum 3:') label.grid(row=3, column=0, sticky=Tkinter.NW) self.tmix3Pulldown = PulldownMenu(labelFrame0, entries=self.getNoesys(), callback=self.setNoesy3, selected_index=0, do_initial_callback=0) self.tmix3Pulldown.grid(row=3, column=1, sticky=Tkinter.NW) label = Label(labelFrame0, text='Tmix (ms): ') label.grid(row=3, column=2, sticky=Tkinter.NW) self.tmix3Entry = FloatEntry(labelFrame0, text=200, width=6) self.tmix3Entry.grid(row=3, column=3, sticky=Tkinter.NW) label = Label(labelFrame0, text='3D NOESY:') label.grid(row=4, column=0, sticky=Tkinter.NW) self.noesy3dPulldown = PulldownMenu(labelFrame0, entries=self.getNoesys3d(), callback=self.setNoesy3d, selected_index=0, do_initial_callback=0) self.noesy3dPulldown.grid(row=4, column=1, sticky=Tkinter.NW) label10 = Label(labelFrame0, text='Num peaks:') label10.grid(row=5, column=0, sticky=Tkinter.NW) self.numPeaksLabel = Label(labelFrame0, text='0') self.numPeaksLabel.grid(row=5, column=1, sticky=Tkinter.NW) label11 = Label(labelFrame0, text='Num resonances:') label11.grid(row=5, column=2, sticky=Tkinter.NW) self.numResonancesLabel = Label(labelFrame0, text='0') self.numResonancesLabel.grid(row=5, column=3, sticky=Tkinter.NW) row += 1 labelFrame1 = LabelFrame(guiFrame, text='Parameters') labelFrame1.grid(row=row, column=0, sticky=Tkinter.NSEW) labelFrame1.grid_columnconfigure(3, weight=1) label = Label(labelFrame1, text='15N labelled sample:') label.grid(row=0, column=0, sticky=Tkinter.NW) self.nitrogenSelect = CheckButton(labelFrame1, callback=self.setNitrogenLabel) self.nitrogenSelect.grid(row=0, column=1, sticky=Tkinter.W) self.nitrogenSelect.set(1) label = Label(labelFrame1, text='13C labelled sample:') label.grid(row=0, column=2, sticky=Tkinter.NW) self.carbonSelect = CheckButton(labelFrame1, callback=self.setCarbonLabel) self.carbonSelect.grid(row=0, column=3, sticky=Tkinter.W) self.carbonSelect.set(0) labelFrame1.grid_rowconfigure(1, weight=1) data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate ] colHeadings = [ 'Spectrometer\nfrequency', 'Max\niterations', 'Mixing\ntime (ms)', 'Correl.\ntime (ns)', 'Leak\nrate' ] editWidgets = [ self.specFreqEntry, self.maxIterEntry, self.mixTimeEntry, self.corrTimeEntry, self.leakRateEntry, ] editGetCallbacks = [ self.getSpecFreq, self.getMaxIter, self.getMixTime, self.getCorrTime, self.getLeakRate, ] editSetCallbacks = [ self.setSpecFreq, self.setMaxIter, self.setMixTime, self.setCorrTime, self.setLeakRate, ] self.midgeParamsMatrix = ScrolledMatrix( labelFrame1, editSetCallbacks=editSetCallbacks, editGetCallbacks=editGetCallbacks, editWidgets=editWidgets, maxRows=1, initialCols=5, headingList=colHeadings, callback=None, objectList=[ 'None', ], textMatrix=[ data, ]) self.midgeParamsMatrix.grid(row=1, column=0, columnspan=4, sticky=Tkinter.NSEW) label10 = Label(labelFrame1, text='Benchmark structure') label10.grid(row=2, column=0, sticky=Tkinter.NW) self.structurePulldown = PulldownMenu(labelFrame1, entries=self.getStructures(), callback=self.setStructure, selected_index=0, do_initial_callback=0) self.structurePulldown.grid(row=2, column=1, sticky=Tkinter.NW) label11 = Label(labelFrame1, text='ADC atom types:') label11.grid(row=2, column=2, sticky=Tkinter.NW) self.adcAtomsPulldown = PulldownMenu(labelFrame1, entries=self.getAdcAtomTypes(), callback=self.setAdcAtomTypes, selected_index=0, do_initial_callback=0) self.adcAtomsPulldown.grid(row=2, column=3, sticky=Tkinter.NW) row += 1 labelFrame2 = LabelFrame(guiFrame, text='Output') labelFrame2.grid(row=row, column=0, sticky=Tkinter.NSEW) labelFrame2.grid_columnconfigure(3, weight=1) label20 = Label(labelFrame2, text='Distance constraints:') label20.grid(row=0, column=0, sticky=Tkinter.NW) self.distConstrLabel = Label(labelFrame2, text='0') self.distConstrLabel.grid(row=0, column=1, sticky=Tkinter.NW) label21 = Label(labelFrame2, text='Anti-distance constraints:') label21.grid(row=0, column=2, sticky=Tkinter.NW) self.antiConstrLabel = Label(labelFrame2, text='0') self.antiConstrLabel.grid(row=0, column=3, sticky=Tkinter.NW) texts = [ 'Calculate distances', 'Show distance\nconstraints', 'Show anti-distance\nconstraints' ] commands = [ self.calculateDistances, self.showConstraints, self.showAntiConstraints ] self.midgeButtons = ButtonList(labelFrame2, expands=1, texts=texts, commands=commands) self.midgeButtons.grid(row=1, column=0, columnspan=4, sticky=Tkinter.NSEW) row += 1 self.bottomButtons = createDismissHelpButtonList(guiFrame, expands=0, help_url=None) self.bottomButtons.grid(row=row, column=0, columnspan=4, sticky=Tkinter.EW) self.getPeaks() self.getResonances() self.update() self.geometry('600x400') def setCarbonLabel(self, boolean): self.carbonLabel = boolean def setNitrogenLabel(self, boolean): self.nitrogenLabel = boolean def update(self): if self.resonances and ( (self.noesyPeaks and self.noesyPeakList1 and self.noesyPeakList2 and self.noesyPeakList3) or self.noesyPeakList3d): self.midgeButtons.buttons[0].enable() else: self.midgeButtons.buttons[0].disable() if self.distanceConstraintList: self.distConstrLabel.set( str(len(self.distanceConstraintList.constraints))) self.midgeButtons.buttons[1].enable() else: self.distConstrLabel.set('') self.midgeButtons.buttons[1].disable() if self.antiDistConstraintList: self.antiConstrLabel.set( str(len(self.antiDistConstraintList.constraints))) self.midgeButtons.buttons[2].enable() else: self.antiConstrLabel.set('') self.midgeButtons.buttons[2].disable() if self.resonances: self.numResonancesLabel.set(str(len(self.resonances))) else: self.numResonancesLabel.set('') if self.noesyPeaks: self.numPeaksLabel.set(str(len(self.noesyPeaks))) else: self.numPeaksLabel.set('') def getStructures(self): names = [ '<None>', ] for molSystem in self.project.sortedMolSystems(): for structure in molSystem.sortedStructureEnsembles(): names.append('%s:%d' % (molSystem.name, structure.ensembleId)) return names def setStructure(self, index, name=None): if index < 1: self.structure = None else: structures = [] for molSystem in self.project.molSystems: for structure in molSystem.structureEnsembles: structures.append(structure) self.structure = structures[index - 1] def getAdcAtomTypes(self): return ['<None>', 'HN', 'HN HA', 'HN HA HB'] def setAdcAtomTypes(self, index, name=None): if name is None: name = self.adcAtomsPulldown.getSelected() if name == '<None>': name = None self.adcAtomTypes = name def getResonances(self): resonanceDict = {} if self.noesyPeaks: for peak in self.noesyPeaks: for peakDim in peak.peakDims: for contrib in peakDim.peakDimContribs: resonanceDict[contrib.resonance] = 1 # TBD: Set resonance.name for typing self.resonances = resonanceDict.keys() def getPeaks(self): if self.noesyPeakList: self.noesyPeaks = self.noesyPeakList.sortedPeaks() def calculateDistances(self): resonances = list(self.resonances) resDict = {} for resonance in resonances: resDict[resonance.serial] = resonance ratioHD = self.ratioHDEntry.get() or self.ratioHD tmix1 = self.tmix1Entry.get() or 60 tmix2 = self.tmix2Entry.get() or 120 tmix3 = self.tmix3Entry.get() or 200 data = [(tmix1, self.noesyPeakList1), (tmix2, self.noesyPeakList2), (tmix3, self.noesyPeakList3)] data.sort() mixingTimes = [x[0] for x in data] peakLists = [x[1] for x in data] # get a clean, symmetric and normalised NOE matrix noeMatrix = getNoeMatrixFromPeaks(self.noesyPeaks, resonances, peakLists, mixingTimes, ratioHD=ratioHD, analysis=self.guiParent) # optimiseRelaxation will remove unconstrained resonances self.distanceConstraintList, resonances = optimiseRelaxation( resonances, noeMatrix, self.mixTime, self.specFreq, self.corrTime, self.leakRate, self.carbonLabel, self.nitrogenLabel, maxIter=self.maxIter) #constrainSpinSystems(self.distanceConstraintList) # for testing calculate distances from structure overrides any resonances: uses assigned ones #(self.distanceConstraintList, self.resonances) = self.cheatForTesting() #self.antiDistConstraintList = self.distanceConstraintList protonNumbs = {'CH3': 3, 'Haro': 2, 'HN': 1, 'H': 1} PI = 3.1415926535897931 GH = 2.6752e4 HB = 1.05459e-27 CONST = GH * GH * GH * GH * HB * HB tc = 1.0e-9 * self.corrTime wh = 2.0 * PI * self.specFreq * 1.0e6 j0 = CONST * tc j1 = CONST * tc / (1.0 + wh * wh * tc * tc) j2 = CONST * tc / (1.0 + 4.0 * wh * wh * tc * tc) #jself = 6.0*j2 + 3.0*j1 + j0 jcross = 6.0 * j2 - j0 if self.distanceConstraintList and self.noesyPeakList: constraintHead = self.distanceConstraintList.nmrConstraintStore if self.adcAtomTypes: adcDict = { 'HN': ['H'], 'HN HA': ['H', 'HA', 'HA1', 'HA2'], 'HN HA HB': ['H', 'HA', 'HA1', 'HA2', 'HB', 'HB2', 'HB3'] } allowedAtomTypes = adcDict[self.adcAtomTypes] print "Making ADCs" self.antiDistConstraintList = makeNoeAdcs( resonances[:], self.noesyPeakList.dataSource, constraintHead, allowedAtomTypes=allowedAtomTypes) print "Done ADCs" if self.structure: N = len(self.resonances) sigmas = [[] for i in range(N)] for i in range(N): sigmas[i] = [0.0 for j in range(N)] for constraint in self.distanceConstraintList.constraints: item = constraint.findFirstItem() resonances = list(item.resonances) ri = resDict[resonances[0].resonanceSerial] rj = resDict[resonances[1].resonanceSerial] i = self.resonances.index(ri) j = self.resonances.index(rj) atomSets1 = list(ri.resonanceSet.atomSets) atomSets2 = list(rj.resonanceSet.atomSets) if atomSets1 == atomSets2: ass = list(atomSets1) atomSets1 = [ ass[0], ] atomSets2 = [ ass[-1], ] distance = getAtomSetsDistance(atomSets1, atomSets2, self.structure) r = distance * 1e-8 nhs = protonNumbs[rj.name] sigma = 0.1 * jcross * nhs / (r**6) sigmas[i][j] = sigma constraint.setOrigData(distance) self.update() def showConstraints(self): if self.distanceConstraintList: self.guiParent.browseConstraints( constraintList=self.distanceConstraintList) def showAntiConstraints(self): if self.antiDistConstraintList: self.guiParent.browseConstraints( constraintList=self.antiDistConstraintList) def getNoesys3d(self): peakLists = getThroughSpacePeakLists(self.project) names = [ '<None>', ] for peakList in peakLists: spectrum = peakList.dataSource if spectrum.numDim != 3: continue name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict3d[name] = peakList if not self.noesyPeakList: self.noesyPeakList = peakList return names def getNoesys(self): peakLists = getThroughSpacePeakLists(self.project) names = [ '<None>', ] for peakList in peakLists: spectrum = peakList.dataSource name = '%s:%s:%s' % (spectrum.experiment.name, spectrum.name, peakList.serial) names.append(name) self.peakListDict[name] = peakList if not self.noesyPeakList: self.noesyPeakList = peakList return names def setNoesy(self, index, name=None): if not name: name = self.noesyPulldown.getSelected() if name == '<None>': self.noesyPeakList = None else: self.noesyPeakList = self.peakListDict[name] self.getPeaks() self.getResonances() self.update() def setNoesy1(self, index, name=None): if not name: name = self.tmix1Pulldown.getSelected() if name != '<None>': self.noesyPeakList1 = self.peakListDict[name] else: self.noesyPeakList1 = None self.update() def setNoesy2(self, index, name=None): if not name: name = self.tmix2Pulldown.getSelected() if name != '<None>': self.noesyPeakList2 = self.peakListDict[name] else: self.noesyPeakList2 = None self.update() def setNoesy3(self, index, name=None): if not name: name = self.tmix3Pulldown.getSelected() if name != '<None>': self.noesyPeakList3 = self.peakListDict[name] else: self.noesyPeakList3 = None self.update() def setNoesy3d(self, index, name=None): if not name: name = self.noesy3dPulldown.getSelected() if name != '<None>': self.noesyPeakList3d = self.peakListDict3d[name] self.noesyPeaks = self.noesyPeakList3d.sortedPeaks() else: self.noesyPeakList3d = None self.noesyPeaks = [] self.getResonances() self.update() def updateMidgeParams(self): data = [ self.specFreq, self.maxIter, self.mixTime, self.corrTime, self.leakRate ] self.midgeParamsMatrix.update(textMatrix=[ data, ]) def getSpecFreq(self, obj): self.specFreqEntry.set(self.specFreq) def getMaxIter(self, obj): self.maxIterEntry.set(self.maxIter) def getMixTime(self, obj): self.mixTimeEntry.set(self.mixTime) def getCorrTime(self, obj): self.corrTimeEntry.set(self.corrTime) def getLeakRate(self, obj): self.leakRateEntry.set(self.leakRate) def setSpecFreq(self, event): value = self.specFreqEntry.get() if value is not None: self.specFreq = value self.updateMidgeParams() def setMaxIter(self, event): value = self.maxIterEntry.get() if value is not None: self.maxIter = value self.updateMidgeParams() def setMixTime(self, event): value = self.mixTimeEntry.get() if value is not None: self.mixTime = value self.updateMidgeParams() def setCorrTime(self, event): value = self.corrTimeEntry.get() if value is not None: self.corrTime = value self.updateMidgeParams() def setLeakRate(self, event): value = self.leakRateEntry.get() if value is not None: self.leakRate = value self.updateMidgeParams() def destroy(self): BasePopup.destroy(self)
class NmrPipePseudoPopup(BasePopup): pseudoEntries = ('Is Pseudo Expt', 'Is Not Pseudo Expt') def __init__(self, parent, params, dim, fileName='', *args, **kw): self.dim = dim self.params = params self.fileName = fileName m = template_re.match(fileName) if m: n = len(m.groups(2)) ss = '%%0%dd' % n template = re.sub(template_re, r'\1%s\3' % ss, fileName) else: template = fileName self.template = template BasePopup.__init__(self, parent=parent, title='NMRPipe Pseudo Data', modal=True, **kw) def body(self, master): fileName = self.fileName directory = os.path.dirname(fileName) if not directory: directory = os.getcwd() fileName = os.path.basename(fileName) m = template_re.match(fileName) if m: n = len(m.groups(2)) ss = '%%0%dd' % n template = re.sub(template_re, r'\1%s\3' % ss, fileName) else: template = fileName master.rowconfigure(0, weight=1) master.rowconfigure(1, weight=1) master.columnconfigure(1, weight=1) tipTexts = [ 'The experiment is pseudo-N dimensional, with a sampled axis', 'The experiment is the regular kind with only NMR frequency axes' ] self.pseudoButton = RadioButtons( master, entries=self.pseudoEntries, select_callback=self.changedPseudoMode, grid=(0, 0), sticky='nw', tipTexts=tipTexts) frame = self.pseudoFrame = Frame(master) self.pseudoFrame.grid(row=1, column=0, sticky='nsew') row = 0 npts = self.params.npts[self.dim] tipText = 'Number of data points (planes) along sampled axis' label = Label(frame, text='Number of points: ') label.grid(row=row, column=0, sticky='e') self.nptsEntry = IntEntry(frame, text=npts, tipText=tipText, width=8, grid=(row, 1)) tipText = 'Load the values for the sampled axis from a text file containing a list of numeric values' Button(frame, text='Load values from text file', command=self.loadValues, tipText=tipText, grid=(row, 2), sticky='ew') row = row + 1 tipText = 'The values (e.g. T1, T2) corresponding to each data point (plane) along sampled axis' label = Label(frame, text='Point values: ') label.grid(row=row, column=0, sticky='e') self.valueEntry = FloatEntry(frame, isArray=True, tipText=tipText) self.valueEntry.grid(row=row, column=1, columnspan=2, sticky='ew') row = row + 1 tipText = 'Fetch the Point values from the files given by the NMRPipe template' button = Button( frame, text='Fetch values from file(s) specified by template below', command=self.fetchValues, tipText=tipText) button.grid(row=row, column=1, columnspan=2, sticky='w') row = row + 1 tipText = 'The directory where the data files reside' button = Button(frame, text='Data directory: ', command=self.chooseDirectory) button.grid(row=row, column=0, sticky='e') self.directoryEntry = Entry(frame, text=directory, width=40, tipText=tipText) self.directoryEntry.grid(row=row, column=1, columnspan=2, sticky='ew') row = row + 1 tipText = 'The NMRPipe template for the data files, if you want to use these to fetch the point values from' button = Button(frame, text='NMRPipe template: ', command=self.chooseFile) button.grid(row=row, column=0, sticky='e') self.templateEntry = Entry(frame, text=template, tipText=tipText) self.templateEntry.grid(row=row, column=1, columnspan=2, sticky='ew') for n in range(row): frame.rowconfigure(n, weight=1) frame.columnconfigure(1, weight=1) buttons = UtilityButtonList(master, closeText='Ok', doClone=False, closeCmd=self.updateParams, helpUrl=self.help_url) buttons.grid(row=2, column=0, sticky='ew') def loadValues(self): directory = self.parent.fileSelect.getDirectory() fileSelectPopup = FileSelectPopup(self, title='Select Sampled Data File', dismiss_text='Cancel', selected_file_must_exist=True, multiSelect=False, directory=directory) fileName = fileSelectPopup.file_select.getFile() if not fileName: return fileObj = open(fileName, 'rU') data = '' line = fileObj.readline() while line: data += line line = fileObj.readline() fileObj.close() data = re.sub(',\s+', ',', data) data = re.sub('\s+', ',', data) data = re.sub(',,', ',', data) data = re.sub('[^0-9,.\-+eE]', '', data) self.valueEntry.set(data) def chooseDirectory(self): directory = os.path.dirname(self.fileName) if not directory: directory = os.getcwd() popup = FileSelectPopup(self, directory=directory, show_file=False) directory = popup.getDirectory() popup.destroy() if directory: self.directoryEntry.set(directory) def chooseFile(self): directory = self.directoryEntry.get() if not directory: directory = os.getcwd() popup = FileSelectPopup(self, directory=directory) file = popup.getFile() popup.destroy() if file: template = os.path.basename(file) self.templateEntry.set(template) def updateParams(self): params = self.params if self.pseudoButton.get() == self.pseudoEntries[0]: npts = self.nptsEntry.get() params.npts[self.dim] = npts values = self.valueEntry.get() try: params.setSampledDim(self.dim, values) except ApiError, e: showError('Set Sampled Dim', e.error_msg, parent=self) return params.fixNullDims(ignoreDim=self.dim) else:
class FilterCloudsPopup(BasePopup): def __init__(self, parent, *args, **kw): self.guiParent = parent self.structure = None self.name = None self.clouds = [] self.rmsds = [] self.names = [] self.atomTypes = None self.waiting = 0 BasePopup.__init__(self, parent=parent, title="Filter Clouds", **kw) def body(self, guiFrame): row = 0 guiFrame.grid_columnconfigure(3, weight=1) label = Label(guiFrame, text='Cloud file names:') label.grid(row=row, column=0, sticky=Tkinter.W) self.fileNameEntry = Entry(guiFrame, text='testHistone\d+.pdb', returnCallback=self.loadClouds) self.fileNameEntry.grid(row=row, column=1, sticky=Tkinter.W) strucLabel = Label(guiFrame, text='Comparison structure') strucLabel.grid(row=row, column=2, sticky=Tkinter.W) self.strucPulldown = PulldownMenu(guiFrame, entries=self.getStructures(), callback=self.setStructure, selected_index=0, do_initial_callback=0) self.strucPulldown.grid(row=row, column=3, sticky=Tkinter.W) row += 1 sdTolLabel = Label(guiFrame, text='Tolerance (SDs):') sdTolLabel.grid(row=row, column=0, sticky=Tkinter.W) self.sdToleranceEntry = FloatEntry(guiFrame, text=2.0, width=6) self.sdToleranceEntry.grid(row=row, column=1, stick=Tkinter.W) atomTypes = ['All', 'H', 'H HA', 'H HA HB'] label = Label(guiFrame, text='RMSD Atom Types:') label.grid(row=row, column=2, sticky=Tkinter.W) self.atomsPulldown = PulldownMenu(guiFrame, entries=atomTypes, callback=self.setAtomTypes, selected_index=0, do_initial_callback=0) self.atomsPulldown.grid(row=row, column=3, sticky=Tkinter.W) row += 1 guiFrame.grid_rowconfigure(row, weight=1) colHeadings = ['#', 'File name', 'RMSD to mean'] self.scrolledMatrix = ScrolledMatrix(guiFrame, initialRows=10, headingList=colHeadings, callback=self.selectCell, objectList=[], textMatrix=[ [], ], multiSelect=1) self.scrolledMatrix.grid(row=row, column=0, columnspan=4, sticky=Tkinter.NSEW) row += 1 texts = [ 'Load\nClouds', 'Align\nClouds', 'Calc\nRMSD', 'Make Cloud\nfrom structure', 'Remove', 'Remove\nbad' ] commands = [ self.loadClouds, self.alignClouds, self.calcRmsd, self.makeStrucCloud, self.deleteClouds, self.filterClouds ] self.bottomButtons = createDismissHelpButtonList( guiFrame, texts=texts, expands=1, commands=commands, help_url=self.help_url) self.bottomButtons.grid(row=row, column=0, columnspan=4, sticky=Tkinter.NSEW) self.update() def alignClouds(self): pattern = self.fileNameEntry.get() self.names = getFileNamesFromPattern(pattern, '.') self.clouds = getCloudsFromFile(self.names, self.guiParent.project) alignClouds(self.clouds, self.names) def loadClouds(self): pattern = self.fileNameEntry.get() self.names = getFileNamesFromPattern(pattern, '.') self.clouds = getCloudsFromFile(self.names, self.guiParent.project) self.name = None self.rmsds = [None for x in range(len(self.clouds))] self.updateAfter() def getStructures(self): names = [ '<None>', ] for molSystem in self.project.sortedMolSystems(): for structure in molSystem.sortedStructureEnsembles(): names.append('%s:%d' % (molSystem.name, structure.ensembleId)) return names def setStructure(self, index, name=None): if index < 1: self.structure = None else: structures = [] for molSystem in self.project.molSystems: for structure in molSystem.structures: structures.append(structure) self.structure = structures[index - 1] self.updateButtons() def setAtomTypes(self, index, name=None): self.atomTypes = atomTypeList[index] def filterClouds(self): if self.clouds: sdTolerance = self.sdToleranceEntry.get() or 2.0 keptClouds = [] meanRmsd = 0.0 N = 0 for rmsd in self.rmsds: meanRmsd += rmsd or 0.0 N += 1 if N > 0: meanRmsd /= float(N) sd = 0.0 for r in self.rmsds: rmsd = r or 0.0 sd += (rmsd - meanRmsd) * (rmsd - meanRmsd) if N > 0: sd /= float(N - 1) sd = sqrt(sd) print meanRmsd, '+/-', sd for i in range(len(self.clouds), 0, -1): rmsd = self.rmsds[i] if abs(rmsd - meanRmsd) > (sdTolerance * sd): self.rmsds.pop(i) self.names.pop(i) self.clouds.pop(i) #print 'Cloud %s is bad' % (cloud) self.updateAfter() def makeStrucCloud(self): if self.structure and self.clouds: pdbFileName = 'CloudForStructure.pdb' atomCoordList = [] atomCoordList0 = [] resDict = {} hmass = 25 resonances = self.clouds[0].keys() resonances2 = [] C = 0 for resonance in resonances: if resonance == 'rmsd': continue resonanceSet = resonance.resonanceSet if resonanceSet: i = list(resonanceSet.resonances).index(resonance) atomSet = list(resonance.resonanceSet.atomSets)[i] coords = getAtomSetCoords(atomSet, self.structure) coord = coords[0] atomCoordList.append([coord.x, coord.y, coord.z]) atomCoordList0.append([coord.x, coord.y, coord.z]) resonances2.append(resonance) C += 1 print len(atomCoordList) print len(resonances), len(resonances2) print "Generating Mean" cloudsList = [] for cloud in self.clouds: orderCloud = [] for resonance in resonances2: x, y, z = cloud.get(resonance) or (0.0, 0.0, 0.0) orderCloud.append([-x, -y, -z]) cloudsList.append(orderCloud) (meanCloud, cloudsList) = alignToMeanCloud(cloudsList) weights = [1.0 for x in atomCoordList] centerCoords(atomCoordList) print "init cen", getMeanCoords(atomCoordList) print "mean cen", getMeanCoords(meanCloud) print "Print aligning struct clouds to mean", len(meanCloud), len( atomCoordList), len(weights) atomCoordsList, error, rotMat = alignCoordinates( meanCloud, atomCoordList, weights) print " Rotation", rotMat writeTypedPdbCloud(atomCoordList, pdbFileName, resonances2) print "Getting centres" oldCentre = getMeanCoords(atomCoordList0) newCentre = getMeanCoords(atomCoordList) delta = [ newCentre[i] - oldCentre[i] for i in range(len(oldCentre)) ] print " New centre", newCentre print " Old centre", oldCentre print " Delta", delta #inverseRot = inverseMatrix(rotMat) model = self.structure.findFirstModel() coordinates = model.coordinates offset = 0 iis = (0, 1, 2) for atom in self.structure.orderedAtoms: next = offset + 3 coords = [coordinates[offset + ii] + delta[ii] for ii in iis] coords = matrixVecMultiply(rotMat, coords) coordinates[offset:next] = coords offset = next model.setSubmatrixData('coordinates', coordinates) clouds = getCloudsFromFile([ pdbFileName, ], self.structure.root) self.clouds.append(clouds[0]) self.rmsds.append(None) self.names.append(pdbFileName) self.updateAfter() def calcRmsd(self): if self.clouds: if len(self.scrolledMatrix.currentObjects) < 2: clouds = self.clouds else: clouds = [] for name in self.scrolledMatrix.currentObjects: clouds.append(self.clouds[self.names.index(name)]) self.rmsds = filterClouds(clouds, atomTypes=self.atomTypes) self.updateAfter() def deleteClouds(self): if self.names and self.name and showOkCancel( 'Confirm', 'Really remove selected clouds?'): indices = [] for name in self.scrolledMatrix.currentObjects: i = self.names.index(name) indices.append(i) indices.sort() indices.reverse() for i in indices: self.clouds.pop(i) self.rmsds.pop(i) self.names.pop(i) self.name = None self.updateAfter() def selectCell(self, name, row, col): self.name = name self.updateButtons() def updateAfter(self, *opt): if self.waiting: return else: self.waiting = 1 self.after_idle(self.update) def destroy(self): BasePopup.destroy(self) def updateButtons(self): if self.names: self.bottomButtons.buttons[1].enable() self.bottomButtons.buttons[2].enable() self.bottomButtons.buttons[5].enable() else: self.bottomButtons.buttons[1].disable() self.bottomButtons.buttons[2].enable() self.bottomButtons.buttons[5].disable() if self.name: self.bottomButtons.buttons[4].enable() else: self.bottomButtons.buttons[4].disable() if self.structure and self.clouds: self.bottomButtons.buttons[3].enable() else: self.bottomButtons.buttons[3].disable() def update(self): textMatrix = [] objectList = self.names self.updateButtons() i = 0 for name in objectList: datum = [] datum.append(i + 1) datum.append(name) datum.append(self.rmsds[i]) textMatrix.append(datum) i += 1 if not objectList: textMatrix = [ [], ] self.scrolledMatrix.update(objectList=objectList, textMatrix=textMatrix) self.waiting = 0
class EditResStructuresPopup(BasePopup): def __init__(self, parent, *args, **kw): self.guiParent = parent self.structure = None self.constraintSet = None self.cloud = None self.cloudRmsdDict = {} self.strucRmsdDict = {} self.waiting = False BasePopup.__init__(self, parent=parent, title="Resonance Cloud Structures", **kw) def body(self, guiFrame): row = 0 guiFrame.grid_columnconfigure(1, weight=1) guiFrame.grid_rowconfigure(0, weight=0) guiFrame.grid_rowconfigure(1, weight=1) self.generationLabel = Label(guiFrame, text='Structure Generation:') constraintSets = [] constraintSetNames = [] index = -1 for constraintSet in self.project.nmrConstraintStores: index += 1 constraintSets.append(constraintSet) constraintSetNames.append(str(constraintSet.serial)) self.constraintSet = constraintSet self.constrSetPulldown = PulldownMenu(guiFrame, self.changeConstraintSet, constraintSetNames, selected_index=index, do_initial_callback=False) self.generationLabel.grid(row=row, column=0, columnspan=1, sticky='e') self.constrSetPulldown.grid(row=row, column=1, columnspan=1, sticky='w') strucLabel = Label(guiFrame, text='Comparison structure') strucLabel.grid(row=row, column=2, sticky='e') self.strucPulldown = PulldownMenu(guiFrame, entries=self.getStructures(), callback=self.setStructure, selected_index=0, do_initial_callback=False) self.strucPulldown.grid(row=row, column=3, sticky='w') sdTolLabel = Label(guiFrame, text='Tolerance (SDs):') sdTolLabel.grid(row=row, column=4, sticky='e') self.sdToleranceEntry = FloatEntry(guiFrame, text=2.0, width=6) self.sdToleranceEntry.grid(row=row, column=5, stick='w') row += 1 colHeadings = ['#', 'File name', 'RMSD to mean', 'RMSD to structure'] self.scrolledMatrix = ScrolledMatrix(guiFrame, initialRows=10, headingList=colHeadings, callback=self.selectCell, objectList=[], textMatrix=[ [], ]) self.scrolledMatrix.grid(row=row, column=0, columnspan=6, sticky='nsew') row += 1 texts = [ 'Calc\nRMSD', 'Make Cloud\nfrom structure', 'Delete', 'Delete\nbad' ] commands = [ self.calcRmsd, self.makeStrucCloud, self.deleteCloud, self.filterClouds ] self.bottomButtons = UtilityButtonList(guiFrame, texts=texts, expands=False, commands=commands, helpUrl=self.help_url) self.bottomButtons.grid(row=row, column=0, columnspan=6, sticky='nsew') self.update() for func in ('__init__', 'delete'): self.registerNotify(self.updateStructureGen, 'ccp.nmr.Nmr.StructureGeneration', func) def open(self): self.updateAfter() BasePopup.open(self) def getStructures(self): names = [ '<None>', ] for molSystem in self.project.sortedMolSystems(): for structure in molSystem.sortedStructureEnsembles(): names.append('%s:%d' % (molSystem.name, structure.ensembleId)) return names def setStructure(self, index, name=None): if index < 1: self.structure = None else: structures = [] for molSystem in self.project.sortedMolSystems(): for structure in molSystem.sortedStructureEnsembles(): structures.append(structure) self.structure = structures[index - 1] def filterClouds(self): if self.constraintSet: sdTolerance = self.sdToleranceEntry.get() or 2.0 keptClouds = [] clouds = self.guiParent.application.getValues( self.constraintSet, 'clouds') meanGroupRmsds = [] for cloud in clouds: rmsd = self.cloudRmsdDict.get(cloud) if rmsd is not None: meanGroupRmsds.append(rmsd) meanRmsd = 0.0 N = 0 for rmsd in meanGroupRmsds: meanRmsd += rmsd N += 1 if N > 0: meanRmsd /= float(N) sd = 0.0 for rmsd in meanGroupRmsds: sd += (rmsd - meanRmsd) * (rmsd - meanRmsd) if N > 0: sd /= float(N - 1) sd = sqrt(sd) print meanRmsd, '+/-', sd n = 0 for cloud in clouds: rmsd = self.cloudRmsdDict.get(cloud) if rmsd is None: keptClouds.append(cloud) elif abs(rmsd - meanRmsd) > (sdTolerance * sd): print 'Cloud %s is bad' % (cloud) else: keptClouds.append(cloud) self.guiParent.application.setValues(self.constraintSet, 'clouds', values=keptClouds) self.updateAfter() def makeStrucCloud(self): if self.structure: serials = self.guiParent.application.getValues( self.constraintSet, 'cloudsResonances') pdbFileName = 'CloudForStructure.pdb' #from ccpnmr.clouds.AtomCoordList import AtomCoordList from ccpnmr.c.AtomCoordList import AtomCoordList atomCoordList = AtomCoordList() resDict = {} hmass = 25 print "L1", len(serials) for resonance in self.nmrProject.resonances: resDict[resonance.serial] = resonance print "L2", len(resDict) resonances = [] for serial in serials: if resDict.get(serial) is not None: resonances.append(resDict[serial]) print "L3", len(resonances) C = 0 for resonance in resonances: resonanceSet = resonance.resonanceSet if resonanceSet: i = resonanceSet.sortedResonances().index(resonance) atomSet = resonance.resonanceSet.sortedAtomSets()[i] coords = getAtomSetCoords(atomSet, self.structure) coord = coords[0] atomCoordList.add(hmass, coord.x, coord.y, coord.z) C += 1 print "L4", len(atomCoordList) from ccpnmr.clouds.FilterClouds import writeTypedPdbCloud writeTypedPdbCloud(atomCoordList, pdbFileName, resonances) clouds = self.guiParent.application.getValues( self.constraintSet, 'clouds') clouds.append(pdbFileName) self.guiParent.application.setValues(self.constraintSet, 'clouds', values=clouds) self.updateAfter() def calcRmsd(self): if self.constraintSet: clouds = self.guiParent.application.getValues( self.constraintSet, 'clouds') from ccpnmr.clouds.FilterClouds import filterClouds rmsds = filterClouds(clouds) n = len(clouds) for i in range(n): cloud = clouds[i] rmsd = rmsds[i] self.cloudRmsdDict[cloud] = rmsd self.updateAfter() def changeConstraintSet(self, i, name): project = self.project if project.nmrConstraintStores: constraintSet = project.nmrConstraintStores[i] else: constraintSet = None if constraintSet is not self.constraintSet: self.constraintSet = constraintSet self.cloud = None self.updateAfter() def deleteCloud(self): if self.constraintSet and self.cloud and showOkCancel( 'Confirm', 'Really delete resonance cloud?', parent=self): clouds = self.guiParent.application.getValues( self.constraintSet, 'clouds') if clouds: clouds.remove(self.cloud) self.cloud = None self.guiParent.application.setValues(self.constraintSet, 'clouds', values=clouds) self.updateAfter() def selectCell(self, cloud, row, col): self.cloud = cloud self.bottomButtons.buttons[1].enable() def updateAfter(self, *opt): if self.waiting: return else: self.waiting = True self.after_idle(self.update) def getConstraintSetNames(self): names = [] constraintSets = self.project.nmrConstraintStores for set in constraintSets: names.append('%d' % set.serial) return names def updateStructureGen(self, *opt): project = self.project constraintSets = self.project.sortedNmrConstraintStores if constraintSets: constraintSetNames = self.getConstraintSetNames() # set defaults if self.constraintSet not in constraintSets: self.constraintSet = constraintSets[0] self.cloud = None i = constraintSets.index(self.constraintSet) self.constrSetPulldown.setup(constraintSetNames, i) else: self.constraintSet = None self.cloud = None self.constrSetPulldown.setup([], -1) def destroy(self): for func in ('__init__', 'delete'): self.unregisterNotify(self.updateStructureGen, 'ccp.nmr.Nmr.StructureGeneration', func) BasePopup.destroy(self) def update(self): objectList = [] textMatrix = [] if self.constraintSet: clouds = self.guiParent.application.getValues( self.constraintSet, 'clouds') if clouds: objectList = list(clouds) i = 0 for cloud in objectList: i += 1 datum = [] datum.append(i) datum.append(cloud) datum.append(self.cloudRmsdDict.get(cloud) or '-') datum.append(self.strucRmsdDict.get(cloud) or '-') textMatrix.append(datum) if not self.cloud: self.bottomButtons.buttons[1].disable() self.scrolledMatrix.update(objectList=objectList, textMatrix=textMatrix) self.waiting = False
class BrukerPseudoPopup(BasePopup): def __init__(self, parent, params, dim, *args, **kw): self.dim = dim self.params = params BasePopup.__init__(self, parent=parent, title='Bruker Pseudo Data', modal=True, **kw) def body(self, master): pseudoExpts = getSampledDimExperiments(self.parent.nmrProject) master.rowconfigure(0, weight=1) master.rowconfigure(1, weight=1) master.columnconfigure(0, weight=1) tipTexts = ['The experiment is pseudo-N dimensional, with a sampled axis', 'The experiment is the regular kind with only NMR frequency axes'] self.pseudoEntries = [x % len(self.params.npts) for x in PSEUDO_ENTRIES] self.pseudoButton = RadioButtons(master, entries=self.pseudoEntries, select_callback=self.changedPseudoMode, grid=(0,0), sticky='nw', tipTexts=tipTexts) frame = self.pseudoFrame = Frame(master) self.pseudoFrame.grid(row=1, column=0, sticky='nsew') row = 0 if pseudoExpts: tipText = 'Select from existing pseudo nD experiments to copy sampled axis values from' texts = [x.name for x in pseudoExpts] label = Label(frame, text='Existing pseudo expts: ') label.grid(row=row, column=0, sticky='e') self.pseudoList = PulldownList(frame, texts=texts, objects=pseudoExpts, tipText=tipText) self.pseudoList.grid(row=row, column=1, sticky='w') tipText = 'Transfer the sampled axis values from the existing experiment to the new one' Button(frame, text='Copy values down', command=self.copyValues, tipText=tipText, grid=(row,2)) row += 1 npts = self.params.npts[self.dim] tipText = 'Number of data points (planes) along sampled axis' label = Label(frame, text='Number of points: ') label.grid(row=row, column=0, sticky='e') self.nptsEntry = IntEntry(frame, text=npts, tipText=tipText, width=8, grid=(row,1)) tipText = 'Load the values for the sampled axis from a text file containing a list of numeric values' Button(frame, text='Load File', command=self.loadValues, tipText=tipText, grid=(row,2), sticky='ew') row += 1 tipText = 'The values (e.g. T1, T2) corresponding to each data point (plane) along sampled axis' label = Label(frame, text='Point values: ') label.grid(row=row, column=0, sticky='e') self.valueEntry = FloatEntry(frame, isArray=True, tipText=tipText) #minRows = self.params.npts[self.dim] #self.valueEntry = MultiWidget(frame, FloatEntry, callback=None, minRows=minRows, maxRows=None, # options=None, values=[], useImages=False) self.valueEntry.grid(row=row, column=1, columnspan=2, sticky='ew') row += 1 label = Label(frame, text='(requires comma-separated list, of length number of points)') label.grid(row=row, column=1, columnspan=2, sticky='w') row += 1 for n in range(row): frame.rowconfigure(n, weight=1) frame.columnconfigure(1, weight=1) buttons = UtilityButtonList(master, closeText='Ok', closeCmd=self.updateParams, helpUrl=self.help_url) buttons.grid(row=row, column=0, sticky='ew') def loadValues(self): directory = self.parent.fileSelect.getDirectory() fileSelectPopup = FileSelectPopup(self, title='Select Sampled Data File', dismiss_text='Cancel', selected_file_must_exist=True, multiSelect=False, directory=directory) fileName = fileSelectPopup.file_select.getFile() fileObj = open(fileName, 'rU') data = '' line = fileObj.readline() while line: data += line line = fileObj.readline() data = re.sub(',\s+', ',', data) data = re.sub('\s+', ',', data) data = re.sub(',,', ',', data) data = re.sub('[^0-9,.\-+eE]', '', data) self.valueEntry.set(data) def copyValues(self): expt = self.pseudoList.getObject() if expt: dataDim = getExperimentSampledDim(expt) values = dataDim.pointValues self.nptsEntry.set(len(values)) self.valueEntry.set(values) def updateParams(self): params = self.params if self.pseudoButton.get() == self.pseudoEntries[0]: npts = self.nptsEntry.get() params.npts[self.dim] = npts values = self.valueEntry.get() try: params.setSampledDim(self.dim, values) except ApiError, e: showError('Set Sampled Dim', e.error_msg, parent=self) return else:
class PrintFrame(LabelFrame): def __init__(self, parent, getOption=None, setOption=None, text='Print Options', haveTicks=False, doOutlineBox=True, *args, **kw): self.getOption = getOption self.setOption = setOption self.haveTicks = haveTicks self.doOutlineBox = doOutlineBox LabelFrame.__init__(self, parent=parent, text=text, *args, **kw) self.file_select_popup = None self.getOptionValues() try: size_index = self.paper_types.index(self.paper_type) except: size_index = 0 try: other_unit_index = self.paper_units.index(self.other_unit) except: other_unit_index = 0 try: orientation_index = self.paper_orientations.index(self.orientation) except: orientation_index = 0 try: style_index = self.style_choices.index(self.output_style) except: style_index = 0 try: format_index = self.format_choices.index(self.output_format) except: format_index = 0 if haveTicks: try: tick_location_index = self.tick_locations.index( self.tick_location) except: tick_location_index = 0 self.grid_columnconfigure(2, weight=1) row = 0 label = Label(self, text='File:') label.grid(row=row, column=0, sticky='e') self.file_entry = Entry(self, width=40, text=self.file_name) self.file_entry.grid(row=row, column=1, columnspan=2, sticky='ew') button = Button(self, text='Choose File', command=self.findFile) button.grid(row=row, column=3, rowspan=2, sticky='nsew') row += 1 label = Label(self, text='Title:') label.grid(row=row, column=0, sticky='e') self.title_entry = Entry(self, width=40, text=self.title) self.title_entry.grid(row=row, column=1, columnspan=2, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(4, weight=1) label = Label(frame, text='Paper size:') label.grid(row=0, column=0, sticky='e') entries = [] for t in paper_types: if t == Output.other_paper_type: entry = t else: (w, h, u) = paper_sizes[t] entry = t + ' (%2.1f %s x %2.1f %s)' % (w, u, h, u) entries.append(entry) self.size_menu = PulldownList(frame, callback=self.changedSize, texts=entries, index=size_index) self.size_menu.grid(row=0, column=1, sticky='w') self.other_frame = Frame(frame) self.other_frame.grid_columnconfigure(0, weight=1) self.other_entry = FloatEntry(self.other_frame, text=self.other_size, isArray=True) self.other_entry.grid(row=0, column=0, sticky='ew') self.other_unit_menu = PulldownList(self.other_frame, texts=paper_units, index=other_unit_index) self.other_unit_menu.grid(row=0, column=1, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) frame.grid_columnconfigure(5, weight=1) label = Label(frame, text='Orientation:') label.grid(row=0, column=0, sticky='e') self.orientation_menu = PulldownList(frame, texts=paper_orientations, index=orientation_index) self.orientation_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Style:') label.grid(row=0, column=2, sticky='e') self.style_menu = PulldownList(frame, texts=style_choices, index=style_index) self.style_menu.grid(row=0, column=3, sticky='w') label = Label(frame, text=' Format:') label.grid(row=0, column=4, sticky='e') self.format_menu = PulldownList(frame, callback=self.changedFormat, texts=format_choices, index=format_index) self.format_menu.grid(row=0, column=5, sticky='w') if haveTicks: row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Tick Location:') label.grid(row=0, column=0, sticky='e') self.tick_menu = PulldownList(frame, texts=tick_locations, index=tick_location_index) self.tick_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Tick Placement:') label.grid(row=0, column=2, sticky='e') self.tick_buttons = CheckButtons(frame, entries=tick_placements, selected=self.tick_placement) self.tick_buttons.grid(row=0, column=3, sticky='w') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Include:') label.grid(row=0, column=0, sticky='e') self.border_buttons = CheckButtons(frame, entries=border_decorations, selected=self.border_decoration) self.border_buttons.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Scaling:') label.grid(row=0, column=2, sticky='e') self.scaling_scale = Scale(frame, orient=Tkinter.HORIZONTAL, value=self.scaling) self.scaling_scale.grid(row=0, column=3, sticky='ew') def destroy(self): self.setOptionValues() if self.file_select_popup: self.file_select_popup.destroy() Frame.destroy(self) def getOptionValues(self): getOption = self.getOption if getOption: file_name = getOption('FileName', defaultValue='') title = getOption('Title', defaultValue='') paper_type = getOption('PaperSize', defaultValue=paper_types[0]) paper_type = paper_type_dict.get(paper_type, paper_types[0]) other_height = getOption('OtherHeight', defaultValue=10) other_width = getOption('OtherWidth', defaultValue=10) other_size = [other_height, other_width] other_unit = getOption('OtherUnit', defaultValue=paper_units[0]) orientation = getOption('Orientation', defaultValue=paper_orientations[0]) in_color = getOption('InColor', defaultValue=True) if in_color: output_style = style_choices[0] else: output_style = style_choices[1] format_option = getOption('OutputFormat', defaultValue=format_options[0]) output_format = format_choices[format_options.index(format_option)] if self.haveTicks: tick_outside = getOption('TickOutside', defaultValue=tick_locations[0]) if tick_outside: tick_location = tick_locations.index(PrintTicks.Outside) else: tick_location = tick_locations.index(PrintTicks.Inside) tick_placement = getTickPlacement1( getOption('TickPlacement', defaultValue='nsew')) dateTime = getOption('ShowsDateTime', defaultValue=True) fileName = getOption('ShowsFileName', defaultValue=True) border_decoration = [] if dateTime: border_decoration.append(border_decorations[0]) if fileName: border_decoration.append(border_decorations[1]) scaling = getOption('Scaling', defaultValue=0.9) scaling = int(round(100.0 * scaling)) else: file_name = '' title = '' paper_type = paper_types[0] other_unit = paper_units[0] other_size = '' orientation = paper_orientations[0] output_style = style_choices[0] output_format = format_choices[0] if self.haveTicks: tick_location = tick_locations[0] tick_placement = tick_placements border_decoration = border_decorations scaling = 90 if not self.haveTicks: tick_location = None tick_placement = None self.file_name = file_name self.title = title self.paper_type = paper_type self.other_unit = other_unit self.other_size = other_size self.orientation = orientation self.output_style = output_style self.output_format = output_format self.tick_location = tick_location self.tick_placement = tick_placement self.border_decoration = border_decoration self.scaling = scaling def setOptionValues(self): self.file_name = file_name = self.file_entry.get() self.title = title = self.title_entry.get() n = self.size_menu.getSelectedIndex() self.paper_type = paper_type = paper_types[n] if paper_type == Output.other_paper_type: other_size = self.other_entry.get() other_unit = self.other_unit_menu.getText() else: other_size = None other_unit = None self.other_size = other_size self.other_unit = other_unit self.paper_orientation = paper_orientation = self.orientation_menu.getText( ) self.output_style = output_style = self.style_menu.getText() self.output_format = output_format = self.format_menu.getText() if self.haveTicks: tick_location = self.tick_menu.getText() tick_placement = self.tick_buttons.getSelected() else: tick_location = tick_placement = None self.tick_location = tick_location self.tick_placement = tick_placement self.border_decoration = border_decoration = self.border_buttons.getSelected( ) scaling = self.scaling_scale.get() self.scaling = scaling = int(round(scaling)) setOption = self.setOption if setOption: setOption('FileName', value=file_name) setOption('Title', value=title) if paper_type == Output.other_paper_type: setOption('OtherHeight', value=other_size[0]) setOption('OtherWidth', value=other_size[1]) setOption('OtherUnit', value=other_unit) else: paper_type = paper_type_inverse_dict[paper_type] setOption('PaperSize', value=paper_type) setOption('Orientation', value=paper_orientation) in_color = (output_style == style_choices[0]) setOption('InColor', value=in_color) output_format = format_options[format_choices.index(output_format)] setOption('OutputFormat', value=output_format) if self.haveTicks: tick_outside = (tick_location == PrintTicks.Outside) setOption('TickOutside', value=tick_outside) tick_placement = getTickPlacement2(tick_placement) setOption('TickPlacement', value=tick_placement) dateTime = (border_decorations[0] in border_decoration) fileName = (border_decorations[1] in border_decoration) setOption('ShowsDateTime', value=dateTime) setOption('ShowsFileName', value=fileName) setOption('Scaling', value=0.01 * scaling) def findFile(self): if self.file_select_popup: self.file_select_popup.open() else: file_types = [ FileType('All', ['*']), FileType('PostScript', ['*.ps', '*.eps']), FileType('PDF', ['*.pdf', '*.ai']) ] self.file_select_popup = FileSelectPopup(self, file_types=file_types) file = self.file_select_popup.getFile() if file: self.file_entry.set(file) def changedSize(self, entry): if entry == Output.other_paper_type: self.other_frame.grid(row=0, column=2, columnspan=2, sticky='w') else: self.other_frame.grid_forget() def changedFormat(self, entry): file_suffix = file_suffixes.get(entry) if not file_suffix: return file_name = self.file_entry.get() if not file_name: return for suffix in format_suffixes: if file_name.endswith(suffix): if suffix != file_suffix: n = len(suffix) file_name = file_name[:-n] + file_suffix self.file_entry.set(file_name) break else: file_name = file_name + file_suffix self.file_entry.set(file_name) # width and height are of plot, in pixels def getOutputHandler(self, width, height, fonts=None): if not fonts: fonts = [] else: fonts = list(fonts) for n in range(len(fonts)): if fonts[n] == 'Times': fonts[n] = 'Times-Roman' self.setOptionValues() if not self.file_name: showError('No file', 'No file specified', parent=self) return None if os.path.exists(self.file_name): if not showYesNo('File exists', 'File "%s" exists, overwrite?' % self.file_name, parent=self): return None if (self.paper_type == Output.other_paper_type): paper_size = self.other_size + [self.other_unit] else: paper_size = paper_sizes[self.paper_type] output_scaling = self.scaling / 100.0 font = 'Times-Roman' border_text = {} for decoration in self.border_decoration: if (decoration == 'Time & date'): location = 'se' text = time.ctime(time.time()) elif (decoration == 'File name'): location = 'sw' text = self.file_name else: continue # should not be here border_text[location] = (text, font, 12) if (self.title): location = 'n' border_text[location] = (self.title, font, 18) if font not in fonts: fonts.append(font) outputHandler = PrintHandler.getOutputHandler( self.file_name, width, height, output_scaling=output_scaling, paper_size=paper_size, paper_orientation=self.paper_orientation, output_style=self.output_style, output_format=self.output_format, border_text=border_text, fonts=fonts, do_outline_box=self.doOutlineBox) return outputHandler def getAspectRatio(self): self.setOptionValues() if self.paper_type == Output.other_paper_type: paper_size = self.other_size else: paper_size = paper_sizes[self.paper_type] r = paper_size[1] / paper_size[0] if self.paper_orientation == 'Landscape': r = 1.0 / r return r
class PrintFrame(Frame): def __init__(self, parent, getOption = None, setOption = None, haveTicks = False, doOutlineBox = True, *args, **kw): self.getOption = getOption self.setOption = setOption self.haveTicks = haveTicks self.doOutlineBox = doOutlineBox Frame.__init__(self, parent=parent, *args, **kw) self.file_select_popup = None self.getOptionValues() try: size_index = paper_types.index(self.paper_type) except: size_index = 0 try: other_unit_index = paper_units.index(self.other_unit) except: other_unit_index = 0 try: orientation_index = paper_orientations.index(self.paper_orientation) except: orientation_index = 0 try: style_index = style_choices.index(self.output_style) except: style_index = 0 try: format_index = format_choices.index(self.output_format) except: format_index = 0 if haveTicks: try: tick_location_index = tick_locations.index(self.tick_location) except: tick_location_index = 0 self.grid_columnconfigure(1, weight=1) row = 0 button = Button(self, text='File:', command=self.findFile, tipText='Select location to save print file') button.grid(row=row, column=0, sticky='e') self.file_entry = Entry(self, width=40, text=self.file_name, tipText='Location where file is saved on disk') self.file_entry.grid(row=row, column=1, sticky='ew') row += 1 label = Label(self, text='Title:') label.grid(row=row, column=0, sticky='e') self.title_entry = Entry(self, width=40, text=self.title, tipText='Title of the printout, displayed at top') self.title_entry.grid(row=row, column=1, sticky='ew') row += 1 label = Label(self, text='X axis label:') label.grid(row=row, column=0, sticky='e') self.x_axis_entry = Entry(self, width=40, text=self.x_axis_label, tipText='X axis label for the printout') self.x_axis_entry.grid(row=row, column=1, sticky='ew') row += 1 label = Label(self, text='Y axis label:') label.grid(row=row, column=0, sticky='e') self.y_axis_entry = Entry(self, width=40, text=self.y_axis_label, tipText='Y axis label for the printout') self.y_axis_entry.grid(row=row, column=1, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=2, sticky='ew') frame.grid_columnconfigure(4, weight=1) label = Label(frame, text='Paper size:') label.grid(row=0, column=0, sticky='e') entries = [] for t in paper_types: if t == Output.other_paper_type: entry = t else: (w, h, u) = paper_sizes[t] entry = t + ' (%2.1f %s x %2.1f %s)' % (w, u, h, u) entries.append(entry) self.size_menu = PulldownList(frame, callback=self.changedSize, texts=entries, index=size_index, tipText='The paper size for the printout') self.size_menu.grid(row=0, column=1, sticky='w') self.other_frame = Frame(frame) self.other_frame.grid_columnconfigure(0, weight=1) self.other_entry = FloatEntry(self.other_frame, text=self.other_size, isArray=True, tipText='The size of the Other paper in both dimensions; this requires two values, space or comma separated') self.other_entry.grid(row=0, column=0, sticky='ew') self.other_unit_menu= PulldownList(self.other_frame, texts=paper_units, index=other_unit_index, tipText='The unit for the Other paper size') self.other_unit_menu.grid(row=0, column=1, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) frame.grid_columnconfigure(5, weight=1) label = Label(frame, text='Orientation:') label.grid(row=0, column=0, sticky='e') self.orientation_menu = PulldownList(frame, texts=paper_orientations, index=orientation_index, tipText='Whether the paper should be set in Portrait or Landscape mode') self.orientation_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Style:') label.grid(row=0, column=2, sticky='e') self.style_menu = PulldownList(frame, texts=style_choices, index=style_index, tipText='Whether the printout should be in colour or black and white') self.style_menu.grid(row=0, column=3, sticky='w') label = Label(frame, text=' Format:') label.grid(row=0, column=4, sticky='e') self.format_menu = PulldownList(frame, callback=self.changedFormat, texts=format_choices, index=format_index, tipText='Whether to save as PS, EPS or PDF') self.format_menu.grid(row=0, column=5, sticky='w') if haveTicks: row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Tick Location:') label.grid(row=0, column=0, sticky='e') self.tick_menu = PulldownList(frame, texts=tick_locations, index=tick_location_index, tipText='Whether the tick marks appear on the inside or outside of the frame') self.tick_menu.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Tick Placement:') label.grid(row=0, column=2, sticky='e') if self.tick_placement is None: selected = None else: selected = [(x in self.tick_placement) for x in tick_placements] self.tick_buttons = CheckButtons(frame, entries=tick_placements, selected=selected, tipTexts=('Whether the tick marks appear on the top and/or bottom and/or left and/or right',)) self.tick_buttons.grid(row=0, column=3, sticky='w') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) frame.grid_columnconfigure(3, weight=1) label = Label(frame, text='Tick Font:') label.grid(row=0, column=0, sticky='e') self.tick_font_list = FontList(frame, mode='Print', selected=self.tick_font, extraTexts=[PrintTicks.no_tick_text], tipText='The font used for the tick mark labels') self.tick_font_list.grid(row=0, column=1, sticky='w') label = Label(frame, text='Tick Spacing:') label.grid(row=0, column=2, sticky='e') # TBD: put preferred choice in data model self.spacing_menu = PulldownList(frame, texts=spacing_choices, index=0, callback=self.changedSpacing, tipText='Whether the program should automatically calculate the major/minor tick spacings and how many decimal places are used for the ticks, or whether the these are specified manually') self.spacing_menu.grid(row=0, column=3, sticky='w') ff = self.spacing_frame = Frame(frame) ff.grid_columnconfigure(1, weight=1) ff.grid_columnconfigure(2, weight=1) label = Label(ff, text='Tick Spacing') label.grid(row=0, column=0, sticky='w') label = Label(ff, text='Major') label.grid(row=0, column=1, sticky='ew') label = Label(ff, text='Minor') label.grid(row=0, column=2, sticky='ew') label = Label(ff, text='Decimals') label.grid(row=0, column=3, sticky='ew') label = Label(ff, text='X:') label.grid(row=1, column=0, sticky='w') self.x_major_entry = FloatEntry(ff, tipText='The spacing in display units of the major tick marks in the X dimension') self.x_major_entry.grid(row=1, column=1, sticky='ew') self.x_minor_entry = FloatEntry(ff, tipText='The spacing in display units of the minor tick marks in the X dimension (not printed if left blank)') self.x_minor_entry.grid(row=1, column=2, sticky='ew') self.x_decimal_entry = IntEntry(ff, tipText='The number of decimal places for the tick numbers in the X dimension') self.x_decimal_entry.grid(row=1, column=3, sticky='ew') label = Label(ff, text='Y:') label.grid(row=2, column=0, sticky='w') self.y_major_entry = FloatEntry(ff, tipText='The spacing in display units of the major tick marks in the Y dimension') self.y_major_entry.grid(row=2, column=1, sticky='ew') self.y_minor_entry = FloatEntry(ff, tipText='The spacing in display units of the minor tick marks in the Y dimension (not printed if left blank)') self.y_minor_entry.grid(row=2, column=2, sticky='ew') self.y_decimal_entry = IntEntry(ff, tipText='The number of decimal places for the tick numbers in the Y dimension') self.y_decimal_entry.grid(row=2, column=3, sticky='ew') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(1, weight=1) label = Label(frame, text='Tick Length:') label.grid(row=0, column=0, sticky='e') # TBD: put preferred choice in data model self.tick_length_menu = PulldownList(frame, texts=tick_length_choices, index=0, callback=self.changedLength, tipText='Whether the program should automatically calculate the major/minor tick lengths, or whether the these are specified manually') self.tick_length_menu.grid(row=0, column=1, sticky='w') ff = self.length_frame = Frame(frame) ff.grid_columnconfigure(1, weight=1) label = Label(ff, text=' Major length:') label.grid(row=0, column=0, sticky='w') self.length_major_entry = FloatEntry(ff, tipText='The length in points of the major tick marks') self.length_major_entry.grid(row=0, column=1, sticky='w') label = Label(ff, text='Minor length:') label.grid(row=0, column=2, sticky='w') self.length_minor_entry = FloatEntry(ff, tipText='The length in points of the minor tick marks') self.length_minor_entry.grid(row=0, column=3, sticky='w') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='ew') frame.grid_columnconfigure(3, weight=1) frame.grid_columnconfigure(4, weight=1) label = Label(frame, text='Scaling:') label.grid(row=0, column=0, sticky='e') # TBD: put preferred choice in data model self.scaling_menu = PulldownList(frame, texts=scaling_choices, index=0, callback=self.changedScaling, tipText='Whether the plot should be scaled as a percentage of the maximum size that would fit on the paper, or instead should be specified by the number of cms or inches per unit') self.scaling_menu.grid(row=0, column=1, sticky='ew') self.scaling_scale = Scale(frame, orient=Tkinter.HORIZONTAL, value=self.scaling, tipText='The percentage of the maximum size that would fit on the paper that the plot is scaled by') self.scaling_scale.grid(row=0, column=2, columnspan=3, sticky='ew') self.x_scaling_label = Label(frame, text='X:') self.x_scaling_entry = FloatEntry(frame, tipText='The scaling that should be used in the X dimension as cms or inches per unit') self.y_scaling_label = Label(frame, text='Y:') self.y_scaling_entry = FloatEntry(frame, tipText='The scaling that should be used in the Y dimension as cms or inches per unit') row += 1 frame = Frame(self) frame.grid(row=row, column=0, columnspan=4, sticky='w') frame.grid_columnconfigure(2, weight=1) label = Label(frame, text='Include:') label.grid(row=0, column=0, sticky='e') tipTexts = ('Whether the time and date should be included in the printout', 'Whether the file name should be included in the printout') if self.border_decoration is None: selected = None else: selected = [(x in self.border_decoration) for x in border_decorations] self.border_buttons = CheckButtons(frame, entries=border_decorations, selected=selected, tipTexts=tipTexts) self.border_buttons.grid(row=0, column=1, sticky='w') label = Label(frame, text=' Using Font:') label.grid(row=0, column=2, sticky='e') self.border_font_list = FontList(frame, mode='Print', selected=self.border_font, tipText='The font used for the border texts') self.border_font_list.grid(row=0, column=3, sticky='w') row += 1 label = Label(self, text='Line width:') label.grid(row=row, column=0, sticky='w') self.linewidth_entry = FloatEntry(self, width=10, text=self.linewidth, tipText='Line width for drawing') self.linewidth_entry.grid(row=row, column=1, sticky='w') def destroy(self): self.setOptionValues() if self.file_select_popup: self.file_select_popup.destroy() Frame.destroy(self) def getOptionValues(self): getOption = self.getOption if getOption: file_name = getOption('FileName', defaultValue='') title = getOption('Title', defaultValue='') x_axis_label = getOption('XAxisLabel', defaultValue='') y_axis_label = getOption('YAxisLabel', defaultValue='') paper_type = getOption('PaperSize', defaultValue=paper_types[0]) paper_type = paper_type_dict.get(paper_type, paper_types[0]) other_height = getOption('OtherHeight', defaultValue=10) other_width = getOption('OtherWidth', defaultValue=10) other_size = [other_height, other_width] other_unit = getOption('OtherUnit', defaultValue=paper_units[0]) paper_orientation = getOption('Orientation', defaultValue=paper_orientations[0]) in_color = getOption('InColor', defaultValue=True) if in_color: output_style = style_choices[0] else: output_style = style_choices[1] format_option = getOption('OutputFormat', defaultValue=format_options[0]) output_format = format_choices[format_options.index(format_option)] if self.haveTicks: tick_outside = getOption('TickOutside', defaultValue=tick_locations[0]) if tick_outside: tick_location = tick_locations.index(PrintTicks.Outside) else: tick_location = tick_locations.index(PrintTicks.Inside) tick_placement = getTickPlacement1(getOption('TickPlacement', defaultValue='nsew')) dateTime = getOption('ShowsDateTime', defaultValue=True) fileName = getOption('ShowsFileName', defaultValue=True) border_font = getOption('BorderFont', defaultValue='Helvetica 10') border_decoration = [] if dateTime: border_decoration.append(border_decorations[0]) if fileName: border_decoration.append(border_decorations[1]) if self.haveTicks: spacing_choice = getOption('SpacingChoice', defaultValue=spacing_choices[0]) x_major = getOption('XMajor', defaultValue=1.0) x_minor = getOption('XMinor', defaultValue=1.0) x_decimal = getOption('XDecimal', defaultValue=3) y_major = getOption('YMajor', defaultValue=1.0) y_minor = getOption('YMinor', defaultValue=1.0) y_decimal = getOption('YDecimal', defaultValue=3) tick_length_choice = getOption('TickLengthChoice', defaultValue=tick_length_choices[0]) tick_major = getOption('TickMajor', defaultValue=10) tick_minor = getOption('TickMinor', defaultValue=5) scaling_choice = getOption('ScalingChoice', defaultValue=scaling_choices[0]) scaling = getOption('Scaling', defaultValue=0.7) scaling = int(round(100.0 * scaling)) x_scaling = getOption('XScaling', defaultValue=1.0) y_scaling = getOption('YScaling', defaultValue=1.0) if self.haveTicks: tick_font = getOption('TickFont', defaultValue='Helvetica 10') linewidth = getOption('LineWidth', defaultValue=Output.default_linewidth) else: file_name = '' title = '' x_axis_label = '' y_axis_label = '' paper_type = paper_types[0] other_unit = paper_units[0] other_size = '' paper_orientation = paper_orientations[0] output_style = style_choices[0] output_format = format_choices[0] if self.haveTicks: tick_location = tick_locations[0] tick_placement = tick_placements border_decoration = border_decorations border_font = 'Helvetica 10' if self.haveTicks: spacing_choice = spacing_choices[0] x_major = 1.0 x_minor = 1.0 x_decimal = 3 y_major = 1.0 y_minor = 1.0 y_decimal = 3 tick_length_choice = tick_length_choices[0] tick_major = 10 tick_minor = 5 scaling_choice = scaling_choices[0] scaling = 70 x_scaling = 1.0 y_scaling = 1.0 if self.haveTicks: tick_font = 'Helvetica 10' linewidth = Output.default_linewidth if not self.haveTicks: tick_location = None tick_placement = None spacing_choice = spacing_choices[0] x_major = 1.0 x_minor = 1.0 x_decimal = 3 y_major = 1.0 y_minor = 1.0 y_decimal = 3 tick_font = 'Helvetica 10' tick_length_choice = tick_length_choices[0] tick_major = 10 tick_minor = 5 self.file_name = file_name self.title = title self.x_axis_label = x_axis_label self.y_axis_label = y_axis_label self.paper_type = paper_type self.other_unit = other_unit self.other_size = other_size self.paper_orientation = paper_orientation self.output_style = output_style self.output_format = output_format self.tick_location = tick_location self.tick_placement = tick_placement self.border_decoration = border_decoration self.border_font = border_font self.spacing_choice = spacing_choice self.x_major = x_major self.x_minor = x_minor self.x_decimal = x_decimal self.y_major = y_major self.y_minor = y_minor self.y_decimal = y_decimal self.scaling_choice = scaling_choices[0] self.scaling = scaling self.x_scaling = x_scaling self.y_scaling = y_scaling self.tick_font = tick_font self.linewidth = linewidth self.tick_length_choice = tick_length_choice self.tick_major = tick_major self.tick_minor = tick_minor def setOptionValues(self): if not hasattr(self, 'file_entry'): # it looks like on destroy can have function called but file_entry deleted already return self.file_name = file_name = self.file_entry.get() self.title = title = self.title_entry.get() self.x_axis_label = x_axis_label = self.x_axis_entry.get() self.y_axis_label = y_axis_label = self.y_axis_entry.get() n = self.size_menu.getSelectedIndex() self.paper_type = paper_type = paper_types[n] if paper_type == Output.other_paper_type: other_size = self.other_entry.get() other_unit = self.other_unit_menu.getText() else: other_size = None other_unit = None self.other_size = other_size self.other_unit = other_unit self.paper_orientation = paper_orientation = self.orientation_menu.getText() self.output_style = output_style = self.style_menu.getText() self.output_format = output_format = self.format_menu.getText() if self.haveTicks: tick_location = self.tick_menu.getText() tick_placement = self.tick_buttons.getSelected() else: tick_location = tick_placement = None self.tick_location = tick_location self.tick_placement = tick_placement self.border_decoration = border_decoration = self.border_buttons.getSelected() self.border_font = border_font = self.border_font_list.getText() if self.haveTicks: self.spacing_choice = spacing_choice = self.spacing_menu.getText() if spacing_choice != spacing_choices[0]: self.x_major = self.x_major_entry.get() self.x_minor = self.x_minor_entry.get() self.x_decimal = self.x_decimal_entry.get() self.y_major = self.y_major_entry.get() self.y_minor = self.y_minor_entry.get() self.y_decimal = self.y_decimal_entry.get() self.tick_length_choice = tick_length_choice = self.tick_length_menu.getText() if tick_length_choice != tick_length_choices[0]: self.tick_major = self.length_major_entry.get() self.tick_minor = self.length_minor_entry.get() self.scaling_choice = scaling_choice = self.scaling_menu.getText() if self.scaling_choice == scaling_choices[0]: scaling = self.scaling_scale.get() self.scaling = int(round(scaling)) else: self.x_scaling = self.x_scaling_entry.get() self.y_scaling = self.y_scaling_entry.get() if self.haveTicks: self.tick_font = self.tick_font_list.getText() self.linewidth = self.linewidth_entry.get() setOption = self.setOption if setOption: setOption('FileName', value=file_name) setOption('Title', value=title) setOption('XAxisLabel', value=x_axis_label) setOption('YAxisLabel', value=y_axis_label) if paper_type == Output.other_paper_type: setOption('OtherHeight', value=other_size[0]) setOption('OtherWidth', value=other_size[1]) setOption('OtherUnit', value=other_unit) else: paper_type = paper_type_inverse_dict[paper_type] setOption('PaperSize', value=paper_type) setOption('Orientation', value=paper_orientation) in_color = (output_style == style_choices[0]) setOption('InColor', value=in_color) output_format = format_options[format_choices.index(output_format)] setOption('OutputFormat', value=output_format) if self.haveTicks: tick_outside = (tick_location == PrintTicks.Outside) setOption('TickOutside', value=tick_outside) tick_placement = getTickPlacement2(tick_placement) setOption('TickPlacement', value=tick_placement) dateTime = (border_decorations[0] in border_decoration) fileName = (border_decorations[1] in border_decoration) setOption('ShowsDateTime', value=dateTime) setOption('ShowsFileName', value=fileName) setOption('BorderFont', value=border_font) if self.haveTicks: setOption('SpacingChoice', value=spacing_choice) if spacing_choice != spacing_choices[0]: setOption('XMajor', self.x_major) setOption('XMinor', self.x_minor) setOption('XDecimal', self.x_decimal) setOption('YMajor', self.y_major) setOption('YMinor', self.y_minor) setOption('YDecimal', self.y_decimal) setOption('TickLengthChoice', value=tick_length_choice) if tick_length_choice != tick_length_choices[0]: setOption('TickMajor', self.tick_major) setOption('TickMinor', self.tick_minor) setOption('ScalingChoice', value=scaling_choice) if scaling_choice == scaling_choices[0]: setOption('Scaling', value=0.01*self.scaling) else: setOption('XScaling', value=self.x_scaling) setOption('YScaling', value=self.y_scaling) if self.haveTicks: setOption('TickFont', self.tick_font) setOption('LineWidth', self.linewidth) def findFile(self): if self.file_select_popup: self.file_select_popup.open() else: file_types = [ FileType('All', ['*']), FileType('PostScript', ['*.ps', '*.eps']), FileType('PDF', ['*.pdf', '*.ai']) ] self.file_select_popup = FileSelectPopup(self, file_types=file_types) file = self.file_select_popup.getFile() if file: self.file_entry.set(file) def changedSize(self, entry): if entry == Output.other_paper_type: self.other_frame.grid(row=0, column=2, columnspan=2, sticky='w') else: self.other_frame.grid_forget() def changedFormat(self, entry): file_suffix = file_suffixes.get(entry) if not file_suffix: return file_name = self.file_entry.get() if not file_name: return for suffix in format_suffixes: if file_name.endswith(suffix): if suffix != file_suffix: n = len(suffix) file_name = file_name[:-n] + file_suffix self.file_entry.set(file_name) break else: file_name = file_name + file_suffix self.file_entry.set(file_name) def changedScaling(self, choice): if choice == scaling_choices[0]: self.scaling_scale.grid(row=0, column=2, columnspan=3, sticky='ew') self.x_scaling_label.grid_forget() self.x_scaling_entry.grid_forget() self.y_scaling_label.grid_forget() self.y_scaling_entry.grid_forget() else: self.scaling_scale.grid_forget() self.x_scaling_label.grid(row=0, column=2, sticky='w') self.x_scaling_entry.grid(row=0, column=3, columnspan=2, sticky='ew') self.y_scaling_label.grid(row=1, column=2, sticky='w') self.y_scaling_entry.grid(row=1, column=3, columnspan=2, sticky='ew') self.setOptionValues() def changedSpacing(self, choice): if choice == spacing_choices[0]: self.spacing_frame.grid_forget() else: self.spacing_frame.grid(row=1, column=1, columnspan=3, sticky='ew') self.setOptionValues() def changedLength(self, choice): if choice == tick_length_choices[0]: self.length_frame.grid_forget() else: self.length_frame.grid(row=1, column=0, columnspan=4, sticky='ew') self.setOptionValues() # width and height are of plot, in pixels def getOutputHandler(self, pixel_width, pixel_height, unit_width=1.0, unit_height=1.0, fonts=None): if not fonts: fonts = [] else: fonts = list(fonts) for n in range(len(fonts)): if fonts[n] == 'Times': fonts[n] = 'Times-Roman' self.setOptionValues() if not self.file_name: showError('No file', 'No file specified', parent=self) return None x_scaling = y_scaling = 1.0 if self.scaling_choice != scaling_choices[0]: try: x_scaling = float(self.x_scaling) except: showError('Bad X Scaling', 'Specified X Scaling must be floating point', parent=self) return None try: y_scaling = float(self.y_scaling) except: showError('Bad Y Scaling', 'Specified Y Scaling must be floating point', parent=self) return None if os.path.exists(self.file_name): if not showYesNo('File exists', 'File "%s" exists, overwrite?' % self.file_name, parent=self): return None if self.paper_type == Output.other_paper_type: paper_size = self.other_size + [ self.other_unit ] else: paper_size = paper_sizes[self.paper_type] output_scaling = self.scaling / 100.0 border_font = self.border_font (font, size) = border_font.split() size = int(size) border_text = {} for decoration in self.border_decoration: if decoration == 'Time and Date': location = 'se' text = time.ctime(time.time()) elif decoration == 'File Name': location = 'sw' text = self.file_name else: continue # should not be here border_text[location] = (text, font, size) if self.title: location = 'n' border_text[location] = (self.title, font, size+6) if font not in fonts: fonts.append(font) if self.haveTicks and self.tick_location == PrintTicks.Outside: axis_label_offset = 2 else: axis_label_offset = 0 outputHandler = PrintHandler.getOutputHandler(self.file_name, pixel_width, pixel_height, unit_width, unit_height, scaling_choice=self.scaling_choice, output_scaling=output_scaling, w_scaling=x_scaling, h_scaling=y_scaling, paper_size=paper_size, paper_orientation=self.paper_orientation, output_style=self.output_style, output_format=self.output_format, border_text=border_text, x_axis_label=self.x_axis_label, y_axis_label=self.y_axis_label, axis_label_font=font, axis_label_size=size, axis_label_offset=axis_label_offset, fonts=fonts, linewidth=self.linewidth, do_outline_box=self.doOutlineBox) return outputHandler def getAspectRatio(self): self.setOptionValues() if self.paper_type == Output.other_paper_type: paper_size = self.other_size else: paper_size = paper_sizes[self.paper_type] r = paper_size[1] / paper_size[0] if self.paper_orientation == 'Landscape': r = 1.0 / r return r