def generate_directory_graph(directory):
    # Create a new directed graph
    graph = yapgvb.Digraph(directory)

    # Traverse the directory structure
    nodes = {}
    try:
        for dirpath, dirnames, filenames in os.walk(directory):
            print "    ", dirpath

            parent_directory, dirname = os.path.split(dirpath)
            nfiles = len(filenames)

            # Create a new node for this directory
            nodes[dirpath] = graph.add_node(
                dirpath,
                label="%s: %s files" % (dirname, nfiles),
                shape='record',
            )

            if parent_directory in nodes:
                # create an edge between the parent directory node
                # and the newly created node
                nodes[parent_directory] >> nodes[dirpath]
    except KeyboardInterrupt:
        print '----> Directory traversal cancelled!'

    return graph
Esempio n. 2
0
 def draw(self, path='adtree.png'):
     G = yapgvb.Digraph('ADTree')
     label = self._node_id_iter()
     viz_adnode = G.add_node(label.next(),
                             label='root (%s)' % self.root.count,
                             shape=yapgvb.shapes.circle,
                             color=yapgvb.colors.blue,
                             root=True)
     self._build_graph(G, self.root, viz_adnode, label)
     G.layout(yapgvb.engines.dot)
     G.render(path)
Esempio n. 3
0
def create_graph(cfg, username):

    userAPI = UserAPI(cfg)
    campaignAPI = CampaignAPI(cfg)

    user = userAPI.show_by_username(username)

    nodes = {}
    edges = {}

    graph = yapgvb.Digraph(username)

    walk_user_campaigns(userAPI, campaignAPI, graph, nodes, edges, user)

    return graph
def generate_directory_graph(directory):
    # Create a new directed graph
    graph = yapgvb.Digraph(directory)
    
    # Traverse the directory structure
    nodes = {}
    try:
        for dirpath, dirnames, filenames in os.walk(directory):
            print "    ", dirpath

            parent_directory, dirname = os.path.split(dirpath)
            nfiles = len(filenames)

            # Create a new node for this directory
            nodes[dirpath] = graph.add_node(dirpath, 
                label = "%s" % (dirname),
                shape = 'record',
            )
            
            # Create nodes for each file in this directory
            for filename in filenames:
                #print "filename:", filename
                bad = False
                for blackitem in BLACKLIST:
                    if blackitem in filename:
                        #print "Passing blacklisted item:", filename
                        #print "because", blackitem, "is in ", filename
                        bad = True
                        break
                if bad:
                    continue
                        
                #print "creating node for ", filename
                nodes[dirpath + filename] = graph.add_node(dirpath + filename,
                    label = "%s" % filename,
                    shape = 'record',
                )
                nodes[dirpath] >> nodes[dirpath + filename]
            
            if parent_directory in nodes:
                # create an edge between the parent directory node 
                # and the newly created node
                nodes[parent_directory] >> nodes[dirpath]            
    except KeyboardInterrupt:
        print '----> Directory traversal cancelled!'

    return graph        
Esempio n. 5
0
    def graph(self, outfile):
        remaining = 60
        try:
            import yapgvb
            g = yapgvb.Digraph('Analysis of ' + self.url)
        except:
            print 'Unable to import yapgvb, please install python library'

        if os.path.exists(outfile): 
            os.remove(outfile)

        for url in self.rooturl:
            urlstr = url
            if self.rooturl[url].malicious > 5:
                color = yapgvb.colors.red
                urlstr += '\nmalicious'
            elif self.rooturl[url].malicious > 0:
                color = yapgvb.colors.orange
                urlstr += '\nsuspicious'
            else:
                color = 'white'
        
            if max(self.rooturl[url].malicious, self.rooturl[url].cumulative_malicious) > 0 or self.graphall:
                remaining -= 1
                node = g.add_node(url)
                node.label = urlstr
                node.color = color
                node.shape = yapgvb.shapes.box

                for type, child in self.rooturl[url].children:
                    if self.rooturl[child].hasParent and type == 'default':
                        pass 
                    elif max(self.rooturl[url].malicious, self.rooturl[child].cumulative_malicious, self.rooturl[child].malicious) > 0 or self.graphall:
                        cnode = g.add_node(child)
                        cnode.shape = yapgvb.shapes.box
                        cnode.label = child

                        edge = g.add_edge(node, cnode)
                        if not type == 'default':
                            edge.label = type
        if remaining > 0:
            g.layout(yapgvb.engines.dot)
            g.render(outfile)
        else:
            print 'Not graphing "%s" because rooturl used (%d) more nodes than the maximum (60)' % (outfile, -remaining)
