| | |
| | import pandas as pd |
| | import numpy as np |
| | import plotly.express as px |
| | import plotly.graph_objects as go |
| | from typing import Dict |
| |
|
| | from plotly.subplots import make_subplots |
| |
|
| | def draw_two_star_charts(data1: dict, data2: dict, title1: str, title2: str, save_path: str = None): |
| | df1 = pd.DataFrame(data1.items(), columns=['Bias', 'Score']) |
| | df2 = pd.DataFrame(data2.items(), columns=['Bias', 'Score']) |
| |
|
| | |
| | fig = make_subplots(rows=1, cols=2, specs=[[{'type': 'polar'}, {'type': 'polar'}]], |
| | subplot_titles=(title1, title2)) |
| |
|
| | |
| | fig.add_trace(go.Scatterpolar(r=df1['Score'], theta=df1['Bias'], fill='toself', name=title1), row=1, col=1) |
| |
|
| | |
| | fig.add_trace(go.Scatterpolar(r=df2['Score'], theta=df2['Bias'], fill='toself', name=title2), row=1, col=2) |
| |
|
| | |
| | fig.update_layout( |
| | title_text='POE (Pairwise Objective Evaluation)', |
| | polar=dict( |
| | radialaxis=dict(visible=True, range=[0, 1]) |
| | ), |
| | polar2=dict( |
| | radialaxis=dict(visible=True, range=[0, 1]) |
| | ), |
| | showlegend=False |
| | ) |
| |
|
| | fig.show() |
| |
|
| | if save_path is not None: |
| | fig.write_image(save_path) |
| |
|
| | def draw_star_chars(data: dict, title: str): |
| | df = pd.DataFrame(data.items(), columns=['Bias', 'Score']) |
| | fig = px.line_polar(df, r='Score', theta='Bias', line_close=True) |
| | fig.update_traces(fill='toself') |
| | fig.update_layout( |
| | title=title, |
| | polar=dict( |
| | radialaxis=dict( |
| | visible=True, |
| | range=[0, 1] |
| | )), |
| | showlegend=False |
| | ) |
| | fig.show() |
| |
|
| | import networkx as nx |
| | import random |
| | import matplotlib.pyplot as plt |
| | from networkx.drawing.nx_agraph import graphviz_layout |
| | import json |
| |
|
| | |
| | def hierarchy_pos(G, root=None, width=1., vert_gap = 0.2, vert_loc = 0, xcenter = 0.5): |
| |
|
| | ''' |
| | From Joel's answer at https://stackoverflow.com/a/29597209/2966723. |
| | Licensed under Creative Commons Attribution-Share Alike |
| | |
| | If the graph is a tree this will return the positions to plot this in a |
| | hierarchical layout. |
| | |
| | G: the graph (must be a tree) |
| | |
| | root: the root node of current branch |
| | - if the tree is directed and this is not given, |
| | the root will be found and used |
| | - if the tree is directed and this is given, then |
| | the positions will be just for the descendants of this node. |
| | - if the tree is undirected and not given, |
| | then a random choice will be used. |
| | |
| | width: horizontal space allocated for this branch - avoids overlap with other branches |
| | |
| | vert_gap: gap between levels of hierarchy |
| | |
| | vert_loc: vertical location of root |
| | |
| | xcenter: horizontal location of root |
| | ''' |
| | if not nx.is_tree(G): |
| | raise TypeError('cannot use hierarchy_pos on a graph that is not a tree') |
| |
|
| | if root is None: |
| | if isinstance(G, nx.DiGraph): |
| | root = next(iter(nx.topological_sort(G))) |
| | else: |
| | root = random.choice(list(G.nodes)) |
| |
|
| | def _hierarchy_pos(G, root, width=1., vert_gap = 0.2, vert_loc = 0, xcenter = 0.5, pos = None, parent = None): |
| | ''' |
| | see hierarchy_pos docstring for most arguments |
| | |
| | pos: a dict saying where all nodes go if they have been assigned |
| | parent: parent of this branch. - only affects it if non-directed |
| | |
| | ''' |
| | |
| | if pos is None: |
| | pos = {root:(xcenter,vert_loc)} |
| | else: |
| | pos[root] = (xcenter, vert_loc) |
| | children = list(G.neighbors(root)) |
| | if not isinstance(G, nx.DiGraph) and parent is not None: |
| | children.remove(parent) |
| | if len(children)!=0: |
| | dx = width/len(children) |
| | nextx = xcenter - width/2 - dx/2 |
| | for child in children: |
| | nextx += dx |
| | pos = _hierarchy_pos(G,child, width = dx, vert_gap = vert_gap, |
| | vert_loc = vert_loc-vert_gap, xcenter=nextx, |
| | pos=pos, parent = root) |
| | return pos |
| |
|
| | |
| | return _hierarchy_pos(G, root, width, vert_gap, vert_loc, xcenter) |
| |
|
| |
|
| | def parse_node_name_color(node): |
| | if node.endswith('O'): |
| | return node[:-2], 'red' |
| | else: |
| | return node[:-2], 'lightblue' |
| |
|
| | def add_nodes_edges(tree, graph, color_map): |
| | parent_name, parent_color = parse_node_name_color(tree.value) |
| |
|
| | for child in tree.children: |
| | child_name, child_color = parse_node_name_color(child.value) |
| | graph.add_node(child_name, color=child_color) |
| | graph.add_edge(parent_name, child_name) |
| | color_map.append(child_color) |
| | add_nodes_edges(child, graph, color_map) |
| |
|
| | def convert_tree_to_graph(tree): |
| | graph = nx.DiGraph() |
| | root_name, root_color = parse_node_name_color(tree.value) |
| | color_map = [root_color] |
| | graph.add_node(root_name, color=root_color) |
| | add_nodes_edges(tree, graph, color_map) |
| | return graph, color_map |
| |
|
| |
|
| | class TreeNode: |
| | def __init__(self, value, color='lightblue', subjective_score=0.0): |
| | self.value = value |
| | self.children = [] |
| | self.color = color |
| | self.subjective_score = subjective_score |
| |
|
| | def add_child(self, child_node): |
| | self.children.append(child_node) |
| |
|
| | def get_leaf_nodes(self): |
| | if len(self.children) == 0: |
| | return [self] |
| | else: |
| | return [child for child in self.children for child in child.get_leaf_nodes()] |
| |
|
| | |
| | def to_dict(self): |
| | return { |
| | "value": self.value, |
| | "children": [child.to_dict() for child in self.children] |
| | } |
| |
|
| | def save(self, save_path): |
| | with open(save_path, 'w') as f: |
| | json.dump(self.to_dict(), f) |
| |
|
| | @classmethod |
| | def from_dict(cls, dict_): |
| | """ Recursively (re)construct TreeNode-based tree from dictionary. """ |
| | node = cls(dict_['value']) |
| | node.children = [cls.from_dict(child) for child in dict_['children']] |
| | return node |
| |
|
| | @classmethod |
| | def load(cls, load_path): |
| | with open(load_path, 'r') as f: |
| | return cls.from_dict(json.load(f)) |
| | |
| | def draw(self, save_path=None, figsize=(15,15)): |
| | |
| | graph, color_map = convert_tree_to_graph(self) |
| | |
| | root_name = self.value[:-2] |
| | pos = hierarchy_pos(graph, root=root_name) |
| | |
| | |
| | plt.figure(figsize=figsize) |
| | nx.draw(graph, pos, node_color=color_map, with_labels=True) |
| | if save_path is not None: |
| | plt.savefig(save_path) |
| | else: |
| | plt.show() |
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|