189def modify_param_card(param_card_input=None,param_card_backup=None,process_dir=MADGRAPH_GRIDPACK_LOCATION,params={},output_location=None):
190 """Build a new param_card.dat from an existing one.
191 Params should be a dictionary of dictionaries. The first key is the block name, and the second in the param name.
192 Keys can include MASS (for masses) and DECAY X (for decays of particle X)"""
193
194
195
196 if param_card_input is None:
197 param_card_input=process_dir+'/Cards/param_card.dat'
198 elif param_card_input is not None and not os.access(param_card_input,os.R_OK):
199 paramcard = subprocess.Popen(['get_files','-data',param_card_input])
200 paramcard.wait()
201 if not os.access(param_card_input,os.R_OK):
202 raise RuntimeError('Could not get param card '+param_card_input)
203 mglog.info('Using input param card at '+param_card_input)
204
205
206 paramsUpper = {}
207 for blockName in list(params.keys()):
208 paramsUpper[blockName.upper()] = {}
209 for paramName in list(params[blockName].keys()):
210 paramsUpper[blockName.upper()][paramName.upper()] = params[blockName][paramName]
211
212 if param_card_backup is not None:
213 mglog.info('Keeping backup of original param card at '+param_card_backup)
214 param_card_old = param_card_backup
215 else:
216 param_card_old = param_card_input+'.old_to_be_deleted'
217 if os.path.isfile(param_card_old):
218 os.unlink(param_card_old)
219 os.rename(param_card_input, param_card_old)
220
221 oldcard = open(param_card_old,'r')
222 param_card_location= process_dir+'/Cards/param_card.dat' if output_location is None else output_location
223 newcard = open(param_card_location,'w')
224 decayEdit = False
225 blockName = ""
226 doneParams = {}
227 for linewithcomment in oldcard:
228 line=linewithcomment.split('#')[0]
229 if line.strip().
upper().startswith(
'BLOCK')
or line.strip().
upper().startswith(
'DECAY')\
230 and len(line.strip().
split()) > 1:
231 if decayEdit and blockName == 'DECAY':
232 decayEdit = False
233 pos = 0 if line.strip().startswith('DECAY') else 1
234 if blockName=='MASS' and 'MASS' in paramsUpper:
235
236 if "MASS" in doneParams:
237 leftOvers = [ x for x in paramsUpper['MASS'] if x not in doneParams['MASS'] ]
238 else:
239 leftOvers = [ x for x in paramsUpper['MASS'] ]
240
241 for pdg_id in leftOvers:
242 mglog.warning('Adding mass line for '+str(pdg_id)+' = '+str(paramsUpper['MASS'][pdg_id])+' which was not in original param card')
243 newcard.write(' '+str(pdg_id)+' '+str(paramsUpper['MASS'][pdg_id])+'\n')
244 doneParams['MASS'][pdg_id]=True
245 if blockName==
'DECAY' and 'DECAY' not in line.strip().
upper()
and 'DECAY' in paramsUpper:
246
247 leftOvers = [ x for x in paramsUpper['DECAY'] if x not in doneParams['DECAY'] ]
248 for pdg_id in leftOvers:
249 mglog.warning('Adding decay for pdg id '+str(pdg_id)+' which was not in the original param card')
250 newcard.write( paramsUpper[
'DECAY'][pdg_id].
strip()+
'\n' )
251 doneParams['DECAY'][pdg_id]=True
253 if decayEdit:
254 continue
255
256 akey = None
257 if blockName !=
'DECAY' and len(line.strip().
split()) > 0:
258
259
260 if len(line.split())==2:
262 else:
263
264 akey = line.upper().
strip()[:line.strip().rfind(
' ')].
strip()
265 elif blockName ==
'DECAY' and len(line.strip().
split()) > 1:
266 akey = line.strip().
split()[1]
267 if akey is None:
268 newcard.write(linewithcomment)
269 continue
270
271
272 if blockName not in paramsUpper:
273 newcard.write(linewithcomment)
274 continue
275 blockParams = paramsUpper[blockName]
276
277 akey = find_key_and_update(akey,blockParams)
278
279
280 stringkey = None
281 if '#' in linewithcomment:
282 stringkey = linewithcomment[linewithcomment.find(
'#')+1:].
strip()
283 if len(stringkey.split()) > 0:
284 stringkey = stringkey.split()[0].
upper()
285
286 if akey not in blockParams and not (stringkey is not None and stringkey in blockParams):
287 newcard.write(linewithcomment)
288 continue
289
290 if akey in blockParams and (stringkey is not None and stringkey in blockParams):
291 raise RuntimeError('Conflicting use of numeric and string keys '+akey+' and '+stringkey)
292
293 theParam = blockParams.get(akey,blockParams[stringkey] if stringkey in blockParams else None)
294 if blockName not in doneParams:
295 doneParams[blockName] = {}
296 if akey in blockParams:
297 doneParams[blockName][akey]=True
298 elif stringkey is not None and stringkey in blockParams:
299 doneParams[blockName][stringkey]=True
300
301
302 if blockName=="DECAY":
303 if theParam.splitlines()[0].
split()[0].
upper()==
"DECAY":
304
305 for newline in theParam.splitlines():
306 newcard.write(newline+'\n')
307 mglog.info(newline)
308 decayEdit = True
309 else:
310 newcard.write(
'DECAY '+akey+
' '+str(theParam)+
' # '+(linewithcomment[linewithcomment.find(
'#')+1:].
strip()
if linewithcomment.find(
'#')>0
else "")+
'\n')
311 mglog.info(
'DECAY '+akey+
' '+str(theParam)+
' # '+(linewithcomment[linewithcomment.find(
'#')+1:].
strip()
if linewithcomment.find(
'#')>0
else "")+
'\n')
312
313 elif blockName=='QNUMBERS':
314
315 for newline in theParam.splitlines():
316 newcard.write(newline+'\n')
317 mglog.info(newline)
318 decayEdit = True
319 else:
320 newcard.write(
' '+akey+
' '+str(theParam)+
' # '+(linewithcomment[linewithcomment.find(
'#')+1:].
strip()
if linewithcomment.find(
'#')>0
else "")+
'\n')
321 mglog.info(
' '+akey+
' '+str(theParam)+
' # '+(linewithcomment[linewithcomment.find(
'#')+1:].
strip()
if linewithcomment.find(
'#')>0
else "")+
'\n')
322
323
324
325 for blockName in paramsUpper:
326 if blockName not in doneParams and len(paramsUpper[blockName].keys())>0:
327 raise RuntimeError('Did not find any of the parameters for block '+blockName+' in param_card')
328 for paramName in paramsUpper[blockName]:
329 if paramName not in doneParams[blockName]:
330 raise RuntimeError('Was not able to replace parameter '+paramName+' in param_card')
331
332
333 oldcard.close()
334 newcard.close()
335