我可以在graphviz中更改哪些参数以使图形看起来更好?

时间:2019-04-14 19:04:43

标签: dot graph-visualization

我正在使用graphviz创建一个图表,显示基于pony的数据库模式。但是,该模式最终变得非常复杂enter image description here

我可以在代码中修改哪些参数以使其看起来更好?

现在,我使用“ neato”作为引擎(与默认设置相比,效果更好),但不知道我可以修改哪些其他参数。

使用ponyorm定义架构的脚本:

from pony import orm
from pony.orm import Required, Optional, Set, db_session, show, composite_key
from decimal import Decimal
import datetime as dtt
import pandas as pd


###############################################################################
# DATABASE DEFINITION
###############################################################################

_db = orm.Database()


class Helper:

    def __repr__(self):
        class_name = type(self).__name__
        return '<' + class_name + self.label() + '>'


class Table1(Helper, _db.Entity):
    attr0 = Required(str, unique=True)
    table2s = Set('Table2')


class Table2(Helper, _db.Entity):
    name = Required(str, unique=True)
    table1 = Required('Table1')
    table6s = Set('Table6')
    notes = Optional(str)


class Table3(Helper, _db.Entity):
    name = Required(str, unique=True)
    table6s = Set('Table6')


class Table4(Helper, _db.Entity):
    number = Required(str, unique=True)
    valid_from = Required(dtt.datetime)
    valid_to = Optional(dtt.datetime)
    table6s = Required('Table6')


class Table5(Helper, _db.Entity):
    text = Required(str, unique=True)
    table6s = Required('Table6')


class Table6(Helper, _db.Entity):
    table2 = Required('Table2')
    table3 = Required('Table3')
    description = Required(str, unique=True)
    table6 = Optional('Table5')
    date_opened = Optional(dtt.datetime)
    date_closed = Optional(dtt.datetime)
    table4s = Set('Table4')
    table7s = Set('Table7')
    table8 = Required('Table8')
    table10 = Optional('Table10')


class Table7(Helper, _db.Entity):
    date = Required(dtt.datetime)
    start = Required(dtt.datetime)
    description = Required(str)
    amount = Required(Decimal)
    table10 = Required('Table10')
    table6 = Required('Table6')
    tabel14s = Set('Table14')
    table9s = Set('Table9')



class Table8(Helper, _db.Entity):
    name = Required(str)
    is_true = Required(bool)
    is_false = Required(bool)
    table11s = Set('Table11')
    table6s = Set('Table6')


class Table9(Helper, _db.Entity):
    date = Required(dtt.datetime)
    description = Required(str)
    table12s = Set('Table12')
    table11s = Set('Table11')
    table7s = Set('Table7')
    table9s = Set('Table9', reverse='table9s')


class Table10(Helper, _db.Entity):
    name = Required(str, unique=True)
    transactions = Set('Table11')
    table7s = Set('Table7')
    table6s = Set('Table6')


class Table11(Helper, _db.Entity):
    amount = Required(Decimal)
    table10 = Required('Table10')
    table8= Required('Table8')
    table9s= Set('Table9')


class Table12(Helper, _db.Entity):
    name = Required(str, unique=True)
    table9s = Set('Table9')



class Table13(Helper, _db.Entity):
    name = Required(str, unique=True)
    table14s = Set('Table14')


class Table14(Helper, _db.Entity):
    filename = Required(str, unique=True)
    suffix = Required(str)
    table13 = Required('Table13')
    date_added = Required(dtt.datetime)
    period_start = Optional(dtt.datetime)
    period_end = Optional(dtt.datetime)
    description = Optional(str)
    table7s = Set('Table7')


###############################################################################
# CONNECT TO DATABASE
###############################################################################
orm.set_sql_debug(False)
_db.bind(provider='sqlite', filename=':memory:', create_db=True)
_db.generate_mapping(create_tables=True)

commit = _db.commit
select = orm.select
entities = _db.entities

# hack to overcome pyflakes thinking that variables aren't used
show = show
db_session = db_session

Python函数可加载ponyorm数据库并创建点文件

def get_port(s):
    return 'port="' + s.replace(' ', '_') + '"'


def calculate_graph():

    s = gv.Graph('graph', node_attr={'shape': 'plaintext'}, engine='neato',
                 graph_attr={'splines': 'true', 'overlap': 'false'})

    edges = []

    for entity in db.entities:

        table_def = '<table border="0" cellborder="1" cellspacing="0">'
        header = (f'<tr><td bgcolor="black"><font color="white">{entity}'
                  '</font></td></tr>')

        attrs = ''
        for attr in db.entities[entity]._attrs_:
            name = attr.name
            port = get_port(name)
            attrs += f'<tr><td {port}>{name}</td></tr>'
            # if isinstance(attr, db.Set):
            if attr.py_type in db.entities.values():
                edges.append((f'{entity}:{attr.name}',
                              f'{attr.py_type.__name__}:id'))

        s_struct = '<' + table_def + header + attrs + '</table>>'
        s.node(entity, s_struct)

    s.edges(edges)

    s.attr(overlap='false')
    s.view()

