Пример #1
0
 def testCentroid(self):
     layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)])
     centroid = layout.centroid()
     self.assertEqual(len(centroid), 3)
     self.assertAlmostEqual(centroid[0], 0.75)
     self.assertAlmostEqual(centroid[1], 0.5)
     self.assertAlmostEqual(centroid[2], 1.)
Пример #2
0
 def testCentroid(self):
     layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)])
     centroid = layout.centroid()
     self.assertEqual(len(centroid), 3)
     self.assertAlmostEqual(centroid[0], 0.75)
     self.assertAlmostEqual(centroid[1], 0.5)
     self.assertAlmostEqual(centroid[2], 1.)
Пример #3
0
 def testToPolar(self):
     layout = Layout([(0, 0), (-1, 1), (0, 1), (1, 1)])
     layout.to_radial(min_angle=180, max_angle=0, max_radius=2)
     exp = [[0., 0.], [-2., 0.], [0., 2.], [2, 0.]]
     for idx in range(4):
         self.assertAlmostEqual(layout.coords[idx][0], exp[idx][0], places=3)
         self.assertAlmostEqual(layout.coords[idx][1], exp[idx][1], places=3)
Пример #4
0
 def testConstructor(self):
     layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0)])
     self.assertEqual(layout.dim, 3)
     layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0)], 3)
     self.assertEqual(layout.dim, 3)
     self.assertRaises(ValueError, Layout, [(0, 1), (1, 0)], 3)
     self.assertRaises(ValueError, Layout, [])
Пример #5
0
 def testToPolar(self):
     layout = Layout([(0, 0), (-1, 1), (0, 1), (1, 1)])
     layout.to_radial(min_angle=180, max_angle=0, max_radius=2)
     exp = [[0., 0.], [-2., 0.], [0., 2.], [2, 0.]]
     for idx in xrange(4):
         self.assertAlmostEqual(layout.coords[idx][0], exp[idx][0], places=3)
         self.assertAlmostEqual(layout.coords[idx][1], exp[idx][1], places=3)
Пример #6
0
    def testTransform(self):
        def tr(coord, dx, dy):
            return coord[0] + dx, coord[1] + dy

        layout = Layout([(1, 2), (3, 4)])
        layout.transform(tr, 2, -1)
        self.assertEqual(layout.coords, [[3, 1], [5, 3]])
Пример #7
0
    def setup_canvas(self):
        """Populate the canvas with the initial instructions.
        """
        self._selecting_nnodes = False

        self.G = Graph.Star(self.nnodes, mode="out")
        self._unscaled_layout = Layout([(0.0, 0.0),
                                        *circle_points(self.nnodes - 1)])

        self.scale = INIT_SCALE
        self.offset_x, self.offset_y = INIT_OFFSET

        self._selected_edge = self._selected_node = None
        self._source_node = self._target_edge = None

        self.canvas.clear()

        with self.canvas.before:
            self.background_color = Color(*BACKGROUND_COLOR)
            self._background = Rectangle(size=self.size, pos=self.pos)

        with self.canvas:
            self.animated_edge_color = Color(*HIGHLIGHTED_EDGE)
            self.animated_edge_color.a = 0
            self.animated_edge = Line(width=1.1)

        # Edge instructions before Node instructions so they're drawn underneath nodes.
        self._edge_instructions = CanvasBase()
        with self._edge_instructions:
            self.edges = {
                edge.tuple: Edge(edge.tuple, self)
                for edge in self.G.es
            }
        self.canvas.add(self._edge_instructions)

        # Animated node drawn above edges but below other nodes.
        with self.canvas:
            PushMatrix()
            self.rotation_instruction = Rotate()
            self.animated_node_color = Color(*ANIMATED_NODE_COLOR)
            self.animated_node_color.a = 0
            self.animated_node = Rectangle(size=(ANIMATION_WIDTH,
                                                 ANIMATION_HEIGHT),
                                           source=ANIMATED_NODE_SOURCE)
            PopMatrix()

        self._node_instructions = CanvasBase()
        with self._node_instructions:
            self.nodes = [Node(vertex.index, self) for vertex in self.G.vs]
        self.canvas.add(self._node_instructions)

        # TODO: Refactor so we only need to do this once
        self.bind(size=self._delayed_resize, pos=self._delayed_resize)
        Window.bind(mouse_pos=self.on_mouse_pos)

        self.step_layout()
        self.layout_stepper()

        self._mouse_pos_disabled = False
