14
class UFOError(Exception):
15
"""Exception raised if when inconsistencies are detected in the UFO model."""
18
class UFOBaseClass(object):
19
"""The class from which all FeynRules classes are derived."""
23
def __init__(self, *args, **options):
24
assert(len(self.require_args) == len (args))
26
for i, name in enumerate(self.require_args):
27
setattr(self, name, args[i])
29
for (option, value) in options.items():
30
setattr(self, option, value)
33
return getattr(self, name)
35
def set(self, name, value):
36
setattr(self, name, value)
39
"""Return a dictionary containing all the information of the object"""
45
def nice_string(self):
46
""" return string with the full information """
47
return '\n'.join(['%s \t: %s' %(name, value) for name, value in self.__dict__.items()])
60
for orig,sub in replacements:
61
text = text.replace(orig,sub)
70
class Particle(UFOBaseClass):
71
"""A standard Particle"""
73
require_args=['pdg_code', 'name', 'antiname', 'spin', 'color', 'mass', 'width', 'texname', 'antitexname', 'charge']
75
require_args_all = ['pdg_code', 'name', 'antiname', 'spin', 'color', 'mass', 'width', 'texname', 'antitexname', 'charge', 'loop_particles', 'counterterm','line', 'propagating', 'goldstoneboson']
77
def __init__(self, pdg_code, name, antiname, spin, color, mass, width, texname,
78
antitexname, charge , loop_particles=None, counterterm=None, line=None, propagating=True, goldstoneboson=False, **options):
80
args= (pdg_code, name, antiname, spin, color, mass, width, texname,
81
antitexname, float(charge))
83
UFOBaseClass.__init__(self, *args, **options)
86
all_particles.append(self)
88
self.propagating = propagating
89
self.goldstoneboson= goldstoneboson
91
self.selfconjugate = (name == antiname)
93
self.line = self.find_line_type()
97
def find_line_type(self):
98
""" find how we draw a line if not defined
99
valid output: dashed/straight/wavy/curly/double/swavy/scurly
109
if not self.selfconjugate:
124
return 'dashed' # return 'dotted' ## not suported yet
126
return 'dashed' # not supported yet
129
# We do not copy the UV wavefunction renormalization as it is defined for the particle only.
130
if self.selfconjugate:
131
raise Exception('%s has no anti particle.' % self.name)
133
for k,v in self.__dict__.iteritems():
134
if k not in self.require_args_all:
136
if self.color in [1,8]:
137
newcolor = self.color
139
newcolor = -self.color
141
return Particle(-self.pdg_code, self.antiname, self.name, self.spin, newcolor, self.mass, self.width,
142
self.antitexname, self.texname, -self.charge, self.line, self.propagating, self.goldstoneboson, **outdic)
148
class Parameter(UFOBaseClass):
150
require_args=['name', 'nature', 'type', 'value', 'texname']
152
def __init__(self, name, nature, type, value, texname, lhablock=None, lhacode=None):
154
args = (name,nature,type,value,texname)
156
UFOBaseClass.__init__(self, *args)
158
args=(name,nature,type,value,texname)
160
global all_parameters
161
all_parameters.append(self)
163
if (lhablock is None or lhacode is None) and nature == 'external':
164
raise Exception('Need LHA information for external parameter "%s".' % name)
165
self.lhablock = lhablock
166
self.lhacode = lhacode
168
all_CTparameters = []
170
class CTParameter(UFOBaseClass):
172
require_args=['name', 'nature,', 'type', 'value', 'texname']
174
def __init__(self, name, type, value, texname):
176
args = (name,'internal',type,value,texname)
178
UFOBaseClass.__init__(self, *args)
180
args=(name,'internal',type,value,texname)
182
self.nature='interal'
184
global all_CTparameters
185
all_CTparameters.append(self)
195
return self.value[-x]
201
class Vertex(UFOBaseClass):
203
require_args=['name', 'particles', 'color', 'lorentz', 'couplings']
205
def __init__(self, name, particles, color, lorentz, couplings, **opt):
207
args = (name, particles, color, lorentz, couplings)
209
UFOBaseClass.__init__(self, *args, **opt)
211
args=(particles,color,lorentz,couplings)
214
all_vertices.append(self)
218
class CTVertex(UFOBaseClass):
220
require_args=['name', 'particles', 'color', 'lorentz', 'couplings', 'type', 'loop_particles']
222
def __init__(self, name, particles, color, lorentz, couplings, type, loop_particles, **opt):
224
args = (name, particles, color, lorentz, couplings, type, loop_particles)
226
UFOBaseClass.__init__(self, *args, **opt)
228
args=(particles,color,lorentz,couplings, type, loop_particles)
230
global all_CTvertices
231
all_CTvertices.append(self)
235
class Coupling(UFOBaseClass):
237
require_args=['name', 'value', 'order']
239
require_args_all=['name', 'value', 'order', 'loop_particles', 'counterterm']
241
def __init__(self, name, value, order, loop_particles=None, counterterm=None, **opt):
243
args =(name, value, order)
244
UFOBaseClass.__init__(self, *args, **opt)
246
all_couplings.append(self)
252
""" the self.value attribute can be a dictionary directly specifying the Laurent serie using normal
253
parameter or just a string which can possibly contain CTparameter defining the Laurent serie."""
255
if isinstance(self.value,dict):
256
if -x in self.value.keys():
257
return self.value[-x]
263
for param in all_CTparameters:
264
pattern=re.compile(r"(?P<first>\A|\*|\+|\-|\(|\s)(?P<name>"+param.name+r")(?P<second>\Z|\*|\+|\-|\)|/|\\|\s)")
265
numberOfMatches=len(pattern.findall(self.value))
267
if numberOfMatches > 0:
271
numbermatch = [numberOfMatches,]
275
CTparam = CTparam + [param,]
276
numbermatch = numbermatch + [numberOfMatches,]
277
# raise UFOError, "UFO does not support yet more than one occurence of CTParameters in the # couplings values."+param.name+" "+self.name+" "+CTparam.name
279
#elif numberOfMatches>1:
280
#raise UFOError, "UFO does not support yet more than one occurence of CTParameters in the #couplings values."+param.name
290
tempvalue = self.value
291
for i,ctpar in enumerate(CTparam):
292
#if ctpar.pole(x)=='ZERO':
295
def substitution(matchedObj):
296
return matchedObj.group('first')+"("+ctpar.pole(x)+")"+matchedObj.group('second')
297
pattern=re.compile(r"(?P<first>\A|\*|\+|\-|\(|\s)(?P<name>"+ctpar.name+r")(?P<second>\Z|\*|\+|\-|\)|/|\\|\s)")
298
tempvalue2 = tempvalue
299
tempvalue = pattern.sub(substitution,tempvalue)
300
num = numbermatch[i]-1
301
while tempvalue2 != tempvalue or num > 0:
302
tempvalue2 = tempvalue
303
tempvalue = pattern.sub(substitution,tempvalue)
305
#for param in CTparam:
306
# pattern=re.compile(r"(?P<first>\A|\*|\+|\-|\()(?P<name>"+param.name+r")(?P<second>\Z|\*|\+|\-|#\)|/|\\)")
307
# numberOfMatches=len(pattern.findall(tempvalue))
308
# if numberOfMatches > 0: raise UFOError,"There is some problem with the substitution of #"+param.name+"."
314
class Lorentz(UFOBaseClass):
316
require_args=['name','spins','structure']
318
def __init__(self, name, spins, structure='external', **opt):
319
args = (name, spins, structure)
320
UFOBaseClass.__init__(self, *args, **opt)
323
all_lorentz.append(self)
328
class Function(object):
330
def __init__(self, name, arguments, expression):
333
all_functions.append(self)
336
self.arguments = arguments
337
self.expr = expression
339
def __call__(self, *opt):
341
for i, arg in enumerate(self.arguments):
342
exec('%s = %s' % (arg, opt[i] ))
344
return eval(self.expr)
348
class CouplingOrder(object):
350
def __init__(self, name, expansion_order, hierarchy, perturbative_expansion = 0):
353
all_orders.append(self)
356
self.expansion_order = expansion_order
357
self.hierarchy = hierarchy
358
self.perturbative_expansion = perturbative_expansion