Beispiel #1
0
def gen_add_input2(
        dfg: AGraph, fu: AGraph,
        input_map: Dict[str, int]) -> Tuple[List[Input], List[Output]]:
    outputs: List[Output] = []
    inputs: List[Input] = []
    nodes: List[Instruction] = []
    for node in fu.nodes():
        nodes.append(parse_instruction(node))

    nodes.sort()
    prev_o = 0
    for node in nodes:
        preds = dfg.predecessors(node.name)
        parent0 = parse_instruction(preds[0])
        parent1 = parse_instruction(preds[1])

        if parent0.name in input_map:
            label = dfg.get_node(parent0.name).attr['label']
            if 'mul' in label:
                latency = 2
            else:
                latency = 1

            i0 = prev_o + 1
            inputs.append(
                Input(i0, input_map[parent0.name], parent0.cycle + latency))
        else:
            for output in outputs:
                if output.cycle == parent0.cycle + 1:
                    i0 = output.val
                    break

        if parent1.name in input_map:
            label = dfg.get_node(parent1.name).attr['label']
            if 'mul' in label:
                latency = 2
            else:
                latency = 1

            i1 = prev_o + 1
            inputs.append(
                Input(i1, input_map[parent1.name], parent1.cycle + latency))
        else:
            for output in outputs:
                if output.cycle == parent1.cycle + 1:
                    i1 = output.val
                    break

        expected = i0 + i1
        prev_o = expected
        outputs.append(Output(expected, node.cycle + 1))

    inputs.sort()
    return inputs, outputs
Beispiel #2
0
def trace(graph: pgv.AGraph, start: str, end: str) -> pgv.AGraph:
    nxgraph = nx.nx_agraph.from_agraph(graph)
    assert(start in nxgraph and end in nxgraph)
    shortest = nx.shortest_path(nxgraph, start, end)

    shgraph = pgv.AGraph(directed=True,overlap=False,rankdir='LR')
    for e in range(len(shortest)-1):
        label = graph.get_edge(shortest[e], shortest[e+1]).attr['label']
        shgraph.add_edge(shortest[e], shortest[e+1], label=label)
    for n in shgraph.nodes_iter():
        n.attr['label'] = graph.get_node(n).attr['label']
        n.attr['style'] = graph.get_node(n).attr['style']
        n.attr['fillcolor'] = graph.get_node(n).attr['fillcolor']
    return shgraph
Beispiel #3
0
def draw_finite_state_machine(finite_state_machine: FiniteStateMachine,
                              path: str):
    """Creates a directed non-strict multi graph image representation of the FSM."""
    from pygraphviz import AGraph
    graph = AGraph(strict=False, directed=True)
    graph.add_nodes_from(finite_state_machine.state_set)
    for initial_state in finite_state_machine.initial_states:
        graph.get_node(initial_state).attr["color"] = "green"
    for element, transitions in finite_state_machine.transitions.items():
        for from_state, to_states in transitions.items():
            for to_state in to_states:
                graph.add_edge(from_state, to_state, label=element)
    for final_state in finite_state_machine.final_states:
        graph.get_node(final_state).attr["color"] = "red"
    graph.draw(path, prog="dot")
def gen_alloc_insts(rf_allocs: List[RFallocation], dfg: AGraph, fu: AGraph,
                    input_map: Dict[str, int]) -> List[ATAI]:
    rf_insts = []

    for rf_alloc in rf_allocs:
        inst = parse_instruction(dfg.get_node(rf_alloc.name))
        if rf_alloc.type == RFallocation.FUTypes.MUL:
            latency = Config.MUL_LATENCY
        elif rf_alloc.type == RFallocation.FUTypes.ADD:
            latency = Config.ADD_LATENCY
        else:
            # TODO: load inst latency?
            latency = 1

        if rf_alloc.name in fu:
            input_type = OpInput()
        else:
            # TODO: map fu input
            input_type = FUinput(input_map[rf_alloc.name])
            if input_type is None:
                raise AllocException('alloc not found in input map')

        cycle = inst.cycle + latency
        rf_insts.append(ATAStore(input_type, rf_alloc.address, cycle))

    return rf_insts
def gen_op_insts(rf_allocs: List[RFallocation], dfg: AGraph, fu: AGraph,
                 input_map: Dict[str, int]) -> List[ATAI]:
    assembly = []
    instructions: List[Instruction] = []

    for instruction in fu.nodes():
        instructions.append(parse_instruction(instruction))

    for instruction in instructions:
        n = dfg.get_node(instruction.name)
        nodes = dfg.predecessors(n)

        input_type0 = inst_input_type(rf_allocs, fu, nodes[0])
        if len(nodes) > 1:
            input_type1 = inst_input_type(rf_allocs, fu, nodes[1])
        else:
            input_type1 = input_type0

        # This should never occur but we check for it anyways
        if input_type0 == OpInput and input_type1 == OpInput:
            if nodes[0] != nodes[1]:
                raise DoubleUnidenticalOPInputException

        # TODO: find scheduling for fetch ops might need to be swapped to fit?
        if input_type0 == RFInput:
            # If the data is in the RF we need to generate fetch instructions
            assembly.append(
                generate_fetch(rf_allocs, instruction, nodes[0],
                               ATAFetch.REG.REG0))
            input0 = RFInput()
        elif input_type0 == OpInput:
            input0 = OpInput()
        else:
            n = input_map[nodes[0].get_name()]
            if n is None:
                raise FUinputException(
                    'Cannot find FU from which predecessing node originates in map'
                )

            input0 = FUinput(n)

        if input_type1 == RFInput:
            assembly.append(
                generate_fetch(rf_allocs, instruction, nodes[1],
                               ATAFetch.REG.REG1))
            input1 = RFInput()
        elif input_type1 == OpInput:
            input1 = OpInput()
        else:
            n = input_map[nodes[1].get_name()]
            if n is None:
                raise FUinputException(
                    'Cannot find FU from which predecessing node originates in map'
                )

            input1 = FUinput(n)

        assembly.append(ATAOp(input0, input1, instruction.cycle))

    return assembly
Beispiel #6
0
 def to_dot(self, filename, edges):
     from pygraphviz import AGraph
     dot = AGraph(directed=True)
     for n in edges.keys():
         dot.add_node(str(n))
         if lib.qcgc_arena_get_blocktype(ffi.cast(
                 "cell_t *", n)) not in [lib.BLOCK_BLACK, lib.BLOCK_WHITE]:
             node = dot.get_node(str(n))
             node.attr['color'] = 'red'
     for n in edges.keys():
         if edges[n] is not None:
             dot.add_edge(str(n), str(edges[n]))
     dot.layout(prog='dot')
     dot.draw(filename)
Beispiel #7
0
 def to_dot(self, filename, edges):
     from pygraphviz import AGraph
     dot = AGraph(directed=True)
     for n in edges.keys():
         dot.add_node(str(n))
         if lib.qcgc_arena_get_blocktype(ffi.cast("cell_t *", n)) not in [
                 lib.BLOCK_BLACK, lib.BLOCK_WHITE]:
             node = dot.get_node(str(n))
             node.attr['color'] = 'red'
     for n in edges.keys():
         if edges[n] is not None:
             dot.add_edge(str(n), str(edges[n]))
     dot.layout(prog='dot')
     dot.draw(filename)
