CMS 3D CMS Logo

Classes | Functions
mergeLHE Namespace Reference

Classes

class  BaseLHEMerger
 
class  DefaultLHEMerger
 
class  ExternalCppLHEMerger
 
class  MG5LOLHEMerger
 

Functions

def main (argv=None)
 

Function Documentation

◆ main()

def mergeLHE.main (   argv = None)
Main routine of the script.

Arguments:
- `argv`: arguments passed to the main routine

Definition at line 328 of file mergeLHE.py.

References submitPVResolutionJobs.count, join(), and addLHEnumbers.number_events().

328 def main(argv = None):
329  """Main routine of the script.
330 
331  Arguments:
332  - `argv`: arguments passed to the main routine
333  """
334 
335  if argv == None:
336  argv = sys.argv[1:]
337 
338  parser = argparse.ArgumentParser(
339  description=("A universal script that merges multiple LHE files for all possible conditions and in the most "
340  "natural way.\n"
341  "A detailed description of the merging step (in the default mode):\n"
342  " 1. Header:\n"
343  " a. assert consistency of the headers (allow difference for the info of e.g. #event, seed);\n"
344  " b. if not MG LO LHEs, will simply use the header from the first LHE; otherwise, reset the "
345  "<MGGenerationInfo> from the headers by merging the #event & xsec info;\n"
346  " 2. Init block: if all <init> blocks are the same, use the same as output; otherwise (the MG LO "
347  "case), merge them by recalculating the # of subprocess (LRPUP) and XSECUP, XERRUP, XMAXUP per "
348  "each subprocess.\n"
349  " 3. Event block: concatenate all event blocks. If for MG LO LHEs, recalculate the per-event "
350  "XWGTUP and all <wgt> tags based on the new XSECUP, #event, and 'event_norm' read from the MG "
351  "run card.\n"
352  "For further development of this script please always validate the merging result on the test "
353  "routines: https://github.com/colizz/mergelhe_validate\n"
354  "Example usage:\n"
355  " mergeLHE.py -i 'thread*/*.lhe,another_file/another.lhe' -o output.lhe"),
356  formatter_class=argparse.RawTextHelpFormatter)
357  parser.add_argument("-i", "--input-files", type=str,
358  help="Input LHE file paths separated by commas. Shell-type wildcards are supported.")
359  parser.add_argument("-o", "--output-file",
360  default='output.lhe', type=str,
361  help="Output LHE file path.")
362  parser.add_argument("--force-mglo-merger", action='store_true',
363  help=("Force to use the merger script dedicated for MG5 LO LHEs, as introduced in "
364  "https://github.com/cms-sw/genproductions/blob/master/bin/MadGraph5_aMCatNLO/Utilities/merge.pl"))
365  parser.add_argument("--force-cpp-merger", action='store_true',
366  help=("Force to use the external mergeLheFiles.cpp file to merge LHE files, as introduced in "
367  "https://twiki.cern.ch/twiki/bin/view/CMSPublic/SWGuideSubgroupMC#1_2_Using_pLHE_campaigns"))
368  parser.add_argument("-b", "--bypass-check", action='store_true',
369  help=("Bypass the compatibility check for the headers. If true, the header and init block "
370  "will be just a duplicate from the first input file, and events are concatenated without "
371  "modification."))
372  parser.add_argument("-n", "--number-events", action='store_true',
373  help=("Add a tag to number each lhe event. Needed for Herwig to find correct lhe events"))
374  parser.add_argument("--debug", action='store_true',
375  help="Use the debug mode.")
376  args = parser.parse_args(argv)
377 
378  logging.basicConfig(
379  format='[%(levelname)s] %(message)s',
380  level=logging.INFO if not args.debug else DEBUG)
381  logging.info('>>> launch mergeLHE.py in %s' % os.path.abspath(os.getcwd()))
382 
383  # Extract input LHE files from the path
384  assert len(args.input_files), \
385  ('Please specify your input LHE files by -i/--input-files. '
386  'Run \'mergeLHE.py -h\' for details.')
387  input_files = [] # each individual input file
388  for path in args.input_files.split(','):
389  find_files = glob.glob(path)
390  if len(find_files) == 0:
391  logging.info('Warning: cannot find files in %s' % path)
392  input_files += find_files
393  input_files.sort()
394  logging.info('>>> Merge %d files: [%s]' % (len(input_files), ', '.join(input_files)))
395  logging.info('>>> Write to output: %s ' % args.output_file)
396 
397  if not os.path.exists(os.path.dirname(os.path.realpath(args.output_file))):
398  os.makedirs(os.path.dirname(os.path.realpath(args.output_file)))
399 
400  if args.number_events:
401  offset = 0
402  for input_file in input_files:
403  offset += addLHEnumbers.number_events(input_file, offset=offset)
404 
405  # Check arguments
406  assert len(input_files) > 0, 'Input LHE files should be more than 0.'
407  if len(input_files) == 1:
408  logging.warning('Input LHE only has 1 file. Will copy this file to the destination.')
409  import shutil
410  shutil.copy(input_files[0], args.output_file)
411  return
412  assert [args.force_mglo_merger, args.force_cpp_merger].count(True) <= 1, \
413  "Can only specify at most one from --force-mglo-merger or --force-cpp-merger."
414 
415  # Determine the merging scheme
416  if args.force_mglo_merger:
417  lhe_merger = MG5LOLHEMerger(input_files, args.output_file)
418  elif args.force_cpp_merger:
419  lhe_merger = ExternalCppLHEMerger(input_files, args.output_file)
420  else:
421  lhe_merger = DefaultLHEMerger(
422  input_files, args.output_file, bypass_check=args.bypass_check)
423 
424  # Do merging
425  lhe_merger.merge()
426 
427 
def main(argv=None)
Definition: mergeLHE.py:328
def number_events(input_file, output_file=None, offset=0)
static std::string join(char **cmd)
Definition: RemoteFile.cc:21