ATLAS Offline Software
Gen_tf.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 
3 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
4 #
5 """
6 # Run event generation and produce an EVNT file.
7 """
8 
9 import os, sys, time, shutil
10 from PyJobTransforms.trfLogger import msg
11 from PyJobTransforms.transform import transform
12 from PyJobTransforms.trfExe import athenaExecutor
13 from PyJobTransforms.trfArgs import addAthenaArguments
14 from PyJobTransforms.trfDecorators import stdTrfExceptionHandler, sigUsrStackTrace
15 from EvgenJobTransforms.evgenTrfArgs import addStdEvgenArgs
16 
17 
19 ListOfDefaultPositionalKeys=['--AMIConfig', '--AMITag', '--argJSON', '--asetup', '--athena', '--athenaMPMergeTargetSize', '--athenaopts', '--attempt', '--checkEventCount', '--command', '--dumpJSON', '--dumpPickle', '--ecmEnergy', '--env', '--eventAcceptanceEfficiency', '--evgenJobOpts', '--execOnly', '--fileValidation', '--firstEvent', '--ignoreErrors', '--ignoreFiles', '--ignorePatterns', '--imf', '--inputEVNT_PreFile', '--inputFileValidation', '--inputGenConfFile', '--inputGeneratorFile', '--jobConfig', '--jobid', '--maxEvents', '--orphanKiller', '--outputEVNTFile', '--outputEVNT_PreFile', '--outputEvtFile', '--outputFileValidation', '--outputNTUP_TRUTHFile', '--outputTXTFile', '--parallelFileValidation', '--postExec', '--postInclude', '--preExec', '--preInclude', '--wprintEvts', '--randomSeed', '--reportName', '--reportType', '--rivetAnas', '--runNumber', '--showGraph', '--showPath', '--showSteps', '--skipEvents', '--skipFileValidation', '--skipInputFileValidation', '--skipOutputFileValidation', '--steering', '--taskid', '--tcmalloc', '--valgrind', '--valgrindbasicopts', '--valgrindextraopts', '--lheOnly', '--localPath', '--cleanOut', '--saveList']
20 
21 class EvgenExecutor(athenaExecutor):
22  "Specialised trf executor class for event generation jobs"
23  def __init__(self, name="generate", skeleton=None, skeletonCA=None, substep=None, inData=set(), outData=set()):
24  athenaExecutor.__init__(self, name=name, skeletonFile=skeleton, skeletonCA=skeletonCA,
25  substep=substep, inputEventTest=False, tryDropAndReload=False,
26  inData=inData, outData=outData)
27 
28  def preExecute(self, input=set(), output=set()):
29  "Get input tarball, unpack and set up env if an evgenJobOpts arg was provided."
30 
31 
32  super(EvgenExecutor, self).preExecute(input, output)
33 
34  def expand_if_archive(filename):
35  "Function to expand a file if it is a zip archive or tarball"
36  if ".tar" in filename:
37  import tarfile
38  with tarfile.open(filename) as tf:
39  tf.extractall()
40  elif filename.endswith(".zip"):
41  import zipfile
42  zf = zipfile.ZipFile(filename)
43  zf.extractall()
44  zf.close()
45 
47  return [name for name in os.listdir(a_dir)
48  if os.path.isdir(os.path.join(a_dir, name))]
49 
50 
52  os.environ['LOCAL_INSTALL_DIR'] = (os.environ['JOBOPTSEARCHPATH']).split(":")[0]
53  if os.path.exists('/cvmfs/atlas.cern.ch/repo/sw/Generators/MCJobOptions/common'):
54  CommonCvmfsDir = '/cvmfs/atlas.cern.ch/repo/sw/Generators/MCJobOptions/common'
55  os.environ["JOBOPTSEARCHPATH"] = CommonCvmfsDir+":"+os.environ["JOBOPTSEARCHPATH"]
56  if os.path.exists('/cvmfs/atlas.cern.ch/repo/sw/Generators/MCJobOptions/common/MadGraphControl/dat/'):
57  datCvmfsDir = '/cvmfs/atlas.cern.ch/repo/sw/Generators/MCJobOptions/common/MadGraphControl/dat/'
58  os.environ["DATAPATH"] = datCvmfsDir+":"+os.environ["DATAPATH"]
59 # dsidparam = (self._trf.argdict["jobConfig"].value).values()[0][0]
60  dsidpar = (self._trf.argdict["jobConfig"].value).values()
61  dsidparam = list(dsidpar)[0][0]
62  # Adding cvmfs path to JOBOPTSEARCHPATH
63  if os.path.exists('/cvmfs/atlas.cern.ch/repo/sw/Generators/MCJobOptions/'):
64  BaseCvmfsPath = "/cvmfs/atlas.cern.ch/repo/sw/Generators/MCJobOptions/"
65 
66  if dsidparam.isdigit() and (len(dsidparam)==6 or len(dsidparam)==7):
67  #only dsid is provided, add cvmfs folder like 123xxx to JOBOPTSEARCHPATH
68  Jodir = dsidparam[:3]+'xxx'
69  if len(dsidparam)==7:
70  Jodir = dsidparam[0] + '/' + dsidparam[:4]+'xxx'
71  cwdir = os.getcwd()
72  cwd_ful = os.path.join(cwdir, dsidparam)
73  if (os.path.isdir(cwd_ful)):
74  os.environ["JOBOPTSEARCHPATH"] = cwd_ful+":"+os.environ["JOBOPTSEARCHPATH"]
75  os.environ["DATAPATH"] = cwd_ful+":"+os.environ["DATAPATH"]
76  else:
77  cwd_Jodir = os.path.join(cwdir,Jodir)
78  cwd_Jodir_ful = os.path.join(cwd_Jodir,dsidparam)
79  if (os.path.isdir(cwd_Jodir_ful)):
80  os.environ["JOBOPTSEARCHPATH"] = cwd_Jodir_ful+":"+os.environ["JOBOPTSEARCHPATH"]
81  os.environ["DATAPATH"] = cwd_Jodir_ful+":"+os.environ["DATAPATH"]
82  else:
83  if (os.path.isdir(BaseCvmfsPath)):
84  JoCvmfsPath = os.path.join(BaseCvmfsPath, Jodir)
85  JoCvmfsPath_ful = os.path.join(JoCvmfsPath, dsidparam)
86  os.environ["JOBOPTSEARCHPATH"] = JoCvmfsPath_ful+":"+os.environ["JOBOPTSEARCHPATH"]
87  os.environ["DATAPATH"] = JoCvmfsPath_ful+":"+os.environ["DATAPATH"]
88  else:
89  msg.error("No access to JOs cvmfs location. JOs should be placed in working directory or full path should be given.")
90  raise RuntimeError("JOs not found - no cvmfs access")
91  else: #Suppose full path of dsid folder is provided(/afs/.../123xxx/123456), add cvmfs floder and local path(/afs/.../123xxx) to JOBOPTSEARCHPATH
92  if dsidparam.startswith("Test"): # for testing
93  for token in (os.environ['JOBOPTSEARCHPATH']).split(":"):
94  if "jobOptions" in token:
95  search_token = token
96  break
97  search_token += "/EvgenJobTransforms/EvgenTest/" + dsidparam.split("Test")[-1]
98  os.environ["JOBOPTSEARCHPATH"] = search_token+":"+os.environ["JOBOPTSEARCHPATH"]
99  os.environ["DATAPATH"] = search_token+":"+os.environ["DATAPATH"]
100  elif (os.path.isdir(dsidparam)):
101  os.environ["JOBOPTSEARCHPATH"] = dsidparam+":"+os.environ["JOBOPTSEARCHPATH"]
102  os.environ["DATAPATH"] = dsidparam+":"+os.environ["DATAPATH"]
103  else:
104  msg.error("JOs not found, please check = '%s'" % dsidparam)
105  raise RuntimeError("JOs not found")
106 
107  msg.info("Using JOBOPTSEARCHPATH = '%s'" % os.environ["JOBOPTSEARCHPATH"])
108  msg.info("Using DATAPATH = '%s'" % os.environ["DATAPATH"])
109 
110  if "evgenJobOpts" in self._trf.argdict:
111  tarball = self._trf.argdict["evgenJobOpts"].value
112 
114  if tarball.startswith("http"):
115  url = tarball
116  tarball = os.basename(tarball)
117  else:
118  url = "http://cern.ch/atlas-computing/links/kitsDirectory/EvgenJobOpts/" + tarball
119 
120  if not os.path.exists(tarball):
121  from EvgenJobTransforms.download import downloadUsingProxy
122  status, output = downloadUsingProxy(url)
123  if status != 0:
124  raise EnvironmentError('Error downloading tarball %s. Downloader reports: %s' % (tarball, output))
125  msg.info('Evgen tarball download success: %s' % output)
126 
127  expand_if_archive(tarball)
128 
130 
131  # copy config files to cwd
132  FIRST_DIR = (os.environ['JOBOPTSEARCHPATH']).split(":")[0]
133  configFiles = [f for f in os.listdir(FIRST_DIR) if ( "GRID" in f)]
134  confFile=None
135  if len(configFiles) == 1:
136  confFile = os.path.join(FIRST_DIR, configFiles[0])
137  elif len(configFiles) >1:
138  msg.info("more then one gridpack ! ")
139  if "--ecmEnergy" in str(sys.argv[1:]):
140  split_args=str(sys.argv[1:]).split("ecmEnergy=",1)[1]
141  ener_GeV=split_args.split(",")[0].strip("\'")
142  energy=str(float(ener_GeV)/1000.0).replace('.','p').strip(" =0\p']")
143  msg.info("Should be used gridpack for energy "+energy)
144  else:
145  energy="13"
146  for x in configFiles:
147  gridS="mc_"+energy+"TeV"
148  msg.info("Gridpack should start from "+gridS)
149  if x.startswith(gridS):
150  confFile = os.path.join(FIRST_DIR, x)
151  msg.info("using gridpack = "+confFile)
152  if confFile is None:
153  msg.error("No *GRID* config files, for requested energy = '%s' please check = '%s'" %(energy,dsidparam))
154 
155  if confFile is not None:
156  expand_if_archive(confFile)
157 # os.system("cp %s ." % confFile)
158  msg.info("Configuration input gridpack found " + confFile)
159 
160  #Expand if a tarball is found in local directory
161  loc_files = os.listdir(os.getcwd())
162  for loc_file in loc_files:
163  if "GRID" not in loc_file:
164  expand_if_archive(loc_file)
165 
166 
167  if "inputGeneratorFile" in self._trf.argdict:
168 # expand_if_archive(self._trf.argdict["inputGeneratorFile"].value)
169  myinputfiles = self._trf.argdict["inputGeneratorFile"].value
170  genInputFiles = myinputfiles.split(',')
171  for file in genInputFiles:
172  expand_if_archive(file)
173  if "inputGenConfFile" in self._trf.argdict:
174  expand_if_archive(self._trf.argdict["inputGenConfFile"].value)
175 
176 def move_files(main_dir,tmp_dir,whitelist):
177  files = os.listdir(tmp_dir)
178  files.sort()
179  for f in files:
180  for i in whitelist:
181  if i in f:
182  src = tmp_dir+"/"+f
183  dest = main_dir+"/"+f
184  os.rename(src,dest)
185  break
186 
187 
189  exeSet = set()
190  msg.info("Transform arguments %s" % sys.argv[1:])
191  if "--outputEVNTFile" in str(sys.argv[1:]):
192  exeSet.add(EvgenExecutor(name="generate", skeleton="EvgenJobTransforms/skel.GENtoEVGEN.py", skeletonCA="EvgenJobTransforms.GENtoEVGEN_Skeleton", inData=["inNULL"], outData=["YODA", "EVNT", "EVNT_Pre", "TXT"]))
193  msg.info("Output EVNT file")
194  elif "--outputYODAFile" in str(sys.argv[1:]):
195  exeSet.add(EvgenExecutor(name="generate", skeleton="EvgenJobTransforms/skel.GENtoEVGEN.py", inData=["inNULL"], outData=["YODA", "TXT"]))
196  msg.info("Output EVNT file")
197  elif "--outputTXTFile" in str(sys.argv[1:]):
198  exeSet.add(EvgenExecutor(name="generate", skeleton="EvgenJobTransforms/skel.GENtoTXT.py", inData=["inNULL"], outData=["TXT"]))
199  msg.info("Output TXT file")
200  else:
201  msg.error("Output cannot be recognised")
202 
203  exeSet.add(EvgenExecutor(name="afterburn", skeleton="EvgenJobTransforms/skel.ABtoEVGEN.py", inData=["EVNT_Pre"], outData=["EVNT"]))
204  exeSet.add(athenaExecutor(name = "AODtoDPD", skeletonFile = "PATJobTransforms/skeleton.AODtoDPD_tf.py",
205  substep = "a2d", inData = ["EVNT"], outData = ["NTUP_TRUTH"], perfMonFile = "ntuple_AODtoDPD.pmon.gz"))
206  exeSet.add(athenaExecutor(name = 'EVNTtoHEPMC', skeletonCA = 'EvgenJobTransforms.EVNTtoHEPMC_Skeleton',
207  substep = "a2d", perfMonFile = 'ntuple.pmon.gz', inData=['EVNT'], outData=['Evt']))
208  trf = transform(executor=exeSet)
209  addAthenaArguments(trf.parser, maxEventsDefaultSubstep='all')
210  addStdEvgenArgs(trf.parser)
211  return trf
212 
213 
214 @stdTrfExceptionHandler
215 @sigUsrStackTrace
216 def main():
217  msg.info("This is %s" % sys.argv[0])
218 
219  main_dir = os.getcwd()
220  trf = getTransform()
221  trf.parseCmdLineArgs(sys.argv[1:])
222  if (("cleanOut" in trf.argdict) and (trf.argdict["cleanOut"].value != 0)):
223  name_tmpdir = "tmprun"
224  tmp_dir = os.path.join(main_dir, name_tmpdir)
225  if os.path.isdir(tmp_dir):
226  shutil.rmtree(tmp_dir, ignore_errors=True)
227  os.mkdir("tmprun")
228  os.chdir("tmprun")
229  tmp_dir = os.getcwd()
230  whitelist_in = ['MC','group','TXT']
231  move_files(tmp_dir,main_dir,whitelist_in)
232 
233  trf.execute()
234  trf.generateReport()
235  msg.info("%s stopped at %s, trf exit code %d" % (sys.argv[0], time.asctime(), trf.exitCode))
236 
237 
238 # read files/dirs that should be saved and if present in cwd - remove
239 
240  if (("cleanOut" in trf.argdict) and (trf.argdict["cleanOut"].value!=0)):
241  whitelist_out = ['log.generate','.root']
242  if "outputTXTFile" in trf.argdict:
243  whitelist_out.append('TXT')
244  if "saveList" in trf.argdict:
245  saveList_dic= trf.argdict["saveList"].value
246  saveList_str= str(saveList_dic)
247  saveList_str=saveList_str[10:-3]
248  saveList= saveList_str.split(",")
249  for item in saveList:
250  test_ex = os.path.join(main_dir,str(item))
251  if os.path.isdir(test_ex):
252  shutil.rmtree(test_ex, ignore_errors=True)
253  elif os.path.isfile(test_ex):
254  os.remove(test_ex)
255  if not saveList[0].isdigit():
256  whitelist_out=whitelist_out+saveList
257 
258  move_files(main_dir,tmp_dir,whitelist_out)
259  os.chdir(main_dir)
260  if "saveList" not in trf.argdict:
261  shutil.rmtree(tmp_dir, ignore_errors=True)
262  elif not saveList[0].isdigit():
263  shutil.rmtree(tmp_dir, ignore_errors=True)
264 # if cleanOut is not defined and multipleinput preset, remove the merged file
265  elif ("inputGeneratorFile" in trf.argdict):
266  myinputfiles = trf.argdict["inputGeneratorFile"].value
267  genInputFiles = myinputfiles.split(',')
268  numberOfFiles = len(genInputFiles)
269  merge_file = 'merged_lhef._0.events'
270  if((numberOfFiles>1) and (os.path.exists(merge_file))):
271  os.remove(merge_file)
272 #
273  if (("lheOnly" in trf.argdict ) and (trf.argdict["lheOnly"].value == 1)):
274  outputName = ''.join(trf.argdict["outputEVNTFile"].value)
275  os.remove(outputName)
276  sys.exit(trf.exitCode)
277 
278 
279 # TODO: Open resulting EVNT file to extract cross-section, generator names+versions, etc. from the HepMC::GenRun or whatever... in an executor postExecute?
280 
281 
282 if __name__ == "__main__":
283  main()
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
Gen_tf.move_files
def move_files(main_dir, tmp_dir, whitelist)
Definition: Gen_tf.py:176
python.jo_proxy.get_immediate_subdirectories
def get_immediate_subdirectories(a_dir)
Definition: jo_proxy.py:6
python.Bindings.values
values
Definition: Control/AthenaPython/python/Bindings.py:805
Gen_tf.getTransform
def getTransform()
Definition: Gen_tf.py:188
python.trfArgs.addAthenaArguments
def addAthenaArguments(parser, maxEventsDefaultSubstep='first', addValgrind=True, addPerfMon=True, addVTune=True)
Options related to running athena in general TODO: Some way to mask certain options (perExec,...
Definition: trfArgs.py:59
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
Gen_tf.EvgenExecutor.preExecute
def preExecute(self, input=set(), output=set())
Definition: Gen_tf.py:28
python.download.downloadUsingProxy
def downloadUsingProxy(url, filename=None)
Definition: download.py:5
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
Gen_tf.EvgenExecutor.__init__
def __init__(self, name="generate", skeleton=None, skeletonCA=None, substep=None, inData=set(), outData=set())
Definition: Gen_tf.py:23
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
PyJobTransforms.trfExe
Transform execution functions.
python.evgenTrfArgs.addStdEvgenArgs
def addStdEvgenArgs(parser)
Definition: evgenTrfArgs.py:5
PyJobTransforms.trfLogger
Logging configuration for ATLAS job transforms.
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
PyJobTransforms.transform
Main package for new style ATLAS job transforms.
str
Definition: BTagTrackIpAccessor.cxx:11
readCCLHist.float
float
Definition: readCCLHist.py:83
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
Gen_tf.EvgenExecutor
Definition: Gen_tf.py:21
Gen_tf.main
def main()
Definition: Gen_tf.py:216