def test_layout(self): g = networkx.DiGraph() g.add_edge('root', 'child 1') g.add_edge('child 1', 'grandchild 1') g.add_edge('child 1', 'grandchild 2') g.add_edge('root', 'child 2') g.add_edge('child 2', 'grandchild 3') g.add_edge('child 2', 'grandchild 4') g.add_edge('child 2', 'grandchild 5') layout = tree_layout(g) expected_root_x, expected_root_y = (0.5, 1.0) self.assertAlmostEqual(layout['root'][0], expected_root_x) self.assertAlmostEqual(layout['root'][1], expected_root_y) gc_xs = [value[0] for key, value in layout.items() if key.startswith('child')] expected_gc_xs = [x / 3.0 for x in range(1, 3)] nptest.assert_almost_equal(sorted(gc_xs), expected_gc_xs) gc_ys = [value[1] for key, value in layout.items() if key.startswith('child')] expected_gc_ys = [0.5] * 2 nptest.assert_almost_equal(sorted(gc_ys), expected_gc_ys) gc_xs = [value[0] for key, value in layout.items() if 'grandchild' in key] expected_gc_xs = [x / 6.0 for x in range(1, 6)] nptest.assert_almost_equal(sorted(gc_xs), expected_gc_xs) gc_ys = [value[1] for key, value in layout.items() if 'grandchild' in key] expected_gc_ys = [0.0] * 5 nptest.assert_almost_equal(sorted(gc_ys), expected_gc_ys)
def test_layout(self): g = networkx.DiGraph() g.add_edge('root', 'child 1') g.add_edge('child 1', 'grandchild 1') g.add_edge('child 1', 'grandchild 2') g.add_edge('root', 'child 2') g.add_edge('child 2', 'grandchild 3') g.add_edge('child 2', 'grandchild 4') g.add_edge('child 2', 'grandchild 5') layout = tree_layout(g) self.assert_layout_positions(layout['root'], (0.5, 1.0)) self.assert_layout_positions(layout['child 1'], (2 / 3., 0.5)) self.assert_layout_positions(layout['child 2'], (1 / 3., 0.5)) self.assert_layout_positions(layout['grandchild 1'], (5 / 6., 0.0)) self.assert_layout_positions(layout['grandchild 2'], (4 / 6., 0.0)) self.assert_layout_positions(layout['grandchild 3'], (3 / 6., 0.0)) self.assert_layout_positions(layout['grandchild 4'], (2 / 6., 0.0)) self.assert_layout_positions(layout['grandchild 5'], (1 / 6., 0.0))
def test_layout(self): g = networkx.DiGraph() g.add_edge('root', 'child 1') g.add_edge('child 1', 'grandchild 1') g.add_edge('child 1', 'grandchild 2') g.add_edge('root', 'child 2') g.add_edge('child 2', 'grandchild 3') g.add_edge('child 2', 'grandchild 4') g.add_edge('child 2', 'grandchild 5') layout = tree_layout(g) self.assert_layout_positions(layout['root'], (0.5, 1.0)) self.assert_layout_positions(layout['child 1'], (2 / 3., 0.5)) self.assert_layout_positions(layout['child 2'], (1 / 3., 0.5)) self.assert_layout_positions(layout['grandchild 1'], (5 / 6., 0.0)) self.assert_layout_positions(layout['grandchild 2'], (4 / 6., 0.0)) self.assert_layout_positions(layout['grandchild 3'], (3 / 6., 0.0)) self.assert_layout_positions(layout['grandchild 4'], (2 / 6., 0.0)) self.assert_layout_positions(layout['grandchild 5'], (1 / 6., 0.0))
def test_layout(self): g = networkx.DiGraph() g.add_edge('root', 'child 1') g.add_edge('child 1', 'grandchild 1') g.add_edge('child 1', 'grandchild 2') g.add_edge('root', 'child 2') g.add_edge('child 2', 'grandchild 3') g.add_edge('child 2', 'grandchild 4') g.add_edge('child 2', 'grandchild 5') layout = tree_layout(g) expected_root_x, expected_root_y = (0.5, 1.0) self.assertAlmostEqual(layout['root'][0], expected_root_x) self.assertAlmostEqual(layout['root'][1], expected_root_y) gc_xs = [ value[0] for key, value in layout.items() if key.startswith('child') ] expected_gc_xs = [x / 3.0 for x in range(1, 3)] nptest.assert_almost_equal(sorted(gc_xs), expected_gc_xs) gc_ys = [ value[1] for key, value in layout.items() if key.startswith('child') ] expected_gc_ys = [0.5] * 2 nptest.assert_almost_equal(sorted(gc_ys), expected_gc_ys) gc_xs = [ value[0] for key, value in layout.items() if 'grandchild' in key ] expected_gc_xs = [x / 6.0 for x in range(1, 6)] nptest.assert_almost_equal(sorted(gc_xs), expected_gc_xs) gc_ys = [ value[1] for key, value in layout.items() if 'grandchild' in key ] expected_gc_ys = [0.0] * 5 nptest.assert_almost_equal(sorted(gc_ys), expected_gc_ys)
def do_layout(self, size=None, force=False): """ Nodes of the graph will be layed out based on the the style attribute """ if not self._graph_layout_needed or len(self.components) == 0: return def _apply_graphviz_layout(layout): min_x = min([pos[0] for pos in layout.values()]) max_y = max([pos[1] for pos in layout.values()]) for component in self.components: component.x = self.width + layout[component._key][0] - min_x component.y = self.height + layout[component._key][1] - max_y initial_positions = { node.value: node.position for node in self.components } if all(point == [0.0, 0.0] for point in initial_positions.values()): initial_positions = None scale = min(self.bounds) if self.style == 'tree': try: layout = networkx.drawing.nx_agraph.pygraphviz_layout( self.graph, prog='dot' ) _apply_graphviz_layout(layout) except ImportError: layout = tree_layout(self.graph) # resize the bounds to fit the graph depths = [v[1] for v in layout.values()] widths = [depths.count(d) for d in numpy.unique(depths)] max_width = max(widths) max_depth = len(widths) self.bounds = [max(75, self.components[0].width)*max_width, max(50, self.components[0].height)*max_depth] for component in self.components: component.x = self.width * layout[component._key][0] component.y = self.height * layout[component._key][1] elif self.style == 'shell': layout = networkx.shell_layout(self.graph) # resize the bounds to fit the graph radius = numpy.log2(len(layout)) self.bounds = [max(75, self.components[0].width)*2*radius, max(50, self.components[0].height)*2*radius] for component in self.components: component.y = self.height * (1 + layout[component._key][0])/2 component.x = self.width * (1 + layout[component._key][1])/2 elif self.style == 'spectral': layout = networkx.spectral_layout(self.graph) # resize the bounds to fit the graph radius = numpy.log2(len(layout)) self.bounds = [max(75, self.components[0].width)*2*radius, max(50, self.components[0].height)*2*radius] for component in self.components: component.y = self.height * (1 + layout[component._key][0])/2 component.x = self.width * (1 + layout[component._key][1])/2 elif self.style == 'circular': try: layout = networkx.drawing.nx_agraph.pygraphviz_layout( self.graph, prog='twopi' ) _apply_graphviz_layout(layout) except ImportError: layout = networkx.circular_layout( self.graph, scale=min(self.bounds) // 2, center=[bound // 2 for bound in self.bounds], ) for component in self.components: component.x = layout[component._key][0] component.y = layout[component._key][1] else: layout = networkx.spring_layout( self.graph, pos=initial_positions, scale=scale, ) # resize the bounds to fit the graph radius = len(layout) self.bounds = [max(75, self.components[0].width)*2*radius, max(50, self.components[0].height)*2*radius] for component in self.components: component.x = layout[component._key][0] component.y = layout[component._key][1] self._graph_layout_needed = False
def test_not_acyclic(self): g = networkx.DiGraph() g.add_edge('root', 'child') g.add_edge('child', 'root') with self.assertRaisesRegexp(ValueError, 'must not contain cycles'): tree_layout(g)
def test_not_directed(self): g = networkx.Graph() with self.assertRaisesRegexp(ValueError, 'directed'): tree_layout(g)
def test_non_2D(self): g = networkx.DiGraph() with self.assertRaisesRegexp(ValueError, 'only 2D graphs'): tree_layout(g, dim=1) tree_layout(g, dim=3)
def do_layout(self, size=None, force=False): """ Nodes of the graph will be layed out based on the the style attribute """ if not self._graph_layout_needed or len(self.components) == 0: return def _apply_graphviz_layout(layout): min_x = min([pos[0] for pos in layout.values()]) max_y = max([pos[1] for pos in layout.values()]) for component in self.components: component.x = self.width + layout[component._key][0] - min_x component.y = self.height + layout[component._key][1] - max_y initial_positions = { node.value: node.position for node in self.components } if all(point == [0.0, 0.0] for point in initial_positions.values()): initial_positions = None scale = min(self.bounds) if self.style == 'tree': try: layout = networkx.drawing.nx_agraph.pygraphviz_layout( self.graph, prog='dot' ) _apply_graphviz_layout(layout) except ImportError: layout = tree_layout(self.graph) # resize the bounds to fit the graph depths = [v[1] for v in layout.values()] widths = [depths.count(d) for d in numpy.unique(depths)] max_width = max(widths) max_depth = len(widths) self.bounds = [max(75, self.components[0].width)*max_width, max(50, self.components[0].height)*max_depth] for component in self.components: component.x = self.width * layout[component._key][0] component.y = self.height * layout[component._key][1] elif self.style == 'shell': layout = networkx.shell_layout(self.graph) # resize the bounds to fit the graph radius = numpy.log2(len(layout)) self.bounds = [max(75, self.components[0].width)*2*radius, max(50, self.components[0].height)*2*radius] for component in self.components: component.y = self.height * (1 + layout[component._key][0])/2 component.x = self.width * (1 + layout[component._key][1])/2 elif self.style == 'spectral': layout = networkx.spectral_layout(self.graph) # resize the bounds to fit the graph radius = numpy.log2(len(layout)) self.bounds = [max(75, self.components[0].width)*2*radius, max(50, self.components[0].height)*2*radius] for component in self.components: component.y = self.height * (1 + layout[component._key][0])/2 component.x = self.width * (1 + layout[component._key][1])/2 elif self.style == 'circular': try: layout = networkx.drawing.nx_agraph.pygraphviz_layout( self.graph, prog='twopi' ) _apply_graphviz_layout(layout) except ImportError: layout = networkx.circular_layout( self.graph, scale=min(self.bounds) // 2, center=[bound // 2 for bound in self.bounds], ) for component in self.components: component.x = layout[component._key][0] component.y = layout[component._key][1] else: layout = networkx.spring_layout( self.graph, pos=initial_positions, scale=scale, ) # resize the bounds to fit the graph radius = len(layout) self.bounds = [max(75, self.components[0].width)*2*radius, max(50, self.components[0].height)*2*radius] for component in self.components: component.x = layout[component._key][0] component.y = layout[component._key][1] self._graph_layout_needed = False
def test_not_acyclic(self): g = networkx.DiGraph() g.add_edge('root', 'child') g.add_edge('child', 'root') with self.assertRaisesRegexp(ValueError, 'must not contain cycles'): tree_layout(g)
def test_not_directed(self): g = networkx.Graph() with self.assertRaisesRegexp(ValueError, 'directed'): tree_layout(g)
def test_non_2D(self): g = networkx.DiGraph() with self.assertRaisesRegexp(ValueError, 'only 2D graphs'): tree_layout(g, dim=1) tree_layout(g, dim=3)