Esempio n. 6
0
    def dot_repr(self, all_instructions=False):
        graph = yapgvb.Digraph('cfg')
        graph.dpi = 600
        nodes_dict = {}

        for cur_bb_id in self.bbs:
            lst = self.bbs[cur_bb_id].dot_repr(self, all_instructions)
            nodes_dict[lst[0]] = graph.add_node(lst[0], label=lst[1])

        for cur_bb_id in self.bbs:
            nextNodeNum = 0
            for next_bb_id in self.bbs[cur_bb_id].get_next_ids():
                edge = nodes_dict["bb_" +
                                  str(cur_bb_id)] - nodes_dict["bb_" +
                                                               str(next_bb_id)]
                edge.label = str(nextNodeNum)
                nextNodeNum += 1
        return graph
Esempio n. 7
0
def generate_random_graph(nnodes=20, nedges=80):
    import random
    graph = yapgvb.Digraph("my_graph")

    for i in xrange(nnodes):
        # Create a node named str(i)
        node = graph.add_node(str(i))

        # Assign a random shape and color
        node.shape = random.choice(yapgvb.shapes.values())
        node.color = random.choice(yapgvb.colors.values())

    # Get all of the nodes as a list
    # (the graph.nodes attribute is an iterator)
    nodes = list(graph.nodes)

    for i in xrange(nedges):
        head = random.choice(nodes)
        tail = random.choice(nodes)
        edge = tail >> head
        edge.color = random.choice(yapgvb.colors.values())

    return graph
Esempio n. 8
0
def dump_back_reference_graph(obj, maxdepth):
    obj = obj()
    if obj is None:
        print "Weakref was freed."
        return

    curframe = inspect.currentframe()

    todo = deque([(obj, 0)])
    strings = {}
    objects = {}
    depths = {}
    edges = []
    skipped = set()

    def element_string(e):
        if type(e) == list:
            return "list"
        if type(e) == type(curframe):
            return "frame: %s:%i" % (os.path.basename(
                e.f_code.co_filename), e.f_lineno)
        if type(e) == dict:
            return "\n".join([
                "%10s : %20s" % (str(k)[0:10], str(v)[0:10])
                for k, v in e.iteritems()
            ][0:10])

        #if type(e) == tuple:
        #    return "tuple"
        return str(e)[0:40]

    def list_str_bounded(l, join_str, max_indices, max_elem):
        l = [str(e)[0:max_elem] for e in l]
        if len(l) > max_indices:
            l = l[0:max_indices]
            l.append('...')
        return join_str.join(l)

    def edge_string(e1, e2):
        if type(e1) == list:
            return list_str_bounded([i for i in range(len(e1)) if e1[i] == e2],
                                    ", ", 10, 10)

        if type(e1) == dict:
            keys = [str(k)[0:20] for (k, v) in e1.iteritems() if e2 == v]
            return list_str_bounded(
                [k for (k, v) in e1.iteritems() if e2 == v], "\n", 10, 20)

        return list_str_bounded(
            [a for a in dir(e1) if e1.__getattribute__(a) == e2], "\n", 10, 20)

    def dont_trace(e):
        if type(e) == type(inspect):
            return True
        return False

    while todo:
        e, d = todo.popleft()
        ide = id(e)
        if ide in strings or d > maxdepth:
            continue
        strings[ide] = element_string(e)
        depths[ide] = d
        objects[ide] = e
        if dont_trace(e):
            skipped.add(ide)
            continue
        d += 1
        refs = gc.get_referrers(e)
        refs.remove(curframe)
        for r in list(refs):
            if r in todo or r == objects:
                refs.remove(r)
        todo.extend((r, d) for r in refs)
        edges.extend((id(r), ide) for r in refs)
        del refs

    print "Found %i nodes and %i edges" % (len(strings), len(edges))
    #for s in strings.values():
    #    print s

    graph = yapgvb.Digraph('Referrers')
    nodes = {}
    colors = ["red", "orange", "yellow", "green", "blue", "purple", "black"]
    ncol = len(colors)
    for (ids, s) in strings.items():
        nodes[ids] = graph.add_node(str(ids),
                                    label=s,
                                    color=colors[depths[ids] % ncol])
        if ids in skipped:
            nodes[ids].shape = 'box'
        if depths[ids] == maxdepth:
            nodes[ids].shape = 'parallelogram'

    for (id1, id2) in edges:
        if id1 in nodes and id2 in nodes:
            edge = nodes[id1] >> nodes[id2]
            s = edge_string(objects[id1], objects[id2])
            if s:
                edge.label = s

    graph.root = str(id(obj))
    #graph.layout(yapgvb.engines.twopi)
    graph.layout(yapgvb.engines.dot)
    graph.render('gcgraph.ps')
    del objects
        for item in items:
            clusterName = str(current + 1)
            nodes[clusterName] = graph.add_node(clusterName,
                                                label='group %s' % clusterName)
            generate_pham_graph(graph,
                                item,
                                parent=clusterName,
                                phage=phage,
                                current=clusterName)
    return graph