点文件代码(自动生成):

graph "graph" {
    graph [overlap=false splines=true]
    node [shape=plaintext]
    Table1 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table1</font></td></tr><tr><td port="id">id</td></tr><tr><td port="attr0">attr0</td></tr><tr><td port="table2s">table2s</td></tr></table>>]
    Table2 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table2</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table1">table1</td></tr><tr><td port="table6s">table6s</td></tr><tr><td port="notes">notes</td></tr></table>>]
    Table3 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table3</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
    Table4 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table4</font></td></tr><tr><td port="id">id</td></tr><tr><td port="number">number</td></tr><tr><td port="valid_from">valid_from</td></tr><tr><td port="valid_to">valid_to</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
    Table5 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table5</font></td></tr><tr><td port="id">id</td></tr><tr><td port="text">text</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
    Table6 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table6</font></td></tr><tr><td port="id">id</td></tr><tr><td port="table2">table2</td></tr><tr><td port="table3">table3</td></tr><tr><td port="description">description</td></tr><tr><td port="table6">table6</td></tr><tr><td port="date_opened">date_opened</td></tr><tr><td port="date_closed">date_closed</td></tr><tr><td port="table4s">table4s</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table8">table8</td></tr><tr><td port="table10">table10</td></tr></table>>]
    Table7 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table7</font></td></tr><tr><td port="id">id</td></tr><tr><td port="date">date</td></tr><tr><td port="start">start</td></tr><tr><td port="description">description</td></tr><tr><td port="amount">amount</td></tr><tr><td port="table10">table10</td></tr><tr><td port="table6">table6</td></tr><tr><td port="tabel14s">tabel14s</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
    Table8 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table8</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="is_true">is_true</td></tr><tr><td port="is_false">is_false</td></tr><tr><td port="table11s">table11s</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
    Table9 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table9</font></td></tr><tr><td port="id">id</td></tr><tr><td port="date">date</td></tr><tr><td port="description">description</td></tr><tr><td port="table12s">table12s</td></tr><tr><td port="table11s">table11s</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
    Table10 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table10</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="transactions">transactions</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
    Table11 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table11</font></td></tr><tr><td port="id">id</td></tr><tr><td port="amount">amount</td></tr><tr><td port="table10">table10</td></tr><tr><td port="table8">table8</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
    Table12 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table12</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
    Table13 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table13</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table14s">table14s</td></tr></table>>]
    Table14 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table14</font></td></tr><tr><td port="id">id</td></tr><tr><td port="filename">filename</td></tr><tr><td port="suffix">suffix</td></tr><tr><td port="table13">table13</td></tr><tr><td port="date_added">date_added</td></tr><tr><td port="period_start">period_start</td></tr><tr><td port="period_end">period_end</td></tr><tr><td port="description">description</td></tr><tr><td port="table7s">table7s</td></tr></table>>]
    Table1:table2s -- Table2:id
    Table2:table1 -- Table1:id
    Table2:table6s -- Table6:id
    Table3:table6s -- Table6:id
    Table4:table6s -- Table6:id
    Table5:table6s -- Table6:id
    Table6:table2 -- Table2:id
    Table6:table3 -- Table3:id
    Table6:table6 -- Table5:id
    Table6:table4s -- Table4:id
    Table6:table7s -- Table7:id
    Table6:table8 -- Table8:id
    Table6:table10 -- Table10:id
    Table7:table10 -- Table10:id
    Table7:table6 -- Table6:id
    Table7:tabel14s -- Table14:id
    Table7:table9s -- Table9:id
    Table8:table11s -- Table11:id
    Table8:table6s -- Table6:id
    Table9:table12s -- Table12:id
    Table9:table11s -- Table11:id
    Table9:table7s -- Table7:id
    Table9:table9s -- Table9:id
    Table10:transactions -- Table11:id
    Table10:table7s -- Table7:id
    Table10:table6s -- Table6:id
    Table11:table10 -- Table10:id
    Table11:table8 -- Table8:id
    Table11:table9s -- Table9:id
    Table12:table9s -- Table9:id
    Table13:table14s -- Table14:id
    Table14:table13 -- Table13:id
    Table14:table7s -- Table7:id
    overlap=false
}

1 个答案:

答案 0 :(得分:1)

  • 使用ortho路由会使该图更具吸引力。
  • 边缘迟早会不可避免地碰到其他事物,因此设置一些透明度可能也会有所帮助(edge[color="#00000080"])。
  • 此外,由于它与表之间的关系有关,因此您可能希望使图形成为有向图,这样您就可以看到图形的前进方向(或在全局边缘声明中使用dir和arrowtail / arrowhead属性,即{ {1}})下面的示例仅使它成为有向图

