1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 import models.model_reader as model_reader
16 import madgraph.core.base_objects as base_objects
20 """ a error class for this file """
21
23 """ A class for writting an update param_card for a given model """
24
25 header = \
26 "######################################################################\n" + \
27 "## PARAM_CARD AUTOMATICALY GENERATED BY MG5 FOLLOWING UFO MODEL ####\n" + \
28 "######################################################################\n" + \
29 "## ##\n" + \
30 "## Width set on Auto will be computed following the information ##\n" + \
31 "## present in the decay.py files of the model. ##\n" + \
32 '## See arXiv:1402.1178 for more details. ##\n' + \
33 "## ##\n" + \
34 "######################################################################\n"
35
36 sm_pdg = [1,2,3,4,5,6,11,12,13,13,14,15,16,21,22,23,24,25]
37 qnumber_str ="""Block QNUMBERS %(pdg)d # %(name)s
38 1 %(charge)g # 3 times electric charge
39 2 %(spin)d # number of spin states (2S+1)
40 3 %(color)d # colour rep (1: singlet, 3: triplet, 8: octet)
41 4 %(antipart)d # Particle/Antiparticle distinction (0=own anti)\n"""
42
43
44 - def __init__(self, model, filepath=None):
64
65
67 """ return {'name': parameterObject}"""
68
69 out = {}
70 for key, params in self.model['parameters'].items():
71 for param in params:
72 out[param.name] = param
73
74 if 'ZERO' not in out.keys():
75 zero = base_objects.ModelVariable('ZERO', '0', 'real')
76 out['ZERO'] = zero
77 return out
78
79
81 """define self.dep_mass and self.dep_width in case that they are
82 requested in the param_card.dat"""
83
84 all_particles = self.model['particles']
85
86
87 self.dep_mass, self.dep_width = [] , []
88 self.duplicate_mass, self.duplicate_width = [], []
89
90 def_param = []
91
92 for p in all_particles:
93 mass = self.param_dict[p["mass"]]
94 if isinstance(mass, base_objects.ParamCardVariable):
95 if mass.lhacode[0] != p['pdg_code']:
96 self.duplicate_mass.append((p, mass))
97 continue
98 if mass in def_param:
99 self.duplicate_mass.append((p, mass))
100 continue
101 elif p["mass"] != 'ZERO':
102 def_param.append(mass)
103 if p['mass'] not in self.external:
104 self.dep_mass.append((p, mass))
105
106
107 def_param = []
108 for p in all_particles:
109 width = self.param_dict[p["width"]]
110 if isinstance(width, base_objects.ParamCardVariable):
111 if width.lhacode[0] != p['pdg_code']:
112 self.duplicate_width.append((p, width))
113 continue
114 if width in def_param:
115 self.duplicate_width.append((p, width))
116 continue
117 else:
118 if p["width"] != 'ZERO':
119 def_param.append(width)
120 if p['width'] not in self.external:
121 self.dep_width.append((p, width))
122
123
124
125 @staticmethod
127 """ order parameter of a given block """
128
129 block1 = obj1.lhablock.upper()
130 block2 = obj2.lhablock.upper()
131
132 if block1 == block2:
133 pass
134 elif block1 == 'DECAY':
135 return 1
136 elif block2 == 'DECAY':
137 return -1
138 elif block1 < block2:
139 return -1
140 elif block1 != block2:
141 return 1
142
143 maxlen = min([len(obj1.lhacode), len(obj2.lhacode)])
144
145 for i in range(maxlen):
146 if obj1.lhacode[i] < obj2.lhacode[i]:
147 return -1
148 elif obj1.lhacode[i] > obj2.lhacode[i]:
149 return 1
150
151
152 if len(obj1.lhacode) > len(obj2.lhacode):
153 return 1
154 elif len(obj1.lhacode) == len(obj2.lhacode):
155 return 0
156 else:
157 return -1
158
160 """ initialize the file"""
161
162 if isinstance(path, str):
163 self.fsock = open(path, mode)
164 else:
165 self.fsock = path
166
167 self.fsock.write(self.header)
168
170 """schedular for writing a card"""
171
172 if path:
173 self.define_input_file(path)
174
175
176 self.external.sort(self.order_param)
177
178 cur_lhablock = ''
179 for param in self.external:
180
181 if cur_lhablock != param.lhablock.upper():
182
183 self.write_dep_param_block(cur_lhablock)
184 cur_lhablock = param.lhablock.upper()
185
186 self.write_block(cur_lhablock)
187
188 self.write_param(param, cur_lhablock)
189 self.write_dep_param_block(cur_lhablock)
190 self.write_qnumber()
191
193 """ write a comment for a block"""
194
195 self.fsock.writelines(
196 """\n###################################""" + \
197 """\n## INFORMATION FOR %s""" % name.upper() +\
198 """\n###################################\n"""
199 )
200 if name!='DECAY':
201 self.fsock.write("""Block %s \n""" % name.lower())
202
204 """ write the line corresponding to a given parameter """
205
206 if hasattr(param, 'info'):
207 info = param.info
208 else:
209 info = param.name
210 if info.startswith('mdl_'):
211 info = info[4:]
212
213 if param.value.imag != 0:
214 raise ParamCardWriterError, 'All External Parameter should be real (not the case for %s)'%param.name
215
216
217
218 if param.value == 9.999999e-1:
219 param.value = 1
220 elif param.value == 0.000001e-99:
221 param.value = 0
222
223
224 lhacode=' '.join(['%3s' % key for key in param.lhacode])
225 if lhablock != 'DECAY':
226 text = """ %s %e # %s \n""" % (lhacode, param.value.real, info)
227 else:
228 text = '''DECAY %s %e # %s \n''' % (lhacode, param.value.real, info)
229 self.fsock.write(text)
230
231
233 """writing the requested LHA parameter"""
234
235 if lhablock == 'MASS':
236 data = self.dep_mass
237 prefix = " "
238 elif lhablock == 'DECAY':
239 data = self.dep_width
240 prefix = "DECAY "
241 else:
242 return
243
244 text = ""
245 def sort(el1, el2):
246 (p1,n) =el1
247 (p2,n) = el2
248 if (p1["pdg_code"] -p2["pdg_code"]) > 0:
249 return 1
250 else:
251 return -1
252
253 data.sort(sort)
254 for part, param in data:
255
256 if part["type"] == "ghost":
257 continue
258 if self.model['parameter_dict'][param.name].imag:
259 raise ParamCardWriterError, 'All Mass/Width Parameter should be real (not the case for %s)'%param.name
260 value = complex(self.model['parameter_dict'][param.name]).real
261 text += """%s %s %f # %s : %s \n""" %(prefix, part["pdg_code"],
262 value, part["name"], param.expr.replace('mdl_',''))
263
264
265 if lhablock == 'MASS':
266 data = self.duplicate_mass
267 name = 'mass'
268 elif lhablock == 'DECAY':
269 data = self.duplicate_width
270 name = 'width'
271
272 for part, param in data:
273 if self.model['parameter_dict'][param.name].imag:
274 raise ParamCardWriterError, 'All Mass/Width Parameter should be real'
275 value = complex(self.model['parameter_dict'][param.name]).real
276 text += """%s %s %f # %s : %s \n""" %(prefix, part["pdg_code"],
277 value, part["name"], part[name].replace('mdl_',''))
278
279 if not text:
280 return
281
282 pretext = "## Dependent parameters, given by model restrictions.\n"
283 pretext += "## Those values should be edited following the \n"
284 pretext += "## analytical expression. MG5 ignores those values \n"
285 pretext += "## but they are important for interfacing the output of MG5\n"
286 pretext += "## to external program such as Pythia.\n"
287 self.fsock.write(pretext + text)
288
289
291 """ write qnumber """
292
293 def is_anti(logical):
294 if logical:
295 return 0
296 else:
297 return 1
298
299
300 text = ""
301 for part in self.model['particles']:
302 if part["pdg_code"] in self.sm_pdg or part["pdg_code"] < 0:
303 continue
304
305 if part["type"] == 'ghost':
306 continue
307 text += self.qnumber_str % {'pdg': part["pdg_code"],
308 'name': part["name"],
309 'charge': 3 * part["charge"],
310 'spin': part["spin"],
311 'color': part["color"],
312 'antipart': is_anti(part['self_antipart'])}
313
314 if text:
315 pretext="""#===========================================================\n"""
316 pretext += """# QUANTUM NUMBERS OF NEW STATE(S) (NON SM PDG CODE)\n"""
317 pretext += """#===========================================================\n\n"""
318
319 self.fsock.write(pretext + text)
320
321
322
323
324
325
326
327
328 if '__main__' == __name__:
329 ParamCardWriter('./param_card.dat', generic=True)
330 print 'write ./param_card.dat'
331