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, write_special=True):
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
196 - def write_card(self, path=None, write_special=True):
197 """schedular for writing a card"""
198
199 if path:
200 self.define_input_file(path)
201
202
203
204 self.external.sort(key=cmp_to_key(self.order_param))
205 todo_block= ['MASS', 'DECAY']
206
207 cur_lhablock = ''
208 for param in self.external:
209 if not write_special and param.lhablock.lower() == 'loop':
210 continue
211
212 if cur_lhablock != param.lhablock.upper():
213
214 self.write_dep_param_block(cur_lhablock)
215 cur_lhablock = param.lhablock.upper()
216 if cur_lhablock in todo_block:
217 todo_block.remove(cur_lhablock)
218
219 self.write_block(cur_lhablock)
220
221 self.write_param(param, cur_lhablock)
222 self.write_dep_param_block(cur_lhablock)
223 for cur_lhablock in todo_block:
224 self.write_block(cur_lhablock)
225 self.write_dep_param_block(cur_lhablock)
226 self.write_qnumber()
227
229 """ write a comment for a block"""
230
231 self.fsock.writelines(
232 """\n###################################""" + \
233 """\n## INFORMATION FOR %s""" % name.upper() +\
234 """\n###################################\n"""
235 )
236 if name!='DECAY':
237 self.fsock.write("""Block %s \n""" % name.lower())
238
240 """ write the line corresponding to a given parameter """
241
242 if hasattr(param, 'info'):
243 info = param.info
244 else:
245 info = param.name
246 if info.startswith('mdl_'):
247 info = info[4:]
248
249 if param.value != 'auto' and param.value.imag != 0:
250 raise ParamCardWriterError('All External Parameter should be real (not the case for %s)'%param.name)
251
252
253 if param.value == 9.999999e-1:
254 param.value = 1
255 elif param.value == 0.000001e-99:
256 param.value = 0
257
258
259
260 if param.lhablock.lower() == 'sminputs' and tuple(param.lhacode) == (3,):
261 info = "%s (Note that Parameter not used if you use a PDF set)" % info
262
263
264
265 lhacode=' '.join(['%3s' % key for key in param.lhacode])
266 if lhablock != 'DECAY':
267 text = """ %s %e # %s \n""" % (lhacode, param.value.real, info)
268 elif param.value == 'auto':
269 text = '''DECAY %s auto # %s \n''' % (lhacode, info)
270 else:
271 text = '''DECAY %s %e # %s \n''' % (lhacode, param.value.real, info)
272 self.fsock.write(text)
273
274
276 """writing the requested LHA parameter"""
277
278 if lhablock == 'MASS':
279 data = self.dep_mass
280
281 prefix = " "
282 elif lhablock == 'DECAY':
283 data = self.dep_width
284 prefix = "DECAY "
285 else:
286 return
287
288 text = ""
289 data.sort(key= lambda el: el[0]["pdg_code"])
290 for part, param in data:
291
292 if part["type"] == "ghost":
293 continue
294 if self.model['parameter_dict'][param.name].imag:
295 raise ParamCardWriterError('All Mass/Width Parameter should be real (not the case for %s)'%param.name)
296 value = complex(self.model['parameter_dict'][param.name]).real
297 text += """%s %s %e # %s : %s \n""" %(prefix, part["pdg_code"],
298 value, part["name"], param.expr.replace('mdl_',''))
299
300
301 if lhablock == 'MASS':
302 data = self.duplicate_mass
303 name = 'mass'
304 elif lhablock == 'DECAY':
305 data = self.duplicate_width
306 name = 'width'
307
308 for part, param in data:
309 if self.model['parameter_dict'][param.name].imag:
310 raise ParamCardWriterError('All Mass/Width Parameter should be real')
311 value = complex(self.model['parameter_dict'][param.name]).real
312 text += """%s %s %e # %s : %s \n""" %(prefix, part["pdg_code"],
313 value, part["name"], part[name].replace('mdl_',''))
314
315 if not text:
316 return
317
318 pretext = "## Dependent parameters, given by model restrictions.\n"
319 pretext += "## Those values should be edited following the \n"
320 pretext += "## analytical expression. MG5 ignores those values \n"
321 pretext += "## but they are important for interfacing the output of MG5\n"
322 pretext += "## to external program such as Pythia.\n"
323 self.fsock.write(pretext + text)
324
325
327 """ write qnumber """
328
329 def is_anti(logical):
330 if logical:
331 return 0
332 else:
333 return 1
334
335
336 text = ""
337 for part in self.model['particles']:
338 if part["pdg_code"] in self.sm_pdg or part["pdg_code"] < 0:
339 continue
340
341
342
343 text += self.qnumber_str % {'pdg': part["pdg_code"],
344 'name': part["name"],
345 'charge': 3 * part["charge"],
346 'spin': part["spin"],
347 'color': part["color"],
348 'antipart': is_anti(part['self_antipart'])}
349
350 if text:
351 pretext="""#===========================================================\n"""
352 pretext += """# QUANTUM NUMBERS OF NEW STATE(S) (NON SM PDG CODE)\n"""
353 pretext += """#===========================================================\n\n"""
354
355 self.fsock.write(pretext + text)
356
357
358
359
360
361
362
363
364 if '__main__' == __name__:
365 ParamCardWriter('./param_card.dat', generic=True)
366 print('write ./param_card.dat')
367