def draw_workflow(filename, workflow, paint=None):
    dot = AGraph(directed=True)  # (comment="Computing scheme")
    dot.node_attr['style'] = 'filled'
    for i, n in workflow.nodes.items():
        dot.add_node(i,
                     label="{0} \n {1}".format(
                         n.foo.__name__,
                         _format_arg_list(n.bound_args.args, None)))
        x = dot.get_node(i)
        if paint:
            paint(x, n.foo.__name__)

    for i in workflow.links:
        for j in workflow.links[i]:
            dot.add_edge(i, j[0])
    dot.layout(prog='dot')

    dot.draw(filename)
def draw_graph(state_manager, filename):
    graph = AGraph()
    graph.node_attr["style"] = "filled"
    graph.node_attr["shape"] = "circle"
    graph.node_attr["fixedsize"] = "true"
    graph.node_attr["width"] = 0.5
    graph.node_attr["height"] = 0.5

    # we add all nodes (keys = ID)
    graph.add_nodes_from(state_manager.state.keys())
    for var_id in state_manager.state:
        # and for each of these nodes, we change color
        node = graph.get_node(var_id)
        node.attr["fillcolor"] = get_color(state_manager.state[var_id])

    # finally, we add edges
    for c in state_manager.constraints:
        e = c.list_vars
        graph.add_edge(e[0], e[1])

    graph.write(filename)
Beispiel #10
0
def dot_layout(cy_elements):
    """
    Get a CyElements object and augment it (in-place) with positions,
    widths, heights, and spline data from a dot based layout.

    Returns the object.
    """
    elements = cy_elements.elements
    g = AGraph(directed=True, strict=False)

    # make transitive relations appear top to bottom
    # TODO: make this not specific to leader example
    elements = list(elements)
    nodes_by_id = dict(
        (e["data"]["id"], e) for e in elements if e["group"] == "nodes")
    order = [(nodes_by_id[e["data"]["source"]],
              nodes_by_id[e["data"]["target"]]) for e in elements
             if e["group"] == "edges" and e["data"]["obj"] in ('reach', 'le')]
    elements = topological_sort(elements, order, lambda e: e["data"]["id"])

    # add nodes to the graph
    for e in elements:
        if e["group"] == "nodes":
            g.add_node(e["data"]["id"],
                       label=e["data"]["label"].replace('\n', '\\n'))

    # TODO: remove this, it's specific to leader_demo
    weight = {
        'reach': 10,
        'le': 10,
        'id': 1,
    }
    constraint = {
        'pending': False,
    }

    # add edges to the graph
    for e in elements:
        if e["group"] == "edges":
            g.add_edge(
                e["data"]["source"],
                e["data"]["target"],
                e["data"]["id"],
                weight=weight.get(e["data"]["obj"], 0),
                #constraint=constraint.get(e["data"]["obj"], True),
            )

    # add clusters
    clusters = defaultdict(list)
    for e in elements:
        if e["group"] == "nodes" and e["data"]["cluster"] is not None:
            clusters[e["data"]["cluster"]].append(e["data"]["id"])
    for i, k in enumerate(sorted(clusters.keys())):
        g.add_subgraph(
            name='cluster_{}'.format(i),
            nbunch=clusters[k],
        )

    # now get positions, heights, widths, and bsplines
    g.layout(prog='dot')
    for e in elements:
        if e["group"] == "nodes":
            attr = g.get_node(e["data"]["id"]).attr
            e["position"] = _to_position(attr['pos'])
            e["data"]["width"] = 72 * float(attr['width'])
            e["data"]["height"] = 72 * float(attr['height'])

        elif e["group"] == "edges":
            attr = g.get_edge(e["data"]["source"], e["data"]["target"],
                              e["data"]["id"]).attr
            e["data"].update(_to_edge_position(attr['pos']))
    g.draw('g.png')

    return cy_elements
Beispiel #11
0
def dot_layout(cy_elements,
               edge_labels=False,
               subgraph_boxes=False,
               node_gt=None):
    """
    Get a CyElements object and augment it (in-place) with positions,
    widths, heights, and spline data from a dot based layout.

    edge_labels is true if labels should appear on edges
    subgraph_boxes is true if boxes should be drawn around subgraphs

    Returns the object.
    """
    elements = cy_elements.elements

    #    g = AGraph(directed=True, strict=False)
    g = AGraph(directed=True, strict=False, forcelabels=True)

    # make transitive relations appear top to bottom

    elements = list(elements)
    nodes_by_id = dict(
        (e["data"]["id"], e) for e in elements if e["group"] == "nodes")
    order = [(nodes_by_id[e["data"]["source"]],
              nodes_by_id[e["data"]["target"]]) for e in elements
             if e["group"] == "edges" and "transitive" in e["data"]
             and e["data"]["transitive"]]
    elements = topological_sort(elements, order, lambda e: e["data"]["id"])

    # get the node id's and stable sort them by cluster
    # the idea here is to convert the graph into a dag by sorting
    # the nodes, then reversing the back edges. In particular, we try to make
    # all the edges between two clusters go in the same direction so clustering
    # doesn't result in horizontal edges, which dot renders badly.

    sorted_nodes = [e["data"]["id"] for e in elements if e["group"] == "nodes"]
    sorted_nodes = sorted(enumerate(sorted_nodes),
                          key=lambda x:
                          (nodes_by_id[x[1]]["data"]["cluster"], x[0]))
    sorted_nodes = [y for idx, y in sorted_nodes]
    node_key = dict((id, idx) for idx, id in enumerate(sorted_nodes))

    if node_gt is None:
        node_gt = lambda X, y: False
    else:
        node_gt = lambda x, y: node_key[x] > node_key[y]

    # add nodes to the graph
    for e in elements:
        if e["group"] == "nodes" and e["classes"] != 'non_existing':
            g.add_node(e["data"]["id"],
                       label=e["data"]["label"].replace('\n', '\\n'))

    # TODO: remove this, it's specific to leader_demo
    weight = {
        'reach': 10,
        'le': 10,
        'id': 1,
    }
    constraint = {
        'pending': False,
    }

    # add edges to the graph
    for e in elements:
        if e["group"] == "edges":
            #            kwargs = {'weight': weight.get(e["data"]["obj"], 0)},
            kwargs = {'label': e["data"]["label"]} if edge_labels else {}
            if node_gt(e["data"]["source"], e["data"]["target"]):
                g.add_edge(e["data"]["target"],
                           e["data"]["source"],
                           e["data"]["id"],
                           dir='back',
                           **kwargs
                           #constraint=constraint.get(e["data"]["obj"], True),
                           )
            else:
                g.add_edge(e["data"]["source"], e["data"]["target"],
                           e["data"]["id"], **kwargs
                           #constraint=constraint.get(e["data"]["obj"], True),
                           )

    # add clusters
    clusters = defaultdict(list)
    for e in elements:
        if e["group"] == "nodes" and e["data"][
                "cluster"] is not None and e["classes"] != 'non_existing':
            clusters[e["data"]["cluster"]].append(e["data"]["id"])
    for i, k in enumerate(sorted(clusters.keys())):
        g.add_subgraph(
            name='cluster_{}'.format(i),
            nbunch=clusters[k],
            rank='min',
        )

    # now get positions, heights, widths, and bsplines
    g.layout(prog='dot')

    # get the y origin. we want the top left of the graph to be a
    # fixed coordinate (hopefully (0,0)) so the graph doesn't jump when
    # its height changes. Unfortunately, pygraphviz has a bug a gives
    # the wrong bbox, so we compute the max y coord.

    #    bbox = pygraphviz.graphviz.agget(g.handle,'bb')

    global y_origin
    y_origin = 0.0
    for n in g.nodes():
        top = float(n.attr['pos'].split(',')[1]) + float(n.attr['height']) / 2
        if top > y_origin:
            y_origin = top
    if subgraph_boxes:
        for sg in g.subgraphs():
            top = float(sg.graph_attr['bb'].split(',')[3])
            if top > y_origin:
                y_origin = top

    for e in elements:
        if e["group"] == "nodes" and e["classes"] != 'non_existing':
            attr = g.get_node(e["data"]["id"]).attr
            e["position"] = _to_position(attr['pos'])
            e["data"]["width"] = 72 * float(attr['width'])
            e["data"]["height"] = 72 * float(attr['height'])

        elif e["group"] == "edges":
            if node_gt(e["data"]["source"], e["data"]["target"]):
                attr = g.get_edge(e["data"]["target"], e["data"]["source"],
                                  e["data"]["id"]).attr
                pos = attr['pos']
                pe = pos.split()
                ppe = pe[1:]
                ppe.reverse()
                pos = ' '.join([pe[0].replace('s', 'e')] + ppe)
            else:
                attr = g.get_edge(e["data"]["source"], e["data"]["target"],
                                  e["data"]["id"]).attr
                pos = attr['pos']
            e["data"].update(_to_edge_position(pos))
            if edge_labels and e["data"]["label"] != '':
                e["data"]["lp"] = _to_position(attr['lp'])