Пример #8
0
 def testCenter(self):
     layout = Layout([(-2,0), (-2,-2), (0,-2), (0,0)])
     layout.center()
     self.assertEqual(layout.coords, [[-1,1], [-1,-1], [1,-1], [1,1]])
     layout.center(5,5)
     self.assertEqual(layout.coords, [[4,6], [4,4], [6,4], [6,6]])
     self.assertRaises(ValueError, layout.center, 3)
     self.assertRaises(TypeError, layout.center, p=6)
Пример #9
0
    def testBoundaries(self):
        layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)])
        self.assertEqual(layout.boundaries(), ([0,0,0],[2,1,3]))
        self.assertEqual(layout.boundaries(1), ([-1,-1,-1],[3,2,4]))

        layout = Layout([])
        self.assertRaises(ValueError, layout.boundaries)
        layout = Layout([], dim=3)
        self.assertRaises(ValueError, layout.boundaries)
Пример #10
0
def network_visualization(w_plot, membership, name, coord_xy):
    """
	plot the newwork

	@ param w_plot: weight matrix for plotting

	@ param membership: a vector indicating the community index for each vertex i.e. [0,0,0,1,1,1,0,0,2,2])

	@ param name: vertex name vectors

	@ param coord_xy: x and y coordinates in a planar for vertices (n_vertices * 2)

	"""
    # construct the plot graph
    g_plot = Graph().Adjacency((w_plot > 0).tolist(), mode='UNDIRECTED')
    n_clusters = len(set(membership))
    n_vertics = len(g_plot.vs)
    n_edges = len(g_plot.es)

    # set the attributes for vertices and edges
    g_plot.vs['name'] = name
    g_plot.vs['i_cluster'] = membership  # the cluster index for each vertex
    g_plot.es['weight'] = w_plot
    # assign the cluster index for each edge
    for v1, v2 in g_plot.get_edgelist():
        eid = g_plot.get_eid(v1, v2)
        if membership[v1] != membership[v2]:
            g_plot.es[eid][
                'i_cluster'] = n_clusters  #if v1,v2 belong to different clusters, g_plot.es['i_cluster'] = n_cluster, crossing clusters condition
        else:
            g_plot.es[eid]['i_cluster'] = membership[
                v1]  # if v1,v2 belong to the same cluster i, g_plot.es['i_cluster'] = i

    palette = ClusterColoringPalette(
        n=n_clusters + 1
    )  # set one palette for each cluster, extra one color for the crossing edge
    vertex_color_list = [
        palette.get(g_plot.vs[i]['i_cluster']) for i in range(n_vertics)
    ]  # configure the vertex color
    edge_color_list = [
        palette.get(g_plot.es[i]['i_cluster']) for i in range(n_edges)
    ]  # configure the edge color

    visual_style = {}
    layout = Layout(list(coord_xy))
    layout.mirror(1)
    visual_style["layout"] = layout
    visual_style["vertex_label"] = g_plot.vs["name"]
    visual_style["vertex_color"] = vertex_color_list
    visual_style["edge_color"] = edge_color_list
    #visual_style["edge_width"] = [1 + 2 * int(is_formal) for is_formal in g.es["is_formal"]]

    plot(g_plot, "network.png", **visual_style)
    plot(g_plot, **visual_style)
Пример #11
0
    def testBoundaries(self):
        layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)])
        self.assertEqual(layout.boundaries(), ([0, 0, 0], [2, 1, 3]))
        self.assertEqual(layout.boundaries(1), ([-1, -1, -1], [3, 2, 4]))

        layout = Layout([])
        self.assertRaises(ValueError, layout.boundaries)
        layout = Layout([], dim=3)
        self.assertRaises(ValueError, layout.boundaries)