if __name__ == '__main__':
    nodes = {}
    clusters = eval(open('graphviz_input.txt').read())
    graph = yapgvb.Digraph()

    # Did the user specify a filename on the command line?
    output_file = sys.argv[1]

    if output_file is None:
        output_file = 'output.png'

    if len(sys.argv) > 2: phage = sys.argv[2]
    else: phage = None
    print 'phage:', phage

    print "Generating pham structure graph... Ctrl-C to terminate"

    for n, item in enumerate(clusters):
        graph = generate_pham_graph(graph, item, phage=phage, current=n)
Esempio n. 10
0
import yapgvb
import subprocess
g = yapgvb.Digraph("tree")
n = [g.add_node(str(i)) for i in xrange(4)]
e = [i >> j for i, j in zip(n[1:], n[:-1])]
e[0].label = 'cat'

# for j in xrange(3):
#     g.add_edge(str(i+1), str(i))
g.layout(yapgvb.engines.dot)
file = 'tree.png'
g.render('tree.png')
subprocess.Popen(['display', file])
Esempio n. 11
0
 def __init__(self, title='Django Model ERD'):
     self._graph = yapgvb.Digraph(title)
Esempio n. 12
0
    def plot(self, filename='computational_graph.png', method='dot',
            orientation='TB'):
        """
        accepted filenames, e.g.:
        filename =
        'myfolder/mypic.png'
        'mypic.svg'
        etc.

        accepted methods
        method = 'dot'
        method = 'circo'
        method = 'fdp'
        method = 'twopi'
        method = 'neato'

        accepted orientations:
        orientation = 'TB'
        orientation = 'LR'
        orientation = 'BT'
        orientation = 'RL'
        """

        try:
            import yapgvb
        except:
            raise PlotError('you will need yapgvb to plot graphs')

        import os

        supported_extensions = list(yapgvb.formats)
        extension = os.path.splitext(filename)[1][1:]
        if extension not in supported_extensions:
            raise PlotError(
                'Unsupported output graphics file extension.\n'
                'Supported extensions: ' + str(supported_extensions))

        supported_methods = list(yapgvb.engines)
        if method not in supported_methods:
            raise PlotError(
                'Unsupported graph layout method.\n'
                'Supported layout methods: ' + str(supported_methods))

        supported_orientations = ['TB', 'LR', 'BT', 'RL']
        if orientation not in supported_orientations:
            raise PlotError(
                'Unsupported graph layout orientation.\n'
                'Supported layout orientations: ' + str(supported_orientations))

        # setting the style for the nodes
        g = yapgvb.Digraph('someplot')
        g.rankdir = orientation

        # add nodes
        for f in self.functionList:
            if f.func == Function.Id:
                g.add_node('%d'%f.ID, label = '%d %s'%(f.ID,f.func.__name__), shape = yapgvb.shapes.doublecircle,
                    color = yapgvb.colors.blue, fontsize = 10)
            else:
                g.add_node('%d'%f.ID, label = '%d %s'%(f.ID,f.func.__name__), shape = yapgvb.shapes.box,
                    color = yapgvb.colors.blue, fontsize = 10)

        # add edges
        nodes = list(g.nodes)
        for f in self.functionList:
            for a in numpy.ravel(f.args):
                if isinstance(a, Function):
                    nodes[a.ID] >> nodes[f.ID]

        # independent nodes
        for f in self.independentFunctionList:
            nodes[f.ID].shape = yapgvb.shapes.octagon

        # dependent nodes
        for f in self.dependentFunctionList:
            nodes[f.ID].shape = yapgvb.shapes.octagon

        g.layout(method)
        g.render(filename, format=extension)
