From 4b6d2fba3f623007648c184fcf75d71e4eb75b7c Mon Sep 17 00:00:00 2001 From: Ewelina Maria Lobodzinska <ewelina.maria.lobodzinska@cern.ch> Date: Wed, 23 Dec 2020 15:50:32 +0000 Subject: [PATCH] update gen_tf.py and skel.GENtoEVGEN.py to include the most recent modifications introduced for rel. 21.6 --- Generators/EvgenJobTransforms/CMakeLists.txt | 2 +- .../EvgenJobTransforms/scripts/Gen_tf.py | 34 +++++- .../share/skel.GENtoEVGEN.py | 104 +++++++++++++++--- .../EvgenJobTransforms/share/skel.GENtoTXT.py | 69 ++++++++---- 4 files changed, 162 insertions(+), 47 deletions(-) diff --git a/Generators/EvgenJobTransforms/CMakeLists.txt b/Generators/EvgenJobTransforms/CMakeLists.txt index 8736b66f00e..4b9ece44306 100644 --- a/Generators/EvgenJobTransforms/CMakeLists.txt +++ b/Generators/EvgenJobTransforms/CMakeLists.txt @@ -6,4 +6,4 @@ atlas_subdir( EvgenJobTransforms ) # Install files from the package: atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} ) atlas_install_joboptions( share/*.py ) -atlas_install_runtime( scripts/*.py ) +atlas_install_runtime( scripts/*.py share/file/*.txt ) diff --git a/Generators/EvgenJobTransforms/scripts/Gen_tf.py b/Generators/EvgenJobTransforms/scripts/Gen_tf.py index ee7ba47953f..91bd3d84c4f 100755 --- a/Generators/EvgenJobTransforms/scripts/Gen_tf.py +++ b/Generators/EvgenJobTransforms/scripts/Gen_tf.py @@ -118,19 +118,39 @@ class EvgenExecutor(athenaExecutor): # copy config files to cwd FIRST_DIR = (os.environ['JOBOPTSEARCHPATH']).split(":")[0] configFiles = [f for f in os.listdir(FIRST_DIR) if ( "GRID" in f)] + confFile=None if len(configFiles) == 1: confFile = os.path.join(FIRST_DIR, configFiles[0]) expand_if_archive(confFile) msg.info('Configuration input found: %s' % confFile) elif len(configFiles) >1: - msg.error("Too many *GRID* config files, please check = '%s'" % dsidparam) + msg.info("more then one gridpack ! ") + if "--ecmEnergy" in str(sys.argv[1:]): + ener=str(sys.argv[1:]).split("ecmEnergy",1)[1] + energy=str(ener)[:4].strip(" =0\']") + printfunc("Should be used gridpack for energy "+energy) + else: + energy="13" + for x in configFiles: + gridS="mc_"+energy+"TeV" + printfunc("Gridpack should start from "+gridS) + if x.startswith(gridS): + confFile = os.path.join(FIRST_DIR, x) + msg.info("using gridpack = "+confFile) + if confFile is None: + msg.error("No *GRID* config files, for requested energy = '%s' please check = '%s'" %(energy,dsidparam)) + + if confFile is not None: + expand_if_archive(confFile) +# os.system("cp %s ." % confFile) + printfunc("Configuration input gridpack found " + confFile) #Expand if a tarball is found in local directory loc_files = os.listdir(os.getcwd()) - for loc_file in loc_files: - expand_if_archive(loc_file) - - + for loc_file in loc_files: + if "GRID" not in loc_file: + expand_if_archive(loc_file) + ## Expand tarball input event and generator conf files, if provided if "inputGeneratorFile" in self._trf.argdict: # expand_if_archive(self._trf.argdict["inputGeneratorFile"].value) @@ -159,6 +179,10 @@ def getTransform(): if "--outputEVNTFile" in str(sys.argv[1:]): exeSet.add(EvgenExecutor(name="generate", skeleton="EvgenJobTransforms/skel.GENtoEVGEN.py", inData=["inNULL"], outData=["EVNT", "EVNT_Pre", "TXT" ])) msg.info("Output EVNT file") + elif "--outputYODAFile" in str(sys.argv[1:]): + exeSet.add(EvgenExecutor(name="generate", skeleton="EvgenJobTransforms/skel.GENtoEVGEN.py", inData=["inNULL"], outData=["outNULL", "TXT" +])) + msg.info("Output EVNT file") elif "--outputTXTFile" in str(sys.argv[1:]): exeSet.add(EvgenExecutor(name="generate", skeleton="EvgenJobTransforms/skel.GENtoTXT.py", inData=["inNULL"], outData=["TXT"])) msg.info("Output TXT file") diff --git a/Generators/EvgenJobTransforms/share/skel.GENtoEVGEN.py b/Generators/EvgenJobTransforms/share/skel.GENtoEVGEN.py index 6b5c098e200..beae3cff244 100644 --- a/Generators/EvgenJobTransforms/share/skel.GENtoEVGEN.py +++ b/Generators/EvgenJobTransforms/share/skel.GENtoEVGEN.py @@ -79,11 +79,21 @@ if hasattr(runArgs, "runNumber"): if hasattr(runArgs, "inputGenConfFile"): raise RuntimeError("inputGenConfFile is invalid !! Gridpacks and config. files/links to be put into DSID directory ") + +if hasattr(runArgs, "inputGeneratorFile"): + evgenLog.info("inputGeneratorFile used " + runArgs.inputGeneratorFile) + +if hasattr(runArgs, "outputYODAFile"): + evgenLog.info("outputYODAFile specified " + runArgs.outputYODAFile) ## Ensure that an output name has been given # TODO: Allow generation without writing an output file (if outputEVNTFile is None)? if not hasattr(runArgs, "outputEVNTFile") and not hasattr(runArgs, "outputEVNT_PreFile"): - raise RuntimeError("No output evgen EVNT or EVNT_Pre file provided.") + if hasattr(runArgs, "outputYODAFile"): + evgenLog.info("No outputEVNTFile specified but outputYODAFile is used") + evgenLog.info("Will run GENtoEVGEN without saving the output EVNT file, asuming a valid outputYODAFile will be produced") + else: + raise RuntimeError("No output evgen EVNT or EVNT_Pre file provided.") ## Ensure that mandatory args have been supplied (complain before processing the includes) if not hasattr(runArgs, "ecmEnergy"): @@ -166,6 +176,8 @@ if hasattr(runArgs, "rivetAnas"): anaSeq += Rivet_i() anaSeq.Rivet_i.Analyses = runArgs.rivetAnas anaSeq.Rivet_i.DoRootHistos = True + if hasattr(runArgs, "outputYODAFile"): + anaSeq.Rivet_i.HistoFile = runArgs.outputYODAFile ##============================================================== ## Pre- and main config parsing @@ -249,6 +261,9 @@ include(jofile) ## Announce start of JO checking evgenLog.debug("****************** CHECKING EVGEN CONFIGURATION *****************") +if hasattr(runArgs,'inputGeneratorFile') and int(evgenConfig.inputFilesPerJob) == 0 : + evgenConfig.inputFilesPerJob = 1 + ## Print out options for opt in str(evgenConfig).split(os.linesep): evgenLog.info(opt) @@ -311,15 +326,29 @@ rounding = 0 if hasattr(runArgs,'inputGeneratorFile') and ',' in runArgs.inputGeneratorFile: multiInput = runArgs.inputGeneratorFile.count(',')+1 else: multiInput = 0 - -if evgenConfig.nEventsPerJob < 1: - raise RunTimeError("evgenConfig.nEventsPerJob must be at least 1") + +# check if default nEventsPerJob used +if not evgenConfig.nEventsPerJob: + evgenLog.info('#############################################################') + evgenLog.info(' !!!! no nEventsPerJob set !!! The default 10000 used. !!! ') + evgenLog.info('#############################################################') +else: + evgenLog.info(' nEventsPerJob set to ' + str(evgenConfig.nEventsPerJob) ) + +if evgenConfig.minevents > 0 : + raise RuntimeError("evgenConfig.minevents is obsolete and should be removed from the JOs") +elif evgenConfig.nEventsPerJob > 100000: + raise RuntimeError("evgenConfig.nEventsPerJob can be max. 100000") else: allowed_nEventsPerJob_lt1000 = [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000] msg = "evgenConfig.nEventsPerJob = %d: " % evgenConfig.nEventsPerJob - if evgenConfig.nEventsPerJob >= 1000 and evgenConfig.nEventsPerJob % 1000 != 0 and 10000 % evgenConfig.nEventsPerJob != 0 : - msg += "nEventsPerJob in range >= 1K must be a multiple of 1K and a divisor of 10K" + if evgenConfig.nEventsPerJob >= 1000 and evgenConfig.nEventsPerJob <=10000 and (evgenConfig.nEventsPerJob % 1000 != 0 or 10000 % +evgenConfig.nEventsPerJob != 0) : + msg += "nEventsPerJob in range [1K, 10K] must be a multiple of 1K and a divisor of 10K" + raise RuntimeError(msg) + elif evgenConfig.nEventsPerJob > 10000 and evgenConfig.nEventsPerJob % 10000 != 0: + msg += "nEventsPerJob >10K must be a multiple of 10K" raise RuntimeError(msg) elif evgenConfig.nEventsPerJob < 1000 and evgenConfig.nEventsPerJob not in allowed_nEventsPerJob_lt1000: msg += "nEventsPerJob in range <= 1000 must be one of %s" % allowed_nEventsPerJob_lt1000 @@ -331,9 +360,9 @@ else: if evgenConfig.keywords: ## Get the allowed keywords file from the JO package if possibe # TODO: Make the package name configurable - kwfile = "EvgenJobTransforms/evgenkeywords.txt" + kwfile = "evgenkeywords.txt" kwpath = None - for p in os.environ["JOBOPTSEARCHPATH"].split(":"): + for p in os.environ["DATAPATH"].split(":"): kwpath = os.path.join(p, kwfile) if os.path.exists(kwpath): break @@ -356,15 +385,15 @@ if evgenConfig.keywords: if officialJO: sys.exit(1) else: - evgenLog.warning("Could not find evgenkeywords.txt file %s in $JOBOPTSEARCHPATH" % kwfile) + evgenLog.warning("Could not find evgenkeywords.txt file %s in DATAPATH" % kwfile ) ## Check that the L1 and L2 keywords pairs are in the list of allowed words pairs (and exit if processing an official JO) if evgenConfig.categories: ## Get the allowed categories file from the JO package if possibe # TODO: Make the package name configurable - lkwfile = "EvgenJobTransforms/CategoryList.txt" + lkwfile = "CategoryList.txt" lkwpath = None - for p in os.environ["JOBOPTSEARCHPATH"].split(":"): + for p in os.environ["DATAPATH"].split(":"): lkwpath = os.path.join(p, lkwfile) if os.path.exists(lkwpath): break @@ -397,7 +426,7 @@ if evgenConfig.categories: if officialJO: sys.exit(1) else: - evgenLog.warning("Could not find CategoryList.txt file %s in $JOBOPTSEARCHPATH" % lkwfile) + evgenLog.warning("Could not find CategoryList.txt file %s in $DATAPATH" % lkwfile) ## Configure POOL streaming to the output EVNT format file from AthenaPoolCnvSvc.WriteAthenaPool import AthenaPoolOutputStream @@ -465,6 +494,38 @@ if hasattr(testSeq, "TestHepMC") and not gens_testhepmc(evgenConfig.generators): evgenLog.info("Removing TestHepMC sanity checker") del testSeq.TestHepMC +##============================================================= +## Check release number +##============================================================= +# Function to check blacklist (from Spyros'es logParser.py) +def checkBlackList(relFlavour,cache,generatorName) : + isError = None + with open('/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/common/BlackList_caches.txt') as bfile: + for line in bfile.readlines(): + if not line.strip(): + continue + # Blacklisted release flavours + badRelFlav=line.split(',')[0].strip() + # Blacklisted caches + badCache=line.split(',')[1].strip() + # Blacklisted generators + badGens=line.split(',')[2].strip() + + used_gens = ','.join(generatorName) + #Match Generator and release type e.g. AtlasProduction, MCProd + if relFlavour==badRelFlav and cache==badCache and re.search(badGens,used_gens) is not None: + if badGens=="": badGens="all generators" + isError=relFlavour+","+cache+" is blacklisted for " + badGens + return isError + return isError +## Announce start of JO checkingrelease number checking +evgenLog.debug("****************** CHECKING RELEASE IS NOT BLACKLISTED *****************") +rel = os.popen("echo $AtlasVersion").read() +rel = rel.strip() +errorBL = checkBlackList("AthGeneration",rel,gennames) +if (errorBL): + raise RuntimeError("This run is blacklisted for this generator, please use a different one !! "+ errorBL) +# evgenLog.warning("This run is blacklisted for this generator, please use a different one !! "+ errorBL ) ##============================================================== ## Handling of a post-include/exec args at the end of standard configuration @@ -659,12 +720,6 @@ else: raise RuntimeError("evgenConfig.inputfilecheck specified in %s, but generators %s do not require an input file" % (runArgs.jobConfig, str(gennames))) -## Check conf files, as above but for a different command line arg, and with omission allowed -if hasattr(runArgs, "inputGenConfFile") and runArgs.inputGenConfFile != "NONE": - if evgenConfig.inputconfcheck and not re.search(evgenConfig.inputconfcheck, runArgs.inputGenConfFile): - raise RuntimeError("inputGenConfFile=%s is incompatible with inputconfcheck (%s) in %s" % - (runArgs.inputGenConfFile, evgenConfig.inputconfcheck, runArgs.jobConfig)) - ## Do the aux-file copying if evgenConfig.auxfiles: from PyJobTransformsCore.trfutil import get_files @@ -683,6 +738,19 @@ def _checkattr(attr, required=False): return False return True +if hasattr(runArgs, "outputTXTFile"): + # counting the number of events in LHE output + with open(eventsFile) as f: + contents = f.read() + count_ev = contents.count("<event>") + printfunc("MetaData: %s = %s" % ("Number of produced LHE events ", count_ev)) +elif hasattr(runArgs, "inputGeneratorFile"): + # counting the number of events in LHE output + with open(eventsFile) as f: + contents = f.read() + count_ev = contents.count("<event>") + printfunc("MetaData: %s = %s" % ("Number of input LHE events ", count_ev)) + if _checkattr("description", required=True): msg = evgenConfig.description if _checkattr("notes"): diff --git a/Generators/EvgenJobTransforms/share/skel.GENtoTXT.py b/Generators/EvgenJobTransforms/share/skel.GENtoTXT.py index db20bad83f6..f213345143a 100644 --- a/Generators/EvgenJobTransforms/share/skel.GENtoTXT.py +++ b/Generators/EvgenJobTransforms/share/skel.GENtoTXT.py @@ -33,7 +33,7 @@ testSeq = acam.athMasterSeq.EvgenTestSeq ## NOTE: LogicalExpressionFilter is an algorithm, not a sequence from EvgenProdTools.LogicalExpressionFilter import LogicalExpressionFilter acam.athMasterSeq += LogicalExpressionFilter("EvgenFilterSeq") -filtSeq = acam.athMsterSeq.EvgenFilterSeq +filtSeq = acam.athMasterSeq.EvgenFilterSeq topSeq = acas.AlgSequence() anaSeq = topSeq topSeq += acas.AlgSequence("EvgenPostSeq") @@ -61,7 +61,7 @@ jobproperties.AthenaCommonFlags.AllowIgnoreConfigError = False ## Set up a standard logger from AthenaCommon.Logging import logging -evgenLog = logging.getLogger('Gen_tf_txt') +evgenLog = logging.getLogger('Gen_tf') ##============================================================== ## Run arg handling @@ -155,7 +155,7 @@ def OutputTXTFile(): ## Only permit one jobConfig argument for evgen: does more than one _ever_ make sense? if len(runArgs.jobConfig) != 1: - evgenLog.info("runArgs.jobConfig %s ", % runArgs.jobConfig) + evgenLog.info("runArgs.jobConfig " + runArgs.jobConfig) evgenLog.error("You must supply one and only one jobConfig file argument. It has to start from mc. and end with .py") sys.exit(1) @@ -169,7 +169,7 @@ evgenLog.info("dsid " + dsid) jofiles = [f for f in os.listdir(FIRST_DIR) if (f.startswith('mc') and f.endswith('.py'))] ## Only permit one JO file in each dsid folder if len(jofiles) !=1: - evgenLog.info("runArgs.jobConfig wrong %s ", % runArgs.jobConfig) + evgenLog.info("runArgs.jobConfig wrong " + runArgs.jobConfig) evgenLog.error("You must supply one and only one jobOption file in DSID directory. It has to start with mc. and end with .py") sys.exit(1) jofile = jofiles[0] @@ -277,21 +277,14 @@ rounding = 0 if hasattr(runArgs,'inputGeneratorFile') and ',' in runArgs.inputGeneratorFile: multiInput = runArgs.inputGeneratorFile.count(',')+1 else: multiInput = 0 + + if evgenConfig.nEventsPerJob < 1: - raise RunTimeError("evgenConfig.nEventsPerJob must be at least 0") -else: - allowed_nEventsPerJob_lt1000 = [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000] - msg = "evgenConfig.nEventsPerJob = %d: " % evgenConfig.nEventsPerJob - - if evgenConfig.nEventsPerJob >= 1000 and evgenConfig.nEventsPerJob % 1000 != 0 and 10000 % evgenConfig.nEventsPerJob != 0: - msg += "nEventsPerJob in range >= 1000 must be a multiple of 1000 and a divisor of 10000" - raise RuntimeError(msg) - elif evgenConfig.nEventsPerJob < 1000 and evgenConfig.nEventsPerJob not in allowed_nEventsPerJob_lt1000: - msg += "nEventsPerJob in range <= 1000 must be one of %s" % allowed_nEventsPerJob_lt1000 - raise RuntimeError(msg) - postSeq.CountHepMC.RequestedOutput = evgenConfig.nEventsPerJob if runArgs.maxEvents == -1 else runArgs.maxEvents - evgenLog.info('Requested output events '+str(postSeq.CountHepMC.RequestedOutput)) + raise RunTimeError("evgenConfig.nEventsPerJob must be at least 1") +else: + evgenLog.info("evgenConfig.nEventsPerJob = {}, but only {} (dummy) event(s) will be generated by Pythia8 for lhe-only production".format(evgenConfig.nEventsPerJob, postSeq.CountHepMC.RequestedOutput)) +### NB: postSeq.CountHepMC.RequestedOutput is set to 1 in LHEonly.py ## Check that the keywords list is not empty: if not evgenConfig.keywords: @@ -373,6 +366,9 @@ if evgenConfig.categories: evgenLog.warning("Could not find CategoryList.txt file %s in $JOBOPTSEARCHPATH" % lkwfile) ## Set the run numbers +dsid = os.path.basename(runArgs.jobConfig[0]) +if not dsid.isdigit(): + dsid = "999999" svcMgr.EventSelector.RunNumber = int(dsid) ## Include information about generators in metadata @@ -398,6 +394,39 @@ include("EvgenJobTransforms/Generate_ecmenergies.py") ## Process random seed arg and pass to generators include("EvgenJobTransforms/Generate_randomseeds.py") +##============================================================= +## Check release number +##============================================================= +# Function to check blacklist (from Spyros'es logParser.py) +def checkBlackList(relFlavour,cache,generatorName) : + isError = None + with open('/cvmfs/atlas.cern.ch/repo/sw/Generators/MC16JobOptions/common/BlackList_caches.txt') as bfile: + for line in bfile.readlines(): + if not line.strip(): + continue + # Blacklisted release flavours + badRelFlav=line.split(',')[0].strip() + # Blacklisted caches + badCache=line.split(',')[1].strip() + # Blacklisted generators + badGens=line.split(',')[2].strip() + + used_gens = ','.join(generatorName) + #Match Generator and release type e.g. AtlasProduction, MCProd + if relFlavour==badRelFlav and cache==badCache and re.search(badGens,used_gens) is not None: + if badGens=="": badGens="all generators" + isError=relFlavour+","+cache+" is blacklisted for " + badGens + return isError + return isError +## Announce start of JO checkingrelease nimber checking +evgenLog.debug("****************** CHECKING RELEASE IS NOT BLACKLISTED *****************") +rel = os.popen("echo $AtlasVersion").read() +rel = rel.strip() +errorBL = checkBlackList("AthGeneration",rel,gennames) +if (errorBL): +# evgenLog.warning("This run is blacklisted for this generator, please use a different one !! "+ errorBL ) + raise RuntimeError("This run is blacklisted for this generator, please use a different one !! "+ errorBL) + ## Add special config option (extended model info for BSM scenarios) svcMgr.TagInfoMgr.ExtraTagValuePairs += ["specialConfiguration", evgenConfig.specialConfig ] @@ -595,12 +624,6 @@ else: raise RuntimeError("evgenConfig.inputfilecheck specified in %s, but generators %s do not require an input file" % (runArgs.jobConfig, str(gennames))) -## Check conf files, as above but for a different command line arg, and with omission allowed -if hasattr(runArgs, "inputGenConfFile") and runArgs.inputGenConfFile != "NONE": - if evgenConfig.inputconfcheck and not re.search(evgenConfig.inputconfcheck, runArgs.inputGenConfFile): - raise RuntimeError("inputGenConfFile=%s is incompatible with inputconfcheck (%s) in %s" % - (runArgs.inputGenConfFile, evgenConfig.inputconfcheck, runArgs.jobConfig)) - ## Do the aux-file copying if evgenConfig.auxfiles: from PyJobTransformsCore.trfutil import get_files -- GitLab