rdkit.DataStructs.HierarchyVis

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