让图表看起来更好可能需要很多修补工作。 edge[color="#00000080" dir=both arrowtail=crow arrowhead=none]路由是我找到的最接近'magic'属性的路由。缺点是它无法缩放到大图(数百个节点或更多)。

tweaked result with neato

ortho

B.t.w。您着手使用 neato 算法(在这种情况下确实提供了最好的结果)-使用digraph "graph" { graph [overlap=true splines=ortho] edge[color="#00000080"] node [shape=plaintext] Table1 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table1</font></td></tr><tr><td port="id">id</td></tr><tr><td port="attr0">attr0</td></tr><tr><td port="table2s">table2s</td></tr></table>>] Table2 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table2</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table1">table1</td></tr><tr><td port="table6s">table6s</td></tr><tr><td port="notes">notes</td></tr></table>>] Table3 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table3</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table6s">table6s</td></tr></table>>] Table4 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table4</font></td></tr><tr><td port="id">id</td></tr><tr><td port="number">number</td></tr><tr><td port="valid_from">valid_from</td></tr><tr><td port="valid_to">valid_to</td></tr><tr><td port="table6s">table6s</td></tr></table>>] Table5 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table5</font></td></tr><tr><td port="id">id</td></tr><tr><td port="text">text</td></tr><tr><td port="table6s">table6s</td></tr></table>>] Table6 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table6</font></td></tr><tr><td port="id">id</td></tr><tr><td port="table2">table2</td></tr><tr><td port="table3">table3</td></tr><tr><td port="description">description</td></tr><tr><td port="table6">table6</td></tr><tr><td port="date_opened">date_opened</td></tr><tr><td port="date_closed">date_closed</td></tr><tr><td port="table4s">table4s</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table8">table8</td></tr><tr><td port="table10">table10</td></tr></table>>] Table7 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table7</font></td></tr><tr><td port="id">id</td></tr><tr><td port="date">date</td></tr><tr><td port="start">start</td></tr><tr><td port="description">description</td></tr><tr><td port="amount">amount</td></tr><tr><td port="table10">table10</td></tr><tr><td port="table6">table6</td></tr><tr><td port="tabel14s">tabel14s</td></tr><tr><td port="table9s">table9s</td></tr></table>>] Table8 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table8</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="is_true">is_true</td></tr><tr><td port="is_false">is_false</td></tr><tr><td port="table11s">table11s</td></tr><tr><td port="table6s">table6s</td></tr></table>>] Table9 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table9</font></td></tr><tr><td port="id">id</td></tr><tr><td port="date">date</td></tr><tr><td port="description">description</td></tr><tr><td port="table12s">table12s</td></tr><tr><td port="table11s">table11s</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table9s">table9s</td></tr></table>>] Table10 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table10</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="transactions">transactions</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table6s">table6s</td></tr></table>>] Table11 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table11</font></td></tr><tr><td port="id">id</td></tr><tr><td port="amount">amount</td></tr><tr><td port="table10">table10</td></tr><tr><td port="table8">table8</td></tr><tr><td port="table9s">table9s</td></tr></table>>] Table12 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table12</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table9s">table9s</td></tr></table>>] Table13 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table13</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table14s">table14s</td></tr></table>>] Table14 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table14</font></td></tr><tr><td port="id">id</td></tr><tr><td port="filename">filename</td></tr><tr><td port="suffix">suffix</td></tr><tr><td port="table13">table13</td></tr><tr><td port="date_added">date_added</td></tr><tr><td port="period_start">period_start</td></tr><tr><td port="period_end">period_end</td></tr><tr><td port="description">description</td></tr><tr><td port="table7s">table7s</td></tr></table>>] Table1:table2s -> Table2:id Table2:table1 -> Table1:id Table2:table6s -> Table6:id Table3:table6s -> Table6:id Table4:table6s -> Table6:id Table5:table6s -> Table6:id Table6:table2 -> Table2:id Table6:table3 -> Table3:id Table6:table6 -> Table5:id Table6:table4s -> Table4:id Table6:table7s -> Table7:id Table6:table8 -> Table8:id Table6:table10 -> Table10:id Table7:table10 -> Table10:id Table7:table6 -> Table6:id Table7:tabel14s -> Table14:id Table7:table9s -> Table9:id Table8:table11s -> Table11:id Table8:table6s -> Table6:id Table9:table12s -> Table12:id Table9:table11s -> Table11:id Table9:table7s -> Table7:id Table9:table9s -> Table9:id Table10:transactions -> Table11:id Table10:table7s -> Table7:id Table10:table6s -> Table6:id Table11:table10 -> Table10:id Table11:table8 -> Table8:id Table11:table9s -> Table9:id Table12:table9s -> Table9:id Table13:table14s -> Table14:id Table14:table13 -> Table13:id Table14:table7s -> Table7:id overlap=false } 属性的默认算法( dot )上的图形可能会有所帮助(在您的情况下,将其设置为rankdir