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

APN-Pucky / pyfeyn2 / 14948992946

10 May 2025 08:46PM UTC coverage: 65.23% (-1.8%) from 67.018%
14948992946

Pull #319

github

APN-Pucky
Fix typo
Pull Request #319: add: root renderer

47 of 155 new or added lines in 9 files covered. (30.32%)

2 existing lines in 1 file now uncovered.

2180 of 3342 relevant lines covered (65.23%)

0.65 hits per line

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

3.9
/pyfeyn2/render/root/rootrender.py
1
import tempfile
1✔
2
from typing import List
1✔
3

4
import ROOT
1✔
5

NEW
6
from pyfeyn2.render.render import Render
×
NEW
7
from pyfeyn2.render.root.pyfeyn import Label, Propagator, Vertex
×
8

NEW
9
type_map = {
×
10
    "line": "line",
11
    "photon": "wavyline",
12
    "gluon": "curlyline",
13
    "gluino": "curlystraightline",
14
    "charged boson": "wavystraightline",
15
    "higgs": "dashedline",
16
    "ghost": "dottedline",
17
}
18

19

NEW
20
def root_to_cpp(root_canvas) -> str:
×
21
    # create a tmp tex file
NEW
22
    with tempfile.NamedTemporaryFile(
×
23
        suffix=".tex", delete=True, mode="w+"
24
    ) as temp_file:
NEW
25
        root_canvas.SaveSource(temp_file.name)
×
26
        # read the file
NEW
27
        tex_src = temp_file.read()
×
NEW
28
        return tex_src
×
NEW
29
    raise RuntimeError("Failed to create temporary file")
×
30

31

NEW
32
def get_property(fd, obj, prop, default=None):
×
NEW
33
    style = fd.get_style(obj)
×
NEW
34
    if style.getProperty(prop) is not None:
×
NEW
35
        return style.getProperty(prop).value
×
36
    else:
NEW
37
        return default
×
38

39

NEW
40
def get_property_value(style, prop, default=None):
×
NEW
41
    if style.getProperty(prop) is not None:
×
NEW
42
        return style.getProperty(prop).value
×
43
    else:
NEW
44
        return default
×
45

46

NEW
47
class ROOTRender(Render):
×
NEW
48
    def __init__(self, fd=None, *args, **kwargs):
×
NEW
49
        super().__init__(fd, *args, **kwargs)
×
50

NEW
51
    def get_src_root(self):
×
NEW
52
        return self.src_root
×
53

NEW
54
    def set_src_root(self, src_root):
×
NEW
55
        self.src_root = src_root
×
NEW
56
        self.src_cpp = root_to_cpp(src_root)
×
57

NEW
58
    def render(
×
59
        self,
60
        file=None,
61
        show=True,
62
        resolution=100,
63
        width=None,
64
        height=None,
65
        clean_up=True,
66
    ):
NEW
67
        if width is None:
×
NEW
68
            width = 600
×
NEW
69
        if height is None:
×
NEW
70
            height = 600
×
71

NEW
72
        minx, miny, maxx, maxy = self.fd.get_bounding_box()
×
NEW
73
        marginx = (maxx - minx) * 0.05
×
NEW
74
        marginy = (maxy - miny) * 0.05
×
NEW
75
        canvas = ROOT.TCanvas("c", "A canvas", 10, 10, width, height)
×
NEW
76
        canvas.Range(minx - marginx, miny - marginy, maxx + marginx, maxy + marginy)
×
77

NEW
78
        vertex_to_vertex = {}
×
79

NEW
80
        for v in self.fd.vertices:
×
NEW
81
            ox = get_property(self.fd, v, "label-offset-x", 0)
×
NEW
82
            oy = get_property(self.fd, v, "label-offset-y", 0)
×
NEW
83
            vertex_to_vertex[v.id] = Vertex(
×
84
                v.x,
85
                v.y,
86
                label=Label(text=v.label, offsetx=ox, offsety=oy),
87
            )