Пример #12
0
    def testFitInto(self):
        layout = Layout([(-2,0), (-2,-2), (0,-2), (0,0)])
        layout.fit_into(BoundingBox(5,5,8,10), keep_aspect_ratio=False)
        self.assertEqual(layout.coords, [[5, 10], [5, 5], [8, 5], [8, 10]])
        layout = Layout([(-2,0), (-2,-2), (0,-2), (0,0)])
        layout.fit_into(BoundingBox(5,5,8,10))
        self.assertEqual(layout.coords, [[5, 9], [5, 6], [8, 6], [8, 9]])

        layout = Layout([(-1,-1,-1), (0,0,0), (1,1,1), (2,2,0), (3,3,-1)])
        layout.fit_into((0,0,0,8,8,4))
        self.assertEqual(layout.coords, \
                [[0, 0, 0], [2, 2, 2], [4, 4, 4], [6, 6, 2], [8, 8, 0]]
        )
Пример #13
0
    def testIndexing(self):
        layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)])
        self.assertEqual(len(layout), 4)
        self.assertEqual(layout[1], [0, 1, 0])
        self.assertEqual(layout[3], [2, 1, 3])

        row = layout[2]
        row[2] = 1
        self.assertEqual(layout[2], [1, 0, 1])

        del layout[1]
        self.assertEqual(len(layout), 3)
Пример #14
0
    def testTranslation(self):
        layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)])
        layout2 = layout.copy()

        layout.translate(1, 3, 2)
        self.assertEqual(layout.coords, [[1, 3, 3], [1, 4, 2], [2, 3, 2], [3, 4, 5]])

        layout.translate((-1, -3, -2))
        self.assertEqual(layout.coords, layout2.coords)

        self.assertRaises(ValueError, layout.translate, v=[3])
Пример #15
0
 def testCenter(self):
     layout = Layout([(-2, 0), (-2, -2), (0, -2), (0, 0)])
     layout.center()
     self.assertEqual(layout.coords, [[-1, 1], [-1, -1], [1, -1], [1, 1]])
     layout.center(5, 5)
     self.assertEqual(layout.coords, [[4, 6], [4, 4], [6, 4], [6, 6]])
     self.assertRaises(ValueError, layout.center, 3)
     self.assertRaises(TypeError, layout.center, p=6)
Пример #16
0
def demo_epidemic():
    from igraph import Graph, Layout
    from random import sample, random

    # Specify the simulation parameters
    initial_outbreak_size = 3
    spread_probability = 0.05
    recovery_probability = 0.1

    # Set up the mapping from vertex states to colors
    colormap = dict(S="white", I="red", R="green")

    # Generate the graph
    graph, xs, ys = Graph.GRG(100, 0.2, return_coordinates=True)
    layout = Layout(zip(xs, ys))

    # Set up the initial state of the individuals
    graph.vs["state"] = ["S"] * graph.vcount()
    for vertex in sample(graph.vs, initial_outbreak_size):
        vertex["state"] = "I"
    graph.vs["size"] = [20] * graph.vcount()

    # Set up the video encoder
    encoder = MEncoderVideoEncoder(bbox=(600, 600), fps=5)

    # Generate frames in the animation one by one
    with encoder.encode_to("demo_epidemic.avi"):
        # Run the simulation until hell freezes over
        while True:
            # Create the plot and add to the encoder
            colors = [colormap[state] for state in graph.vs["state"]]
            encoder.add(graph,
                        layout=layout,
                        vertex_color=colors,
                        vertex_label=graph.vs["state"],
                        margin=20)
            # First, the infected individuals try to infect their neighbors
            infected = graph.vs.select(state="I")
            for vertex in infected:
                for idx in graph.neighbors(vertex.index):
                    if graph.vs[idx]["state"] == "S" and random(
                    ) < spread_probability:
                        graph.vs[idx]["state"] = "I"
            # Second, the infected individuals try to recover
            for vertex in infected:
                if random() < recovery_probability:
                    vertex["state"] = "R"
            # Okay, are there any infected people left?
            if not infected:
                break
Пример #17
0
    def testScaling(self):
        layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)])
        layout.scale(1.5)
        self.assertEqual(layout.coords, [[0., 0., 1.5], \
                                         [0., 1.5, 0.], \
                                         [1.5, 0., 0.], \
                                         [3., 1.5, 4.5]])

        layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)])
        layout.scale(1, 1, 3)
        self.assertEqual(layout.coords, [[0, 0, 3], \
                                         [0, 1, 0], \
                                         [1, 0, 0], \
                                         [2, 1, 9]])

        layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)])
        layout.scale((2, 2, 1))
        self.assertEqual(layout.coords, [[0, 0, 1], \
                                         [0, 2, 0], \
                                         [2, 0, 0], \
                                         [4, 2, 3]])

        self.assertRaises(ValueError, layout.scale, 2, 3)
