Пример #1
0
    def __init__(self,
                 parent,
                 matrix=None,
                 boxSize=8,
                 maxVal=None,
                 title=None,
                 xLabels=[],
                 yLabels=[],
                 borderWidth=0.1,
                 canvasOrigin=None,
                 labelAxes=True,
                 barPlot=False,
                 borderColor='grey',
                 zoom=1.0,
                 *args,
                 **kw):

        ScrolledCanvas.__init__(self, parent, width=250)
        self.font = 'Helvetica 8'
        self.boldFont = 'Helvetica 8 bold'

        self.origin = canvasOrigin or (0, 0)
        self.labelAxes = labelAxes
        self.border = None
        self.indent = 50
        self.matrix = matrix
        self.borderWidth = borderWidth
        self.borderColor = borderColor
        self.zoom = zoom
        self.boxSize = boxSize
        self.maxVal = maxVal
        self.minVal = 0
        if not self.maxVal:
            if self.matrix is not None:
                self.setMatrixMaxVal()
            else:
                self.maxVal = 1.0

        self.hilightedItems = []

        self.barPlot = barPlot
        self.title = title
        self.legend = []
        self.canvasDict = {}
        self.boxes = []
        self.xGrid = []
        self.yGrid = []
        self.xLabels = xLabels or []
        self.yLabels = yLabels or []
        self.xText = None
        self.yText = None
        self.xBg = None
        self.yBg = None
        self.draw()

        self.canvas.bind('<Button-1>', self.mouseClick)
        self.canvas.bind('<Double-1>', self.mouseDoubleClick)
        self.canvas.bind('<Motion>', self.mouseEnter)
        self.canvas.bind('<Enter>', self.mouseEnter)
        self.canvas.bind('<Leave>', self.mouseLeave)
Пример #2
0
    def mouseMotion(self, event):

        if event.state & 1:
            # shift - zoom
            self.removeMenu()

            dx = event.x - self.initialX
            dy = self.initialY - event.y

            if dx == 0 and dy == 0:
                return

            if dy < 0:
                self.zoomOut()
            else:
                self.zoomIn()

        else:
            ScrolledCanvas.mouseScroll(self, event)
Пример #3
0
    def __init__(self,
                 parent,
                 callback=None,
                 rightCallback=None,
                 width=420,
                 height=440,
                 bgColor='#FFFFFF',
                 showCoords=True,
                 xTicks=True,
                 yTicks=True,
                 xLabel=u'\u03A6',
                 yLabel=u'\u03A8',
                 titleText='',
                 nullColor='#FFFFFF',
                 enterCallback=None,
                 leaveCallback=None,
                 defaultPlot=True,
                 *args,
                 **kw):

        self.parent = parent
        ScrolledCanvas.__init__(self,
                                parent,
                                resizeCallback=self.drawCanvas,
                                width=width,
                                height=height)

        self.bitmapDir = joinPath(getTopDirectory(), 'data', 'ccpnmr',
                                  'ramachandranPlot')
        self.canvas.config(bg=bgColor)
        self.rightCallback = rightCallback  # handle for change of chosen quadrant
        self.callback = callback  # handle for estimation selection
        self.enterCallback = enterCallback  # handle for mouse enter an estimation
        self.leaveCallback = leaveCallback  # handle for mouse leave an estimation
        self.defaultPlot = defaultPlot

        self.showCoords = showCoords
        self.xTicks = xTicks
        self.yTicks = yTicks
        self.xLabel = xLabel
        self.yLabel = yLabel

        self.matrix = []  # bin matrix forming the plot
        self.canvasDict = {}  # aaType : a list of color distribution
        self.intensityDict = {}  # aaType : a list of color distribution
        self.currentObjDict = {}  # object : estimation circle on plot
        self.currentCirDict = {}  # circle on plot : object
        self.residueLabels = {}
        self.currentObjects = []
        self.selectedObjects = []  # a list of selected objects

        self.binSize = 10  # 10 degree for each bin
        self.cirTag = "est"  # arbitrary tag of estimation circles
        self.maxInt = 255  # max number of color used
        self.selectColor = "#00C000"  # color of a selected estimation
        self.unselectColor = "#000000"  # color of a unselected estimation
        self.nullColor = nullColor
        self.objectColors = []
        self.titleText = titleText
        self.title = None
        self.phi = None
        self.psi = None
        self.sd1 = None
        self.sd2 = None
        self.phiPsiList = []
        self.labels = []
        self.crosshair = []
        self.plotCoords = []

        self.aminoAcid = None

        self.binWidth = 10  # Arbitrary deafult - reset dynamically
        self.binHeight = 10  # Arbitrary deafult - reset dynamically
        self.cirRadius = 4
        self.axisObjects = []
        self.zoom = 1.0

        # add handle function to mouse events on estimation objects
        self.canvas.bind("<Button-1>", self.circleClick)

        #if self.enterCallback:
        #  self.canvas.tag_bind(self.cirTag, "<Enter>", self.circleEnter, "+")

        #if self.leaveCallback:
        #  self.canvas.tag_bind(self.cirTag, "<Leave>", self.circleLeave, "+")

        self.canvas.bind('<B2-Motion>', self.mouseMotion)
        self.canvas.bind('<Button-4>', self.zoomIn)
        self.canvas.bind('<Button-5>', self.zoomOut)
        self.canvas.bind('<Motion>', self.mouseEnter)
        self.canvas.bind('<Enter>', self.mouseEnter)
        self.canvas.bind('<Leave>', self.mouseLeave)

        # add handle function to double mouse click on Rama plot
        #self.canvas.bind("<Button-3>", self.rightClick)

        self.drawCanvas()
Пример #4
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)  
Пример #5
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)
Пример #6
0
 def mouseButton3(self, event):
   
   self.stop()
   ScrolledCanvas.mouseButton3(self, event)
Пример #7
0
 def removeMenu(self, event=None):
 
   ScrolledCanvas.removeMenu(self, event)
   self.drawStructure()
Пример #8
0
  def __init__(self, parent, model=None, zoom=1.0, resizeCallback=None,
               radiiScale=0.2, bondWidth=2, width=400, height=400, project=None,
               getPrintOption=None, setPrintOption=None, atomCallback=None,
               bondCallback=None, *args, **kw):

    self.project = project
    self.symbolColor = symbolColor

    self.getPrintOption = getPrintOption
    self.setPrintOption = setPrintOption

    ScrolledCanvas.__init__(self, parent, borderwidth=1, width=width, height=height, relief='solid', **kw)

    self.atomicColorDict = {'C':'#404040','N':'#0000A0',
                            'O':'#A00000','H':'#A0A0A0',
                            'P':'#00A000','S':'#A0A000'}

    self.radiiScale = radiiScale
    self.bondWidth  = bondWidth 

    self.yRotation = 0.0
    self.xRotation = 0.0
    self.zoomStep  = 1.0
    self.width     = None
    self.height    = None
    self.initialX  = None
    self.initialY  = None
    self.model     = model
    self.connections = []
    self.anchors     = []
    self.allAtoms    = []
    self.selectedAtoms = set()
    self.atomColors  = {}
    self.cAtomDict = {}
    self.cBondDict = {}
    self.backbone  = set()
    self.bbHighlight = False
    self.seqLabels = True
    self.center    = (width/2.0,height/2.0,0)
    self.view      = [x/zoom for x in (-1,1,-1,1)]
    self.animate = None
    self.atomCallback = atomCallback
    self.bondCallback = bondCallback
    
    self.grid_columnconfigure(0, weight=1)
    self.grid_rowconfigure(0, weight=1)
    
    self.cStructure = None # StructStructure.StructStructure()
    self.cStructureRotate = None
    self.cStructureZoom = None
    self.canvas.config(background='black')

    self.handler = TkHandler.TkHandler(self.canvas)
    self.bind('<Configure>', self.resize)
        
    self.canvas.bind('<Button-1>', self.mouseButton1)
    self.canvas.bind('<Button-2>', self.mouseButton2)
    self.canvas.bind('<Button-3>', self.mouseButton3)
    self.canvas.bind('<Prior>', self.zoomOut)
    self.canvas.bind('<Next>', self.zoomIn)
    if not isWindowsOS:
      self.canvas.bind('<Button-4>', self.zoomIn)
      self.canvas.bind('<Button-5>', self.zoomOut)
    else:
      self.canvas.bind('<MouseWheel>', self.windowsOsZoom)
    self.canvas.bind('<Up>', self.rotateUp)
    self.canvas.bind('<Down>', self.rotateDown)
    self.canvas.bind('<Left>', self.rotateLeft)
    self.canvas.bind('<Right>', self.rotateRight)
    self.canvas.bind('<Control-Up>', lambda e: self.translate(0,6))
    self.canvas.bind('<Control-Down>', lambda e: self.translate(0,-6))
    self.canvas.bind('<Control-Left>', lambda e: self.translate(-6,0))
    self.canvas.bind('<Control-Right>',lambda e: self.translate(6,0))
    self.canvas.bind('<Leave>', self.stop)
    self.canvas.bind('<Enter>', self.enter)
    self.canvas.bind('<ButtonRelease-1>',self.mouseButtonRelease1)
    self.canvas.bind('<ButtonRelease-2>',self.mouseButtonRelease2)
    self.canvas.bind('<B2-Motion>', self.mouseMotion)
    self.bind('<Configure>', self.resize)
    self.bind('<Expose>', self.expose)
    self.configMenu()
Пример #9
0
    def __init__(self,
                 parent,
                 dataSets=None,
                 title=None,
                 width=650,
                 height=400,
                 zoom=1.0,
                 xLabels=None,
                 symbolSize=5,
                 xLabel=None,
                 yLabel=None,
                 dataNames=None,
                 showCoords=True,
                 xTicks=True,
                 yTicks=True,
                 yRange=None,
                 xLog=False,
                 yLog=False,
                 reverseX=False,
                 relief='sunken',
                 bgColor='white',
                 mgColor='grey90',
                 fgColor='black',
                 symbols=None,
                 canvasOrigin=(0, 0),
                 dataColors=None,
                 lineWidths=None,
                 graphType='line',
                 *args,
                 **kw):

        Frame.__init__(self, parent, *args, **kw)

        if dataSets:
            nSets = len(dataSets)
        else:
            nSets = 0

        defaultColors = [
            '#800000', '#000080', '#008000', '#808000', '#800080', '#008080',
            '#808080', '#000000', '#804000', '#004080'
        ]

        self.canvasOrigin = canvasOrigin

        self.showCoords = showCoords
        self.xTicks = xTicks
        self.yTicks = yTicks
        self.dataSets = dataSets
        self.width = width
        self.height = height
        self.title = title or ''
        self.zoom = zoom or 1.0
        self.xLabel = xLabel or 'x'
        self.yLabel = yLabel or 'y'
        self.xLabels = xLabels or []
        self.xLog = xLog
        self.yLog = yLog
        self.bgColor = bgColor
        self.fgColor = fgColor
        self.mgColor = mgColor
        self.graphType = graphType
        self.symbolSize = symbolSize
        self.reverseX = reverseX
        self.dataColors = dataColors or [
            defaultColors[i % 10] for i in range(nSets)
        ]
        self.dataNames = dataNames or [None] * nSets
        self.lineWidths = lineWidths or [1 for x in range(nSets)]
        self.symbols = symbols or ['circle' for x in range(nSets)]
        self.legend = (1.0, 0.75, {})
        self.yRange = yRange

        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.scrolledCanvas = ScrolledCanvas(self,
                                             borderwidth=2,
                                             relief=relief,
                                             width=width + 100,
                                             height=height + 100)
        self.scrolledCanvas.grid(row=0, column=0, sticky=Tkinter.NSEW)
        self.scrolledCanvas.canvas.config(bg=bgColor)

        self.inMotion = False
        self.canvas = self.scrolledCanvas.canvas
        self.canvasDict = {}
        self.waiting = 0

        self.canvas.bind('<Button-1>', self.mouseClick)
        self.canvas.bind('<B1-Motion>', self.mouseDrag)
        self.canvas.bind('<Motion>', self.mouseEnter)
        self.canvas.bind('<Enter>', self.mouseEnter)
        self.canvas.bind('<Leave>', self.mouseLeave)

        if not isWindowsOS:
            self.canvas.bind('<Button-4>',
                             lambda event: self.setZoom(self.zoom * 1.2))
            self.canvas.bind('<Button-5>',
                             lambda event: self.setZoom(self.zoom / 1.2))
        else:
            self.canvas.bind('<MouseWheel>', self.windowsOsZoom)

        self.configMenu()
        self.draw()
