Guest User

Untitled

a guest
Jan 25th, 2019
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.29 KB | None | 0 0
  1. import argparse
  2. import psycopg2
  3. import psycopg2.extras
  4.  
  5. try:
  6. import igraph
  7. except ImportError:
  8. print("""
  9. Please install igraph library
  10.  
  11. pip install python-igraph cairocffi
  12.  
  13. """)
  14. raise
  15.  
  16.  
  17. def get_data(db_name, user, password, schema, table):
  18. conn = psycopg2.connect(f"dbname={db_name} user={user} password={password}")
  19.  
  20. # create a cursor
  21. cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
  22.  
  23. cur.execute(f'SELECT * FROM {schema}.{table}')
  24. data = cur.fetchall()
  25.  
  26. cur.close()
  27. conn.close()
  28.  
  29. return data
  30.  
  31.  
  32. def create_graph(data):
  33. g = igraph.Graph(directed=True)
  34.  
  35. # Add vertices
  36. for db_row in data:
  37. label = f"""{db_row['term_id']}
  38. {db_row['term_name'][:24]}
  39. LVL:{db_row['level']} - SO:{db_row['sort_order']}
  40. L:{db_row['lft']} - R:{db_row['rght']}"""
  41.  
  42. g.add_vertex(name=db_row["term_id"], label=label, **db_row)
  43.  
  44. # map id to vertex
  45. vertices = {v["term_id"]: v for v in g.vs}
  46.  
  47. # Add edges
  48. for term_id, v in vertices.items():
  49. parent_id = v["parent_id"]
  50. if parent_id is not None:
  51. parent_v = vertices[parent_id]
  52.  
  53. kwds = {"color": get_edge_color(parent_v, v)}
  54.  
  55. g.add_edge(parent_v, v, **kwds)
  56.  
  57. # check vertices
  58. for v in g.vs:
  59. color_left_right(g, v)
  60.  
  61. return g
  62.  
  63.  
  64. def get_edge_color(parent_v, v):
  65. if parent_v["level"] != v["level"] - 1:
  66. return "red"
  67.  
  68. return {0: "blue", 1: "brown"}.get(parent_v["level"], "black")
  69.  
  70.  
  71. def color_left_right(graph, source_vertex):
  72. if "color" in source_vertex.attributes() and source_vertex["color"] is not None:
  73. return (source_vertex["sort_order"], source_vertex["true_lft"], source_vertex["true_rght"])
  74. source_vertex["color"] = "pink"
  75.  
  76. children_so_left_right = []
  77. children = graph.es.select(_source_in=[source_vertex.index])
  78. for child_edge in children:
  79. child_v = graph.vs[child_edge.target]
  80. child_data = color_left_right(graph, child_v)
  81.  
  82. children_so_left_right.append(child_data)
  83.  
  84. so, left, right = source_vertex["sort_order"], source_vertex["lft"], source_vertex["rght"]
  85.  
  86. # in case of no child
  87. if not children_so_left_right:
  88. if right != left + 1:
  89. source_vertex["color"] = "yellow"
  90.  
  91. source_vertex["true_lft"] = left
  92. source_vertex["true_rght"] = right
  93.  
  94. return (so, left, right)
  95.  
  96. # check sort_order matches left and right
  97. children_so_left_right.sort()
  98. prev = children_so_left_right[0]
  99.  
  100. for child in children_so_left_right[1:]:
  101. _, _, p_rght = prev
  102. _, c_lft, _ = child
  103.  
  104. if p_rght + 1 != c_lft:
  105. source_vertex["color"] = "blue"
  106.  
  107. prev = child
  108.  
  109. source_vertex["true_lft"] = min(c[1] for c in children_so_left_right) - 1
  110. source_vertex["true_rght"] = max(c[2] for c in children_so_left_right) + 1
  111.  
  112. if source_vertex["true_lft"] != source_vertex["lft"] or \
  113. source_vertex["true_rght"] != source_vertex["rght"]:
  114. source_vertex["color"] = "red"
  115.  
  116. return so, source_vertex["true_lft"], source_vertex["true_rght"]
  117.  
  118.  
  119. def plot_graph(g, layout="kk"):
  120. visual_style = {
  121. "layout": g.layout(layout),
  122. "edge_width": 2,
  123. "bbox": (2400, 2400),
  124. "vertex_size": 100,
  125. "margin": 160,
  126. }
  127. igraph.plot(g, **visual_style)
  128.  
  129.  
  130. help_msg = """
  131. Plot MPTT table.
  132.  
  133. # pip install python-igraph cairocffi
  134.  
  135. Legend:
  136.  
  137. Vertices:
  138.  
  139. pink - OK
  140. blue - sort order does not match mptt order
  141. red - issue with children mptt left - right index
  142. yellow - mptt issue of leaf vertex
  143.  
  144.  
  145. Edges:
  146. Level 0 -> Level 1 - blue
  147. Level 1 -> Level 2 - brown
  148. other - black
  149.  
  150.  
  151. """
  152.  
  153. if __name__ == "__main__":
  154. parser = argparse.ArgumentParser(description=help_msg)
  155.  
  156. parser.add_argument('--db', '-d', help='Name of database', default='postgres')
  157. parser.add_argument('--user', '-u', help='Database user', default='pgadmin')
  158. parser.add_argument('--password', '-p', help='User password', required=True)
  159. parser.add_argument('--schema', '-s', help='Schema', default='cmc')
  160. parser.add_argument('--table', '-t', help='Table', default='analytic_term_tree')
  161.  
  162. args = parser.parse_args()
  163.  
  164. data = get_data(
  165. db_name=args.db,
  166. user=args.user,
  167. password=args.password,
  168. schema=args.schema,
  169. table=args.table
  170. )
  171.  
  172. g = create_graph(data)
  173. plot_graph(g)
Add Comment
Please, Sign In to add comment