Source code for pyfeyn2.render.pyx.pyxrender

import os
from warnings import warn

import pyx
from IPython.display import display
from pyx import *
from wand.image import Image as WImage

# from pyfeyn2.feynmandiagram import Line, Point
from pyfeyn2.render.pyx.deco import Arrow, PointLabel
from pyfeyn2.render.pyx.diagrams import FeynDiagram
from pyfeyn2.render.pyx.lines import Line, NamedLine
from pyfeyn2.render.pyx.points import SQUARE, DecoratedPoint, NamedMark, Point
from pyfeyn2.render.render import Render


[docs]class PyxRender(Render):
[docs] def __init__(self, fd=None, *args, **kwargs): super().__init__(fd, *args, **kwargs)
[docs] def render( self, file=None, show=True, resolution=200, width=None, height=None, clean_up=False, ): delete = False if file is None: file = "tmp.pdf" delete = True pyxfd = FeynDiagram() for v in self.fd.vertices: dp = DecoratedPoint(v.x, v.y) dp = self.apply_layout(self.fd.get_style(v).cssText.replace("\n", " "), dp) if v.label is not None: dp.setFillstyles(PointLabel(dp, v.label, displace=3, angle=90)) pyxfd.add(dp) for l in self.fd.legs: lp = Point(l.x, l.y) lstyle = self.fd.get_style(l) tar = self.fd.get_point(l.target) if lstyle.getProperty("line") is not None: lname = lstyle.getProperty("line").value else: lname = l.type # fallback to type if l.is_incoming(): nl = NamedLine[lname](lp, Point(tar.x, tar.y)) elif l.is_outgoing(): nl = NamedLine[lname](Point(tar.x, tar.y), lp) if lstyle.getProperty("bend") is not None: nl = nl.bend(lstyle.getProperty("bend").value) nl = self.apply_layout(self.fd.get_style(l).cssText.replace("\n", " "), nl) nl = nl.addLabel(l.label) for p in self.fd.propagators: pstyle = self.fd.get_style(p) src = self.fd.get_point(p.source) tar = self.fd.get_point(p.target) if pstyle.getProperty("line") is not None: lname = pstyle.getProperty("line").value else: lname = p.type nl = NamedLine[lname](Point(src.x, src.y), Point(tar.x, tar.y)) if pstyle.getProperty("bend") is not None: nl = nl.bend(pstyle.getProperty("bend").value) nl = self.apply_layout(self.fd.get_style(p).cssText.replace("\n", " "), nl) nl = nl.addLabel(p.label) pyxfd.draw(file) # print("Drawing to %s" % file) wi = WImage(filename=file, resolution=resolution, width=width, height=height) if delete: os.remove(file) if show: display(wi) if clean_up: # TODO: clean up pass return wi
[docs] def apply_layout(self, stylestring, obj): """Apply the decorators encoded in a style string to an object.""" if stylestring is None: return obj styleelements = stylestring.split(";") styledict = {} for styling in styleelements: if styling == "": break s = styling.split(":") styledict[s[0].lstrip().rstrip()] = s[1] if "fill-style" in styledict: filltype = styledict["fill-style"].split() if filltype[0] == "solid": R, G, B = [ int("0x" + x, base=16) / 255.0 # eval("0x%s" % x) / 255.0 # <- old code for x in [filltype[1][n : n + 2] for n in (1, 3, 5)] ] obj.fillstyles = [pyx.color.rgb(R, G, B)] elif filltype[0] == "hatched": D, A = float(filltype[1]), int(filltype[2]) obj.fillstyles = [pyx.pattern.hatched(D, A)] elif filltype[0] == "crosshatched": D, A = float(filltype[1]), int(filltype[2]) obj.fillstyles = [pyx.pattern.crosshatched(D, A)] if ("mark-shape" in styledict or "mark-size" in styledict) and isinstance( obj, DecoratedPoint ): try: marktype = NamedMark[styledict["mark-shape"]] except Exception: marktype = SQUARE try: marksize = float(styledict["mark-size"]) except Exception: marksize = 0.075 obj.setMark(marktype(size=marksize)) if ( "arrow-size" in styledict or "arrow-angle" in styledict or "arrow-constrict" in styledict or "arrow-pos" in styledict or "arrow-sense" in styledict or "arrow-displace" in styledict ) and isinstance(obj, Line): try: arrsize = pyx.unit.length(float(styledict["arrow-size"]), unit="cm") except Exception: arrsize = 6 * pyx.unit.v_pt try: arrangle = float(styledict["arrow-angle"]) except Exception: arrangle = 45 try: arrconstrict = float(styledict["arrow-constrict"]) except Exception: arrconstrict = 0.8 try: arrpos = float(styledict["arrow-pos"]) except Exception: arrpos = 0.5 try: arrsense = float(styledict["arrow-sense"]) except Exception: arrsense = 1 if arrsense == 1 or arrsense == -1: obj.addArrow( arrow=Arrow(arrpos, arrsize, arrangle, arrconstrict, arrsense) ) elif arrsense == 0: # no arrow pass else: warn("arrow-sense must be 1, -1 or 0 (no arrow).") # obj.addArrow(arrow=Arrow(arrpos, arrsize, arrangle, arrconstrict, arrsense)) if ( "momentum-arrow" in styledict or "momentum-arrow-sense" in styledict or "parallel-arrow-size" in styledict or "parallel-arrow-angle" in styledict or "parallel-arrow-constrict" in styledict or "parallel-arrow-pos" in styledict or "parallel-arrow-length" in styledict or "parallel-arrow-displace" in styledict or "parallel-arrow-sense" in styledict ) and isinstance(obj, Line): try: arrsize = pyx.unit.length( float(styledict["parallel-arrow-size"]), unit="cm" ) except Exception: arrsize = 6 * pyx.unit.v_pt try: arrangle = float(styledict["parallel-arrow-angle"]) except Exception: arrangle = 45 try: arrconstrict = float(styledict["parallel-arrow-constrict"]) except Exception: arrconstrict = 0.8 try: arrpos = float(styledict["parallel-arrow-pos"]) except Exception: arrpos = 0.5 try: arrlen = float(styledict["parallel-arrow-length"]) except Exception: arrlen = 0.5 * pyx.unit.v_cm try: arrdisp = float(styledict["parallel-arrow-displace"]) except Exception: arrdisp = 0.3 try: arrsense = int(styledict["momentum-arrow-sense"]) except Exception: arrsense = +1 try: arrsense = int(styledict["parallel-arrow-sense"]) except Exception: arrsense = +1 if arrsense == 1 or arrsense == -1: obj.addParallelArrow( arrpos, arrdisp, arrlen, arrsize, arrangle, arrconstrict, arrsense ) elif arrsense == 0: # no arrow pass else: warn("momentum-arrow-sense must be 1, -1 or 0 (no arrow).") if "is3d" in styledict and isinstance(obj, Line): fwords = ["0", "no", "false", "f", "off"] twords = ["1", "yes", "true", "t", "on"] if styledict["is3d"].lstrip().lower() in fwords: obj.set3D(False) elif styledict["is3d"].lstrip().lower() in twords: obj.set3D(True) return obj
@classmethod def valid_types(cls): return super().valid_types() + list(NamedLine.keys()) @classmethod def valid_attributes(cls): return super().valid_attributes() + [ "style", "type", "label", "x", "y", ] @classmethod def valid_styles(cls): return super().valid_styles() + [ "line", "bend", "arrow-pos", "arrow-sense", "arrow-size", "arrow-angle", "arrow-constrict", ]