326 def main(argv = None):
327 """Main routine of the script.
330 - `argv`: arguments passed to the main routine
336 parser = argparse.ArgumentParser(
337 description=(
"A universal script that merges multiple LHE files for all possible conditions and in the most "
339 "A detailed description of the merging step (in the default mode):\n"
341 " a. assert consistency of the headers (allow difference for the info of e.g. #event, seed);\n"
342 " b. if not MG LO LHEs, will simply use the header from the first LHE; otherwise, reset the "
343 "<MGGenerationInfo> from the headers by merging the #event & xsec info;\n"
344 " 2. Init block: if all <init> blocks are the same, use the same as output; otherwise (the MG LO "
345 "case), merge them by recalculating the # of subprocess (LRPUP) and XSECUP, XERRUP, XMAXUP per "
347 " 3. Event block: concatenate all event blocks. If for MG LO LHEs, recalculate the per-event "
348 "XWGTUP and all <wgt> tags based on the new XSECUP, #event, and 'event_norm' read from the MG "
350 "For further development of this script please always validate the merging result on the test "
351 "routines: https://github.com/colizz/mergelhe_validate\n"
353 " mergeLHE.py -i 'thread*/*.lhe,another_file/another.lhe' -o output.lhe"),
354 formatter_class=argparse.RawTextHelpFormatter)
355 parser.add_argument(
"-i",
"--input-files", type=str,
356 help=
"Input LHE file paths separated by commas. Shell-type wildcards are supported.")
357 parser.add_argument(
"-o",
"--output-file",
358 default=
'output.lhe', type=str,
359 help=
"Output LHE file path.")
360 parser.add_argument(
"--force-mglo-merger", action=
'store_true',
361 help=(
"Force to use the merger script dedicated for MG5 LO LHEs, as introduced in "
362 "https://github.com/cms-sw/genproductions/blob/master/bin/MadGraph5_aMCatNLO/Utilities/merge.pl"))
363 parser.add_argument(
"--force-cpp-merger", action=
'store_true',
364 help=(
"Force to use the external mergeLheFiles.cpp file to merge LHE files, as introduced in "
365 "https://twiki.cern.ch/twiki/bin/view/CMSPublic/SWGuideSubgroupMC#1_2_Using_pLHE_campaigns"))
366 parser.add_argument(
"-b",
"--bypass-check", action=
'store_true',
367 help=(
"Bypass the compatibility check for the headers. If true, the header and init block "
368 "will be just a duplicate from the first input file, and events are concatenated without "
370 parser.add_argument(
"--debug", action=
'store_true',
371 help=
"Use the debug mode.")
372 args = parser.parse_args(argv)
375 format=
'[%(levelname)s] %(message)s',
376 level=logging.INFO
if not args.debug
else DEBUG)
377 logging.info(
'>>> launch mergeLHE.py in %s' % os.path.abspath(os.getcwd()))
380 assert len(args.input_files), \
381 (
'Please specify your input LHE files by -i/--input-files. '
382 'Run \'mergeLHE.py -h\' for details.')
384 for path
in args.input_files.split(
','):
385 find_files = glob.glob(path)
386 if len(find_files) == 0:
387 logging.info(
'Warning: cannot find files in %s' % path)
388 input_files += find_files
390 logging.info(
'>>> Merge %d files: [%s]' % (len(input_files),
', '.
join(input_files)))
391 logging.info(
'>>> Write to output: %s ' % args.output_file)
393 if not os.path.exists(os.path.dirname(os.path.realpath(args.output_file))):
394 os.makedirs(os.path.dirname(os.path.realpath(args.output_file)))
397 assert len(input_files) > 0,
'Input LHE files should be more than 0.'
398 if len(input_files) == 1:
399 logging.warning(
'Input LHE only has 1 file. Will copy this file to the destination.')
401 shutil.copy(input_files[0], args.output_file)
403 assert [args.force_mglo_merger, args.force_cpp_merger].
count(
True) <= 1, \
404 "Can only specify at most one from --force-mglo-merger or --force-cpp-merger."
407 if args.force_mglo_merger:
409 elif args.force_cpp_merger:
412 lhe_merger =
DefaultLHEMerger(input_files, args.output_file, bypass_check=args.bypass_check)