Beispiel #1
0
  def draw(self):
  
    self.drawContours()
  
    ScrolledGraph.draw(self)
  
    plotRegion = self.getPlotRegion()

    minX = self.minT1
    maxX = self.maxT1
    minY = self.minT2
    maxY = self.maxT2

    dataRegion = [minX, minY, maxX, maxY]
    
    deltaXplot = plotRegion[2] - plotRegion[0]
    deltaYplot = plotRegion[3] - plotRegion[1] 
    deltaXdata = dataRegion[2] - dataRegion[0]
    deltaYdata = dataRegion[3] - dataRegion[1]
  
    ppvX = deltaXplot/float(deltaXdata)
    ppvY = deltaYplot/float(deltaYdata)
    createText = self.canvas.create_text

    for label, x, y in self.outlierLabels:
      x0 = (x - dataRegion[0])*ppvX
      y0 = (y - dataRegion[1])*ppvY
      x0 += plotRegion[0]
      y0 += plotRegion[1]
      
      item = createText(x0+8,y0, text=label,
                        fill='#000000',anchor='w')
      self.contourItems.add(item)
Beispiel #2
0
    def body(self, guiParent):

        row = 0
        self.graph = ScrolledGraph(guiParent)
        self.graph.grid(row=row, column=0, sticky='NSEW')

        row += 1
        texts = ['Draw graph', 'Goodbye']
        commands = [self.draw, self.destroy]
        buttons = ButtonList(guiParent, texts=texts, commands=commands)
        buttons.grid(row=row, column=0, sticky='NSEW')
Beispiel #3
0
class DangleGraphPopup(BasePopup):
  
  def __init__(self, parent):

    BasePopup.__init__(self, parent=parent, title=" Dangle Prediction Graph",
                       transient=False, borderwidth=6)

    parent.protocol("WM_DELETE_WINDOW", self.close)

    self.geometry('700x700+50+50')

  def body(self, guiFrame):
 
    guiFrame.expandGrid(0,0)
    guiFrame.expandGrid(1,0)
 
    self.anglesGraph = ScrolledGraph(guiFrame, xLabel='Residue',yLabel='Angle',
                                     relief='flat', symbolSize=1, grid=(0,0),
                                     zoom=1.0,width=500,height=200,
                                     dataColors=['#D00000','#0000D0'],
                                     dataNames=['Phi','Psi'])
    self.anglesGraph.draw()

    self.islandsGraph = ScrolledGraph(guiFrame, xLabel='Residue',yLabel='No. Islands',
                                     relief='flat', graphType='histogram',
                                     zoom=1.0,width=500,height=200 ,grid=(1,0),
                                     dataColors=['#8080FF','#FFFF00','#E00000'],
                                     dataNames=['1','2-3','4+'],)
    self.islandsGraph.draw()

  def update(self, phiData, psiData, islandData):
    
    self.anglesGraph.update(dataSets=[phiData,psiData])   
    self.islandsGraph.update(dataSets=islandData)
Beispiel #4
0
  def body(self, guiFrame):

    ProgressBar.body(self, guiFrame)
    guiFrame.expandGrid(2,3)
    
    self.stepLabel = Label(guiFrame, text='Best step:  ', grid=(0,3))

    
    frame = LabelFrame(guiFrame, text='Best mappings', grid=(1,0), gridSpan=(1,4))

    row = 0
    for i in range(self.ensembleSize):
      label = Label(frame, text='', pady=0, font='Courier 10',
                    borderwidth=0, grid=(row,0), sticky='ew')
      self.labels.append(label)
      row +=1

    guiFrame.grid_rowconfigure(2, weight=1)
    self.graph = ScrolledGraph(guiFrame, width=450, height=300,
                               graphType='scatter', title='Typing Scores',
                               xLabel='Spin System', yLabel='Score',
                               grid=(2,0), gridSpan=(1,4))


    self.buttonList = ButtonList(guiFrame, texts=['Close',], commands=[self.done],
                                 grid=(3,0), gridSpan=(1,4))
    self.buttonList.buttons[0].disable() 
Beispiel #5
0
 def __init__(self, parent, name, *args, **kw):
  
   kw['title'] = '%s vs Residue Sequence' % name
   kw['xLabel'] = 'Residue number'
   kw['yLabel'] = '%s' % name
   kw['width'] = 500
   kw['height'] = 150
   kw['xGrid'] = True
   kw['yGrid'] = False
   kw['graphType'] = 'histogram'
   
   self.minRes = 0
   self.maxRes = 100
   self.minVal = -1.0
   self.maxVal = 1.0
     
   ScrolledGraph.__init__(self, parent, **kw)
Beispiel #6
0
  def body(self, guiFrame):
 
    guiFrame.expandGrid(0,0)
    guiFrame.expandGrid(1,0)
 
    self.anglesGraph = ScrolledGraph(guiFrame, xLabel='Residue',yLabel='Angle',
                                     relief='flat', symbolSize=1, grid=(0,0),
                                     zoom=1.0,width=500,height=200,
                                     dataColors=['#D00000','#0000D0'],
                                     dataNames=['Phi','Psi'])
    self.anglesGraph.draw()

    self.islandsGraph = ScrolledGraph(guiFrame, xLabel='Residue',yLabel='No. Islands',
                                     relief='flat', graphType='histogram',
                                     zoom=1.0,width=500,height=200 ,grid=(1,0),
                                     dataColors=['#8080FF','#FFFF00','#E00000'],
                                     dataNames=['1','2-3','4+'],)
    self.islandsGraph.draw()
Beispiel #7
0
 def getMinMaxValues(self, dataSets):
 
   minX,maxX,minY,maxY,maxN,minDx,minDy = ScrolledGraph.getMinMaxValues(self, dataSets)
   
   minX = self.minT1
   maxX = self.maxT1
   minY = self.minT2
   maxY = self.maxT2
   
   return minX,maxX,minY,maxY,maxN,minDx,minDy
Beispiel #8
0
 def getMinMaxValues(self, dataSets):
 
   minX,maxX,minY,maxY,maxN,minDx,minDy = ScrolledGraph.getMinMaxValues(self, dataSets)
   
   minX = self.minRes
   maxX = self.maxRes
   #minY = self.minVal
   #maxY = self.maxVal
   
   return minX,maxX,minY,maxY,maxN,minDx,minDy
Beispiel #9
0
class MyPopup(BasePopup):
    def __init__(self, parent, peakList, *args, **kw):

        self.peakList = peakList
        self.colours = ['red', 'green']
        self.dataSets = []

        BasePopup.__init__(self, parent=parent, title='Test Popup', **kw)

    def body(self, guiParent):

        row = 0
        self.graph = ScrolledGraph(guiParent)
        self.graph.grid(row=row, column=0, sticky='NSEW')

        row += 1
        texts = ['Draw graph', 'Goodbye']
        commands = [self.draw, self.destroy]
        buttons = ButtonList(guiParent, texts=texts, commands=commands)
        buttons.grid(row=row, column=0, sticky='NSEW')

    def draw(self):

        self.dataSets = self.getData()
        self.graph.update(self.dataSets, self.colours)

    def getData(self):

        peakData = [(getPeakVolume(peak) or 0.0, peak)
                    for peak in self.peakList.peaks]
        peakData.sort()

        heights = []
        volumes = []
        i = 0
        for volume, peak in peakData:
            heights.append([i, getPeakHeight(peak) or 0.0])
            volumes.append([i, volume])
            i += 1

        return [heights, volumes]
Beispiel #10
0
 def __init__(self, parent, contourColorA='#FFC0B0', contourColorB='#B0C0FF', *args, **kw):
  
   kw['title'] =  u'%s vs %s Relaxation Analysis' % (T1, T2)
   kw['xLabel'] = u'%s (ms)' % T1
   kw['yLabel'] = u'%s (ms)' % T2
   kw['width'] = 500
   kw['height'] = 500
   kw['xGrid'] = False
   kw['yGrid'] = False
   kw['graphType'] = 'scatter'
   
   self.minT1 = 0.0
   self.maxT1 = 1000.0
   self.minT2 = 0.0
   self.maxT2 = 1000.0
   self.contourColorA = contourColorA
   self.contourColorB = contourColorB
   self.orderParamLines = []
   self.rotCorrTimeLines = []
   self.contourItems = set([])
   self.outlierLabels = []
     
   ScrolledGraph.__init__(self, parent, **kw)
Beispiel #11
0
  def update(self, t1List, t2List, cSize, cDist, sf, lenNh, ict,
             csaN, paramsS2, paramsRct, graphBounds):
    
    self.calcContourLines(sf, lenNh, ict, csaN, paramsS2, paramsRct)
    
    self.minT1, self.maxT1, self.minT2, self.maxT2 = graphBounds
    
    dataSets = []
    dataColors = []
    symbols = []
    outliers = []
    nColors = len(CLUSTER_COLORS)
    nSymbols = len(CLUSTER_SYMBOLS)
    cDist2 = cDist**2
    
    if t1List and t2List:
      t1t2Points = []
      resonancesT1 = {}

      t1Unit = MS_UNIT_MULTIPLIERS[t1List.unit]
      t2Unit = MS_UNIT_MULTIPLIERS[t2List.unit]
      
      for t1 in t1List.measurements:
        resonancesT1[t1.resonance] = t1
         
      for t2 in t2List.measurements:
        resonance = t2.resonance
        t1 = resonancesT1.get(resonance)
        
        if t1:
          xyr = (t1Unit*t1.value,t2Unit*t2.value, resonance)
          t1t2Points.append(xyr)
      
      # Do clustering
      clusters = [[pt,] for pt in t1t2Points]
      
      nMerge = 1
      while nMerge:
        nMerge = 0
        
        for i, clusterA in enumerate(clusters[:-1]):
          for j in range(i+1,len(clusters)):
            clusterB = clusters[j]
            
            for x1, y1, r1 in clusterA:
              for x2, y2, r2 in clusterB:
                dx = x2-x1
                dy = y2-y1
                
                if (dx*dx) + (dy*dy) <= cDist2:
                  clusterA += clusterB
                  clusters[j] = []
                  nMerge += 1
                  break
              
              else:
                continue
              break      
        
        clusters = [c for c in clusters if c]
      
      self.outlierLabels = []
      for c in clusters:
        if len(c) < cSize:
          for x,y,r in c:
            outliers.append((x,y))
            label =  makeResonanceGuiName(r)
            self.outlierLabels.append((label,x,y))
        else:
          data = [xyr[:2] for xyr in c]
          dataSets.append(data)
               
      dataSets.append(outliers)
      
      for i, dataSet in enumerate(dataSets):
        dataSet.sort()
        dataColors.append(CLUSTER_COLORS[i % nColors])
        symbols.append(CLUSTER_SYMBOLS[i % nSymbols])
    
    if outliers:
      symbols[-1] = 'star'
      
    #else:
    #  dataSets.append([(0,0),(1000,1000)])

    
    ScrolledGraph.update(self, dataSets, dataColors, symbols=symbols)