Esempio n. 13
0
#!/usr/bin/env python

#
# This file is a part of the Yapgvb software package, and is
# licensed under the New BSD License.
# A `LICENSE' file should have been included with this source.
#
# Copyright (c) 2009 Lonnie Princehouse
#

# A silly example to generate the logo for the yapgvb homepage

import yapgvb

if __name__ == '__main__':
    g = yapgvb.Digraph('yapgvb_logo')

    yapgvb_node = g.add_node("YAPGVB",
                             label='YAPGVB',
                             shape=yapgvb.shapes.doublecircle,
                             color=yapgvb.colors.blue,
                             fontsize=48)

    last_word = None

    for word in "Yet Another Python Graphviz Binding".split():
        word_node = g.add_node(word,
                               label=word,
                               fontsize=24,
                               shape=yapgvb.shapes.circle)
Esempio n. 14
0
def moerdergraph(round,
                 filename,
                 alledges=False,
                 nodefontsize=8.0,
                 edgefontsize=8.0):
    # G is the main Graph object
    G = graph.Digraph("Moerder")
    # a dict for indexing all nodes
    nodes = {}
    # we need to keep some of the nodes in mind
    prev_node = first_node = node = None
    # make a copy of the participant list so we don't jumble up the original list
    participants = round.participants[:]
    if not alledges:
        # if not admin/gameover view: sort nodes prior to adding them to the graph
        participants.sort(key=lambda p: p.player.name + p.player.info)
    # for each participant, add a node to the graph bearing his name
    for participant in participants:
        name = participant.player.name
        if len(participant.player.info) > 0:
            name += "\\n" + participant.player.info
        node = G.add_node(participant.player.public_id)
        node.label = name.encode('utf-8')
        node.fontsize = nodefontsize
        node.margin = 0.03
        if not prev_node:
            first_node = node
        # put all the nodes into a dict so we could find them fast by the player's id (needed later)
        nodes[participant.player.public_id] = node

        prev_node = node
        node.fontname = 'arial'
        # kicked participants are gray
        if participant.killed() and participant.killedby.killer is None:
            node.color = 'gray'
            node.fontcolor = 'gray'
        # dead participants are red
        if participant.killed() and not participant.killedby.killer is None:
            node.color = 'red'
            node.fontcolor = 'red'

    for participant in round.participants:
        if alledges or participant.killed():
            # add black edges for the initial kill assignment
            edge = G.add_edge(
                nodes[participant.getInitialKiller().player.public_id],
                nodes[participant.player.public_id])
            edge.color = 'black'
            edge.weight = 1.0
        if participant.killed():
            # add red edges for the kill
            if not participant.killedby.killer is None:
                # normal case
                edge = G.add_edge(
                    nodes[participant.killedby.killer.player.public_id],
                    nodes[participant.player.public_id])
            else:
                # special case of a game master kill
                node = G.add_node('vorzeitig ausgestiegen')
                node.fontsize = nodefontsize
                node.fontname = 'arial'
                node.color = 'gray'
                node.fontcolor = 'gray'
                edge = G.add_edge(node, nodes[participant.player.public_id])
            edge.color = 'red'
            edge.fontcolor = 'red'
            edge.weight = 1.0
            # set edge label to kill description
            label = utils.dateformat(participant.killedby.date) + ":\\n"
            maxlinelen = max(
                24,
                math.trunc(
                    math.ceil(math.sqrt(6 *
                                        len(participant.killedby.reason)))))
            label += "\\n".join(
                textwrap.wrap(participant.killedby.reason, maxlinelen))
            edge.label = label.encode('utf-8')
            edge.fontsize = edgefontsize
            edge.fontname = 'arial'
    # do the layout math and save to file
    G.layout(graph.engines.dot)
    G.render(filename)
