Page MenuHomeHEPForge

No OneTemporary

Index: pyfeyn/trunk/ChangeLog
===================================================================
--- pyfeyn/trunk/ChangeLog (revision 1908)
+++ pyfeyn/trunk/ChangeLog (revision 1909)
@@ -1,232 +1,234 @@
2007-05-16 Georg von Hippel <gmv22@cantab.net>
* Added support for further styling (arrows, labels) to FeynML module.
* Added leg sense (in/out, antiparticle) attribute to FeynML schema,
and corresponding support to FeynML module.
+ * Added FreeArrow and ParallelArrow classes for free-standing and
+ line-parallel arrows in diagrams.
2007-05-15 Georg von Hippel <gmv22@cantab.net>
* Improved FeynML writer so as to actually write to an XML file.
2007-05-13 Andy Buckley <andy@insectnation.org>
* paint.py: now colours, patterns and line thicknesses are defined here
as upper-case constants (via import from PyX). The import * has been removed.
The examples have been updated to match.
2007-05-02 Georg von Hippel <gmv22@cantab.net>
* Added code to FeynML writer to combine dangling vertices and lines
into external legs. Works only for diagrams where all internal
vertices have been connected properly (unlike the Drell-Yan example)
2007-05-01 Georg von Hippel <gmv22@cantab.net>
* Added support for free labels to FeynML module.
2007-05-01 Andy Buckley <andy@insectnation.org>
* Added 3D deformations to the SUSY and graviton lines. Again, they're
time-consuming to render, but they look pretty.
* Points are now drawn by definition after lines (well, there's a
layer offset of 1000, which should be enough).
2007-04-26 Andy Buckley <andy@insectnation.org>
* Added silly example using multiple canvases and transparency.
* Added a 3D version of the gluon line (can be time-consuming).
2007-04-25 Andy Buckley <andy@insectnation.org>
* Added frequency, amplitude and "extra (half) cycles" methods to
decorated lines.
* Now using copy when assigning a mark constant to a DecoratedPoint.
* Cleaned up the code a bit based on output from pylint.
2007-04-24 Georg von Hippel <gmv22@cantab.net>
* Repaired FeynML support broken by Andy's recent changes.
2007-04-24 Andy Buckley <andy@insectnation.org>
* Added graviton and SUSY lines - rather silly but hey...
2007-04-23 Andy Buckley <andy@insectnation.org>
* Added speculative MultiLine and test #5. Very alpha and ropey.
* Replaced the NamedMark lookup with mark classes and module
constants for the defaults. Might reinstate the size attr on the
DecoratedPoint.
2007-04-03 Georg von Hippel <gmv22@cantab.net>
* Added label support for blobs.
* Further repairs to the FeynML module.
2007-03-28 Georg von Hippel <gmv22@cantab.net>
* Started to repair the FeynML module
* Fixed a bug in lines.py (never use == or != with None, use is/is not
instead).
2007-03-18 Andy Buckley <andy@insectnation.org>
* Added layer-based sorting of the object list before drawing, and
a get/setDepth() method via the Visible interface.
* Tidied up a bit: in particular, removed a mutual dependence bug
between the deco and points modules.
2007-03-07 Andy Buckley <andy@insectnation.org>
* Added point-attached labels.
* Added unattached label implementation and updated example 1 to
demonstrate it.
2007-03-05 Andy Buckley <andy@insectnation.org>
* Moved Label to LineLabel and introduced placeholders for Label
and PointLabel.
2007-02-09 Andy Buckley <andy@insectnation.org>
* Added Vector and Scalar/Higgs line types.
2006-12-29 Andy Buckley <andy@insectnation.org>
* Added a fix to the Point.arc method to deal with the sign
ambiguity when the end points are purely vertically separated.
2006-12-23 Andy Buckley <andy@insectnation.org>
* Added distutils setup.py installation script.
* Moved various files into pyfeyn modules, examples and tests
directories.
* Rehacked the module import structure a bit more to get epydoc to
treat the modules as public (as it should).
2006-12-22 Andy Buckley <andy@insectnation.org>
* Removed feyn module and added initialisation stuff to
__init__.py
2006-12-21 Andy Buckley <andy@insectnation.org>
* Made logo.
* Added 4x scaling to get output resolution more reasonable.
* Removed explicit units dependencies in the coil deformer and
label displacement code.
2006-12-20 Andy Buckley <andy@insectnation.org>
* Changed number of curves per half-loop to get nicer gluons and
photons.
* Added test1 program (e+ e- -> q q~).
* Various other interface hacks... too many changes this evening
to remember them all!
* Changed bend() to use a displacement which is always on the left
of the line, as viewed from start to end.
* Rewrote labels as the Label class, which computes its offsets
using the normal to the curve at that point.
* Neatened up the point, line and blob interfaces a lot with
additions of get/set/add prefixes in lots of places.
2006-11-24 Andy Buckley <andy@insectnation.org>
* Added Fermion and Vertex as aliases to Line and DecoratedPoint.
* Made visible objects add themselves to the current diagram.
* Made fd.draw() take a filename argument: PyX canvases are now
hidden from the user.
* Added get/set/add methods to Lines for labels and arrows, so
that the Element.style([...]) methods don't need to be exposed to
the user.
* Fixed tadpole loop "visible path" interpretation: more complex
than the usual case because the line gets split twice.
2006-10-13 Andy Buckley <andy@insectnation.org>
* Added command line option handling as class property of
FeynDiagram. -D enables text-based debugging statements, -V
enables visual debugging. Accessed via FeynDiagram.options.
* Made it possible for Blobs to be attached to Points.
* Added "visible line" functionality, so that lines whose ends are
attached to Blobs will only be deformed and drawn for the portion
outside the blobs.
2006-09-25 Andy Buckley <andy@insectnation.org>
* Moved XML functionality out of classes and into an external
module. Currently broken.
2006-06-30 Georg von Hippel <gmv22@cantab.net>, <vonhippg@uregina.ca>
* Added rudimentary style support to feynML read/write functions
* Added label support to feynML read/write functions
* Added a new class for labels attached to points rather than lines
* Improved interface of DecoratedPoint class
2006-06-29 Georg von Hippel <gmv22@cantab.net>, <vonhippg@uregina.ca>
* Improved feynML Schema to look more like proposed
* Corresponding changes to feynML code
* Added bend method to lines (autmoatically finds an arcpoint)
2006-06-28 Georg von Hippel <gmv22@cantab.net>, <vonhippg@uregina.ca>
* Fixed some divide-by-zero bugs in points.py
* Added feynML as a W3C XML Schema
* Added feynML reader support module
* Added rudimentary feynML writing support to feyn submodules
2006-06-22 Georg von Hippel <gmv22@cantab.net>, <vonhippg@uregina.ca>
* Fixed Arrow code to work with PyX 0.9
* Split code into submodules for convenience
* Removed StraightLine class, moved trig. code into Point class
* Added hepnames module
* Added Photon line class
* Added Support for tadpole-type loops into Line class
* Added TexLabel decorator
* Added DecoratedPoint class
2005-09-23 Andy Buckley <andy@insectnation.org>
* Start of ChangeLog. Basic functionality aready exists.
* Added Arrow class, courtest of Andre Wobst.
Index: pyfeyn/trunk/pyfeyn/deco.py
===================================================================
--- pyfeyn/trunk/pyfeyn/deco.py (revision 1908)
+++ pyfeyn/trunk/pyfeyn/deco.py (revision 1909)
@@ -1,168 +1,267 @@
"""A couple of classes for decorating diagram elements."""
import pyx, math
from pyfeyn.diagrams import FeynDiagram
from pyfeyn.utils import Visible
## Arrow decorator class
class Arrow(pyx.deco.deco, pyx.attr.attr):
"""Arrow for Feynman diagram lines"""
def __init__(self, pos=0.5, size=6*pyx.unit.v_pt,
angle=45, constriction=0.8):
self.pos = pos
self.size = size
self.angle = angle
self.constriction = constriction
def decorate(self, dp, texrunner):
"""Attach arrow to a path (usually a line)."""
dp.ensurenormpath()
constrictionlen = self.size * self.constriction * \
math.cos(self.angle*math.pi/360.0)
arrowtopos = self.pos * dp.path.arclen()+0.5*self.size
arrowtopath = dp.path.split(arrowtopos)[0]
arrowpath = pyx.deco._arrowhead(arrowtopath, self.pos*dp.path.arclen(),
1, self.size, 45, constrictionlen)
dp.ornaments.fill(arrowpath)
return dp
+class FreeArrow(Visible):
+ """Arrow not attached to any line in a diagram."""
+ def __init__(self, length=0.5*pyx.unit.v_cm, size=6*pyx.unit.v_pt,
+ angle=45, constriction=0.8, pos=None, x=None, y=None,
+ direction=0):
+ self.x, self.y = 0, 0
+ if x is not None:
+ self.x = x
+ if y is not None:
+ self.y = y
+ if pos is not None:
+ self.x, self.y = pos.getXY()
+ self.direction = direction
+ self.length = length
+ self.size = size
+ self.angle = angle
+ self.constriction = constriction
+ ## Add this to the current diagram automatically
+ FeynDiagram.currentDiagram.add(self)
+
+ def draw(self, canvas):
+ """Draw this arrow on the supplied canvas."""
+ endx, endy = self.x-self.length*math.sin(self.direction*math.pi/180.), \
+ self.y-self.length*math.cos(self.direction*math.pi/180.)
+ linepath = pyx.deco.decoratedpath(
+ pyx.path.path(pyx.path.moveto(endx,endy),
+ pyx.path.lineto(self.x,self.y)))
+ styles = [Arrow(pos=1.0, size=self.size, angle=self.angle,
+ constriction=self.constriction)]
+ canvas.stroke(linepath.path,styles)
+
+
+class ParallelArrow(Visible):
+ """Arrow running parallel to a line, for momenta, helicities etc."""
+ def __init__(self, line, pos=0.5, displace=0.3, length=0.5*pyx.unit.v_cm,
+ size=6*pyx.unit.v_pt, angle=45, constriction=0.8, sense=+1):
+ self.line = line
+ self.pos = pos
+ self.displace = pyx.unit.length(displace)
+ self.length = length
+ self.size = size
+ self.angle = angle
+ self.constriction = constriction
+ self.sense = sense
+
+ def draw(self, canvas):
+ """Draw this arrow on the supplied canvas."""
+ p = self.line.getPath()
+ posparam = p.begin() + self.pos * p.arclen()
+ x, y = self.line.fracpoint(self.pos).getXY()
+ arrx, arry = self.line.fracpoint(self.pos+self.length/2./p.arclen()).getXY()
+ endx, endy = self.line.fracpoint(self.pos-self.length/2./p.arclen()).getXY()
+
+ ## Calculate the displacement from the line
+ displacement = self.displace
+ intrinsicwidth = pyx.unit.length(0.1)
+ if hasattr(self.line, "arcradius"):
+ intrinsicwidth = self.line.arcradius
+ if displacement > 0:
+ displacement += intrinsicwidth
+ else:
+ displacement -= intrinsicwidth
+ if FeynDiagram.options.DEBUG:
+ print "Displacement = ", displacement
+
+ ## Position the arrow on the right hand side of lines
+ tangent = p.tangent(posparam, displacement)
+ normal = tangent.transformed(pyx.trafo.rotate(90, x, y))
+ nx, ny = normal.atend()
+ nxcm, nycm = pyx.unit.tocm(nx - x), pyx.unit.tocm(ny - y)
+ vx, vy = p.atbegin()
+ vxcm, vycm = pyx.unit.tocm(x - vx), pyx.unit.tocm(y - vy)
+
+ ## If the arrow is on the left, flip it by 180 degrees
+ if (vxcm * nycm - vycm * nxcm) > 0:
+ normal = normal.transformed(pyx.trafo.rotate(180, x, y))
+ nx, ny = normal.atend()
+ if displacement < 0:
+ normal = normal.transformed(pyx.trafo.rotate(180, x, y))
+ nx, ny = normal.atend()
+ if FeynDiagram.options.VDEBUG:
+ FeynDiagram.currentCanvas.stroke(normal)
+
+ ## Displace the arrow by this normal vector
+ endx, endy = endx + (nx-x), endy + (ny-y)
+ arrx, arry = arrx + (nx-x), arry + (ny-y)
+
+ if self.sense<0.:
+ arrx, arry, endx, endy = endx, endy, arrx, arry
+
+ linepath = pyx.deco.decoratedpath(
+ pyx.path.path(pyx.path.moveto(endx,endy),
+ pyx.path.lineto(arrx,arry)))
+ styles = [Arrow(pos=1.0, size=self.size, angle=self.angle,
+ constriction=self.constriction)]
+ canvas.stroke(linepath.path,styles)
+
+
+
## Label
class Label(Visible):
"""General label, unattached to any diagram elements"""
def __init__(self, text, pos=None, x=None, y=None):
self.x, self.y = 0, 0
if x is not None:
self.x = x
if y is not None:
self.y = y
self.size = pyx.text.size.normalsize
self.text = text
self.textattrs = []
self.pos = pos
## Add this to the current diagram automatically
FeynDiagram.currentDiagram.add(self)
def draw(self, canvas):
"""Draw this label on the supplied canvas."""
textattrs = pyx.attr.mergeattrs([pyx.text.halign.center,
pyx.text.vshift.mathaxis,
self.size] + self.textattrs)
t = pyx.text.defaulttexrunner.text(self.x, self.y, self.text, textattrs)
canvas.insert(t)
## PointLabel
class PointLabel(Label):
"""Label attached to points on the diagram"""
def __init__(self, point, text, displace=0.3, angle=0):
self.size = pyx.text.size.normalsize
self.displace = pyx.unit.length(displace)
self.angle = angle
self.text = text
self.point = point
self.textattrs = []
def getPoint(self):
"""Get the point associated with this label."""
return self.point
def setPoint(self, point):
"""Set the point associated with this label."""
self.point = point
return self
def draw(self, canvas):
"""Draw this label on the supplied canvas."""
if FeynDiagram.options.VDEBUG:
canvas.fill(pyx.path.circle(self.point.getX(),
self.point.getY(), 0.05), [pyx.color.rgb.green])
x = self.point.getX() + self.displace * math.cos(math.radians(self.angle))
y = self.point.getY() + self.displace * math.sin(math.radians(self.angle))
textattrs = pyx.attr.mergeattrs([pyx.text.halign.center,
pyx.text.vshift.mathaxis,
self.size] + self.textattrs)
t = pyx.text.defaulttexrunner.text(x, y, self.text, textattrs)
canvas.insert(t)
## LineLabel
class LineLabel(Label):
"""Label for Feynman diagram lines"""
def __init__(self, line, text, pos=0.5, displace=0.3, angle=0):
self.pos = pos
self.size = pyx.text.size.normalsize
self.displace = pyx.unit.length(displace)
self.angle = angle
self.text = text
self.line = line
self.textattrs = []
def getLine(self):
"""Get the associated line."""
return self.line
def setLine(self, line):
"""Set the associated line."""
self.line = line
return self
def draw(self, canvas):
"""Draw this label on the supplied canvas."""
p = self.line.getPath()
#x, y = self.line.fracPoint(self.pos).getXY()
posparam = p.begin() + self.pos * p.arclen()
x, y = p.at(posparam)
## Calculate the displacement from the line
displacement = self.displace
intrinsicwidth = pyx.unit.length(0.1)
if hasattr(self.line, "arcradius"):
intrinsicwidth = self.line.arcradius
if displacement > 0:
displacement += intrinsicwidth
else:
displacement -= intrinsicwidth
if FeynDiagram.options.DEBUG:
print "Displacement = ", displacement
## Position the label on the right hand side of lines
tangent = p.tangent(posparam, displacement)
normal = tangent.transformed(pyx.trafo.rotate(90, x, y))
nx, ny = normal.atend()
nxcm, nycm = pyx.unit.tocm(nx - x), pyx.unit.tocm(ny - y)
vx, vy = p.atbegin()
vxcm, vycm = pyx.unit.tocm(x - vx), pyx.unit.tocm(y - vy)
## If the label is on the left, flip it by 180 degrees
if (vxcm * nycm - vycm * nxcm) > 0:
normal = normal.transformed(pyx.trafo.rotate(180, x, y))
nx, ny = normal.atend()
if displacement < 0:
normal = normal.transformed(pyx.trafo.rotate(180, x, y))
nx, ny = normal.atend()
if FeynDiagram.options.VDEBUG:
FeynDiagram.currentCanvas.stroke(normal)
## Displace the label by this normal vector
x, y = nx, ny
textattrs = pyx.attr.mergeattrs([pyx.text.halign.center,
pyx.text.vshift.mathaxis,
self.size] + self.textattrs)
t = pyx.text.defaulttexrunner.text(x, y, self.text, textattrs)
#t.linealign(self.displace,
# math.cos(self.angle * math.pi/180),
# math.sin(self.angle * math.pi/180))
canvas.insert(t)
Index: pyfeyn/trunk/pyfeyn/lines.py
===================================================================
--- pyfeyn/trunk/pyfeyn/lines.py (revision 1908)
+++ pyfeyn/trunk/pyfeyn/lines.py (revision 1909)
@@ -1,767 +1,775 @@
"""Various particle line types."""
import pyx, math
from pyx import color
from pyfeyn.diagrams import FeynDiagram
from pyfeyn.points import Point
-from pyfeyn.deco import Arrow, LineLabel
+from pyfeyn.deco import Arrow, ParallelArrow, LineLabel
from pyfeyn.utils import Visible, defunit
## Line base class
class Line(Visible):
"Base class for all objects which connect points in Feynman diagrams"
def __init__(self, point1, point2):
self.p1 = point1
self.p2 = point2
self.styles = []
self.arcthrupoint = None
self.is3D = False
self.arrows = []
self.labels = []
## Add this to the current diagram automatically
FeynDiagram.currentDiagram.add(self)
def addLabel(self, text, pos=0.5, displace=-0.25, angle = 0):
"""Add a LaTeX label to this line, either via parameters or actually as
a TeXLable object."""
if FeynDiagram.options.DEBUG:
print "Adding label: " + text
#if text.__class__ == "Label":
# self.labels.append(label)
#else:
self.labels.append(LineLabel(text=text, line=self, pos=pos, displace=displace, angle=angle))
if FeynDiagram.options.DEBUG:
print "Labels = " + str(self.labels)
return self
+ def addParallelArrow(self, pos=0.5, displace=0.3, length=0.5*pyx.unit.v_cm,
+ size=6*pyx.unit.v_pt, angle=45, constriction=0.8, sense=+1):
+ self.labels.append(ParallelArrow(self, pos=pos, displace=displace,
+ length=length, size=size, angle=angle,
+ constriction=constriction,
+ sense=sense))
+ return self
+
def removeLabels(self):
"""Remove the labels from this line."""
self.labels = []
return self
def fracpoint(self, frac):
"""
Get a new Point representing the point at the given fraction along
the fundamental line (i.e. no truncation or deformation).
TODO: Handle units properly.
"""
p = self.getPath() ## no truncation or deformation
x, y = p.at(p.begin() + frac * p.arclen())
return Point(x/defunit, y/defunit)
def setArrows(self, arrows):
"""Define the arrows on this line."""
## TODO: Check that the arg is a list
self.arrows = []
for i in arrows:
if i.__class__ == "deco.Arrow":
self.arrows.append(i)
else:
self.arrows.append(Arrow(pos = i))
return self
def addArrow(self, position = 0.53, arrow = None):
"""Add an arrow to the line at the specified position, which is a number
between 0 and 1, representing the fraction along the line at which the
arrow should be placed. The default arrow style can be overridden by
explicitly supplying an arrow object as the 'arrow' argument, in which
case the position argument will be ignored."""
if arrow:
self.arrows.append(arrow)
else:
self.arrows.append(Arrow(pos=position))
return self
def removeArrows(self):
"""Remove all arrows from this line."""
self.arrows = []
return self
def arcThru(self, arcpoint = None, x = None, y = None):
"""Set the point through which this line will arc. Either pass a Point
or set x, y as floats."""
if arcpoint is not None:
self.arcthrupoint = arcpoint
elif x is not None and y is not None:
self.arcthrupoint = Point(x, y)
else:
raise Exception("Tried to set an arcpoint with invalid arguments")
return self
def straighten(self):
"""Make this line a straight line between start and end."""
self.arcthrupoint = None
def bend(self, amount):
"""Bend the line to the right by a given distance."""
middle = self.p1.midpoint(self.p2)
nx = (middle.y() - self.p1.y()) / abs(self.p1.distance(middle))
ny = (self.p1.x() - middle.x()) / abs(self.p1.distance(middle))
vx = middle.x() - self.p1.x()
vy = middle.y() - self.p1.y()
if (vx * ny - vy * nx) > 0:
nx *= -1
ny *= -1
arcpoint = Point(middle.x() + amount * nx, middle.y() + amount * ny)
if FeynDiagram.options.VDEBUG:
FeynDiagram.currentCanvas.stroke(
pyx.path.line(middle.x(), middle.y(), arcpoint.x(),
arcpoint.y()), [color.rgb.blue] )
self.arcThru(arcpoint)
if FeynDiagram.options.DEBUG:
print self.getVisiblePath()
if FeynDiagram.options.VDEBUG:
FeynDiagram.currentCanvas.stroke(self.getVisiblePath(), [color.rgb.blue])
return self
def set3D(self, choice):
"""Make this line display in '3D'."""
self.is3D = choice
return self
def getStyles(self, stylelist):
"""Get the styles associated with this line."""
return self.styles
def setStyles(self, stylelist):
"""Set the styles associated with this line."""
self.styles = stylelist
return self
def addStyle(self, style):
"""Add a style to this line."""
self.styles.append(style)
return self
def addStyles(self, stylelist):
"""Add some styles to this line."""
self.styles = self.styles + stylelist
return self
def getPath(self):
"""Get the path taken by this line."""
if self.arcthrupoint is None:
## This is a simple straight line
return pyx.path.path( pyx.path.moveto( *(self.p1.getXY()) ),
pyx.path.lineto( *(self.p2.getXY()) ) )
elif (self.p1.x() == self.p2.x() and self.p1.y() == self.p2.y()):
## This is a tadpole-type loop and needs special care;
## We shall assume that the arcthrupoint is meant to be
## the antipode of the basepoint
arccenter = self.p1.midpoint(self.arcthrupoint)
arcradius = self.p1.distance(self.arcthrupoint) / 2.0
## TODO Why does a circle work and an arc doesn't?
cargs = (arccenter.x(), arccenter.y(), arcradius)
circle = pyx.path.circle(*cargs)
line = pyx.path.line( self.p1.x(), self.p1.y(), arccenter.x(), arccenter.y())
if FeynDiagram.options.VDEBUG:
FeynDiagram.currentCanvas.stroke(line, [color.rgb.green])
as, bs = circle.intersect(line)
subpaths = circle.split(as[0])
cpath = subpaths[0]
return cpath
## or, with an arc...
arcangle1 = arccenter.arg(self.p1)
arcangle2 = arccenter.arg(self.p1) + 360
arcargs = (arccenter.x(), arccenter.y(), arcradius, arcangle1, arcangle2)
return pyx.path.path( pyx.path.arc(*arcargs) )
else:
n13, n23 = None, None
## Work out line gradients
try:
n13 = (self.p1.y() - self.arcthrupoint.y()) / (self.p1.x() - self.arcthrupoint.x())
except ZeroDivisionError:
if FeynDiagram.options.DEBUG:
print "Grad 1 diverges"
n13 = 1e100
try:
n23 = (self.p2.y() - self.arcthrupoint.y()) / (self.p2.x() - self.arcthrupoint.x())
except ZeroDivisionError:
if FeynDiagram.options.DEBUG:
print "Grad 2 diverges"
n23 = 1e100
## If gradients match,
## then we have a straight line, so bypass the complexity
if n13 == n23:
return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())),
pyx.path.lineto(*(self.p2.getXY())) )
## Otherwise work out conjugate gradients and midpoints
m13, m23 = None, None
try:
m13 = -1.0 / n13
except ZeroDivisionError:
m13 = 1e100
try:
m23 = -1.0 / n23
except ZeroDivisionError:
m23 = 1e100
mid13 = self.p1.midpoint(self.arcthrupoint)
mid23 = self.p2.midpoint(self.arcthrupoint)
## Line y-intercepts
c13 = mid13.y() - m13 * mid13.x()
c23 = mid23.y() - m23 * mid23.x()
## Find the centre of the arc
xcenter = - (c23 - c13) / (m23 - m13)
ycenter = m13 * xcenter + c13
arccenter = Point(xcenter, ycenter)
## Get the angles required for drawing the arc
arcradius = arccenter.distance(self.arcthrupoint)
arcangle1 = arccenter.arg(self.p1)
arcangle2 = arccenter.arg(self.p2)
arcangle3 = arccenter.arg(self.arcthrupoint)
arcargs = (arccenter.x(), arccenter.y(), arcradius, arcangle1, arcangle2)
if FeynDiagram.options.DEBUG and arcangle1 == arcangle2:
print "Arc angles are the same - not drawing anything"
## Calculate cross product to determine direction of arc
vec12 = [self.p2.x()-self.p1.x(), self.p2.y()-self.p1.y(), 0.0]
vec13 = [self.arcthrupoint.x()-self.p1.x(), self.arcthrupoint.y()-self.p1.y(), 0.0]
crossproductZcoord = vec12[0]*vec13[1] - vec12[1]*vec13[0]
if crossproductZcoord < 0:
return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())),
pyx.path.arc(*arcargs))
else:
return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())),
pyx.path.arcn(*arcargs))
def getVisiblePath(self):
"""Find the subpath between the endpoints which isn't overshadowed by a blob of some kind"""
p1path = self.p1.getPath()
p2path = self.p2.getPath()
vispath = self.getPath()
if FeynDiagram.options.VDEBUG:
FeynDiagram.currentCanvas.stroke(vispath, [color.rgb.green])
if p1path:
as, bs = p1path.intersect(vispath)
for b in bs:
subpaths = vispath.split(b)
if len(subpaths) > 1:
if FeynDiagram.options.DEBUG:
print "Num subpaths 1 = %d" % len(subpaths)
subpaths.sort(
lambda x, y :
int(pyx.unit.tocm(x.arclen() - y.arclen()) /
math.fabs(pyx.unit.tocm(x.arclen() - y.arclen()))) )
vispath = subpaths[-1]
if FeynDiagram.options.VDEBUG:
FeynDiagram.currentCanvas.stroke(subpaths[0], [color.rgb.blue])
if FeynDiagram.options.VDEBUG:
for a in as:
ix, iy = p1path.at(a)
FeynDiagram.currentCanvas.fill(pyx.path.circle(ix, iy, 0.05),
[color.rgb.green])
if p2path:
as, bs = p2path.intersect(vispath)
for b in bs:
subpaths = vispath.split(b)
if len(subpaths) > 1:
if FeynDiagram.options.DEBUG:
print "Num subpaths 2 = %d" % len(subpaths)
subpaths.sort(
lambda x, y :
int(pyx.unit.tocm(x.arclen() - y.arclen()) /
math.fabs(pyx.unit.tocm(x.arclen() - y.arclen()))) )
vispath = subpaths[-1]
if FeynDiagram.options.VDEBUG:
FeynDiagram.currentCanvas.stroke(subpaths[0], [color.rgb.red])
if FeynDiagram.options.VDEBUG:
for a in as:
ix, iy = p2path.at(a)
FeynDiagram.currentCanvas.fill(pyx.path.circle(ix, iy, 0.05),
[color.rgb.blue])
if FeynDiagram.options.VDEBUG:
FeynDiagram.currentCanvas.stroke(vispath, [color.rgb.red])
#return pyx.path.circle(-2,-1,0.2)
return vispath
def draw(self, canvas):
"""Drwa this line on the given canvas."""
path = self.getVisiblePath()
styles = self.styles + self.arrows
if FeynDiagram.options.DEBUG:
print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
print path
canvas.stroke(path, styles)
for l in self.labels:
l.draw(canvas)
## Fermion is an alias for Line
Fermion = Line
class MultiLine(Line):
"""A class for drawing multiple parallel straight lines."""
def draw(self, canvas):
"""Draw this multiline on the supplied canvas."""
dist = 0.2
n = 5
path = pyx.deformer.parallel(-n/2.0 * dist).deform(self.getPath())
paths = [path]
defo = pyx.deformer.parallel(dist)
for m in range(0, n):
path = defo.deform(path)
paths.append(path)
styles = self.styles + self.arrows
for p in paths:
canvas.stroke(p, styles)
class Scalar(Line):
"""A scalar particle line, like a Higgs boson."""
def draw(self, canvas):
"""Draw this scalar line on the given canvas."""
path = self.getVisiblePath()
styles = self.styles + [pyx.style.linestyle.dashed] + self.arrows
## TODO: call base class method?
if FeynDiagram.options.DEBUG:
print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
print path
canvas.stroke(path, styles)
for l in self.labels:
l.draw(canvas)
## Higgs is an alias for Scalar
Higgs = Scalar
## Sfermion is also an alias for Scalar
Sfermion = Scalar
## DecoratedLine base class
class DecoratedLine(Line):
"""Base class for spring and sine-like lines"""
def invert(self):
"""Reflect the line decoration about the line."""
pass
def getNumHalfCycles(self):
"""Get the number of half cycles in this line."""
pass
def getDeformedPath(self):
"""Get the deformed path."""
return getVisiblePath()
class Gluon(DecoratedLine):
"""A line with a cycloid deformation"""
def __init__(self, point1, point2):
self.p1 = point1
self.p2 = point2
self.styles = []
self.arcthrupoint = None
self.is3D = False
self.skipsize3D = pyx.unit.length(0.04)
self.parity3D = 0
self.arrows = []
self.labels = []
self.arcradius = pyx.unit.length(0.25)
self.frequency = 1.3
self.extras = 0
self.inverted = False
self.linetype = "gluon"
## Add this to the current diagram automatically
FeynDiagram.currentDiagram.add(self)
def set3D(self, is3D=True, skipsize=pyx.unit.length(0.04), parity=0):
self.is3D = is3D
self.skipsize3D = skipsize
self.parity3D = parity
return self
def invert(self):
"""Flip the line decoration around the line."""
self.inverted = not self.inverted
return self
def getFrequency(self):
"""Get the rate of occurence of the coil decoration."""
return self.frequency
def setFrequency(self, freq):
"""Set the rate of occurence of the coil decoration."""
self.frequency = freq
return self
def getAmplitude(self):
"""Get the radius of the coil decoration."""
return self.arcradius
def setAmplitude(self, amplitude):
"""Set the radius of the coil decoration."""
self.arcradius = amplitude
return self
def setExtraCycles(self, extras):
"""Add some extra (possibly negative) oscillations to the coil decoration."""
self.extras = extras
return self
def getDeformedPath(self):
"""Get the path modified by the coil warping."""
needwindings = self.frequency * \
pyx.unit.tocm(self.getVisiblePath().arclen()) / \
pyx.unit.tocm(self.arcradius)
## Get the whole number of windings and make sure that it's odd so we
## don't get a weird double-back thing
intwindings = int(needwindings)
intwindings += 2 * self.extras
if intwindings % 2 == 0:
intwindings -= 1
deficit = needwindings - intwindings
sign = 1
if self.inverted: sign = -1
defo = pyx.deformer.cycloid(self.arcradius, intwindings, curvesperhloop=10,
skipfirst = 0.0, skiplast = 0.0, sign = sign)
return defo.deform(self.getVisiblePath())
def draw(self, canvas):
"""Draw the line on the supplied canvas."""
styles = self.styles + self.arrows
if FeynDiagram.options.DEBUG:
print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
mypath = self.getDeformedPath()
if not self.is3D:
canvas.stroke(mypath, styles)
else:
para = pyx.deformer.parallel(0.001)
as, bs, cs = para.normpath_selfintersections(mypath.normpath(), epsilon=0.01)
coil_params = []
for b in bs:
coil_params.append(b[self.parity3D] - self.skipsize3D)
coil_params.append(b[self.parity3D] + self.skipsize3D)
pathbits = mypath.split(coil_params)
on = True
for pathbit in pathbits:
if on:
canvas.stroke(pathbit, styles)
on = not on
## Labels
for l in self.labels:
l.draw(canvas)
class Vector(DecoratedLine):
"""A line with a sinoid deformation"""
def __init__(self, point1, point2, amplitude=0.25, frequency=1.0):
self.p1 = point1
self.p2 = point2
self.styles = []
self.arcthrupoint = None
self.is3D = False
self.arrows = []
self.labels = []
self.inverted = False
self.arcradius = amplitude #pyx.unit.length(0.25)
self.linetype = "photon"
self.frequency = frequency
self.extrahalfs = 0
## Add this to the current diagram automatically
FeynDiagram.currentDiagram.add(self)
def invert(self):
"""Reflect the decoration in the line itself."""
self.inverted = not self.inverted
return self
def getFrequency(self):
"""Get the rate of occurance of the oscillation."""
return self.frequency
def setFrequency(self, freq):
"""Set the rate of occurance of the oscillation."""
self.frequency = freq
return self
def getAmplitude(self):
"""Get the size of the oscillation."""
return self.arcradius
def setAmplitude(self, amplitude):
"""Set the size of the oscillation."""
self.arcradius = amplitude
return self
def setExtraHalfCycles(self, extras):
"""Add some extra half cycles to the oscillation on top of those
determined from the frequency."""
self.extrahalfs = extras
return self
def getDeformedPath(self):
"""Get the path with the decorative deformation."""
intwindings = int(self.frequency * pyx.unit.tocm(self.getVisiblePath().arclen()) /
pyx.unit.tocm(self.arcradius))
intwindings += self.extrahalfs
sign = 1
if self.inverted: sign = -1
defo = pyx.deformer.cycloid(self.arcradius, intwindings, curvesperhloop=5,
skipfirst=0.0, skiplast=0.0, turnangle=0, sign=sign)
return defo.deform(self.getVisiblePath())
def draw(self, canvas):
"""Draw the line on the supplied canvas."""
styles = self.styles + self.arrows
if FeynDiagram.options.DEBUG:
print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
canvas.stroke(self.getDeformedPath(), styles)
for l in self.labels:
l.draw(canvas)
## Photon is an alias for Vector
Photon = Vector
class Graviton(DecoratedLine):
"""A line with a double sinoid deformation"""
def __init__(self, point1, point2):
self.p1 = point1
self.p2 = point2
self.styles = []
self.arcthrupoint = None
self.is3D = False
self.skipsize3D = pyx.unit.length(0.04)
self.parity3D = 0
self.inverted = False
self.arrows = []
self.labels = []
self.arcradius = pyx.unit.length(0.25)
self.linetype = "graviton"
## Add this to the current diagram automatically
FeynDiagram.currentDiagram.add(self)
def set3D(self, is3D=True, skipsize=pyx.unit.length(0.04), parity=0):
self.is3D = is3D
self.skipsize3D = skipsize
self.parity3D = parity
return self
def invert(self):
"""Reflect the decoration in the line itself."""
self.inverted = not self.inverted
return self
def getDeformedPath(self, sign = 1):
"""Get the path with the decorative deformation."""
intwindings = int(0.6 * pyx.unit.tocm(self.getVisiblePath().arclen()) /
pyx.unit.tocm(self.arcradius))
defo = pyx.deformer.cycloid(self.arcradius, intwindings, curvesperhloop=5,
skipfirst=0.0, skiplast=0.0, turnangle=0, sign=sign)
return defo.deform(self.getVisiblePath())
def draw(self, canvas):
"""Draw the line on the supplied canvas."""
styles = self.styles + self.arrows
if FeynDiagram.options.DEBUG:
print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
mypath1 = self.getDeformedPath(+1)
mypath2 = self.getDeformedPath(-1)
if self.inverted:
mypathtmp = mypath1
mypath1 = mypath2
mypath2 = mypathtmp
if not self.is3D:
canvas.stroke(mypath1, styles)
canvas.stroke(mypath2, styles)
else:
as, bs = mypath1.intersect(mypath2)
params1, params2 = [], []
parity1 = True
if self.parity3D == 0:
parity1 = False
for a in as[1:]: ## TODO: better endpoint cut vetoing
if parity1:
params1.append(a - self.skipsize3D)
params1.append(a + self.skipsize3D)
parity1 = not parity1
pathbits1 = mypath1.split(params1)
on = True
for pathbit in pathbits1:
if on:
canvas.stroke(pathbit, styles)
on = not on
parity2 = False
if self.parity3D == 0:
parity2 = True
for b in bs[1:]: ## TODO: better endpoint cut vetoing
if parity2:
params2.append(b - self.skipsize3D)
params2.append(b + self.skipsize3D)
parity2 = not parity2
pathbits2 = mypath2.split(params2)
on = True
for pathbit in pathbits2:
if on:
canvas.stroke(pathbit, styles)
on = not on
for l in self.labels:
l.draw(canvas)
class Gaugino(DecoratedLine):
"""A line with a sinoid deformation and a normal line"""
def __init__(self, point1, point2):
self.p1 = point1
self.p2 = point2
self.styles = []
self.arcthrupoint = None
self.is3D = False
self.skipsize3D = pyx.unit.length(0.04)
self.parity3D = 0
self.inverted = False
self.arrows = []
self.labels = []
self.arcradius = pyx.unit.length(0.25)
self.linetype = "susyboson"
## Add this to the current diagram automatically
FeynDiagram.currentDiagram.add(self)
def set3D(self, is3D=True, skipsize=pyx.unit.length(0.04), parity=0):
self.is3D = is3D
self.skipsize3D = skipsize
self.parity3D = parity
return self
def invert(self):
"""Reflect the decoration in the line itself."""
self.inverted = not self.inverted
return self
def getDeformedPath(self):
"""Get the path with the decorative deformation."""
intwindings = int(pyx.unit.tocm(self.getVisiblePath().arclen()) /
pyx.unit.tocm(self.arcradius))
sign = 1
if self.inverted: sign = -1
defo = pyx.deformer.cycloid(self.arcradius, intwindings, curvesperhloop=5,
skipfirst=0.0, skiplast=0.0, turnangle=0, sign=sign)
return defo.deform(self.getVisiblePath())
def draw(self, canvas):
"""Draw the line on the supplied canvas."""
styles = self.styles + self.arrows
if FeynDiagram.options.DEBUG:
print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
mypath1 = self.getVisiblePath()
mypath2 = self.getDeformedPath()
if not self.is3D:
canvas.stroke(mypath1, styles)
canvas.stroke(mypath2, styles)
else:
as, bs = mypath1.intersect(mypath2)
params1, params2 = [], []
parity1 = True
if self.parity3D == 0:
parity1 = False
for a in as:
if parity1:
params1.append(a - self.skipsize3D)
params1.append(a + self.skipsize3D)
parity1 = not parity1
pathbits1 = mypath1.split(params1)
on = True
for pathbit in pathbits1:
if on:
canvas.stroke(pathbit, styles)
on = not on
parity2 = False
if self.parity3D == 0:
parity2 = True
for b in bs:
if parity2:
params2.append(b - self.skipsize3D)
params2.append(b + self.skipsize3D)
parity2 = not parity2
pathbits2 = mypath2.split(params2)
on = True
for pathbit in pathbits2:
if on:
canvas.stroke(pathbit, styles)
on = not on
for l in self.labels:
l.draw(canvas)
# A dictionary for mapping FeynML line types to line classes
NamedLine = { "higgs" : Higgs,
"photon" : Photon,
"gluon" : Gluon,
"fermion" : Fermion,
"graviton" : Graviton }
Index: pyfeyn/trunk/examples/pyfeyn-test1.py
===================================================================
--- pyfeyn/trunk/examples/pyfeyn-test1.py (revision 1908)
+++ pyfeyn/trunk/examples/pyfeyn-test1.py (revision 1909)
@@ -1,23 +1,23 @@
from pyfeyn import *
from pyfeyn.user import *
fd = FeynDiagram()
in1 = Point(-4, 2)
in2 = Point(-4, -2)
out1 = Point(4, -2)
out2 = Point(4, 2)
in_vtx = Vertex(-2, 0, mark=CIRCLE)
out_vtx = Vertex(2, 0, mark=CIRCLE)
l1 = Label("Drell-Yan QCD vertex correction", x=0, y=2)
fa1 = Fermion(in1, in_vtx).addArrow().addLabel(r"\Pelectron")
-fa2 = Fermion(in_vtx, in2).addArrow().addLabel(r"\Ppositron")
+fa2 = Fermion(in_vtx, in2).addArrow().addLabel(r"\Ppositron").addParallelArrow(size=0.1,displace=-0.05,sense=-1)
bos = Photon(in_vtx, out_vtx).addLabel(r"\Pphoton/\PZ")
-fb1 = Fermion(out1, out_vtx).addArrow(0.2).addLabel(r"\APquark")
+fb1 = Fermion(out1, out_vtx).addArrow(0.2).addLabel(r"\APquark").addParallelArrow(size=0.1,displace=-0.05,sense=-1)
fb2 = Fermion(out_vtx, out2).addArrow(0.8).addLabel(r"\Pquark")
glu = Gluon(midpoint(out_vtx, out1), midpoint(out_vtx, out2)).set3D()
glu.invert().bend(0.5).addLabel("\Pgluon", displace=0.25)
fd.draw("pyfeyn-test1.pdf")

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 6:19 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805563
Default Alt Text
(46 KB)

Event Timeline