Beispiel #12
0
  def body(self, guiFrame):

    self.geometry('700x840')
    
    guiFrame.expandGrid(1,0)
    
    # Top frame
    
    frame = Frame(guiFrame, grid=(0,0))
    frame.expandGrid(None,8)
    
    label = Label(frame, text=u' %s List:' % T1, grid=(0,0))
    self.t1Pulldown = PulldownList(frame, callback=self.selectT1List, grid=(0,1))
    
    label = Label(frame, text=u'  %s List:' % T2, grid=(0,2))
    self.t2Pulldown = PulldownList(frame, callback=self.selectT2List, grid=(0,3))
    
    label = Label(frame, text='  NOE List:', grid=(0,4))
    self.noePulldown = PulldownList(frame, callback=self.selectNoeList, grid=(0,5))
 
    label = Label(frame, text='  Spectrometer Freq (MHz):', grid=(0,6))
    self.sfEntry = FloatEntry(frame, grid=(0,7), text=600.00, width=6)

    UtilityButtonList(frame, grid=(0,9), sticky='e')
    
    # Tabs
    
    options = [u'%s vs %s Scatter' % (T1, T2),
               u'%s,%s & NOE Graphs' % (T1, T2) ,
               u'%s/%s Graph' % (T1, T2),
               u'%s Estimate Graph' % S2,
               'Options']
    self.tabbedFrame = TabbedFrame(guiFrame, options=options,
                                   callback=self.toggleTab, grid=(1,0))
    frameA, frameD, frameC, frameE, frameB = self.tabbedFrame.frames

    # T1 vs T2 Graph

    frameA.expandGrid(0,0)
 
    self.t1t2Graph = T1VersesT2Plot(frameA, grid=(0,0))

    # T1 & T2 Graph

    frameD.expandGrid(0,0)
    frameD.expandGrid(1,0)
    frameD.expandGrid(2,0)
 
    self.t1Graph = MeasurementPlot(frameD, T1, grid=(0,0))
    self.t2Graph = MeasurementPlot(frameD, T2, grid=(1,0))
    self.noeGraph = NoePlot(frameD, 'NOE', grid=(2,0))

    # T1 over T2 Graph

    frameC.expandGrid(0,0)
 
    self.t1t2GraphB = T1OverT2Plot(frameC, grid=(0,0))
    
    # Order params graph
    
    frameE.expandGrid(0,0)
    frameE.expandGrid(1,0)
    frameE.expandGrid(2,0)
    
    self.s2Graph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % S2,
                                 xLabel='Residue number', yLabel=S2,
                                 width=500, height=150, graphType='histogram', 
                                 xGrid=True, yGrid=False, grid=(0,0),
                                 dataColors=['#0000A0','#808000'],
                                 dataNames=['Isotropic',])

    self.teGraph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % Te,
                                 xLabel='Residue number', yLabel=u'%s (ps)' % Te,
                                 width=500, height=150, graphType='histogram',
                                 xGrid=True, yGrid=False, grid=(1,0),
                                 dataColors=['#008000',])
                                 
    self.rexGraph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % 'Rex',
                                  xLabel='Residue number', yLabel='Rex',
                                  width=500, height=150, graphType='histogram',
                                  xGrid=True, yGrid=False, grid=(2,0),
                                  dataColors=['#900000',])
    
    # Options
    
    frameB.expandGrid(4,2)
    
    frame = LabelFrame(frameB, text='Physical Params', grid=(0,0))
    frame.expandGrid(None,3)
   
    label = Label(frame, text=u'N-H bond length (\u00C5)', grid=(0,0))
    self.lenNhEntry = FloatEntry(frame, text=1.015, grid=(0,1), width=8)

    label = Label(frame, text=u'Internal correlation\ntime, \u03C4e (ps)', grid=(1,0))
    self.ictEntry = FloatEntry(frame, text=50.0, grid=(1,1), width=8)
    
    label = Label(frame, text=u'15N Chemical Shift\nAnisotopy,\u0394N (ppm)',
                  grid=(2,0))
    self.csaNEntry = FloatEntry(frame, text=-160.0, grid=(2,1), width=8)
    
    frame = LabelFrame(frameB, text=u'%s vs %s Scatter' % (T1, T2), grid=(1,0))
    
    label = Label(frame, text='Max cluster difference (ms):', grid=(0,0))
    self.clusterDictEntry = FloatEntry(frame, text=20.0, grid=(0,1), width=8)    

    label = Label(frame, text='Min cluster size:', grid=(1,0))
    self.clusterSizeEntry = FloatEntry(frame, text=5, grid=(1,1), width=8)    

    label = Label(frame, text=u'Min graph %s (ms):' % T1, grid=(2,0))
    self.minT1Entry = FloatEntry(frame, text=300.0, grid=(2,1), width=8)    

    label = Label(frame, text=u'Max graph %s (ms):' % T1, grid=(3,0))
    self.maxT1Entry = FloatEntry(frame, text=1000.0, grid=(3,1), width=8)    

    label = Label(frame, text=u'Min graph %s (ms):' % T2, grid=(4,0))
    self.minT2Entry = FloatEntry(frame, text=0.0, grid=(4,1), width=8)    

    label = Label(frame, text=u'Max graph %s (ms):' % T2, grid=(5,0))
    self.maxT2Entry = FloatEntry(frame, text=600.0, grid=(5,1), width=8)    
    
    frame = LabelFrame(frameB, text=u'%s Contours' % S2, grid=(0,1))
    frame.expandGrid(4,3)

    label = Label(frame, text='(Order Parameter Lines)',
                  grid=(0,0), gridSpan=(1,2))

    label = Label(frame, text='Min value:', grid=(1,0))
    self.minS2Entry = FloatEntry(frame, text=0.3, grid=(1,1), width=8)
    
    label = Label(frame, text='Max value:', grid=(2,0))
    self.maxS2Entry = FloatEntry(frame, text=1.0, grid=(2,1), width=8)
    
    label = Label(frame, text='Step:', grid=(3,0))
    self.stepS2Entry = FloatEntry(frame, text=0.1, grid=(3,1), width=8)

    frame = LabelFrame(frameB, text=u'\u03C4m Contours', grid=(1,1))
    frame.expandGrid(4,3)

    label = Label(frame, text='(Rotational Correlation Time Lines)',
                  grid=(0,0), gridSpan=(1,2))
                  
    label = Label(frame, text='Min value (ns):', grid=(1,0))
    self.minRctEntry = FloatEntry(frame, text=5.0, grid=(1,1), width=8)
    
    label = Label(frame, text='Max value (ns):', grid=(2,0))
    self.maxRctEntry = FloatEntry(frame, text=14.0, grid=(2,1), width=8)
    
    label = Label(frame, text='Step (ns):', grid=(3,0))
    self.stepRctEntry = FloatEntry(frame, text=1.0, grid=(3,1), width=8)

    # Bottom frame
 
    texts = [u'Show %s Table' % T1,u'Show %s Table' % T2, u'Estimate %s' % S2]
    commands = [self.showT1List, self.showT2List, self.mc]
    buttonList = ButtonList(guiFrame, grid=(2,0), texts=texts, commands=commands)

    # Update

    self.updateRelaxationLists()

    self.drawAfter()

    self.administerNotifiers(self.registerNotify)