Esempio n. 15
0
def renderGraphMain(argv, stdout, env):
    # default arguments
    server = "http://localhost"
    server_port = rospy.DEFAULT_TEST_PORT

    #check arguments for a help flag
    optlist, args = getopt.getopt(argv[1:], "h?p:s:",
                                  ["help", "port=", "server=", "test"])
    for o, a in optlist:
        if o in ("-h", "-?", "--help"):
            usage(stdout, argv[0])
            return
        elif o in ("--test"):
            server_port = rospy.DEFAULT_TEST_PORT
        elif o in ("-p", "--port"):
            server_port = a
        elif o in ("-s", "--server"):
            server = a

    serverUri = '%s:%s/' % (server, server_port)
    print "Looking for server at %s" % serverUri
    os.environ[rospy.ROS_MASTER_URI] = serverUri
    os.environ[rospy.ROS_NODE] = NAME
    os.environ[rospy.ROS_PORT] = str(0)  # any

    master = rospy.getMaster()

    out_FlowImageString = OutflowpyImageString(".imageOut")
    require(
        master.addMachine('default', rospy.getRosRoot(), 'localhost', 22, '',
                          ''))
    require(
        master.addNode('', 'imageViewer', 'pyImageViewer', 'imageViewer',
                       'default', 0))

    rospy.ready()

    require(
        master.connectFlow(out_FlowImageString.locator, "imageViewer:imageIn",
                           1))
    while not rospy.isShutdown():
        status_code, statusMessage, [nodes, flows] = master.getGraph()
        #        print 'nodes' + str(nodes)
        #        print 'flows ' + str(flows)

        print '--------------------------------------------'
        print 'This is the graph:'
        print 'refreshing every ' + str(sleep_time) + ' seconds'
        print '--------------------------------------------'

        for anode in nodes:
            status_code, statusMessage, [machine, address,
                                         port] = master.getNodeAddress(anode)
            print 'NODE: ' + str(anode) + ' on ' + str(machine) + ' at ' + str(
                address) + ' on port: ' + str(port)
            for aflow in flows:
                aflow_split = str(aflow[1]).split('.')
                destination = aflow_split[0]
                aflow_split_source = str(aflow[0]).split('.')
                source = aflow_split_source[0]
                if destination == anode:
                    print '\tINFLOW: ' + str(aflow_split[1]) + ' from: ' + str(
                        aflow[0])
                if source == anode:
                    print '\tOUTFLOW: ' + str(
                        aflow_split_source[1]) + ' to: ' + str(aflow[1])

        output_file = 'ROSGraph.jpeg'
        pid = os.fork(
        )  # This is a hack to get around an underlying memory leak in
        # the agraph library.
        if pid == 0:
            #print "starting yapgvb process"
            try:
                print '--------------------------------------------'
                ygraph = yapgvb.Digraph('ROSGraph')
                gnodes = {}
                for anode in nodes:
                    gnodes[anode] = ygraph.add_node(label=anode)
                #print "added allnodes"
                #print flows
                for aflow in flows:
                    aflow_split = str(aflow[1]).split(':')
                    destination = aflow_split[0]
                    aflow_split_source = str(aflow[0]).split(':')
                    source = aflow_split_source[0]
                    gnodes[source] >> gnodes[destination]
                #print "done setting up graph for rendering"
                ygraph.layout(yapgvb.engines.dot)
                ygraph.render(output_file)
            finally:
                mpid = os.getpid()
                os.kill(mpid, 9)
        else:
            os.wait()

        # Wrap up the image and send it out over a flow
        imToSend = Image.open(output_file)

        future_packet = pyImageString()
        future_packet.imageString = imToSend.tostring()

        future_packet.imageFormat = "RGB"
        future_packet.width, future_packet.height = imToSend.size

        out_FlowImageString.publish(future_packet)

        # don't loop too fast
        time.sleep(sleep_time)
