• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Edinburgh-Genome-Foundry / DnaCauldron / 14249097482

03 Apr 2025 05:22PM UTC coverage: 87.716% (-0.8%) from 88.541%
14249097482

push

github

veghp
Bump to v2.0.10

1 of 1 new or added line in 1 file covered. (100.0%)

114 existing lines in 21 files now uncovered.

2185 of 2491 relevant lines covered (87.72%)

0.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.57
/dnacauldron/AssemblyPlan/plot_leveled_graph.py
1
import numpy as np
1✔
2
import matplotlib.pyplot as plt
1✔
3
import matplotlib.patches as mpatches
1✔
4
from matplotlib.path import Path
1✔
5

6

7
def plot_leveled_graph(
1✔
8
    levels,
9
    edges,
10
    draw_node,
11
    elements_positions=None,
12
    ax=None,
13
    width_factor=2.5,
14
    height_factor=2,
15
    scale=1.0,
16
    edge_left_space=0.015,
17
    edge_right_space=0.015,
18
    interlevel_shift=0,
19
    margin=None,
20
    **txt_kw
21
):
22
    """General function for plotting tree graphs.
23
    Parameters
24
    ----------
25
    levels
26
      A list of lists of nodes grouped by "level", i.e distance to the in the
27
      graph to the level 0. levels will be displayed on a same column.
28
    edges
29
      List of nodes pairs (source node, target node).
30
    draw_node
31
      A function f(x , y , node, ax, **kw) which draws something related to the
32
      node at the position x,y on the given Matplotlib ax.
33
    ax
34
      The matplotlib ax to use. If none is provided, a new ax is generated.
35
    Returns
36
    -------
37
    elements_positions, ax
38
      Dictionary of elements positions, matplotlib ax.
39
    Examples:
40
    ---------
41
    >>> def draw_node(x,y, node, ax):
42
            ax.text(x,y, node)
43
    >>> positions, ax = plot_tree_graph(
44
            levels=[["A","B","C"], ["D,E"], ["F"]],
45
            edges=[("A","D"),("B","D"),("C","E"), ("D","F"),("E","F")],
46
            draw_node = draw_node
47
        )
48
    """
49
    levels_dict = {
1✔
50
        element: level for level, elements in enumerate(levels) for element in elements
51
    }
52
    if elements_positions is None:
1✔
53
        elements_positions = {}
1✔
54
        for lvl, elements in enumerate(levels):
1✔
55
            yy = np.linspace(0, 1, len(elements) + 2)[1:-1]
1✔
56
            yy += interlevel_shift * (1 - 2 * (lvl % 2))
1✔
57
            x = 1.0 * (1 + lvl) / (len(levels) + 1)
1✔
58
            for y, element in zip(yy, elements):
1✔
59
                elements_positions[element] = (x, y)
1✔
60

61
    if ax is None:
1✔
62
        width = width_factor * len(levels) * scale
1✔
63
        height = height_factor * max([len(lvl) for lvl in levels]) * scale
1✔
64
        fig, ax = plt.subplots(1, figsize=(width, height))
1✔
65

66
    for element, (x, y) in elements_positions.items():
1✔
67
        draw_node(x, y, element, ax, **txt_kw)
1✔
68

69
    y_spans = [
1✔
70
        elements_positions[elements[1]][1] - elements_positions[elements[0]][1]
71
        for elements in levels
72
        if len(elements) > 1
73
    ]
74

75
    delta_y = 0.5 * min(y_spans) if y_spans != [] else 0
1✔
76
    for el1, el2 in edges:
1✔
77
        x1, y1 = elements_positions[el1]
1✔
78
        x2, y2 = elements_positions[el2]
1✔
79
        x1 += edge_left_space * np.sqrt(scale)
1✔
80
        x2 += -edge_right_space * np.sqrt(scale)
1✔
81
        if ((levels_dict[el2] - levels_dict[el1]) > 1) and (y1 == y2):
1✔
UNCOV
82
            patch = mpatches.PathPatch(
×
83
                Path(
84
                    [
85
                        (x1, y1),
86
                        (0.5 * x2 + 0.5 * x1, y1 - delta_y),
87
                        (0.5 * x2 + 0.5 * x1, y2 - delta_y),
88
                        (x2, y2),
89
                    ],
90
                    [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4],
91
                ),
92
                facecolor="none",
93
                lw=1 * scale,
94
                zorder=-1000,
95
            )
96

97
        else:
98
            patch = mpatches.PathPatch(
1✔
99
                Path(
100
                    [
101
                        (x1, y1),
102
                        (0.9 * x2 + 0.1 * x1, y1),
103
                        (0.1 * x2 + 0.9 * x1, y2),
104
                        (x2, y2),
105
                    ],
106
                    [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4],
107
                ),
108
                facecolor="none",
109
                lw=1 * scale,
110
                zorder=-1000,
111
            )
112

113
        ax.add_patch(patch)
1✔
114

115
    ax.axis("off")
1✔
116
    if margin is not None:
1✔
UNCOV
117
        xx, yy = [np.array(e) for e in zip(*elements_positions.values())]
×
UNCOV
118
        xmin, xmax = xx.min(), xx.max()
×
119
        dx = margin * (xmax - xmin)
×
120
        ymin, ymax = yy.min(), yy.max()
×
121
        dy = margin * (ymax - ymin)
×
122
        d = max(dx, dy)
×
123
        ax.set_xlim(xmin - d, xmax + d)
×
124
        ax.set_ylim(ymin - d, ymax + d)
×
125

126
    return elements_positions, ax
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc