Package rdkit :: Package DataStructs :: Module HierarchyVis

[hide private]
[frames] | no frames]

# Source Code for Module rdkit.DataStructs.HierarchyVis

      1  # $Id$
      2  #
      3  #  Copyright (C)2003-2006  Rational Discovery LLC
      4  #
      5  #   @@ All Rights Reserved @@
      6  #  This file is part of the RDKit.
      7  #  The contents are covered by the terms of the BSD license
      8  #  which is included in the file license.txt, found at the root
      9  #  of the RDKit source tree.
     10  #
     11  """ functionality for drawing hierarchical catalogs on sping
     12      canvases
     13
     14  """
     15  from sping import pid as piddle
     16
     17 -class VisOpts(object):
     18    circRad = 10
     19    minCircRad = 4
     20    maxCircRad = 16
     21    circColor = piddle.Color(0.6,0.6,0.9)
     22    terminalEmptyColor = piddle.Color(.8,.8,.2)
     23    terminalOnColor = piddle.Color(0.8,0.8,0.8)
     24    terminalOffColor = piddle.Color(0.2,0.2,0.2)
     25    outlineColor = piddle.transparent
     26    lineColor = piddle.Color(0,0,0)
     27    lineWidth = 1
     28    horizOffset = 5
     29    vertOffset = 75
     30    topMargin = 20
     31    labelFont = piddle.Font(face='helvetica',size=10)
     32    highlightColor = piddle.Color(1.,1.,.4)
     33    highlightWidth = 2
     34
     35  visOpts = VisOpts()
     36
     37 -def GetMinCanvasSize(adjList,levelList):
     38    maxAcross = -1
     39    for k in levelList.keys():
     40      nHere = len(levelList[k])
     41      maxAcross = max(maxAcross,nHere)
     42    nLevs = len(levelList.keys())
     43    minSize = ( maxAcross*(visOpts.minCircRad*2+visOpts.horizOffset),
     44                visOpts.topMargin + nLevs * visOpts.vertOffset )
     45    return minSize
     46
     47 -def DrawHierarchy(adjList,levelList,canvas,entryColors=None,
     48                    bitIds=None,minLevel=-1,maxLevel=1e8):
     49    """
     50
     51    Arguments:
     52
     53     - adjList: adjacency list representation of the hierarchy to be drawn
     54
     55     - levelList: dictionary mapping level -> list of ids
     56
     57    """
     58    if bitIds is None:
     59      bitIds = []
     60    if entryColors is None:
     61      entryColors = {}
     62
     63    levelLengths = levelList.keys()
     64    levelLengths.sort()
     65    minLevel = max(minLevel,levelLengths[0])
     66    maxLevel = min(maxLevel,levelLengths[-1])
     67
     68    dims = canvas.size
     69    drawLocs = {}
     70    # start at the bottom of the hierarchy and work up:
     71    for levelLen in range(maxLevel,minLevel-1,-1):
     72      nLevelsDown = levelLen-minLevel
     73      pos = [0,visOpts.vertOffset*nLevelsDown+visOpts.topMargin]
     74
     75      ids = levelList.get(levelLen,[])
     76
     77      # FIX: we'll eventually want to figure out some kind of sorting here:
     78      nHere = len(ids)
     79      canvas.defaultFont=visOpts.labelFont
     80      if nHere:
     81        # figure the size of each node at this level:
     82        spacePerNode = float(dims[0]) / nHere
     83        spacePerNode -= visOpts.horizOffset
     84        nodeRad = max(spacePerNode/2,visOpts.minCircRad)
     85        nodeRad = min(nodeRad,visOpts.maxCircRad)
     86        spacePerNode = nodeRad*2+visOpts.horizOffset
     87        # start in the midde of the canvas:
     88        pos[0] = dims[0]/2.
     89        # maybe we need to offset a little:
     90        if nHere%2:
     91          pos[0] -= spacePerNode/2
     92
     93        # move to the left by half the number of nodes:
     94        pos[0] -= (nHere // 2 - .5) * spacePerNode
     95
     96        # Find the locations and draw connectors:
     97        for id in ids:
     98          if not bitIds or id in bitIds:
     99            # first do lines down to the next level:
    100            if levelLen != maxLevel:
    101              for neighbor in adjList[id]:
    102                if drawLocs.has_key(neighbor):
    103                  p2 = drawLocs[neighbor][0]
    104                  canvas.drawLine(pos[0],pos[1],p2[0],p2[1],
    105                                  visOpts.lineColor,visOpts.lineWidth)
    106            drawLocs[id] = tuple(pos),nodeRad
    107            pos[0] += spacePerNode
    108
    109    for id in drawLocs.keys():
    110      pos,nodeRad = drawLocs[id]
    111      x1,y1 = pos[0]-nodeRad,pos[1]-nodeRad
    112      x2,y2 = pos[0]+nodeRad,pos[1]+nodeRad
    113      drawColor = entryColors.get(id,visOpts.circColor)
    114      canvas.drawEllipse(x1,y1,x2,y2,visOpts.outlineColor,
    115                         0,drawColor)
    116      label = str(id)
    117      #txtLoc = ( pos[0]-canvas.stringWidth(label)/2,
    118      #           pos[1]+canvas.fontHeight()/4 )
    119      txtLoc = ( pos[0]+canvas.fontHeight()/4,
    120                 pos[1]+canvas.stringWidth(label)/2)
    121      canvas.drawString(label,txtLoc[0],txtLoc[1],angle=90)
    122
    123    return drawLocs
    124