1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 from __future__ import absolute_import
16 from __future__ import print_function
17 import models.model_reader as model_reader
18 import madgraph.core.base_objects as base_objects
19 import madgraph.various.misc as misc
20 from six.moves import range
23 """ a error class for this file """
24
26 'Convert a cmp= function into a key= function'
27
28
29 class K:
30 def __init__(self, obj, *args):
31 self.obj = obj
32 def __lt__(self, other):
33 return mycmp(self.obj, other.obj) < 0
34 def __gt__(self, other):
35 return mycmp(self.obj, other.obj) > 0
36 def __eq__(self, other):
37 return mycmp(self.obj, other.obj) == 0
38 def __le__(self, other):
39 return mycmp(self.obj, other.obj) <= 0
40 def __ge__(self, other):
41 return mycmp(self.obj, other.obj) >= 0
42 def __ne__(self, other):
43 return mycmp(self.obj, other.obj) != 0
44 return K
45
48 """ A class for writting an update param_card for a given model """
49
50 header = \
51 "######################################################################\n" + \
52 "## PARAM_CARD AUTOMATICALY GENERATED BY MG5 FOLLOWING UFO MODEL ####\n" + \
53 "######################################################################\n" + \
54 "## ##\n" + \
55 "## Width set on Auto will be computed following the information ##\n" + \
56 "## present in the decay.py files of the model. ##\n" + \
57 '## See arXiv:1402.1178 for more details. ##\n' + \
58 "## ##\n" + \
59 "######################################################################\n"
60
61 sm_pdg = [1,2,3,4,5,6,11,12,13,13,14,15,16,21,22,23,24,25]
62 qnumber_str ="""Block QNUMBERS %(pdg)d # %(name)s
63 1 %(charge)g # 3 times electric charge
64 2 %(spin)d # number of spin states (2S+1)
65 3 %(color)d # colour rep (1: singlet, 3: triplet, 8: octet)
66 4 %(antipart)d # Particle/Antiparticle distinction (0=own anti)\n"""
67
68
69 - def __init__(self, model, filepath=None):
91
92
94 """ return {'name': parameterObject}"""
95
96 out = {}
97 for key, params in self.model['parameters'].items():
98 for param in params:
99 out[param.name] = param
100
101 if 'ZERO' not in list(out.keys()):
102 zero = base_objects.ModelVariable('ZERO', '0', 'real')
103 out['ZERO'] = zero
104 return out
105
106
108 """define self.dep_mass and self.dep_width in case that they are
109 requested in the param_card.dat"""
110
111 all_particles = self.model['particles']
112
113
114 self.dep_mass, self.dep_width = [] , []
115 self.duplicate_mass, self.duplicate_width = [], []
116
117 def_param = []
118
119 for p in all_particles:
120 mass = self.param_dict[p["mass"]]
121 if isinstance(mass, base_objects.ParamCardVariable):
122 if mass.lhacode[0] != p['pdg_code']:
123 self.duplicate_mass.append((p, mass))
124 continue
125 if mass in def_param:
126 self.duplicate_mass.append((p, mass))
127 continue
128 elif p["mass"] != 'ZERO':
129 def_param.append(mass)
130 if p['mass'] not in self.external:
131 self.dep_mass.append((p, mass))
132
133
134 def_param = []
135 for p in all_particles:
136 width = self.param_dict[p["width"]]
137 if isinstance(width, base_objects.ParamCardVariable):
138 if width.lhacode[0] != p['pdg_code']:
139 self.duplicate_width.append((p, width))
140 continue
141 if width in def_param:
142 self.duplicate_width.append((p, width))
143 continue
144 else:
145 if p["width"] != 'ZERO':
146 def_param.append(width)
147 if p['width'] not in self.external:
148 self.dep_width.append((p, width))
149
150
151
152 @staticmethod
154 """ order parameter of a given block """
155
156 block1 = obj1.lhablock.upper()
157 block2 = obj2.lhablock.upper()
158
159 if block1 == block2:
160 pass
161 elif block1 == 'DECAY':
162 return 1
163 elif block2 == 'DECAY':
164 return -1
165 elif block1 < block2:
166 return -1
167 elif block1 != block2:
168 return 1
169
170 maxlen = min([len(obj1.lhacode), len(obj2.lhacode)])
171
172 for i in range(maxlen):
173 if obj1.lhacode[i] < obj2.lhacode[i]:
174 return -1
175 elif obj1.lhacode[i] > obj2.lhacode[i]:
176 return 1
177
178
179 if len(obj1.lhacode) > len(obj2.lhacode):
180 return 1
181 elif len(obj1.lhacode) == len(obj2.lhacode):
182 return 0
183 else:
184 return -1
185
195
224
226 """ write a comment for a block"""
227
228 self.fsock.writelines(
229 """\n###################################""" + \
230 """\n## INFORMATION FOR %s""" % name.upper() +\
231 """\n###################################\n"""
232 )
233 if name!='DECAY':
234 self.fsock.write("""Block %s \n""" % name.lower())
235
237 """ write the line corresponding to a given parameter """
238
239 if hasattr(param, 'info'):
240 info = param.info
241 else:
242 info = param.name
243 if info.startswith('mdl_'):
244 info = info[4:]
245
246 if param.value.imag != 0:
247 raise ParamCardWriterError('All External Parameter should be real (not the case for %s)'%param.name)
248
249
250
251 if param.value == 9.999999e-1:
252 param.value = 1
253 elif param.value == 0.000001e-99:
254 param.value = 0
255
256
257 lhacode=' '.join(['%3s' % key for key in param.lhacode])
258 if lhablock != 'DECAY':
259 text = """ %s %e # %s \n""" % (lhacode, param.value.real, info)
260 else:
261 text = '''DECAY %s %e # %s \n''' % (lhacode, param.value.real, info)
262 self.fsock.write(text)
263
264
266 """writing the requested LHA parameter"""
267
268 if lhablock == 'MASS':
269 data = self.dep_mass
270
271 prefix = " "
272 elif lhablock == 'DECAY':
273 data = self.dep_width
274 prefix = "DECAY "
275 else:
276 return
277
278 text = ""
279 data.sort(key= lambda el: el[0]["pdg_code"])
280 for part, param in data:
281
282 if part["type"] == "ghost":
283 continue
284 if self.model['parameter_dict'][param.name].imag:
285 raise ParamCardWriterError('All Mass/Width Parameter should be real (not the case for %s)'%param.name)
286 value = complex(self.model['parameter_dict'][param.name]).real
287 text += """%s %s %e # %s : %s \n""" %(prefix, part["pdg_code"],
288 value, part["name"], param.expr.replace('mdl_',''))
289
290
291 if lhablock == 'MASS':
292 data = self.duplicate_mass
293 name = 'mass'
294 elif lhablock == 'DECAY':
295 data = self.duplicate_width
296 name = 'width'
297
298 for part, param in data:
299 if self.model['parameter_dict'][param.name].imag:
300 raise ParamCardWriterError('All Mass/Width Parameter should be real')
301 value = complex(self.model['parameter_dict'][param.name]).real
302 text += """%s %s %e # %s : %s \n""" %(prefix, part["pdg_code"],
303 value, part["name"], part[name].replace('mdl_',''))
304
305 if not text:
306 return
307
308 pretext = "## Dependent parameters, given by model restrictions.\n"
309 pretext += "## Those values should be edited following the \n"
310 pretext += "## analytical expression. MG5 ignores those values \n"
311 pretext += "## but they are important for interfacing the output of MG5\n"
312 pretext += "## to external program such as Pythia.\n"
313 self.fsock.write(pretext + text)
314
315
317 """ write qnumber """
318
319 def is_anti(logical):
320 if logical:
321 return 0
322 else:
323 return 1
324
325
326 text = ""
327 for part in self.model['particles']:
328 if part["pdg_code"] in self.sm_pdg or part["pdg_code"] < 0:
329 continue
330
331
332
333 text += self.qnumber_str % {'pdg': part["pdg_code"],
334 'name': part["name"],
335 'charge': 3 * part["charge"],
336 'spin': part["spin"],
337 'color': part["color"],
338 'antipart': is_anti(part['self_antipart'])}
339
340 if text:
341 pretext="""#===========================================================\n"""
342 pretext += """# QUANTUM NUMBERS OF NEW STATE(S) (NON SM PDG CODE)\n"""
343 pretext += """#===========================================================\n\n"""
344
345 self.fsock.write(pretext + text)
346
347
348
349
350
351
352
353
354 if '__main__' == __name__:
355 ParamCardWriter('./param_card.dat', generic=True)
356 print('write ./param_card.dat')
357