Esempio n. 16
0
def main(filename):
    try:
        file = open(filename, 'r')
    except Exception as e:
        print "Errors occurred opening input file %s" % filename 
        print e
        exit(1)
        
    graph = yapgvb.Digraph()
    
    node_from = None
    node_to = None
    
    tmp = tempfile.NamedTemporaryFile()
    
    # set file pointer on PROCEDURE DIVISION line
    for line in file:
        if PROC.match(line):
            break
    
    # now writes to temp file, deleting comments and debug statement
    for line in file:
        try:
            if line[6] in ('*', 'D'):
                continue
        except IndexError:
            continue
            
        tmp.write(line)
        
    # look for labels and build graph
    # every label is a node, every perform is an edge
    tmp.seek(0)
    for line in tmp:
        mtch = LABEL.match(line)
        if mtch and mtch.group(1):
            #if mtch.group(1)[0:1] in ("Z-"):
            #    continue
            node_from = graph.find_node(mtch.group(1))
            
        mtch = PERFORM.match(line)
        if mtch and mtch.group(1) and mtch.group(1) != "VARYING":
            #if mtch.group(1)[0:1] in ("Z-"):
            #    continue
            node_to = graph.find_node(mtch.group(1))
            graph.add_edge(node_from, node_to)
    
    print "Graph edges: ", len([n for n in graph.edges])
    print "Graph nodes: ", len([n for n in graph.nodes])
    
    graph.layout(engine='dot')
    print "rendering graph..."
    try:
        fileoname = filename + ".jpg"
        fileout = open(fileoname, 'w')
    except Exception as e:
        print "Errors occurred opening output file %s" % fileoname 
        print e
        exit(1)
    
    graph.render(outstream=fileout,format='jpg')
    print "Done!"
    tmp.close()
    file.close()
