Exemple #1
0
 def test_invalid_backend(self):
     png_rend = GraphRenderer(backend=PngBackend())
     json_rend = GraphRenderer(backend=JsonBackend())
     with pytest.raises(TypeError):
         GifAnimator(renderer=json_rend)
     with pytest.raises(TypeError):
         JsonAnimator(renderer=png_rend)
Exemple #2
0
 def test_png_is_default(self, dataset, tmpdir):
     out = tmpdir.join("mygraph.png")
     rend = GraphRenderer(backend=None)
     assert isinstance(rend.backend, PngBackend)
     rend.render(dataset, out)
     with open(str(out), "rb") as f:
         assert is_valid_png(f)
Exemple #3
0
    def test_entity_positioning(self, dataset):
        cs = ExampleColourScheme()
        rend = GraphRenderer(width=100, node_radius=10, spacing=14, colours=cs)
        ents = list(rend.compile(dataset))

        assert len(ents) == (
            1  # background
            + 4 * 2  # sources
            + 6  # edges from sources to claims
            + 4 * 2  # claims
            + 4  # edges from claims to variables
            + 3 * 2  # variables
            + 2 * (6 + 4)  # arrow heads
        )

        colours = ExampleColourScheme.colours
        bgs = [e for e in ents if e.colour == colours["background"]]
        assert len(bgs) == 1
        assert isinstance(bgs[0], Rectangle)
        assert bgs[0].x == 0
        assert bgs[0].y == 0
        assert bgs[0].width == 100

        # The max number of verical nodes is 4, so height should be
        # 2*radius*4 + spacing*3
        assert bgs[0].height == 2 * 10 * 4 + 14 * 3

        # Should be 4 sources, 4 claims, and 3 variables
        source_ents = [e for e in ents if e.colour == colours[NodeType.SOURCE]]
        claim_ents = [e for e in ents if e.colour == colours[NodeType.CLAIM]]
        var_ents = [e for e in ents if e.colour == colours[NodeType.VARIABLE]]
        for e in source_ents:
            print(e.x, e.y, e.colour)
        assert len(source_ents) == 4
        assert len(claim_ents) == 4
        assert len(var_ents) == 3

        # Should be 4 + 4 + 3 border circles
        border_ents = [e for e in ents if e.colour == colours["border"]]
        assert len(border_ents) == 4 + 4 + 3

        # All nodes should be Circle objects
        for e in source_ents + claim_ents + var_ents + border_ents:
            assert isinstance(e, Circle)

        # There should be 6 edges from sources to claims, and 4 from claims to
        # variables. For each edge there should be two lines for the arrow
        # heads
        edge_ents = [e for e in ents if e.colour == colours["edge"]]
        assert len(edge_ents) == (6 + 4) * 3
        for e in edge_ents:
            assert isinstance(e, Line)

        # Sources should be aligned in x coordinates
        source_coords = [(ent.x, ent.y) for ent in source_ents]
        assert len(set(x for x, y in source_coords)) == 1
        # Check y positioning
        y_coords = sorted(y for x, y in source_coords)
        assert y_coords == [10, 44, 78, 112]
Exemple #4
0
    def test_progress_bar(self, dataset):
        w = 200
        rend = GraphRenderer(width=w, backend=JsonBackend())
        anim = JsonAnimator(renderer=rend)

        buf = StringIO()
        it = FixedIterator(20)
        alg = Sums(iterator=it)
        anim.animate(buf, alg, dataset, show_progress=True)
        buf.seek(0)
        obj = json.load(buf)
        # Get the frame for the 5th iteration, which is 1 / 4 through
        frame = obj["frames"][5]
        rects = [
            e for e in frame["entities"]
            if e["type"] == "rectangle" and e["width"] != w
        ]
        assert len(rects) == 1
        assert rects[0]["x"] == 0
        assert rects[0]["width"] == w / 4

        # Test without progress
        buf2 = StringIO()
        anim.animate(buf2, alg, dataset, show_progress=False)
        buf2.seek(0)
        obj2 = json.load(buf2)
        frame2 = obj2["frames"][5]
        rects2 = [
            e for e in frame2["entities"]
            if e["type"] == "rectangle" and e["width"] != w
        ]
        assert not len(rects2)