Beispiel #13
0
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)  
Beispiel #14
0
  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 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()
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 BrowseReferenceShiftsPopup(BasePopup):
  """
  **Graphs and Charts of Database Chemical Shift Data**
  
  This popup window presents the user with the distributions of known chemical
  shift values, for various kinds of atom, as they appear in the BioMagResBank
  or re-referenced RefDB databases. This information is useful when attempting
  to determine the type of a residue from its NMR spectra, for example when
  performing protein sequence assignment.

  The popup is divided into two tabs for two different kinds of graphical
  display. The first "1D graphs" tab shows the distributions of chemical shift
  value for either hydrogens or other "heavy" atoms within a given kind of
  residue. The buttons that carry atom names above the main graph can be toggled
  two switch the display for different kinds of atom on or off.

  The second "Amino Acid CA CB" tab is a special display to assist in the 
  assignment of protein sequences when using triple-resonance experiments
  like HNCA/CB. Data for all of the common amino acids is displayed, but
  only for the alpha and beta carbons.

  **Caveats & Tips**

  Two dimensional correlations, e.g. between a 1H resonance and a covalently
  bound 13C will be added to Analysis in the future.

  DNA and RNA chemical shift distributions is not present in the RefDB data, but
  are present in the BMRB data; to view the BMRB data change the pulldown menu
  at the top-right.

  Some of the atom types have a second, minor chemical shift distribution, far
  from the main peak, that is erroneous (this data is still present in the
  source databases). An example of this is for the NE atom of the amino acid
  arginine at around 115 ppm, which in this instance is probably caused by peaks
  being assigned in HSQC spectra in the normal backbone amide ppm range when the
  NE peak is really an aliased harmonic and should be a spectrum width away,
  nearer 85 ppm.

  Distributions that are notably jagged, due to lack of data for a given atom
  type should naturally not be relied upon to any great degree.

  """

  def __init__(self, parent, *args, **kw):

    self.guiParent = parent
    self.sourceName = 'RefDB'
    self.chemAtomNmrRefs = {}
    
    BasePopup.__init__(self, parent=parent, title="Resonance : Reference Chemical Shifts", **kw)

  def body(self, guiFrame):
    
    self.geometry("775x500")
    guiFrame.expandGrid(0,0)
    
    options = ['1D Graphs','Amino Acid CA CB']
    tipTexts = ['Simple graphs of how chemical shift values are distributed for a given atom type',
                'Density plots of alpha a & beta carbon shift distributions for common amnio acids']
    tabbedFrame = TabbedFrame(guiFrame, options=options, grid=(0,0), tipTexts=tipTexts)
    frameA, frameB = tabbedFrame.frames
    
    # # # # # # #  1D GRAPHS  # # # # # # # 
    
 
    row = 0
     
    MolType = self.project.metaclass.metaObjFromQualName('ccp.molecule.ChemComp.MolType')
    molTypes = MolType.enumeration
    molTypes.remove('other')
    molTypes.remove('carbohydrate')
   
    self.molType = 'protein'
    
    ccpCodes = self.getCcpCodes(self.molType) or [None,]
    self.ccpCode = 'Ala'
    
    self.atomType = ATOM_TYPES[0]
    
    self.atomNamesDict = {}
    self.chemAtomNmrRefs = self.getCcpCodeData(self.ccpCode, atomType=self.atomType)
    
    
    tipText = 'Which of the common bio-polymer types to show data for'
    self.molTypeLabel     = Label(frameA, text = 'Molecule Type:', grid=(row,0))
    self.molTypePulldown  = PulldownList(frameA, callback=self.changeMolType,
                                         texts=molTypes, grid=(row,1), tipText=tipText)

    tipText = 'Which residue code to show chemical shift distributions for'
    self.ccpCodeLabel     = Label(frameA, text = 'Residue Code:', grid=(row,2))
    self.ccpCodePulldown  = PulldownList(frameA, callback=self.changeCcpCode, texts=ccpCodes,
                                         index=ccpCodes.index(self.ccpCode), 
                                         grid=(row,3), tipText=tipText)

    tipText = 'Whether to show distributions for hydrogen atoms or other atoms'
    self.atomTypeLabel    = Label(frameA, text = 'Atom Type:', grid=(row,4))
    self.atomTypePulldown = PulldownList(frameA, callback=self.changeAtomType,
                                         texts=ATOM_TYPES, tipText=tipText,
                                         grid=(row,5))

    row += 1

    tipText = 'The selection of atom name to display distributions for'
    self.atomSelector = PartitionedSelector(frameA, self.toggleAtom,
                                            tipText=tipText, maxRowObjects=20)
    self.atomSelector.grid(row=row, column=0, columnspan=6, sticky='ew')

    row += 1

    frameA.expandGrid(row,5)
    self.scrolledGraph = ScrolledGraph(frameA, symbolSize=2, reverseX=True, width=650,
                                       height=300, title='Chemical shift distribution',
                                       xLabel='Chemical shift', yLabel='proportion',
                                       motionCallback=self.updateCrosshairs)
    self.scrolledGraph.grid(row=row, column=0, columnspan=6, sticky='nsew')
    
    # # # # # # #  PROTEIN CA CB   # # # # # # # 
    
    frameB.expandGrid(0,0)
    matrix, ppms = self.getCaCbMatrix()
    title = 'Amino Acid CA & CB Chemical Shifts'
    self.cacbMatrix = ScrolledDensityMatrix(frameB, matrix=matrix, boxSize=14,
                                            title=title,
                                            xLabels=ppms, yLabels=AMINO_ACIDS,
                                            borderColor='grey', zoom=1.0,
                                            labelAxes=True, barPlot=False,
                                            doLegend=False, grid=(0,0))
    
    sdm = self.cacbMatrix
    font = sdm.boldFont
    
    x0, y0 = (470,370)
    sdm.canvas.create_rectangle(x0+170,y0-6,x0+182,y0+6,fill='#4040A0',
                                outline=sdm.borderColor, width=1)
    sdm.canvas.create_text(x0+200, y0, text='CA', font=font)
    sdm.canvas.create_rectangle(x0+220,y0-6,x0+232,y0+6,fill='#A04040',
                                outline=sdm.borderColor, width=1)
    sdm.canvas.create_text(x0+250, y0, text='CB', font=font)
    sdm.canvas.create_text(x0, y0, text='13C PPM +/- 0.5', font=font)
    
    # # # # # # #  M A I N   # # # # # # # 
    
    tipText = 'Whether to use chemical shift data from the BMRB (unfiltered) or RefDB sets'
    label = Label(tabbedFrame.sideFrame, text='Source Database:', grid=(0,0), sticky='e')
    index = SOURCE_NAMES.index(self.sourceName)
    self.sourcePulldown = PulldownList(tabbedFrame.sideFrame, self.changeSource,
                                       texts=SOURCE_NAMES, index=index, 
                                       grid=(0,1), sticky='e', tipText=tipText)

    self.bottomButtons = UtilityButtonList(tabbedFrame.sideFrame, expands=True,
                                           helpUrl=self.help_url, sticky='e',
                                           grid=(0,2))
                                               
    self.waiting = False
    self.updateAfter()

    for func in ('__init__', 'delete'):
      self.registerNotify(self.updateAfter, 'ccp.nmr.NmrReference.NmrReferenceStore', func)

  def open(self):
  
    self.updateAfter()
    BasePopup.open(self)
  
  def changeSource(self, sourceName):
  
    if sourceName is not self.sourceName:
      self.sourceName = sourceName
      self.updateCcpCodes()
      self.updateAfter()
    
  def getAtomColor(self, i,N):
    
    h = i/float(N)
    s = 1
    v = 0.8
    [r,g,b] = hsbToRgb(h,s,v)
   
    return hexRepr(r,g,b)

  def toggleAtom(self, atomName):
  
    if self.atomNamesDict.get(atomName):
      self.atomNamesDict[atomName] = False
    else:
      self.atomNamesDict[atomName] = True

    self.updateAfter()

  def getCcpCodes(self, molType):
  
    sourceName = self.sourceName

    ccpCodes = []
    for nmrRef in self.project.findAllNmrReferenceStores(molType=molType):
      chemCompNmrRef = nmrRef.findFirstChemCompNmrRef(sourceName=sourceName)
      
      if chemCompNmrRef:
        ccpCodes.append(nmrRef.ccpCode)
    
    ccpCodes.sort()
      
    return ccpCodes
  
  def getCcpCodeData(self, ccpCode, molType=None, atomType=None):

    if not molType:
      molType = self.molType

    dataDict = {}
    project = self.project
    sourceName = self.sourceName
    
    nmrRefStore = project.findFirstNmrReferenceStore(molType=molType,ccpCode=ccpCode)
     
    chemCompNmrRef = nmrRefStore.findFirstChemCompNmrRef(sourceName=sourceName)
    if chemCompNmrRef:
    
      chemCompVarNmrRef = chemCompNmrRef.findFirstChemCompVarNmrRef(linking='any',descriptor='any')
      if chemCompVarNmrRef:
        for chemAtomNmrRef in chemCompVarNmrRef.chemAtomNmrRefs:
          atomName = chemAtomNmrRef.name
          element  = chemAtomNmrRef.findFirstChemAtom().elementSymbol
  
          if not atomType:
            dataDict[atomName] = chemAtomNmrRef
  
          elif (atomType == 'Hydrogen' and element == 'H') or \
               (atomType == 'Heavy' and element != 'H'):
            dataDict[atomName] = chemAtomNmrRef
 
    return dataDict  
 
  def changeMolType(self, molType):
  
    self.molType = molType
    self.updateCcpCodes()
  
  def changeCcpCode(self, ccpCode):
  
    self.ccpCode = ccpCode
    self.updateAtomNames()
       
  def changeAtomType(self, atomType):
  
    self.atomType = atomType
    self.updateAtomNames()
       
  def updateAfter(self, *opt):
  
    if self.waiting:
      return
    else:
      self.waiting = True
      self.after_idle(self.update)

  def updateCcpCodes(self):
    
    ccpCodes = self.getCcpCodes(self.molType)
    if ccpCodes:
      self.ccpCodePulldown.setup(ccpCodes, ccpCodes, 0)
      self.changeCcpCode(ccpCodes[0])
    else:
      self.ccpCodePulldown.setup([], [], 0)
      self.changeCcpCode(None)
      
  
  def updateAtomNames(self):
  
    if self.ccpCode:
      self.chemAtomNmrRefs = self.getCcpCodeData(self.ccpCode, atomType=self.atomType)
      atomNames = self.chemAtomNmrRefs.keys()
      atomNames = greekSortAtomNames(atomNames, self.molType)
      N = len(atomNames)

      for atomName in atomNames:
        if self.atomNamesDict.get(atomName) is None:
          self.atomNamesDict[atomName] = True

      colors = []
      for i in range(N):
        colors.append( self.getAtomColor(i,N) )

 
    else:
      colors = []
      atomNames = []
      N = 0
 
    self.atomSelector.update(objects=atomNames,labels=atomNames,colors=colors)
        
    for i in range(N):
      if self.atomNamesDict[atomNames[i]]:
        self.atomSelector.setButtonState(i, True)
      else:
        self.atomSelector.setButtonState(i, False)

    self.updateAfter()
  
  def destroy(self):

    for func in ('__init__', 'delete'):
      self.unregisterNotify(self.updateAfter, 'ccp.nmr.NmrReference.NmrReferenceStore', func)

    BasePopup.destroy(self)
    
  def update(self):

    matrix, ppms = self.getCaCbMatrix()
    self.cacbMatrix.xLabels = ppms
    self.cacbMatrix.update(matrix)
       
    self.updateAtomNames()
    dataSets = []
    colorList = []
    atomsString = ''
    
    if self.ccpCode:
      c = 0
      atomNames = self.chemAtomNmrRefs.keys()
      N = len(atomNames)
      for atomName in greekSortAtomNames(atomNames, self.molType):
        if self.atomNamesDict[atomName]:
          atomsString += '%s ' % atomName
          chemAtomNmrRef = self.chemAtomNmrRefs[atomName]
          distribution   = chemAtomNmrRef.distribution
          refPoint       = chemAtomNmrRef.refPoint
          refValue       = chemAtomNmrRef.refValue
          valuePerPoint  = chemAtomNmrRef.valuePerPoint

          data = []
          for i in range(len(distribution)):
            x = refValue + valuePerPoint*( i-refPoint)
            y = distribution[i]
            data.append( (x,y) )
 
          dataSets.append(data)
          colorList.append(self.getAtomColor(c,N))
        c += 1
 
      self.scrolledGraph.title = '%s %s Chemical shift distribution' % (self.ccpCode,atomsString)
    else:
      dataSets = [[(0,0)],]
      self.scrolledGraph.title = 'Chemical shift distribution'
    
    self.scrolledGraph.zoom  = 1.0
    
    self.scrolledGraph.update(dataSets=dataSets, dataColors=colorList)  
    
    self.waiting = False
    
  def getCaCbMatrix(self):  
    
    ppms = range(73,14,-1)
    blankCol = [0.0]*len(ppms)
    matrix = [[0.0]*len(AMINO_ACIDS) for x in ppms]
    
    for i, ccpCode in enumerate(AMINO_ACIDS):
      atomRefDict = self.getCcpCodeData(ccpCode, molType='protein')
      valueDict = {}
      
      for atomName in ('CA','CB'):
        valueDict[atomName] = blankCol[:]
        
        chemAtomNmrRef = atomRefDict.get(atomName)
        if not chemAtomNmrRef:
          continue
          
        distribution   = chemAtomNmrRef.distribution
        refPoint       = chemAtomNmrRef.refPoint
        refValue       = chemAtomNmrRef.refValue
        valuePerPoint  = chemAtomNmrRef.valuePerPoint
        
        
        for j, ppm in enumerate(ppms):
          ppmMin = ppm-0.5
          ppmMax = ppm+0.5
 
          v = 0.0
          n = 0.0
          for k in range(len(distribution)):
            y = refValue + valuePerPoint*(k-refPoint)
 
            if ppmMin < y <= ppmMax:
              v += distribution[k]
              n += 1.0
            elif y > ppmMax:
              break
 
          if n:
            valueDict[atomName][j] = v/n
      
      for j, ppm in enumerate(ppms):
        matrix[j][i] = valueDict['CA'][j] - valueDict['CB'][j]

    return matrix, ppms

  def updateCrosshairs(self, event):

    # code below is a bit dangerous

    position = self.scrolledGraph.getPlotCoords(event)[0]

    typeLocation = []
    isHydrogen = (self.atomType == 'Hydrogen')
    for panelType in self.analysisProject.panelTypes:
      axisType = panelType.axisType
      if isHydrogen:
        if axisType.name in ('1H', '2H'):
          typeLocation.append((panelType, position))
      else:
        if axisType.name not in ('1H', '2H'):
          typeLocation.append((panelType, position))

    self.scrolledGraph.mouseEnter(event)
    self.parent.drawWindowCrosshairs(typeLocation)

  def drawCrosshairs(self, typeLocation):
    """ Draw crosshairs at specified locations.
        typeLocation = tuple of (PanelType, position)
    """

    isHydrogen = (self.atomType == ATOM_TYPES[0])

    positions = []
    for (panelType, position) in typeLocation:
      axisType = panelType.axisType
      if axisType.measurementType != 'Shift':
        continue
        
      if position is None:
        continue

      if isHydrogen:
        if axisType.name in ('1H', '2H'):
          positions.append(position)
      else:
        if axisType.name not in ('1H', '2H'):
          positions.append(position)

    self.scrolledGraph.drawVerticalLines(positions)
  def body(self, guiFrame):
    
    self.geometry("775x500")
    guiFrame.expandGrid(0,0)
    
    options = ['1D Graphs','Amino Acid CA CB']
    tipTexts = ['Simple graphs of how chemical shift values are distributed for a given atom type',
                'Density plots of alpha a & beta carbon shift distributions for common amnio acids']
    tabbedFrame = TabbedFrame(guiFrame, options=options, grid=(0,0), tipTexts=tipTexts)
    frameA, frameB = tabbedFrame.frames
    
    # # # # # # #  1D GRAPHS  # # # # # # # 
    
 
    row = 0
     
    MolType = self.project.metaclass.metaObjFromQualName('ccp.molecule.ChemComp.MolType')
    molTypes = MolType.enumeration
    molTypes.remove('other')
    molTypes.remove('carbohydrate')
   
    self.molType = 'protein'
    
    ccpCodes = self.getCcpCodes(self.molType) or [None,]
    self.ccpCode = 'Ala'
    
    self.atomType = ATOM_TYPES[0]
    
    self.atomNamesDict = {}
    self.chemAtomNmrRefs = self.getCcpCodeData(self.ccpCode, atomType=self.atomType)
    
    
    tipText = 'Which of the common bio-polymer types to show data for'
    self.molTypeLabel     = Label(frameA, text = 'Molecule Type:', grid=(row,0))
    self.molTypePulldown  = PulldownList(frameA, callback=self.changeMolType,
                                         texts=molTypes, grid=(row,1), tipText=tipText)

    tipText = 'Which residue code to show chemical shift distributions for'
    self.ccpCodeLabel     = Label(frameA, text = 'Residue Code:', grid=(row,2))
    self.ccpCodePulldown  = PulldownList(frameA, callback=self.changeCcpCode, texts=ccpCodes,
                                         index=ccpCodes.index(self.ccpCode), 
                                         grid=(row,3), tipText=tipText)

    tipText = 'Whether to show distributions for hydrogen atoms or other atoms'
    self.atomTypeLabel    = Label(frameA, text = 'Atom Type:', grid=(row,4))
    self.atomTypePulldown = PulldownList(frameA, callback=self.changeAtomType,
                                         texts=ATOM_TYPES, tipText=tipText,
                                         grid=(row,5))

    row += 1

    tipText = 'The selection of atom name to display distributions for'
    self.atomSelector = PartitionedSelector(frameA, self.toggleAtom,
                                            tipText=tipText, maxRowObjects=20)
    self.atomSelector.grid(row=row, column=0, columnspan=6, sticky='ew')

    row += 1

    frameA.expandGrid(row,5)
    self.scrolledGraph = ScrolledGraph(frameA, symbolSize=2, reverseX=True, width=650,
                                       height=300, title='Chemical shift distribution',
                                       xLabel='Chemical shift', yLabel='proportion',
                                       motionCallback=self.updateCrosshairs)
    self.scrolledGraph.grid(row=row, column=0, columnspan=6, sticky='nsew')
    
    # # # # # # #  PROTEIN CA CB   # # # # # # # 
    
    frameB.expandGrid(0,0)
    matrix, ppms = self.getCaCbMatrix()
    title = 'Amino Acid CA & CB Chemical Shifts'
    self.cacbMatrix = ScrolledDensityMatrix(frameB, matrix=matrix, boxSize=14,
                                            title=title,
                                            xLabels=ppms, yLabels=AMINO_ACIDS,
                                            borderColor='grey', zoom=1.0,
                                            labelAxes=True, barPlot=False,
                                            doLegend=False, grid=(0,0))
    
    sdm = self.cacbMatrix
    font = sdm.boldFont
    
    x0, y0 = (470,370)
    sdm.canvas.create_rectangle(x0+170,y0-6,x0+182,y0+6,fill='#4040A0',
                                outline=sdm.borderColor, width=1)
    sdm.canvas.create_text(x0+200, y0, text='CA', font=font)
    sdm.canvas.create_rectangle(x0+220,y0-6,x0+232,y0+6,fill='#A04040',
                                outline=sdm.borderColor, width=1)
    sdm.canvas.create_text(x0+250, y0, text='CB', font=font)
    sdm.canvas.create_text(x0, y0, text='13C PPM +/- 0.5', font=font)
    
    # # # # # # #  M A I N   # # # # # # # 
    
    tipText = 'Whether to use chemical shift data from the BMRB (unfiltered) or RefDB sets'
    label = Label(tabbedFrame.sideFrame, text='Source Database:', grid=(0,0), sticky='e')
    index = SOURCE_NAMES.index(self.sourceName)
    self.sourcePulldown = PulldownList(tabbedFrame.sideFrame, self.changeSource,
                                       texts=SOURCE_NAMES, index=index, 
                                       grid=(0,1), sticky='e', tipText=tipText)

    self.bottomButtons = UtilityButtonList(tabbedFrame.sideFrame, expands=True,
                                           helpUrl=self.help_url, sticky='e',
                                           grid=(0,2))
                                               
    self.waiting = False
    self.updateAfter()

    for func in ('__init__', 'delete'):
      self.registerNotify(self.updateAfter, 'ccp.nmr.NmrReference.NmrReferenceStore', func)
Beispiel #19
0
  def update(self, t1List, t2List):
    
    nColors = len(CLUSTER_COLORS)

    dataSets = []
    dataColors = []
    dataNames = []
    seqNums = set()
    values = set()
    
    if t1List and t2List:
      t1t2Points = {}
      resonancesT1 = {}

      t1Unit = MS_UNIT_MULTIPLIERS[t1List.unit]
      t2Unit = MS_UNIT_MULTIPLIERS[t2List.unit]
      
      for t1 in t1List.measurements:
        resonancesT1[t1.resonance] = t1
         
      for t2 in t2List.measurements:
        resonance = t2.resonance
        
        if not resonance.resonanceSet:
          continue
        
        t1 = resonancesT1.get(resonance)
        
        if t1:
          residue = resonance.resonanceSet.findFirstAtomSet().findFirstAtom().residue
          value = (t1Unit*t1.value) / (t2Unit*t2.value)
          chain = residue.chain
          
          if chain not in t1t2Points:
            t1t2Points[chain] = []
          
          seqCode = residue.seqCode
          t1t2Points[chain].append((seqCode, value))
          seqNums.add(seqCode)
          values.add(value)
       
      chains = t1t2Points.keys()
      molSystems = set([c.molSystem for c in chains])
      
      if len(molSystems) > 1:
        chainLabels = [('Chain %s:%s' % (c.molSystem.code, c.code),  c) for c in chains]
        chainLabels.sort()
        
      else:
        chainLabels = [('Chain %s' % c.code, c) for c in chains]
        chainLabels.sort()
        
      for label, chain in chainLabels:
        data = t1t2Points[chain]
        data.sort()
        dataSets.append(data)
        dataNames.append(label)
      
      for i, dataSet in enumerate(dataSets):
        dataColors.append(CLUSTER_COLORS[i % nColors])
    
      res = [c.sortedResidues() for c in chains]
      
      if seqNums:
        self.minRes = min(seqNums) - 1
        self.maxRes = max(seqNums) + 1
      
      if values:
        self.minVal = 0.0 # min(values)
        self.maxVal = int(max(values) + 1) 
    
    if len(dataNames) < 2:
      dataNames = None
       
    ScrolledGraph.update(self, dataSets, dataColors, dataNames=dataNames)
    def body(self):
        '''describes the body of this tab. It bascically consists
           of some field to fill out for the user at the top and
           a ScrolledGraph that shows the progess of the annealing
           procedure a the bottom.
        '''

        frame = self.frame

        # frame.expandGrid(13,0)
        frame.expandGrid(15, 1)
        row = 0

        text = 'Calculate Assignment Suggestions'
        command = self.runCalculations
        self.startButton = Button(frame, command=command, text=text)
        self.startButton.grid(row=row, column=0, sticky='nsew', columnspan=2)

        row += 1

        Label(frame, text='Amount of runs: ', grid=(row, 0))
        tipText = 'The amount of times the whole optimization procedure is performed, each result is safed'
        self.repeatEntry = IntEntry(frame, grid=(row, 1), width=7, text=10,
                                    returnCallback=self.updateRepeatEntry,
                                    tipText=tipText, sticky='nsew')
        self.repeatEntry.bind('<Leave>', self.updateRepeatEntry, '+')

        row += 1

        Label(frame, text='Temperature regime: ', grid=(row, 0))
        tipText = 'This list of numbers govern the temperature steps during the annealing, every number represents 1/(kb*t), where kb is the Boltzmann constant and t the temperature of one step.'
        self.tempEntry = Entry(frame, text=map(str, self.acceptanceConstantList), width=64,
                               grid=(row, 1), isArray=True, returnCallback=self.updateAcceptanceConstantList,
                               tipText=tipText, sticky='nsew')

        row += 1

        Label(frame, text='Amount of attempts per temperature:', grid=(row, 0))
        tipText = 'The amount of attempts to switch the position of two spinsystems in the sequence are performed for each temperature point'
        self.NAStepEntry = IntEntry(frame, grid=(row, 1), width=7, text=10000,
                                    returnCallback=self.updateStepEntry,
                                    tipText=tipText, sticky='nsew')
        self.NAStepEntry.bind('<Leave>', self.updateStepEntry, '+')

        row += 1

        Label(frame, text='Fraction of peaks to leave out:', grid=(row, 0))
        tipText = 'In each run a fraction of the peaks can be left out of the optimization, thereby increasing the variability in the outcome and reducing false negatives. In each run this will be different randomly chosen sub-set of all peaks. 0.1 (10%) can be a good value.'
        self.leaveOutPeaksEntry = FloatEntry(frame, grid=(row, 1), width=7, text=0.0,
                                             returnCallback=self.updateLeavePeaksOutEntry,
                                             tipText=tipText, sticky='nsew')
        self.leaveOutPeaksEntry.bind(
            '<Leave>', self.updateLeavePeaksOutEntry, '+')

        row += 1

        Label(frame, text='Minmal amino acid typing score:', grid=(row, 0))
        tipText = 'If automatic amino acid typing is selected, a cut-off value has to set. Every amino acid type that scores higher than the cut-off is taken as a possible type. This is the same score as can be found under resonance --> spin systems --> predict type. Value should be between 0 and 100'
        self.minTypeScoreEntry = FloatEntry(frame, grid=(row, 1), width=7, text=1.0,
                                            returnCallback=self.updateMinTypeScoreEntry,
                                            tipText=tipText, sticky='nsew')
        self.minTypeScoreEntry.bind(
            '<Leave>', self.updateMinTypeScoreEntry, '+')

        row += 1

        Label(frame, text='Minimal colabelling fraction:', grid=(row, 0))
        tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.'
        self.minLabelEntry = FloatEntry(frame, grid=(row, 1), width=7, text=0.1,
                                        returnCallback=self.updateMinLabelEntry,
                                        tipText=tipText, sticky='nsew')
        self.minLabelEntry.bind('<Leave>', self.updateMinLabelEntry, '+')

        row += 1

        Label(frame, text='Use sequential assignments:', grid=(row, 0))
        tipText = 'When this option is select the present sequential assignments will be kept in place'
        self.useAssignmentsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use tentative assignments:', grid=(row, 0))
        tipText = 'If a spin system has tentative assignments this can be used to narrow down the amount of possible sequential assignments.'
        self.useTentativeCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use amino acid types:', grid=(row, 0))
        tipText = 'Use amino acid types of the spin systems. If this option is not checked the spin systems are re-typed, only resonance names and frequencies are used'
        self.useTypeCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Include untyped spin systems:', grid=(row, 0))
        tipText = 'Also include spin system that have no type information. Amino acid typing will be done on the fly.'
        self.useAlsoUntypedSpinSystemsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use dimensional assignments:', grid=(row, 0))
        tipText = 'If one or more dimensions of a peak is already assigned, assume that this assignment is the only option. If not the check the program will consider all possibilities for the assignment of the dimension.'
        self.useDimensionalAssignmentsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Chain:', grid=(row, 0))
        self.molPulldown = PulldownList(
            frame, callback=self.changeMolecule, grid=(row, 1))
        self.updateChains()

        row += 1

        Label(frame, text='Residue ranges: ', grid=(row, 0))
        tipText = 'Which residues should be included. Example: "10-35, 62-100, 130".'
        self.residueRangeEntry = Entry(frame, text=None, width=64,
                                       grid=(row, 1), isArray=True, returnCallback=self.updateResidueRanges,
                                       tipText=tipText, sticky='nsew')
        self.updateResidueRanges(fromChain=True)

        row += 1

        self.energyPlot = ScrolledGraph(frame, symbolSize=2, width=600,
                                        height=200, title='Annealing',
                                        xLabel='temperature step', yLabel='energy')
        self.energyPlot.grid(row=row, column=0, columnspan=2, sticky='nsew')
Beispiel #21
0
  def update(self, mList):
    
    nColors = len(CLUSTER_COLORS)

    dataSets = []
    dataColors = []
    dataNames = []
    seqNums = set()
    values = set()
    
    if mList:
      points = {}
           
      for measurement in mList.measurements:
        resonance = list(measurement.resonances)[0]
        
        if not resonance.resonanceSet:
          continue
        
        residue = resonance.resonanceSet.findFirstAtomSet().findFirstAtom().residue
        value = measurement.value
        chain = residue.chain
        
        if chain not in points:
          points[chain] = []
        
        seqCode = residue.seqCode
        points[chain].append((seqCode, value))
        seqNums.add(seqCode)
        values.add(value)
       
      chains = points.keys()
      molSystems = set([c.molSystem for c in chains])
      
      if len(molSystems) > 1:
        chainLabels = [('Chain %s:%s' % (c.molSystem.code, c.code),  c) for c in chains]
        chainLabels.sort()
        
      else:
        chainLabels = [('Chain %s' % c.code, c) for c in chains]
        chainLabels.sort()
        
      for label, chain in chainLabels:
        data = points[chain]
        data.sort()
        dataSets.append(data)
        dataNames.append(label)
      
      for i, dataSet in enumerate(dataSets):
        dataColors.append(CLUSTER_COLORS[i % nColors])
    
      res = [c.sortedResidues() for c in chains]
      
      if seqNums:
        self.minRes = min(seqNums) - 1
        self.maxRes = max(seqNums) + 1
      
      if values:
        self.minVal = int(min(values))
        self.maxVal = int(max(values) + 1) 
    
    if len(dataNames) < 2:
      dataNames = None
       
    ScrolledGraph.update(self, dataSets, dataColors, dataNames=dataNames)
Beispiel #22
0
    def body(self, guiFrame):

        guiFrame.grid_columnconfigure(0, weight=1)
        row = 0

        self.scrolledGraph = ScrolledGraph(guiFrame,
                                           width=400,
                                           height=300,
                                           symbolSize=5,
                                           symbols=['square', 'circle'],
                                           dataColors=['#000080', '#800000'],
                                           lineWidths=[0, 1],
                                           grid=(row, 0))

        #self.scrolledGraph.setZoom(0.7)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Fitting Function:', grid=(0, 0))

        tipText = 'Selects which form of function to fit to the experimental data'
        self.methodPulldown = PulldownList(frame,
                                           self.changeMethod,
                                           grid=(0, 1),
                                           tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        tipText = 'The effective equation of the final fitted graph, incorporating all parameters'
        self.equationLabel = Label(frame,
                                   text='Equation:',
                                   grid=(0, 0),
                                   tipText=tipText)

        tipText = 'The error in the fit of the selected parameterised function to the experimental data'
        self.errorLabel = Label(frame,
                                text='Fit Error:',
                                grid=(0, 1),
                                tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Include x origin?:', grid=(0, 0))

        tipText = 'Whether to include the x=0 point in the drawing'
        self.xOriginSelect = CheckButton(frame,
                                         callback=self.draw,
                                         grid=(0, 1),
                                         selected=False,
                                         tipText=tipText)

        label = Label(frame, text='Include y origin?:', grid=(0, 2))

        tipText = 'Whether to include the y=0 point in the drawing'
        self.yOriginSelect = CheckButton(frame,
                                         callback=self.draw,
                                         grid=(0, 3),
                                         selected=False,
                                         tipText=tipText)

        label = Label(frame, text='Include y error?:', grid=(0, 4))

        tipText = 'Whether to include the y error bars in the drawing (if these exist)'
        self.yErrorSelect = CheckButton(frame,
                                        callback=self.draw,
                                        grid=(0, 5),
                                        selected=False,
                                        tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Navigation Window:', grid=(0, 0))

        tipText = 'Selects which spectrum window will be used for navigating to peak positions'
        self.windowPanePulldown = PulldownList(frame,
                                               self.changeWindow,
                                               grid=(0, 1),
                                               tipText=tipText)

        label = Label(frame, text='Follow in window?:', grid=(0, 2))

        tipText = 'Whether to navigate to the position of the reference peak (for the group), in the selected window'
        self.followSelect = CheckButton(frame,
                                        callback=self.windowPaneNavigate,
                                        grid=(0, 3),
                                        selected=False,
                                        tipText=tipText)

        label = Label(frame, text='Mark Ref Peak?:', grid=(0, 4))

        tipText = 'Whether to put a multi-dimensional cross-mark through the reference peak position, so it can be identified in spectra'
        self.markSelect = CheckButton(frame,
                                      callback=None,
                                      tipText=tipText,
                                      grid=(0, 5),
                                      selected=False)

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)
        tipTexts = [
            'The number of the data point, in order of increasing X-axis value',
            'For each point, the value of the parameter which is varied in the NMR series, e.g. T1, temperature, concentration etc.',
            'For each point, the experimental value being fitted, e.g. peak intensity of chemical shift distance',
            'The value of the best-fit function at the X-axis location',
            'The difference between the experimental (Y-axis) value and the fitted value',
            'The error in the experimental (Y-axis) value'
        ]
        headingList = ['Point', 'x', 'y', 'Fitted y', u'\u0394', 'y error']
        self.scrolledMatrix = ScrolledMatrix(guiFrame,
                                             headingList=headingList,
                                             callback=self.selectObject,
                                             tipTexts=tipTexts,
                                             grid=(row, 0))

        row += 1
        tipTexts = [
            'Remove the selected data point, optionally removing the underlying peak',
            'Show a table of spectrum peaks that correspond to the selected data point'
        ]
        texts = ['Remove Point', 'Show Peak']
        commands = [self.removePoint, self.showObject]

        if self.prevSetFunction:
            texts.append('Previous Set')
            tipTexts.append(
                'Move to the previous set of fitted values; the next group of peaks, often corresponding to a different residue or resonance'
            )
            commands.append(self.prevSet)

        if self.nextSetFunction:
            tipTexts.append(
                'Move to the next set of fitted values; the next group of peaks, often corresponding to a different residue or resonance'
            )
            texts.append('Next Set')
            commands.append(self.nextSet)

        bottomButtons = UtilityButtonList(guiFrame,
                                          texts=texts,
                                          commands=commands,
                                          helpUrl=self.help_url,
                                          tipTexts=tipTexts,
                                          grid=(row, 0),
                                          doClone=False)
        self.removeButton = bottomButtons.buttons[0]

        for func in ('__init__', 'delete', 'setName'):
            self.registerNotify(self.updateWindows,
                                'ccpnmr.Analysis.SpectrumWindow', func)

        self.update()
Beispiel #23
0
class RelaxationAnalysisPopup(BasePopup):

  def __init__(self, parent, *args, **kw):
    
    self.guiParent = parent
    self.t1List = None
    self.t2List = None
    self.noeList = None
    self.waiting = False
   
    BasePopup.__init__(self, parent, title="Relaxation Analyses", **kw)

    periodicTable = self.project.currentChemElementStore
    
    nitrogen = periodicTable.findFirstChemElement(elementSymbol='N')
    hydrogen = periodicTable.findFirstChemElement(elementSymbol='H')

  def body(self, guiFrame):

    self.geometry('700x840')
    
    guiFrame.expandGrid(1,0)
    
    # Top frame
    
    frame = Frame(guiFrame, grid=(0,0))
    frame.expandGrid(None,8)
    
    label = Label(frame, text=u' %s List:' % T1, grid=(0,0))
    self.t1Pulldown = PulldownList(frame, callback=self.selectT1List, grid=(0,1))
    
    label = Label(frame, text=u'  %s List:' % T2, grid=(0,2))
    self.t2Pulldown = PulldownList(frame, callback=self.selectT2List, grid=(0,3))
    
    label = Label(frame, text='  NOE List:', grid=(0,4))
    self.noePulldown = PulldownList(frame, callback=self.selectNoeList, grid=(0,5))
 
    label = Label(frame, text='  Spectrometer Freq (MHz):', grid=(0,6))
    self.sfEntry = FloatEntry(frame, grid=(0,7), text=600.00, width=6)

    UtilityButtonList(frame, grid=(0,9), sticky='e')
    
    # Tabs
    
    options = [u'%s vs %s Scatter' % (T1, T2),
               u'%s,%s & NOE Graphs' % (T1, T2) ,
               u'%s/%s Graph' % (T1, T2),
               u'%s Estimate Graph' % S2,
               'Options']
    self.tabbedFrame = TabbedFrame(guiFrame, options=options,
                                   callback=self.toggleTab, grid=(1,0))
    frameA, frameD, frameC, frameE, frameB = self.tabbedFrame.frames

    # T1 vs T2 Graph

    frameA.expandGrid(0,0)
 
    self.t1t2Graph = T1VersesT2Plot(frameA, grid=(0,0))

    # T1 & T2 Graph

    frameD.expandGrid(0,0)
    frameD.expandGrid(1,0)
    frameD.expandGrid(2,0)
 
    self.t1Graph = MeasurementPlot(frameD, T1, grid=(0,0))
    self.t2Graph = MeasurementPlot(frameD, T2, grid=(1,0))
    self.noeGraph = NoePlot(frameD, 'NOE', grid=(2,0))

    # T1 over T2 Graph

    frameC.expandGrid(0,0)
 
    self.t1t2GraphB = T1OverT2Plot(frameC, grid=(0,0))
    
    # Order params graph
    
    frameE.expandGrid(0,0)
    frameE.expandGrid(1,0)
    frameE.expandGrid(2,0)
    
    self.s2Graph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % S2,
                                 xLabel='Residue number', yLabel=S2,
                                 width=500, height=150, graphType='histogram', 
                                 xGrid=True, yGrid=False, grid=(0,0),
                                 dataColors=['#0000A0','#808000'],
                                 dataNames=['Isotropic',])

    self.teGraph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % Te,
                                 xLabel='Residue number', yLabel=u'%s (ps)' % Te,
                                 width=500, height=150, graphType='histogram',
                                 xGrid=True, yGrid=False, grid=(1,0),
                                 dataColors=['#008000',])
                                 
    self.rexGraph = ScrolledGraph(frameE, title=u'%s vs Residue Sequence' % 'Rex',
                                  xLabel='Residue number', yLabel='Rex',
                                  width=500, height=150, graphType='histogram',
                                  xGrid=True, yGrid=False, grid=(2,0),
                                  dataColors=['#900000',])
    
    # Options
    
    frameB.expandGrid(4,2)
    
    frame = LabelFrame(frameB, text='Physical Params', grid=(0,0))
    frame.expandGrid(None,3)
   
    label = Label(frame, text=u'N-H bond length (\u00C5)', grid=(0,0))
    self.lenNhEntry = FloatEntry(frame, text=1.015, grid=(0,1), width=8)

    label = Label(frame, text=u'Internal correlation\ntime, \u03C4e (ps)', grid=(1,0))
    self.ictEntry = FloatEntry(frame, text=50.0, grid=(1,1), width=8)
    
    label = Label(frame, text=u'15N Chemical Shift\nAnisotopy,\u0394N (ppm)',
                  grid=(2,0))
    self.csaNEntry = FloatEntry(frame, text=-160.0, grid=(2,1), width=8)
    
    frame = LabelFrame(frameB, text=u'%s vs %s Scatter' % (T1, T2), grid=(1,0))
    
    label = Label(frame, text='Max cluster difference (ms):', grid=(0,0))
    self.clusterDictEntry = FloatEntry(frame, text=20.0, grid=(0,1), width=8)    

    label = Label(frame, text='Min cluster size:', grid=(1,0))
    self.clusterSizeEntry = FloatEntry(frame, text=5, grid=(1,1), width=8)    

    label = Label(frame, text=u'Min graph %s (ms):' % T1, grid=(2,0))
    self.minT1Entry = FloatEntry(frame, text=300.0, grid=(2,1), width=8)    

    label = Label(frame, text=u'Max graph %s (ms):' % T1, grid=(3,0))
    self.maxT1Entry = FloatEntry(frame, text=1000.0, grid=(3,1), width=8)    

    label = Label(frame, text=u'Min graph %s (ms):' % T2, grid=(4,0))
    self.minT2Entry = FloatEntry(frame, text=0.0, grid=(4,1), width=8)    

    label = Label(frame, text=u'Max graph %s (ms):' % T2, grid=(5,0))
    self.maxT2Entry = FloatEntry(frame, text=600.0, grid=(5,1), width=8)    
    
    frame = LabelFrame(frameB, text=u'%s Contours' % S2, grid=(0,1))
    frame.expandGrid(4,3)

    label = Label(frame, text='(Order Parameter Lines)',
                  grid=(0,0), gridSpan=(1,2))

    label = Label(frame, text='Min value:', grid=(1,0))
    self.minS2Entry = FloatEntry(frame, text=0.3, grid=(1,1), width=8)
    
    label = Label(frame, text='Max value:', grid=(2,0))
    self.maxS2Entry = FloatEntry(frame, text=1.0, grid=(2,1), width=8)
    
    label = Label(frame, text='Step:', grid=(3,0))
    self.stepS2Entry = FloatEntry(frame, text=0.1, grid=(3,1), width=8)

    frame = LabelFrame(frameB, text=u'\u03C4m Contours', grid=(1,1))
    frame.expandGrid(4,3)

    label = Label(frame, text='(Rotational Correlation Time Lines)',
                  grid=(0,0), gridSpan=(1,2))
                  
    label = Label(frame, text='Min value (ns):', grid=(1,0))
    self.minRctEntry = FloatEntry(frame, text=5.0, grid=(1,1), width=8)
    
    label = Label(frame, text='Max value (ns):', grid=(2,0))
    self.maxRctEntry = FloatEntry(frame, text=14.0, grid=(2,1), width=8)
    
    label = Label(frame, text='Step (ns):', grid=(3,0))
    self.stepRctEntry = FloatEntry(frame, text=1.0, grid=(3,1), width=8)

    # Bottom frame
 
    texts = [u'Show %s Table' % T1,u'Show %s Table' % T2, u'Estimate %s' % S2]
    commands = [self.showT1List, self.showT2List, self.mc]
    buttonList = ButtonList(guiFrame, grid=(2,0), texts=texts, commands=commands)

    # Update

    self.updateRelaxationLists()

    self.drawAfter()

    self.administerNotifiers(self.registerNotify)
  
  def open(self):
  
    self.updateRelaxationLists()
    self.drawAfter()
  
    BasePopup.open(self)
  
  def destroy(self):
  
    self.administerNotifiers(self.unregisterNotify)
    
    BasePopup.destroy(self)
  
  def getSanitisedParams(self):
  
     cDist = self.clusterDictEntry.get() or 0.0
     lenNh = max(min(self.lenNhEntry.get() or 1.015, 1.2), 0.8)
     ict = self.ictEntry.get() or 0.0
     csaN = self.csaNEntry.get() or -180.0
     
     if csaN > 0:
       csaN *= -1.0
     
     minS2 = max(min(self.minS2Entry.get() or 0.0, 0.9), 0.0)
     maxS2 = max(min(self.maxS2Entry.get() or 1.0, 1.0), 0.1)
     
     if minS2 > maxS2:
       maxS2, minS2 = minS2, maxS2
     
     stepS2 = max(self.stepS2Entry.get() or 0.1, (maxS2-minS2)/100)
     
     minRct = self.minRctEntry.get()
     maxRct = self.maxRctEntry.get()
     
     if minRct > maxRct:
       maxRct, minRct = minRct, maxRct
     
     stepRct = max(self.stepRctEntry.get() or 0.1, (maxRct-minRct)/100)
     
     cluster = max(abs(self.clusterSizeEntry.get() or 10), 1)
     
     minT1 = self.minT1Entry.get() or 300.0
     maxT1 = self.maxT1Entry.get() or 1000.0
     minT2 = self.minT2Entry.get() or 0.0
     maxT2 = self.maxT2Entry.get() or 600.0
   
     
     if minT1 < 0:
       minT1 = 0.0

     if minT2 < 0:
       minT2 = 0.0


     if maxT1 < 0:
       maxT1 = 0.0

     if maxT2 < 0:
       maxT2 = 0.0


     if minT1 > maxT1:
       minT1, maxT1 = maxT1, minT1
       
     if minT2 > maxT2:
       minT2, maxT2 = maxT2, minT2


     if minT1 == maxT1:
       maxT1 += 100
     if minT2 == maxT2:
       maxT2 += 100
     
     
     self.clusterSizeEntry.set(cluster)
     self.minT1Entry.set(minT1)
     self.maxT1Entry.set(maxT1)
     self.minT2Entry.set(minT2)
     self.maxT2Entry.set(maxT2)
     self.clusterDictEntry.set(cDist)
     self.lenNhEntry.set(lenNh)
     self.ictEntry.set(ict)
     self.csaNEntry.set(csaN)
     self.minS2Entry.set(minS2)
     self.maxS2Entry.set(maxS2)
     self.stepS2Entry.set(stepS2)
     self.minRctEntry.set(minRct)
     self.maxRctEntry.set(maxRct)
     self.stepRctEntry.set(stepRct)
     
     paramsS2 = (minS2, maxS2, stepS2)
     paramsRct = (minRct, maxRct, stepRct)
     tBounds = (minT1, maxT1, minT2, maxT2)

     return cluster, cDist, lenNh, ict, csaN,  paramsS2, paramsRct, tBounds

  def administerNotifiers(self, notifyFunc):
  
    for func in ('__init__', 'delete','setName'):
      for clazz in ('ccp.nmr.Nmr.T1List','ccp.nmr.Nmr.T2List'):
        notifyFunc(self.updateRelaxationLists,clazz, func)

    for func in ('__init__', 'delete', 'setValue'):
      notifyFunc(self.updateMeasurementAfter,'ccp.nmr.Nmr.T1', func)
      notifyFunc(self.updateMeasurementAfter,'ccp.nmr.Nmr.T2', func)

  def showT1List(self):
  
    if self.t1List:
      self.guiParent.editMeasurements(self.t1List)

  def showT2List(self):
  
    if self.t2List:
      self.guiParent.editMeasurements(self.t2List)

  def toggleTab(self, index):
  
    if index == 0:
      self.drawAfter()

  def updateMeasurementAfter(self, measurement):
  
    if measurement.parentList in (self.t1List, self.t2List):
      self.drawAfter()
  
  def updateRelaxationLists(self, obj=None):
  
    mLists = self.nmrProject.sortedMeasurementLists()
    

    # T1
    t1List = self.t1List
    t1Lists = [ml for ml in mLists if ml.className == 'T1List']

    index = 0
    names = []
    
    if t1Lists:
      if t1List not in t1Lists:
        t1List = t1Lists[0]
      
      index = t1Lists.index(t1List)
      names = [ml.name or 'List %d' % ml.serial for ml in t1Lists]
    
    else:
      t1List = None
      
    self.selectT1List(t1List)
    self.t1Pulldown.setup(names, t1Lists, index)


    # T2
    t2List = self.t2List
    t2Lists = [ml for ml in mLists if ml.className == 'T2List']
    
    index = 0
    names = []
    
    if t2Lists:
      if t2List not in t2Lists:
        t2List = t2Lists[0]
      
      index = t2Lists.index(t2List)
      names = [ml.name or 'List %d' % ml.serial for ml in t2Lists]
    
    else:
      t2List = None
      
    self.selectT2List(t2List)
    self.t2Pulldown.setup(names, t2Lists, index)
    
    
    # NOE
    noeList = self.noeList
    noeLists = [ml for ml in mLists if ml.className == 'NoeList']
    
    index = 0
    names = []
    
    if noeLists:
      if noeList not in noeLists:
        noeList = noeLists[0]
      
      index = noeLists.index(noeList)
      names = [ml.name or 'List %d' % ml.serial for ml in noeLists]
    
    else:
      noeList = None
      
    self.selectNoeList(noeList)
    self.noePulldown.setup(names, noeLists, index)


  def drawAfter(self):
  
    if self.waiting:
      return
      
    self.waiting = True
    self.after_idle(self.draw)

  def selectT1List(self, t1List):
  
    if t1List is not self.t1List:
      self.t1List = t1List
      self.sfEntry.set(t1List.sf)
      values = [m.value for m in t1List.measurements]
      values.sort()
      minVal = self.minT1Entry.get()
      maxVal = self.maxT1Entry.get()
      minVal0 = values[0]*MS_UNIT_MULTIPLIERS[t1List.unit]
      maxVal0 = values[-1]*MS_UNIT_MULTIPLIERS[t1List.unit]

      if minVal0 < minVal:
        self.minT1Entry.set(max(minVal0 - 100, 0))
      
      if maxVal0 > maxVal:
        self.maxT1Entry.set(maxVal0 + 100)
      
      self.drawAfter()
    
  
  def selectT2List(self, t2List):
  
    if t2List is not self.t2List:
      self.t2List = t2List
      self.sfEntry.set(t2List.sf)
      values = [m.value for m in t2List.measurements]
      values.sort()
      values.sort()
      minVal = self.minT2Entry.get()
      maxVal = self.maxT2Entry.get()
      minVal0 = values[0]*MS_UNIT_MULTIPLIERS[t2List.unit]
      maxVal0 = values[-1]*MS_UNIT_MULTIPLIERS[t2List.unit]

      if minVal0 < minVal:
        self.minT2Entry.set(max(minVal0 - 50, 0))
      
      if maxVal0 > maxVal:
        self.maxT2Entry.set(maxVal0 + 50)
      
      self.drawAfter()
  
  
  def selectNoeList(self, noeList):
  
    if noeList is not self.noeList:
      self.noeList = noeList
      self.sfEntry.set(noeList.sf)
      
      #self.drawAfter()

  def draw(self):
  
    params = self.getSanitisedParams()
    
    cSize, cDist, lenNh, ict, csaN, paramsS2, paramsRct, tBounds = params
 
    sf = abs(self.sfEntry.get() or 500.010)
    
    self.t1t2Graph.update(self.t1List, self.t2List, cSize, cDist, sf, lenNh,
                          ict, csaN, paramsS2, paramsRct, tBounds)
                          
    self.t1t2GraphB.update(self.t1List, self.t2List)
    
    self.t1Graph.update(self.t1List)
    self.t2Graph.update(self.t2List)
    self.noeGraph.update(self.noeList)
      
    self.waiting = False


  def mc(self):
  
    sf = abs(self.sfEntry.get() or 500.010)
    
    if not self.t1List and self.t2List:
      return
    
    chains = set([])
    t1t2Points = {}
    resonancesT1 = {}
    resonancesNoe = {}
    residueResonances = {}

    t1Unit = MS_UNIT_MULTIPLIERS[self.t1List.unit]
    t2Unit = MS_UNIT_MULTIPLIERS[self.t2List.unit]
    
    
    if self.noeList:
      for noe in self.noeList.measurements:
        for resonance in noe.resonances:
          resonancesNoe[resonance] = noe
    
    for t1 in self.t1List.measurements:
      resonancesT1[t1.resonance] = t1
       
    for t2 in self.t2List.measurements:
      resonance = t2.resonance
      if not resonance.resonanceSet:
        continue
      
      residue = resonance.resonanceSet.findFirstAtomSet().findFirstAtom().residue
      
      t1 = resonancesT1.get(resonance)
      noe = resonancesNoe.get(resonance)
      
      if t1 and noe:
        t1t2Points[residue] = 1e-3*t1Unit*t1.value, 1e-3*t2Unit*t2.value, noe.value
        chains.add(residue.chain)
        residueResonances[residue] = resonance
      
      if t1:
        t1t2Points[residue] = 1e-3*t1Unit*t1.value, 1e-3*t2Unit*t2.value, None
        chains.add(residue.chain)
        residueResonances[residue] = resonance
     
    for chain in chains:
      residues = chain.sortedResidues()
      t1Values = []
      t2Values = []
      noeValues = []
      n = len(residues)
      n2 = n-1
      jj = range(n)
      s2Best = [0.0] * n
      teBest = [0.0] * n
      rexBest = [0.0] * n
      
      print ''
      
      for residue in residues:
        t1,t2, noe = t1t2Points.get(residue, (None, None, None))
        t1Values.append(t1)
        t2Values.append(t2)
        noeValues.append(noe)
      
      t1s = [v for v in t1Values if v]
      t2s = [v for v in t2Values if v]
      noes = [v for v in noeValues if v]
      
      m = len(t1s)
      
      t1 = sum(t1s)/float(m)
      t2 = sum(t2s)/float(m)
      noe = sum(noes)/float(m)
      
      t12 = [v/t2s[i] for i, v in enumerate(t1s) if v]
      t12m = sum(t12)/float(len(t12))
      deltas = [abs(v-t12m)/t12m for v in t12]
      w = [1.0/(v*v) for v in deltas]
      
      t1 = sum([ t1s[j]*w[j] for j in range(m)])/sum(w)
      t2 = sum([ t2s[j]*w[j] for j in range(m)])/sum(w)
      
      if noes:
        noe = sum([ noes[j]*w[j] for j in range(m)])/sum(w)
      else:
        noe = None

      i, ensemble = self.fitT1T2(t1, t2, noe, sf, tmFix=None, teFix=None, s2Fix=None,
                                 tmMin=1e-9, tmMax=100e-9, teMin=1e-12, teMax=1e-10,
                                 rexFix=0.0)
      ensemble.sort()
      score, s2, te0, tm0, rex, t1t, t2t, noet = ensemble[0]
 
      data = (s2, te0*1e12, tm0*1e9, rex, t1, t1t, t2, t2t, noe or 0.0, noet,  score, i)
      print 'Mean A S2:%5.3f Te:%5.1f Tm:%5.3f Rex:%5.3f T1:%5.3f %5.3f T2:%5.3f %5.3f NOE:%5.3f %5.3f %e %6d' % data
      
      rexCheck = 999 # 1.40 * t1/t2
       
      # Prior is mean, then region 
   
      for j in jj:
        t1 = t1Values[j]
        t2 = t2Values[j]
        noe = noeValues[j]
        if t1 is None:
          continue
         
        residue = residues[j]
        print '%3d%s' %  (residue.seqCode, residue.ccpCode),
        
        i, ensemble = self.fitT1T2(t1, t2, noe, sf, tmFix=tm0, teFix=None, s2Fix=None,
                                   tmMin=tm0*0.1, tmMax=tm0*5, teMin=te0/100, teMax=te0*20,
                                   rexFix=0.0, rexMax=15.0)
        ensemble.sort()
        score, s2, te, tm, rex, t1t, t2t, noet = ensemble[0]
        
        if s2 > 0.995:
          i, ensemble = self.fitT1T2(t1, t2, noe, sf, tmFix=tm0, teFix=None, s2Fix=None,
                                     teMin=te/10, teMax=te*10,
                                     rexFix=None, rexMax=15.0)
          ensemble.sort()
          score, s2, te, tm, rex, t1t, t2t, noet = ensemble[0]
         
          
        teBest[j] = te
        s2Best[j] = s2
        rexBest[j] = rex
 
        data = (s2, te*1e12, tm*1e9, rex, t1, t1t, t2, t2t, noe or 0.0, noet, score, i)
        print 'S2:%5.3f Te:%5.1f Tm:%5.3f Rex:%5.3f T1:%5.3f %5.3f T2:%5.3f %5.3f NOE:%5.3f %5.3f %e %6d' % data

      dataSet1 = []
      dataSet2 = []
      dataSet3 = []
      for j in jj:
        residue = residues[j]
        resonance = residueResonances.get(residue)
        
        if not resonance:
          continue
        
        dataSet1.append((residue.seqCode, s2Best[j]))
        dataSet2.append((residue.seqCode, teBest[j]*1e9))
        dataSet3.append((residue.seqCode, rexBest[j]))
        
      self.s2Graph.update([dataSet1,])
      self.teGraph.update([dataSet2,])
      self.rexGraph.update([dataSet3,])
      
      self.tabbedFrame.select(3)

  def fitT1T2(self, t1, t2, noe, sf, tmFix=None, teFix=None, s2Fix=None,
              tmMin=1e-9, tmMax=100e-9, teMin=1e-12, teMax=1e-9,
              rexFix=None, rexMax=15.0, niter=10000):
    
    # Could have multiple sf
    
    rNH = 1.015
    csaN = 160*1e-6 # 160 ppm
    omegaH = sf * 2 * PI * 1e6 # Rad/s
    omegaN = omegaH * GAMMA_N/GAMMA_H
    gammaHN = GAMMA_H/GAMMA_N
     
    A = REDUCED_PERM_VACUUM * REDUCED_PLANK * GAMMA_N * GAMMA_H * 1e30 # Cubic Angstrom adjust
    A /= rNH**3.0
    A = A*A/4.0
    C = omegaN * omegaN * csaN * csaN 
    C /= 3.0
    
    # Init params
    if s2Fix is None:
      s2Start = [x*0.05 for x in range(1,20)]
    else:
      s2Start = [s2Fix,]
    
    if teFix is None:
      teStart = [x*1e-12 for x in [10,30,70,100,300,700,1000]]
    else:
      teStart = [teFix,]
    
    if tmFix is None:
      tmStart = [x*1e-9 for x in range(1,30)]
    else:
      tmStart = [tmFix,]
    
    if rexFix is None:
      rexStart = [float(x) for x in range(int(rexMax))]
    else:
      rexStart = [rexFix,]
    
    # Init ensemble of solutions
    ensemble = []
    for s2 in s2Start:
      for te in teStart:
        for tm in tmStart:
          for rex in rexStart:
             ensemble.append((None, s2, te, tm, rex))
   
    
    # Init scores
    for k, (score, s2, te, tm, rex) in enumerate(ensemble):
      jH   = getSpectralDensity(s2, tm, te, omegaH)
      jN   = getSpectralDensity(s2, tm, te, omegaN)
      jHpN = getSpectralDensity(s2, tm, te, omegaH+omegaN)
      jHmN = getSpectralDensity(s2, tm, te, omegaH-omegaN)
      j0   = getSpectralDensity(s2, tm, te, 0.0)
 
      r1 = A*( (3*jN) + (6*jHpN) + jHmN ) + C*jN
      r2 = 0.5*A*( (4*j0) + (3*jN) + (6*jHpN) + (6*jH) + jHmN ) + C*( 2*j0/3.0 + 0.5*jN ) + rex
 
      t1p = 1.0/r1
      t2p = 1.0/r2
 
 
      d1 = (t1p-t1)/t1
      d2 = (t2p-t2)/t2
 
      score = (d1*d1) + (d2*d2)
      
      if noe is None:
        noep = 0.0
        
      else:
        noep = 1.0 + ( A * gammaHN * t1 * ((6*jHpN)-jHmN) )
        dn = (noep-noe)/2.0
        score += (dn*dn) 
      
      ensemble[k] = (score, s2, te, tm, rex, t1p, t2p, noep)
      
      # Matrix
      # 
      # Pred    Jh        
      # R1
      # R2
      # NOE
      #   r = 1.0/rct + 1.0/ict 
      #   t = 1.0/r
      #   j = (s2*rct) / (1.0 + w*w*rct*rct)
      #   j += ((1.0-s2)*t) / (1.0 + w*w*t*t)
      #       
      #   return j*0.4
    
    ensemble.sort()
    ensemble = ensemble[:10]
    ensembleSize = len(ensemble)
         
    bestScore = 1e99
    
    for i in xrange(niter):
 
      f = i/float(niter)
      f = exp(-10.0*f)
      # Mutate
 
      ensemble.sort()
      prevScore, s2, te, tm, rex, t1p, t2p, noep = ensemble[-1] #Biggest is worst
 
      if ensemble[0][0] < 1e-10:
        break
 
      if not s2Fix:
        #d = ((random() + 0.618 - 1.0) * f) + 1.0
        d = ((random() - 0.382) * f) + 1.0
        s2 = max(0.0, min(1.0, s2*d))
 
      if not tmFix:
        d = ((random() - 0.382) * f) + 1.0
        tm = max(tmMin, min(tmMax, tm*d))
      
      if not teFix:
        d = ((random() - 0.382) * f) + 1.0 
        te = max(teMin, min(teMax, te*d))

      d = ((random() - 0.382) * f) + 1.0 
      rex = max(0.0, min(rexMax, rex*d))
 
      jH   = getSpectralDensity(s2, tm, te, omegaH)
      jN   = getSpectralDensity(s2, tm, te, omegaN)
      jHpN = getSpectralDensity(s2, tm, te, omegaH+omegaN)
      jHmN = getSpectralDensity(s2, tm, te, omegaH-omegaN)
      j0   = getSpectralDensity(s2, tm, te, 0.0)

      r1 = A*( (3*jN) + (6*jHpN) + jHmN ) + C*jN
      r2 = 0.5*A*( (4*j0) + (3*jN) + (6*jHpN) + (6*jH) + jHmN ) + C*( 2*j0/3.0 + 0.5*jN ) + rex
 
      t1p = 1.0/r1
      t2p = 1.0/r2
 
      d1 = (t1p-t1)/t1
      d2 = (t2p-t2)/t2
 
      score = (d1*d1) + (d2*d2)
      if noe is None:
        noep = 0.0
      else:
        noep = 1.0 + ( A * gammaHN * t1 * ((6*jHpN)-jHmN) )
        dn = (noep-noe)/2.0
        score += (dn*dn) 
      
      ratio = exp(prevScore-score)
                      
      if ratio > 1.0: # random():
        ensemble[-1] = (score, s2, te, tm, rex, t1p, t2p, noep)
      else:
        k = randint(0,ensembleSize-1)
        score, s2, te, tm, rex, t1p, t2p, noep = ensemble[k]
        ensemble[-1] = (score, s2, te, tm, rex, t1p, t2p, noep)
    
      
      if score < bestScore:
        bestScore = score
    
    #print bestScore, ', '.join(['%.3e' % x[0] for x in ensemble])
        
    return i, ensemble
Beispiel #24
0
class EditFitGraphPopup(BasePopup):
    """
  **Analyse Function Curve Fitting to Peak Series Data**
  
  This popup is used to display the fit of a curve, of the displayed equation
  type, to data that has been extracted for a group of spectrum peaks from an
  NMR series. Precisely which kind of data is being fitted depends on the parent
  tool that this popup window was launched from. For example, for the `Follow
  Intensity Changes`_ tool the displayed graph is of a time or frequency value
  on the "X" axis (e.g. T1) verses peak intensity. For the `Follow Shift
  Changes`_ system the plot is for the parameters of the experiment titration on
  the "X" axis (e.g concentration) verses chemical shift distance.

  The upper graph shows the peak data that was used; the blue points, and the
  points of the fitted theoretical curve; red points. The lower table lists the
  data points for all of the peaks in the group, to which the data relates.
  There will be one peak for each row of the table, and hence point on the "X"
  axis. For each data point in the table the corresponding peak from which the
  data was extracted may be located with the "Follow in window" option, using
  the stated spectrum window and making marker lines as desired. Alternatively,
  the peak may be viewed in a table with [Show Peak]

  In general operation this system is used to check how well the selected
  function curve fits the peak data. The data that is displayed comes from the
  analysis tool that launched this popup. Any outliers may be removed using
  [Remove Point] (only with good reason) or the peaks themselves may be
  corrected if something has gone awry. Given that the display is launched from
  the selection of a specific group of peaks from a popup like `Follow Shift
  Changes`_  or `Follow Intensity Changes`_ and there are usually several peak
  groups that need to be analysed, the [Previous Set] and [Next Set] buttons can
  be used to quickly jump to the next peak group and see the next curve in the
  analysis results.

  .. _`Follow Intensity Changes`: CalcRatesPopup.html
  .. _`Follow Shift Changes`: FollowShiftChangesPopup.html

  """
    def __init__(self,
                 parent,
                 dataFitting,
                 getXYfunction,
                 updateFunction,
                 xLabel,
                 yLabel,
                 showObjectFunction=None,
                 nextSetFunction=None,
                 prevSetFunction=None,
                 graphTitle='',
                 **kw):

        self.guiParent = parent
        self.getXYfunction = getXYfunction
        self.updateFunction = updateFunction
        self.nextSetFunction = nextSetFunction
        self.prevSetFunction = prevSetFunction
        self.dataFitting = dataFitting
        self.object = None
        self.xLabel = xLabel
        self.yLabel = yLabel
        self.x = []
        self.y = []
        self.yFit = []
        self.params = ()
        self.chiSq = 0
        self.method = dataFitting.fitFunction
        self.waiting = False
        self.noiseLevel = dataFitting.noiseLevel
        self.graphTitle = graphTitle
        self.windowPane = None
        self.mark = None

        BasePopup.__init__(self, parent=parent, title='Fit Graph', **kw)
        parent.protocol("WM_DELETE_WINDOW", self.close)

    def body(self, guiFrame):

        guiFrame.grid_columnconfigure(0, weight=1)
        row = 0

        self.scrolledGraph = ScrolledGraph(guiFrame,
                                           width=400,
                                           height=300,
                                           symbolSize=5,
                                           symbols=['square', 'circle'],
                                           dataColors=['#000080', '#800000'],
                                           lineWidths=[0, 1],
                                           grid=(row, 0))

        #self.scrolledGraph.setZoom(0.7)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Fitting Function:', grid=(0, 0))

        tipText = 'Selects which form of function to fit to the experimental data'
        self.methodPulldown = PulldownList(frame,
                                           self.changeMethod,
                                           grid=(0, 1),
                                           tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        tipText = 'The effective equation of the final fitted graph, incorporating all parameters'
        self.equationLabel = Label(frame,
                                   text='Equation:',
                                   grid=(0, 0),
                                   tipText=tipText)

        tipText = 'The error in the fit of the selected parameterised function to the experimental data'
        self.errorLabel = Label(frame,
                                text='Fit Error:',
                                grid=(0, 1),
                                tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Include x origin?:', grid=(0, 0))

        tipText = 'Whether to include the x=0 point in the drawing'
        self.xOriginSelect = CheckButton(frame,
                                         callback=self.draw,
                                         grid=(0, 1),
                                         selected=False,
                                         tipText=tipText)

        label = Label(frame, text='Include y origin?:', grid=(0, 2))

        tipText = 'Whether to include the y=0 point in the drawing'
        self.yOriginSelect = CheckButton(frame,
                                         callback=self.draw,
                                         grid=(0, 3),
                                         selected=False,
                                         tipText=tipText)

        label = Label(frame, text='Include y error?:', grid=(0, 4))

        tipText = 'Whether to include the y error bars in the drawing (if these exist)'
        self.yErrorSelect = CheckButton(frame,
                                        callback=self.draw,
                                        grid=(0, 5),
                                        selected=False,
                                        tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0), sticky='ew')

        label = Label(frame, text='Navigation Window:', grid=(0, 0))

        tipText = 'Selects which spectrum window will be used for navigating to peak positions'
        self.windowPanePulldown = PulldownList(frame,
                                               self.changeWindow,
                                               grid=(0, 1),
                                               tipText=tipText)

        label = Label(frame, text='Follow in window?:', grid=(0, 2))

        tipText = 'Whether to navigate to the position of the reference peak (for the group), in the selected window'
        self.followSelect = CheckButton(frame,
                                        callback=self.windowPaneNavigate,
                                        grid=(0, 3),
                                        selected=False,
                                        tipText=tipText)

        label = Label(frame, text='Mark Ref Peak?:', grid=(0, 4))

        tipText = 'Whether to put a multi-dimensional cross-mark through the reference peak position, so it can be identified in spectra'
        self.markSelect = CheckButton(frame,
                                      callback=None,
                                      tipText=tipText,
                                      grid=(0, 5),
                                      selected=False)

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)
        tipTexts = [
            'The number of the data point, in order of increasing X-axis value',
            'For each point, the value of the parameter which is varied in the NMR series, e.g. T1, temperature, concentration etc.',
            'For each point, the experimental value being fitted, e.g. peak intensity of chemical shift distance',
            'The value of the best-fit function at the X-axis location',
            'The difference between the experimental (Y-axis) value and the fitted value',
            'The error in the experimental (Y-axis) value'
        ]
        headingList = ['Point', 'x', 'y', 'Fitted y', u'\u0394', 'y error']
        self.scrolledMatrix = ScrolledMatrix(guiFrame,
                                             headingList=headingList,
                                             callback=self.selectObject,
                                             tipTexts=tipTexts,
                                             grid=(row, 0))

        row += 1
        tipTexts = [
            'Remove the selected data point, optionally removing the underlying peak',
            'Show a table of spectrum peaks that correspond to the selected data point'
        ]
        texts = ['Remove Point', 'Show Peak']
        commands = [self.removePoint, self.showObject]

        if self.prevSetFunction:
            texts.append('Previous Set')
            tipTexts.append(
                'Move to the previous set of fitted values; the next group of peaks, often corresponding to a different residue or resonance'
            )
            commands.append(self.prevSet)

        if self.nextSetFunction:
            tipTexts.append(
                'Move to the next set of fitted values; the next group of peaks, often corresponding to a different residue or resonance'
            )
            texts.append('Next Set')
            commands.append(self.nextSet)

        bottomButtons = UtilityButtonList(guiFrame,
                                          texts=texts,
                                          commands=commands,
                                          helpUrl=self.help_url,
                                          tipTexts=tipTexts,
                                          grid=(row, 0),
                                          doClone=False)
        self.removeButton = bottomButtons.buttons[0]

        for func in ('__init__', 'delete', 'setName'):
            self.registerNotify(self.updateWindows,
                                'ccpnmr.Analysis.SpectrumWindow', func)

        self.update()

    def destroy(self):

        for func in ('__init__', 'delete', 'setName'):
            self.unregisterNotify(self.updateWindows,
                                  'ccpnmr.Analysis.SpectrumWindow', func)

        BasePopup.destroy(self)

    def nextSet(self):

        if self.nextSetFunction:
            self.nextSetFunction()
            self.windowPaneNavigate()

    def prevSet(self):

        if self.prevSetFunction:
            self.prevSetFunction()
            self.windowPaneNavigate()

    def windowPaneNavigate(self, event=None):

        if self.followSelect.get() and self.dataFitting:
            peaks = self.dataFitting.objects
            if self.windowPane and peaks:
                peak = peaks[int(len(peaks) / 2)]

                windowFrame = self.windowPane.getWindowFrame()
                windowFrame.gotoPeak(peak)

                if self.markSelect.get():
                    if self.mark and not self.mark.isDeleted:
                        self.mark.delete()

                    self.mark = createPeakMark(self.dataFitting.refObject)

    def getWindows(self):

        peaks = self.scrolledMatrix.objectList

        windowPanes = []
        if peaks:
            peak = peaks[0]
            project = peak.root
            spectrum = peak.peakList.dataSource
            tryWindows = getActiveWindows(project)
            for window in tryWindows:
                for windowPane in window.sortedSpectrumWindowPanes():
                    if isSpectrumInWindowPane(windowPane, spectrum):
                        windowPanes.append(windowPane)

        return windowPanes

    def changeWindow(self, windowPane):

        if windowPane is not self.windowPane:
            self.windowPane = windowPane
            self.windowPaneNavigate()

    def updateWindows(self, window=None):

        windowPanes = self.getWindows()
        index = -1
        names = [getWindowPaneName(wp) for wp in windowPanes]
        windowPane = self.windowPane

        if windowPanes:
            if windowPane not in windowPanes:
                windowPane = windowPanes[0]

            index = windowPanes.index(windowPane)

        if windowPane is not self.windowPane:
            self.windowPane = windowPane
            self.windowPaneNavigate()

        self.windowPanePulldown.setup(names, windowPanes, index)

    def showObject(self):

        if self.object and (self.object.className == 'Peak'):
            peaks = [self.object]
            self.guiParent.guiParent.viewPeaks(peaks)

    def close(self):

        BasePopup.close(self)

    def changeMethod(self, index):

        if self.dataFitting:
            self.method = index
            self.dataFitting.fitFunction = self.method

        self.updateAfter()

    def updateMethods(self, *opt):

        n = len(METHOD_NAMES)
        if self.method >= n:
            self.method = 1

        self.methodPulldown.setup(METHOD_NAMES, range(n), self.method)

    def selectObject(self, object, row, col):

        if object:
            self.object = object
            self.updateButtons()

    def removePoint(self):

        if self.object and (len(self.dataFitting.objects) > 2):
            self.dataFitting.objects.remove(self.object)
            if showYesNo('Query',
                         'Delete the corresponding %s?' %
                         (self.object.className),
                         parent=self):
                self.object.delete()
            self.updateAfter()

    def draw(self, *junk):

        title = '%s Function fit %s' % (self.graphTitle,
                                        METHOD_NAMES[self.method])
        dataSet1 = []
        dataSet2 = []
        useErr = self.yErrorSelect.isSelected()
        if not useErr:
            useErr = None
        for i in range(len(self.scrolledMatrix.textMatrix)):
            row = self.scrolledMatrix.textMatrix[i]
            x = row[1]
            y = row[2]
            y2 = row[3]
            err = useErr and row[5]
            dataSet1.append([x, y, err])
            dataSet2.append([x, y2])

        dataSet1.sort()
        dataSet2.sort()

        if dataSet1 and dataSet2:
            drawOriginX = self.xOriginSelect.isSelected()
            drawOriginY = self.yOriginSelect.isSelected()
            self.scrolledGraph.update(dataSets=[dataSet1, dataSet2],
                                      xLabel=self.xLabel,
                                      yLabel=self.yLabel,
                                      title=title,
                                      drawOriginX=drawOriginX,
                                      drawOriginY=drawOriginY)
            self.scrolledGraph.draw()

    def updateAfter(self, *object):

        if self.waiting:
            return
        else:
            self.waiting = True
            self.after_idle(self.update)

    def update(self,
               dataFitting=None,
               xLabel=None,
               yLabel=None,
               graphTitle=None,
               force=False):

        if (not force) and dataFitting and (self.dataFitting is dataFitting):
            if (self.method, self.xLabel, self.yLabel, self.noiseLevel) == \
               (self.dataFitting.fitFunction, xLabel, yLabel, self.dataFitting.noiseLevel):
                self.waiting = False
                return

        if dataFitting:
            self.dataFitting = dataFitting

        self.xLabel = xLabel or self.xLabel
        self.yLabel = yLabel or self.yLabel
        self.graphTitle = graphTitle or self.graphTitle

        if not self.dataFitting:
            self.waiting = False
            return
        else:
            dataFitting = self.dataFitting
            dataFitting = self.getXYfunction(dataFitting)
            if dataFitting.fitFunction is not None:
                self.method = dataFitting.fitFunction
            self.noiseLevel = dataFitting.noiseLevel or self.noiseLevel
        self.updateMethods()

        isFitted = dataFitting.fit()

        textMatrix = []
        objectList = []

        if isFitted and self.method:
            methodInfo = getFitMethodInfo()[self.method - 1]
            textFormat, indices = methodInfo[2]
            textParams = [dataFitting.parameters[i] or 0 for i in indices]
            equationText = textFormat % tuple(textParams)
            errorText = '%4f' % dataFitting.fitError

            x = dataFitting.dataX
            y = dataFitting.dataY
            yFit = dataFitting.fittedY
            N = len(x)
            err = hasattr(dataFitting, 'dataErr') and dataFitting.dataErr
            if not err:
                err = None

            # wb104: 10 Mar 2014: not sure why the below was here, it isn't needed
            #if self.method == 10:
            #  x = [sqrt(v) for v in x]

            data = [(x[i], y[i], yFit[i], y[i] - yFit[i],
                     dataFitting.objects[i], err and err[i]) for i in range(N)]
            data.sort()
            for i in range(N):
                xi, yi, yFiti, deltai, object, erri = data[i]
                textMatrix.append([i + 1, xi, yi, yFiti, deltai, erri])
                objectList.append(object)

        else:
            equationText = 'Equation: <No Fit>'
            errorText = '<None>'
            x = dataFitting.dataX
            y = dataFitting.dataY

            for i, x in enumerate(x):
                textMatrix.append([i + 1, x, y[i], None, None, None])
                objectList.append(dataFitting.objects[i])

        self.equationLabel.set('Equation: %s' % equationText)
        self.errorLabel.set('Fit Error: %s' % errorText)
        self.scrolledMatrix.update(textMatrix=textMatrix,
                                   objectList=objectList)

        self.updateWindows()
        self.updateButtons()

        self.draw()

        if self.updateFunction:
            self.updateFunction(dataFitting)

        self.waiting = False

    def updateButtons(self):

        if self.object:
            self.removeButton.enable()
        else:
            self.removeButton.disable()