#    g.draw('g.png')

    if subgraph_boxes:
        for sg in g.subgraphs():
            box = cy_elements.add_shape(sg.name, classes='subgraphs')
            coords = _to_coord_list(sg.graph_attr['bb'])
            box["data"]["coords"] = coords

    return cy_elements
def recalculate(user):
    # remove old ranking
    RankedTeam.objects.filter(team__user = user).delete()
    for pic in RankingPicture.objects.all():
        pic.image.delete()
        pic.delete()
    color_index = 0

    team_graph = Graph()
    gvfull = AGraph(directed = True)
    for team in user.teams.all():
        gvfull.add_node(asciiname(team), label = team.name)
        team_graph.add_node(team)
    for game in Game.objects.filter(team_1__user = user, team_2__user = user):
        team_graph.add_edge(game.winner(), game.loser(), game.jugg_diff())
    for source, dest, weight in team_graph.edges():
        gvfull.add_edge(asciiname(source), asciiname(dest), label = str(weight))

    current_place = 1
    gvcircles = AGraph(directed = True)
    gvtiebreaker = AGraph(directed = True)
    for place in team_graph.topological_sort():
        place_list = []
        relevant_teams = set()
        for circle in place:
            relevant_teams |= circle
            if len(circle) == 1:
                continue
            color_index, current_color = getcolor(color_index)
            for team in circle:
                gvcircles.add_node(asciiname(team), label = team.name, color = current_color, fontcolor = current_color)
                gvfull.get_node(asciiname(team)).attr['color'] = current_color
                gvfull.get_node(asciiname(team)).attr['fontcolor'] = current_color
            for source, dest, weight in team_graph.edges():
                if source in circle and dest in circle:
                    gvcircles.add_edge(asciiname(source), asciiname(dest), label = str(weight), color = current_color, fontcolor = current_color)
                    gvfull.get_edge(asciiname(source), asciiname(dest)).attr['color'] = current_color
                    gvfull.get_edge(asciiname(source), asciiname(dest)).attr['fontcolor'] = current_color
        place = [[(team.normalized_jugg_diff(relevant_teams), team.name, team) for team in circle] for circle in place]
        for circle in place:
            circle.sort(reverse = True)
        while place:
            place_list.append(set())
            i = 0
            while i < len(place):
                circle = place[i]
                jd = circle[0][0]
                while circle and circle[0][0] == jd:
                    place_list[-1].add(circle.pop(0))
                if not circle:
                    place.remove(circle)
                else:
                    i += 1
        for same_place_set in place_list:
            # tie breaker
            if len(same_place_set) > 1:
                # teams that everyone on this place played against
                relevant_teams = team_graph.nodes()
                for circ_jugg_diff, name, team in same_place_set:
                    opponents = set()
                    for game in team.games():
                        if game.team_1 == team:
                            opponents.add(game.team_2)
                        else:
                            opponents.add(game.team_1)
                    relevant_teams &= opponents
                if len(relevant_teams) > 0:
                    color_index, current_color_a = getcolor(color_index)
                    color_index, current_color_b = getcolor(color_index)
                    for team in relevant_teams:
                        gvtiebreaker.add_node("b-" + asciiname(team), label = team.name, color = current_color_b, fontcolor = current_color_b)
                    for void, void, team in same_place_set:
                        gvtiebreaker.add_node("a-" + asciiname(team), label = team.name, color = current_color_a, fontcolor = current_color_a)
                        for game in team.games():
                            if game.team_1 == team and game.team_2 in relevant_teams:
                                if game.winner() == team:
                                    gvtiebreaker.add_edge("a-" + asciiname(team), "b-" + asciiname(game.team_2), label = game.jugg_diff(), color = current_color_a, fontcolor = current_color_a)
                                else:
                                    gvtiebreaker.add_edge("b-" + asciiname(game.team_2), "a-" + asciiname(team), label = game.jugg_diff(), color = current_color_b, fontcolor = current_color_b)
                            elif game.team_2 == team and game.team_1 in relevant_teams:
                                if game.winner() == team:
                                    gvtiebreaker.add_edge("a-" + asciiname(team), "b-" + asciiname(game.team_1), label = game.jugg_diff(), color = current_color_a, fontcolor = current_color_a)
                                else:
                                    gvtiebreaker.add_edge("b-" + asciiname(game.team_1), "a-" + asciiname(team), label = game.jugg_diff(), color = current_color_b, fontcolor = current_color_b)
                # jugg differences against relevant teams
                rel_jugg_diffs = set()
                for team_tuple in same_place_set:
                    rel_jugg_diffs.add((team_tuple, team_tuple[2].normalized_jugg_diff(relevant_teams)))
                # pop all teams, highest relevant jugg difference first
                while rel_jugg_diffs:
                    # current maximum
                    max_rel_jugg_diff = None
                    # teams with maximum jugg difference
                    to_remove = None
                    for team_tuple, rel_jugg_diff in rel_jugg_diffs:
                        # new maximum
                        if max_rel_jugg_diff is None or rel_jugg_diff > max_rel_jugg_diff[0]:
                            max_rel_jugg_diff = (rel_jugg_diff, {team_tuple})
                            to_remove = {(team_tuple, rel_jugg_diff)}
                        # same as maximum
                        elif rel_jugg_diff == max_rel_jugg_diff[0]:
                            max_rel_jugg_diff[1].add(team_tuple)
                            to_remove.add((team_tuple, rel_jugg_diff))
                    # remove teams with maximum jugg difference
                    rel_jugg_diffs -= to_remove
                    # add teams to listing
                    for (circ_jugg_diff, name, team), rel_jugg_diff in to_remove:
                        RankedTeam.objects.create(place = current_place, team = team)
                    current_place += 1
            else:
                circ_jugg_diff, name, team = same_place_set.pop()
                RankedTeam.objects.create(place = current_place, team = team)
                current_place += 1
    with tempfile.NamedTemporaryFile(suffix = ".png") as tmp:
        gvfull.draw(tmp, "png", "dot")
        pic = RankingPicture(user = user, image = File(tmp), title = "Full Team Graph")
        pic.save()
    with tempfile.NamedTemporaryFile(suffix = ".png") as tmp:
        gvcircles.draw(tmp, "png", "dot")
        pic = RankingPicture(user = user, image = File(tmp), title = "Circles")
        pic.save()
    with tempfile.NamedTemporaryFile(suffix = ".png") as tmp:
        gvtiebreaker.draw(tmp, "png", "dot")
        pic = RankingPicture(user = user, image = File(tmp), title = "Tie Breaker")
        pic.save()
