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  import models.model_reader as model_reader 
 16  import madgraph.core.base_objects as base_objects 
17 18 19 -class ParamCardWriterError(Exception):
20 """ a error class for this file """
21
22 -class ParamCardWriter(object):
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):
45 """ model is a valid MG5 model, filepath is the path were to write the 46 param_card.dat """ 47 48 # Compute the value of all dependant parameter 49 if isinstance(model, model_reader.ModelReader): 50 self.model = model 51 else: 52 self.model = model_reader.ModelReader(model) 53 self.model.set_parameters_and_couplings() 54 55 56 # Organize the data 57 self.external = self.model['parameters'][('external',)] 58 self.param_dict = self.create_param_dict() 59 self.define_not_dep_param() 60 61 if filepath: 62 self.define_output_file(filepath) 63 self.write_card()
64 65
66 - def create_param_dict(self):
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
80 - def define_not_dep_param(self):
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 # one loop for the mass 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 # one loop for the width 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
126 - def order_param(obj1, obj2):
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 #identical up to the first finish 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
159 - def define_output_file(self, path, mode='w'):
160 """ initialize the file""" 161 162 if isinstance(path, str): 163 self.fsock = open(path, mode) 164 else: 165 self.fsock = path # prebuild file/IOstring 166 167 self.fsock.write(self.header)
168
169 - def write_card(self, path=None):
170 """schedular for writing a card""" 171 172 if path: 173 self.define_input_file(path) 174 175 # order the parameter in a smart way 176 self.external.sort(self.order_param) 177 178 cur_lhablock = '' 179 for param in self.external: 180 #check if we change of lhablock 181 if cur_lhablock != param.lhablock.upper(): 182 # check if some dependent param should be written 183 self.write_dep_param_block(cur_lhablock) 184 cur_lhablock = param.lhablock.upper() 185 # write the header of the new block 186 self.write_block(cur_lhablock) 187 #write the parameter 188 self.write_param(param, cur_lhablock) 189 self.write_dep_param_block(cur_lhablock) 190 self.write_qnumber()
191
192 - def write_block(self, name):
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
203 - def write_param(self, param, lhablock):
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 # avoid to keep special value used to avoid restriction 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
232 - def write_dep_param_block(self, lhablock):
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 # don't write the width of ghosts particles 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 # Add duplicate parameter 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
290 - def write_qnumber(self):
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 # don't write ghosts in the QNumbers block 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