Пример #18
0
    def testTranslation(self):
        layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)])
        layout2 = layout.copy()
        
        layout.translate(1,3,2)
        self.assertEqual(layout.coords, [[1, 3, 3], \
                                         [1, 4, 2], \
                                         [2, 3, 2], \
                                         [3, 4, 5]])
        
        layout.translate((-1,-3,-2))
        self.assertEqual(layout.coords, layout2.coords)

        self.assertRaises(ValueError, layout.translate, v=[3])
Пример #19
0
def _get_layout(g, coordinates):
    return g.layout(GRAPH_LAYOUT) if coordinates is None else Layout(
        coordinates.tolist())
Пример #20
0
    def testScaling(self):
        layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)])
        layout.scale(1.5)
        self.assertEqual(layout.coords, [[0., 0., 1.5], \
                                         [0., 1.5, 0.], \
                                         [1.5, 0., 0.], \
                                         [3., 1.5, 4.5]])

        layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)])
        layout.scale(1, 1, 3)
        self.assertEqual(layout.coords, [[0, 0, 3], \
                                         [0, 1, 0], \
                                         [1, 0, 0], \
                                         [2, 1, 9]])

        layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)])
        layout.scale((2, 2, 1))
        self.assertEqual(layout.coords, [[0, 0, 1], \
                                         [0, 2, 0], \
                                         [2, 0, 0], \
                                         [4, 2, 3]])

        self.assertRaises(ValueError, layout.scale, 2, 3)
Пример #21
0
 def testBoundingBox(self):
     layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)])
     self.assertEqual(layout.bounding_box(), (0, 0, 0, 2, 1, 3))
     self.assertEqual(layout.bounding_box(1), (-1, -1, -1, 3, 2, 4))
Пример #22
0
 def testBoundaries(self):
     layout = Layout([(0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 1, 3)])
     self.assertEqual(layout.boundaries(), ([0, 0, 0], [2, 1, 3]))
     self.assertEqual(layout.boundaries(1), ([-1, -1, -1], [3, 2, 4]))
Пример #23
0
 def testTransform(self):
     def tr(coord, dx, dy): return coord[0]+dx, coord[1]+dy
     layout = Layout([(1, 2), (3, 4)])
     layout.transform(tr, 2, -1)
     self.assertEqual(layout.coords, [[3, 1], [5, 3]])
Пример #24
0
 def testBoundingBox(self):
     layout = Layout([(0, 1), (2, 7)])
     self.assertEqual(layout.bounding_box(), BoundingBox(0, 1, 2, 7))
     self.assertEqual(layout.bounding_box(1), BoundingBox(-1, 0, 3, 8))
     layout = Layout([])
     self.assertEqual(layout.bounding_box(), BoundingBox(0, 0, 0, 0))
Пример #25
0
 def testBoundaries(self):
     layout = Layout([(0,0,1), (0,1,0), (1,0,0), (2,1,3)])
     self.assertEqual(layout.boundaries(), ([0,0,0],[2,1,3]))
     self.assertEqual(layout.boundaries(1), ([-1,-1,-1],[3,2,4]))
Пример #26
0
    def testFitInto(self):
        layout = Layout([(-2, 0), (-2, -2), (0, -2), (0, 0)])
        layout.fit_into(BoundingBox(5, 5, 8, 10), keep_aspect_ratio=False)
        self.assertEqual(layout.coords, [[5, 10], [5, 5], [8, 5], [8, 10]])
        layout = Layout([(-2, 0), (-2, -2), (0, -2), (0, 0)])
        layout.fit_into(BoundingBox(5, 5, 8, 10))
        self.assertEqual(layout.coords, [[5, 9], [5, 6], [8, 6], [8, 9]])

        layout = Layout([(-1, -1, -1), (0, 0, 0), (1, 1, 1), (2, 2, 0),
                         (3, 3, -1)])
        layout.fit_into((0, 0, 0, 8, 8, 4))
        self.assertEqual(layout.coords, \
                [[0, 0, 0], [2, 2, 2], [4, 4, 4], [6, 6, 2], [8, 8, 0]]
        )

        layout = Layout([])
        layout.fit_into((6, 7, 8, 11))
        self.assertEqual(layout.coords, [])