Beispiel #13
0
class GraphGeneratingReporter(BaseReporter):
    def __init__(self):
        self.evolution = []  # List[str]
        self._evaluating = None

        # Dict[Candidate, Set[Requirement]]
        self._dependencies = defaultdict(set)
        # Dict[Candidate.name, Counter[Requirement]]
        self._active_requirements = defaultdict(Counter)

        self._node_names = {}
        self._counter = count()

        self.graph = AGraph(
            directed=True,
            rankdir="LR",
            labelloc="top",
            labeljust="center",
            nodesep="0",
            concentrate="true",
        )
        self.graph.add_node("root", label=":root:", shape="Mdiamond")
        self._node_names[self._key(None)] = "root"

        del self.graph.node_attr["label"]
        self.graph.edge_attr.update({
            "arrowhead": "empty",
            "style": "dashed",
            "color": "#808080"
        })

    #
    # Internal Graph-handling API
    #
    def _prepare_node(self, obj):
        cls = obj.__class__.__name__
        n = next(self._counter)
        node_name = f"{cls}_{n}"
        self._node_names[self._key(obj)] = node_name
        return node_name

    def _key(self, obj):
        if obj is None:
            return None
        return (
            obj.__class__.__name__,
            repr(obj),
        )

    def _get_subgraph(self, name, *, must_exist_already=True):
        name = canonicalize_name(name)

        c_name = f"cluster_{name}"
        subgraph = self.graph.get_subgraph(c_name)
        if subgraph is None:
            if must_exist_already:
                existing = [s.name for s in self.graph.subgraphs_iter()]
                raise RuntimeError(
                    f"Graph for {name} not found. Existing: {existing}")
            else:
                subgraph = self.graph.add_subgraph(name=c_name, label=name)

        return subgraph

    def _add_candidate(self, candidate):
        if candidate is None:
            return
        if self._key(candidate) in self._node_names:
            return

        node_name = self._prepare_node(candidate)

        # A candidate is only seen after a requirement with the same name.
        subgraph = self._get_subgraph(candidate.name, must_exist_already=True)
        subgraph.add_node(node_name, label=candidate.version, shape="box")

    def _add_requirement(self, req):
        if self._key(req) in self._node_names:
            return

        name = self._prepare_node(req)

        subgraph = self._get_subgraph(req.name, must_exist_already=False)
        subgraph.add_node(name, label=str(req.specifier) or "*", shape="cds")

    def _ensure_edge(self, from_, *, to, **attrs):
        from_node = self._node_names[self._key(from_)]
        to_node = self._node_names[self._key(to)]

        try:
            existing = self.graph.get_edge(from_node, to_node)
        except KeyError:
            attrs.update(headport="w", tailport="e")
            self.graph.add_edge(from_node, to_node, **attrs)
        else:
            existing.attr.update(attrs)

    def _get_node_for(self, obj):
        node_name = self._node_names[self._key(obj)]
        node = self.graph.get_node(node_name)
        assert node is not None
        return node_name, node

    def _track_evaluating(self, candidate):
        if self._evaluating != candidate:
            if self._evaluating is not None:
                self.backtracking(self._evaluating, internal=True)
                self.evolution.append(self.graph.to_string())
            self._evaluating = candidate

    #
    # Public reporter API
    #
    def starting(self):
        print("starting(self)")

    def starting_round(self, index):
        print(f"starting_round(self, {index})")
        # self.graph.graph_attr["label"] = f"Round {index}"
        self.evolution.append(self.graph.to_string())

    def ending_round(self, index, state):
        print(f"ending_round(self, {index}, state)")

    def ending(self, state):
        print("ending(self, state)")

    def adding_requirement(self, req, parent):
        print(f"adding_requirement(self, {req!r}, {parent!r})")
        self._track_evaluating(parent)

        self._add_candidate(parent)
        self._add_requirement(req)

        self._ensure_edge(parent, to=req)

        self._active_requirements[canonicalize_name(req.name)][req] += 1
        self._dependencies[parent].add(req)

        if parent is None:
            return

        # We're seeing the parent candidate (which is being "evaluated"), so
        # color all "active" requirements pointing to the it.
        # TODO: How does this interact with revisited candidates?
        for parent_req in self._active_requirements[canonicalize_name(
                parent.name)]:
            self._ensure_edge(parent_req, to=parent, color="#80CC80")

    def backtracking(self, candidate, internal=False):
        print(f"backtracking(self, {candidate!r}, internal={internal})")
        self._track_evaluating(candidate)
        self._evaluating = None

        # Update the graph!
        node_name, node = self._get_node_for(candidate)
        node.attr.update(shape="signature", color="red")

        for edge in self.graph.out_edges_iter([node_name]):
            edge.attr.update(style="dotted", arrowhead="vee", color="#FF9999")
            _, to = edge
            to.attr.update(color="black")

        for edge in self.graph.in_edges_iter([node_name]):
            edge.attr.update(style="dotted", color="#808080")

        # Trim "active" requirements to remove anything not relevant now.
        for requirement in self._dependencies[candidate]:
            active = self._active_requirements[canonicalize_name(
                requirement.name)]
            active[requirement] -= 1
            if not active[requirement]:
                del active[requirement]

    def pinning(self, candidate):
        print(f"pinning(self, {candidate!r})")
        assert self._evaluating == candidate or self._evaluating is None
        self._evaluating = None

        self._add_candidate(candidate)

        # Update the graph!
        node_name, node = self._get_node_for(candidate)
        node.attr.update(color="#80CC80")

        # Requirement -> Candidate edges, from this candidate.
        for req in self._active_requirements[canonicalize_name(
                candidate.name)]:
            self._ensure_edge(req,
                              to=candidate,
                              arrowhead="vee",
                              color="#80CC80")

        # Candidate -> Requirement edges, from this candidate.
        for edge in self.graph.out_edges_iter([node_name]):
            edge.attr.update(style="solid", arrowhead="vee", color="#80CC80")
            _, to = edge
            to.attr.update(color="#80C080")
Beispiel #14
0
 def get_node(self, graph: AGraph):
     return graph.get_node(self.name)
Beispiel #15
0
class DotGraphSearchProblem(Problem):
    """
    Playground for stuff in the library... eats a .dot graph and allows you
    to try it with the search methods.
    """
    def __init__(self, filename):
        self.G = AGraph(filename)
        xs = [(nodo, nodo.attr.get("initial", None))
              for nodo in self.G.iternodes()]
        xs = [x for x in xs if x[1]]
        if len(xs) == 0:
            raise BadInputGraph("Missing 'initial' node")
        elif len(xs) > 1:
            raise BadInputGraph("Cannot have two initial nodes")
        if not any(nodo.attr.get("goal", None) for nodo in self.G.iternodes()):
            raise BadInputGraph("Missing a goal state '[goal=\"1\"]'")
        super(DotGraphSearchProblem, self).__init__(xs[0][0])
        self.initial_state.attr["shape"] = "doublecircle"
        for node in self.G.iternodes():
            if self.is_goal(node):
                node.attr["shape"] = "hexagon"
                node.attr["color"] = "blue"
        self.seen = set()
        self.visit(self.initial_state)
        for edge in self.G.iteredges():
            edge.attr["style"] = "dotted"
            x = edge.attr.get("weight", None)
            if x:
                x = int(x)
            else:
                x = 1
            edge.attr["weight"] = x
            edge.attr["label"] = x

    def actions(self, state):
        assert state in self.G
        if self.G.is_directed():
            return self.G.itersucc(state)
        else:
            assert self.G.is_undirected()
            return self.G.iterneighbors(state)

    def result(self, state, action):
        assert state in self.G and action in self.G
        self.visit(state)
        return action

    def cost(self, state1, action, state2):
        assert state1 in self.G and action in self.G and action == state2
        x = self.G.get_edge(state1, state2).attr["weight"]
        if float(x) == int(x):
            return int(x)
        else:
            return float(x)

    def visit(self, state):
        if state in self.seen:
            return
        self.seen.add(state)
        attr = self.G.get_node(state).attr
        attr["color"] = "firebrick"

    def is_goal(self, state):
        return bool(state.attr.get("goal", False))

    def value(self, state):
        assert state in self.G
        value = self.G.get_node(state).attr.get("value", None)
        if not value:
            return 0
        return float(value)