class AnnealingSettingsTab(object):
    '''This class describes the tab in the GUI where the user
       can change setting that govern the monte carlo / annleaing
       procedure. This also includes which information from the ccpn
       analysis project is used and which information is
       ignored. This includes:
           * present sequential assignments
           * tentative assignments
           * amino acid type information
           * whether to include untyped spin systems
           * assignments to peak dimensions
       ALso the chain can be selected here.
       Furthermore the user can set the temperature
       regime of the annealing, the amount of times the procedure
       is repeated to obtain statistics. The fraction of peaks
       that is left out in each run to diversify the results,
       the treshhold score for amino acid typing and the treshhold
       collabelling for a peak to be expected.
    '''

    def __init__(self, parent, frame):
        '''Init. args: parent: the guiElement that this
                               tab is part of.
                       frame:  the frame this part of the
                               GUI lives in.
        '''

        self.guiParent = parent
        self.frame = frame
        self.project = parent.project
        self.nmrProject = parent.nmrProject

        self.minIsoFrac = 0.1
        self.leavePeaksOutFraction = 0.0
        self.minTypeScore = 1.0
        self.chain = None
        self.amountOfRepeats = 10
        self.amountOfSteps = 10000
        self.acceptanceConstantList = [0.0, 0.01, 0.015, 0.022,
                                       0.033, 0.050, 0.075, 0.113,
                                       0.170, 0.256, 0.384, 0.576,
                                       0.864, 1.297, 1.946, 2.919,
                                       4.378, 6.568, 9.852, 14.77,
                                       22.16, 33.25]
        self.energyDataSets = [[]]
        self.residues = []
        self.body()

    def body(self):
        '''describes the body of this tab. It bascically consists
           of some field to fill out for the user at the top and
           a ScrolledGraph that shows the progess of the annealing
           procedure a the bottom.
        '''

        frame = self.frame

        # frame.expandGrid(13,0)
        frame.expandGrid(15, 1)
        row = 0

        text = 'Calculate Assignment Suggestions'
        command = self.runCalculations
        self.startButton = Button(frame, command=command, text=text)
        self.startButton.grid(row=row, column=0, sticky='nsew', columnspan=2)

        row += 1

        Label(frame, text='Amount of runs: ', grid=(row, 0))
        tipText = 'The amount of times the whole optimization procedure is performed, each result is safed'
        self.repeatEntry = IntEntry(frame, grid=(row, 1), width=7, text=10,
                                    returnCallback=self.updateRepeatEntry,
                                    tipText=tipText, sticky='nsew')
        self.repeatEntry.bind('<Leave>', self.updateRepeatEntry, '+')

        row += 1

        Label(frame, text='Temperature regime: ', grid=(row, 0))
        tipText = 'This list of numbers govern the temperature steps during the annealing, every number represents 1/(kb*t), where kb is the Boltzmann constant and t the temperature of one step.'
        self.tempEntry = Entry(frame, text=map(str, self.acceptanceConstantList), width=64,
                               grid=(row, 1), isArray=True, returnCallback=self.updateAcceptanceConstantList,
                               tipText=tipText, sticky='nsew')

        row += 1

        Label(frame, text='Amount of attempts per temperature:', grid=(row, 0))
        tipText = 'The amount of attempts to switch the position of two spinsystems in the sequence are performed for each temperature point'
        self.NAStepEntry = IntEntry(frame, grid=(row, 1), width=7, text=10000,
                                    returnCallback=self.updateStepEntry,
                                    tipText=tipText, sticky='nsew')
        self.NAStepEntry.bind('<Leave>', self.updateStepEntry, '+')

        row += 1

        Label(frame, text='Fraction of peaks to leave out:', grid=(row, 0))
        tipText = 'In each run a fraction of the peaks can be left out of the optimization, thereby increasing the variability in the outcome and reducing false negatives. In each run this will be different randomly chosen sub-set of all peaks. 0.1 (10%) can be a good value.'
        self.leaveOutPeaksEntry = FloatEntry(frame, grid=(row, 1), width=7, text=0.0,
                                             returnCallback=self.updateLeavePeaksOutEntry,
                                             tipText=tipText, sticky='nsew')
        self.leaveOutPeaksEntry.bind(
            '<Leave>', self.updateLeavePeaksOutEntry, '+')

        row += 1

        Label(frame, text='Minmal amino acid typing score:', grid=(row, 0))
        tipText = 'If automatic amino acid typing is selected, a cut-off value has to set. Every amino acid type that scores higher than the cut-off is taken as a possible type. This is the same score as can be found under resonance --> spin systems --> predict type. Value should be between 0 and 100'
        self.minTypeScoreEntry = FloatEntry(frame, grid=(row, 1), width=7, text=1.0,
                                            returnCallback=self.updateMinTypeScoreEntry,
                                            tipText=tipText, sticky='nsew')
        self.minTypeScoreEntry.bind(
            '<Leave>', self.updateMinTypeScoreEntry, '+')

        row += 1

        Label(frame, text='Minimal colabelling fraction:', grid=(row, 0))
        tipText = 'The minimal amount of colabelling the different nuclei should have in order to still give rise to a peak.'
        self.minLabelEntry = FloatEntry(frame, grid=(row, 1), width=7, text=0.1,
                                        returnCallback=self.updateMinLabelEntry,
                                        tipText=tipText, sticky='nsew')
        self.minLabelEntry.bind('<Leave>', self.updateMinLabelEntry, '+')

        row += 1

        Label(frame, text='Use sequential assignments:', grid=(row, 0))
        tipText = 'When this option is select the present sequential assignments will be kept in place'
        self.useAssignmentsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use tentative assignments:', grid=(row, 0))
        tipText = 'If a spin system has tentative assignments this can be used to narrow down the amount of possible sequential assignments.'
        self.useTentativeCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use amino acid types:', grid=(row, 0))
        tipText = 'Use amino acid types of the spin systems. If this option is not checked the spin systems are re-typed, only resonance names and frequencies are used'
        self.useTypeCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Include untyped spin systems:', grid=(row, 0))
        tipText = 'Also include spin system that have no type information. Amino acid typing will be done on the fly.'
        self.useAlsoUntypedSpinSystemsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Use dimensional assignments:', grid=(row, 0))
        tipText = 'If one or more dimensions of a peak is already assigned, assume that this assignment is the only option. If not the check the program will consider all possibilities for the assignment of the dimension.'
        self.useDimensionalAssignmentsCheck = CheckButton(
            frame, selected=True, tipText=tipText, grid=(row, 1))

        row += 1

        Label(frame, text='Chain:', grid=(row, 0))
        self.molPulldown = PulldownList(
            frame, callback=self.changeMolecule, grid=(row, 1))
        self.updateChains()

        row += 1

        Label(frame, text='Residue ranges: ', grid=(row, 0))
        tipText = 'Which residues should be included. Example: "10-35, 62-100, 130".'
        self.residueRangeEntry = Entry(frame, text=None, width=64,
                                       grid=(row, 1), isArray=True, returnCallback=self.updateResidueRanges,
                                       tipText=tipText, sticky='nsew')
        self.updateResidueRanges(fromChain=True)

        row += 1

        self.energyPlot = ScrolledGraph(frame, symbolSize=2, width=600,
                                        height=200, title='Annealing',
                                        xLabel='temperature step', yLabel='energy')
        self.energyPlot.grid(row=row, column=0, columnspan=2, sticky='nsew')

    def runCalculations(self):
        '''Run all calculations. Also triggers the disabling of
           some buttons and fields.
        '''

        self.startButton.disable()
        self.disableIllegalButtonsAfterPrecalculations()
        self.guiParent.connector.runAllCalculations()
        self.startButton.configure(text='More runs')
        self.startButton.enable()

    def disableIllegalButtonsAfterPrecalculations(self):
        '''Disable buttons and field the user can not alter
           any longer after the model is set up and the
           'pre-calculations' have finished.
           This is done because this part of the calculation
           should only be run once. All settings that would
           be changed after this point will not have any influence.
        '''

        illegalButtons = [self.minTypeScoreEntry, self.minLabelEntry,
                          self.useAlsoUntypedSpinSystemsCheck, self.useAssignmentsCheck,
                          self.useTypeCheck, self.useDimensionalAssignmentsCheck,
                          self.useTentativeCheck]

        for illegalButton in illegalButtons:
            illegalButton.configure(state='disabled')

        self.molPulldown.disable()

    def getChainName(self, chain):
        '''Get the name for a chain.
               args: chain: ccpn analysis
                            chain object
               returns: chain name
        '''

        return '%s:%s (%s)' % (chain.molSystem.code, chain.code, chain.molecule.molType)

    def getChains(self):
        '''Get all chains present in the project.
               returns: list of ccpn analysis chain objects
        '''
        chains = []
        if self.project:
            for molSystem in self.project.sortedMolSystems():
                for chain in molSystem.sortedChains():
                    if chain.residues:
                        chains.append(chain)

        return chains

    def updateChains(self, *opt):
        '''Updates the list of chains if a new one is added
           to or deleted from the project. Updates the
           pull down list where a chain can be selected.
        '''

        index = 0
        texts = []
        chains = self.getChains()
        chain = self.chain

        if chains:
            if chain not in chains:
                chain = chains[0]

            texts = [self.getChainName(c) for c in chains]
            index = chains.index(chain)

        else:
            chain = None

        self.molPulldown.setup(texts, chains, index)

        if chain is not self.chain:
            self.chain = chain

    def changeMolecule(self, chain):
        '''Select a molecular chain.'''

        if chain is not self.chain:
            self.chain = chain
            self.updateResidueRanges(fromChain=True)

    def updateStepEntry(self, event=None):
        '''Update the value and entry that sets the amount of
           steps per temperature point.
        '''

        value = self.NAStepEntry.get()
        if value == self.amountOfSteps:
            return
        if value < 1:
            self.NAStepEntry.set(1)
            self.amountOfSteps = 1
        else:
            self.amountOfSteps = value
            self.NAStepEntry.set(value)

    def updateRepeatEntry(self, event=None):
        '''Update the value and entry of that sets
           the amount of times the whole annealing
           procedure is repeated in order
           to obtain statistics.
        '''

        value = self.repeatEntry.get()

        if value == self.amountOfRepeats:
            return
        if value < 1:
            self.repeatEntry.set(1)
            self.amountOfRepeats = 1
        else:
            self.amountOfRepeats = value
            self.repeatEntry.set(value)

    def updateMinTypeScoreEntry(self, event=None):
        '''Updates the value and the entry for the
           treshhold value for amino acid typing.
        '''

        value = self.minTypeScoreEntry.get()

        if value == self.minTypeScore:
            return
        if value < 0:
            self.minTypeScoreEntry.set(0.0)
            self.minTypeScore = 0.0
        elif value > 100:
            self.minTypeScoreEntry.set(100.0)
            self.minTypeScore = 100.0
        else:
            self.minTypeScoreEntry.set(value)
            self.minTypeScore = value

    def updateMinLabelEntry(self, event=None):
        '''Updates the minimum colabelling fraction
           for which a peak is expected to be present
           in the spectra.
        '''

        value = self.minLabelEntry.get()

        if value == self.minIsoFrac:
            return
        if value < 0:
            self.minIsoFrac = 0.0
            self.minLabelEntry.set(0.0)
        elif value > 1:
            self.minIsoFrac = 1.0
            self.minLabelEntry.set(1.0)
        else:
            self.minIsoFrac = value
            self.minLabelEntry.set(value)

    def updateLeavePeaksOutEntry(self, event=None):
        '''Updates the value and entry of the fraction
           of peaks that should be left out in each
           run in order to diversify the results.
        '''

        value = self.leaveOutPeaksEntry.get()

        if value == self.leavePeaksOutFraction:
            return
        if value < 0:
            self.leavePeaksOutFraction = 0.0
            self.leaveOutPeaksEntry.set(0.0)
        elif value > 1:
            self.leavePeaksOutFraction = 1.0
            self.leaveOutPeaksEntry.set(1.0)
        else:
            self.leavePeaksOutFraction = value
            self.leaveOutPeaksEntry.set(value)

    def updateAcceptanceConstantList(self, event=None):
        '''Updates the list with constants that are used
           during the monte carlo procedure to decide whether
           a changed is accepted or not.
        '''

        acList = self.tempEntry.get()
        newList = []

        for constant in acList:

            try:

                number = float(constant)
                newList.append(number)

            except ValueError:

                string = constant + \
                    ' in temperature constants is not a number.'

                showWarning('Not A Number', string, parent=self.guiParent)

                return False

        self.acceptanceConstantList = newList

        return True

    def updateResidueRanges(self, event=None, fromChain=False):

        self.residues = set()

        subRanges = self.residueRangeEntry.get()
        if not subRanges or fromChain:
            self.residues = set(self.chain.residues)
            residues = self.chain.sortedResidues()
            text = '{}-{}'.format(residues[0].seqCode, residues[-1].seqCode)
            self.residueRangeEntry.set(text=text)
            return

        for subRange in subRanges:
            indeces = subRange.split('-')
            start = int(indeces[0])
            stop = int(indeces[-1]) + 1
            for seqCode in range(start, stop):
                residue = self.chain.findFirstResidue(seqCode=seqCode)
                if not residue:
                    showWarning('Residue out of range.',
                                'There is no residue at position {}'.format(seqCode),
                                parent=self.guiParent)
                    self.residues = set()
                    return
                self.residues.add(residue)

    def addEnergyPoint(self, energy, time):
        '''Adds a point to the graph that shows the progress
           of the annealling procedure.
               args: energy: the y-value
                     time:   the x-value
        '''

        point = (time, energy * -1)

        # This means one run has finished
        if len(self.energyDataSets[-1]) / (len(self.acceptanceConstantList) + 1):

            self.energyDataSets.append([point])

        else:

            self.energyDataSets[-1].append(point)

        colors = colorSeries
        Ncolors = len(colors)
        NdataSets = len(self.energyDataSets)
        colorList = (NdataSets / Ncolors) * colors + \
            colors[:NdataSets % Ncolors]
        self.energyPlot.update(dataSets=self.energyDataSets,
                               dataColors=colorList)

        # Forcing the graph to draw, eventhough calculations
        # are still running. Only do this with high numbers of
        # steps, otherwise drawing takes longer than annealling.
        if self.amountOfSteps >= 100000:

            self.energyPlot.draw()