################################################################################
#
# Copyright (c) 2016 The MadGraph5_aMC@NLO Development team and Contributors
#
# This file is a part of the MadGraph5_aMC@NLO project, an application which
# automatically generates Feynman diagrams and matrix elements for arbitrary
# high-energy processes in the Standard Model and beyond.
#
# It is subject to the MadGraph5_aMC@NLO license which should accompany this
# distribution.
#
# For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
#
################################################################################
from __future__ import division
if __name__ == "__main__":
import sys
import os
root = os.path.dirname(__file__)
if os.path.basename(root) == 'internal':
sys.path.append(os.path.dirname(root))
else:
sys.path.append(os.path.dirname(os.path.dirname(root)))
import lhe_parser
import banner
import banner as banner_mod
import itertools
import misc
import math
import os
import re
import sys
import time
import StringIO
pjoin = os.path.join
class SystematicsError(Exception):
pass
class Systematics(object):
def __init__(self, input_file, output_file,
start_event=0, stop_event=sys.maxint, write_banner=False,
mur=[0.5,1,2],
muf=[0.5,1,2],
alps=[1],
pdf='errorset', #[(id, subset)]
dyn=[-1,1,2,3,4],
together=[('mur', 'muf', 'dyn')],
lhapdf_config=misc.which('lhapdf-config'),
log=lambda x: sys.stdout.write(str(x)+'\n')
):
# INPUT/OUTPUT FILE
if isinstance(input_file, str):
self.input = lhe_parser.EventFile(input_file)
else:
self.input = input_file
self.output_path = output_file
if output_file != None:
if isinstance(output_file, str):
if output_file == input_file:
directory,name = os.path.split(output_file)
new_name = pjoin(directory, '.tmp_'+name)
self.output = lhe_parser.EventFile(new_name, 'w')
else:
self.output = lhe_parser.EventFile(output_file, 'w')
else:
self.output = output_file
self.log = log
#get some information from the run_card.
self.banner = banner_mod.Banner(self.input.banner)
self.force_write_banner = bool(write_banner)
self.orig_dyn = self.banner.get('run_card', 'dynamical_scale_choice')
self.orig_pdf = self.banner.run_card.get_lhapdf_id()
#check for beam
beam1, beam2 = self.banner.get_pdg_beam()
if abs(beam1) != 2212 and abs(beam2) != 2212:
self.b1 = 0
self.b2 = 0
pdf = 'central'
#raise SystematicsError, 'can only reweight proton beam'
elif abs(beam1) != 2212:
self.b1 = 0
self.b2 = beam2//2212
elif abs(beam2) != 2212:
self.b1 = beam1//2212
self.b2 = 0
else:
self.b1 = beam1//2212
self.b2 = beam2//2212
if isinstance(self.banner.run_card, banner_mod.RunCardLO):
self.is_lo = True
if not self.banner.run_card['use_syst']:
raise SystematicsError, 'The events have not been generated with use_syst=True. Cannot evaluate systematics error on these events.'
else:
self.is_lo = False
if not self.banner.run_card['store_rwgt_info']:
raise SystematicsError, 'The events have not been generated with store_rwgt_info=True. Cannot evaluate systematics error on these events.'
# MUR/MUF/ALPS PARSING
if isinstance(mur, str):
mur = mur.split(',')
self.mur=[float(i) for i in mur]
if isinstance(muf, str):
muf = muf.split(',')
self.muf=[float(i) for i in muf]
if isinstance(alps, str):
alps = alps.split(',')
self.alps=[float(i) for i in alps]
# DYNAMICAL SCALE PARSING + together
if isinstance(dyn, str):
dyn = dyn.split(',')
self.dyn=[int(i) for i in dyn]
if isinstance(together, str):
self.together = together.split(',')
else:
self.together = together
# START/STOP EVENT
self.start_event=int(start_event)
self.stop_event=int(stop_event)
if start_event != 0:
self.log( "#starting from event #%s" % start_event)
if stop_event != sys.maxint:
self.log( "#stopping at event #%s" % stop_event)
# LHAPDF set
if isinstance(lhapdf_config, list):
lhapdf_config = lhapdf_config[0]
lhapdf = misc.import_python_lhapdf(lhapdf_config)
if not lhapdf:
return
lhapdf.setVerbosity(0)
self.pdfsets = {}
if isinstance(pdf, str):
pdf = pdf.split(',')
if isinstance(pdf,list) and isinstance(pdf[0],(str,int)):
self.pdf = []
for data in pdf:
if data == 'errorset':
data = '%s' % self.orig_pdf
if data == 'central':
data = '%s@0' % self.orig_pdf
if '@' in data:
#one particular dataset
name, arg = data.rsplit('@',1)
if int(arg) == 0:
if name.isdigit():
self.pdf.append(lhapdf.mkPDF(int(name)))
else:
self.pdf.append(lhapdf.mkPDF(name))
elif name.isdigit():
try:
self.pdf.append(lhapdf.mkPDF(int(name)+int(arg)))
except:
raise Exception, 'Individual error sets need to be called with LHAPDF NAME not with LHAGLUE NUMBER'
else:
self.pdf.append(lhapdf.mkPDF(name, int(arg)))
else:
if data.isdigit():
pdfset = lhapdf.mkPDF(int(data)).set()
else:
pdfset = lhapdf.mkPDF(data).set()
self.pdfsets[pdfset.lhapdfID] = pdfset
self.pdf += pdfset.mkPDFs()
else:
self.pdf = pdf
for p in self.pdf:
if p.lhapdfID == self.orig_pdf:
self.orig_pdf = p
break
else:
self.orig_pdf = lhapdf.mkPDF(self.orig_pdf)
if not self.b1 == 0 == self.b2:
self.log( "# events generated with PDF: %s (%s)" %(self.orig_pdf.set().name,self.orig_pdf.lhapdfID ))
# create all the function that need to be called
self.get_all_fct() # define self.fcts and self.args
# For e+/e- type of collision initialise the running of alps
if self.b1 == 0 == self.b2:
try:
from models.model_reader import Alphas_Runner
except ImportError:
root_path = pjoin(root, os.pardir, os.pardir)
try:
import internal.madevent_interface as me_int
cmd = me_int.MadEventCmd(root_path,force_run=True)
except ImportError:
import internal.amcnlo_run_interface as me_int
cmd = me_int.Cmd(root_path,force_run=True)
if 'mg5_path' in cmd.options and cmd.options['mg5_path']:
sys.path.append(cmd.options['mg5_path'])
from models.model_reader import Alphas_Runner
if not hasattr(self.banner, 'param_card'):
param_card = self.banner.charge_card('param_card')
else:
param_card = self.banner.param_card
asmz = param_card.get_value('sminputs', 3, 0.13)
nloop =2
zmass = param_card.get_value('mass', 23, 91.188)
cmass = param_card.get_value('mass', 4, 1.4)
if cmass == 0:
cmass = 1.4
bmass = param_card.get_value('mass', 5, 4.7)
if bmass == 0:
bmass = 4.7
self.alpsrunner = Alphas_Runner(asmz, nloop, zmass, cmass, bmass)
def run(self, stdout=sys.stdout):
""" """
start_time = time.time()
if self.start_event == 0 or self.force_write_banner:
lowest_id = self.write_banner(self.output)
else:
lowest_id = self.get_id()
ids = [lowest_id+i for i in range(len(self.args)-1)]
all_cross = [0 for i in range(len(self.args))]
self.input.parsing = False
for nb_event,event in enumerate(self.input):
if nb_event < self.start_event:
continue
elif nb_event == self.start_event:
self.input.parsing = True
event = lhe_parser.Event(event)
elif nb_event >= self.stop_event:
if self.force_write_banner:
self.output.write('\n')
break
if self.is_lo:
if (nb_event-self.start_event)>=0 and (nb_event-self.start_event) % 2500 ==0:
self.log( '# currently at event %s [elapsed time: %.2g s]' % (nb_event, time.time()-start_time))
else:
if (nb_event-self.start_event)>=0 and (nb_event-self.start_event) % 1000 ==0:
self.log( '# currently at event %i [elapsed time: %.2g s]' % (nb_event, time.time()-start_time))
self.new_event() #re-init the caching of alphas/pdf
if self.is_lo:
wgts = [self.get_lo_wgt(event, *arg) for arg in self.args]
else:
wgts = [self.get_nlo_wgt(event, *arg) for arg in self.args]
if wgts[0] == 0:
print wgts
print event
raise Exception
wgt = [event.wgt*wgts[i]/wgts[0] for i in range(1,len(wgts))]
all_cross = [(all_cross[j] + event.wgt*wgts[j]/wgts[0]) for j in range(len(wgts))]
rwgt_data = event.parse_reweight()
rwgt_data.update(zip(ids, wgt))
event.reweight_order += ids
# order the
self.output.write(str(event))
else:
self.output.write('\n')
self.output.close()
self.print_cross_sections(all_cross, min(nb_event,self.stop_event)-self.start_event+1, stdout)
if self.output.name != self.output_path:
import shutil
shutil.move(self.output.name, self.output_path)
return all_cross
def print_cross_sections(self, all_cross, nb_event, stdout):
"""print the cross-section."""
norm = self.banner.get('run_card', 'event_norm', default='sum')
#print "normalisation is ", norm
#print "nb_event is ", nb_event
max_scale, min_scale = 0,sys.maxint
max_alps, min_alps = 0, sys.maxint
max_dyn, min_dyn = 0,sys.maxint
pdfs = {}
dyns = {} # dyn : {'max': , 'min':}
if norm == 'sum':
norm = 1
elif norm == 'average':
norm = 1./nb_event
elif norm == 'unity':
norm = 1
all_cross = [c*norm for c in all_cross]
stdout.write("# mur\t\tmuf\t\talpsfact\tdynamical_scale\tpdf\t\tcross-section\n")
for i,arg in enumerate(self.args):
to_print = list(arg)
to_print[4] = to_print[4].lhapdfID
to_print.append(all_cross[i])
to_report = []
stdout.write('%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\n' % tuple(to_print))
mur, muf, alps, dyn, pdf = arg[:5]
if pdf == self.orig_pdf and (dyn==self.orig_dyn or dyn==-1)\
and (mur!=1 or muf!=1 or alps!=1):
max_scale = max(max_scale,all_cross[i])
min_scale = min(min_scale,all_cross[i])
if pdf == self.orig_pdf and mur==1 and muf==1 and \
(dyn==self.orig_dyn or dyn==-1) and alps!=1:
max_alps = max(max_alps,all_cross[i])
min_alps = min(min_alps,all_cross[i])
if pdf == self.orig_pdf and mur==1 and muf==1 and alps==1:
max_dyn = max(max_dyn,all_cross[i])
min_dyn = min(min_dyn,all_cross[i])
if pdf == self.orig_pdf and (alps!=1 or mur!=1 or muf!=1) and \
(dyn!=self.orig_dyn or dyn!=-1):
if dyn not in dyns:
dyns[dyn] = {'max':0, 'min':sys.maxint,'central':0}
curr = dyns[dyn]
curr['max'] = max(curr['max'],all_cross[i])
curr['min'] = min(curr['min'],all_cross[i])
if pdf == self.orig_pdf and (alps==1 and mur==1 and muf==1) and \
(dyn!=self.orig_dyn or dyn!=-1):
if dyn not in dyns:
dyns[dyn] = {'max':0, 'min':sys.maxint,'central':all_cross[i]}
else:
dyns[dyn]['central'] = all_cross[i]
if alps==1 and mur==1 and muf==1 and (dyn==self.orig_dyn or dyn==-1):
pdfset = pdf.set()
if pdfset.lhapdfID in self.pdfsets:
if pdfset.lhapdfID not in pdfs :
pdfs[pdfset.lhapdfID] = [0] * pdfset.size
pdfs[pdfset.lhapdfID][pdf.memberID] = all_cross[i]
else:
to_report.append('# PDF %s : %s\n' % (pdf.lhapdfID, all_cross[i]))
stdout.write('\n')
resume = StringIO.StringIO()
resume.write( '#***************************************************************************\n')
resume.write( "#\n")
resume.write( '# original cross-section: %s\n' % all_cross[0])
if max_scale:
resume.write( '# scale variation: +%2.3g%% -%2.3g%%\n' % ((max_scale-all_cross[0])/all_cross[0]*100,(all_cross[0]-min_scale)/all_cross[0]*100))
if max_alps:
resume.write( '# emission scale variation: +%2.3g%% -%2.3g%%\n' % ((max_alps-all_cross[0])/all_cross[0]*100,(max_alps-min_scale)/all_cross[0]*100))
if max_dyn and (max_dyn!= all_cross[0] or min_dyn != all_cross[0]):
resume.write( '# central scheme variation: +%2.3g%% -%2.3g%%\n' % ((max_dyn-all_cross[0])/all_cross[0]*100,(all_cross[0]-min_dyn)/all_cross[0]*100))
if self.orig_pdf.lhapdfID in pdfs:
lhapdfid = self.orig_pdf.lhapdfID
values = pdfs[lhapdfid]
pdfset = self.pdfsets[lhapdfid]
pdferr = pdfset.uncertainty(values)
resume.write( '# PDF variation: +%2.3g%% -%2.3g%%\n' % (pdferr.errplus*100/all_cross[0], pdferr.errminus*100/all_cross[0]))
# report error/central not directly linked to the central
resume.write( "#\n")
for lhapdfid,values in pdfs.items():
if lhapdfid == self.orig_pdf.lhapdfID:
continue
if len(values) == 1 :
continue
pdfset = self.pdfsets[lhapdfid]
if pdfset.errorType == 'unknown' :
# Don't know how to determine uncertainty for 'unknown' errorType :
# File "lhapdf.pyx", line 329, in lhapdf.PDFSet.uncertainty (lhapdf.cpp:6621)
# RuntimeError: "ErrorType: unknown" not supported by LHAPDF::PDFSet::uncertainty.
continue
pdferr = pdfset.uncertainty(values)
resume.write( '#PDF %s: %g +%2.3g%% -%2.3g%%\n' % (pdfset.name, pdferr.central,pdferr.errplus*100/all_cross[0], pdferr.errminus*100/all_cross[0]))
dyn_name = {1: '\sum ET', 2:'\sum\sqrt{m^2+pt^2}', 3:'0.5 \sum\sqrt{m^2+pt^2}',4:'\sqrt{\hat s}' }
for key, curr in dyns.items():
if key ==-1:
continue
central, maxvalue, minvalue = curr['central'], curr['max'], curr['min']
if central == 0:
continue
if maxvalue == 0:
resume.write("# dynamical scheme # %s : %g # %s\n" %(key, central, dyn_name[key]))
else:
resume.write("# dynamical scheme # %s : %g +%2.3g%% -%2.3g%% # %s\n" %(key, central, (maxvalue-central)/central*100,(central-minvalue)/central*100, dyn_name[key]))
resume.write('\n'.join(to_report))
resume.write( '#***************************************************************************\n')
stdout.write(resume.getvalue())
self.log(resume.getvalue())
def write_banner(self, fsock):
"""create the new banner with the information of the weight"""
cid = self.get_id()
lowest_id = cid
in_scale = False
in_pdf = False
in_alps = False
text = ''
default = self.args[0]
for arg in self.args[1:]:
mur, muf, alps, dyn, pdf = arg[:5]
if pdf == self.orig_pdf and alps ==1 and (mur!=1 or muf!=1 or dyn!=-1):
if not in_scale:
text += "\n"
in_scale=True
elif in_scale:
if (pdf == self.orig_pdf and alps ==1) and arg != default:
pass
else:
text += " # scale\n"
in_scale = False
if pdf == self.orig_pdf and mur == muf == 1 and dyn==-1 and alps!=1:
if not in_alps:
text += "\n"
in_alps=True
elif in_alps:
text += " # ALPS\n"
in_alps=False
if mur == muf == 1 and dyn==-1 and alps ==1:
if pdf.lhapdfID < 0:
for central,sets in self.pdfsets.items():
if pdf in sets.set():
misc.sprint(central)
if pdf.lhapdfID in self.pdfsets:
if in_pdf:
text += " # PDFSET -> PDFSET\n"
pdfset = self.pdfsets[pdf.lhapdfID]
descrip = pdfset.description.replace('=>',';').replace('>','.gt.').replace('<','.lt.')
text +=" # %s: %s\n" %\
(pdfset.name, pdfset.errorType,pdfset.lhapdfID, descrip)
in_pdf=pdf.lhapdfID
elif pdf.memberID == 0 and (pdf.lhapdfID - pdf.memberID) in self.pdfsets:
if in_pdf:
text += " # PDFSET -> PDFSET\n"
pdfset = self.pdfsets[pdf.lhapdfID - 1]
descrip = pdfset.description.replace('=>',';').replace('>','.gt.').replace('<','.lt.')
text +=" # %s: %s\n" %\
(pdfset.name, pdfset.errorType,pdfset.lhapdfID, descrip)
in_pdf=pdfset.lhapdfID
elif in_pdf and pdf.lhapdfID - pdf.memberID != in_pdf:
misc.sprint(pdf.lhapdfID)
text += " # PDFSET -> PDF\n"
in_pdf = False
elif in_pdf:
text += " PDF \n"
in_pdf=False
tag, info = '',''
if mur!=1.:
tag += 'MUR="%s" ' % mur
info += 'MUR=%s ' % mur
else:
tag += 'MUR="%s" ' % mur
if muf!=1.:
tag += 'MUF="%s" ' % muf
info += 'MUF=%s ' % muf
else:
tag += 'MUF="%s" ' % muf
if alps!=1.:
tag += 'ALPSFACT="%s" ' % alps
info += 'alpsfact=%s ' % alps
if dyn!=-1.:
tag += 'DYN_SCALE="%s" ' % dyn
info += 'dyn_scale_choice=%s ' % {1:'sum pt', 2:'HT',3:'HT/2',4:'sqrts'}[dyn]
if pdf != self.orig_pdf:
tag += 'PDF="%s" ' % pdf.lhapdfID
info += 'PDF=%s MemberID=%s' % (pdf.lhapdfID-pdf.memberID, pdf.memberID)
else:
tag += 'PDF="%s" ' % pdf.lhapdfID
text +=' %s \n' % (cid, tag, info)
cid+=1
if in_scale or in_alps or in_pdf:
text += "\n"
if 'initrwgt' in self.banner:
self.banner['initrwgt'] += text
else:
self.banner['initrwgt'] = text
self.banner.write(self.output, close_tag=False)
return lowest_id
def get_id(self):
if 'initrwgt' in self.banner:
pattern = re.compile(' now just move to central
if f == 0 and pdf.memberID ==0:
# to avoid problem with nnpdf2.3 in lhapdf6.1.6
#print 'central pdf returns 0', pdg, x, scale
#print self.pdfsets
pdfset = pdf.set()
allnumber= [0] + [self.get_pdfQ2(p, pdg, x, scale) for p in pdfset.mkPDFs()[1:]]
f = pdfset.uncertainty(allnumber).central
self.pdfQ2[(pdf, pdg,x,scale)] = f
return f
def get_lo_wgt(self,event, Dmur, Dmuf, Dalps, dyn, pdf):
"""
pdf is a lhapdf object!"""
loinfo = event.parse_lo_weight()
if dyn == -1:
mur = loinfo['ren_scale']
muf1 = loinfo['pdf_q1'][-1]
muf2 = loinfo['pdf_q2'][-1]
else:
if dyn == 1:
mur = event.get_et_scale(1.)
elif dyn == 2:
mur = event.get_ht_scale(1.)
elif dyn == 3:
mur = event.get_ht_scale(0.5)
elif dyn == 4:
mur = event.get_sqrts_scale(1.)
muf1 = mur
muf2 = mur
loinfo = dict(loinfo)
loinfo['pdf_q1'] = loinfo['pdf_q1'] [:-1] + [mur]
loinfo['pdf_q2'] = loinfo['pdf_q2'] [:-1] + [mur]
# MUR part
if self.b1 == 0 == self.b2:
if loinfo['n_qcd'] != 0:
wgt = self.alpsrunner(Dmur*mur)**loinfo['n_qcd']
else:
wgt = 1.0
else:
wgt = pdf.alphasQ(Dmur*mur)**loinfo['n_qcd']
# MUF/PDF part
wgt *= self.get_pdfQ(pdf, self.b1*loinfo['pdf_pdg_code1'][-1], loinfo['pdf_x1'][-1], Dmuf*muf1)
wgt *= self.get_pdfQ(pdf, self.b2*loinfo['pdf_pdg_code2'][-1], loinfo['pdf_x2'][-1], Dmuf*muf2)
for scale in loinfo['asrwt']:
if self.b1 == 0 == self.b2:
wgt = self.alpsrunner(Dalps*scale)
else:
wgt *= pdf.alphasQ(Dalps*scale)
# ALS part
for i in range(loinfo['n_pdfrw1']-1):
scale = min(Dalps*loinfo['pdf_q1'][i], Dmuf*muf1)
wgt *= self.get_pdfQ(pdf, self.b1*loinfo['pdf_pdg_code1'][i], loinfo['pdf_x1'][i], scale)
wgt /= self.get_pdfQ(pdf, self.b1*loinfo['pdf_pdg_code1'][i], loinfo['pdf_x1'][i+1], scale)
for i in range(loinfo['n_pdfrw2']-1):
scale = min(Dalps*loinfo['pdf_q2'][i], Dmuf*muf2)
wgt *= self.get_pdfQ(pdf, self.b2*loinfo['pdf_pdg_code2'][i], loinfo['pdf_x2'][i], scale)
wgt /= self.get_pdfQ(pdf, self.b2*loinfo['pdf_pdg_code2'][i], loinfo['pdf_x2'][i+1], scale)
return wgt
def get_nlo_wgt(self,event, Dmur, Dmuf, Dalps, dyn, pdf):
"""return the new weight for NLO event --with weight information-- """
wgt = 0
nloinfo = event.parse_nlo_weight(real_type=(1,11,12,13))
for cevent in nloinfo.cevents:
if dyn == 1:
mur2 = cevent.get_et_scale(1.)**2
elif dyn == 2:
mur2 = cevent.get_ht_scale(1.)**2
elif dyn == 3:
mur2 = cevent.get_ht_scale(0.5)**2
elif dyn == 4:
mur2 = cevent.get_sqrts_scale(event,1)**2
else:
mur2 = 0
muf2 = mur2
for onewgt in cevent.wgts:
if not __debug__ and (dyn== -1 and Dmur==1 and Dmuf==1 and pdf==self.orig_pdf):
wgt += onewgt.ref_wgt
if dyn == -1:
mur2 = onewgt.scales2[1]
muf2 = onewgt.scales2[2]
Q2 = onewgt.scales2[0] # Ellis-Sexton scale
wgtpdf = self.get_pdfQ2(pdf, self.b1*onewgt.pdgs[0], onewgt.bjks[0],
Dmuf**2 * muf2)
wgtpdf *= self.get_pdfQ2(pdf, self.b2*onewgt.pdgs[1], onewgt.bjks[1],
Dmuf**2 * muf2)
tmp = onewgt.pwgt[0]
tmp += onewgt.pwgt[1] * math.log(Dmur**2 * mur2/ Q2)
tmp += onewgt.pwgt[2] * math.log(Dmuf**2 * muf2/ Q2)
if self.b1 == 0 == self.b2:
alps = self.alpsrunner(Dmur*math.sqrt(mur2))
else:
alps = pdf.alphasQ2(Dmur**2*mur2)
tmp *= math.sqrt(4*math.pi*alps)**onewgt.qcdpower
if wgtpdf == 0: #happens for nn23pdf due to wrong set in lhapdf
key = (self.b1*onewgt.pdgs[0], self.b2*onewgt.pdgs[1], onewgt.bjks[0],onewgt.bjks[1], muf2)
if dyn== -1 and Dmuf==1 and Dmur==1 and pdf==self.orig_pdf:
wgtpdf = onewgt.ref_wgt / tmp
self.pdfQ2[key] = wgtpdf
elif key in self.pdfQ2:
wgtpdf = self.pdfQ2[key]
else:
# real zero!
wgtpdf = 0
tmp *= wgtpdf
wgt += tmp
if __debug__ and dyn== -1 and Dmur==1 and Dmuf==1 and pdf==self.orig_pdf:
if not misc.equal(tmp, onewgt.ref_wgt, sig_fig=2):
misc.sprint(tmp, onewgt.ref_wgt, (tmp-onewgt.ref_wgt)/tmp)
misc.sprint(onewgt)
misc.sprint(cevent)
misc.sprint(mur2,muf2)
raise Exception, 'not enough agreement between stored value and computed one'
return wgt
def call_systematics(args, result=sys.stdout, running=True,
log=lambda x:sys.stdout.write(str(x)+'\n')):
"""calling systematics from a list of arguments"""
input, output = args[0:2]
opts = {}
for arg in args[2:]:
if '=' in arg:
key,values= arg.split('=')
key = key.replace('-','')
values = values.strip()
if values[0] in ["'",'"'] and values[-1]==values[0]:
values = values[1:-1]
values = values.split(',')
if key == 'together':
if key in opts:
opts[key].append(tuple(values))
else:
opts[key]=[tuple(values)]
elif key == 'result':
result = open(values[0],'w')
elif key in ['start_event', 'stop_event']:
opts[key] = int(values[0])
elif key == 'write_banner':
opts[key] = banner_mod.ConfigFile.format_variable(values[0], bool, 'write_banner')
else:
if key in opts:
opts[key] += values
else:
opts[key] = values
else:
raise SystematicsError, "unknow argument %s" % arg
#load run_card and extract parameter if needed.
if 'from_card' in opts:
if opts['from_card'] != ['internal']:
card = banner.RunCard(opts['from_card'][0])
else:
for i in range(10):
try:
lhe = lhe_parser.EventFile(input)
break
except OSError,error:
print error
time.sleep(15*(i+1))
else:
raise
card = banner.RunCard(banner.Banner(lhe.banner)['mgruncard'])
lhe.close()
if isinstance(card, banner.RunCardLO):
# LO case
opts['mur'] = [float(x) for x in card['sys_scalefact'].split()]
opts['muf'] = opts['mur']
if card['sys_alpsfact'] != 'None':
opts['alps'] = [float(x) for x in card['sys_alpsfact'].split()]
else:
opts['alps'] = [1.0]
opts['together'] = [('mur','muf','alps','dyn')]
if '&&' in card['sys_pdf']:
pdfs = card['sys_pdf'].split('&&')
else:
data = card['sys_pdf'].split()
pdfs = []
for d in data:
if not d.isdigit():
pdfs.append(d)
elif int(d) > 500:
pdfs.append(d)
else:
pdfs[-1] = '%s %s' % (pdfs[-1], d)
opts['dyn'] = [-1,1,2,3,4]
opts['pdf'] = []
for pdf in pdfs:
split = pdf.split()
if len(split)==1:
opts['pdf'].append('%s' %pdf)
else:
pdf,nb = split
for i in range(int(nb)):
opts['pdf'].append('%s@%s' % (pdf, i))
if not opts['pdf']:
opts['pdf'] = 'central'
else:
#NLO case
raise Exception
del opts['from_card']
obj = Systematics(input, output, log=log,**opts)
if running:
obj.run(result)
return obj
if __name__ == "__main__":
sys_args = sys.argv[1:]
for i, arg in enumerate(sys_args) :
if arg.startswith('--lhapdf_config=') :
lhapdf = misc.import_python_lhapdf(arg[len('--lhapdf_config='):])
del sys_args[i]
break
if 'lhapdf' not in globals():
lhapdf = misc.import_python_lhapdf('lhapdf-config')
if not lhapdf:
sys.exit('Can not run systematics since can not link python to lhapdf, specify --lhapdf-config=')
call_systematics(sys_args)