Beispiel #16
0
__author__ = """Aric Hagberg ([email protected])"""

from pygraphviz import AGraph

A = AGraph()

# set some default node attributes
A.node_attr['style'] = 'filled'
A.node_attr['shape'] = 'circle'
A.node_attr['fixedsize'] = 'true'
A.node_attr['fontcolor'] = '#FFFFFF'

# make a star in shades of red
for i in range( 16 ):
    A.add_edge( 0, i )
    n = A.get_node( i )
    n.attr['fillcolor'] = "#%2x0000" % ( i * 16 )
    n.attr['height'] = "%s" % ( i / 16.0 + 0.5 )
    n.attr['width'] = "%s" % ( i / 16.0 + 0.5 )

print A.string() # print to screen
A.write( "star.dot" ) # write to simple.dot
print "Wrote star.dot"
A.draw( 'star.png', prog="circo" ) # draw to png using circo
print "Wrote star.png"

import matplotlib.pyplot as plt
a = plt.imread( 'star.png' )
plt.imshow( a )
plt.show()
Beispiel #17
0
def dot_layout(cy_elements, edge_labels=False, subgraph_boxes=False, node_gt=None):
    """
    Get a CyElements object and augment it (in-place) with positions,
    widths, heights, and spline data from a dot based layout.

    edge_labels is true if labels should appear on edges
    subgraph_boxes is true if boxes should be drawn around subgraphs

    Returns the object.
    """
    elements = cy_elements.elements

    #    g = AGraph(directed=True, strict=False)
    g = AGraph(directed=True, strict=False, forcelabels=True)

    # make transitive relations appear top to bottom

    elements = list(elements)
    nodes_by_id = dict((e["data"]["id"], e) for e in elements if e["group"] == "nodes")
    order = [
        (nodes_by_id[e["data"]["source"]], nodes_by_id[e["data"]["target"]])
        for e in elements
        if e["group"] == "edges" and "transitive" in e["data"] and e["data"]["transitive"]
    ]
    elements = topological_sort(elements, order, lambda e: e["data"]["id"])

    # get the node id's and stable sort them by cluster
    # the idea here is to convert the graph into a dag by sorting
    # the nodes, then reversing the back edges. In particular, we try to make
    # all the edges between two clusters go in the same direction so clustering
    # doesn't result in horizontal edges, which dot renders badly.

    sorted_nodes = [e["data"]["id"] for e in elements if e["group"] == "nodes"]
    sorted_nodes = sorted(enumerate(sorted_nodes), key=lambda x: (nodes_by_id[x[1]]["data"]["cluster"], x[0]))
    sorted_nodes = [y for idx, y in sorted_nodes]
    node_key = dict((id, idx) for idx, id in enumerate(sorted_nodes))

    if node_gt is None:
        node_gt = lambda X, y: False
    else:
        node_gt = lambda x, y: node_key[x] > node_key[y]

    # add nodes to the graph
    for e in elements:
        if e["group"] == "nodes" and e["classes"] != "non_existing":
            g.add_node(e["data"]["id"], label=e["data"]["label"].replace("\n", "\\n"))

    # TODO: remove this, it's specific to leader_demo
    weight = {"reach": 10, "le": 10, "id": 1}
    constraint = {"pending": False}

    # add edges to the graph
    for e in elements:
        if e["group"] == "edges":
            #            kwargs = {'weight': weight.get(e["data"]["obj"], 0)},
            kwargs = {"label": e["data"]["label"]} if edge_labels else {}
            if node_gt(e["data"]["source"], e["data"]["target"]):
                g.add_edge(
                    e["data"]["target"],
                    e["data"]["source"],
                    e["data"]["id"],
                    dir="back",
                    **kwargs
                    # constraint=constraint.get(e["data"]["obj"], True),
                )
            else:
                g.add_edge(
                    e["data"]["source"],
                    e["data"]["target"],
                    e["data"]["id"],
                    **kwargs
                    # constraint=constraint.get(e["data"]["obj"], True),
                )

    # add clusters
    clusters = defaultdict(list)
    for e in elements:
        if e["group"] == "nodes" and e["data"]["cluster"] is not None and e["classes"] != "non_existing":
            clusters[e["data"]["cluster"]].append(e["data"]["id"])
    for i, k in enumerate(sorted(clusters.keys())):
        g.add_subgraph(name="cluster_{}".format(i), nbunch=clusters[k], rank="min")

    # now get positions, heights, widths, and bsplines
    g.layout(prog="dot")

    # get the y origin. we want the top left of the graph to be a
    # fixed coordinate (hopefully (0,0)) so the graph doesn't jump when
    # its height changes. Unfortunately, pygraphviz has a bug a gives
    # the wrong bbox, so we compute the max y coord.

    #    bbox = pygraphviz.graphviz.agget(g.handle,'bb')

    global y_origin
    y_origin = 0.0
    for n in g.nodes():
        top = float(n.attr["pos"].split(",")[1]) + float(n.attr["height"]) / 2
        if top > y_origin:
            y_origin = top
    if subgraph_boxes:
        for sg in g.subgraphs():
            top = float(sg.graph_attr["bb"].split(",")[3])
            if top > y_origin:
                y_origin = top

    for e in elements:
        if e["group"] == "nodes" and e["classes"] != "non_existing":
            attr = g.get_node(e["data"]["id"]).attr
            e["position"] = _to_position(attr["pos"])
            e["data"]["width"] = 72 * float(attr["width"])
            e["data"]["height"] = 72 * float(attr["height"])

        elif e["group"] == "edges":
            if node_gt(e["data"]["source"], e["data"]["target"]):
                attr = g.get_edge(e["data"]["target"], e["data"]["source"], e["data"]["id"]).attr
                pos = attr["pos"]
                pe = pos.split()
                ppe = pe[1:]
                ppe.reverse()
                pos = " ".join([pe[0].replace("s", "e")] + ppe)
            else:
                attr = g.get_edge(e["data"]["source"], e["data"]["target"], e["data"]["id"]).attr
                pos = attr["pos"]
            e["data"].update(_to_edge_position(pos))
            if edge_labels and e["data"]["label"] != "":
                e["data"]["lp"] = _to_position(attr["lp"])
    #    g.draw('g.png')

    if subgraph_boxes:
        for sg in g.subgraphs():
            box = cy_elements.add_shape(sg.name, classes="subgraphs")
            coords = _to_coord_list(sg.graph_attr["bb"])
            box["data"]["coords"] = coords

    return cy_elements
