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):
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()
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):
197 """schedular for writing a card""" 198 199 if path: 200 self.define_input_file(path) 201 202 # order the parameter in a smart way 203 self.external.sort(key=cmp_to_key(self.order_param)) 204 todo_block= ['MASS', 'DECAY'] # ensure that those two block are always written 205 206 cur_lhablock = '' 207 for param in self.external: 208 #check if we change of lhablock 209 if cur_lhablock != param.lhablock.upper(): 210 # check if some dependent param should be written 211 self.write_dep_param_block(cur_lhablock) 212 cur_lhablock = param.lhablock.upper() 213 if cur_lhablock in todo_block: 214 todo_block.remove(cur_lhablock) 215 # write the header of the new block 216 self.write_block(cur_lhablock) 217 #write the parameter 218 self.write_param(param, cur_lhablock) 219 self.write_dep_param_block(cur_lhablock) 220 for cur_lhablock in todo_block: 221 self.write_block(cur_lhablock) 222 self.write_dep_param_block(cur_lhablock) 223 self.write_qnumber()
224
225 - def write_block(self, name):
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
236 - def write_param(self, param, lhablock):
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 # avoid to keep special value used to avoid restriction 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
265 - def write_dep_param_block(self, lhablock):
266 """writing the requested LHA parameter""" 267 268 if lhablock == 'MASS': 269 data = self.dep_mass 270 #misc.sprint(data) 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 # don't write the width of ghosts particles 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 # Add duplicate parameter 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
316 - def write_qnumber(self):
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 # don't write ghosts in the QNumbers block 331 #if part["type"] == 'ghost': 332 # continue 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