Package models :: Module write_param_card
[hide private]
[frames] | no frames]

Source Code for Module models.write_param_card

  1  ############################################################################### 
  2  # 
  3  # Copyright (c) 2010 The MadGraph5_aMC@NLO Development team and Contributors 
  4  # 
  5  # This file is a part of the MadGraph5_aMC@NLO project, an application which  
  6  # automatically generates Feynman diagrams and matrix elements for arbitrary 
  7  # high-energy processes in the Standard Model and beyond. 
  8  # 
  9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
 10  # distribution. 
 11  # 
 12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
 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 
21 22 -class ParamCardWriterError(Exception):
23 """ a error class for this file """
24
25 -def cmp_to_key(mycmp):
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
46 47 -class ParamCardWriter(object):
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):
70 """ model is a valid MG5 model, filepath is the path were to write the 71 param_card.dat """ 72 73 # Compute the value of all dependant parameter 74 if isinstance(model, model_reader.ModelReader): 75 self.model = model 76 else: 77 self.model = model_reader.ModelReader(model) 78 self.model.set_parameters_and_couplings() 79 80 81 assert self.model['parameter_dict'] 82 83 # Organize the data 84 self.external = self.model['parameters'][('external',)] 85 self.param_dict = self.create_param_dict() 86 self.define_not_dep_param() 87 88 if filepath: 89 self.define_output_file(filepath) 90 self.write_card(write_special=write_special)
91 92
93 - def create_param_dict(self):
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
107 - def define_not_dep_param(self):
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 # one loop for the mass 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 # one loop for the width 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
153 - def order_param(obj1, obj2):
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 #identical up to the first finish 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
186 - def define_output_file(self, path, mode='w'):
187 """ initialize the file""" 188 189 if isinstance(path, str): 190 self.fsock = open(path, mode) 191 else: 192 self.fsock = path # prebuild file/IOstring 193 194 self.fsock.write(self.header)
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 # order the parameter in a smart way 204 self.external.sort(key=cmp_to_key(self.order_param)) 205 todo_block= ['MASS', 'DECAY'] # ensure that those two block are always written 206 207 cur_lhablock = '' 208 for param in self.external: 209 if not write_special and param.lhablock.lower() == 'loop': 210 continue 211 #check if we change of lhablock 212 if cur_lhablock != param.lhablock.upper(): 213 # check if some dependent param should be written 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 # write the header of the new block 219 self.write_block(cur_lhablock) 220 #write the parameter 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
228 - def write_block(self, name):
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
239 - def write_param(self, param, lhablock):
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 # avoid to keep special value used to avoid restriction 253 if param.value == 9.999999e-1: 254 param.value = 1 255 elif param.value == 0.000001e-99: 256 param.value = 0 257 258 # If write_special is on False, activate special handling of special parameter 259 # like aS/MUR (fixed via run_card / lhapdf) 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
275 - def write_dep_param_block(self, lhablock):
276 """writing the requested LHA parameter""" 277 278 if lhablock == 'MASS': 279 data = self.dep_mass 280 #misc.sprint(data) 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 # don't write the width of ghosts particles 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 # Add duplicate parameter 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
326 - def write_qnumber(self):
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 # don't write ghosts in the QNumbers block 341 #if part["type"] == 'ghost': 342 # continue 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