Beispiel #18
0
class DotGraphSearchProblem(Problem):
    def __init__(self, filename):
        self.G = AGraph(filename)
        xs = [(nodo, nodo.attr.get("initial", None))
              for nodo in self.G.iternodes()]
        xs = [x for x in xs if x[1]]
        if len(xs) == 0:
            raise BadInputGraph("Missing 'initial' node")
        elif len(xs) > 1:
            raise BadInputGraph("Cannot have two initial nodes")
        if not any(nodo.attr.get("goal", None) for nodo in self.G.iternodes()):
            raise BadInputGraph("Missing a goal state '[goal=\"1\"]'")
        super(DotGraphSearchProblem, self).__init__(xs[0][0])
        self.initial_state.attr["shape"] = "doublecircle"
        for node in self.G.iternodes():
            if self.is_goal(node):
                node.attr["shape"] = "hexagon"
                node.attr["color"] = "blue"
        self.seen = set()
        self.visit(self.initial_state)
        for edge in self.G.iteredges():
            edge.attr["style"] = "dotted"
            x = edge.attr.get("weight", None)
            if x:
                x = int(x)
            else:
                x = 1
            edge.attr["weight"] = x
            edge.attr["label"] = x

    def actions(self, state):
        assert state in self.G
        if self.G.is_directed():
            return self.G.itersucc(state)
        else:
            assert self.G.is_undirected()
            return self.G.iterneighbors(state)

    def result(self, state, action):
        assert state in self.G and action in self.G
        self.visit(state)
        return action

    def cost(self, state1, action, state2):
        assert state1 in self.G and action in self.G and action == state2
        x = self.G.get_edge(state1, state2).attr["weight"]
        if float(x) == int(x):
            return int(x)
        else:
            return float(x)

    def visit(self, state):
        if state in self.seen:
            return
        self.seen.add(state)
        attr = self.G.get_node(state).attr
        attr["color"] = "firebrick"

    def is_goal(self, state):
        return bool(state.attr.get("goal", False))

    def value(self, state):
        assert state in self.G
        value = self.G.get_node(state).attr.get("value", None)
        if not value:
            return 0
        return float(value)
Beispiel #19
0
def convert(graph, desired_ns=[], exclude_ns=[]):
    # graph.parse('rdf-schema.ttl', format='turtle')
    # network.feedFactsToAdd(generateTokenSet(graph))
    # for n in network.inferredFacts.triples((None, None, None)):
    #     graph.add(n)

    agraph = AGraph(directed=True, clusterrank="global", rankdir="LR")
    namespaces = {}
    nsm = graph.namespace_manager
    deferred_resources = set()
    included_resources = set()

    def prefix(ressource):
        return nsm.qname(ressource).split(':')[0]

    def add_ressource(ressource):
        if ressource not in included_resources:
            qname = nsm.qname(ressource)
            prefix = qname.split(':')[0]
            shape = 'rect' if (ressource, RDF.type,
                               OWL.Class) in graph else 'oval'
            color = 'black' if prefix in desired_ns else 'grey'
            if prefix in namespaces:
                namespaces[prefix].add_node(qname, shape=shape, color=color)
            else:
                agraph.add_node(qname, shape=shape, color=color)
            included_resources.add(ressource)
            if ressource in deferred_resources:
                deferred_resources.remove(ressource)

    def add_edge(r1, r2, **kwargs):
        pr1, pr2 = prefix(r1), prefix(r2)
        if pr1 in exclude_ns or pr2 in exclude_ns:
            return
        if pr1 in desired_ns or pr2 in desired_ns:
            add_ressource(r1)
            add_ressource(r2)
            agraph.add_edge(nsm.qname(r1), nsm.qname(r2), **kwargs)

    for kprefix, namespace in graph.namespaces():
        namespaces[kprefix] = agraph.add_subgraph(name="cluster_" + kprefix,
                                                  color="grey")
    for k in graph.subjects(RDF.type, OWL.Class):
        if isinstance(k, BNode):
            continue
        qname = nsm.qname(k)
        kprefix = prefix(k)
        if kprefix in exclude_ns:
            continue
        elif kprefix in desired_ns:
            add_ressource(k)
        else:
            deferred_resources.add(k)
    for (s, p, o) in chain(graph.triples((None, RDFS.subClassOf, None)),
                           graph.triples((None, OWL.subClassOf, None))):
        if isinstance(s, BNode) or isinstance(o, BNode):
            continue
        add_edge(s, o, arrowhead='empty', color="blue")
    prop_types = [
        OWL.Property, OWL.AnnotationProperty, OWL.DatatypeProperty,
        OWL.AsymmetricProperty, OWL.ObjectProperty, OWL.FunctionalProperty,
        OWL.InverseFunctionalProperty
    ]
    properties = set()
    for prop in prop_types:
        properties.update(graph.subjects(RDF.type, prop))
    for k in properties:
        if isinstance(k, BNode):
            continue
        qname = nsm.qname(k)
        kprefix = prefix(k)
        if kprefix in exclude_ns:
            continue
        elif kprefix in desired_ns:
            add_ressource(k)
        else:
            deferred_resources.add(k)
    for (s, p, o) in chain(graph.triples((None, RDFS.subPropertyOf, None)),
                           graph.triples((None, OWL.subPropertyOf, None))):
        if isinstance(s, BNode) or isinstance(o, BNode):
            continue
        add_edge(s, o, arrowhead='empty', color="blue")

    for (s, p, o) in graph.triples((None, OWL.equivalentClass, None)):
        if isinstance(s, BNode) or isinstance(o, BNode):
            continue
        add_edge(s, o, arrowhead="odot", arrowtail="odot", color="blue")
    for (s, p, o) in graph.triples((None, RDFS.domain, None)):
        if isinstance(s, BNode):
            continue
        if isinstance(o, BNode):
            for o2 in graph.objects(o, OWL.unionOf):
                for o3 in list_content(o2, graph):
                    add_edge(o3, s, arrowhead="open")
            for o2 in graph.objects(o, OWL.intersectionOf):
                for o3 in list_content(o2, graph):
                    add_edge(o3, s, arrowhead="open")
            continue
        add_edge(o, s, arrowhead="open")
    for (s, p, o) in graph.triples((None, RDFS.range, None)):
        if isinstance(s, BNode):
            continue
        if isinstance(o, BNode):
            for o2 in graph.objects(o, OWL.unionOf):
                for o3 in list_content(o2, graph):
                    add_edge(s, o3, arrowhead="open")
            for o2 in graph.objects(o, OWL.intersectionOf):
                for o3 in list_content(o2, graph):
                    add_edge(s, o3, arrowhead="open")
            continue
        add_edge(s, o, arrowhead="open")
    for (s, p, o) in graph.triples((None, OWL.inverseOf, None)):
        if isinstance(s, BNode) or isinstance(o, BNode):
            continue
        if str(o) < str(s):
            s, o = o, s
        add_edge(o, s, arrowhead="crow", arrowtail="crow", dir="both")

    for ressource in included_resources:
        labels = graph.objects(ressource, RDFS.label)
        en_labels = [l for l in labels if l.language == 'eng']
        if en_labels:
            label = en_labels[0]
            qname = nsm.qname(ressource)
            prefix, name = qname.split(':', 1)
            if normalize_label(name) != normalize_label(label):
                node = agraph.get_node(qname)
                node.attr['label'] = "%s\n(%s)" % (qname, label)

    return agraph
