ATLAS Offline Software
Loading...
Searching...
No Matches
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
6import ast
7from MadGraphControl.MadGraphUtilsHelpers import checkSetting,checkSettingExists
8from MadGraphControl.MadGraphUtils import get_lhapdf_id_and_name
9
10from AthenaCommon import Logging
11mgsyslog = Logging.logging.getLogger('MadGraphSysUtils')
12
13SYSTEMATICS_WEIGHT_INFO="MUR%(mur).1f_MUF%(muf).1f_PDF%(pdf)i"
14SYSTEMATICS_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
22def 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
164def 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
207def 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
278def 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']
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
get_pdf_and_systematic_settings(the_base_fragment, isNLO, useNLOotf=False)
base_fragment_setup_check(the_base_fragment, extras, isNLO)
setup_pdf_and_systematic_weights(the_base_fragment, extras, isNLO)
write_systematics_arguments(systematics_arguments)