3 Submits per run Primary Vertex Resoltion Alignment validation using the split vertex method,
6 submitPVResolutionJobs.py -i PVResolutionExample.ini -D /JetHT/Run2018C-TkAlMinBias-12Nov2019_UL2018-v2/ALCARECO
9 from __future__
import print_function
11 __author__ =
'Marco Musich'
12 __copyright__ =
'Copyright 2020, CERN CMS'
13 __credits__ = [
'Ernesto Migliore',
'Salvatore Di Guida']
14 __license__ =
'Unknown'
15 __maintainer__ =
'Marco Musich'
16 __email__ =
'marco.musich@cern.ch'
29 from subprocess
import Popen, PIPE
30 import multiprocessing
31 from optparse
import OptionParser
32 import os, shlex, shutil, getpass
33 import configparser
as ConfigParser
35 CopyRights =
'##################################\n'
36 CopyRights +=
'# submitPVVResolutioJobs.py #\n'
37 CopyRights +=
'# marco.musich@cern.ch #\n'
38 CopyRights +=
'# October 2020 #\n'
39 CopyRights +=
'##################################\n'
44 p = subprocess.Popen(*args, **kwargs)
45 stdout, stderr = p.communicate()
46 return p.returncode, stdout, stderr
51 """Check if GRID proxy has been initialized."""
54 with open(os.devnull,
"w")
as dump:
55 subprocess.check_call([
"voms-proxy-info",
"--exists"],
56 stdout = dump, stderr = dump)
57 except subprocess.CalledProcessError:
64 """Forward proxy to location visible from the batch system.
66 - `rundir`: directory for storing the forwarded proxy
70 print(
"Please create proxy via 'voms-proxy-init -voms cms -rfc'.")
73 local_proxy = subprocess.check_output([
"voms-proxy-info",
"--path"]).
strip()
74 shutil.copyfile(local_proxy, os.path.join(rundir,
".user_proxy"))
80 returns the list of list files associated with a given dataset for a certain run
83 cmd2 =
' dasgoclient -limit=0 -query \'file run='+blob[0]+
' dataset='+blob[1]+
'\''
84 q = Popen(cmd2 , shell=
True, stdout=PIPE, stderr=PIPE)
85 out, err = q.communicate()
86 outputList = out.decode().
split(
'\n')
93 """Writes 'job.submit' file in `path`.
95 - `path`: job directory
96 - `script`: script to be executed
97 - `proxy_path`: path to proxy (only used in case of requested proxy forward)
100 job_submit_template=
"""\
102 executable = {script:s}
103 output = {jobm:s}/{out:s}.out
104 error = {jobm:s}/{out:s}.err
105 log = {jobm:s}/{out:s}.log
106 transfer_output_files = ""
107 +JobFlavour = "{flavour:s}"
110 if proxy_path
is not None:
111 job_submit_template +=
"""\
112 +x509userproxy = "{proxy:s}"
115 job_submit_file = os.path.join(path,
"job_"+name+
".submit")
116 with open(job_submit_file,
"w")
as f:
117 f.write(job_submit_template.format(script = os.path.join(path,name+
"_$(ProcId).sh"),
118 out = name+
"_$(ProcId)",
119 jobm = os.path.abspath(path),
120 flavour =
"tomorrow",
124 return job_submit_file
129 """Expects something like
130 +-------+------+--------+--------+-------------------+------------------+
131 | nfill | nrun | nls | ncms | totdelivered(/fb) | totrecorded(/fb) |
132 +-------+------+--------+--------+-------------------+------------------+
133 | 73 | 327 | 142418 | 138935 | 19.562 | 18.036 |
134 +-------+------+--------+--------+-------------------+------------------+
135 And extracts the total recorded luminosity (/b).
146 output = subprocess.check_output([homedir+
"/.local/bin/brilcalc",
"lumi",
"-b",
"STABLE BEAMS",
"-u",
"/pb",
"--begin",
str(minRun),
"--end",
str(maxRun),
"--output-style",
"csv"])
148 warnings.warn(
'ATTENTION! Impossible to query the BRIL DB!')
152 print(
"INSIDE GET LUMINOSITY")
155 for line
in output.decode().
split(
"\n"):
156 if (
"#" not in line):
157 runToCache = line.split(
",")[0].
split(
":")[0]
158 lumiToCache = line.split(
",")[-1].
replace(
"\r",
"")
161 myCachedLumi[runToCache] = lumiToCache
171 with open(jsonfile,
'r')
as myJSON:
172 jsonDATA = json.load(myJSON)
173 return (run
in jsonDATA)
175 warnings.warn(
'ATTENTION! Impossible to find lumi mask! All runs will be used.')
182 for section
in config.sections():
183 dictionary[section] = {}
184 for option
in config.options(section):
185 dictionary[section][option] = config.get(section, option)
192 '''prepare the batch script, to run on HTCondor'''
193 script =
"""#!/bin/bash
194 source /afs/cern.ch/cms/caf/setup.sh
195 CMSSW_DIR={CMSSW_BASE_DIR}/src/Alignment/OfflineValidation/test
196 echo "the mother directory is $CMSSW_DIR"
197 export X509_USER_PROXY=$CMSSW_DIR/.user_proxy
198 #OUT_DIR=$CMSSW_DIR/harvest ## for local storage
200 LOG_DIR=$CMSSW_DIR/out
203 eval `scram runtime -sh`
205 cp -pr $CMSSW_DIR/cfg/PrimaryVertexResolution_{KEY}_{runindex}_cfg.py .
206 cmsRun PrimaryVertexResolution_{KEY}_{runindex}_cfg.py GlobalTag={GT} lumi={LUMITORUN} {REC} {EXT} >& log_{KEY}_run{runindex}.out
208 #for payloadOutput in $(ls *root ); do cp $payloadOutput $OUT_DIR/pvresolution_{KEY}_{runindex}.root ; done
209 for payloadOutput in $(ls *root ); do xrdcp -f $payloadOutput root://eoscms/$OUT_DIR/pvresolution_{KEY}_{runindex}.root ; done
210 tar czf log_{KEY}_run{runindex}.tgz log_{KEY}_run{runindex}.out
211 for logOutput in $(ls *tgz ); do cp $logOutput $LOG_DIR/ ; done
212 """.
format(CMSSW_BASE_DIR=theCMSSW_BASE,
217 GT=config[
'globaltag'],
218 EXT=
"external="+config[
'external']
if 'external' in config.keys()
else "",
219 REC=
"records="+config[
'records']
if 'records' in config.keys()
else "")
227 print(
"creating",out_path)
229 for dir
in out_path.split(
'/'):
230 newpath=os.path.join(newpath,dir)
232 if newpath.find(
'test_out') > 0:
233 command=
"eos mkdir "+newpath
234 p = subprocess.Popen(command,shell=
True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
235 (out, err) = p.communicate()
240 command2=
"/afs/cern.ch/project/eos/installation/cms/bin/eos.select ls "+out_path
241 p = subprocess.Popen(command2,shell=
True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
242 (out, err) = p.communicate()
251 desc=
"""This is a description of %prog."""
252 parser = OptionParser(description=desc,version=
'%prog version 0.1')
253 parser.add_option(
'-s',
'--submit', help=
'job submitted', dest=
'submit', action=
'store_true', default=
False)
254 parser.add_option(
'-j',
'--jobname', help=
'task name', dest=
'taskname', action=
'store', default=
'myTask')
255 parser.add_option(
'-i',
'--init', help=
'ini file', dest=
'iniPathName', action=
'store', default=
"default.ini")
256 parser.add_option(
'-b',
'--begin', help=
'starting point', dest=
'start', action=
'store', default=
'1')
257 parser.add_option(
'-e',
'--end', help=
'ending point', dest=
'end', action=
'store', default=
'999999')
258 parser.add_option(
'-D',
'--Dataset', help=
'dataset to run upon', dest=
'DATASET', action=
'store', default=
'/StreamExpressAlignment/Run2017F-TkAlMinBias-Express-v1/ALCARECO')
259 parser.add_option(
'-v',
'--verbose', help=
'verbose output', dest=
'verbose', action=
'store_true', default=
False)
260 parser.add_option(
'-u',
'--unitTest',help=
'unit tests?', dest=
'isUnitTest', action=
'store_true', default=
False)
261 (opts, args) = parser.parse_args()
264 print(
'\n'+CopyRights)
266 input_CMSSW_BASE = os.environ.get(
'CMSSW_BASE')
270 USER = os.environ.get(
'USER')
271 HOME = os.environ.get(
'HOME')
272 eosdir=os.path.join(
"/store/group/alca_trackeralign",USER,
"test_out",opts.taskname)
276 print(
"Not going to create EOS folder. -s option has not been chosen")
281 config = ConfigParser.ConfigParser()
282 config.read(opts.iniPathName)
283 except ConfigParser.MissingSectionHeaderError
as e:
284 raise WrongIniFormatError(e)
286 print(
"Parsed the following configuration \n\n")
288 pprint.pprint(inputDict)
291 raise SystemExit(
"\n\n ERROR! Could not parse any input file, perhaps you are submitting this from the wrong folder? \n\n")
300 print(
"\n\n Will run on the following runs: \n",runs)
302 if(
not os.path.exists(
"cfg")):
303 os.system(
"mkdir cfg")
304 os.system(
"mkdir BASH")
305 os.system(
"mkdir harvest")
306 os.system(
"mkdir out")
309 bashdir = os.path.join(cwd,
"BASH")
318 print(
"|| WARNING: won't run on any run, probably DAS returned an empty query,\n|| but that's fine because this is a unit test!")
323 raise Exception(
'Will not run on any run.... please check again the configuration')
329 pprint.pprint(myLumiDB)
331 lumimask = inputDict[
"Input"][
"lumimask"]
332 print(
"\n\n Using JSON file:",lumimask)
335 print(
"\n\n First run:",opts.start,
"last run:",opts.end)
338 if (
int(run)<
int(opts.start)
or int(run)>
int(opts.end)):
339 print(
"excluding run",run)
346 print(
"'======> taking run",run)
347 mytuple.append((run,opts.DATASET))
351 pool = multiprocessing.Pool(processes=20)
352 count = pool.map(getFilesForRun,mytuple)
353 file_info = dict(
zip(runs, count))
365 if (
int(run)<
int(opts.start)
or int(run)>
int(opts.end)):
366 print(
"excluding",run)
370 print(
"=====> excluding run:",run)
373 files = file_info[run]
378 listOfFiles=listOfFiles+
"\""+
str(ffile)+
"\","
384 if (run)
in myLumiDB:
385 theLumi = myLumiDB[run]
386 print(
"run",run,
" int. lumi:",theLumi,
"/pb")
388 print(
"=====> COULD NOT FIND LUMI, setting default = 1/pb")
390 print(
"run",run,
" int. lumi:",theLumi,
"/pb")
393 for key, value
in inputDict.items():
398 key = key.split(
":", 1)[1]
399 print(
"dealing with",key)
401 os.system(
"cp "+input_CMSSW_BASE+
"/src/Alignment/OfflineValidation/test/PrimaryVertexResolution_templ_cfg.py ./cfg/PrimaryVertexResolution_"+key+
"_"+run+
"_cfg.py")
402 os.system(
"sed -i 's|XXX_FILES_XXX|"+listOfFiles+
"|g' "+cwd+
"/cfg/PrimaryVertexResolution_"+key+
"_"+run+
"_cfg.py")
403 os.system(
"sed -i 's|XXX_RUN_XXX|"+run+
"|g' "+cwd+
"/cfg/PrimaryVertexResolution_"+key+
"_"+run+
"_cfg.py")
404 os.system(
"sed -i 's|YYY_KEY_YYY|"+key+
"|g' "+cwd+
"/cfg/PrimaryVertexResolution_"+key+
"_"+run+
"_cfg.py")
406 scriptFileName = os.path.join(bashdir,
"batchHarvester_"+key+
"_"+
str(count-1)+
".sh")
407 scriptFile = open(scriptFileName,
'w')
408 scriptFile.write(
batchScriptCERN(input_CMSSW_BASE,run,eosdir,theLumi,key,value))
413 for key, value
in inputDict.items():
417 key = key.split(
":", 1)[1]
422 os.system(
"chmod u+x "+bashdir+
"/*.sh")
423 submissionCommand =
"condor_submit "+job_submit_file
424 print(submissionCommand)
425 os.system(submissionCommand)
428 if __name__ ==
"__main__":