Beispiel #20
0
def convert_to_a_graph(rdf_graph):
    multi_di_graph = rdflib_to_networkx_multidigraph(rdf_graph)
    directed = multi_di_graph.is_directed()
    strict = nx.number_of_selfloops(
        multi_di_graph) == 0 and not multi_di_graph.is_multigraph()
    a_graph = AGraph(name=multi_di_graph.name,
                     strict=strict,
                     directed=directed)

    a_graph.graph_attr.update(
        multi_di_graph.graph.get(
            "graph", {
                'label': 'Network Map',
                'fontsize': '16',
                'fontcolor': 'white',
                'bgcolor': '#333333',
                'rankdir': 'BT',
                'overlap': 'prism',
                'splines': 'true'
            }))
    a_graph.node_attr.update(
        multi_di_graph.graph.get(
            "node", {
                'fontname': 'Helvetica',
                'fontcolor': 'white',
                'color': '#006699',
                'style': 'filled',
                'fillcolor': '#006699',
            }))
    a_graph.edge_attr.update(
        multi_di_graph.graph.get(
            "edge", {
                'style': 'dashed',
                'color': 'green',
                'arrowhead': 'open',
                'fontname': 'Courier',
                'fontsize': '14',
                'fontcolor': 'white',
            }))

    a_graph.graph_attr.update((k, v) for k, v in multi_di_graph.graph.items()
                              if k not in ("graph", "node", "edge"))

    for n, node_data in multi_di_graph.nodes(data=True):
        a_graph.add_node(n)
        a = a_graph.get_node(n)
        a.attr.update({k: str(v) for k, v in node_data.items()})

    if multi_di_graph.is_multigraph():
        for u, v, key, edge_data in multi_di_graph.edges(data=True, keys=True):
            str_edge_data = {
                k: str(v)
                for k, v in edge_data.items() if k != "key"
            }
            a_graph.add_edge(u, v, headlabel=str(key))
            a = a_graph.get_edge(u, v)
            a.attr.update(str_edge_data)

    a_graph.layout()

    return a_graph
Beispiel #21
0
def gen_mul_inputs(
        dfg: AGraph, fu: AGraph,
        input_map: Dict[str, int]) -> Tuple[List[Input], List[Output]]:
    outputs: List[Output] = []
    inputs: List[Input] = []
    nodes: List[Instruction] = []

    for node in fu.nodes():
        nodes.append(parse_instruction(node))

    nodes.sort()
    prime_idx = 0
    for node in nodes:
        preds = dfg.predecessors(node.name)
        parent0 = parse_instruction(preds[0])
        parent1 = parse_instruction(preds[1])

        label0 = dfg.get_node(parent0.name).attr['label']
        label1 = dfg.get_node(parent1.name).attr['label']

        i0, edge_case0, prime_idx = gen_mul_input(node, parent0, input_map,
                                                  inputs, outputs, prime_idx,
                                                  label0)
        i1, edge_case1, prime_idx = gen_mul_input(node, parent1, input_map,
                                                  inputs, outputs, prime_idx,
                                                  label1)

        if edge_case0 or edge_case1:
            expected = None
        else:
            expected = i0 * i1

        # if parent0.name in input_map:
        #     label = dfg.get_node(parent0.name).attr['label']
        #     if 'mul' in label:
        #         latency = 2
        #     else:
        #         latency = 1
        #
        #     i0 = PRIMES[prime_idx]
        #     prime_idx += 1
        #     inputs.append(Input(i0, input_map[parent0.name], parent0.cycle + latency))
        # else:
        #     for output in outputs:
        #         if output.cycle == parent0.cycle + 2:
        #             i0 = output.val
        #             break
        #
        # if parent1.name in input_map:
        #     label = dfg.get_node(parent1.name).attr['label']
        #     if 'mul' in label:
        #         latency = 2
        #     else:
        #         latency = 1
        #
        #     i1 = PRIMES[prime_idx]
        #     prime_idx += 1
        #     inputs.append(Input(i1, input_map[parent1.name], parent1.cycle + latency))
        # else:
        #     for output in outputs:
        #         if output.cycle == parent1.cycle + 2:
        #             i1 = output.val
        #             break

        # expected = i0 * i1
        outputs.append(Output(expected, node.cycle + 1))

    inputs.sort()
    return inputs, outputs
Beispiel #22
0
def dot_layout(cy_elements):
    """
    Get a CyElements object and augment it (in-place) with positions,
    widths, heights, and spline data from a dot based layout.

    Returns the object.
    """
    elements = cy_elements.elements
    g = AGraph(directed=True, strict=False)

    # make transitive relations appear top to bottom
    # TODO: make this not specific to leader example
    elements = list(elements)
    nodes_by_id = dict(
        (e["data"]["id"], e)
        for e in elements if e["group"] == "nodes"
    )
    order = [
        (nodes_by_id[e["data"]["source"]], nodes_by_id[e["data"]["target"]])
        for e in elements if
        e["group"] == "edges" and
        e["data"]["obj"] in ('reach', 'le')
    ]
    elements = topological_sort(elements, order, lambda e: e["data"]["id"])

    # add nodes to the graph
    for e in elements:
        if e["group"] == "nodes":
            g.add_node(e["data"]["id"], label=e["data"]["label"].replace('\n', '\\n'))

    # TODO: remove this, it's specific to leader_demo
    weight = {
        'reach': 10,
        'le': 10,
        'id': 1,
    }
    constraint = {
        'pending': False,
    }

    # add edges to the graph
    for e in elements:
        if e["group"] == "edges":
            g.add_edge(
                e["data"]["source"],
                e["data"]["target"],
                e["data"]["id"],
                weight=weight.get(e["data"]["obj"], 0),
                #constraint=constraint.get(e["data"]["obj"], True),
            )

    # add clusters
    clusters = defaultdict(list)
    for e in elements:
        if e["group"] == "nodes" and e["data"]["cluster"] is not None:
            clusters[e["data"]["cluster"]].append(e["data"]["id"])
    for i, k in enumerate(sorted(clusters.keys())):
        g.add_subgraph(
            name='cluster_{}'.format(i),
            nbunch=clusters[k],
        )

    # now get positions, heights, widths, and bsplines
    g.layout(prog='dot')
    for e in elements:
        if e["group"] == "nodes":
            attr = g.get_node(e["data"]["id"]).attr
            e["position"] = _to_position(attr['pos'])
            e["data"]["width"] = 72 * float(attr['width'])
            e["data"]["height"] = 72 * float(attr['height'])

        elif e["group"] == "edges":
            attr = g.get_edge(e["data"]["source"], e["data"]["target"], e["data"]["id"]).attr
            e["data"].update(_to_edge_position(attr['pos']))
    g.draw('g.png')

    return cy_elements
Beispiel #23
0
def convert(graph, desired_ns=[], exclude_ns=[]):
    # graph.parse('rdf-schema.ttl', format='turtle')
    # network.feedFactsToAdd(generateTokenSet(graph))
    # for n in network.inferredFacts.triples((None, None, None)):
    #     graph.add(n)

    agraph = AGraph(directed=True, clusterrank="global", rankdir="LR")
    namespaces = {}
    nsm = graph.namespace_manager
    deferred_resources = set()
    included_resources = set()

    def prefix(ressource):
        return nsm.qname(ressource).split(':')[0]

    def add_ressource(ressource):
        if ressource not in included_resources:
            qname = nsm.qname(ressource)
            prefix = qname.split(':')[0]
            shape = 'rect' if (
                ressource, RDF.type, OWL.Class) in graph else 'oval'
            color = 'black' if prefix in desired_ns else 'grey'
            if prefix in namespaces:
                namespaces[prefix].add_node(qname, shape=shape, color=color)
            else:
                agraph.add_node(qname, shape=shape, color=color)
            included_resources.add(ressource)
            if ressource in deferred_resources:
                deferred_resources.remove(ressource)

    def add_edge(r1, r2, **kwargs):
        pr1, pr2 = prefix(r1), prefix(r2)
        if pr1 in exclude_ns or pr2 in exclude_ns:
            return
        if pr1 in desired_ns or pr2 in desired_ns:
            add_ressource(r1)
            add_ressource(r2)
            agraph.add_edge(nsm.qname(r1), nsm.qname(r2), **kwargs)

    for kprefix, namespace in graph.namespaces():
        namespaces[kprefix] = agraph.add_subgraph(
            name="cluster_"+kprefix, color="grey")
    for k in graph.subjects(RDF.type, OWL.Class):
        if isinstance(k, BNode):
            continue
        qname = nsm.qname(k)
        kprefix = prefix(k)
        if kprefix in exclude_ns:
            continue
        elif kprefix in desired_ns:
            add_ressource(k)
        else:
            deferred_resources.add(k)
    for (s, p, o) in chain(graph.triples((None, RDFS.subClassOf, None)),
            graph.triples((None, OWL.subClassOf, None))):
        if isinstance(s, BNode) or isinstance(o, BNode):
            continue
        add_edge(s, o, arrowhead='empty', color="blue")
    prop_types = [OWL.Property, OWL.AnnotationProperty, OWL.DatatypeProperty,
                  OWL.AsymmetricProperty, OWL.ObjectProperty,
                  OWL.FunctionalProperty, OWL.InverseFunctionalProperty]
    properties = set()
    for prop in prop_types:
        properties.update(graph.subjects(RDF.type, prop))
    for k in properties:
        if isinstance(k, BNode):
            continue
        qname = nsm.qname(k)
        kprefix = prefix(k)
        if kprefix in exclude_ns:
            continue
        elif kprefix in desired_ns:
            add_ressource(k)
        else:
            deferred_resources.add(k)
    for (s, p, o) in chain(graph.triples((None, RDFS.subPropertyOf, None)),
            graph.triples((None, OWL.subPropertyOf, None))):
        if isinstance(s, BNode) or isinstance(o, BNode):
            continue
        add_edge(s, o, arrowhead='empty', color="blue")

    for (s, p, o) in graph.triples((None, OWL.equivalentClass, None)):
        if isinstance(s, BNode) or isinstance(o, BNode):
            continue
        add_edge(s, o, arrowhead="odot", arrowtail="odot", color="blue")
    for (s, p, o) in graph.triples((None, RDFS.domain, None)):
        if isinstance(s, BNode):
            continue
        if isinstance(o, BNode):
            for o2 in graph.objects(o, OWL.unionOf):
                for o3 in list_content(o2, graph):
                    add_edge(o3, s, arrowhead="open")
            for o2 in graph.objects(o, OWL.intersectionOf):
                for o3 in list_content(o2, graph):
                    add_edge(o3, s, arrowhead="open")
            continue
        add_edge(o, s, arrowhead="open")
    for (s, p, o) in graph.triples((None, RDFS.range, None)):
        if isinstance(s, BNode):
            continue
        if isinstance(o, BNode):
            for o2 in graph.objects(o, OWL.unionOf):
                for o3 in list_content(o2, graph):
                    add_edge(s, o3, arrowhead="open")
            for o2 in graph.objects(o, OWL.intersectionOf):
                for o3 in list_content(o2, graph):
                    add_edge(s, o3, arrowhead="open")
            continue
        add_edge(s, o, arrowhead="open")
    for (s, p, o) in graph.triples((None, OWL.inverseOf, None)):
        if isinstance(s, BNode) or isinstance(o, BNode):
            continue
        if str(o) < str(s):
            s, o = o, s
        add_edge(o, s, arrowhead="crow", arrowtail="crow", dir="both")

    for ressource in included_resources:
        labels = graph.objects(ressource, RDFS.label)
        en_labels = [l for l in labels if l.language == 'eng']
        if en_labels:
            label = en_labels[0]
            qname = nsm.qname(ressource)
            prefix, name = qname.split(':', 1)
            if normalize_label(name) != normalize_label(label):
                node = agraph.get_node(qname)
                node.attr['label'] = "%s\n(%s)" % (qname, label)

    return agraph
Beispiel #24
0
def create_graph(filename,
                 layout="dot",
                 use_singularity=False,
                 color_for_disabled_converter='red'):
    """

    :param filename: should end in .png or .svg or .dot

    If extension is .dot, only the dot file is created.
    This is useful if you have issues installing graphviz.
    If so, under Linux you could use our singularity container
    see github.com/cokelaer/graphviz4all

    """
    from bioconvert.core.registry import Registry
    rr = Registry()

    try:
        if filename.endswith(".dot") or use_singularity is True:
            raise Exception()
        from pygraphviz import AGraph
        dg = AGraph(directed=True)

        url = "https://bioconvert.readthedocs.io/en/master/formats.html#{}"

        for a, b, s in rr.get_all_conversions():
            if len(a) == 1 and len(b) == 1:

                dg.add_node(a[0],
                            shape="rectangle",
                            style="filled",
                            url=url.format(a[0].upper()))
                dg.add_node(b[0],
                            shape="rectangle",
                            style="filled",
                            url=url.format(b[0].upper()))
                dg.add_edge(
                    a[0],
                    b[0],
                    color='black' if s else color_for_disabled_converter)
            else:
                and_node = "_".join(a) + "_and_" + "_".join(b)

                dg.add_node(and_node,
                            label="",
                            fillcolor="black",
                            width=.1,
                            height=.1,
                            styled="filled",
                            fixedsize=True,
                            shape="circle")

                for this in a:
                    dg.add_edge(
                        this,
                        and_node,
                        color="black" if s else color_for_disabled_converter)

                for this in b:
                    dg.add_edge(
                        and_node,
                        this,
                        color="black" if s else color_for_disabled_converter)

        for name in dg.nodes():
            if dg.degree(name) < 5:
                dg.get_node(name).attr["fillcolor"] = "white"
            elif dg.degree(name) < 10:
                # yellow
                dg.get_node(name).attr["fillcolor"] = "yellow"
            elif dg.degree(name) < 20:
                # orange
                dg.get_node(name).attr["fillcolor"] = "orange"
            else:
                # red
                dg.get_node(name).attr["fillcolor"] = "red"

        dg.layout(layout)
        dg.draw(filename)
        dg.write("conversion.dot")
        print(list(dg.get_node("FASTQ").attr.values()))

    except Exception as e:
        _log.error(e)
        dot = """
strict digraph{
    node [label="\\N"];

    """
        nodes = set([
            item for items in rr.get_all_conversions() for item in items[0:1]
        ])

        for node in nodes:
            dot += "\"{}\";\n".format(node)
        for a, b, s in rr.get_all_conversions():
            dot += "\"{}\" -> \"{}\";\n".format(a, b)
        dot += "}\n"

        from easydev import TempFile
        from bioconvert import shell
        dotfile = TempFile(suffix=".dot")
        with open(dotfile.name, "w") as fout:
            fout.write(dot)

        dotpath = ""
        if use_singularity:
            from bioconvert.core.downloader import download_singularity_image
            singfile = download_singularity_image(
                "graphviz.simg", "shub://cokelaer/graphviz4all:v1",
                "4288088d91c848e5e3a327282a1ab3d1")

            dotpath = "singularity run {} ".format(singfile)
            on_rtd = environ.get('READTHEDOCS', None) == 'True'
            if on_rtd:
                dotpath = ""

        ext = filename.rsplit(".", 1)[1]
        cmd = "{}dot -T{} {} -o {}".format(dotpath, ext, dotfile.name,
                                           filename)
        print(dotfile.name)
        try:
            shell(cmd)
        except:
            import os
            os.system(cmd)