Пример #10
0
class ScrolledGraph(Frame):

    items = []
    crosshair = []
    dataRegion = (0.0, 0.0, 1.0, 1.0)
    font = '-schumacher-clean-bold-r-normal--17-120-100-100-c-0-iso646.1991-irv',

    # category axes
    # log scale
    # fix variable bin width
    # redo ticks esp for category axis

    def __init__(self,
                 parent,
                 dataSets=None,
                 title=None,
                 width=650,
                 height=400,
                 zoom=1.0,
                 xLabels=None,
                 symbolSize=5,
                 xLabel=None,
                 yLabel=None,
                 dataNames=None,
                 showCoords=True,
                 xTicks=True,
                 yTicks=True,
                 yRange=None,
                 xLog=False,
                 yLog=False,
                 reverseX=False,
                 relief='sunken',
                 bgColor='white',
                 mgColor='grey90',
                 fgColor='black',
                 symbols=None,
                 canvasOrigin=(0, 0),
                 dataColors=None,
                 lineWidths=None,
                 graphType='line',
                 *args,
                 **kw):

        Frame.__init__(self, parent, *args, **kw)

        if dataSets:
            nSets = len(dataSets)
        else:
            nSets = 0

        defaultColors = [
            '#800000', '#000080', '#008000', '#808000', '#800080', '#008080',
            '#808080', '#000000', '#804000', '#004080'
        ]

        self.canvasOrigin = canvasOrigin

        self.showCoords = showCoords
        self.xTicks = xTicks
        self.yTicks = yTicks
        self.dataSets = dataSets
        self.width = width
        self.height = height
        self.title = title or ''
        self.zoom = zoom or 1.0
        self.xLabel = xLabel or 'x'
        self.yLabel = yLabel or 'y'
        self.xLabels = xLabels or []
        self.xLog = xLog
        self.yLog = yLog
        self.bgColor = bgColor
        self.fgColor = fgColor
        self.mgColor = mgColor
        self.graphType = graphType
        self.symbolSize = symbolSize
        self.reverseX = reverseX
        self.dataColors = dataColors or [
            defaultColors[i % 10] for i in range(nSets)
        ]
        self.dataNames = dataNames or [None] * nSets
        self.lineWidths = lineWidths or [1 for x in range(nSets)]
        self.symbols = symbols or ['circle' for x in range(nSets)]
        self.legend = (1.0, 0.75, {})
        self.yRange = yRange

        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        self.scrolledCanvas = ScrolledCanvas(self,
                                             borderwidth=2,
                                             relief=relief,
                                             width=width + 100,
                                             height=height + 100)
        self.scrolledCanvas.grid(row=0, column=0, sticky=Tkinter.NSEW)
        self.scrolledCanvas.canvas.config(bg=bgColor)

        self.inMotion = False
        self.canvas = self.scrolledCanvas.canvas
        self.canvasDict = {}
        self.waiting = 0

        self.canvas.bind('<Button-1>', self.mouseClick)
        self.canvas.bind('<B1-Motion>', self.mouseDrag)
        self.canvas.bind('<Motion>', self.mouseEnter)
        self.canvas.bind('<Enter>', self.mouseEnter)
        self.canvas.bind('<Leave>', self.mouseLeave)

        if not isWindowsOS:
            self.canvas.bind('<Button-4>',
                             lambda event: self.setZoom(self.zoom * 1.2))
            self.canvas.bind('<Button-5>',
                             lambda event: self.setZoom(self.zoom / 1.2))
        else:
            self.canvas.bind('<MouseWheel>', self.windowsOsZoom)

        self.configMenu()
        self.draw()

    def configMenu(self):

        zoom_items = [ \
          { 'kind': 'command', 'label': 'In',
          'command': lambda event: self.setZoom(self.zoom*1.2) },
          { 'kind': 'command', 'label': 'Out',
          'command': lambda event: self.setZoom(self.zoom/1.2) },
          { 'kind': 'command', 'label': 'Reset',
          'command': lambda event: self.setZoom(1.0) },
        ]

        type_items = [ \
          { 'kind': 'command', 'label': 'Line',
          'command':lambda event: self.setGraphType('line') },
          { 'kind': 'command', 'label': 'Scatter',
          'command':lambda event: self.setGraphType('scatter') },
          { 'kind': 'command', 'label': 'Bar chart',
          'command':lambda event: self.setGraphType('bar') },
          { 'kind': 'command', 'label': 'Histogram',
          'command':lambda event: self.setGraphType('histogram') },
        ]

        symboltype_items = [ \
          { 'kind': 'command', 'label': 'Circle',
          'command':lambda event: self.setSymbols('circle') },
          { 'kind': 'command', 'label': 'Square',
          'command':lambda event: self.setSymbols('square') },
          { 'kind': 'command', 'label': 'Triangle',
          'command':lambda event: self.setSymbols('triangle') },
        ]

        symbolsize_items = [ \
          { 'kind': 'command', 'label': '+',
          'command':lambda event: self.setSymbolSize( self.symbolSize+1 ) },
          { 'kind': 'command', 'label': '-',
          'command':lambda event: self.setSymbolSize( max(self.symbolSize-1,1) ) },
          { 'kind': 'command', 'label': 'Small',
          'command':lambda event: self.setSymbolSize(3) },
          { 'kind': 'command', 'label': 'Normal',
          'command':lambda event: self.setSymbolSize(5) },
          { 'kind': 'command', 'label': 'Big',
          'command':lambda event: self.setSymbolSize(7) },
        ]

        _items = [ \
          { 'kind': 'command', 'label': '', 'command':'' },
          { 'kind': 'command', 'label': '', 'command':'' },
          { 'kind': 'command', 'label': '', 'command':'' },
        ]

        items = [
            {
                'kind': 'cascade',
                'label': 'Zoom',
                'submenu': zoom_items
            },
            {
                'kind': 'cascade',
                'label': 'Graph type',
                'submenu': type_items
            },
            {
                'kind': 'cascade',
                'label': 'Symbol type',
                'submenu': symboltype_items
            },
            {
                'kind': 'cascade',
                'label': 'Symbol size',
                'submenu': symbolsize_items
            },
            {
                'kind': 'command',
                'label': 'Set Title',
                'command': self.setGraphTitle
            },
            {
                'kind': 'command',
                'label': 'Print to file',
                'command': self.scrolledCanvas.printCanvas
            },
        ]

        self.scrolledCanvas.menu.setMenuItems(items)

    def setGraphTitle(self, event):

        self.title = askString('Text Entry', 'Enter graph title', self.title,
                               self)
        self.drawAfter()

    def mouseClick(self, event):

        self.inMotion = False

    def mouseDrag(self, event):

        self.scrolledCanvas.removeMenu()

        canvas = self.canvas
        x = canvas.canvasx(event.x)
        y = canvas.canvasy(event.y)

        obj = self.canvas.find('closest', x, y)[0]
        inMotion = self.inMotion

        xF, yF, itemDict = self.legend
        if inMotion or itemDict.has_key(obj):
            plotRegion = self.getPlotRegion()

            x1 = plotRegion[0]
            y1 = plotRegion[1]
            rX = plotRegion[2] - x1
            rY = plotRegion[3] - y1

            if inMotion:
                dx, dy = inMotion
            else:
                x0 = x1 + (xF * rX)
                y0 = y1 + (yF * rY)
                dx = x - x0
                dy = y - y0

            self.legend = ((x - dx - x1) / rX, (y - dy - y1) / rY, itemDict)

            for item in itemDict:
                canvas.delete(item)

            self.drawLegend(plotRegion)
            self.inMotion = (dx, dy)

    def mouseEnter(self, event):

        canvas = self.canvas
        cCoords = canvas.coords
        cLine = canvas.create_line
        cText = canvas.create_text

        crosshair = self.crosshair
        canvas.focus_force()
        self.scrolledCanvas.removeMenu()

        x = canvas.canvasx(event.x)
        y = canvas.canvasy(event.y)

        plotRegion = self.getPlotRegion()
        (x0, y0, x1, y1) = plotRegion

        if (x < x0) or (x > x1) or (y < y1) or (y > y0):
            self.mouseLeave()
        else:
            if self.showCoords:
                coordStr = '[ %3.3f, %3.3f ]' % self.getPlotCoords(
                    event, self.dataRegion, plotRegion)
            else:
                coordStr = ''

            if crosshair:
                (itemV, itemH, itemT) = crosshair
                cCoords(itemV, x, y0, x, y1)
                cCoords(itemH, x0, y, x1, y)
                cCoords(itemT, x0 + (0.9 * (x1 - x0)), y0 + y1)
                canvas.itemconfig(itemT, text=coordStr)
            else:
                mgColor = self.mgColor
                itemV = cLine(x, y0, x, y1, fill=mgColor, width=1)
                itemH = cLine(x0, y, x1, y, fill=mgColor, width=1)
                itemT = cText(x0 + (0.9 * (x1 - x0)),
                              y0 + y1,
                              text=coordStr,
                              fill=self.fgColor)
                self.crosshair = (itemV, itemH, itemT)

    def mouseLeave(self, *event):

        if self.crosshair:
            for item in self.crosshair:
                self.canvas.delete(item)

            self.crosshair = []

    def drawAfter(self):

        if not self.waiting:
            self.waiting = 1
            self.after_idle(self.draw)

    def getMinMaxValues(self, dataSets):

        if (not dataSets):
            return [0.0, 1.0, 0.0, 1.0, 1, 1.0, 1.0]

        maxN = len(dataSets[0])
        bigSet = 0
        for i in range(len(dataSets)):
            if (len(dataSets[i]) > maxN):
                maxN = len(dataSets[i])
                bigSet = i

        if (maxN < 1):
            return [0.0, 1.0, 0.0, 1.0, 1, 1.0, 1.0]

        maxX = dataSets[bigSet][0][0] or 0.0
        minX = dataSets[bigSet][0][0] or 0.0
        maxY = dataSets[bigSet][0][1] or 0.0
        minY = dataSets[bigSet][0][1] or 0.0

        minDy = None
        minDx = None

        for i in range(len(dataSets)):
            N = len(dataSets[i])
            for j in range(N):
                x, y, e = dataSets[i][j]

                e = e or 0.0

                if x is not None:
                    if x < minX:
                        minX = x
                    if x > maxX:
                        maxX = x

                    if j + 1 < N:
                        x2 = dataSets[i][j + 1][0]

                        if x2 is not None:
                            dX = dataSets[i][j + 1][0] - x

                            if (minDx is None) or (dX < minDx):
                                minDx = dX

                if y is not None:
                    if y - e < minY:
                        minY = y - e
                    if y + e > maxY:
                        maxY = y + e

                    if j + 1 < N:
                        y2 = dataSets[i][j + 1][1]

                        if y2 is not None:
                            dY = y2 - y

                            if (minDy is None) or (dY < minDy):
                                minDy = dY

        if self.yRange:
            yRange = list(self.yRange)
            yRange.sort()
            yMin, yMax = yRange

        if maxX == minX:
            maxX += 1.0

        if maxY == minY:
            maxY += 1.0

        if not minDx:
            minDx = 1.0

        if not minDy:
            minDy = 1.0

        return [minX, maxX, minY, maxY, maxN, minDx, minDy]

    def checkDataSets(self, dataSets):

        if not dataSets:
            return

        N = len(dataSets)

        validTypes = (type(float()), type(int()))

        for i in range(N):

            c = 0.0
            for j in range(len(dataSets[i])):

                datum = dataSets[i][j]
                (x, y) = datum[:2]

                if len(datum) == 2:
                    e = None
                else:
                    e = datum[2]

                if (not y) and (y != 0):
                    y = None

                if (not x) and (x != 0):
                    x = None

                else:
                    t = type(x)

                    if t not in validTypes:
                        x = c
                        c += 1.0

                dataSets[i][j] = (x, y, e)

            dataSets[i].sort()

        return dataSets

    def getDrawCoords(self, dataSet, dataRegion, plotRegion):

        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)

        coords = []
        for x, y, e in dataSet:

            if (y is not None) and (x is not None):
                x0 = (x - dataRegion[0]) * ppvX
                y0 = (y - dataRegion[1]) * ppvY
                x0 += plotRegion[0]
                y0 += plotRegion[1]

                if e is None:
                    e1 = e2 = None
                else:
                    e0 = e * ppvY
                    e1 = y0 + e0
                    e2 = y0 - e0

                coords.append((x0, y0, e1, e2))

        return coords

    def getPlotCoords(self, event, dataRegion, plotRegion):

        x = self.canvas.canvasx(event.x) - plotRegion[0]
        y = self.canvas.canvasy(event.y) - plotRegion[1]

        deltaXplot = plotRegion[2] - plotRegion[0]
        deltaYplot = plotRegion[3] - plotRegion[1]
        deltaXdata = dataRegion[2] - dataRegion[0]
        deltaYdata = dataRegion[3] - dataRegion[1]

        vppX = deltaXdata / float(deltaXplot)
        vppY = deltaYdata / float(deltaYplot)

        plotX = dataRegion[0] + x * vppX
        plotY = dataRegion[1] + y * vppY

        return (plotX, plotY)

    def getBoxSize(self, plotRegion, numBoxes, numSets=1):

        deltaXplot = plotRegion[2] - plotRegion[0]
        size = deltaXplot / float(numBoxes * numSets)
        return size

    def drawBoxes(self,
                  plotRegion,
                  coords,
                  size,
                  outline='black',
                  fill='grey',
                  setSel=0,
                  numSets=1,
                  graphType='bar'):

        create_rectangle = self.canvas.create_rectangle
        create_line = self.canvas.create_line
        d = size / 2.0

        m = 0.0
        if self.xLabels:
            if graphType == 'bar':
                m = size * (numSets / 2.0)
            else:
                m = d

        d1 = (setSel - ((numSets - 1) / 2.0)) * size

        maxX, minY, minX, maxY = self.dataRegion

        if (minY < 0) and (maxY > 0):
            f = maxY / (maxY - minY)
            y1 = plotRegion[3] + (f * (plotRegion[1] - plotRegion[3]))

        elif (minY < 0) and (maxY < 0):
            y1 = plotRegion[3]

        else:
            y1 = plotRegion[1]

        items = []
        for (x, y0, yU, yL) in coords:
            if graphType == 'bar':
                x0 = x + d1 - d + m
                x1 = x + d1 + d + m
            else:
                x0 = x - d + m
                x1 = x + d + m

            item = create_rectangle(x0, y0, x1, y1, outline=outline, fill=fill)
            items.append(item)

            if yU is not None:
                xm = (x1 + x0) / 2.0
                item = create_line(xm, y0, xm, yU, fill=outline)
                items.append(item)
                item = create_line(x0, yU, x1, yU, fill=outline)
                items.append(item)

            if yL is not None:
                xm = (x1 + x0) / 2.0
                item = create_line(xm, y0, xm, yL, fill=outline)
                items.append(item)
                item = create_line(x0, yL, x1, yL, fill=outline)
                items.append(item)

        return items

    def drawLines(self, coords, outline, lineWidth):

        create_line = self.canvas.create_line
        N = len(coords)
        items = []
        for i in range(N - 1):
            (x0, y0, y0a, y0b) = coords[i]
            (x1, y1, y1a, y1b) = coords[i + 1]
            item = create_line(x0, y0, x1, y1, fill=outline, width=lineWidth)
            items.append(item)

        return items

    def drawSymbols(self,
                    coords,
                    size,
                    lineWidth,
                    shape='circle',
                    outline='black',
                    fill='grey'):

        d = size / 2.0
        d1 = sqrt3over2 * d
        d2 = size / 4.0
        items = []
        create_line = self.canvas.create_line
        if shape == 'triangle':
            create_polygon = self.canvas.create_polygon

            for (x, y, yU, yL) in coords:
                x0 = x
                x1 = x + d1
                x2 = x - d1
                y0 = y - d
                y1 = y + d2

                if yU is not None:
                    item = create_line(x, y, x, yU, fill=outline)
                    items.append(item)
                    item = create_line(x1, yU, x2, yU, fill=outline)
                    items.append(item)

                if yL is not None:
                    item = create_line(x, y, x, yL, fill=outline)
                    items.append(item)
                    item = create_line(x1, yL, x2, yL, fill=outline)
                    items.append(item)

                item = create_polygon(x0,
                                      y0,
                                      x1,
                                      y1,
                                      x2,
                                      y1,
                                      x0,
                                      y0,
                                      outline=outline,
                                      fill=fill,
                                      width=lineWidth)
                items.append(item)

        else:

            if shape == 'square':
                create_rectangle = self.canvas.create_rectangle

                for (x, y, yU, yL) in coords:
                    x0 = x - d
                    x1 = x + d
                    y0 = y - d
                    y1 = y + d

                    if yU is not None:
                        item = create_line(x, y, x, yU, fill=outline)
                        items.append(item)
                        item = create_line(x0, yU, x1, yU, fill=outline)
                        items.append(item)

                    if yL is not None:
                        item = create_line(x, y, x, yL, fill=outline)
                        items.append(item)
                        item = create_line(x0, yL, x1, yL, fill=outline)
                        items.append(item)

                    item = create_rectangle(x0,
                                            y0,
                                            x1,
                                            y1,
                                            outline=outline,
                                            fill=fill,
                                            width=lineWidth)
                    items.append(item)

            else:
                create_oval = self.canvas.create_oval

                for (x, y, yU, yL) in coords:
                    x0 = x - d
                    x1 = x + d
                    y0 = y - d
                    y1 = y + d

                    if yU is not None:
                        item = create_line(x, y, x, yU, fill=outline)
                        items.append(item)
                        item = create_line(x0, yU, x1, yU, fill=outline)
                        items.append(item)

                    if yL is not None:
                        item = create_line(x, y, x, yL, fill=outline)
                        items.append(item)
                        item = create_line(x0, yL, x1, yL, fill=outline)
                        items.append(item)

                    item = create_oval(x0,
                                       y0,
                                       x1,
                                       y1,
                                       outline=outline,
                                       fill=fill,
                                       width=lineWidth)
                    items.append(item)

        return items

    def getPlotRegion(self):

        zoom = self.zoom
        x0, y0 = self.canvasOrigin

        plotRegion = (x0 + 75, y0 + 50 + (self.height * zoom),
                      x0 + 75 + (self.width * zoom), y0 + 50)

        return plotRegion

    def draw(self):

        zoom = self.zoom
        canvas = self.canvas
        canvasDict = self.canvasDict
        dataSets = self.dataSets

        for item in self.items:
            canvas.delete(item)

        self.items = []

        dataSets = self.checkDataSets(dataSets)
        if not dataSets:
            return

        [minX, maxX, minY, maxY, maxN, minDx,
         minDy] = self.getMinMaxValues(dataSets)

        if self.reverseX:
            dataRegion = (maxX, minY, minX, maxY)
        else:
            dataRegion = (minX, minY, maxX, maxY)

        plotRegion = self.getPlotRegion()
        symbolSize = self.symbolSize  # max(1,int(zoom*self.symbolSize))
        self.dataRegion = dataRegion

        diffX = float(maxX - minX) or 1.0
        diffY = float(maxY - minY) or 1.0

        width = self.width * zoom
        height = self.height * zoom
        xpad = 75
        ypad = 50

        binLabels = [''] * (maxN + 1)
        N = float(len(dataSets))
        M = len(dataSets[0])
        step = diffX / maxN
        for n in range(maxN):
            x = minX + (n * step)
            binLabels[n] = '%4.2f' % x

        bins = diffX / min(1.0, minDx)

        if self.graphType == 'bar':
            size = self.getBoxSize(plotRegion, bins, N)
        else:
            size = self.getBoxSize(plotRegion, bins, 1)

        self.items.extend(self.drawAxes(plotRegion, dataRegion, 1))

        i = 0
        for dataSet in dataSets:
            color = self.dataColors[i]
            lineWidth = 1  # max(1,int(self.lineWidths[i]*zoom))
            coords = self.getDrawCoords(dataSet, dataRegion, plotRegion)
            symbol = self.symbols[i]
            if self.graphType == 'line':
                items = self.drawLines(coords, color, lineWidth)
                self.items.extend(items)
                items = self.drawSymbols(coords,
                                         symbolSize,
                                         lineWidth,
                                         shape=symbol,
                                         outline=color,
                                         fill='grey')
                self.items.extend(items)
            elif self.graphType == 'scatter':
                items = self.drawSymbols(coords,
                                         symbolSize,
                                         lineWidth,
                                         shape=symbol,
                                         outline=color,
                                         fill='grey')
                self.items.extend(items)
            else:
                items = self.drawBoxes(plotRegion,
                                       coords,
                                       size,
                                       outline=self.fgColor,
                                       fill=color,
                                       setSel=i,
                                       numSets=N,
                                       graphType=self.graphType)
                self.items.extend(items)
            i += 1

        self.scrolledCanvas.refresh()

        self.waiting = 0

    def windowsOsZoom(self, event):

        delta = event.delta
        if delta > 0:
            self.setZoom(self.zoom * 1.2)
        elif delta < 0:
            self.setZoom(self.zoom / 1.2)

    def setZoom(self, factor=1.0):

        if factor:
            self.zoom = min(20, max(0.25, factor))

        self.drawAfter()

    def setTitle(self, title):

        if title:
            self.title = str(title)
        else:
            self.title = ''
        self.drawAfter()

    def setXLabel(self, label):

        if label:
            self.xLabel = label
        else:
            self.xLabel = ''
        self.drawafter()

    def setYLabel(self, label):

        if label:
            self.yLabel = label
        else:
            self.yLabel = ''
        self.drawafter()

    def setYLog(self, boolean=True):

        self.yLog = boolean
        self.drawAfter()

    def setXLog(self, boolean=True):

        self.xLog = boolean
        self.drawAfter()

    def setDataColors(self, dataColors):

        self.dataColors = []
        for i in range(len(self.dataSets)):
            if i < len(dataColors):
                self.dataColors.append(dataColors[i])
            else:
                self.dataColors.append('black')
        self.drawAfter()

    def setLineWidths(self, widthsList):

        N = len(self.dataSets)
        if not widthsList:
            self.lineWidths = [1 for x in range(N)]

        else:
            self.lineWidths = []
            for i in range(N):
                if i < len(widthsList):
                    self.lineWidths.append(widthsList[i])
                else:
                    self.lineWidths.append(1)

        self.drawAfter()

    def setSymbols(self, symbolName):

        self.symbols = [symbolName for x in range(len(self.dataSets))]
        self.drawAfter()

    def setSymbolSize(self, size):

        self.symbolSize = size
        self.drawAfter()

    def setDataNames(self, names):

        self.dataNames = names
        self.drawAfter()

    def setGraphType(self, graphType):

        if graphType in ('line', 'bar', 'histogram', 'scatter'):
            self.graphType = graphType

        self.drawAfter()

    def update(self,
               dataSets=None,
               dataColors=None,
               lineWidths=None,
               title=None,
               xLabel=None,
               yLabel=None,
               dataNames=None,
               symbols=None):

        if dataSets:
            self.dataSets = dataSets
            self.setLineWidths(lineWidths)

        if dataNames:
            self.dataNames = dataNames

        if symbols:
            self.symbols = symbols

        if title:
            self.title = title

        if xLabel:
            self.xLabel = xLabel

        if yLabel:
            self.yLabel = yLabel

        if dataColors:
            self.setDataColors(dataColors)

        if len(self.dataSets) > len(self.dataColors):
            for i in range(len(self.dataColors), len(self.dataSets)):
                self.dataColors.append('red')
        else:
            self.dataColors = self.dataColors[:len(self.dataSets)]

        if len(self.dataSets) > len(self.symbols):
            for i in range(len(self.symbols), len(self.dataSets)):
                self.symbols.append('circle')
        else:
            self.symbols = self.symbols[:len(self.dataSets)]

        self.drawAfter()

    def drawAxes(self, plotRegion, dataRegion, lineWidth):

        items = []
        (x0, y0, x1, y1) = plotRegion

        outline = self.canvas.create_rectangle(0,
                                               0,
                                               1,
                                               1,
                                               outline=self.bgColor,
                                               width=1)
        background = self.canvas.create_rectangle(x0,
                                                  y0,
                                                  x1,
                                                  y1,
                                                  outline='#FFFFFF',
                                                  fill='#FFFFFF',
                                                  width=lineWidth)

        self.canvas.lower(outline)
        items.append(outline)
        items.extend(self.drawTicks(plotRegion, dataRegion))
        items.append(
            self.canvas.create_line(x0,
                                    y0,
                                    x1,
                                    y0,
                                    fill=self.fgColor,
                                    width=lineWidth))
        items.append(
            self.canvas.create_line(x0,
                                    y0,
                                    x0,
                                    y1,
                                    fill=self.fgColor,
                                    width=lineWidth))
        items.extend(self.drawTitle(plotRegion))
        items.extend(self.drawLegend(plotRegion))

        return items

    def drawTicks(self, plotRegion, dataRegion):

        if not (self.xTicks or self.yTicks):
            return []

        createLine = self.canvas.create_line
        createText = self.canvas.create_text

        deltaXplot = plotRegion[2] - plotRegion[0]
        deltaYplot = plotRegion[3] - plotRegion[1]
        deltaXdata = dataRegion[2] - dataRegion[0]
        deltaYdata = dataRegion[3] - dataRegion[1]

        x0 = plotRegion[0]
        y0 = plotRegion[1]

        x1 = plotRegion[2]
        y1 = plotRegion[3]

        size = 7
        if self.xLabels:
            sizes = [len(x) for x in self.xLabels]
            size = max(sizes)

        item = createText(0, 0, text='A' * size)
        bbox = self.canvas.bbox(item)
        self.canvas.delete(item)

        dy = bbox[3] - bbox[1]
        dx = bbox[2] - bbox[0]

        yClose = 2 * dy
        xClose = dx * 1.5

        items = []

        lineWidth = 1  # max(1,self.zoom)

        # calculate major and minor lines
        # minor lines will be equispaced between major and of a suitable size. 2, 5, 10 target numbers
        # major lines
        # in the data range find the non fractional points - not too close and enough
        # given the plot range we know the delta
        # split the delta into adequately,minimally spaced chunks
        # split the plot range into the same number chunks
        # round up the plot diff to the nearest round point with the accuracy
        # specified by the data delta
        # 100 in 8 chunks => 12.5/chumk round to 10
        # 0.3 in 5 chunks => 0.06/chunk round to 0.05
        # 21 in 7 = 3/chunk round to 2 or 5 or 3
        # 0.16 in 10 = 0.016 per chunk => round to 0.01 or 0.02

        xt = x0 - 10
        yt = y0 + 10

        xs = x0 - 8
        ys = y0 + 8

        ppvX = deltaXplot / float(deltaXdata)
        ppvY = deltaYplot / float(deltaYdata)

        spaceXdata = xClose / ppvX
        spaceYdata = yClose / ppvY

        sciX = '%e' % abs(spaceXdata)
        sciY = '%e' % abs(spaceYdata)

        deciX = int(sciX[-3:])
        deciY = int(sciY[-3:])

        sigDX = int(sciX[0])
        sigDY = int(sciY[0])

        nX = 10.0
        nY = 10.0
        sX = abs(sigDX - nX)
        sY = abs(sigDY - nY)
        for n in (1.0, 2.0, 5.0):

            s = abs(sigDX - n)
            if s < sX:
                sX = s
                nX = n

            s = abs(sigDY - n)
            if s < sY:
                sY = s
                nY = n

        incX = (abs(spaceXdata) / spaceXdata) * nX * 10**(deciX)
        incY = (abs(spaceYdata) / spaceYdata) * -nY * 10**(deciY)

        valX = dataRegion[0] - (dataRegion[0] % incX)
        valY = dataRegion[1] - (dataRegion[1] % incY)

        if self.xTicks:
            for i in range(int(round(deltaXdata / incX)) + 2):

                tickX = round(valX, -deciX)
                x = plotRegion[0] + (tickX - dataRegion[0]) * ppvX
                valX += incX

                if x > plotRegion[2]:
                    continue
                if x < plotRegion[0]:
                    continue

                if self.xLabels and (i < len(self.xLabels)):
                    if self.graphType in ('bar', 'histogram'):
                        mid = (tickX + round(valX, -deciX)) / 2.0
                        x2 = plotRegion[0] + (mid - dataRegion[0]) * ppvX
                    else:
                        x2 = x

                    text = self.xLabels[i]
                    item = createText(x2, yt, text=text, anchor='n')
                else:
                    text = self.formatText(tickX)
                    item = createText(x, yt, text=text, anchor='n')

                items.append(item)
                item = createLine(x,
                                  y0,
                                  x,
                                  ys,
                                  fill=self.mgColor,
                                  width=lineWidth)
                items.append(item)
                item = createLine(x,
                                  y0,
                                  x,
                                  ys,
                                  fill=self.fgColor,
                                  width=lineWidth)
                items.append(item)

        if self.yTicks:
            for i in range(int(round(deltaYdata / incY)) + 2):

                tickY = round(valY, -deciY)
                y = plotRegion[1] + (tickY - dataRegion[1]) * ppvY
                valY += incY

                if y < plotRegion[3]:
                    continue
                if y > plotRegion[1]:
                    continue

                item = createText(xt,
                                  y,
                                  text=self.formatText(tickY),
                                  anchor='e')
                items.append(item)
                item = createLine(x0,
                                  y,
                                  x1,
                                  y,
                                  fill=self.mgColor,
                                  width=lineWidth)
                items.append(item)
                item = createLine(x0,
                                  y,
                                  xs,
                                  y,
                                  fill=self.fgColor,
                                  width=lineWidth)
                items.append(item)

        return items

    def formatText(self, text):

        if type(text) == type(float(1)):
            if text == 0:
                text = '0'
            elif abs(text) > 999999 or abs(text) < 0.01:
                text = '%5.2e' % text
            else:
                text = str(text)
        elif type(text) == type(int(1)):
            text = str(text)
        if text and text[0:1] == '@':
            text = ''

        return text

    def drawLegend(self, plotRegion):

        pad = 2
        drawSymbols = self.drawSymbols
        createText = self.canvas.create_text
        createRect = self.canvas.create_rectangle
        symbolSize = max(5, int(self.zoom * self.symbolSize))
        lineWidth = 1
        graphType = self.graphType
        canvasBbox = self.canvas.bbox
        symbols = self.symbols
        fgColor = self.fgColor
        delete = self.canvas.delete
        x0, y0, x1, y1 = plotRegion
        canvasCoords = self.canvas.coords
        dataColors = self.dataColors
        outline = None
        dX = x1 - x0
        dY = y1 - y0

        fX, fY, itemDict = self.legend

        for item in itemDict:
            delete(item)

        xMax = 0
        items = []
        x = xS = x0 + (fX * dX)
        y = yS = y0 + (fY * dY)
        i = 0
        for dataName in self.dataNames:
            if dataName is not None:
                if outline is None:
                    outline = createRect(0,
                                         0,
                                         0,
                                         0,
                                         fill=self.bgColor,
                                         outline=self.mgColor)

                color = dataColors[i]
                item = createText(x,
                                  y,
                                  text=dataName,
                                  fill=fgColor,
                                  anchor='nw')
                bbox = canvasBbox(item)
                items.append(item)

                h = bbox[3] - bbox[1]
                h2 = h / 2

                canvasCoords(item, x + h + 2, y)
                coordsA = [
                    (x + h2, y + h2, None, None),
                ]

                if bbox[2] + h + 2 > xMax:
                    xMax = bbox[2] + h + 2

                if graphType == 'line':
                    symbol = symbols[i]
                    items0 = drawSymbols(coordsA,
                                         symbolSize,
                                         lineWidth,
                                         shape=symbol,
                                         outline=color,
                                         fill='grey')

                elif graphType == 'scatter':
                    symbol = symbols[i]
                    items0 = drawSymbols(coordsA,
                                         symbolSize,
                                         lineWidth,
                                         shape=symbol,
                                         outline=color,
                                         fill='grey')

                else:
                    symbol = 'square'
                    items0 = drawSymbols(
                        coordsA,
                        h,
                        lineWidth,
                        shape=symbol,
                        outline=fgColor,
                        fill=color,
                    )

                items.extend(items0)
                y += h + pad

            i += 1

        if outline is not None:
            canvasCoords(outline, xS - 4, yS - 4, xMax + 2, y + 2)
            items.append(outline)

            itemDict = {}
            for item in items:
                itemDict[item] = True

        self.legend = fX, fY, itemDict

        return items

    def drawTitle(self, plotRegion):

        (x0, y0, x1, y1) = plotRegion
        createText = self.canvas.create_text
        fgColor = self.fgColor

        item0 = createText((x0 + x1) / 2.0,
                           y1 / 2.0,
                           text=self.title,
                           fill=fgColor,
                           font=self.font)
        item1 = createText((x0 + x1) / 2.0,
                           y0 + y1,
                           text=self.xLabel,
                           fill=fgColor)
        item2 = createText(x0,
                           y1 - 5,
                           text=self.yLabel,
                           fill=fgColor,
                           anchor='se')

        return (item0, item1, item2)