Exemple #5
0
    def test_renderer(self):
        # Custom renderer should be used if provided
        custom_renderer = GraphRenderer(font_size=10000)
        anim = GifAnimator(renderer=custom_renderer)
        assert anim.renderer == custom_renderer

        # Otherwise a default renderer
        anim2 = GifAnimator()
        assert isinstance(anim2.renderer, GraphRenderer)
Exemple #6
0
 def test_single_source(self):
     one_source_dataset = Dataset(
         (("source 1", "x", 1), ("source 1", "y", 1)))
     one_var_dataset = Dataset((("source 1", "x", 1), ("source 2", "x", 2)))
     one_claim_dataset = Dataset(
         (("source 1", "x", 1), ("source 2", "x", 1)))
     rend = GraphRenderer(node_radius=66,
                          spacing=13,
                          colours=ExampleColourScheme())
     # Check the positioning of nodes for the one-source dataset
     ents = list(rend.compile(one_source_dataset))
     colours = ExampleColourScheme.colours
     sources = [e for e in ents if e.colour == colours[NodeType.SOURCE]]
     assert len(sources) == 1
     assert sources[0].y == (2 * 66 * 2 + 13) / 2
     # Check the other two don't raise any exceptions
     list(rend.compile(one_var_dataset))
     list(rend.compile(one_claim_dataset))
Exemple #7
0
    def test_progress_bar(self, dataset):
        w = 200
        anim_colour = (0.34, 0.99, 0.34)

        class MyColourScheme(GraphColourScheme):
            def get_animation_progress_colour(self):
                return anim_colour

        rend = GraphRenderer(width=w, colours=MyColourScheme())
        ents = list(rend.compile(dataset, animation_progress=0.25))
        rects = [e for e in ents if e.colour == anim_colour]
        assert len(rects) == 1
        assert rects[0].x == 0
        assert rects[0].width == 50

        # Test without progress bar
        ents2 = list(rend.compile(dataset, animation_progress=None))
        rects2 = [e for e in ents2 if e.colour == anim_colour]
        assert not len(rects2)
Exemple #8
0
 def test_long_labels(self):
     dataset = Dataset(
         (("a-source-with-an-extremely-long-name", "x",
           1000000000000000000),
          ("source 2", "quite a complicated variable name", 100)))
     ents = list(GraphRenderer().compile(dataset))
     assert len(ents) == (
         1 +  # background
         6 * 2 +  # 6 nodes, each represented by two circles
         4 * 3  # 4 edges and arrowheads
     )
Exemple #9
0
    def test_image_size(self, dataset):
        buf = BytesIO()
        w = 142

        nr = 13
        sp = 15
        h = 2 * nr * 4 + sp * 3

        print(dataset.num_sources)
        print(dataset.num_claims)
        print(dataset.num_variables)

        rend = GraphRenderer(width=w,
                             node_radius=nr,
                             spacing=sp,
                             backend=PngBackend())
        rend.render(dataset, buf)
        buf.seek(0)
        img_data = imageio.imread(buf)
        got_w, got_h, _ = img_data.shape
        assert (got_h, got_w) == (w, h)
Exemple #10
0
    def test_json_backend(self):
        w = 123
        h = 2 * 10 * 2 + 5
        rend = GraphRenderer(width=w,
                             node_radius=10,
                             spacing=5,
                             backend=JsonBackend())
        buf = StringIO()

        data = Dataset((("s1", "x", 0), ("s2", "y", 1)))

        rend.render(data, buf)
        buf.seek(0)
        obj = json.load(buf)
        assert isinstance(obj, dict)
        assert "width" in obj
        assert "height" in obj
        assert "entities" in obj
        assert obj["width"] == w
        assert obj["height"] == h

        ents = obj["entities"]
        assert isinstance(ents, list)
        # Background
        assert len([e for e in ents if e["type"] == "rectangle"]) == 1
        # Nodes and borders
        assert len([e for e in ents if e["type"] == "circle"]) == 6 * 2
        # Edges and arrow heads
        assert len([e for e in ents if e["type"] == "line"]) == 3 * 4

        assert ents[0] == {
            "type": "rectangle",
            "x": 0,
            "y": 0,
            "colour": list(rend.colours.get_background_colour()),
            "width": w,
            "height": h
        }
