ATLAS Offline Software
MadGraphSystematicsUtils.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
2 
3 # utils to set systematics according to base fragment
4 
5 # use some helper functions from MadGraphUtils
6 import ast
7 from MadGraphControl.MadGraphUtilsHelpers import checkSetting,checkSettingExists
8 from MadGraphControl.MadGraphUtils import get_lhapdf_id_and_name
9 
10 from AthenaCommon import Logging
11 mgsyslog = Logging.logging.getLogger('MadGraphSysUtils')
12 
13 SYSTEMATICS_WEIGHT_INFO="MUR%(mur).1f_MUF%(muf).1f_PDF%(pdf)i"
14 SYSTEMATICS_WEIGHT_INFO_ALTDYNSCALES="MUR%(mur).1f_MUF%(muf).1f_DYNSCALE%(dyn)i_PDF%(pdf)i"
15 
16 #==================================================================================
17 # main function: figure out run_card arguments that need to be set
18 # depends on
19 # * base fragment
20 # * NLO vs LO
21 # * MadGraph version
22 def get_pdf_and_systematic_settings(the_base_fragment,isNLO,useNLOotf=False):
23 
24  if not isNLO:
25  useNLOotf=False
26 
27 
28  runcard_settings={}
29  runcard_systematics_arguments={}
30 
31  basefragment_settings={}
32  basefragment_settings['central_pdf']=None
33  basefragment_settings['alternative_pdfs']=None
34  basefragment_settings['pdf_variations']=None
35  basefragment_settings['scale_variations']=None
36  basefragment_settings['alternative_dynamic_scales']=None
37  for s in basefragment_settings:
38  if s in the_base_fragment:
39  if isinstance(basefragment_settings[s],list) and len(basefragment_settings[s])==0:
40  continue
41  basefragment_settings[s]=the_base_fragment[s]
42  else:
43  if s=='central_pdf':
44  raise RuntimeError('No "central_pdf" configured in base fragment')
45  if s=='alternative_dynamic_scales':
46  continue
47  mgsyslog.warning('base fragment or pdf settings does not define "'+s+'"')
48 
49 
50  for s in basefragment_settings:
51  if s=='central_pdf':
52  if not isinstance(basefragment_settings[s],int):
53  raise RuntimeError(s+', configured in base fragment, has to be an integer')
54  continue
55  if basefragment_settings[s] is None:
56  continue
57  if s=='scale_variations':
58  if not isinstance(basefragment_settings[s],list):
59  raise RuntimeError(s+', configured in base fragment, has to be a list of numbers')
60  for pdf in basefragment_settings[s]:
61  if not isinstance(pdf,float) and not isinstance(pdf,int):
62  raise RuntimeError(s+', configured in base fragment, has to be a list of numbers')
63  else:
64  if not isinstance(basefragment_settings[s],list):
65  raise RuntimeError(s+', configured in base fragment, has to be a list of integers')
66  for element in basefragment_settings[s]:
67  if not isinstance(element,int) or not element>0:
68  raise RuntimeError(s+', configured in base fragment, has to be a list of positive integers')
69 
70 
71  if basefragment_settings['alternative_pdfs'] is not None:
72  # if a PDF set is included as variation (i.e. nominal + error pdf) there is no need to have it as alternative pdf (i.e. only nominal)
73  if basefragment_settings['pdf_variations'] is not None:
74  basefragment_settings['alternative_pdfs']=[ a for a in basefragment_settings['alternative_pdfs'] if a not in basefragment_settings['pdf_variations'] ]
75  # the central pdf does not need to be included as alternative PDF
76  if basefragment_settings['central_pdf'] in basefragment_settings['alternative_pdfs']:
77  basefragment_settings['alternative_pdfs'].remove(basefragment_settings['central_pdf'])
78 
79 
80  runcard_settings['pdlabel']='lhapdf'
81  runcard_settings['lhaid']=str(basefragment_settings['central_pdf'])
82 
83  # turn on LO systematics and use new systematics script
84  if not useNLOotf:
85  if basefragment_settings['alternative_dynamic_scales'] is not None:
86  runcard_systematics_arguments['weight_info']=SYSTEMATICS_WEIGHT_INFO_ALTDYNSCALES
87  else:
88  runcard_systematics_arguments['weight_info']=SYSTEMATICS_WEIGHT_INFO
89  runcard_systematics_arguments['remove_wgts']='".*MUR0.5_MUF2.0.*|.*MUR2.0_MUF0.5.*"'
90 
91  runcard_settings['systematics_program']='none'
92  for s in ['alternative_pdfs','pdf_variations','scale_variations']:
93  if basefragment_settings[s] is not None and len(basefragment_settings[s])>0:
94  # set use_syst true if some variations are used
95  if isNLO:
96  runcard_settings['store_rwgt_info']='True'
97  else:
98  runcard_settings['use_syst']='True'
99  # use the MadGraph systematics program != syscalc
100  runcard_settings['systematics_program']='systematics'
101  break
102 
103 
104  if useNLOotf:
105  # pdf weights with NLO syntax
106  if basefragment_settings['pdf_variations'] is not None and basefragment_settings['central_pdf'] in basefragment_settings['pdf_variations']:
107  runcard_settings['reweight_pdf']='True'
108  else:
109  runcard_settings['reweight_pdf']='False'
110  if basefragment_settings['pdf_variations'] is not None:
111  for v in basefragment_settings['pdf_variations']:
112  if v==basefragment_settings['central_pdf']:
113  continue
114  runcard_settings['lhaid']+=' '+str(v)
115  runcard_settings['reweight_pdf']+=' True'
116  if basefragment_settings['alternative_pdfs'] is not None:
117  for a in basefragment_settings['alternative_pdfs']:
118  runcard_settings['lhaid']+=' '+str(a)
119  runcard_settings['reweight_pdf']+=' False'
120 
121  else: #use the new python systematics module
122  sys_pdfs=[]
123  if basefragment_settings['pdf_variations'] is not None:
124  for v in basefragment_settings['pdf_variations']:
125  sys_pdfs.append(get_lhapdf_id_and_name(v)[1])
126  if basefragment_settings['alternative_pdfs'] is not None:
127  for a in basefragment_settings['alternative_pdfs']:
128  sys_pdfs.append(get_lhapdf_id_and_name(a)[1]+'@0')
129  if len(sys_pdfs)>0:
130  runcard_systematics_arguments['pdf']=','.join(sys_pdfs)
131  if isNLO:
132  runcard_settings['reweight_pdf']='False'
133 
134 
135 
136  if basefragment_settings['scale_variations'] is None and isNLO:
137  runcard_settings['reweight_scale']='False'
138  if basefragment_settings['scale_variations'] is not None:
139  if useNLOotf:
140  runcard_settings['reweight_scale']='True'
141  runcard_settings['rw_rscale']=' '.join([str(s) for s in basefragment_settings['scale_variations']])
142  runcard_settings['rw_fscale']=' '.join([str(s) for s in basefragment_settings['scale_variations']])
143  else:
144  runcard_systematics_arguments['muf']=','.join([str(s) for s in basefragment_settings['scale_variations']])
145  runcard_systematics_arguments['mur']=','.join([str(s) for s in basefragment_settings['scale_variations']])
146  runcard_systematics_arguments['dyn']='-1'
147  if isNLO:
148  runcard_settings['reweight_scale']='False'
149 
150  if basefragment_settings['alternative_dynamic_scales'] is not None:
151  if useNLOotf:
152  raise RuntimeError('Cannot reweight to alternative dynamic scales using the NLO OTF module')
153  else:
154  runcard_systematics_arguments['dyn']=','.join([str(s) for s in [-1]+basefragment_settings['alternative_dynamic_scales']])
155 
156  if not useNLOotf:
157  runcard_settings['systematics_arguments']=write_systematics_arguments(runcard_systematics_arguments)
158 
159  return runcard_settings
160 
161 #==================================================================================
162 # this function is called during build_run card to check the consistency of user-provided arguments with the inlude
163 # and throw errors, warnings, or corrects the input as is appropriate
164 def setup_pdf_and_systematic_weights(the_base_fragment,extras,isNLO):
165 
166 
167 
168  for k in extras:
169  k_clean=k.lower().replace("'",'').replace('"','')
170  if k_clean!=k and k_clean in systematics_run_card_options(isNLO):
171  extras[k_clean]=extras[k]
172  extras.pop(k,None)
173 
174 
175  if base_fragment_setup_check(the_base_fragment,extras,isNLO):
176  return
177  # if something is set that contradicts the base fragment: bad!
178  for o in systematics_run_card_options(isNLO):
179  if o in extras:
180  raise RuntimeError('Error, you tried to set "'+str(o)+'" by hand, but you should trust the base fragment with the following options: '+', '.join(systematics_run_card_options(isNLO)))
181 
182 
183  new_settings=get_pdf_and_systematic_settings(the_base_fragment,isNLO)
184 
185  user_set_extras=dict(extras)
186  for s in new_settings:
187  if s is not None:
188  extras[s]=new_settings[s]
189 
190 
191  mgsyslog.info('PDF and scale settings were set as follows:')
192  for p in systematics_run_card_options(isNLO):
193  user_set='not set'
194  if p in user_set_extras:
195  user_set=str(user_set_extras[p])
196  new_value='not set'
197  if p in extras:
198  new_value=str(extras[p])
199  mgsyslog.info('MadGraphUtils set '+str(p)+' to "'+new_value+'", was set to "'+user_set+'"')
200 
201 
202 #==================================================================================
203 # check whether a configuration is in agreement with base fragment
204 # true if nothing needs to be done
205 # false if still needs setup
206 # error if inconsistent config
207 def base_fragment_setup_check(the_base_fragment,extras,isNLO):
208  # no include: allow it (with warning), as long as lhapdf is used
209  # if not (e.g. because no choice was made and the internal pdf ise used): error
210  if the_base_fragment is None:
211  mgsyslog.warning('!!! No pdf base fragment was included in your job options. PDFs should be set with an include file. You might be unable to follow the PDF4LHC uncertainty prescription. Let\'s hope you know what you doing !!!')
212  if not checkSetting('pdlabel','lhapdf',extras) or not checkSettingExists('lhaid',extras):
213  mgsyslog.warning('!!! No pdf base fragment was included in your job options and you did not specify a LHAPDF yourself -- in the future, this will cause an error !!!')
214  #TODO: in the future this should be an error
215  #raise RuntimeError('No pdf base fragment was included in your job options and you did not specify a LHAPDF yourself')
216  return True
217  else:
218  # if setting is already exactly as it should be -- great!
219  correct_settings=get_pdf_and_systematic_settings(the_base_fragment,isNLO)
220  allgood=True
221  for s in correct_settings:
222  if s is None and s in extras:
223  allgood=False
224  break
225  if s not in extras or extras[s]!=correct_settings[s]:
226  allgood=False
227  break
228  if allgood:
229  return True
230  # no error but also nothing set
231  return False
232 
233 #==================================================================================
234 # convert settings from the syscalc syntax to the new systematics syntax which is steered via "systematics_arguments"
235 # will modify the dict and also return new setting
237  if 'systematics_program' in extras:
238  if extras['systematics_program'].lower=='none':
239  mgsyslog.warning('no need to convert systematics arguments if systematcs are not run')
240  return
241  if extras['systematics_program'].lower=='syscalc':
242  mgsyslog.warning('systematics already correct for chosen systematics program SysCalc')
243  return
244 
245  if 'systematics_arguments' in extras:
246  mgsyslog.warning('systematics_arguments already defined, will be overwritten')
247  systematics_arguments={}
248  systematics_arguments['dyn']='-1'
249  systematics_arguments['mur']='1'
250  systematics_arguments['muf']='1'
251 
252  if 'sys_scalefact' in extras:
253  sys_scalefact=extras['sys_scalefact']
254  extras.pop('sys_scalefact')
255  if len(sys_scalefact.split())>0:
256  systematics_arguments['mur']=','.join(sys_scalefact.split())
257  systematics_arguments['muf']=','.join(sys_scalefact.split())
258 
259  systematics_arguments['pdf']='central'
260  if 'sys_pdf' in extras:
261  sys_pdf=extras['sys_pdf']
262  extras.pop('sys_pdf')
263  spl=sys_pdf.replace('&&',' ').split()
264  i=0
265  pdfs=[]
266  while i <len(spl):
267  pdfs.append(spl[i])
268  if i+1<len(spl) and spl[i+1].isdigit() and int(spl[i+1])<1000:
269  pdfs[-1]+='@'+str(int(spl[i+1])-1)
270  i+=1
271  i+=1
272  if len(pdfs)>0:
273  systematics_arguments['pdf']=','.join(pdfs)
274  systematics_arguments['weight_info']=SYSTEMATICS_WEIGHT_INFO
275  extras['systematics_arguments']=write_systematics_arguments(systematics_arguments)
276  return extras['systematics_arguments']
277 
278 def write_systematics_arguments(systematics_arguments):
279  return '['+','.join(["'--"+k+"="+systematics_arguments[k]+"'" for k in systematics_arguments])+']'
280 
281 #==================================================================================
282 # create a map from the 'systematics_arguments' run card argument
284  parsed={}
285  if sys_args.strip().startswith('['):
286  argument_list = ast.literal_eval(sys_args)
287  for a in argument_list:
288  key,value=parse_systematics_argument(a)
289  parsed[key]=value
290  else:
291  arg=sys_args.replace("'",'').replace('"','')
292  key,value=parse_systematics_argument(arg)
293  return parsed
294 
296  spl=sys_arg.strip().split('=')
297  return (spl[0].strip()[2:],spl[1].strip())
298 
299 #==================================================================================
300 # these arguments steer systematics
302  if isNLO:
303  return ['pdlabel','lhaid','reweight_pdf','reweight_scale','rw_rscale','rw_fscale','store_rwgt_info','systematics_arguments' ]
304  else:
305  return ['pdlabel','lhaid','use_syst','sys_scalefact','sys_pdf','systematics_arguments']
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
python.MadGraphSystematicsUtils.convertSysCalcArguments
def convertSysCalcArguments(extras)
Definition: MadGraphSystematicsUtils.py:236
MadGraphUtils
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
python.MadGraphSystematicsUtils.setup_pdf_and_systematic_weights
def setup_pdf_and_systematic_weights(the_base_fragment, extras, isNLO)
Definition: MadGraphSystematicsUtils.py:164
python.MadGraphSystematicsUtils.base_fragment_setup_check
def base_fragment_setup_check(the_base_fragment, extras, isNLO)
Definition: MadGraphSystematicsUtils.py:207
python.MadGraphUtilsHelpers.checkSetting
def checkSetting(key_, value_, mydict_)
Definition: MadGraphUtilsHelpers.py:35
python.MadGraphSystematicsUtils.write_systematics_arguments
def write_systematics_arguments(systematics_arguments)
Definition: MadGraphSystematicsUtils.py:278
python.MadGraphSystematicsUtils.get_pdf_and_systematic_settings
def get_pdf_and_systematic_settings(the_base_fragment, isNLO, useNLOotf=False)
Definition: MadGraphSystematicsUtils.py:22
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
python.MadGraphSystematicsUtils.parse_systematics_argument
def parse_systematics_argument(sys_arg)
Definition: MadGraphSystematicsUtils.py:295
python.MadGraphSystematicsUtils.parse_systematics_arguments
def parse_systematics_arguments(sys_args)
Definition: MadGraphSystematicsUtils.py:283
python.MadGraphUtils.get_lhapdf_id_and_name
def get_lhapdf_id_and_name(pdf)
Definition: MadGraphUtils.py:849
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.MadGraphSystematicsUtils.systematics_run_card_options
def systematics_run_card_options(isNLO)
Definition: MadGraphSystematicsUtils.py:301
python.MadGraphUtilsHelpers.checkSettingExists
def checkSettingExists(key_, mydict_)
Definition: MadGraphUtilsHelpers.py:50
str
Definition: BTagTrackIpAccessor.cxx:11
Trk::split
@ split
Definition: LayerMaterialProperties.h:38