Esempio n. 17
0
def _PlotAndDisplay(imageViewerApp_, graph_, timeStamp_):

    global _firstPlot

    if _which(imageViewerApp_) == None:
        print 'Image rendering application:', '"' + imageViewerApp_ + '"', 'does not exist on your machine.'
        print 'Change application name from your master script.'
        exit(1)

    (graphId, (source, destination), (primaryClockSources,
                                      secondaryClockSources), path) = graph_

    if len(path) == 0:
        return None

    if source == 'F980' or source == 'F981':
        source = '1'

    if destination == 'F980' or destination == 'F981':
        destination = '1'

    # node that the clockSource will be provided for
    clockNode = source
    if source == '1':
        clockNode = destination

    pClckSource = ''
    sClckSource = ''
    if clockNode in primaryClockSources.keys():
        pClckSource = primaryClockSources[clockNode]
    if clockNode in secondaryClockSources.keys():
        sClckSource = secondaryClockSources[clockNode]

    # ploting starts here
    graphviz_graph = yapgvb.Digraph()

    colors = "#000000"
    colord = "#000000"
    for (s, d) in path:

        if s == source:
            colors = yapgvb.colors.blue
        else:
            colors = "#000000"

        if d == destination:
            colord = yapgvb.colors.blue
        else:
            colord = "#000000"

        source_label = s
        if s == pClckSource:
            source_label = s + '\nPCS'
        elif s == sClckSource:
            source_label = s + '\nSCS'

        dest_label = d
        if d == pClckSource:
            dest_label = d + '\nPCS'
        elif d == sClckSource:
            dest_label = d + '\nSCS'

        source_node = graphviz_graph.add_node(s,
                                              label=source_label,
                                              shape=yapgvb.shapes.circle,
                                              color=colors,
                                              fontsize=10)
        dest_node = graphviz_graph.add_node(d,
                                            label=dest_label,
                                            shape=yapgvb.shapes.circle,
                                            color=colord,
                                            fontsize=10)
        source_node >> dest_node

    graphviz_graph.add_node("GraphId",
                            label='Graph ID: ' + graphId + ', time stamp:\n' +
                            timeStamp_,
                            shape=yapgvb.shapes.rectangle,
                            color=yapgvb.colors.violet,
                            fontsize=10)

    #graphviz_graph.label = 'Graph ID: ' + graphId + ', time stamp:\n' + timeStamp_
    graphviz_graph.layout(yapgvb.engines.circo)

    # get a temp file
    tmpFile = tempfile.NamedTemporaryFile(prefix='graphviz',
                                          suffix='.png',
                                          delete='False')
    tmpFile.close()

    # render plot
    graphviz_graph.render(tmpFile.name)

    # avoid crashes when rendering multiple plots
    if _firstPlot == True:
        _firstPlot = False
    else:
        time.sleep(2)

    # show image
    os.system(imageViewerApp_ + ' ' + tmpFile.name + ' &')

    return None
