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

问题描述 投票:0回答:1

我正在使用graphviz创建一个显示基于小马的数据库模式的图表。然而,架构最终是非常复杂的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
}
dot graph-visualization
1个回答
1
投票
  • 使用ortho路由将使图表更加开胃。
  • 边缘迟早会不可避免地跑过其他东西,所以设置一点透明度也可能有所帮助(edge[color="#00000080"])。
  • 此外,由于它是关于表之间的关系,您可能希望使图形成为有向图,因此您可以看到它们在哪个方向(或者在全局边缘声明中使用dir和arrowtail /箭头属性,即edge[color="#00000080" dir=both arrowtail=crow arrowhead=none])下面简单地说它是一个有向图

让图表看起来很漂亮可能需要大量的修补。 ortho路由是我发现的最接近“魔法”属性的路由。缺点是它不能扩展到大图(几百个或更多节点)。

tweaked result with 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
}

B.t.w.你使用了neato算法(在这种情况下确实给出了最好的结果) - 对于默认算法(点),使用图表上的rankdir属性可能有所帮助(在你的情况下将其设置为LR

© www.soinside.com 2019 - 2024. All rights reserved.