Пример #11
0
class ViewChemicalShiftsPopup(BasePopup):
    """
  **A Table of Chemical Shifts for Export**
  
  This section is designed to make a layout of a table for chemical shifts  on a
  per-residue basis which may them be exported as either PostScript, for
  printing and graphical manipulation, or as plain text for import into other
  software or computer scripts. 

  The user chooses the molecular chain (which sequence) and the shift list to
  use at the top of the popup, together with a few other options that control
  how things are rendered. Then buttons are toggled to select which kinds of
  atom will be displayed in aligned columns; other kinds will simply be listed
  to the right of the columns. Thus for example if the shift list does not
  contain any carbonyl resonances in a protein chain then the user may toggle
  the empty "C" column off.

  Once the desired layout is achieved the user then uses the [Export PostScript]
  or [Export Text] buttons to write the data into a file of the appropriate
  type. The user will be presented wit ha file browser to specify the location
  and the name of the file to be saved. It should be noted that although the
  graphical display in the popup itself is somewhat limited, e.g. the gaps and
  spacing doesn't always look perfect, the PostScript version that is exported
  is significantly neater.

  **Caveats & Tips**

  If you need a chemical shift list represented in a particular format, specific
  for a particular external NMR program then you should use the FormatConverter
  software.

  Chemical shifts may also be exported from any table in Analysis that contains
  such data by clicking the right mouse button over the table and selecting the
  export option. 

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

        self.shiftList = None
        self.font = 'Helvetica 10'
        self.boldFont = 'Helvetica 10 bold'
        self.symbolFont = 'Symbol 8'
        self.smallFont = 'Helvetica 8'
        self.chain = None
        self.textOut = ''
        self.textMatrix = []

        BasePopup.__init__(self,
                           parent=parent,
                           title='Chart : Chemical Shifts Table')

    def body(self, guiFrame):

        row = 0
        frame = Frame(guiFrame, grid=(row, 0))
        frame.expandGrid(None, 6)

        label = Label(frame, text='Chain:', grid=(0, 0))
        tipText = 'Selects which molecular chain to show residues and chemical shift values for'
        self.chainPulldown = PulldownList(frame,
                                          callback=self.changeChain,
                                          grid=(0, 1),
                                          tipText=tipText)

        label = Label(frame, text='  Shift List:', grid=(0, 2))
        tipText = 'Selects which shift list is used to derive the displayed chemical shift values'
        self.shiftListPulldown = PulldownList(frame,
                                              callback=self.changeShiftList,
                                              grid=(0, 3),
                                              tipText=tipText)

        label = Label(frame, text=' List all shifts:', grid=(0, 4))
        tipText = 'Sets whether to display all the chemical shifts for residues or just for the nominated atom types in columns'
        self.otherShiftsSelect = CheckButton(frame,
                                             callback=self.draw,
                                             grid=(0, 5),
                                             tipText=tipText)

        utilButtons = UtilityButtonList(frame,
                                        helpUrl=self.help_url,
                                        grid=(0, 7))

        row += 1
        frame = Frame(guiFrame, grid=(row, 0))
        frame.expandGrid(None, 6)

        label = Label(frame, text=' 1-letter codes:', grid=(0, 0))
        tipText = 'Whether to use 1-letter residue codes in the table, or otherwise Ccp/three-letter codes'
        self.oneLetterSelect = CheckButton(frame,
                                           callback=self.draw,
                                           grid=(0, 1),
                                           selected=False,
                                           tipText=tipText)

        precisions = [0.1, 0.01, 0.001]
        texts = [str(t) for t in precisions]
        label = Label(frame, text='  1H precision:', grid=(0, 2))
        tipText = 'Specifies how many decimal places to use when displaying 1H chemical shift values'
        self.protonPrecisionSelect = PulldownList(frame,
                                                  texts=texts,
                                                  objects=precisions,
                                                  callback=self.draw,
                                                  index=1,
                                                  grid=(0, 3),
                                                  tipText=tipText)

        label = Label(frame, text='  Other precision:')
        label.grid(row=0, column=4, sticky='w')
        tipText = 'Specifies how many decimal places to use when displaying chemical shift values for isotopes other than 1H'
        self.otherPrecisionSelect = PulldownList(frame,
                                                 texts=texts,
                                                 objects=precisions,
                                                 callback=self.draw,
                                                 index=1,
                                                 grid=(0, 5),
                                                 tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0))
        frame.expandGrid(None, 1)

        label = Label(frame, text='Column\nAtoms:', grid=(0, 0))
        tipText = 'Selects which kinds of atoms are displayed in aligned columns, or otherwise displayed at the end of the residue row (if "List all shifts" is set)'
        self.optSelector = PartitionedSelector(frame,
                                               self.toggleOpt,
                                               tipText=tipText,
                                               maxRowObjects=10,
                                               grid=(0, 1),
                                               sticky='ew')
        options = ['H', 'N', 'C', 'CA', 'CB', 'CG']
        self.optSelector.update(objects=options,
                                labels=options,
                                selected=['H', 'N', 'CA'])

        row += 1
        guiFrame.expandGrid(row, 0)
        self.canvasFrame = ScrolledCanvas(guiFrame,
                                          relief='groove',
                                          width=650,
                                          borderwidth=2,
                                          resizeCallback=None,
                                          grid=(row, 0),
                                          padx=1,
                                          pady=1)
        self.canvas = self.canvasFrame.canvas
        #self.canvas.bind('<Button-1>', self.toggleResidue)

        row += 1
        tipTexts = [
            'Output information from the table as PostScript file, for printing etc.',
            'Output information from the table as a whitespace separated plain text file'
        ]
        commands = [self.makePostScript, self.exportText]
        texts = ['Export PostScript', 'Export Text']
        buttonList = ButtonList(guiFrame,
                                commands=commands,
                                texts=texts,
                                grid=(row, 0),
                                tipTexts=tipTexts)

        chains = self.getChains()
        if len(chains) > 1:
            self.chain = chains[1]
        else:
            self.chain = None

        self.updateShiftLists()
        self.updateChains()
        self.otherShiftsSelect.set(True)
        self.update()

        for func in ('__init__', 'delete'):
            self.registerNotify(self.updateChains,
                                'ccp.molecule.MolSystem.Chain', func)
        for func in ('__init__', 'delete'):
            self.registerNotify(self.updateShiftLists, 'ccp.nmr.Nmr.ShiftList',
                                func)

    def changeShiftList(self, shiftList):

        if shiftList is not self.shiftList:
            self.shiftList = shiftList
            self.update()

    def updateShiftLists(self, *opt):

        names = []
        index = 0

        shiftLists = getShiftLists(self.nmrProject)

        shiftList = self.shiftList

        if shiftLists:
            names = [
                '%s [%d]' % (sl.name or '<No name>', sl.serial)
                for sl in shiftLists
            ]
            if shiftList not in shiftLists:
                shiftList = shiftLists[0]

            index = shiftLists.index(shiftList)

        if self.shiftList is not shiftList:
            self.shiftList = shiftList

        self.shiftListPulldown.setup(names, shiftLists, index)

    def getChains(self):

        chains = [
            None,
        ]
        for molSystem in self.project.sortedMolSystems():
            for chain in molSystem.sortedChains():
                if len(chain.residues) > 1:
                    chains.append(chain)

        return chains

    def changeChain(self, chain):

        if chain is not self.chain:
            self.chain = chain
            self.update()

    def updateChains(self, *opt):

        names = []
        index = -1

        chains = self.getChains()
        chain = self.chain

        if len(chains) > 1:
            names = [
                'None',
            ] + ['%s:%s' % (ch.molSystem.code, ch.code) for ch in chains[1:]]
            if chain not in chains:
                chain = chains[1]

            index = chains.index(chain)

        else:
            chain = None

        self.chainPulldown.setup(names, chains, index)

    def destroy(self):

        for func in ('__init__', 'delete'):
            self.unregisterNotify(self.updateChains,
                                  'ccp.molecule.MolSystem.Chain', func)
        for func in ('__init__', 'delete'):
            self.unregisterNotify(self.updateShiftLists,
                                  'ccp.nmr.Nmr.ShiftList', func)

        BasePopup.destroy(self)

    def exportText(self, *event):

        from memops.gui.FileSelect import FileType
        from memops.gui.FileSelectPopup import FileSelectPopup

        if self.textOut:
            fileTypes = [
                FileType('Text', ['*.txt']),
                FileType('CSV', ['*.csv']),
                FileType('All', ['*'])
            ]
            fileSelectPopup = FileSelectPopup(self,
                                              file_types=fileTypes,
                                              title='Save table as text',
                                              dismiss_text='Cancel',
                                              selected_file_must_exist=False)

            fileName = fileSelectPopup.getFile()

            if fileName:
                file = open(fileName, 'w')
                if fileName.endswith('.csv'):
                    for textRow in self.textMatrix:
                        file.write(','.join(textRow) + '\n')
                else:
                    file.write(self.textOut)

    def toggleOpt(self, selected):

        self.draw()

    def makePostScript(self):

        self.canvasFrame.printCanvas()

    def update(self):

        colors = []
        selected = set()
        atomNames = set()

        if self.chain:
            for residue in self.chain.sortedResidues():
                for atom in residue.atoms:
                    chemAtom = atom.chemAtom

                    if colorDict.get(chemAtom.elementSymbol) is None:
                        continue

                    if chemAtom.waterExchangeable:
                        continue

                    atomNames.add(atom.name[:2])

                molType = residue.molResidue.molType
                if molType == 'protein':
                    selected.add('H')
                    selected.add('N')
                    selected.add('CA')
                    selected.add('C')

                elif molType == 'DNA':
                    selected.add("C1'")

                elif molType == 'RNA':
                    selected.add("C1'")

                elif molType == 'carbohydrate':
                    selected.add("C1")

        else:
            for spinSystem in self.shiftList.nmrProject.resonanceGroups:
                if not spinSystem.residue:
                    for resonance in spinSystem.resonances:
                        for name in resonance.assignNames:
                            atomNames.add(name)

        options = list(atomNames)

        molType = 'protein'
        if self.chain:
            molType = self.chain.molecule.molType
        options = greekSortAtomNames(options, molType=molType)

        if 'H' in options:
            options.remove('H')
            options = [
                'H',
            ] + options
        colors = [colorDict.get(n[0]) for n in options]

        if options and not selected:
            selected = [
                options[0],
            ]

        self.optSelector.update(objects=options,
                                labels=options,
                                colors=colors,
                                selected=list(selected))

        self.draw()

    def draw(self, *opt):

        if not self.shiftList:
            return

        nmrProject = self.shiftList.nmrProject
        shiftList = self.shiftList
        font = self.font
        bfont = self.boldFont
        symbolFont = self.symbolFont
        sFont = self.smallFont
        bbox = self.canvas.bbox
        doOthers = self.otherShiftsSelect.get()

        spc = 4
        gap = 14
        x = gap
        y = gap
        ct = self.canvas.create_text
        cl = self.canvas.create_line
        cc = self.canvas.coords

        self.canvas.delete('all')

        ssDict = {}

        formatDict = {
            0.1: '%.1f',
            0.01: '%.2f',
            0.001: '%.3f',
        }

        protonFormat = formatDict[self.protonPrecisionSelect.getObject()]
        otherFormat = formatDict[self.otherPrecisionSelect.getObject()]

        uSpinSystems = []
        chains = set()
        molSystems = set()

        for spinSystem in nmrProject.resonanceGroups:

            residue = spinSystem.residue
            if residue:
                ssDict[residue] = ssDict.get(residue, []) + [
                    spinSystem,
                ]
            else:
                uSpinSystems.append((spinSystem.serial, spinSystem))

        uSpinSystems.sort()

        commonAtoms = self.optSelector.getSelected()
        N = len(commonAtoms)

        chain = self.chain

        if chain:
            spinSystems = []
            for residue in chain.sortedResidues():
                spinSystems0 = ssDict.get(residue, [])

                for spinSystem in spinSystems0:
                    if spinSystem and spinSystem.resonances:
                        spinSystems.append([residue, spinSystem])
        else:
            spinSystems = uSpinSystems

        strings = []

        doOneLetter = self.oneLetterSelect.get()

        if spinSystems:

            x = gap
            y += gap

            numItems = []
            codeItems = []
            commonItems = []
            otherItems = []

            numWidth = 0
            codeWidth = 0
            commonWidths = [0] * N
            commonCounts = [0] * N

            for residue, spinSystem in spinSystems:

                if type(residue) is type(1):
                    seqNum = '{%d}' % residue

                    if doOneLetter:
                        ccpCode = '-'
                    else:
                        ccpCode = spinSystem.ccpCode or ''

                else:
                    if doOneLetter:
                        ccpCode = residue.chemCompVar.chemComp.code1Letter

                    else:
                        ccpCode = getResidueCode(residue)

                    seqNum = str(residue.seqCode)

                subStrings = []
                subStrings.append(seqNum)
                subStrings.append(ccpCode)

                item = ct(x, y, text=seqNum, font=font, anchor='se')
                box = bbox(item)
                iWidth = box[2] - box[0]
                numWidth = max(numWidth, iWidth)
                numItems.append(item)

                item = ct(x, y, text=ccpCode, font=font, anchor='sw')
                box = bbox(item)
                iWidth = box[2] - box[0]
                codeWidth = max(codeWidth, iWidth)
                codeItems.append(item)

                commonShifts, commonElements, otherShifts = self.getShiftData(
                    spinSystem, shiftList, commonAtoms)

                items = []
                for i in range(N):
                    values = commonShifts[i]
                    element = commonElements[i]

                    if element == 'H':
                        shiftFormat = protonFormat
                    else:
                        shiftFormat = otherFormat

                    subItems = []
                    for value in values:
                        text = shiftFormat % value

                        if text:
                            item = ct(x, y, text=text, font=font, anchor='se')
                            box = bbox(item)
                            iWidth = box[2] - box[0]
                            commonWidths[i] = max(commonWidths[i], iWidth)
                            commonCounts[i] += 1
                            subItems.append(item)

                    subStrings.append(
                        ','.join([shiftFormat % v for v in values]) or '-')

                    items.append(subItems)

                commonItems.append(items)

                if doOthers:
                    items0 = []
                    i = 0
                    I = len(otherShifts)
                    for atomLabel, element, value in otherShifts:

                        label = atomLabel
                        if label[0] == '?':
                            label = label[3:-1]

                        if element == 'H':
                            shiftFormat = protonFormat
                        else:
                            shiftFormat = otherFormat

                        subStrings.append('%6s:%-4s' %
                                          (shiftFormat % value, label))
                        i += 1

                        atoms = atomLabel.split('|')

                        items = []
                        j = 0
                        for atom in atoms:
                            text = element
                            if j > 0:
                                text = '/' + text

                            item = ct(x, y, text=text, font=font, anchor='sw')
                            box = bbox(item)
                            iWidth = box[2] - box[0] - 3
                            items.append((iWidth, item, 0))

                            p = len(element)
                            if len(atom) > p:
                                letter = atom[p]
                                if letter not in ('0123456789'):
                                    item = ct(x,
                                              y,
                                              text=letter.lower(),
                                              font=symbolFont,
                                              anchor='sw')
                                    box = bbox(item)
                                    iWidth = box[2] - box[0] - 2
                                    items.append((iWidth, item, -4))
                                    p += 1

                            text = atom[p:]
                            if text:
                                item = ct(x,
                                          y,
                                          text=text,
                                          font=sFont,
                                          anchor='sw')
                                box = bbox(item)
                                iWidth = box[2] - box[0] - 2
                                items.append((iWidth, item, -4))
                            j += 1

                        text = ' ' + shiftFormat % value
                        if i != I:
                            text += ','

                        item = ct(x, y, text=text, font=font, anchor='sw')
                        box = bbox(item)
                        iWidth = box[2] - box[0] - 4
                        items.append((iWidth, item, 0))

                        items0.append(items)

                    otherItems.append(items0)

                strings.append(subStrings)

            y0 = y
            x = x0 = gap + numWidth + codeWidth + spc + spc
            for i in range(N):

                if not commonCounts[i]:
                    continue

                x += commonWidths[i] + spc + spc

                element = commonElements[i]

                iWidth = 0
                text = commonAtoms[i][len(element):].lower()
                if text:
                    item = ct(x, y, text=text, font=symbolFont, anchor='se')
                    box = bbox(item)
                    iWidth = box[2] - box[0] - 2

                ct(x - iWidth, y, text=element, font=font, anchor='se')

            y += gap

            for i in range(len(numItems)):
                x = gap + numWidth + spc

                cc(numItems[i], x, y)

                x += spc

                cc(codeItems[i], x, y)

                x += codeWidth

                x1 = x + spc

                yM = y
                for j in range(N):
                    if not commonCounts[j]:
                        continue

                    x += commonWidths[j] + spc + spc

                    items = commonItems[i][j]

                    yB = y - gap
                    for item in items:
                        yB += gap
                        cc(item, x, yB)
                        yM = max(yB, yM)

                x += gap

                if doOthers:
                    x += spc
                    x3 = x

                    for items in otherItems[i]:
                        if x > 550:
                            x = x3
                            y += gap

                        for iWidth, item, dy in items:
                            cc(item, x, y + dy)
                            x += iWidth

                y = max(y, yM)
                y += gap

            x = x0
            for i in range(N):
                if not commonCounts[i]:
                    continue

                x += commonWidths[i] + spc + spc

                cl(x + 8, y0, x + 8, y - gap, width=0.3, fill='#808080')

            cl(x1, y0, x1, y - gap, width=0.3, fill='#808080')
            cl(0, 0, 550, 0, width=0.3, fill='#FFFFFF')

            y += gap

        textWidths = {}
        for subStrings in strings:
            for i, text in enumerate(subStrings):
                if text and len(text) > textWidths.get(i, 0):
                    textWidths[i] = len(text)
                else:
                    textWidths[i] = 0

        formats = {}
        for i in textWidths.keys():
            formats[i] = ' %%%ds' % max(6, textWidths[i])

        textOut = '!'
        textRow = ['', '']
        textMatrix = [textRow]
        textOut += ' ' * (max(6, textWidths.get(0, 6)) +
                          max(6, textWidths.get(1, 6)) + 1)

        i = 2
        for atom in commonAtoms:
            if i in formats:
                textOut += formats[i] % atom
                textRow.append((formats[i] % atom).strip())
                i += 1
        textOut += '\n'

        for subStrings in strings:
            textRow = []
            textMatrix.append(textRow)
            i = 0
            for text in subStrings:
                textOut += formats[i] % text
                textRow.append((formats[i] % text).strip())
                i += 1

            textOut += '\n'

        self.textOut = textOut
        self.textMatrix = textMatrix

    def getShiftData(self,
                     spinSystem,
                     shiftList,
                     commonAtoms=('H', 'N', 'CA', 'CB')):

        commonShifts = []
        commonResonances = {}
        commonElements = []

        for atomName in commonAtoms:
            elements = set()
            resonances = []

            for resonance in spinSystem.resonances:
                resonanceSet = resonance.resonanceSet

                if resonanceSet:
                    for atomSet in resonanceSet.atomSets:
                        for atom in atomSet.atoms:
                            if atomName == atom.name[:2]:
                                resonances.append(resonance)
                                break

                        else:
                            continue
                        break

                else:
                    for assignName in resonance.assignNames:
                        if atomName == assignName[:2]:
                            resonances.append(resonance)
                            break

            shiftValues = []
            for resonance in resonances:
                isotope = resonance.isotope
                if isotope:
                    elements.add(isotope.chemElement.symbol)
                commonResonances[resonance] = True
                shift = resonance.findFirstShift(parentList=shiftList)
                if shift:
                    shiftValues.append(shift.value)

            if not elements:
                element = atomName[0]
            else:
                element = elements.pop()

            commonElements.append(element)
            commonShifts.append(shiftValues)

        otherShifts = []
        for resonance in spinSystem.resonances:
            if not commonResonances.get(resonance):
                shift = resonance.findFirstShift(parentList=shiftList)

                if shift:
                    isotope = resonance.isotope

                    if isotope:
                        element = isotope.chemElement.symbol
                    else:
                        element = '??'

                    if resonance.assignNames or resonance.resonanceSet:
                        name = getResonanceName(resonance)
                    else:
                        name = '??[%d]' % resonance.serial

                    otherShifts.append((name, element, shift.value))

        molType = 'protein'
        if spinSystem.residue:
            molType = spinSystem.residue.molResidue.molType

        otherShifts = greekSortAtomNames(otherShifts, molType)

        return commonShifts, commonElements, otherShifts
Пример #12
0
    def body(self, guiFrame):

        row = 0
        frame = Frame(guiFrame, grid=(row, 0))
        frame.expandGrid(None, 6)

        label = Label(frame, text='Chain:', grid=(0, 0))
        tipText = 'Selects which molecular chain to show residues and chemical shift values for'
        self.chainPulldown = PulldownList(frame,
                                          callback=self.changeChain,
                                          grid=(0, 1),
                                          tipText=tipText)

        label = Label(frame, text='  Shift List:', grid=(0, 2))
        tipText = 'Selects which shift list is used to derive the displayed chemical shift values'
        self.shiftListPulldown = PulldownList(frame,
                                              callback=self.changeShiftList,
                                              grid=(0, 3),
                                              tipText=tipText)

        label = Label(frame, text=' List all shifts:', grid=(0, 4))
        tipText = 'Sets whether to display all the chemical shifts for residues or just for the nominated atom types in columns'
        self.otherShiftsSelect = CheckButton(frame,
                                             callback=self.draw,
                                             grid=(0, 5),
                                             tipText=tipText)

        utilButtons = UtilityButtonList(frame,
                                        helpUrl=self.help_url,
                                        grid=(0, 7))

        row += 1
        frame = Frame(guiFrame, grid=(row, 0))
        frame.expandGrid(None, 6)

        label = Label(frame, text=' 1-letter codes:', grid=(0, 0))
        tipText = 'Whether to use 1-letter residue codes in the table, or otherwise Ccp/three-letter codes'
        self.oneLetterSelect = CheckButton(frame,
                                           callback=self.draw,
                                           grid=(0, 1),
                                           selected=False,
                                           tipText=tipText)

        precisions = [0.1, 0.01, 0.001]
        texts = [str(t) for t in precisions]
        label = Label(frame, text='  1H precision:', grid=(0, 2))
        tipText = 'Specifies how many decimal places to use when displaying 1H chemical shift values'
        self.protonPrecisionSelect = PulldownList(frame,
                                                  texts=texts,
                                                  objects=precisions,
                                                  callback=self.draw,
                                                  index=1,
                                                  grid=(0, 3),
                                                  tipText=tipText)

        label = Label(frame, text='  Other precision:')
        label.grid(row=0, column=4, sticky='w')
        tipText = 'Specifies how many decimal places to use when displaying chemical shift values for isotopes other than 1H'
        self.otherPrecisionSelect = PulldownList(frame,
                                                 texts=texts,
                                                 objects=precisions,
                                                 callback=self.draw,
                                                 index=1,
                                                 grid=(0, 5),
                                                 tipText=tipText)

        row += 1
        frame = Frame(guiFrame, grid=(row, 0))
        frame.expandGrid(None, 1)

        label = Label(frame, text='Column\nAtoms:', grid=(0, 0))
        tipText = 'Selects which kinds of atoms are displayed in aligned columns, or otherwise displayed at the end of the residue row (if "List all shifts" is set)'
        self.optSelector = PartitionedSelector(frame,
                                               self.toggleOpt,
                                               tipText=tipText,
                                               maxRowObjects=10,
                                               grid=(0, 1),
                                               sticky='ew')
        options = ['H', 'N', 'C', 'CA', 'CB', 'CG']
        self.optSelector.update(objects=options,
                                labels=options,
                                selected=['H', 'N', 'CA'])

        row += 1
        guiFrame.expandGrid(row, 0)
        self.canvasFrame = ScrolledCanvas(guiFrame,
                                          relief='groove',
                                          width=650,
                                          borderwidth=2,
                                          resizeCallback=None,
                                          grid=(row, 0),
                                          padx=1,
                                          pady=1)
        self.canvas = self.canvasFrame.canvas
        #self.canvas.bind('<Button-1>', self.toggleResidue)

        row += 1
        tipTexts = [
            'Output information from the table as PostScript file, for printing etc.',
            'Output information from the table as a whitespace separated plain text file'
        ]
        commands = [self.makePostScript, self.exportText]
        texts = ['Export PostScript', 'Export Text']
        buttonList = ButtonList(guiFrame,
                                commands=commands,
                                texts=texts,
                                grid=(row, 0),
                                tipTexts=tipTexts)

        chains = self.getChains()
        if len(chains) > 1:
            self.chain = chains[1]
        else:
            self.chain = None

        self.updateShiftLists()
        self.updateChains()
        self.otherShiftsSelect.set(True)
        self.update()

        for func in ('__init__', 'delete'):
            self.registerNotify(self.updateChains,
                                'ccp.molecule.MolSystem.Chain', func)
        for func in ('__init__', 'delete'):
            self.registerNotify(self.updateShiftLists, 'ccp.nmr.Nmr.ShiftList',
                                func)