1 """PyFeyn interface to the proposed FeynML XML dialect."""
2
3 import math, pyx, md5
4 from xml.dom.minidom import *
5
6
8 """Class to write a FeynML representation of a Feynman diagram."""
9
11 """Write FeynML to a file."""
12 pass
13
14
16 root = xml.Element("diagram")
17 for obj in self.__objs:
18 root.append(obj.to_xml())
19 return xml.tostring(root).replace(">",">\n")
20
22 ele = xml.Element("blob",
23 {"id" : "V%s" % md5.md5(str(self.xpos, self.ypos)).hexdigest(),
24 "x" : str(self.xpos), "y" : str(self.ypos),
25 "shape" : hasattr(self,"blobshape") and self.blobshape or "circle"})
26 return ele
27
29 attribs = {"id":"P%s"%md5.md5(str((self.p1.xpos,self.p1.ypos,self.p2.xpos,self.p2.ypos,self.__arcthrupoint and (self.__arcthrupoint.xpos,self.__arcthrupoint.ypos)))).hexdigest(),
30 "source":"V%s"%md5.md5(str((self.p1.xpos,self.p1.ypos))).hexdigest(),
31 "target":"V%s"%md5.md5(str((self.p2.xpos,self.p2.ypos))).hexdigest(),
32 "type":hasattr(self,"linetype") and self.linetype or "fermion"}
33 if self.bendamount:
34 attribs["bend"] = str(self.bendamount)
35 ele = xml.Element("propagator",attribs)
36 return ele
37
39 ele = xml.Element("vertex",{"id":"V%s"%md5.md5(str((self.xpos,self.ypos))).hexdigest(),"x":str(self.xpos), "y":str(self.ypos)})
40 return ele
41
43 ele = Point.to_xml(self)
44 fills = ""
45 for x in self.fillstyles:
46 if isinstance(x,pyx.color.rgb):
47 fills = fills + " #%02x%02x%02x"%(255*x.color["r"], 255*x.color["g"], 255*x.color["b"])
48 strokes = ""
49 for x in self.strokestyles:
50 if isinstance(x,pyx.color.rgb):
51 strokes = strokes + " #%02x%02x%02x"%(255*x.color["r"], 255*x.color["g"],255*x.color["b"])
52 s = "mark-shape:%s;mark-size:%s;fill-style:%s;line-style:%s;" % \
53 (MarkedName[self.marker],pyx.unit.tocm(self.radius), fills,strokes )
54 ele.attrib["style"] = s
55 return ele
56
57
58
59
60
61
62
64 """Class to construct a Feynman diagram from its FeynML representation."""
65
67 """Read FeynML from a file."""
68 self.root = elementtree.parse(filename).getroot()
69 self.diagrams = []
70 self.dicts = []
71 if self.root.tag != "feynml":
72 raise "FeynML Error: <Feynml> must be root element"%self.root.tag
73 for element in self.root:
74 if element.tag == "head":
75 pass
76 elif element.tag == "diagram":
77 self.diagrams.append(element)
78 self.dicts.append({})
79 else:
80 raise "FeynML Error: invalid top-level tag <%s>"%element.tag
81
83 """Return the nth Feynman diagram represented by file contents."""
84 fd = feyn.FeynDiagram()
85 thediagram = self.diagrams[n]
86 thedict = self.dicts[n]
87 for element in thediagram:
88 if element.tag == "propagator":
89 fd.add( self.get_line(element,thedict) )
90 elif element.tag == "vertex":
91 fd.add( self.get_vertex(element,thedict) )
92 elif element.tag == "leg":
93 fd.add( self.get_leg(element,thedict) )
94 elif element.tag == "blob":
95 fd.add( self.get_blob(element,thedict) )
96 elif element.tag == "connect":
97 fd.add( self.get_connect(element,thedict) )
98 elif element.tag == "label":
99 pass
100 else:
101 raise "FeynML Error: invalid tag <%s> in <diagram>"%element.tag
102 return fd
103
105 """Build a vertex from its FeynML representation."""
106
107 try:
108 x = float(element.attrib["x"])
109 y = float(element.attrib["y"])
110 except:
111 raise "FeynML Error: invalid x,y attributes for <vertex> element"
112 v = feyn.DecoratedPoint(x,y)
113 if "style" in element.attrib:
114 v = self.apply_layout(element.attrib["style"],v)
115 if "label" in element.attrib:
116 v = v.fillstyle(feyn.FreeTeXLabel(element.attrib["label"],x,y,displace=3*pyx.unit.t_pt,angle=90))
117 try:
118 thedict[element.attrib["id"]] = v
119 except:
120 raise "FeynML Error: missing id attribute in <vertex> element"
121 return v
122
124 """Build a line from its feynML representation."""
125
126 try:
127 type = element.attrib["type"]
128 p1 = thedict[element.attrib["source"]]
129 p2 = thedict[element.attrib["target"]]
130 except:
131 raise "FeynML Error: invalid attribute for <propagator> element"
132 l = feyn.NamedLine[type](p1,p2)
133 if "bend" in element.attrib:
134 l.bend(float(element.attrib["bend"]))
135 if "style" in element.attrib:
136 l = self.apply_layout(element.attrib["style"],l)
137 if "label" in element.attrib:
138 l = l.style(feyn.TeXLabel(element.attrib["label"]))
139 try:
140 thedict[element.attrib["id"]] = l
141 except:
142 raise "FeynML Error: missing id attribute in <propagator> element"
143 return l
144
145 - def get_leg(self,element,thedict):
146 """Build a leg from its FeynML representation."""
147
148 try:
149 type = element.attrib["type"]
150 x = float(element.attrib["x"])
151 y = float(element.attrib["y"])
152 p2 = thedict[element.attrib["target"]]
153 except:
154 raise "FeynML Error: invalid attribute for <leg> element"
155 l = feyn.NamedLine[type](feyn.Point(x,y),p2)
156 if "style" in element.attrib:
157 l = self.apply_layout(element.attrib["style"],l)
158 if "label" in element.attrib:
159 l = l.style(feyn.TeXLabel(element.attrib["label"]))
160 try:
161 thedict[element.attrib["id"]] = l
162 except:
163 raise "FeynML Error: missing id attribute in <leg> element"
164 return l
165
167 """Build a blob from its FeynML representation."""
168 try:
169 x = float(element.attrib["x"])
170 y = float(element.attrib["y"])
171 shape = element.attrib["shape"]
172 radius = float(element.attrib["radius"])
173 except:
174 raise "FeynML Error: invalid attribute for <blob> element"
175 b = feyn.NamedBlob[shape](x,y,radius)
176 if "style" in element.attrib:
177 b = self.apply_layout(element.attrib["style"],b)
178 if "label" in element.attrib:
179 b = b.strokestyle(feyn.FreeTeXLabel(element.attrib["label"],x,y))
180 try:
181 thedict[element.attrib["id"]] = b
182 except:
183 raise "FeynML Error: missing id attribute in <blob> element"
184 return b
185
187 """Build a blob's connect-point from its FeynML representation."""
188 try:
189 parent = thedict[element.attrib["blob"]]
190 direction = element.attrib["dir"]
191 except:
192 raise "feynML Error: invalid attribute for <connect> element"
193 try:
194 angle = float(direction) * math.pi/180.
195 except:
196 winds = {"n":90,"s":-90,"e":0,"w":180, "ne":45,"se":-45,"nw":135,"sw":-135}
197 try:
198 angle = winds[direction] * math.pi/180.
199 except:
200 raise "FeynML Error: invalid direction %s"%direction
201 if parent.blobshape == "circle":
202 x = parent.centre.x() + parent.radius*math.cos(angle)
203 y = parent.centre.y() + parent.radius*math.sin(angle)
204 else:
205 raise "*** TODO *** connecting to non-circles not yet implemented !!"
206 p = feyn.Point(x,y)
207 try:
208 thedict[element.attrib["id"]] = p
209 except:
210 raise "FeynML Error: missing id attribute in <connect> element"
211 return p
212
214 """Apply the decorators encoded in a style string to an object."""
215 styleelements = stylestring.split(";")
216 for styling in styleelements:
217 if styling[:10] == "mark-shape" and isinstance(object,feyn.DecoratedPoint):
218 object.mark(feyn.NamedMark[styling[11:]])
219 elif styling[:9] == "mark-size" and isinstance(object,feyn.DecoratedPoint):
220 object.size(float(styling[10:]))
221 else:
222 pass
223 return object
224
225
226
227
228
229
230
231 if __name__=="__main__":
232 import sys
233 reader = FeynMLReader(sys.argv[1])
234 _f = reader.get_diagram(0)
235 _c = pyx.canvas.canvas()
236 _f.draw(_c)
237 c.writeEPSfile(sys.argv[1])
238