3 from AthenaCommon
import Logging
4 from ...decorators
import timed
5 from ...utility
import FileParser
6 from ..generators
import multicore_untimed, singlecore_untimed
13 logger = Logging.logging.getLogger(
"PowhegControl")
16 WeightTuple = collections.namedtuple(
"WeightTuple", [
"parameter_settings",
"keywords",
"ID",
"name",
"combine",
"group",
"parallel_xml_compatible"])
19 """! Returns True if the LHE file contains a weight called "nominal".
21 The weight must be present before the beginning of the first <event> block,
22 otherwise the function returns False.
24 @param powheg_LHE_output Name of LHE file produced by PowhegBox.
26 search_string =
"<weight id='0' >default</weight>"
27 with open(powheg_LHE_output,
'r')
as lhe_file:
29 if search_string
in line:
38 def reweighter(process, weight_groups, powheg_LHE_output):
39 """! Add a series of additional weights to an LHE file.
41 @param process PowhegBox process.
42 @param weight_groups OrderedDict containing groups of weights to add.
43 @param powheg_LHE_output Name of LHE file produced by PowhegBox.
45 logger.info(
"Starting to run PowhegControl PDF and QCD scale reweighter")
50 non_weight_attributes = [
"parameter_names",
"combination_method",
"keywords"]
53 xml_kwds = {
"renscfact":
"renscfact",
"facscfact":
"facscfact",
"lhans1":
"lhapdf",
"lhans2":
"lhapdf",
"width_correction" :
"width_correction"}
56 _idx_scale_start, _idx_PDF_start, _idx_other_start = 1001, 2001, 3001
58 if not process.use_XML_reweighting:
59 logger.warning(
"... XML-style reweighting is not enabled for this process. Will use old (multiple-pass) method.")
62 for group_name, weight_group
in weight_groups.items():
63 logger.info(
"Preparing weight group: {:<19} with {} weights".
format(group_name, len(weight_group) - len(non_weight_attributes)))
66 is_parallel_xml_compatible = process.use_XML_reweighting
and all([k
in xml_kwds.keys()
for _kw_set
in weight_group[
"keywords"]
for k
in _kw_set])
67 if is_parallel_xml_compatible:
68 _keywords = [
list(
set([xml_kwds[k]
for k
in _kw_set]))
for _kw_set
in weight_group[
"keywords"]]
70 if process.use_XML_reweighting:
71 logger.warning(
"... this weight group is incompatible with XML-style reweighting. Will use old (multiple-pass) method.")
72 _keywords = weight_group[
"keywords"]
73 keyword_dict = dict((n, k)
for n, k
in zip(weight_group[
"parameter_names"], _keywords))
76 tuple_kwargs = {
"keywords": keyword_dict,
"combine": weight_group[
"combination_method"],
"group": group_name,
"parallel_xml_compatible": is_parallel_xml_compatible}
80 weight_list.append(
WeightTuple(parameter_settings=weight_group[
"nominal"], ID=0, name=
"nominal", **tuple_kwargs))
83 elif group_name ==
"scale_variation":
84 for idx, name
in enumerate([k
for k
in weight_group.keys()
if k
not in non_weight_attributes], start=_idx_scale_start):
85 weight_list.append(
WeightTuple(parameter_settings=weight_group[name], ID=idx, name=name, **tuple_kwargs))
86 _idx_scale_start = idx + 1
89 elif group_name ==
"PDF_variation":
90 for idx, name
in enumerate([k
for k
in weight_group.keys()
if k
not in non_weight_attributes], start=_idx_PDF_start):
91 weight_list.append(
WeightTuple(parameter_settings=weight_group[name], ID=idx, name=name, **tuple_kwargs))
92 _idx_PDF_start = idx + 1
96 for idx, name
in enumerate([k
for k
in weight_group.keys()
if k
not in non_weight_attributes], start=_idx_other_start):
97 weight_list.append(
WeightTuple(parameter_settings=weight_group[name], ID=idx, name=name, **tuple_kwargs))
98 _idx_other_start = idx + 1
101 if os.path.isfile(
"pwgcounters.dat"):
102 shutil.copy(
"pwgcounters.dat",
"pwgcounters.dat.bak")
106 shutil.copy(
"powheg.input",
"powheg.input.before_reweighting")
108 raise IOError(
"Powheg input card ('powheg.input') cannot be found at the start of reweighting. In a normal setup, PowhegControl generates this input card. Its absence is probably a sign of problems --- please investigate or contact the PowhegControl experts.")
112 shutil.copy(powheg_LHE_output,
"{}.before_reweighting".
format(powheg_LHE_output))
114 raise IOError(
"Nominal LHE file could not be found. Probably POWHEG-BOX crashed during event generation.")
117 if process.use_XML_reweighting:
120 weight_list = [
WeightTuple(ID=0, name=
"nominal", group=
"nominal", parallel_xml_compatible=
True, parameter_settings=[], keywords=
None, combine=
None)] + weight_list
122 FileParser(
"powheg.input").text_replace(
"pdfreweight .*",
"pdfreweight 0")
124 xml_lines, serial_xml_weight_list, current_weightgroup = [], [],
None
125 for weight
in weight_list:
127 if weight.parallel_xml_compatible
and weight.group != current_weightgroup:
128 xml_lines.append(
"</weightgroup>")
129 current_weightgroup = weight.group
130 xml_lines.append(
"<weightgroup name='{}' combine='{}'>".
format(weight.group, weight.combine))
132 if weight.parallel_xml_compatible:
133 keyword_pairs_str =
" ".
join([
"{}={}".
format(k, v)
for p, v
in weight.parameter_settings
for k
in weight.keywords[p]])
134 xml_lines.append(
"<weight id='{}'> {} </weight>".
format(weight.ID, keyword_pairs_str))
136 serial_xml_weight_list.append(weight)
137 xml_lines.append(xml_lines.pop(0))
138 n_parallel_xml_weights = len(weight_list) - len(serial_xml_weight_list)
141 if n_parallel_xml_weights > 0:
143 with open(
"reweighting_input.xml",
"w")
as f_rwgt:
144 f_rwgt.write(
"<initrwgt>\n")
145 [f_rwgt.write(
"{}\n".
format(xml_line))
for xml_line
in xml_lines]
146 f_rwgt.write(
"</initrwgt>")
151 FileParser(
"powheg.input").text_replace(
"rwl_file .*",
"rwl_file 'reweighting_input.xml'")
152 FileParser(
"powheg.input").text_replace(
"rwl_add .*",
"rwl_add 1")
153 FileParser(
"powheg.input").text_replace(
"clobberlhe .*",
"clobberlhe 1")
155 logger.info(
"Preparing simultaneous calculation of {} additional weights for generated events.".
format(n_parallel_xml_weights))
158 if list(process.parameters_by_name(
"manyseeds"))[0].value == 1:
159 if process.powheg_version ==
"RES":
160 os.system(
'cp reweighting_input.xml backup_of_reweighting_input.xml')
161 os.system(
'cp powheg.input powheg.input.for_reweighting')
164 FileParser(
"powheg.input").text_replace(
"manyseeds .*",
"manyseeds 0")
165 FileParser(
"powheg.input").text_replace(
"parallelstage .*",
"parallelstage -1")
166 os.system(
'cp reweighting_input.xml backup_of_reweighting_input.xml')
167 os.system(
'cp powheg.input powheg.input.for_reweighting')
170 os.system(
'cp reweighting_input.xml backup_of_reweighting_input.xml')
171 os.system(
'cp powheg.input powheg.input.for_reweighting')
178 if len(serial_xml_weight_list) > 0:
179 logger.info(
"Preparing individual calculation of {} additional weights for generated events.".
format(len(serial_xml_weight_list)))
180 shutil.move(
"reweighting_input.xml",
"reweighting_input.nominal")
181 for idx_weight, weight
in enumerate(serial_xml_weight_list, start=1):
182 add_single_weight(process, weight, idx_weight, len(serial_xml_weight_list), use_XML=
True)
184 shutil.move(
"reweighting_input.nominal",
"reweighting_input.xml")
189 logger.info(
"Preparing individual calculation of {} additional weights for generated events.".
format(len(weight_list)))
190 for idx_weight, weight
in enumerate(weight_list, start=1):
194 if process.use_XML_reweighting:
195 comment_patterns = [
"#pdf",
"#rwgt",
"#new weight",
"#matching",
" #Random" ]
196 if process.remove_oldStyle_rwt_comments:
198 logger.info(
"Removing comment lines from lhe file - these lines can be added back using the 'remove_oldStyle_rwt_comments=False' argument in generate()")
200 for pattern
in comment_patterns:
201 removed = FileParser(powheg_LHE_output).text_remove(
"^"+pattern)
202 logger.info(
"{} line(s) starting with '{}' were removed from {}".
format(removed, pattern, powheg_LHE_output))
204 logger.info(
"Fixing comment lines from lhe file - these lines can be simply removed using the 'remove_oldStyle_rwt_comments=True' argument in generate()")
205 for pattern
in comment_patterns:
210 for weight
in weight_list:
211 replacelist += [[
".* id='{}' .*".
format(weight.ID),
"<weight id='{weight_id}'>{weight_name}</weight>".
format(weight_id=weight.ID, weight_name=weight.name), 1]]
214 replacelist += [[
'LesHouchesEvents version="1.0"',
'LesHouchesEvents version="3.0"', 1]]
215 FileParser(powheg_LHE_output).text_replace_multi(replacelist)
218 shutil.move(
"powheg_nominal.input",
"powheg.input")
219 if os.path.isfile(
"pwgcounters.dat.bak"):
220 shutil.move(
"pwgcounters.dat.bak",
"pwgcounters.dat")
223 """! Add a single additional weight to an LHE file.
225 @param process PowhegBox process.
226 @param weight Tuple with details of the weight to be added.
227 @param idx_weight Which number this weight is.
228 @param n_total Total number of weights being added.
229 @param use_XML Whether to use XML or old-style reweighting.
231 @
timed(
"weight variation {}/{}".
format(idx_weight, n_total))
232 def __timed_inner_fn():
233 logger.info(
"... weight name is: {}".
format(weight.name))
234 logger.info(
"... weight index ID is: {}".
format(weight.ID))
235 shutil.copy(
"powheg_nominal.input",
"powheg.input")
239 FileParser(
"powheg.input").text_replace(
"rwl_file .*",
"rwl_file 'reweighting_input.xml'")
240 FileParser(
"powheg.input").text_replace(
"rwl_add .*",
"rwl_add 1")
241 FileParser(
"powheg.input").text_replace(
"clobberlhe .*",
"clobberlhe 1")
242 FileParser(
"powheg.input").text_replace(
"pdfreweight .*",
"pdfreweight 0")
245 FileParser(
"powheg.input").text_replace(
"compute_rwgt 0",
"compute_rwgt 1")
247 FileParser(
"powheg.input").text_replace(
"manyseeds .*",
"manyseeds 0")
248 FileParser(
"powheg.input").text_replace(
"parallelstage .*",
"parallelstage -1")
251 for (parameter, value)
in weight.parameter_settings:
253 for keyword
in weight.keywords[parameter]:
254 FileParser(
"powheg.input").text_replace(
"^{} .*".
format(keyword),
"{} {}".
format(keyword, value))
255 logger.info(
"... setting {} to {}".
format(parameter, value))
257 logger.warning(
"Parameter '{}' not recognised. Cannot reweight!".
format(parameter))
261 with open(
"reweighting_input.xml",
"w")
as f_rwgt:
262 f_rwgt.write(
"<initrwgt>\n")
263 f_rwgt.write(
"<weightgroup name='{}' combine='{}'>\n".
format(weight.group, weight.combine))
264 f_rwgt.write(
"<weight id='{}'> </weight>\n".
format(weight.ID))
265 f_rwgt.write(
"</weightgroup>\n")
266 f_rwgt.write(
"</initrwgt>")
269 FileParser(
"powheg.input").text_replace(
"lhrwgt_descr .*",
"lhrwgt_descr '{}'".
format(weight.name))
270 FileParser(
"powheg.input").text_replace(
"lhrwgt_id .*",
"lhrwgt_id '{}'".
format(weight.ID))
271 FileParser(
"powheg.input").text_replace(
"lhrwgt_group_combine .*",
"lhrwgt_group_combine '{}'".
format(weight.combine))
272 FileParser(
"powheg.input").text_replace(
"lhrwgt_group_name .*",
"lhrwgt_group_name '{}'".
format(weight.group))
275 if list(process.parameters_by_name(
"manyseeds"))[0].value == 1:
276 if process.powheg_version ==
"RES":
279 FileParser(
"powheg.input").text_replace(
"manyseeds .*",
"manyseeds 0")
280 FileParser(
"powheg.input").text_replace(
"parallelstage .*",
"parallelstage -1")
290 reweighted_events_file_name = powheg_LHE_output.replace(
".lhe",
"-rwgt.lhe")
292 shutil.move(reweighted_events_file_name, powheg_LHE_output)
294 raise IOError(
"Reweighted LHE file '{filename}' could not be found. Probably POWHEG-BOX crashed during reweighting.".
format(filename=reweighted_events_file_name))
300 if not os.path.isfile(
"{}.before_reweighting".
format(lheFile)):
301 logger.error(
"Impossible to find file {}.before_reweighting".
format(lheFile))
305 shutil.move(lheFile,
"{}.text_replace_backup".
format(lheFile))
309 with open(
"{}.text_replace_backup".
format(lheFile),
"rb")
as f_input:
310 line_in = f_input.readline()
312 if re.search(
"^"+pattern.lstrip(), line_in.decode().lstrip()):
314 elif re.search(
"^</event>", line_in.decode().lstrip()):
316 line_in = f_input.readline()
318 n_found_noWeights = 0
319 n_events_noWeights = 0
320 with open(
"{}.before_reweighting".
format(lheFile),
"rb")
as f_input:
321 line_in = f_input.readline()
323 if re.search(
"^"+pattern.lstrip(), line_in.decode().lstrip()):
324 n_found_noWeights += 1
325 elif re.search(
"^</event>", line_in.decode().lstrip()):
326 n_events_noWeights += 1
327 line_in = f_input.readline()
330 impossible_to_fix =
False
335 with open(lheFile,
"w")
as f_output:
337 if n_found == n_found_noWeights:
339 with open(
"{}.text_replace_backup".
format(lheFile),
"rb")
as f_input,
open(
"{}.before_reweighting".
format(lheFile),
"rb")
as f_input_noWeights:
340 line_in = f_input.readline()
341 line_in_noWeights = f_input_noWeights.readline()
343 if re.search(
"^"+pattern.lstrip(), line_in.decode().lstrip()):
345 while line_in_noWeights:
346 if re.search(
"^"+pattern, line_in_noWeights.decode().lstrip()):
347 if (line_in.decode().rstrip().lstrip() != line_in_noWeights.decode().rstrip().lstrip()):
348 f_output.write(line_in_noWeights.decode())
351 f_output.write(line_in.decode())
352 line_in_noWeights = f_input_noWeights.readline()
356 line_in_noWeights = f_input_noWeights.readline()
358 line_in = f_input.readline()
360 impossible_to_fix =
True
362 if impossible_to_fix:
365 f_output.write(line_in.decode())
366 line_in = f_input.readline()
369 while line_in_noWeights:
370 if re.search(
"^"+pattern, line_in_noWeights.decode()):
371 impossible_to_fix =
True
373 if impossible_to_fix:
375 line_in_noWeights = f_input_noWeights.readline()
377 elif n_found == 0
and n_found_noWeights == n_events_noWeights
and n_events == n_events_noWeights:
379 with open(
"{}.text_replace_backup".
format(lheFile),
"rb")
as f_input,
open(
"{}.before_reweighting".
format(lheFile),
"rb")
as f_input_noWeights:
380 line_in = f_input.readline()
381 line_in_noWeights = f_input_noWeights.readline()
382 while line_in_noWeights:
383 if re.search(
"^"+pattern, line_in_noWeights.decode().lstrip()):
385 if re.search(
"^</event>", line_in.decode().lstrip()):
386 f_output.write(line_in_noWeights.decode())
387 f_output.write(line_in.decode())
389 line_in = f_input.readline()
392 f_output.write(line_in.decode())
393 line_in = f_input.readline()
394 line_in_noWeights = f_input_noWeights.readline()
396 f_output.write(line_in.decode())
397 line_in = f_input.readline()
400 if n_found == 0
and n_found_noWeights == 0:
401 shutil.move(
"{}.text_replace_backup".
format(lheFile), lheFile)
402 logger.info(
"No line with pattern '{}' was found in lhe file before or after reweighting, so need to fix it".
format(pattern))
403 elif impossible_to_fix:
404 shutil.move(
"{}.text_replace_backup".
format(lheFile), lheFile)
405 logger.info(
"Impossible to fix the possibly buggy comment lines with pattern {} in {} using the corresponding lines from {}.before_reweighting".
format(pattern, lheFile, lheFile))
406 logger.info(
"Keeping those lines as they are in '{}".
format(lheFile))
408 os.remove(
"{}.text_replace_backup".
format(lheFile))
410 logger.info(
"{} line(s) starting with '{}' replaced in {} using the corresponding line(s) from {}.before_reweighting".
format(n_replaced, pattern, lheFile, lheFile))
411 elif n_found != 0
and n_replaced == 0:
412 logger.info(
"No line starting with '{}' was replaced in {} ({} were found) since none seems buggy".
format(pattern, lheFile, n_found))
413 elif n_added_back !=0:
414 logger.info(
"{} line(s) starting with '{}' added back in {} using the corresponding line(s) from {}.before_reweighting".
format(n_added_back, pattern, lheFile, lheFile))