CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
cmsswPreprocessor.py
Go to the documentation of this file.
1 import os
2 import sys
3 import re
4 import imp
5 import timeit
6 import subprocess
7 from math import ceil
8 from PhysicsTools.HeppyCore.framework.config import CFG
9 from PhysicsTools.Heppy.utils.edmUtils import edmFileLs
11  def __init__(self,configFile,command="cmsRun", addOrigAsSecondary=True, prefetch=False, options={}) :
12  self.configFile=configFile
13  self.command=command
14  self.addOrigAsSecondary=addOrigAsSecondary
15  self.prefetch=prefetch
16  self.garbageFiles=[]
17  self.options=options
18 
19  def prefetchOneXrootdFile(self,fname):
20  tmpdir = os.environ['TMPDIR'] if 'TMPDIR' in os.environ else "/tmp"
21  rndchars = "".join([hex(ord(i))[2:] for i in os.urandom(8)])
22  localfile = "%s/%s-%s.root" % (tmpdir, os.path.basename(fname).replace(".root",""), rndchars)
23  try:
24  print "Fetching %s to local path %s " % (fname,localfile)
25  start = timeit.default_timer()
26  subprocess.check_output(["xrdcp","-f","-N",fname,localfile])
27  print "Time used for transferring the file locally: %s s" % (timeit.default_timer() - start)
28  return (localfile,True)
29  except:
30  print "Could not save file locally, will run from remote"
31  if os.path.exists(localfile): os.remove(localfile) # delete in case of incomplete transfer
32  return (fname,False)
33  def maybePrefetchFiles(self,component):
34  newfiles = []
35  component._preprocessor_tempFiles = []
36  for fn in component.files:
37  if self.prefetch and fn.startswith("root://"):
38  (newfile,istemp) = self.prefetchOneXrootdFile(fn)
39  newfiles.append(newfile)
40  if istemp:
41  component._preprocessor_tempFiles.append(newfile)
42  else:
43  newfiles.append(fn)
44  component.files = newfiles
45  def endLoop(self,component):
46  for fname in component._preprocessor_tempFiles:
47  print "Removing local cache file ",fname
48  os.remove(fname)
49  component._preprocessor_tempFiles = []
50  def run(self,component,wd,firstEvent,nEvents):
51  if firstEvent != 0: raise RuntimeError("The preprocessor can't skip events at the moment")
52  fineSplitIndex, fineSplitFactor = getattr(component, 'fineSplit', (1,1))
53  if fineSplitFactor > 1:
54  if len(component.files) != 1:
55  raise RuntimeError("Any component with fineSplit > 1 is supposed to have just a single file, while %s has %s" % (component.name, component.files))
56  evtsInFile = edmFileLs(component.files[0])['events']
57  if nEvents in (None, -1) or nEvents > evtsInFile: nEvents = evtsInFile
58  nEvents = int(ceil(nEvents/float(fineSplitFactor)))
59  firstEvent = fineSplitIndex * nEvents
60  # Now we will run on these events, and the output will contain only those
61  # Thus, we switch off fine-split in the component
62  component.fineSplit = (1,1)
63  if nEvents is None:
64  nEvents = -1
65  self.maybePrefetchFiles(component)
66  cmsswConfig = imp.load_source("cmsRunProcess",os.path.expandvars(self.configFile))
67  inputfiles= []
68  for fn in component.files :
69  if not re.match("file:.*",fn) and not re.match("root:.*",fn) :
70  fn="file:"+fn
71  inputfiles.append(fn)
72 
73  # Four cases:
74  # - no options, cmsswConfig with initialize function
75  # run initialize with default parameters
76  # - filled options, cmsswConfig with initialize function
77  # pass on options to initialize
78  # - no options, classic cmsswConfig
79  # legacy mode
80  # - filled options, classic cmsswConfig
81  # legacy mode but warn that options are not passed on
82 
83  if hasattr(cmsswConfig, "initialize"):
84  if len(self.options) == 0:
85  cmsswConfig.process = cmsswConfig.initialize()
86  else:
87  cmsswConfig.process = cmsswConfig.initialize(**self.options)
88  else:
89  if len(self.options) == 0:
90  pass
91  else:
92  print "WARNING: cmsswPreprocessor received options but can't pass on to cmsswConfig"
93 
94  cmsswConfig.process.source.fileNames = inputfiles
95  # cmsRun will not create the output file if maxEvents==0, leading to crash of the analysis downstream.
96  # Thus, we set nEvents = 1 if the input file is empty (the output file will be empty as well).
97  cmsswConfig.process.maxEvents.input = 1 if (fineSplitFactor>1 and nEvents==0) else nEvents
98  cmsswConfig.process.source.skipEvents = cmsswConfig.cms.untracked.uint32(0 if (fineSplitFactor>1 and nEvents==0) else firstEvent)
99  #fixme: implement skipEvent / firstevent
100 
101  outfilename=wd+"/cmsswPreProcessing.root"
102  # for outName in cmsswConfig.process.endpath.moduleNames():
103  for module in cmsswConfig.process.endpaths.viewvalues():
104  for outName in module.moduleNames():
105  out = getattr(cmsswConfig.process,outName)
106  if not hasattr(out,"fileName"): continue
107  out.fileName = outfilename
108 
109  if not hasattr(component,"options"):
110  component.options = CFG(name="postCmsrunOptions")
111  #use original as primary and new as secondary
112  #component.options.inputFiles= component.files
113  #component.options.secondaryInputFiles=[outfilename]
114 
115  #use new as primary and original as secondary
116  if self.addOrigAsSecondary:
117  component.options.secondaryInputFiles= component.files
118  component.options.inputFiles=[outfilename]
119  component.files=[outfilename]
120 
121  configfile=wd+"/cmsRun_config.py"
122  f = open(configfile, 'w')
123  f.write(cmsswConfig.process.dumpPython())
124  f.close()
125  runstring="%s %s >& %s/cmsRun.log" % (self.command,configfile,wd)
126  print "Running pre-processor: %s " %runstring
127  ret=os.system(runstring)
128  if ret != 0:
129  print "CMSRUN failed"
130  exit(ret)
131  return component
def edmFileLs
Definition: edmUtils.py:3
static std::string join(char **cmd)
Definition: RemoteFile.cc:18