Exemple #11
0
    def test_gif_animation(self, dataset):
        w, h = 123, 95
        renderer = GraphRenderer(width=w, node_radius=10, spacing=5)
        animator = GifAnimator(renderer=renderer)
        alg = Sums()
        buf = BytesIO()
        animator.animate(buf, alg, dataset)
        buf.seek(0)
        assert is_valid_gif(buf)

        # Check dimensions are as expected
        buf.seek(0)
        img_data = imageio.imread(buf)
        got_w, got_h, _ = img_data.shape
        assert (got_h, got_w) == (w, h)
Exemple #12
0
    def test_json_animation(self, dataset):
        w, h = 123, 95
        renderer = GraphRenderer(width=w,
                                 node_radius=10,
                                 spacing=5,
                                 backend=JsonBackend())
        animator = JsonAnimator(renderer=renderer, frame_duration=1 / 9)
        alg = Sums(iterator=FixedIterator(4))
        buf = StringIO()
        animator.animate(buf, alg, dataset)
        buf.seek(0)
        obj = json.load(buf)

        assert "fps" in obj
        assert obj["fps"] == 9
        assert "frames" in obj
        assert isinstance(obj["frames"], list)
        assert len(obj["frames"]) == 5
        assert isinstance(obj["frames"][0], dict)
        assert "width" in obj["frames"][0]
        assert "height" in obj["frames"][0]
        assert "entities" in obj["frames"][0]
        assert obj["frames"][0]["width"] == w
        assert obj["frames"][0]["height"] == h
Exemple #13
0
 def test_results_based_valid_png(self, dataset, tmpdir):
     cs = ResultsGradientColourScheme(Sums().run(dataset))
     out = tmpdir.join("mygraph.png")
     GraphRenderer(backend=PngBackend(), colours=cs).render(dataset, out)
     with open(str(out), "rb") as f:
         assert is_valid_png(f)
Exemple #14
0
 def test_valid_png(self, dataset, tmpdir):
     out = tmpdir.join("mygraph.png")
     GraphRenderer(backend=PngBackend()).render(dataset, out)
     with open(str(out), "rb") as f:
         assert is_valid_png(f)
Exemple #15
0
 def test_base_backend(self, dataset, tmpdir):
     out = tmpdir.join("mygraph.png")
     with pytest.raises(NotImplementedError):
         GraphRenderer(backend=BaseBackend()).render(dataset, out)
    plain = False
    if len(sys.argv) == 3 and sys.argv[1] == "--plain":
        outpath = sys.argv[2]
        plain = True
    elif len(sys.argv) == 2:
        outpath = sys.argv[1]
    else:
        print("usage: {} [--plain] DEST".format(sys.argv[0]), file=sys.stderr)
        sys.exit(1)

    tuples = [
        ("source 1", "x", 4),
        ("source 1", "y", 7),
        ("source 2", "y", 7),
        ("source 2", "z", 5),
        ("source 3", "x", 3),
        ("source 3", "z", 5),
        ("source 4", "x", 3),
        ("source 4", "y", 6),
        ("source 4", "z", 8),
        ("my really long source name", "mylongvar", "extremelylongvalue"),
    ]
    mydata = Dataset(tuples)
    results = Sums().run(mydata)

    colour_scheme = (PlainColourScheme()
                     if plain else ResultsGradientColourScheme(results))
    renderer = GraphRenderer(width=1000, colours=colour_scheme)
    with open(outpath, "wb") as imgfile:
        renderer.render(mydata, imgfile)