Пример #27
0
 def testBoundingBox(self):
     layout = Layout([(0,1), (2,7)])
     self.assertEqual(layout.bounding_box(), BoundingBox(0,1,2,7))
     self.assertEqual(layout.bounding_box(1), BoundingBox(-1,0,3,8))
Пример #28
0
class GraphCanvas(Widget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._touches = []
        self.delay = RESIZE_DELAY
        self._mouse_pos_disabled = True

        self._init_animations()
        self.load_graph()

    def _init_animations(self):
        self.scale_animation = (
            Animation(size=(ANIMATION_WIDTH_2, ANIMATION_HEIGHT_2),
                      duration=SCALE_SPEED_OUT,
                      step=UPDATE_INTERVAL) +
            Animation(size=(ANIMATION_WIDTH, ANIMATION_HEIGHT),
                      duration=SCALE_SPEED_IN,
                      step=UPDATE_INTERVAL))
        self.scale_animation.repeat = True
        self.scale_animation.bind(on_progress=self._reposition_animated_node)

        self.rotate_animation = Clock.schedule_interval(
            self._rotate_node, UPDATE_INTERVAL)
        self.rotate_animation.cancel()

        self.edge_color_animation = Animation(a=0)
        self.edge_animation = Animation(width=ANIMATED_EDGE_WIDTH)
        self.edge_animation.bind(on_start=self._edge_animation_start,
                                 on_complete=self._reschedule_edge_animation)

        # Schedule events
        self.edge_move = Clock.schedule_interval(self._move_edge,
                                                 UPDATE_INTERVAL)
        self.edge_move.cancel()

        self.resize_event = Clock.schedule_once(self.update_canvas, self.delay)
        self.resize_event.cancel()

        self.layout_stepper = Clock.schedule_interval(self.step_layout,
                                                      UPDATE_INTERVAL)
        self.layout_stepper.cancel()

    def load_graph(self):
        """Set initial graph.
        """
        self._selecting_nnodes = True
        NewGameDialogue(self).open()

    def setup_canvas(self):
        """Populate the canvas with the initial instructions.
        """
        self._selecting_nnodes = False

        self.G = Graph.Star(self.nnodes, mode="out")
        self._unscaled_layout = Layout([(0.0, 0.0),
                                        *circle_points(self.nnodes - 1)])

        self.scale = INIT_SCALE
        self.offset_x, self.offset_y = INIT_OFFSET

        self._selected_edge = self._selected_node = None
        self._source_node = self._target_edge = None

        self.canvas.clear()

        with self.canvas.before:
            self.background_color = Color(*BACKGROUND_COLOR)
            self._background = Rectangle(size=self.size, pos=self.pos)

        with self.canvas:
            self.animated_edge_color = Color(*HIGHLIGHTED_EDGE)
            self.animated_edge_color.a = 0
            self.animated_edge = Line(width=1.1)

        # Edge instructions before Node instructions so they're drawn underneath nodes.
        self._edge_instructions = CanvasBase()
        with self._edge_instructions:
            self.edges = {
                edge.tuple: Edge(edge.tuple, self)
                for edge in self.G.es
            }
        self.canvas.add(self._edge_instructions)

        # Animated node drawn above edges but below other nodes.
        with self.canvas:
            PushMatrix()
            self.rotation_instruction = Rotate()
            self.animated_node_color = Color(*ANIMATED_NODE_COLOR)
            self.animated_node_color.a = 0
            self.animated_node = Rectangle(size=(ANIMATION_WIDTH,
                                                 ANIMATION_HEIGHT),
                                           source=ANIMATED_NODE_SOURCE)
            PopMatrix()

        self._node_instructions = CanvasBase()
        with self._node_instructions:
            self.nodes = [Node(vertex.index, self) for vertex in self.G.vs]
        self.canvas.add(self._node_instructions)

        # TODO: Refactor so we only need to do this once
        self.bind(size=self._delayed_resize, pos=self._delayed_resize)
        Window.bind(mouse_pos=self.on_mouse_pos)

        self.step_layout()
        self.layout_stepper()

        self._mouse_pos_disabled = False

    def reset(self):
        self._mouse_pos_disabled = True

        # Stop all animations
        self.layout_stepper.cancel()
        self.edge_move.cancel()

        self.scale_animation.stop(self.animated_node)
        self.rotate_animation.cancel()

        self.edge_color_animation.stop(self.animated_edge_color)
        self.edge_animation.stop(self.animated_edge)

        self.canvas.clear()
        self.load_graph()

    @property
    def selected_edge(self):
        """While there is no source node, the selected edge is just the edge that is currently colliding with the mouse.
        """
        return self._selected_edge

    @selected_edge.setter
    def selected_edge(self, edge):
        if self.selected_edge is not None:
            self.selected_edge.is_tail_selected = None

        self._selected_edge = edge

    @property
    def selected_node(self):
        """This is the end of selected edge that is closest to the mouse position.
        """
        return self._selected_node

    @selected_node.setter
    def selected_node(self, node):
        edges = self.edges
        G = self.G

        if self._selected_node is not None:
            # Reset node and out-edges to their default colors
            self._selected_node.color.rgba = NODE_COLOR

            for edge in G.vs[self._selected_node.index].out_edges():
                e = edges[edge.tuple]
                if e is not self.selected_edge:
                    e.color.rgba = EDGE_COLOR
                    e.head_color.rgba = HEAD_COLOR

        self._selected_node = node
        if node is not None:
            # Highlight this node and adjacent out-edges
            node.color.rgba = HIGHLIGHTED_NODE

            for edge in G.vs[node.index].out_edges():
                e = edges[edge.tuple]
                if e is not self.selected_edge:
                    e.color.rgba = HIGHLIGHTED_EDGE
                    e.head_color.rgba = HIGHLIGHTED_HEAD

            self._selected_node_x, self._selected_node_y = self._unscaled_layout[
                node.index]
            self.animated_node_color.a = 1
            self.rotate_animation()
            self.scale_animation.start(self.animated_node)

        else:
            self.animated_node_color.a = 0
            self.rotate_animation.cancel()
            self.scale_animation.stop(self.animated_node)

    @property
    def source_node(self):
        """Source node is set to selected node when the selected node is clicked.
        """
        return self._source_node

    @source_node.setter
    def source_node(self, node):
        if self.source_node is not None:
            self.animated_node_color.rgba = HIGHLIGHTED_EDGE

        self._source_node = node

        if node is not None:
            self.animated_node_color.rgba = HIGHLIGHTED_NODE

    @property
    def target_edge(self):
        """The target edge is the edge we move along.
        """
        return self._target_edge

    @target_edge.setter
    def target_edge(self, edge):
        if self.target_edge is not None:
            self.target_edge.color.rgba = HIGHLIGHTED_EDGE
            self.target_edge.head_color.rgba = HIGHLIGHTED_HEAD

            self._keep_animating = False
            self.edge_animation.stop(self.animated_edge)

        self._target_edge = edge

        if edge is not None:
            edge.color.rgba = HIGHLIGHTED_NODE
            edge.head_color.rgba = WHITE
            self._keep_animating = True
            self.edge_animation.start(self.animated_edge)

    def _transform_coords(self, coord):
        """Transform vertex coordinates to canvas coordinates.
        """
        return (
            (coord[0] * self.scale + self.offset_x) * self.width,
            (coord[1] * self.scale + self.offset_y) * self.height,
        )

    def _invert_coords(self, x, y):
        """Transform canvas coordinates to vertex coordinates.
        """
        return (x / self.width - self.offset_x) / self.scale, (
            y / self.height - self.offset_y) / self.scale

    def _rotate_node(self, dt):
        """This rotates `animated_node` when called. `dt` does nothing, but is required for kivy's scheduler.
        """
        self.rotation_instruction.origin = self.layout[
            self.selected_node.index]
        self.rotation_instruction.angle = (self.rotation_instruction.angle +
                                           ROTATE_INCREMENT) % 360

    def _reposition_animated_node(self, *args):
        x, y = self.layout[self.selected_node.index]
        w, h = self.animated_node.size
        self.animated_node.pos = x - w // 2, y - h // 2

    def _delayed_resize(self, *args):
        self.resize_event.cancel()
        self.resize_event()

        self._background.size = self.size
        self._background.pos = self.pos

    def _edge_animation_start(self, *args):
        self.animated_edge.width = 1.1

        self.animated_edge_color.a = 1
        self.edge_color_animation.start(self.animated_edge_color)

    def _reschedule_edge_animation(self, *args):
        self.edge_color_animation.stop(self.animated_edge_color)
        self.animated_edge_color.a = 0
        self.animated_edge.width = 1.1

        if self._keep_animating:
            # Just calling edge_animation.start won't work as we're still animating, we must schedule the restart.
            Clock.schedule_once(
                lambda dt: self.edge_animation.start(self.animated_edge))

    def _lerp_edge(self):
        """Generator that updates the selected edge position.
        """
        # Before we reset the edge colors grab the information we need to lerp:
        selected_edge = self.selected_edge
        is_tail_selected = selected_edge.is_tail_selected
        sx, sy, tx, ty = selected_edge.points

        start_x, start_y, stop_x, stop_y = self.target_edge.points
        new_end = self.target_edge.edge[1]

        # Reset the colors:
        self.source_node = self.target_edge = self.selected_edge = None  # WARNING: The order of these assignments is important.

        self.layout_stepper.cancel(
        )  # Need to turn off the layout_stepper while lerping
        self._mouse_pos_disabled = True

        yield

        for i in range(MOVE_STEPS):
            k = i / MOVE_STEPS
            x = start_x * (1 - k) + stop_x * k
            y = start_y * (1 - k) + stop_y * k
            selected_edge.update_points(*((x, y, tx,
                                           ty) if is_tail_selected else (sx,
                                                                         sy, x,
                                                                         y)))
            yield

        return selected_edge, is_tail_selected, new_end  # _move_edge needs this information to update the underlying graph

    def _move_edge(self, dt):
        """Lerp the selected edge to it's new position and update the underlying graph when finished.
        """
        try:
            next(self._edge_lerp)

        except StopIteration as e:
            selected_edge, is_tail_selected, new_end = e.value

            self.edge_move.cancel()
            self.G.delete_edges((selected_edge.edge, ))
            del self.edges[selected_edge.edge]

            source, target = selected_edge.edge
            if is_tail_selected:
                selected_edge.edge = self.G.add_edge(new_end, target).tuple
                self.edges[new_end, target] = selected_edge
            else:
                selected_edge.edge = self.G.add_edge(source, new_end).tuple
                self.edges[source, new_end] = selected_edge

            self.layout_stepper()
            self._mouse_pos_disabled = False

    def move_edge(self):
        self._edge_lerp = self._lerp_edge()
        next(
            self._edge_lerp
        )  # Prime the generator -- If we don't do this immediately it's possible to lose the
        # selected edge information before the scheduler calls `_move_edge`
        self.edge_move()

    def on_touch_move(self, touch):
        """Zoom if multitouch, else if a node is selected, drag it, else move the entire graph.
        """
        if touch.grab_current is not self or touch.button == 'right':
            return

        if self._selecting_nnodes:
            return

        if len(self._touches) > 1:
            self.transform_on_touch(touch)

        elif self.selected_edge is not None:
            px, py = self._invert_coords(touch.px, touch.py)
            x, y = self._invert_coords(touch.x, touch.y)
            self._selected_node_x += x - px
            self._selected_node_y += y - py

        else:
            self.offset_x += touch.dx / self.width
            self.offset_y += touch.dy / self.height

        self.update_canvas()
        return True

    def transform_on_touch(self, touch):
        """Rescales the canvas.
        """
        ax, ay = self._touches[-2].pos  # Anchor coords
        x, y = self._invert_coords(ax, ay)

        cx = (touch.x - ax) / self.width
        cy = (touch.y - ay) / self.height
        current_length = hypot(cx, cy)

        px = (touch.px - ax) / self.width
        py = (touch.py - ay) / self.height
        previous_length = hypot(px, py)

        self.scale = max(self.scale + current_length - previous_length,
                         MIN_SCALE)

        # Make sure the anchor is a fixed point:
        # Note we can't use `ax, ay` as `self.scale` has changed.
        x, y = self._transform_coords((x, y))

        self.offset_x += (ax - x) / self.width
        self.offset_y += (ay - y) / self.height

    def on_touch_down(self, touch):
        if touch.is_mouse_scrolling:  # REMOVE THIS: For testing only
            self.reset()
            return True

        if self._selecting_nnodes:
            return

        if not self.collide_point(*touch.pos):
            return

        touch.grab(self)
        self._touches.append(touch)
        self._mouse_pos_disabled = True

        # Change the color of multitouch dots to match our color scheme:
        if touch.button == 'right':
            touch.multitouch_sim = True
            with Window.canvas.after:
                touch.ud._drawelement = (
                    Color(*HIGHLIGHTED_EDGE),
                    Ellipse(size=(20, 20),
                            segments=15,
                            pos=(touch.x - 10, touch.y - 10)),
                )

        return True

    def on_touch_up(self, touch):
        if touch.grab_current is not self:
            return

        touch.ungrab(self)
        self._touches.remove(touch)
        self._mouse_pos_disabled = False

        if touch.time_end - touch.time_start > TOUCH_INTERVAL:
            return

        if self.source_node is not None:
            if self.target_edge is not None:
                self.move_edge()
            else:
                self.source_node = None
                # Recheck collision with edge:
                collides, is_tail_selected = self.selected_edge.collides(
                    touch.x, touch.y)
                if collides:
                    self.selected_edge.is_tail_selected = is_tail_selected
                else:
                    self.selected_edge = None

        elif self.selected_node is not None:
            self.source_node = self.selected_node

    def on_mouse_pos(self, *args):
        mx, my = args[-1]

        if self._mouse_pos_disabled or not self.collide_point(mx, my):
            return

        # If source node is set, check collision with an adjacent out-edge.
        if self.source_node is not None:
            if self.target_edge is None:
                for edge in self.G.vs[self.source_node.index].out_edges():
                    target = self.edges[edge.tuple]
                    if target is not self.selected_edge and target.collides(
                            mx, my)[0]:
                        self.target_edge = target
                        break
            else:
                if not self.target_edge.collides(mx, my)[0]:
                    self.target_edge = None

        # If an edge is selected, just check collision with that edge.
        elif self.selected_edge is not None:
            collides, is_tail_selected = self.selected_edge.collides(mx, my)
            if collides:
                self.selected_edge.is_tail_selected = is_tail_selected
            else:
                self.selected_edge = None

        # Check collision with all edges.
        else:
            for edge in self.edges.values():
                collides, is_tail_selected = edge.collides(mx, my)
                if collides:
                    self.selected_edge = edge  # This should be set before `edge.is_tail_selected`
                    edge.is_tail_selected = is_tail_selected
                    break
            else:
                self.selected_edge = None

    def update_canvas(self, dt=0):
        """Update coordinates of all elements. `dt` is a dummy arg required for kivy's scheduler.
        """
        if self.resize_event.is_triggered:  # We use a delayed resize, this will make sure we're done resizing before we update.
            return

        for edge in self.edges.values():
            edge.update()

        if self.target_edge is not None:
            self.animated_edge.points = self.target_edge.points

        for node in self.nodes:
            node.update()

    def step_layout(self, dt=0):
        """Iterate the graph layout algorithm. `dt` is a dummy arg required for kivy's scheduler.
        """
        self._unscaled_layout = self.G.layout_graphopt(
            niter=1,
            seed=self._unscaled_layout,
            max_sa_movement=.1,
            node_charge=.00001)

        # Keep the selected node fixed:
        if self.selected_node is not None:
            self._unscaled_layout[
                self.selected_node.
                index] = self._selected_node_x, self._selected_node_y

        self.layout = self._unscaled_layout.copy()
        self.layout.transform(self._transform_coords)

        self.update_canvas()
Пример #29
0
    elif graph.degree(v.index) <= 304:
        v["size"] = 20
    elif graph.degree(v.index) <= 1216:
        v["size"] = 15
    elif graph.degree(v.index) <= 4864:
        v["size"] = 12
    elif graph.degree(v.index) <= 19456:
        v["size"] = 10
    else:
        v["size"] = 6


shells = list(set(coreness))
shells.sort()

layout = Layout(dim=2)

frequency = {}
for item in coreness:
    if item not in frequency:
        frequency[item] = 0
    frequency[item] += 1

for shell in shells:
    print(f"Calculating {shell} from {len(shells)-1}")
    v = (1 - ((shell) / max(shells)))
    nodes_in_shell = frequency[shell]
    angles = []
    angle = 0
    while angle <= 360.1:
        angles.append(angle)