NEW
88
        for l in self.fd.legs:
×
89
            # ox = get_property(self.fd, l, "label-offset-x", 0)
90
            # oy = get_property(self.fd, l, "label-offset-y", 0)
NEW
91
            vertex_to_vertex[l.id] = Vertex(
×
92
                l.x,
93
                l.y,
94
                # label=Label(text = l.label, offsetx=ox, offsety=oy),
95
            )
96

NEW
97
        for p in self.fd.propagators:
×
NEW
98
            style = self.fd.get_style(p)
×
NEW
99
            ox = get_property_value(style, "label-offset-x", 0)
×
NEW
100
            oy = get_property_value(style, "label-offset-y", 0)
×
NEW
101
            double_distance = int(get_property_value(style, "double-distance", "3"))
×
NEW
102
            Propagator(
×
103
                vertex_to_vertex[p.source],
104
                vertex_to_vertex[p.target],
105
                typ=get_property_value(style, "line", "line"),
106
                label=Label(text=p.label, offsetx=ox, offsety=oy),
107
                linecolor=style.color,
108
                double_distance=double_distance,
109
            ).draw()
NEW
110
        for l in self.fd.legs:
×
NEW
111
            style = self.fd.get_style(l)
×
NEW
112
            ox = get_property_value(style, "label-offset-x", 0)
×
NEW
113
            oy = get_property_value(style, "label-offset-y", 0)
×
NEW
114
            double_distance = int(get_property_value(style, "double-distance", "3"))
×
NEW
115
            if l.is_incoming():
×
NEW
116
                src, tgt = l.target, l.id
×
117
            else:
NEW
118
                src, tgt = l.id, l.target
×
119

NEW
120
            Propagator(
×
121
                vertex_to_vertex[src],
122
                vertex_to_vertex[tgt],
123
                typ=get_property_value(style, "line", "line"),
124
                label=Label(text=l.label, offsetx=ox, offsety=oy),
125
                linecolor=style.color,
126
                double_distance=double_distance,
127
            ).draw()
128

NEW
129
        if show:
×
NEW
130
            canvas.Update()
×
NEW
131
        self.set_src_root(canvas)
×
NEW
132
        return canvas
×
133

NEW
134
    @classmethod
×
NEW
135
    def valid_styles(cls) -> bool:
×
NEW
136
        return super().valid_styles() + [
×
137
            "line",
138
            "label-offset-x",
139
            "label-offset-y",
140
            "double-distance",
141
            "color",
142
            # "symbol",
143
            # "symbol-size",
144
            # "opacity",
145
            # "bend-direction",
146
            # "bend-in",
147
            # "bend-out",
148
            # "bend-loop",
149
            # "bend-min-distance",
150
            # "momentum-arrow",
151
            # "momentum-arrow-sense",
152
            # "label-side",
153
        ]
154

NEW
155
    @classmethod
×
NEW
156
    def valid_attributes(cls) -> List[str]:
×
NEW
157
        return super().valid_attributes() + [
×
158
            "x",
159
            "y",
160
            "label",
161
            "style",
162
        ]
163

NEW
164
    @classmethod
×
NEW
165
    def valid_types(cls) -> List[str]:
×
NEW
166
        return super().valid_types() + [
×
167
            "baryon",
168
            "anti baryon",
169
            "line",
170
            "photon",
171
            "gluon",
172
            "gluino",
173
            "charged boson",
174
            "higgs",
175
            "ghost",
176
            "phantom",
177
            "boson",
178
            "fermion",
179
            "anti fermion",
180
            "squark",
181
            "anti squark",
182
        ]
183

NEW
184
    @classmethod
×
NEW
185
    def valid_shapes(cls) -> List[str]:
×
NEW
186
        return super().valid_types() + []
×
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

© 2026 Coveralls, Inc