Esempio n. 18
0
def moerdergraphall(game,
                    filename,
                    alledges=False,
                    nodefontsize=8.0,
                    edgefontsize=8.0,
                    rounds=None):
    if rounds is None:
        rounds = game.rounds.values()
    elif type(rounds) is not list:
        rounds = [rounds]
    # G is the main Graph object
    G = graph.Digraph("Moerder")
    G.model = 'subset'
    G.overlap = 'compress'
    G.splines = True
    G.normalize = True
    G.packmode = 'graph'
    G.rankdir = 'LR'
    # a dict for indexing all nodes
    nodes = {}
    # we need to keep some of the nodes in mind
    prev_node = first_node = node = None
    # make a copy of the participant list so we don't jumble up the original list
    participants = sorted(
        rounds, key=lambda x: len(x.participants))[-1].participants[:]
    gmnode = G.add_node('Game Master')
    gmnode.label = 'Game Master'
    gmnode.fontsize = nodefontsize
    gmnode.fontname = 'arial'
    gmnode.color = 'gray'
    gmnode.fontcolor = 'gray'
    gmnode.style = 'rounded'
    hnode = inode = G.add_node('invisible')
    inode.style = 'invisible'
    inode.pos = (0.0, 0.0)
    if len(participants) > 120:
        sorrynode = G.add_node(u'Sorry, zu viele Nodes in diesem Graph...')
        sorrynode.label = u'Sorry, zu viele Nodes in diesem Graph...'
        sorrynode.style = 'rounded,filled'
        sorrynode.fontsize = nodefontsize
        sorrynode.style = 'rounded,filled'
        sorrynode.penwidth = 2
        sorrynode.color = '#00003380'
        sorrynode.fillcolor = '#FFFFFF00'
        sorrynode.margin = 0.01
        # do the layout math and save to file
        if graph.__dict__.has_key('_yapgvb_py'):
            # if yapgvb works in python-only mode
            rc = MyRenderingContext()
            G.layout(graph.engines.dot, rendering_context=rc)
            G.render(filename, rendering_context=rc)
        else:
            # if yapgvb has libboost support compiled in
            G.layout(graph.engines.dot)
            G.render(filename)
        return
    massmurderers = game.getMassMurderer()
    massmurdererlist = [
        player.public_id for player in massmurderers['killers']
    ] if len(massmurderers) > 0 else []

    if not alledges:
        # if not admin/gameover view: sort nodes prior to adding them to the graph
        participants.sort(key=lambda p: p.player.name + p.player.info)
    nodecount = len(participants)
    nodesperline = math.trunc(math.sqrt(nodecount))
    # for each participant, add a node to the graph bearing his name
    nodenumber = 0
    for participant in participants:
        nodenumber += 1
        name = participant.player.name
        if len(participant.player.info) > 0:
            name += "\\n" + participant.player.info
        name = utils.dotescape(name)
        node = G.add_node(participant.player.public_id)
        node.label = name.encode('utf-8')
        node.fontsize = nodefontsize
        node.style = 'rounded,filled'
        node.penwidth = 2
        node.color = '#00003380'
        node.fillcolor = '#FFFFFF00'
        node.margin = 0.01
        nodeweight = game.getDeathsCount(participant) + game.getKillsCount(
            participant)
        #node.group = str(nodeweight)
        node.pos = (nodenumber % nodesperline, nodenumber / nodesperline)
        if nodeweight == 0:
            iedge = G.add_edge(inode, node)
            iedge.style = 'invisible'
            iedge.arrowhead = 'none'
            iedge.weight = 0.1
            node.pos = (0.0, 0.0)
            #iedge.constraint = False
        if not prev_node:
            first_node = node
        # put all the nodes into a dict so we could find them fast by the player's id (needed later)
        nodes[participant.player.public_id] = node

        prev_node = node
        node.fontname = 'arial'
        # kicked participants are gray
        if participant.killed() and participant.killedby.killer is None:
            #node.color = '#FF6666FF'
            #node.fontcolor = '#33333388'
            #node.fillcolor = '#66666622'
            node.style += ',dashed'
        # mass murderers are black
        if participant.player.public_id in massmurdererlist:
            node.color = 'black'
            node.fillcolor = 'black'
            node.fontcolor = 'white'
        # dead participants are red
        if (game.getDeathsCount(participant) >= len(game.rounds)):
            node.color = '#FF0000FF'
            node.penwidth = 2
            #node.fontcolor = '#FFFFFFFF'
            #node.fillcolor = '#FF0000FF'

    colorgenerator = colorgen(0.86)
    for round in game.rounds.values():
        edgecolor = next(colorgenerator)
        if round not in rounds:
            continue
        for participant in round.participants:
            if alledges or participant.killed():
                edge = G.add_edge(
                    nodes[participant.getInitialKiller().player.public_id],
                    nodes[participant.player.public_id])
                edge.color = edgecolor
                edge.style = 'dashed'
                edge.penwidth = 2
                edge.weight = 6.0
                #edge.constraint = False
            if participant.killed():
                if not participant.killedby.killer is None:
                    # normal case
                    edge = G.add_edge(
                        nodes[participant.killedby.killer.player.public_id],
                        nodes[participant.player.public_id])
                else:
                    # special case of a game master kill
                    edge = G.add_edge(gmnode,
                                      nodes[participant.player.public_id])
                edge.color = edgecolor
                edge.fontcolor = 'red'
                edge.style = 'solid'
                edge.penwidth = 4
                edge.weight = 10.0
                # set edge label to kill description
                label = utils.dateformat(participant.killedby.date) + ":\\n"
                maxlinelen = max(
                    24,
                    math.trunc(
                        math.ceil(
                            math.sqrt(6 * len(participant.killedby.reason)))))
                label += "\\n".join(
                    textwrap.wrap(participant.killedby.reason,
                                  maxlinelen)).replace('"', "'")
                edge.label = ''.join(
                    [c for c in label.encode('utf-8') if ord(c) < 2048])
                edge.fontsize = edgefontsize
                edge.fontname = 'arial'
    # do the layout math and save to file
    if graph.__dict__.has_key('_yapgvb_py'):
        # if yapgvb works in python-only mode
        rc = MyRenderingContext()
        G.layout(graph.engines.dot, rendering_context=rc)
        G.render(filename, rendering_context=rc)
    else:
        # if yapgvb has libboost support compiled in
        G.layout(graph.engines.dot)
        G.render(filename)