2 #include benchmark.config
4 # blame: Mikolaj Krzewicki, mkrzewic@cern.ch
5 # this script runs the CPass0/CPass1 train
6 # produced OCDB updates are local
10 #run in proper mode depending on the selection
11 if [[ $# -lt 1 ]]; then
12 if [[ ! "${0}" =~ "bash" ]]; then
14 echo " ${0} \"run\" productionID inputList configFile [extraOpts]"
15 echo "uses a batch system (SGE):"
16 echo " ${0} \"submit\" productionID inputList configFile [extraOpts]"
17 echo "extraOpts if non-empty override the config file, e.g.:"
18 echo " ${0} submit test1 benchmark.list benchmark.config runNumber=169123 nEvents=10"
23 #define some aliases - default is to call one of the functions directly
28 "CPass0") goCPass0 "$@";;
29 "CPass1") goCPass1 "$@";;
30 "MakeLocalOCDBaccessConfig") goMakeLocalOCDBaccessConfig "$@";;
31 "MergeCPass0") goMergeCPass0 "$@";;
32 "MergeCPass1") goMergeCPass1 "$@";;
33 "MakeFilteredTrees") goMakeFilteredTrees "$@";;
34 "MakeSummary") goMakeSummary "$@";;
35 "run") goSubmitMakeflow "$@";;
36 "submit") goSubmitBatch "$@";;
38 "GenerateMakeflow") goGenerateMakeflow "$@";;
39 "PrintValues") goPrintValues "$@";;
40 "CreateQAplots") goCreateQAplots "$@";;
41 "WaitForOutput") goWaitForOutput "$@";;
42 "Merge") goMerge "$@";;
52 #generate one raw chunk in current directory
53 SEED=${JOB_ID}${SGE_TASK_ID}
54 export CONFIG_SEED=${SEED}
58 if [[ -n ${pretend} ]]; then
62 if [[ -f sim.C && -f Config.C ]] ; then
63 time aliroot -b -q -x sim.C\(${runNumber},\"${OCDBpath}\",${nEventsim}\) >sim.log 2>&1
64 mv syswatch.log simwatch.log
81 if ! parseConfig ${configFile} "$@"; then return 1; fi
83 #record the working directory provided by the batch system
84 batchWorkingDirectory=${PWD}
86 #use the jobindex only if set and non-negative
87 if [[ -z ${jobindex} || ${jobindex} -lt 0 ]]; then
88 [[ -n "${LSB_JOBINDEX}" ]] && jobindex=${LSB_JOBINDEX}
89 [[ -n "${SGE_TASK_ID}" ]] && jobindex=${SGE_TASK_ID}
90 if [[ -z ${jobindex} ]]; then
96 [[ -z ${commonOutputPath} ]] && commonOutputPath=${PWD}
98 # This file signals that/if everything went fine
99 doneFileBase="cpass0.job${jobindex}.run${runNumber}.done"
100 [[ -n ${useProfilingCommand} ]] && doneFileBase="profiling.cpass0.job${jobindex}.run${runNumber}.done"
102 # We will have two copies of the file
103 mkdir -p "${commonOutputPath}/meta" || return 1
104 doneFileTmp="${batchWorkingDirectory}/${doneFileBase}"
105 doneFile="${commonOutputPath}/meta/${doneFileBase}"
107 [[ -f ${alirootSource} && -z ${ALICE_ROOT} ]] && source ${alirootSource}
109 if [[ -n ${ALIROOT_FORCE_COREDUMP} ]]; then
111 export ALIROOT_FORCE_COREDUMP
114 #the contents of this is stored in the tree and used later (e.g. AliAnalysisTaskPIDResponse)!
115 #at the QA stage the pass number is guessed from the path stored here.
117 #Packages= ;OutputDir= ;LPMPass= ;TriggerAlias= ;LPMRunNumber= ;LPMProductionType= ;LPMInteractionType= ;LPMProductionTag= ;LPMAnchorRun= ;LPMAnchorProduction= ;LPMAnchorYear=
118 export PRODUCTION_METADATA="OutputDir=cpass0"
120 if [[ "${inputList}" =~ \.root$ ]]; then
123 infile=$(sed -ne "${jobindex}p" ${inputList} | egrep '\s*\w*/\w*')
125 chunkName=${infile##*/}
127 outputDir=${targetDirectory}/${jobindex}_${chunkName%.*}
128 mkdir -p ${outputDir}
129 if [[ ! -d ${outputDir} ]]; then
131 echo "cannot make ${outputDir}" >> ${doneFileTmp}
132 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
133 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
138 [[ ${reconstructInTemporaryDir} -eq 1 ]] && runpath=$(mktemp -d -t cpass0.XXXXXX)
139 [[ ${reconstructInTemporaryDir} -eq 2 ]] && runpath=${PWD}/rundir_cpass0_${runNumber}_${jobindex}
141 if [[ ! -d ${runpath} ]]; then
143 echo "cannot make runpath ${runpath}" >> ${doneFileTmp}
144 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
145 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
148 if ! cd ${runpath}; then
150 echo "PWD=$PWD is not the runpath=${runpath}" >> ${doneFileTmp}
151 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
152 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
156 #runCPassX/C expects the raw chunk to be linked in the run dir
157 #despite it being accessed by the full path
158 if [[ $copyInputData == 0 ]]; then
159 ln -s ${infile} ${runpath}/${chunkName}
161 copyFileToLocal ${infile} ${runpath}/${chunkName}
165 if [[ -n ${generateMC} ]]; then
167 outputDirMC=${commonOutputPath}/000${runNumber}/sim/${jobindex}
168 simrunpath=${outputDirMC}
169 #[[ ${simulateInTemporaryDir} -eq 1 && -n ${TMPDIR} ]] && simrunpath=${TMPDIR}
170 [[ ${simulateInTemporaryDir} -eq 1 ]] && simrunpath=$(mktemp -d -t cpass0MC.XXXXXX)
171 mkdir -p ${outputDirMC}
172 mkdir -p ${simrunpath}
173 if cd ${simrunpath}; then
176 "${batchWorkingDirectory}/sim.C"
177 "${batchWorkingDirectory}/rec.C"
178 "${batchWorkingDirectory}/Config.C"
179 "${batchWorkingDirectory}/OCDB_*.root"
181 for file in ${filesMC[*]}; do
182 [[ ! -f ${file##*/} && -f ${file} ]] && echo "copying ${file}" && cp -f ${file} .
185 generateMC ${runNumber} ${ocdbPath} ${nEvents}
187 [[ ! "${simrunpath}" =~ "${outputDirMC}" ]] && mv * ${outputDirMC} #TODO check if it works
190 ln -s ${outputDirMC}/* ${runpath}/
192 inputList=${outputDirMC}/galice.root #TODO not valid outside shell !!!
198 if [[ "${inputList}" == "${inputList%%://*}" && ! -f "${inputList}" && -z ${pretend} ]]; then
200 echo "input file ${inputList} not found, exiting..." >> ${doneFileTmp}
201 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
202 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
206 logOutputDir=${runpath}
207 [[ -n ${logToFinalDestination} ]] && logOutputDir=${outputDir}
208 [[ -z ${dontRedirectStdOutToLog} ]] && exec &> ${logOutputDir}/stdout
209 #[[ -z ${dontRedirectStdOutToLog} ]] && exec 2> ${logOutputDir}/stderr
212 echo "#####################"
215 echo nEvents ${nEvents}
216 echo runNumber ${runNumber}
217 echo ocdbPath ${ocdbPath}
218 echo infile ${infile}
219 echo chunkName ${chunkName}
220 echo jobindex ${jobindex}
221 echo recoTriggerOptions ${recoTriggerOptions}
222 echo targetDirectory ${targetDirectory}
223 echo commonOutputPath ${commonOutputPath}
224 echo doneFile ${doneFile}
225 echo batchWorkingDirectory ${batchWorkingDirectory}
226 echo runpath ${runpath}
227 echo outputDir ${outputDir}
229 echo ALICE_ROOT ${ALICE_ROOT}
230 echo "########## ###########"
232 alirootInfo > ALICE_ROOT.log
235 "${batchWorkingDirectory}/runCPass0.sh"
236 "${batchWorkingDirectory}/recCPass0.C"
237 "${batchWorkingDirectory}/runCalibTrain.C"
238 "${batchWorkingDirectory}/localOCDBaccessConfig.C"
239 "${batchWorkingDirectory}/OCDB.root"
240 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass0/runCPass0.sh"
241 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass0/recCPass0.C"
242 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass0/runCalibTrain.C"
245 for file in ${filesCPass0[*]}; do
246 [[ ! -f ${file##*/} && -f ${file} ]] && echo "copying ${file}" && cp -f ${file} .
247 [[ ${file##*/} =~ .*\.sh ]] && chmod +x ${file##*/}
250 echo "this directory (${PWD}) contents:"
253 chmod u+x runCPass0.sh
255 #remove spaces from around arguments to root macros
256 #for example this sometimes fails:
257 # root 'macro.C(argument1, argument2)'
258 sed -i '/.*root .*\.C/ s|\s*,\s*|,|g' *.sh
260 if [[ -n ${postSetUpActionCPass0} ]]; then
261 echo "running ${postSetUpActionCPass0}"
262 eval ${postSetUpActionCPass0}
266 echo "${runpath}/runCPass0.sh /${infile} ${nEvents} ${runNumber} ${ocdbPath} ${recoTriggerOptions}"
267 if [[ -n ${pretend} ]]; then
268 sleep ${pretendDelay}
270 touch AliESDfriends.root
271 touch AliESDfriends_v1.root
275 #caveat: in the local case, first arg must start with a slash
276 ./runCPass0.sh "/${infile}" "${nEvents}" "${runNumber}" "${ocdbPath}" "${recoTriggerOptions}"
279 #move stuff to final destination
280 echo "this directory (${PWD}) contents:"
284 # [dberzano] OK this is fine!
285 echo rm -f ./${chunkName}
287 echo "paranoidCp ${runpath}/* ${outputDir}"
288 paranoidCp ${runpath}/* ${outputDir}
293 if summarizeLogs >> ${doneFileTmp}; then
294 [[ -f ${outputDirMC}/galice.root ]] && echo "sim ${outputDirMC}/galice.root" >> ${doneFileTmp}
295 [[ -f AliESDfriends_v1.root ]] && echo "calibfile ${outputDir}/AliESDfriends_v1.root" >> ${doneFileTmp}
296 [[ -f AliESDs.root ]] && echo "esd ${outputDir}/AliESDs.root" >> ${doneFileTmp}
299 [[ "${runpath}" != "${outputDir}" ]] && rm -rf ${runpath} && echo "removing ${runpath}"
300 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
301 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
318 if ! parseConfig ${configFile} "$@"; then return 1; fi
320 #record the working directory provided by the batch system
321 batchWorkingDirectory=${PWD}
323 #use the jobindex only if set and non-negative
324 if [[ -z ${jobindex} || ${jobindex} -lt 0 ]]; then
325 [[ -n "${LSB_JOBINDEX}" ]] && jobindex=${LSB_JOBINDEX}
326 [[ -n "${SGE_TASK_ID}" ]] && jobindex=${SGE_TASK_ID}
327 if [[ -z ${jobindex} ]]; then
333 [[ -z ${commonOutputPath} ]] && commonOutputPath=${PWD}
335 # This file signals that/if everything went fine
336 doneFileBase="cpass1.job${jobindex}.run${runNumber}.done"
337 [[ -n ${useProfilingCommand} ]] && doneFileBase="profiling.cpass0.job${jobindex}.run${runNumber}.done"
339 # We will have two copies of the file
340 mkdir -p "${commonOutputPath}/meta" || return 1
341 doneFileTmp="${batchWorkingDirectory}/${doneFileBase}"
342 doneFile="${commonOutputPath}/meta/${doneFileBase}"
344 [[ -f ${alirootSource} && -z ${ALICE_ROOT} ]] && source ${alirootSource}
346 if [[ -n ${ALIROOT_FORCE_COREDUMP} ]]; then
348 export ALIROOT_FORCE_COREDUMP
351 #the contents of this is stored in the tree and used later (e.g. AliAnalysisTaskPIDResponse)!
352 #at the QA stage the pass number is guessed from the path stored here.
354 #Packages= ;OutputDir= ;LPMPass= ;TriggerAlias= ;LPMRunNumber= ;LPMProductionType= ;LPMInteractionType= ;LPMProductionTag= ;LPMAnchorRun= ;LPMAnchorProduction= ;LPMAnchorYear=
355 export PRODUCTION_METADATA="OutputDir=cpass1"
357 if [[ "${inputList}" == "${inputList%%://*}" && ! -f "${inputList}" && -z ${pretend} ]]; then
359 echo "input file ${inputList} not found, exiting..." >> ${doneFileTmp}
360 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
361 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
364 if [[ "${inputList}" =~ \.root$ ]]; then
367 infile=$(sed -ne "${jobindex}p" ${inputList} | egrep '\s*\w*/\w*')
369 chunkName=${infile##*/}
371 outputDir=${targetDirectory}/${jobindex}_${chunkName%.*}
372 mkdir -p ${outputDir}
373 if [[ ! -d ${outputDir} ]];then
375 echo "cannot make ${outputDir}" >> ${doneFileTmp}
376 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
377 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
382 [[ ${reconstructInTemporaryDir} -eq 1 ]] && runpath=$(mktemp -d -t cpass1.XXXXXX)
383 [[ ${reconstructInTemporaryDir} -eq 2 ]] && runpath=${PWD}/rundir_cpass1_${runNumber}_${jobindex}
386 if [[ "${infile}" =~ galice\.root ]]; then
387 ln -s ${inputList%/*}/* ${runpath}
391 #init the running path
393 if [[ ! -d ${runpath} ]]; then
395 echo "cannot make runpath ${runpath}" >> ${doneFileTmp}
396 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
397 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
400 if ! cd ${runpath}; then
402 echo "PWD=$PWD is not the runpath=${runpath}" >> ${doneFileTmp}
403 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
404 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
408 #this is needed for runCPass1.sh
409 if [[ $copyInputData == 0 ]]; then
410 ln -s ${infile} ${runpath}/${chunkName}
412 copyFileToLocal ${infile} ${runpath}/${chunkName}
415 logOutputDir=${runpath}
416 [[ -n ${logToFinalDestination} ]] && logOutputDir=${outputDir}
417 [[ -z ${dontRedirectStdOutToLog} ]] && exec &> ${logOutputDir}/stdout
418 #[[ -z ${dontRedirectStdOutToLog} ]] && exec 2> ${logOutputDir}/stderr
421 echo "#####################"
424 echo nEvents ${nEvents}
425 echo runNumber ${runNumber}
426 echo ocdbPath ${ocdbPath}
427 echo infile ${infile}
428 echo chunkName ${chunkName}
429 echo jobindex ${jobindex}
430 echo recoTriggerOptions ${recoTriggerOptions}
431 echo targetDirectory ${targetDirectory}
432 echo commonOutputPath ${commonOutputPath}
433 echo doneFile ${doneFile}
434 echo runpath ${runpath}
435 echo outputDir ${outputDir}
436 echo batchWorkingDirectory ${batchWorkingDirectory}
437 echo ALICE_ROOT ${ALICE_ROOT}
439 echo "#####################"
441 alirootInfo > ALICE_ROOT.log
444 "${batchWorkingDirectory}/runCPass1.sh"
445 "${batchWorkingDirectory}/recCPass1.C"
446 "${batchWorkingDirectory}/recCPass1_OuterDet.C"
447 "${batchWorkingDirectory}/runCalibTrain.C"
448 "${batchWorkingDirectory}/QAtrain_duo.C"
449 "${batchWorkingDirectory}/localOCDBaccessConfig.C"
450 "${batchWorkingDirectory}/${configFile}"
451 "${commonOutputPath}/meta/cpass0.localOCDB.${runNumber}.tgz"
452 "${batchWorkingDirectory}/OCDB.root"
453 "${trustedQAtrainMacro}"
454 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass1/runCPass1.sh"
455 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass1/recCPass1.C"
456 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass1/recCPass1_OuterDet.C"
457 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass1/runCalibTrain.C"
458 "${ALICE_ROOT}/ANALYSIS/macros/QAtrain_duo.C"
461 for file in "${filesCPass1[@]}"; do
462 [[ ! -f ${file##*/} && -f ${file} ]] && echo "copying ${file}" && cp -f ${file} .
463 [[ ${file##*/} =~ .*\.sh ]] && echo "making ${file##*/} executable" && chmod +x ${file##*/}
466 echo "this directory (${PWD}) contents:"
470 #remove spaces from around arguments to root macros
471 #for example this sometimes fails:
472 # root 'macro.C(argument1, argument2)'
473 sed -i '/.*root .*\.C/ s|\s*,\s*|,|g' *.sh
475 if [[ -n ${postSetUpActionCPass1} ]]; then
476 echo "running ${postSetUpActionCPass1}"
477 eval ${postSetUpActionCPass1}
481 #configure local OCDB storage from CPass0 (creates the localOCDBaccessConfig.C script)
482 if [[ -f cpass0.localOCDB.${runNumber}.tgz ]]; then
483 echo goMakeLocalOCDBaccessConfig "cpass0.localOCDB.${runNumber}.tgz"
484 goMakeLocalOCDBaccessConfig "cpass0.localOCDB.${runNumber}.tgz"
486 echo "WARNING: file cpass0.localOCDB.${runNumber}.tgz not found!"
489 if [[ ! $(/bin/ls -1 OCDB/*/*/*/*.root 2>/dev/null) ]]; then
491 echo "cpass0 produced no calibration! exiting..." >> ${doneFileTmp}
492 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
493 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
497 #create the Barrel and OuterDet directories for CPass1 and link the local OCDB directory
498 #there to make the localOCDBaccessConfig.C file work, since it may point to the OCDB
499 #entries using a relative path, e.g. local://./OCDB
500 echo "linking the OCDB/ for Barrel and OuterDet directories"
501 mkdir Barrel OuterDet
503 ln -s ../OCDB Barrel/OCDB
504 ln -s ../OCDB OuterDet/OCDB
507 #the following option enables the filtering task inside the QAtrain_duo.C
508 [[ -n $runESDfiltering ]] && export QA_TaskFilteredTree=1
509 #set the downscaling factors during the filtering fro expert QA (overrides the previous values)
510 if [[ -n ${filteringFactorHighPt} ]]; then
511 export AliAnalysisTaskFilteredTree_fLowPtTrackDownscaligF=${filteringFactorHighPt}
513 if [[ -n ${filteringFactorV0s} ]]; then
514 export AliAnalysisTaskFilteredTree_fLowPtV0DownscaligF=${filteringFactorV0s}
518 chmod u+x runCPass1.sh
519 echo "${runpath}/runCPass1.sh /${infile} ${nEvents} ${runNumber} ${ocdbPath} ${recoTriggerOptions}"
520 if [[ -n ${pretend} ]]; then
521 sleep ${pretendDelay}
522 touch AliESDs_Barrel.root
523 touch AliESDfriends_Barrel.root
524 touch AliESDfriends_v1.root
525 touch QAresults_barrel.root
526 touch EventStat_temp_barrel.root
528 touch AliESDs_Outer.root
529 touch AliESDfriends_Outer.root
530 touch QAresults_outer.root
531 touch EventStat_temp_outer.root
535 touch filtering.log FilterEvents_Trees.root
537 #caveat: in the local case, first arg must start with a slash
538 ./runCPass1.sh "/${infile}" "${nEvents}" "${runNumber}" "${ocdbPath}" "${recoTriggerOptions}"
540 [[ ! -f AliESDs_Barrel.root && -f Barrel/AliESDs.root ]] && mv Barrel/AliESDs.root AliESDs_Barrel.root
541 [[ ! -f AliESDfriends_Barrel.root && -f Barrel/AliESDfriends.root ]] && mv Barrel/AliESDfriends.root AliESDfriends_Barrel.root
542 [[ ! -f AliESDfriends_v1.root && -f Barrel/AliESDfriends_v1.root ]] && mv Barrel/AliESDfriends_v1.root .
543 [[ ! -f QAresults_barrel.root && -f Barrel/QAresults_barrel.root ]] && mv Barrel/QAresults_barrel.root .
544 [[ ! -f AliESDs_Outer.root && -f OuterDet/AliESDs.root ]] && mv OuterDet/AliESDs.root AliESDs_Outer.root
545 [[ ! -f AliESDfriends_Outer.root && -f OuterDet/AliESDfriends.root ]] && mv OuterDet/AliESDfriends.root AliESDfriends_Outer.root
546 [[ ! -f QAresults_outer.root && -f OuterDet/QAresults_outer.root ]] && mv OuterDet/QAresults_outer.root .
547 [[ ! -f FilterEvents_Trees.root && -f Barrel/FilterEvents_Trees.root ]] && mv Barrel/FilterEvents_Trees.root .
549 #make the filtered tree (if requested and not already produced by QA
550 [[ -f AliESDs_Barrel.root ]] && echo "AliESDs_Barrel.root" > filtered.list
551 if [[ -n ${runESDfiltering} && ! -f FilterEvents_Trees.root && -f filtered.list ]]; then
552 goMakeFilteredTrees ${PWD} ${runNumber} "${PWD}/filtered.list" ${filteringFactorHighPt} ${filteringFactorV0s} ${ocdbPath} 1000000 0 10000000 0 ${configFile} AliESDs_Barrel.root "${extraOpts[@]}" >filtering.log
559 ##handle possible crashes in QA (happens often in trunk)
560 ##rerun QA with a trusted aliroot version
561 #if [[ $(validateLog qa_barrel.log) ]]; then
562 # echo "qa_barrel.log not validated!"
564 #if [[ ! -f QAresults_barrel.root && -f ${setupTrustedAliROOTenvInCurrentShell} || $(validateLog qa_barrel.log) ]]; then
565 # echo "WARNING: using trusted QA aliroot ${ALICE_ROOT}"
566 # source ${setupTrustedAliROOTenvInCurrentShell}
568 # rm QAresults_barrel.root
569 # rm EventStat_temp_barrel.root
571 # [[ ! -f AliESDs.root ]] && ln -s ../AliESDs_Barrel.root AliESDs.root
572 # [[ ! -f AliESDfriends.root ]] && ln -s ../AliESDfriends_Barrel.root AliESDfriends.root
573 # if [[ -n ${trustedQAtrainMacro} ]]; then
574 # eval "cp ${trustedQAtrainMacro} QAtrain_duo_trusted.C"
576 # echo executing aliroot -b -q "QAtrain_duo_trusted.C(\"_barrel\",${runNumber},\"wn.xml\",0,\"${ocdbPath}\")"
577 # time aliroot -b -q "QAtrain_duo.C(\"_barrel\",${runNumber},\"wn.xml\",0,\"${ocdbPath}\")" &> ../qa_barrel_trusted.log
581 #move stuff to final destination
582 echo "this directory (${PWD}) contents:"
584 echo rm -f ./${chunkName}
586 echo "paranoidCp ${runpath}/* ${outputDir}"
587 paranoidCp ${runpath}/* ${outputDir}
592 if summarizeLogs >> ${doneFileTmp}; then
593 [[ -f AliESDs_Barrel.root ]] && echo "esd ${outputDir}/AliESDs_Barrel.root" >> ${doneFileTmp}
594 [[ -f AliESDfriends_v1.root ]] && echo "calibfile ${outputDir}/AliESDfriends_v1.root" >> ${doneFileTmp}
595 [[ -f QAresults_Barrel.root ]] && echo "qafile ${outputDir}/QAresults_Barrel.root" >> ${doneFileTmp}
596 [[ -f QAresults_Outer.root ]] && echo "qafile ${outputDir}/QAresults_Outer.root" >> ${doneFileTmp}
597 [[ -f QAresults_barrel.root ]] && echo "qafile ${outputDir}/QAresults_barrel.root" >> ${doneFileTmp}
598 [[ -f QAresults_outer.root ]] && echo "qafile ${outputDir}/QAresults_outer.root" >> ${doneFileTmp}
599 [[ -f FilterEvents_Trees.root ]] && echo "filteredTree ${outputDir}/FilterEvents_Trees.root" >> ${doneFileTmp}
601 if grep "qa_outer.log.*OK" ${doneFileTmp} > /dev/null; then
602 [[ -f QAresults_Outer.root ]] && echo "qafile ${outputDir}/QAresults_Outer.root" >> ${doneFileTmp}
603 [[ -f QAresults_outer.root ]] && echo "qafile ${outputDir}/QAresults_outer.root" >> ${doneFileTmp}
605 if grep "qa_barrel.log.*OK" ${doneFileTmp} > /dev/null; then
606 [[ -f QAresults_Barrel.root ]] && echo "qafile ${outputDir}/QAresults_Barrel.root" >> ${doneFileTmp}
607 [[ -f QAresults_barrel.root ]] && echo "qafile ${outputDir}/QAresults_barrel.root" >> ${doneFileTmp}
609 if grep "filtering.log.*OK" ${doneFileTmp} > /dev/null; then
610 [[ -f FilterEvents_Trees.root ]] && echo "filteredTree ${outputDir}/FilterEvents_Trees.root" >> ${doneFileTmp}
614 [[ "${runpath}" != "${outputDir}" ]] && rm -rf ${runpath}
615 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
616 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
624 # find the output files and merge them
631 calibrationFilesToMerge=${5} #can be a non-existent file, will then be produced on the fly
633 if ! parseConfig ${configFile} "$@"; then return 1; fi
635 #record the working directory provided by the batch system
636 batchWorkingDirectory=${PWD}
638 [[ -z ${commonOutputPath} ]] && commonOutputPath=${PWD}
640 # This file signals that everything went fine
641 doneFileBase="merge.cpass0.run${runNumber}.done"
643 # We will have two copies of the file
644 mkdir -p "${commonOutputPath}/meta" || return 1
645 doneFileTmp="${batchWorkingDirectory}/${doneFileBase}"
646 doneFile="${commonOutputPath}/meta/${doneFileBase}"
651 [[ -f ${alirootSource} && -z ${ALICE_ROOT} ]] && source ${alirootSource}
654 [[ ${reconstructInTemporaryDir} -eq 1 ]] && runpath=$(mktemp -d -t mergeCPass0.XXXXXX)
655 [[ ${reconstructInTemporaryDir} -eq 2 ]] && runpath=${PWD}/rundir_mergeCPass0_${runNumber}
658 if [[ ! -d ${runpath} ]]; then
660 echo "not able to make the runpath ${runpath}" >> ${doneFileTmp}
661 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
662 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
665 if ! cd ${runpath}; then
667 echo "PWD=$PWD is not the runpath=${runpath}" >> ${doneFileTmp}
668 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
669 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
673 logOutputDir=${runpath}
674 [[ -n ${logToFinalDestination} ]] && logOutputDir=${outputDir}
675 [[ -z ${dontRedirectStdOutToLog} ]] && exec &> ${logOutputDir}/stdout
678 mergingScript="mergeMakeOCDB.byComponent.sh"
680 echo goMergeCPass0 SETUP:
681 echo runNumber=${runNumber}
682 echo outputDir=${outputDir}
683 echo ocdbStorage=${ocdbStorage}
684 echo calibrationFilesToMerge=${calibrationFilesToMerge}
685 echo mergingScript=${mergingScript}
686 echo commonOutputPath=${commonOutputPath}
687 echo runpath=${runpath}
689 # copy files in case they are not already there
691 "${batchWorkingDirectory}/${calibrationFilesToMerge}"
692 "${batchWorkingDirectory}/OCDB.root"
693 "${batchWorkingDirectory}/localOCDBaccessConfig.C"
694 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass0/mergeMakeOCDB.byComponent.sh"
695 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass0/mergeByComponent.C"
696 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass0/makeOCDB.C"
697 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass0/merge.C"
698 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass0/mergeMakeOCDB.sh"
700 for file in ${filesMergeCPass0[*]}; do
701 [[ ! -f ${file##*/} && -f ${file} ]] && echo "copying ${file}" && cp -f ${file} .
702 [[ ${file##*/} =~ .*\.sh ]] && chmod +x ${file##*/}
705 #remove spaces from around arguments to root macros
706 #for example this sometimes fails:
707 # root 'macro.C(argument1, argument2)'
708 sed -i '/.*root .*\.C/ s|\s*,\s*|,|g' *.sh
710 alirootInfo > ALICE_ROOT.log
720 chmod u+x ${mergingScript}
722 if [[ ! -f ${calibrationFilesToMerge} ]]; then
723 echo "/bin/ls -1 ${outputDir}/*/AliESDfriends_v1.root > ${calibrationFilesToMerge}"
724 /bin/ls -1 ${outputDir}/*/AliESDfriends_v1.root 2>/dev/null > ${calibrationFilesToMerge}
727 echo "${mergingScript} ${calibrationFilesToMerge} ${runNumber} local://./OCDB defaultOCDB=${ocdbStorage} fileAccessMethod=nocopy"
728 if [[ -n ${pretend} ]]; then
729 sleep ${pretendDelay}
730 touch CalibObjects.root
734 mkdir -p ./OCDB/TPC/Calib/TimeGain/
735 mkdir -p ./OCDB/TPC/Calib/TimeDrift/
736 echo "some calibration" >> ./OCDB/TPC/Calib/TimeGain/someCalibObject_0-999999_cpass0.root
737 echo "some calibration" >> ./OCDB/TPC/Calib/TimeDrift/otherCalibObject_0-999999_cpass0.root
739 ./${mergingScript} ${calibrationFilesToMerge} ${runNumber} "local://./OCDB" defaultOCDB=${ocdbStorage} fileAccessMethod=nocopy >> "mergeMakeOCDB.log"
741 #produce the calib trees for expert QA (dcsTime.root)
742 goMakeLocalOCDBaccessConfig ./OCDB
743 echo aliroot -b -q "${ALICE_ROOT}/PWGPP/TPC/macros/CalibSummary.C(${runNumber},\"${ocdbStorage}\")"
744 aliroot -b -q "${ALICE_ROOT}/PWGPP/TPC/macros/CalibSummary.C(${runNumber},\"${ocdbStorage}\")"
747 ### produce the output
748 #tar the produced OCDB for reuse
749 #tar czf ${commonOutputPath}/meta/cpass0.localOCDB.${runNumber}.tgz ./OCDB
751 # Create tarball with OCDB, store on the shared directory, create signal file on batch directory
752 mkdir -p ${commonOutputPath}/meta
753 baseTar="cpass0.localOCDB.${runNumber}.tgz"
754 tar czf ${batchWorkingDirectory}/${baseTar} ./OCDB && \
755 mv ${batchWorkingDirectory}/${baseTar} ${commonOutputPath}/meta/${baseTar} && \
756 touch ${batchWorkingDirectory}/${baseTar}.done
760 #copy all to output dir
761 echo "paranoidCp ${runpath}/* ${outputDir}"
762 paranoidCp ${runpath}/* ${outputDir}
764 if [[ -n ${generateMC} ]]; then
765 goPrintValues sim ${commonOutputPath}/meta/sim.run${runNumber}.list ${commonOutputPath}/meta/cpass0.job*.run${runNumber}.done
768 #validate merging cpass0
770 if summarizeLogs >> ${doneFileTmp}; then
771 [[ -f CalibObjects.root ]] && echo "calibfile ${outputDir}/CalibObjects.root" >> ${doneFileTmp}
772 [[ -f dcsTime.root ]] && echo "dcsTree ${outputDir}/dcsTime.root" >> ${doneFileTmp}
775 [[ "${runpath}" != "${outputDir}" ]] && rm -rf ${runpath}
776 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
777 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
784 # find the output files and merge them
791 calibrationFilesToMerge=${5}
793 filteredFilesToMerge=${7}
795 if ! parseConfig ${configFile} "$@"; then return 1; fi
797 #record the working directory provided by the batch system
798 batchWorkingDirectory=${PWD}
800 [[ -z ${commonOutputPath} ]] && commonOutputPath=${PWD}
802 # This file signals that everything went fine
803 doneFileBase="merge.cpass1.run${runNumber}.done"
805 # We will have two copies of the file
806 mkdir -p "${commonOutputPath}/meta" || return 1
807 doneFileTmp="${batchWorkingDirectory}/${doneFileBase}"
808 doneFile="${commonOutputPath}/meta/${doneFileBase}"
814 rm -f ${outputDir}/*.log
815 rm -f ${outputDir}/*.root
816 rm -f ${outputDir}/*done
818 [[ -f ${alirootSource} && -z ${ALICE_ROOT} ]] && source ${alirootSource}
821 [[ ${reconstructInTemporaryDir} -eq 1 ]] && runpath=$(mktemp -d -t mergeCPass1.XXXXXX)
822 [[ ${reconstructInTemporaryDir} -eq 2 ]] && runpath=${PWD}/rundir_mergeCPass1_${runNumber}
825 if [[ ! -d ${runpath} ]]; then
827 echo "not able to make the runpath ${runpath}" >> ${doneFileTmp}
828 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
829 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
832 if ! cd ${runpath}; then
834 echo "PWD=$PWD is not the runpath=${runpath}" >> ${doneFileTmp}
835 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
836 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
840 logOutputDir=${runpath}
841 [[ -n ${logToFinalDestination} ]] && logOutputDir=${outputDir}
842 [[ -z ${dontRedirectStdOutToLog} ]] && exec &> ${logOutputDir}/mergeMakeOCDB.log
845 calibrationOutputFileName='AliESDfriends_v1.root'
846 qaOutputFileName='QAresults*.root'
847 mergingScript="mergeMakeOCDB.byComponent.sh"
848 #important to have the string "Stage.txt" in the filename to trigger the merging
849 #it has to be a list of directories containing the files
850 qaMergedOutputFileName="QAresults_merged.root"
852 echo goMergeCPass1 SETUP:
853 echo runNumber=${runNumber}
854 echo outputDir=${outputDir}
855 echo ocdbStorage=${ocdbStorage}
856 echo calibrationFilesToMerge=$calibrationFilesToMerge
857 echo qaFilesToMerge=$qaFilesToMerge
858 echo calibrationOutputFileName=${calibrationOutputFileName}
859 echo mergingScript=${mergingScript}
861 # copy files in case they are not already there
863 "${batchWorkingDirectory}/${calibrationFilesToMerge}"
864 "${batchWorkingDirectory}/${qaFilesToMerge}"
865 "${batchWorkingDirectory}/OCDB.root"
866 "${batchWorkingDirectory}/localOCDBaccessConfig.C"
867 "${commonOutputPath}/meta/cpass0.localOCDB.${runNumber}.tgz"
868 "${batchWorkingDirectory}/QAtrain_duo.C"
869 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass1/mergeMakeOCDB.byComponent.sh"
870 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass1/mergeByComponent.C"
871 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass1/makeOCDB.C"
872 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass1/merge.C"
873 "${ALICE_ROOT}/PWGPP/CalibMacros/CPass1/mergeMakeOCDB.sh"
874 "${trustedQAtrainMacro}"
875 "${ALICE_ROOT}/ANALYSIS/macros/QAtrain_duo.C"
877 for file in ${filesMergeCPass1[*]}; do
878 [[ ! -f ${file##*/} && -f ${file} ]] && echo "copying ${file}" && cp -f ${file} .
879 [[ ${file##*/} =~ .*\.sh ]] && chmod +x ${file##*/}
882 #remove spaces from around arguments to root macros
883 #for example this sometimes fails:
884 # root 'macro.C(argument1, argument2)'
885 sed -i '/.*root .*\.C/ s|\s*,\s*|,|g' *.sh
887 #configure local OCDB storage from CPass0 (creates the localOCDBaccessConfig.C script)
888 if [[ -f cpass0.localOCDB.${runNumber}.tgz ]]; then
889 echo goMakeLocalOCDBaccessConfig "cpass0.localOCDB.${runNumber}.tgz"
890 goMakeLocalOCDBaccessConfig "cpass0.localOCDB.${runNumber}.tgz"
892 echo "WARNING: file cpass0.localOCDB.${runNumber}.tgz not found!"
895 alirootInfo > ALICE_ROOT.log
901 chmod u+x ${mergingScript}
904 #if not provided, create the lists of files to merge
905 if [[ ! -f ${filteredFilesToMerge} ]]; then
906 echo "/bin/ls -1 ${outputDir}/*/FilterEvents_Trees.root > ${filteredFilesToMerge}"
907 /bin/ls -1 ${outputDir}/*/FilterEvents_Trees.root 2>/dev/null > ${filteredFilesToMerge}
909 if [[ ! -f ${calibrationFilesToMerge} ]]; then
910 echo "/bin/ls -1 ${outputDir}/*/AliESDfriends_v1.root > ${calibrationFilesToMerge}"
911 /bin/ls -1 ${outputDir}/*/AliESDfriends_v1.root 2>/dev/null > ${calibrationFilesToMerge}
913 if [[ ! -f ${qaFilesToMerge} ]]; then
914 #find the files, but only store the directories (QAtrain_duo.C requires this)
915 echo "/bin/ls -1 ${outputDir}/*/QAresults*.root | while read x; do echo ${x%/*}; done | sort | uniq > ${qaFilesToMerge}"
916 /bin/ls -1 ${outputDir}/*/QAresults*.root | while read x; do echo ${x%/*}; done | sort | uniq > ${qaFilesToMerge}
919 echo "${mergingScript} ${calibrationFilesToMerge} ${runNumber} local://./OCDB defaultOCDB=${ocdbStorage} fileAccessMethod=nocopy"
920 if [[ -n ${pretend} ]]; then
921 sleep ${pretendDelay}
923 touch cpass1.localOCDB.${runNumber}.tgz
924 touch ${qaMergedOutputFileName}
927 touch FilterEvents_Trees.root
928 touch CalibObjects.root
930 touch ${qaMergedOutputFileName}
933 ./${mergingScript} ${calibrationFilesToMerge} ${runNumber} "local://./OCDB" defaultOCDB=${ocdbStorage} fileAccessMethod=nocopy
935 #merge QA (and filtered trees)
936 [[ -n ${AliAnalysisTaskFilteredTree_fLowPtTrackDownscaligF} ]] && export AliAnalysisTaskFilteredTree_fLowPtTrackDownscaligF
937 [[ -n ${AliAnalysisTaskFilteredTree_fLowPtV0DownscaligF} ]] && export AliAnalysisTaskFilteredTree_fLowPtV0DownscaligF
939 #echo aliroot -l -b -q "merge.C(\"${qaFilesToMerge}\",\"\",kFALSE,\"${qaMergedOutputFileName}\")"
940 echo aliroot -b -q "QAtrain_duo.C(\"_barrel\",${runNumber},\"${qaFilesToMerge}\",1,\"${ocdbStorage}\")"
941 #aliroot -l -b -q "merge.C(\"${qaFilesToMerge}\",\"\",kFALSE,\"${qaMergedOutputFileName}\")"
942 aliroot -b -q "QAtrain_duo.C(\"_barrel\",${runNumber},\"${qaFilesToMerge}\",1,\"${ocdbStorage}\")" > mergeQA.log
943 mv QAresults_barrel.root ${qaMergedOutputFileName}
944 mv trending_barrel.root trending.root
946 #merge filtered trees
947 echo aliroot -l -b -q "merge.C(\"${qaFilesToMerge}\",\"\",kFALSE,\"${qaMergedOutputFileName}\")"
948 aliroot -l -b -q "merge.C(\"${filteredFilesToMerge}\",\"\",kFALSE,\"FilterEvents_Trees.root\")" > mergeFilteredTrees.log
950 #produce the calib trees for expert QA
951 echo aliroot -b -q "${ALICE_ROOT}/PWGPP/TPC/macros/CalibSummary.C(${runNumber},\"${ocdbStorage}\")"
952 aliroot -b -q "${ALICE_ROOT}/PWGPP/TPC/macros/CalibSummary.C(${runNumber},\"${ocdbStorage}\")" > calibTree.log
955 # Create tarball with OCDB, store on the shared directory, create signal file on batch directory
956 mkdir -p ${commonOutputPath}/meta
957 baseTar="cpass1.localOCDB.${runNumber}.tgz"
958 tar czf ${batchWorkingDirectory}/${baseTar} ./OCDB && \
959 mv ${batchWorkingDirectory}/${baseTar} ${commonOutputPath}/meta/${baseTar} && \
960 touch ${batchWorkingDirectory}/${baseTar}.done
964 #copy all to output dir
965 echo "paranoidCp ${runpath}/* ${outputDir}"
966 paranoidCp ${runpath}/* ${outputDir}
968 #validate merge cpass1
970 if summarizeLogs >> ${doneFileTmp}; then
971 [[ -f CalibObjects.root ]] && echo "calibfile ${outputDir}/CalibObjects.root" >> ${doneFileTmp}
972 [[ -f ${qaMergedOutputFileName} ]] && echo "qafile ${outputDir}/${qaMergedOutputFileName}" >> ${doneFileTmp}
973 [[ -f trending.root ]] && echo "trendingfile ${outputDir}/trending.root" >> ${doneFileTmp}
974 [[ -f dcsTime.root ]] && echo "dcsTree ${outputDir}/dcsTime.root" >> ${doneFileTmp}
975 [[ -f FilterEvents_Trees.root ]] && echo "filteredTree ${outputDir}/FilterEvents_Trees.root" >> ${doneFileTmp}
977 if grep "mergeQA.log.*OK" ${doneFileTmp} > /dev/null; then
978 [[ -f ${qaMergedOutputFileName} ]] && echo "qafile ${outputDir}/${qaMergedOutputFileName}" >> ${doneFileTmp}
980 if grep "mergeFilteredTrees.log.*OK" ${doneFileTmp} > /dev/null; then
981 [[ -f FilterEvents_Trees.root ]] && echo "filteredTree ${outputDir}/FilterEvents_Trees.root" >> ${doneFileTmp}
985 [[ "${runpath}" != "${outputDir}" ]] && rm -rf ${runpath}
986 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
987 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
993 #generic root merge using CPass1 merge.C script
996 configFile=${3-"benchmark.config"}
998 if ! parseConfig ${configFile} "$@"; then return 1; fi
1000 #record the working directory provided by the batch system
1001 batchWorkingDirectory=${PWD}
1003 [[ ! -f ${inputList} ]] && echo "inputList ${inputList} does not exist!" && return 1
1004 [[ ! -f ${configFile} ]] && echo "configFile ${configFile} does not exist!" && return 1
1006 [[ -f ${alirootSource} && -z ${ALICE_ROOT} ]] && source ${alirootSource}
1008 aliroot -b -q "${ALICE_ROOT}/PWGPP/CalibMacros/CPass0/merge.C(\"${inputList}\",\"\",kFALSE,\"${outputFile}\")" > merge_${inputList}.log
1020 if ! parseConfig ${configFile} "${extraOpts[@]}"; then return 1; fi
1022 #record the working directory provided by the batch system
1023 batchWorkingDirectory=${PWD}
1025 [[ -z ${configFile} ]] && configFile="benchmark.config"
1026 [[ ! -f ${configFile} ]] && echo "no config file found (${configFile})" && return 1
1028 if [[ ! $(which makeflow &>/dev/null) && -n ${makeflowPath} ]]; then
1029 echo "setting the makflow path from the config: "
1030 echo " export PATH=${makeflowPath}:${PATH}"
1031 export PATH=${makeflowPath}:${PATH}
1034 #create the common output dir and the meta dir
1035 commonOutputPath=${baseOutputDirectory}/${productionID}
1036 if [[ -d ${commonOutputPath} ]]; then
1037 echo "output dir ${commonOutputPath} exists!"
1040 mkdir -p ${commonOutputPath}
1042 mkdir -p ${commonOutputPath}/meta
1045 #if which greadlink; then self=$(greadlink -f "${0}"); fi
1047 #for reference copy the setup to the output dir
1048 paranoidCp ${self} ${commonOutputPath}
1049 paranoidCp ${configFile} ${commonOutputPath}
1050 paranoidCp ${inputFileList} ${commonOutputPath}
1052 #submit - use makeflow if available, fall back to old stuff when makeflow not there
1053 if which makeflow; then
1054 goGenerateMakeflow ${productionID} ${inputFileList} ${configFile} "${extraOpts[@]}" commonOutputPath=${commonOutputPath} > benchmark.makeflow
1055 cp benchmark.makeflow ${commonOutputPath}
1056 makeflow ${makeflowOptions} benchmark.makeflow
1061 #summarize the run based on the makeflow log
1062 #and add it to the end of summary log
1063 awk '/STARTED/ {startTime=$3}
1064 /COMPLETED/ {endTime=$3}
1065 END {print "makeflow running time: "(endTime-startTime)/1000000/3600" hours"}' \
1066 benchmark.makeflow.makeflowlog | tee -a summary.log
1067 paranoidCp summary.log ${commonOutputPath}
1072 goGenerateMakeflow()
1074 #generate the makeflow file
1075 [[ $# -lt 3 ]] && echo "args: id inputFileList configFile" && return 1
1082 #batch systems/makeflow sometimes handle spaces in arguments poorly, so encode them
1083 for (( i=0;i<${#extraOpts[@]};i++ )); do
1084 extraOpts[i]=$(encSpaces "${extraOpts[i]}")
1086 extraOpts+=("encodedSpaces=1")
1088 if ! parseConfig ${configFile} "${extraOpts[@]}" &>/dev/null; then return 1; fi
1091 if [[ -z ${commonOutputPath} ]]; then
1092 commonOutputPath=${baseOutputDirectory}/${productionID}
1093 extraOpts=( "${extraOpts[@]}" "commonOutputPath=${commonOutputPath}" )
1096 #record the working directory provided by the batch system
1097 batchWorkingDirectory=${PWD}
1099 [[ -z ${configFile} ]] && configFile="benchmark.config"
1100 [[ ! -f ${configFile} ]] && echo "no config file found (${configFile})" && return 1
1102 #these files will be made a dependency - will be copied to the working dir of the jobs
1103 declare -a copyFiles
1106 "localOCDBaccessConfig.C"
1110 "recCPass1_OuterDet.C"
1116 for file in ${inputFiles[*]}; do
1117 [[ -f ${file} ]] && copyFiles+=("${file}")
1120 #create the makeflow file
1121 [[ -n ${batchFlags} ]] && echo "BATCH_OPTIONS = ${batchFlags}"
1122 declare -A arr_cpass0_merged arr_cpass1_merged
1123 declare -A arr_cpass0_calib_list arr_cpass1_calib_list
1124 declare -A arr_cpass1_QA_list arr_cpass1_ESD_list arr_cpass1_filtered_list
1125 declare -A arr_cpass0_profiled_outputs
1126 declare -A listOfRuns
1127 [[ -n ${runNumber} ]] && listOfRuns[${runNumber}]=1
1128 while read x; do tmpRun=$(guessRunNumber ${x}); [[ -n ${tmpRun} ]] && listOfRuns[${tmpRun}]=1; done < ${inputFileList}
1129 for runNumber in "${!listOfRuns[@]}"; do
1130 [[ -z ${runNumber} ]] && continue
1131 [[ ! ${runNumber} =~ ^[0-9]*[0-9]$ ]] && continue
1133 unset arr_cpass0_outputs
1134 unset arr_cpass1_outputs
1135 declare -a arr_cpass0_outputs
1136 declare -a arr_cpass1_outputs
1139 echo "### Automatically generated on $(LANG=C date) ###"
1144 while read inputFile; do
1145 currentDefaultOCDB=${defaultOCDB}
1146 [[ -z ${autoOCDB} ]] && autoOCDB=1
1147 if [[ ${autoOCDB} -ne 0 ]]; then
1148 currentDefaultOCDB=$(setYear ${inputFile} ${defaultOCDB})
1150 guessRunData ${inputFile}
1153 echo "### Variables ###"
1154 echo "OUTPATH=\"${commonOutputPath}/${year}/${period}\""
1158 #arr_cpass0_outputs[${jobindex}]="${commonOutputPath}/meta/cpass0.job${jobindex}.run${runNumber}.done"
1159 arr_cpass0_outputs[${jobindex}]="cpass0.job${jobindex}.run${runNumber}.done"
1160 echo "### CPass0 ###"
1161 echo "${arr_cpass0_outputs[${jobindex}]}: benchmark.sh ${configFile} ${copyFiles[@]}"
1162 echo " ${alirootEnv} ./benchmark.sh CPass0 \$OUTPATH/000${runNumber}/cpass0 ${inputFile} ${nEvents} ${currentDefaultOCDB} ${configFile} ${runNumber} ${jobindex} ${extraOpts[@]}"" "
1166 #arr_cpass1_outputs[${jobindex}]="${commonOutputPath}/meta/cpass1.job${jobindex}.run${runNumber}.done"
1167 arr_cpass1_outputs[${jobindex}]="cpass1.job${jobindex}.run${runNumber}.done"
1168 echo "### CPass1 ###"
1169 echo "${arr_cpass1_outputs[${jobindex}]}: benchmark.sh ${configFile} cpass0.localOCDB.${runNumber}.tgz.done ${copyFiles[@]}"
1170 echo " ${alirootEnv} ./benchmark.sh CPass1 \$OUTPATH/000${runNumber}/cpass1 ${inputFile} ${nEvents} ${currentDefaultOCDB} ${configFile} ${runNumber} ${jobindex} ${extraOpts[@]}"" "
1174 done< <(grep "/000${runNumber}/" ${inputFileList})
1176 #CPass0 list of Calib files to merge
1177 #arr_cpass0_calib_list[${runNumber}]="${commonOutputPath}/meta/cpass0.calib.run${runNumber}.list"
1178 arr_cpass0_calib_list[${runNumber}]="cpass0.calib.run${runNumber}.list"
1179 echo "### Produces the list of CPass0 files to merge (executes locally) ###"
1180 echo "${arr_cpass0_calib_list[${runNumber}]}: benchmark.sh ${arr_cpass0_outputs[*]}"
1181 echo " LOCAL ./benchmark.sh PrintValues calibfile ${arr_cpass0_calib_list[${runNumber}]} ${arr_cpass0_outputs[*]} && mkdir -p \$OUTPATH/meta && cp ${arr_cpass0_calib_list[${runNumber}]} \$OUTPATH/meta/${arr_cpass0_calib_list[${runNumber}]}"
1185 echo "### Merges CPass0 files ###"
1186 #arr_cpass0_merged[${runNumber}]="${commonOutputPath}/meta/merge.cpass0.run${runNumber}.done"
1187 arr_cpass0_merged[${runNumber}]="merge.cpass0.run${runNumber}.done"
1188 echo "cpass0.localOCDB.${runNumber}.tgz.done ${arr_cpass0_merged[${runNumber}]}: benchmark.sh ${configFile} ${arr_cpass0_calib_list[${runNumber}]} ${copyFiles[@]}"
1189 echo " ${alirootEnv} ./benchmark.sh MergeCPass0 \$OUTPATH/000${runNumber}/cpass0 ${currentDefaultOCDB} ${configFile} ${runNumber} ${arr_cpass0_calib_list[${runNumber}]} ${extraOpts[@]}"" "
1192 #CPass1 list of Calib/QA/ESD/filtered files
1193 # the trick with QA is to have the string "Stage.txt" in the file name of the list of directories with QA output to trigger
1194 # the production of the QA trending tree (only then the task->Finish() will be called in QAtrain_duo.C, on the grid
1195 # this corresponds to the last merging stage)
1196 #arr_cpass1_QA_list[${runNumber}]="${commonOutputPath}/meta/cpass1.QA.run${runNumber}.lastMergingStage.txt.list"
1197 arr_cpass1_QA_list[${runNumber}]="cpass1.QA.run${runNumber}.lastMergingStage.txt.list"
1198 echo "### Lists CPass1 QA ###"
1199 echo "${arr_cpass1_QA_list[${runNumber}]}: benchmark.sh ${arr_cpass1_outputs[*]}"
1200 echo " LOCAL ./benchmark.sh PrintValues dir ${arr_cpass1_QA_list[${runNumber}]} ${arr_cpass1_outputs[*]} && mkdir -p \$OUTPATH/meta && cp ${arr_cpass1_QA_list[${runNumber}]} \$OUTPATH/meta/${arr_cpass1_QA_list[${runNumber}]}"
1203 #arr_cpass1_calib_list[${runNumber}]="${commonOutputPath}/meta/cpass1.calib.run${runNumber}.list"
1204 arr_cpass1_calib_list[${runNumber}]="cpass1.calib.run${runNumber}.list"
1205 echo "### Lists CPass1 Calib ###"
1206 echo "${arr_cpass1_calib_list[${runNumber}]}: benchmark.sh ${arr_cpass1_outputs[*]}"
1207 echo " LOCAL ./benchmark.sh PrintValues calibfile ${arr_cpass1_calib_list[${runNumber}]} ${arr_cpass1_outputs[*]} && mkdir -p \$OUTPATH/meta && cp ${arr_cpass1_calib_list[${runNumber}]} \$OUTPATH/meta/${arr_cpass1_calib_list[${runNumber}]}"
1210 #arr_cpass1_ESD_list[${runNumber}]="${commonOutputPath}/meta/cpass1.ESD.run${runNumber}.list"
1211 arr_cpass1_ESD_list[${runNumber}]="cpass1.ESD.run${runNumber}.list"
1212 echo "### Lists CPass1 ESDs ###"
1213 echo "${arr_cpass1_ESD_list[${runNumber}]}: benchmark.sh ${arr_cpass1_outputs[*]}"
1214 echo " LOCAL ./benchmark.sh PrintValues esd ${arr_cpass1_ESD_list[${runNumber}]} ${arr_cpass1_outputs[*]} && mkdir -p \$OUTPATH/meta && cp ${arr_cpass1_ESD_list[${runNumber}]} \$OUTPATH/meta/${arr_cpass1_ESD_list[${runNumber}]}"
1217 #arr_cpass1_filtered_list[${runNumber}]="${commonOutputPath}/meta/cpass1.filtered.run${runNumber}.list"
1218 arr_cpass1_filtered_list[${runNumber}]="cpass1.filtered.run${runNumber}.list"
1219 echo "### Lists CPass1 filtered ###"
1220 echo "${arr_cpass1_filtered_list[${runNumber}]}: benchmark.sh ${arr_cpass1_outputs[*]}"
1221 echo " LOCAL ./benchmark.sh PrintValues filteredTree ${arr_cpass1_filtered_list[${runNumber}]} ${arr_cpass1_outputs[*]} && mkdir -p \$OUTPATH/meta && cp ${arr_cpass1_filtered_list[${runNumber}]} \$OUTPATH/meta/${arr_cpass1_filtered_list[${runNumber}]}"
1225 #arr_cpass1_merged[${runNumber}]="${commonOutputPath}/meta/merge.cpass1.run${runNumber}.done"
1226 arr_cpass1_merged[${runNumber}]="merge.cpass1.run${runNumber}.done"
1227 echo "### Merges CPass1 files ###"
1228 echo "cpass1.localOCDB.${runNumber}.tgz.done ${arr_cpass1_merged[${runNumber}]}: benchmark.sh ${configFile} ${arr_cpass1_calib_list[${runNumber}]} ${arr_cpass1_QA_list[${runNumber}]} ${copyFiles[@]}"
1229 echo " ${alirootEnv} ./benchmark.sh MergeCPass1 \$OUTPATH/000${runNumber}/cpass1 ${currentDefaultOCDB} ${configFile} ${runNumber} ${arr_cpass1_calib_list[${runNumber}]} ${arr_cpass1_QA_list[${runNumber}]} ${arr_cpass1_filtered_list[${runNumber}]} ${extraOpts[@]}"" "
1232 #CPass0 wrapped in a profiling tool (valgrind,....)
1233 if [[ -n ${profilingCommand} ]]; then
1234 inputFile=$(grep -m1 "${runNumber}/" ${inputFileList})
1235 [[ -z ${nEventsProfiling} ]] && nEventsProfiling=2
1236 currentDefaultOCDB=$(setYear ${inputFile} ${defaultOCDB})
1237 jobindex="profiling"
1239 #arr_cpass0_profiled_outputs[${runNumber}]="${commonOutputPath}/meta/profiling.cpass0.job${jobindex}.run${runNumber}.done"
1240 arr_cpass0_profiled_outputs[${runNumber}]="profiling.cpass0.job${jobindex}.run${runNumber}.done"
1241 echo "### CPass0 in a profiler ###"
1242 echo "${arr_cpass0_profiled_outputs[${runNumber}]}: benchmark.sh ${configFile} ${copyFiles[@]}"
1243 profilingCommand=$(encSpaces "${profilingCommand}")
1244 echo " ${alirootEnv} ./benchmark.sh CPass0 \$OUTPATH/000${runNumber}/${jobindex} ${inputFile} ${nEventsProfiling} ${currentDefaultOCDB} ${configFile} ${runNumber} ${jobindex} ${extraOpts[@]} useProfilingCommand=${profilingCommand}"
1251 echo "### Summary ###"
1252 echo "summary.log: benchmark.sh ${configFile} ${arr_cpass1_merged[*]}"
1253 echo " ${alirootEnv} ./benchmark.sh MakeSummary ${configFile} ${extraOpts[@]}"
1261 #print the values given the key from any number of files (store in output file on second argument)
1262 if [[ $# -lt 3 ]]; then
1263 echo "goPrintValues key outputFile inputFiles"
1264 echo "if outputFile is \"-\" don't redirect to a file"
1269 [[ ${outputFile} =~ "-" ]] && outputFile=""
1270 shift 2 #remove 2 first arguments from arg list to only pass the input files to awk
1271 awk -v key=${key} '$0 ~ key" " {print $2}' "$@" | tee ${outputFile}
1278 mergedQAfileList=${1}
1283 if ! parseConfig ${configFile} "$@"; then return 1; fi
1285 #record the working directory provided by the batch system
1286 batchWorkingDirectory=${PWD}
1288 [[ -f ${alirootSource} && -z ${ALICE_ROOT} ]] && source ${alirootSource}
1290 [[ -z ${logOutputDir} ]] && logOutputDir=${PWD}
1291 [[ -z ${dontRedirectStdOutToLog} ]] && exec &> ${logOutputDir}/makeQAplots.log
1295 mkdir -p ${outputDir}
1297 [[ ! "${PWD}" =~ "${outputDir}" ]] && echo "PWD is not equal to outputDir=${outputDir}" && cd ${olddir} && return 1
1300 "${batchWorkingDirectory}/runQA.sh"
1301 "${ALICE_ROOT}/PWGPP/QA/scripts/runQA.sh"
1303 for file in ${inputFiles[*]}; do
1304 [[ ! -f ${file##*/} && -f ${file} ]] && echo "copying ${file}" && cp -f ${file} .
1307 echo "running QA with command:"
1308 echo ./runQA.sh inputList="${mergedQAfileList}" inputListHighPtTrees="${filteringList}" ocdbStorage="${defaultOCDB}"
1309 ./runQA.sh inputList="${mergedQAfileList}" inputListHighPtTrees="${filteringList}" ocdbStorage="${defaultOCDB}"
1322 # save aliroot repository info
1323 [[ -z "${ALICE_ROOT}" ]] && return 1
1325 echo "\${ALICE_ROOT}=${ALICE_ROOT}"
1326 echo "\${ROOTSYS}=${ROOTSYS}"
1327 echo "\${PATH}=${PATH}"
1328 echo "\${LD_LIBRARY_PATH}=${LD_LIBRARY_PATH}"
1334 currentBranch=$(git rev-parse --abbrev-ref HEAD)
1338 git diff ${currentBranch}
1346 # ${1} - year to be set
1347 # ${2} - where to set the year
1348 year1=$(guessYear ${1})
1349 year2=$(guessYear ${2})
1351 [[ ${year1} -ne ${year2} && -n ${year2} && -n ${year1} ]] && path=${2/\/${year2}\//\/${year1}\/}
1358 #guess the period from the path, pick the rightmost one
1360 declare -a path=( ${1} )
1361 local dirDepth=${#path[*]}
1362 for ((x=${dirDepth}-1;x>=0;x--)); do
1363 local field=${path[${x}]}
1364 [[ ${field} =~ ^LHC[0-9][0-9][a-z]$ ]] && period=${field} && break
1372 #guess the year from the path, pick the rightmost one
1374 declare -a path=( ${1} )
1375 local dirDepth=${#path[*]}
1376 for ((x=${dirDepth}-1;x>=0;x--)); do
1377 local field=${path[${x}]}
1378 [[ ${field} =~ ^20[0-9][0-9]$ ]] && year=${field} && break
1386 #guess the run number from the path, pick the rightmost one
1387 #works for /path/foo/000123456/bar/...
1388 #and /path/foo.run123456.bar
1390 declare -a path=( ${1} )
1391 local dirDepth=${#path[*]}
1392 for ((x=${dirDepth}-1;x>=0;x--)); do
1393 local field=${path[${x}]}
1394 field=${field/run/000}
1395 [[ ${field} =~ [0-9][0-9][0-9][0-9][0-9][0-9]$ ]] && runNumber=${field#000} && break
1407 'error while loading shared libraries'
1410 'Thread [0-9]* (Thread'
1413 '\.C.*error:.*\.h: No such file'
1419 'rocVoltage out of range:'
1423 local errorSummary=""
1424 local warningSummary=""
1426 for ((i=0; i<${#errorConditions[@]};i++)); do
1427 local tmp=$(grep -m1 -e "${errorConditions[${i}]}" ${log})
1428 [[ -n ${tmp} ]] && tmp+=" : "
1429 errorSummary+=${tmp}
1432 for ((i=0; i<${#warningConditions[@]};i++)); do
1433 local tmp=$(grep -m1 -e "${warningConditions[${i}]}" ${log})
1434 [[ -n ${tmp} ]] && tmp+=" : "
1435 warningSummary+=${tmp}
1438 if [[ -n ${errorSummary} ]]; then
1439 echo "${errorSummary}"
1443 if [[ -n ${warningSummary} ]]; then
1444 echo "${warningSummary}"
1453 #print a summary of logs
1460 #put dir information in the output
1465 for log in ${logFiles[*]}; do
1466 finallog=${PWD%/}/${log}
1467 [[ ! -f ${log} ]] && continue
1468 errorSummary=$(validateLog ${log})
1470 if [[ ${validationStatus} -eq 0 ]]; then
1471 #in pretend mode randomly report an error in rec.log some cases
1472 if [[ -n ${pretend} && "${log}" == "rec.log" ]]; then
1473 #[[ $(( ${RANDOM}%2 )) -ge 1 ]] && echo "${finallog} BAD random error" || echo "${finallog} OK"
1474 echo "${finallog} OK"
1476 echo "${finallog} OK"
1478 elif [[ ${validationStatus} -eq 1 ]]; then
1479 echo "${finallog} BAD ${errorSummary}"
1481 elif [[ ${validationStatus} -eq 2 ]]; then
1482 echo "${finallog} OK MWAH ${errorSummary}"
1490 gdb --batch --quiet -ex "bt" -ex "quit" aliroot ${x} > stacktrace_${x//\//_}.log
1491 done < <(/bin/ls ${PWD}/*/core 2>/dev/null; /bin/ls ${PWD}/core 2>/dev/null)
1496 spitOutLocalOCDBaccessConfig()
1499 #find ${1} -name "*root" | \
1500 /bin/ls -1 ${1}/*/*/*/*.root 2>/dev/null | \
1503 local tmp=${line#${1}}
1505 awk -v ocdb=${1} '{print " man->SetSpecificStorage(\""$1"\",\"local://"ocdb"\");"}'
1510 goMakeLocalOCDBaccessConfig()
1513 # make a script that sets the specific storages form all the root files produced by CPass0
1514 local localOCDBpathCPass0=${1}
1515 local OCDBpathPrefix=${2}
1516 [[ -z ${OCDBpathPrefix} ]] && OCDBpathPrefix="."
1518 if [[ -f ${localOCDBpathCPass0} && ${localOCDBpathCPass0} =~ \.tgz$ ]]; then
1519 tar xzf ${localOCDBpathCPass0}
1520 local localOCDBpathCPass0="${OCDBpathPrefix}/OCDB"
1524 echo creating the specific storage script
1525 echo localOCDBaccessConfig.C
1526 echo based on OCDB: ${localOCDBaccessConfig}
1529 local tempLocalOCDB=""
1530 if [[ -f localOCDBaccessConfig.C ]]; then
1531 tempLocalOCDB=$(mktemp -t tempLocalOCDB.XXXXXX)
1532 echo "egrep "SetSpecificStorage" localOCDBaccessConfig.C > ${tempLocalOCDB}"
1533 egrep "SetSpecificStorage" localOCDBaccessConfig.C > ${tempLocalOCDB}
1536 echo "localOCDBaccessConfig()" > localOCDBaccessConfig.C
1537 echo "{" >> localOCDBaccessConfig.C
1538 echo " AliCDBManager* man = AliCDBManager::Instance();" >> localOCDBaccessConfig.C
1539 spitOutLocalOCDBaccessConfig ${localOCDBpathCPass0}|sort|uniq >> localOCDBaccessConfig.C
1540 [[ -f "${tempLocalOCDB}" ]] && cat ${tempLocalOCDB} >> localOCDBaccessConfig.C
1541 echo "}" >> localOCDBaccessConfig.C
1543 [[ -f "${tempLocalOCDB}" ]] && rm -f ${tempLocalOCDB}
1545 if ! grep SetSpecificStorage localOCDBaccessConfig.C; then
1547 echo "!!!!!!! CPass0 produced no OCDB entries"
1553 goMakeFilteredTrees()
1557 #get path to input list
1559 #get scale number for tracks
1561 #get scale number for V0s
1563 #get OCDB path (optional)
1565 #get max number of files
1566 maxFiles=${7-"1000000"}
1567 #get offset of first file
1569 #get max number of events
1570 maxEvents=${9-"30000000"}
1571 #get offset of first event
1572 offsetEvent=${10-"0"}
1573 configFile=${11-"benchmark.config"}
1574 esdFileName=${12-"AliESDs_Barrel.root"}
1576 if ! parseConfig ${configFile} "$@"; then return 1; fi
1578 #record the working directory provided by the batch system
1579 batchWorkingDirectory=${PWD}
1581 [[ -z ${commonOutputPath} ]] && commonOutputPath=${PWD}
1582 doneFileBase=filtering.cpass1.run${runNumber}.done
1583 doneFileTmp=${batchWorkingDirectory}/${doneFileBase}
1584 doneFile=${commonOutputPath}/meta/${doneFileBase}
1586 cat > filtering.log << EOF
1587 goMakeFilteredTrees config:
1589 outputDir=${outputDir}
1590 commonOutputPath=${commonOutputPath}
1591 ALICE_ROOT=${ALICE_ROOT}
1593 offsetEvent=$offsetEvent
1594 configFile=$configFile
1595 esdFileName=$esdFileName
1596 inputListfiles=$inputListfiles
1600 #runpath=${outputDir}
1601 #[[ ${reconstructInTemporaryDir} -eq 1 && -n ${TMPDIR} ]] && runpath=${TMPDIR}
1602 #[[ ${reconstructInTemporaryDir} -eq 1 ]] && runpath=$(mktemp -d -t goMakeFilteredTrees.XXXXXX)
1603 #mkdir -p ${outputDir}
1604 #mkdir -p ${runpath}
1605 #if ! cd ${runpath}; then
1606 # echo "PWD=$PWD is not the runpath=${runpath}"
1611 if [[ -z ${pretend} ]];then
1612 aliroot -l -b -q "${ALICE_ROOT}/PWGPP/macros/runFilteringTask.C(\"${inputListfiles}\",${filterT},${filterV},\"${OCDBpath}\",${maxFiles},${offsetFile},${maxEvents},${offsetEvent},\"${esdFileName}\")" &>> filtering.log
1614 sleep ${pretendDelay}
1615 touch filtering.log FilterEvents_Trees.root
1619 summarizeLogs >> ${doneFile}
1621 #echo mv -f * ${outputDir}
1622 #mv -f * ${outputDir}
1623 #[[ -f ${outputDir}/FilterEvents_Trees.root ]] && echo "filteredTree ${outputDir}/FilterEvents_Trees.root" >> ${doneFile}
1624 #cd ${commonOutputPath}
1625 #[[ "${runpath}" != "${outputDir}" ]] && rm -rf ${runpath}
1627 cp "$doneFileTmp" "$doneFile" || rm -f "$doneFileTmp" "$doneFile"
1628 [[ -n ${removeTMPdoneFile} ]] && rm -f ${doneFileTmp}
1636 [[ $# -lt 5 ]] && echo "at least 5 args needed, you supplied $#" && return 1
1643 local commandArgs=("$@")
1645 #add quote strings around the extra arguments
1646 for ((i=0; i<${#commandArgs[@]}; i++)); do
1647 commandArgs[i]=\"${commandArgs[i]}\"
1650 [[ -z ${waitForJOBID} ]] && waitForJOBID=0
1652 newFarm=$(which qsub|grep "^/usr/bin/qsub")
1656 if [[ -z "${newFarm}" ]]
1659 # submit it (as job array)
1660 nFiles=$(( ${endID}-${startID}+1 ))
1661 while [ ${startID} -le ${nFiles} ] ; do
1662 if [ $(expr ${nFiles} - ${startID}) -gt 999 ] ; then
1663 endID=$(expr ${startID} + 999)
1667 if [[ ${waitForJOBID} -eq 0 ]]; then
1668 echo ${batchCommand} ${batchFlags} -J "${JobID}[${startID}-${endID}]" -e "${commonOutputPath}/logs/job_%I.err" -o "${commonOutputPath}/logs/job_%I.out" "${command}"
1669 ${batchCommand} ${batchFlags} -J "${JobID}[${startID}-${endID}]" -e "${commonOutputPath}/logs/job_%I.err" -o "${commonOutputPath}/logs/job_%I.out" "${command}"
1671 echo ${batchCommand} ${batchFlags} -J "${JobID}[${startID}-${endID}]" -w "ended(${waitForJOBID})" -e "${commonOutputPath}/logs/job_%I.err" -o "${commonOutputPath}/logs/job_%I.out" "${command}"
1672 ${batchCommand} ${batchFlags} -J "${JobID}[${startID}-${endID}]" -w "ended(${waitForJOBID})" -e "${commonOutputPath}/logs/job_%I.err" -o "${commonOutputPath}/logs/job_%I.out" "${command}"
1674 startID=$(expr ${endID} + 1)
1678 if [[ ${waitForJOBID} =~ "000" ]]; then
1679 echo ${batchCommand} ${batchFlags} -wd ${commonOutputPath} -b y -v commonOutputPath -N "${JobID}" -t "${startID}-${endID}" -e "${commonOutputPath}/logs/" -o "${commonOutputPath}/logs/" "${command}" "${commandArgs[@]}"
1680 ${batchCommand} ${batchFlags} -wd ${commonOutputPath} -b y -v commonOutputPath -N "${JobID}" -t "${startID}-${endID}" -e "${commonOutputPath}/logs/" -o "${commonOutputPath}/logs/" "${command}" "${commandArgs[@]}"
1682 echo ${batchCommand} ${batchFlags} -wd ${commonOutputPath} -b y -v commonOutputPath -N "${JobID}" -t "${startID}-${endID}" -hold_jid "${waitForJOBID}" -e "${commonOutputPath}/logs/" -o "${commonOutputPath}/logs/" "${command}" "${commandArgs[@]}"
1683 ${batchCommand} ${batchFlags} -wd ${commonOutputPath} -b y -v commonOutputPath -N "${JobID}" -t "${startID}-${endID}" -hold_jid "${waitForJOBID}" -e "${commonOutputPath}/logs/" -o "${commonOutputPath}/logs/" "${command}" "${commandArgs[@]}"
1691 if [[ $# -lt 3 ]]; then
1693 echo " ${0} submit fileList productionID configFile"
1699 configFile=${3:-"benchmark.config"}
1700 #if which greadlink; then configFile=$(greadlink -f ${configFile}); fi
1703 if ! parseConfig ${configFile} "${extraOpts[@]}"; then return 1; fi
1705 #batch systems/makeflow sometimes handle spaces in arguments poorly, so encode them
1706 for (( i=0;i<${#extraOpts[@]};i++ )); do
1707 extraOpts[i]=$(encSpaces "${extraOpts[i]}")
1709 extraOpts+=("encodedSpaces=1")
1710 #this removes the copy of the done file used by makeflow (in the running dir)
1711 extraOpts+=("removeTMPdoneFile=1")
1713 #record the working directory provided by the batch system
1714 batchWorkingDirectory=${PWD}
1716 #redirect all output to submit.log
1717 echo "redirecting all output to ${PWD}/submit_${productionID//"/"/_}.log"
1719 exec 1>submit_${productionID//"/"/_}.log 2>&1
1722 echo ${0}" submit $*"
1723 if [[ -z "${inputList}" || -z "${productionID}" ]]
1726 echo " Usage: ${0} submit inputList productionID [configFile=benchmark.config]"
1731 # check if config file is there
1732 if [ ! -f ${configFile} ]; then
1733 echo "ERROR! Config File '${configFile}' not found" >&2
1736 echo "Using Config File: '${configFile}'"
1739 [[ ! -f ${alirootEnv} ]] && echo "alirootEnv script ${alirootEnv} not found!..." && return 1
1741 #move the script, config and some other stuff to ${commonOutputPath} first, then use them from there
1743 #if which greadlink; then self=$(greadlink -f "${0}"); fi
1744 configPath=$(dirname ${configFile})
1745 export commonOutputPath=${baseOutputDirectory}/${productionID}
1747 mkdir -p ${commonOutputPath}
1748 mkdir -p ${commonOutputPath}/logs
1749 mkdir -p ${commonOutputPath}/meta
1751 cp ${self} ${commonOutputPath}
1752 cp ${configFile} ${commonOutputPath}
1753 cp ${inputList} ${commonOutputPath}
1754 self=${commonOutputPath}/${self##*/}
1756 configFile=${commonOutputPath}/${configFile##*/}
1757 inputList=${commonOutputPath}/${inputList##*/}
1759 #convert to absolut pathnames
1760 #if which greadlink; then inputList=$(greadlink -f "${inputList}"); fi
1762 if [[ -z ${runNumber} ]]; then
1763 listOfRuns=($(while read x; do guessRunNumber ${x}; done < ${inputList} | sort | uniq))
1765 listOfRuns=${runNumber}
1768 #if which greadlink; then alirootSource=$(greadlink -f "${alirootSource}"); fi
1771 echo "### BEGIN CONFIGURATION ###"
1775 echo " productionID: ${productionID}"
1776 echo " batchCommand: ${batchCommand}"
1777 echo " batchFlags: ${batchFlags}"
1778 echo " alirootEnv: ${alirootEnv}"
1779 ${alirootEnv} echo ' ALICE_ROOT: ${ALICE_ROOT}'
1780 ${alirootEnv} echo ' ALIROOT_RELEASE: ${ALICE_RELEASE}'
1781 echo " inputList: ${inputList}"
1782 echo " configPath: ${configPath}"
1783 echo " commonOutputPath: ${commonOutputPath}"
1784 echo " defaultOCDB: ${defaultOCDB}"
1785 echo " autoOCDB: ${autoOCDB}"
1786 echo " recoTriggerOptions: ${recoTriggerOptions}"
1788 echo " ${listOfRuns[*]}"
1790 echo "THE TRAIN WILL RUN:"
1792 if [ ${runCPass0reco} -eq 1 ]; then
1793 echo " Pass0 - Recontruction"
1796 if [ ${runCPass0MergeMakeOCDB} -eq 1 ]; then
1797 echo " Pass0 - merging and OCDB export"
1800 if [ ${runCPass1reco} -eq 1 ]; then
1801 echo " Pass1 - Recontruction"
1803 if [ ${runCPass1MergeMakeOCDB} -eq 1 ]; then
1804 echo " Pass1 - merging and OCDB export"
1809 echo " max. Events/Chunk: ${nEvents}"
1810 echo " max. Number of Chunks per Run: ${nMaxChunks}"
1812 echo "### END CONFIGURATION ###"
1816 # check if input file is there
1817 if [ ! -f ${inputList} ]; then
1818 echo "ERROR! Input List '${inputList}' not found" >&2
1822 # define jobid (for dependent jobs)
1823 date=$(date +%Y_%m_%d_%H%M%S)
1824 #for each run we submit one jobarray:
1825 for runNumber in ${listOfRuns[*]}; do
1827 [[ -z ${runNumber} ]] && continue
1828 [[ ! ${runNumber} =~ ^[0-9]*[0-9]$ ]] && continue
1830 JOBpostfix="${productionID//"/"/_}_${runNumber}_${date}"
1831 JOBID1="p0_${JOBpostfix}"
1832 JOBID1wait="w0_${JOBpostfix}"
1833 JOBID2="m0_${JOBpostfix}"
1834 JOBID2wait="wm0_${JOBpostfix}"
1835 JOBID3="op0_${JOBpostfix}"
1836 JOBID3wait="wop0_${JOBpostfix}"
1837 JOBID4="p1_${JOBpostfix}"
1838 JOBID4wait="w1_${JOBpostfix}"
1839 JOBID5="m1_${JOBpostfix}"
1840 JOBID5wait="wm1_${JOBpostfix}"
1841 JOBID6="s1_${JOBpostfix}"
1842 JOBID6wait="ws1_${JOBpostfix}"
1843 JOBID7="QA_${JOBpostfix}"
1844 JOBmakeESDlistCPass1="lp1_${JOBpostfix}"
1845 JOBfilterESDcpass1="fp1_${JOBpostfix}"
1848 oneInputFile=$(egrep -m1 "${runNumber}/" ${inputList})
1850 currentDefaultOCDB=${defaultOCDB}
1851 [[ -z ${autoOCDB} ]] && autoOCDB=1
1852 if [[ ${autoOCDB} -ne 0 ]]; then
1853 currentDefaultOCDB=$(setYear ${oneInputFile} ${defaultOCDB})
1855 period=$(guessPeriod ${oneInputFile})
1856 year=$(guessYear ${oneInputFile})
1858 echo "submitting run ${runNumber} with OCDB ${currentDefaultOCDB}"
1860 ###############################################################################
1861 #run one chunk with valgrind:
1862 if [[ -n ${profilingCommand} ]]; then
1863 [[ -z ${nEventsProfiling} ]] && nEventsProfiling=2
1864 [[ -z ${profilingCommand} ]] && profilingCommand="/usr/bin/valgrind --tool=callgrind --num-callers=40 -v --trace-children=yes"
1865 submit "profile-${JOBpostfix}" 1 1 000 "${alirootEnv} ${self}" CPass0 ${commonOutputPath}/${year}/${period}/000${runNumber}/${jobindex} ${oneInputFile} ${nEventsProfiling} ${currentDefaultOCDB} ${configFile} ${runNumber} ${jobindex} useProfilingCommand=$(encSpaces "${profilingCommand}") "${extraOpts[@]}"
1868 ################################################################################
1869 ################################################################################
1870 # run the CPass0 if requested
1872 if [ ${runCPass0reco} -eq 1 ]; then
1875 echo "starting CPass0... for run ${runNumber}"
1878 # create directory and copy all files that are needed
1879 targetDirectory="${commonOutputPath}/${year}/${period}/000${runNumber}/cpass0"
1880 mkdir -p ${targetDirectory}
1883 "${configPath}/runCPass0.sh"
1884 "${configPath}/recCPass0.C"
1885 "${configPath}/runCalibTrain.C"
1886 "${configPath}/localOCDBaccessConfig.C"
1887 "${configPath}/OCDB*.root"
1888 "${configPath}/sim.C"
1889 "${configPath}/rec.C"
1890 "${configPath}/Config.C"
1892 for file in ${filesCPass0[*]}; do
1893 [[ -f ${file} ]] && echo "copying ${file}" && cp -f ${file} ${commonOutputPath}
1896 localInputList=${targetDirectory}/${inputList##*/}
1897 [[ ! -f ${localInputList} ]] && egrep "\/000${runNumber}\/" ${inputList} > ${localInputList}
1898 # limit nFiles to nMaxChunks
1899 nFiles=$(wc -l < ${localInputList})
1900 [[ ${nFiles} -eq 0 ]] && echo "list contains ZERO files! exiting..." && return 1
1901 echo "raw files in list: ${nFiles}"
1902 if [[ ${nMaxChunks} -gt 0 && ${nMaxChunks} -le ${nFiles} ]]; then
1903 nFiles=${nMaxChunks}
1905 echo "raw files to process: ${nFiles}"
1906 [[ -z "${percentProcessedFilesToContinue}" ]] && percentProcessedFilesToContinue=100
1907 if [[ ${percentProcessedFilesToContinue} -eq 100 ]]; then
1908 nFilesToWaitFor=${nFiles}
1910 nFilesToWaitFor=$(( ${nFiles}-${nFiles}/(100/(100-${percentProcessedFilesToContinue})) ))
1912 echo "requested success rate is ${percentProcessedFilesToContinue}%"
1913 echo "merging will start after ${nFilesToWaitFor} jobs are done"
1915 submit ${JOBID1} 1 ${nFiles} 000 "${alirootEnv} ${self}" CPass0 ${targetDirectory} ${localInputList} ${nEvents} ${currentDefaultOCDB} ${configFile} ${runNumber} -1 "${extraOpts[@]}"
1917 ## submit a monitoring job that will run until a certain number of jobs are done with reconstruction
1918 submit "${JOBID1wait}" 1 1 000 "${alirootEnv} ${self}" WaitForOutput ${commonOutputPath} "meta/cpass0.job*.run${runNumber}.done" ${nFilesToWaitFor} ${maxSecondsToWait}
1919 LASTJOB=${JOBID1wait}
1921 fi #end running CPass0
1922 ################################################################################
1925 ################################################################################
1926 # submit merging of CPass0, depends on the reconstruction
1928 if [ ${runCPass0MergeMakeOCDB} -eq 1 ]; then
1931 echo "submit CPass0 merging for run ${runNumber}"
1934 targetDirectory="${commonOutputPath}/${year}/${period}/000${runNumber}/cpass0"
1935 mkdir -p ${targetDirectory}
1939 "${configPath}/OCDB.root"
1940 "${configPath}/mergeMakeOCDB.byComponent.sh"
1941 "${configPath}/mergeMakeOCDB.sh"
1942 "${configPath}/localOCDBaccessConfig.C"
1943 "${configPath}/mergeByComponent.C"
1944 "${configPath}/makeOCDB.C"
1945 "${configPath}/merge.C"
1947 for file in ${filesMergeCPass0[*]}; do
1948 [[ -f ${file} ]] && echo "copying ${file}" && cp -f ${file} ${commonOutputPath}
1951 submit ${JOBID2} 1 1 "${LASTJOB}" "${alirootEnv} ${self}" MergeCPass0 ${targetDirectory} ${currentDefaultOCDB} ${configFile} ${runNumber} cpass0.calib.run${runNumber}.list "${extraOpts[@]}"
1954 if [[ -n ${generateMC} ]]; then
1955 submit "mrl${JOBpostfix}" 1 1 "${LASTJOB}" "${alirootEnv} ${self}" PrintValues sim ${commonOutputPath}/meta/sim.run${runNumber}.list ${commonOutputPath}/meta/cpass0.job*.run${runNumber}.done
1956 LASTJOB="mrl${JOBpostfix}"
1961 # end of merging CPass0
1962 ################################################################################
1964 ################################################################################
1965 ################################################################################
1966 # run the CPass1 if requested
1968 if [ ${runCPass1reco} -eq 1 ]; then
1970 targetDirectory="${commonOutputPath}/${year}/${period}/000${runNumber}/cpass1"
1971 rm -f ${commonOutputPath}/meta/cpass1.job*.run${runNumber}.done
1973 # safety feature: if we are re-running for any reason we want to delete the previous output first.
1974 [[ -d ${targetDirectory} ]] && rm -rf ${targetDirectory}/* && echo "removed old output at ${targetDirectory}/*"
1977 echo "starting CPass1... for run ${runNumber}"
1980 # create directory and copy all files that are needed
1981 mkdir -p ${targetDirectory}
1984 "${configPath}/runCPass1.sh"
1985 "${configPath}/recCPass1.C"
1986 "${configPath}/recCPass1_OuterDet.C"
1987 "${configPath}/runCalibTrain.C"
1988 "${configPath}/QAtrain_duo.C"
1989 "${configPath}/localOCDBaccessConfig.C"
1990 "${configPath}/OCDB.root"
1992 for file in ${filesCPass1[*]}; do
1993 [[ -f ${file} ]] && echo "copying ${file}" && cp -f ${file} ${commonOutputPath}
1996 if [[ -n ${generateMC} ]]; then
1997 localInputList=${commonOutputPath}/meta/sim.run${runNumber}.list
1999 localInputList=${targetDirectory}/${inputList##*/}
2000 [[ ! -f ${localInputList} ]] && egrep "\/000${runNumber}\/" ${inputList} > ${localInputList}
2002 # limit nFiles to nMaxChunks
2003 nFiles=$(wc -l < ${localInputList})
2004 [[ ${nFiles} -eq 0 ]] && echo "list contains ZERO files! continuing..." && continue
2005 echo "raw files in list: ${nFiles}"
2006 if [[ ${nMaxChunks} -gt 0 && ${nMaxChunks} -le ${nFiles} ]]; then
2007 nFiles=${nMaxChunks}
2009 echo "raw files to process: ${nFiles}"
2010 [[ -z "${percentProcessedFilesToContinue}" ]] && percentProcessedFilesToContinue=100
2011 if [[ ${percentProcessedFilesToContinue} -eq 100 ]]; then
2012 nFilesToWaitFor=${nFiles}
2014 nFilesToWaitFor=$(( ${nFiles}-${nFiles}/(100/(100-${percentProcessedFilesToContinue})) ))
2016 echo "requested success rate is ${percentProcessedFilesToContinue}%"
2017 echo "merging will start after ${nFilesToWaitFor} jobs are done"
2019 submit ${JOBID4} 1 ${nFiles} "${LASTJOB}" "${alirootEnv} ${self}" CPass1 ${targetDirectory} ${localInputList} ${nEvents} ${currentDefaultOCDB} ${configFile} ${runNumber} -1 "${extraOpts[@]}"
2021 ################################################################################
2022 ## submit a monitoring job that will run until a certain number of jobs are done with reconstruction
2023 submit "${JOBID4wait}" 1 1 "${LASTJOB}" "${alirootEnv} ${self}" WaitForOutput ${commonOutputPath} "meta/cpass1.job*.run${runNumber}.done" ${nFilesToWaitFor} ${maxSecondsToWait}
2024 LASTJOB=${JOBID4wait}
2025 ################################################################################
2028 fi #end running CPass1
2030 ################################################################################
2031 # submit merging of CPass1, depends on the reconstruction
2032 if [ ${runCPass1MergeMakeOCDB} -eq 1 ]; then
2035 echo "submit CPass1 merging for run ${runNumber}"
2038 targetDirectory="${commonOutputPath}/${year}/${period}/000${runNumber}/cpass1"
2039 rm -f ${commonOutputPath}/meta/merge.cpass1.run${runNumber}.done
2040 mkdir -p ${targetDirectory}
2044 "${configPath}/OCDB.root"
2045 "${configPath}/localOCDBaccessConfig.C"
2046 "${configPath}/mergeMakeOCDB.byComponent.sh"
2047 "${configPath}/mergeByComponent.C"
2048 "${configPath}/makeOCDB.C"
2049 "${configPath}/merge.C"
2050 "${configPath}/mergeMakeOCDB.sh"
2051 "${configPath}/QAtrain_duo.C"
2053 for file in ${filesMergeCPass1[*]}; do
2054 [[ -f ${file} ]] && echo "copying ${file}" && cp -f ${file} ${commonOutputPath}
2057 submit "${JOBID5}" 1 1 "${LASTJOB}" "${alirootEnv} ${self}" MergeCPass1 ${targetDirectory} ${currentDefaultOCDB} ${configFile} ${runNumber} cpass1.calib.run${runNumber}.list cpass1.QA.run${runNumber}.lastMergingStage.txt.list cpass1.filtered.run${runNumber}.list "${extraOpts[@]}"
2062 ###############################
2063 #if [ ${runESDfiltering} -eq 1 ]; then
2064 # rm -f ${commonOutputPath}/cpass1.ESD.run${runNumber}.list
2065 # rm -f ${commonOutputPath}/meta/filtering.cpass1.run*.done
2067 # echo submitting filtering for run ${runNumber}
2069 # submit "${JOBmakeESDlistCPass1}" 1 1 "${LASTJOB}" "${self}" PrintValues esd ${commonOutputPath}/meta/cpass1.ESD.run${runNumber}.list ${commonOutputPath}/meta/cpass1.job*.run${runNumber}.done
2070 # submit "${JOBfilterESDcpass1}" 1 1 "${JOBmakeESDlistCPass1}" "${alirootEnv} ${self}" MakeFilteredTrees ${commonOutputPath}/${year}/${period}/000${runNumber}/cpass1 ${runNumber} ${commonOutputPath}/meta/cpass1.ESD.run${runNumber}.list ${filteringFactorHighPt} ${filteringFactorV0s} ${currentDefaultOCDB} 1000000 0 10000000 0 ${configFile} AliESDs_Barrel.root "${extraOpts[@]}"
2071 # LASTJOB=${JOBfilterESDcpass1}
2076 #################################################################################
2077 #################################################################################
2078 #if [ ${runESDfiltering} -eq 1 ]; then
2079 # submit "${JOBID5wait}" 1 1 "${LASTJOB}" "${self}" WaitForOutput ${commonOutputPath} "meta/filtering.cpass1.run*.done" "${#listOfRuns[@]}" ${maxSecondsToWait}
2081 submit "${JOBID5wait}" 1 1 "${LASTJOB}" "${self}" WaitForOutput ${commonOutputPath} "meta/merge.cpass1.run*.done" ${#listOfRuns[@]} ${maxSecondsToWait}
2083 LASTJOB=${JOBID5wait}
2085 #################################################################################
2087 echo "submit make a summary"
2090 [[ -z ${alirootEnvQA} ]] && alirootEnvQA=$(encSpaces "${alirootEnv}")
2091 submit "${JOBID6}" 1 1 "${LASTJOB}" "${alirootEnvQA} ${self}" MakeSummary ${configFile} "commonOutputPath=${commonOutputPath}"
2093 #################################################################################
2097 echo "jobs submitted."
2104 [[ $# -lt 3 ]] && echo "goWaitForOutput() wrong number of arguments, exiting.." && return 1
2105 echo searchPath=${1}
2107 echo numberOfFiles=${3}
2108 echo maxSecondsToWait=${4}
2112 maxSecondsToWait=${4}
2113 echo "command to be executed: /bin/ls -1 ${searchPath}/${fileName}"
2114 [[ -z "${maxSecondsToWait}" ]] && maxSecondsToWait=$(( 3600*12 ))
2116 n=$(/bin/ls -1 ${searchPath}/${fileName} 2>/dev/null | wc -l)
2117 [[ ${n} -gt 0 ]] && echo "found ${n} X ${fileName}"
2118 [[ ${n} -ge ${numberOfFiles} ]] && break
2119 [[ ${SECONDS} -gt ${maxSecondsToWait} ]] && echo "timeout of ${maxSecondsToWait}s!" && break
2122 echo "DONE! exiting..."
2132 if ! ls -1 ${inputFiles} &>/dev/null; then echo "the files dont exist!: ${inputFiles}"; return 1; fi
2134 runNumber=$(guessRunNumber ${x})
2135 [[ -z ${runNumber} ]] && echo "run number cannot be guessed for ${x}" && continue
2136 awk -v run=${runNumber} -v i=${i} 'NR > 1 {print run" "$0} NR==1 && i==0 {print "run/I:"$0}' ${x}
2138 done < <(ls -1 ${inputFiles}) > ${outputFile}
2142 goMakeMergedSummaryTree()
2144 # create list of calibration entries
2145 # takes no arguments, just run it in the base output
2146 # directory with the following files in the working directory
2148 # Calibration file lists:
2149 # cpass0.dcsTree.list, cpass1.dcsTree.list
2150 # QA trending root file:
2153 # Production infoo ascii files:
2154 # summary_pass0.tree
2155 # summary_pass1.tree
2158 [[ ! -f cpass0.dcsTree.list ]] && echo "no cpass0.dcsTree.list" && return 1
2159 [[ ! -f cpass1.dcsTree.list ]] && echo "no cpass1.dcsTree.list" && return 1
2160 [[ ! -f trending.root ]] && echo "no trending.root" && return 1
2161 [[ ! -f summary_pass0.tree ]] && echo "no summary_pass0.tree" && return 1
2162 [[ ! -f summary_pass1.tree ]] && echo "no summary_pass1.tree" && return 1
2164 #first, dump the C macro to file
2165 cat << EOF > mergeTree.C
2167 // Merge summary information
2168 // Following files are expected to be in the working directory
2170 // Calibration file lists:
2171 // cpass0.dcsTree.list, cpass1.dcsTree.list
2172 // QA trending root file:
2175 // Production infoo ascii files:
2176 // summary_pass0.tree
2177 // summary_pass1.tree
2183 // Calibration values dump
2185 //Printf("MakeTreeFromList cpass0.dcsTree.list");
2186 AliXRDPROOFtoolkit::MakeTreeFromList("Calib.TPC.CPass0.root", "dcs","dcs","cpass0.dcsTree.list",1);
2187 //Printf("MakeTreeFromList cpass1.dcsTree.list");
2188 AliXRDPROOFtoolkit::MakeTreeFromList("Calib.TPC.CPass1.root", "dcs","dcs","cpass1.dcsTree.list",1);
2190 // Calibration status dump
2192 TFile *fprod = TFile::Open("fproduction.root","recreate");
2194 //Printf("reading summary_pass0.tree");
2195 tree0.ReadFile("summary_pass0.tree");
2196 //Printf("reading summary_pass1.tree");
2197 tree1.ReadFile("summary_pass1.tree");
2198 tree0.Write("CPass0");
2199 tree1.Write("CPass1");
2204 TString stringSetup="";
2205 stringSetup+="1#QA.TPC#run#SummaryTPCQA/tpcQA#trending.root+"; //
2206 stringSetup+="1#Calib.TPC.CPass0#run#dcs#Calib.TPC.CPass0.root+"; //
2207 stringSetup+="1#Calib.TPC.CPass1#run#dcs#Calib.TPC.CPass1.root+"; //
2209 stringSetup+="1#CPass0#runnumber#CPass0#fproduction.root+"; //
2210 stringSetup+="1#CPass1#runnumber#CPass1#fproduction.root+"; //
2212 //Printf("stringSetup: %s", stringSetup.Data());
2213 AliXRDPROOFtoolkit::JoinTreesIndex("outAll.root","joinAll","run",stringSetup.Data(), 1);
2217 aliroot -b -q "mergeTree.C" > mergeTrees.log
2223 if [[ $# -lt 1 ]]; then
2224 echo 'make stacktrace processing in case of standard root crash log'
2225 echo 'input is a (list of) text files with the stack trace (either gdb aoutput'
2226 echo 'produced with e.g. gdb --batch --quiet -ex "bt" -ex "quit" aliroot core,'
2227 echo 'or the root crash log), output is a TTree formatted table.'
2228 echo 'example usage:'
2229 echo 'benchmark.sh stackTraceTree /foo/*/rec.log'
2230 echo 'benchmark.sh stackTraceTree $(cat file.list)'
2231 echo 'benchmark.sh stackTraceTree `cat file.list`'
2236 print "frame/I:method/C:line/C:cpass/I:aliroot/I:file/C";
2241 /There was a crash/ {read=1;}
2242 /The lines below might hint at the cause of the crash/ {read=0;}
2244 if ($3 ~ /Ali*/) aliroot=1; else aliroot=0;
2246 if ($NF!="" && RT!="" && $3!="") print RT" "$3" "$NF" "0" "aliroot" "FILENAME
2253 #all the final stuff goes in here for ease of use:
2257 # runs in current dir - in makeflow mode it can run LOCAL, then the QA plots and summaries
2258 # will appear in the submission dir.
2261 jsonLog="summary.json"
2267 if ! parseConfig ${configFile} "${extraOpts[@]}"; then return 1; fi
2269 #if which greadlink; then configFile=$(greadlink -f ${configFile}); fi
2271 #record the working directory provided by the batch system
2272 batchWorkingDirectory=${PWD}
2274 logTmp="${batchWorkingDirectory}/${log}"
2275 jsonLogTmp="${batchWorkingDirectory}/${jsonLog}"
2277 [[ -f ${alirootSource} && -z ${ALICE_ROOT} ]] && source ${alirootSource}
2279 [[ ! -f ${configFile} ]] && echo "no config file ${configFile}!" && return
2281 [[ -z ${commonOutputPath} ]] && commonOutputPath=${PWD}
2283 #copy some useful stuff
2284 [ -f "${commonOutputPath}/${configFile}" ] || paranoidCp "${configFile}" "${commonOutputPath}"
2286 exec &> >(tee ${logTmp})
2288 #summarize the global stuff
2289 echo "env script: ${alirootSource} ${alirootEnv}"
2290 echo "\$ALICE_ROOT=${ALICE_ROOT}"
2291 echo "commonOutputPath=${commonOutputPath}"
2293 #summarize the stacktraces
2294 stackTraceTree ${commonOutputPath}/*/*/000*/cpass0/*/stacktrace* > stacktrace_cpass0.tree
2295 stackTraceTree ${commonOutputPath}/*/*/000*/cpass1/*/stacktrace* > stacktrace_cpass1.tree
2297 # json header: open array of objects
2298 echo '[' > "${jsonLogTmp}"
2300 echo total numbers for the production:
2302 awk 'BEGIN {nFiles=0;nCore=0;}
2303 /^calibfile/ {nFiles++;}
2304 /core dumped/ {nCore++i;}
2305 END {print "cpass0 produced "nFiles" calib files, "nCore" core files";}' ${commonOutputPath}/meta/cpass0.job*done 2>/dev/null
2306 awk 'BEGIN {nOK=0; nBAD=0; }
2307 /\/rec.log OK/ {nOK++;}
2308 /\/rec.log BAD/ {nBAD++;}
2309 /stderr BAD/ {if ($0 ~ /rec.log/){nBAD++;}}
2310 END {print "cpass0 reco: OK: "nOK"\tBAD: "nBAD;}' ${commonOutputPath}/meta/cpass0.job*done 2>/dev/null
2311 awk 'BEGIN {nOK=0; nBAD=0; }
2312 /\/calib.log OK/ {nOK++;}
2313 /\/calib.log BAD/ {nBAD++;}
2314 END {print "cpass0 calib: OK: "nOK"\tBAD: "nBAD;}' ${commonOutputPath}/meta/cpass0.job*done 2>/dev/null
2316 awk 'BEGIN {nOK=0; nBAD=0; }
2317 /merge.log OK/ {nOK++;}
2318 /merge.log BAD/ {nBAD++;}
2319 END {print "cpass0 merge: OK: "nOK"\tBAD: "nBAD;}' ${commonOutputPath}/meta/merge.cpass0*done 2>/dev/null
2320 awk 'BEGIN {nOK=0; nBAD=0; }
2321 /ocdb.log OK/ {nOK++;}
2322 /ocdb.log BAD/ {nBAD++;}
2323 END {print "cpass0 OCDB: OK: "nOK"\tBAD: "nBAD;}' ${commonOutputPath}/meta/merge.cpass0*done 2>/dev/null
2326 awk 'BEGIN {nFiles=0;nCore=0;}
2327 /^calibfile/ {nFiles++;}
2328 /core dumped/ {nCore++;}
2329 END {print "cpass1 produced "nFiles" calib files, "nCore" core files";}' ${commonOutputPath}/meta/cpass1.job*done 2>/dev/null
2330 awk 'BEGIN {nOK=0; nBAD=0; }
2331 /\/rec.log OK/ {nOK++;}
2332 /\/rec.log BAD/ {nBAD++;}
2333 /stderr BAD/ {if ($0 ~ /rec.log/){nBAD++;}}
2334 END {print "cpass1 reco: OK: "nOK"\tBAD: "nBAD;}' ${commonOutputPath}/meta/cpass1.job*done 2>/dev/null
2335 awk 'BEGIN {nOK=0; nBAD=0; }
2336 /\/calib.log OK/ {nOK++;}
2337 /\/calib.log BAD/ {nBAD++;}
2338 END {print "cpass1 calib: OK: "nOK"\tBAD: "nBAD;}' ${commonOutputPath}/meta/cpass1.job*done 2>/dev/null
2340 awk 'BEGIN {nOK=0; nBAD=0; }
2341 /merge.log OK/ {nOK++;}
2342 /merge.log BAD/ {nBAD++;}
2343 END {print "cpass1 merge: OK: "nOK"\tBAD: "nBAD;}' ${commonOutputPath}/meta/merge.cpass1*done 2>/dev/null
2344 awk 'BEGIN {nOK=0; nBAD=0; }
2345 /ocdb.log OK/ {nOK++;}
2346 /ocdb.log BAD/ {nBAD++;}
2347 END {print "cpass1 OCDB: OK: "nOK"\tBAD: "nBAD;}' ${commonOutputPath}/meta/merge.cpass1*done 2>/dev/null
2351 /bin/ls -1 ${commonOutputPath}/meta/merge.cpass0.run*.done | while read x
2353 dir=$(goPrintValues dir - ${x})
2354 runNumber=$(guessRunNumber ${dir})
2355 [[ -z ${runNumber} ]] && continue
2357 if $(/bin/ls ${commonOutputPath}/meta/cpass0.job*.run${runNumber}.done &> /dev/null); then
2359 awk 'BEGIN {nOKrec=0;nBADrec=0;nOKcalib=0;nBADcalib=0;nOKstderr=0;nBADstderr=0;}
2360 /\/rec.log OK/ {nOKrec++;}
2361 /\/rec.log BAD/ {nBADrec++;}
2362 /stderr BAD/ {if ($0 ~ /rec.log/) {nBADrec++;} nBADstderr++;}
2363 /stderr OK/ {nOKstderr++;}
2364 /\/calib.log OK/ {nOKcalib++;}
2365 /\/calib.log BAD/ {nBADcalib++}
2366 END {print ""nOKrec" "nBADrec" "nOKstderr" "nBADstderr" "nOKcalib" "nBADcalib;}' ${commonOutputPath}/meta/cpass0.job*.run${runNumber}.done 2>/dev/null
2370 if $(/bin/ls ${commonOutputPath}/meta/cpass1.job*.run${runNumber}.done &>/dev/null); then
2372 awk 'BEGIN {nOKrec=0;nBADrec=0;nOKcalib=0;nBADcalib=0;nOKstderr=0;nBADstderr=0;nQAbarrelOK=0;nQAbarrelBAD=0;nQAouterOK=0;nQAouterBAD=0;}
2373 /\/rec.log OK/ {nOKrec++;}
2374 /\/rec.log BAD/ {nBADrec++;}
2375 /stderr BAD/ {if ($0 ~ /rec.log/) nBADrec++;nBADstderr++;}
2376 /stderr OK/ {nOKstderr++;}
2377 /\/calib.log OK/ {nOKcalib++;}
2378 /\/calib.log BAD/ {nBADcalib++}
2379 /\/qa_barrel.log OK/ {nQAbarrelOK++;}
2380 /\/qa_barrel.log BAD/ {nQAbarrelBAD++;}
2381 /\/qa_outer.log OK/ {nQAouterOK++;}
2382 /\/qa_outer.log BAD/ {nQAouterBAD++;}
2383 END {print ""nOKrec" "nBADrec" "nOKstderr" "nBADstderr" "nOKcalib" "nBADcalib" "nQAbarrelOK" "nQAbarrelBAD" "nQAouterOK" "nQAouterBAD;}' ${commonOutputPath}/meta/cpass1.job*.run${runNumber}.done 2>/dev/null
2387 statusOCDBcpass0=$(awk '/ocdb.log/ {print $2} ' ${x} 2>/dev/null)
2388 statusOCDBcpass1=$(awk '/ocdb.log/ {print $2}' ${x/cpass0/cpass1} 2>/dev/null)
2389 statusQA=$(awk '/mergeMakeOCDB.log/ {print $2}' ${x/cpass0/cpass1} 2>/dev/null)
2391 printf "%s\t ocdb.log cpass0: %s\t ocdb.log cpass1: %s\tqa.log:%s\t| cpass0: rec:%s/%s stderr:%s/%s calib:%s/%s cpass1: rec:%s/%s stderr:%s/%s calib:%s/%s QAbarrel:%s/%s QAouter:%s/%s\n" ${runNumber} ${statusOCDBcpass0} ${statusOCDBcpass1} ${statusQA} ${statusCPass0[0]} ${statusCPass0[1]} ${statusCPass0[2]} ${statusCPass0[3]} ${statusCPass0[4]} ${statusCPass0[5]} ${statusCPass1[0]} ${statusCPass1[1]} ${statusCPass1[2]} ${statusCPass1[3]} ${statusCPass1[4]} ${statusCPass1[5]} ${statusCPass1[6]} ${statusCPass1[7]} ${statusCPass1[8]} ${statusCPass1[9]}
2393 # produce json summary
2394 statusOCDBcpass0json=false
2395 statusOCDBcpass1json=false
2397 [[ "$statusOCDBcpass0" == 'OK' ]] && statusOCDBcpass0json=true
2398 [[ "$statusOCDBcpass1" == 'OK' ]] && statusOCDBcpass1json=true
2399 [[ "$statusQA" == 'OK' ]] && statusQAjson=true
2400 cat >> "$jsonLogTmp" <<EOF
2403 status: { ocdb_pass0: ${statusOCDBcpass0json}, ocdb_pass1: ${statusOCDBcpass1json}, qa: ${statusQAjson} },
2405 reco: { n_ok: ${statusCPass0[0]}, n_bad: ${statusCPass0[1]} },
2406 stderr: { n_ok: ${statusCPass0[2]}, n_bad: ${statusCPass0[3]} },
2407 calib: { n_ok: ${statusCPass0[4]}, n_bad: ${statusCPass0[5]} }
2410 reco: { n_ok: ${statusCPass1[0]}, n_bad: ${statusCPass1[1]} },
2411 stderr: { n_ok: ${statusCPass1[2]}, n_bad: ${statusCPass1[3]} },
2412 calib: { n_ok: ${statusCPass1[4]}, n_bad: ${statusCPass1[5]} },
2413 qabarrel: { n_ok: ${statusCPass1[6]}, n_bad: ${statusCPass1[7]} },
2414 qarouter: { n_ok: ${statusCPass1[8]}, n_bad: ${statusCPass1[9]} }
2421 # json footer: close array of objects
2422 echo ']' >> "${jsonLogTmp}"
2424 #make lists with output files - QA, trending, filtering and calibration
2425 ### wait for the merging of all runs to be over ###
2427 goPrintValues qafile qa.list ${commonOutputPath}/meta/merge.cpass1.run*.done &>/dev/null
2429 goPrintValues calibfile calib.list ${commonOutputPath}/meta/merge.cpass1.run*.done &>/dev/null
2431 goPrintValues trendingfile trending.list ${commonOutputPath}/meta/merge.cpass1.run*.done &>/dev/null
2432 rm -f filtering.list
2433 goPrintValues filteredTree filtering.list ${commonOutputPath}/meta/merge.cpass1.run*.done &>/dev/null
2434 rm -f cpass0.dcsTree.list
2435 goPrintValues dcsTree cpass0.dcsTree.list ${commonOutputPath}/meta/merge.cpass0.run*.done &>/dev/null
2436 rm -f cpass1.dcsTree.list
2437 goPrintValues dcsTree cpass1.dcsTree.list ${commonOutputPath}/meta/merge.cpass1.run*.done &>/dev/null
2441 goMerge trending.list trending.root ${configFile} "${extraOpts[@]}" &> mergeTrending.log
2443 goMakeSummaryTree ${commonOutputPath} 0
2444 goMakeSummaryTree ${commonOutputPath} 1
2446 goCreateQAplots "${PWD}/qa.list" "${productionID}" "QAplots" "${configFile}" "${extraOpts[@]}" filteringList="${PWD}/filtering.list" &>createQAplots.log
2448 #make a merged summary tree out of the QA trending, dcs trees and log summary trees
2449 goMakeMergedSummaryTree
2451 #if set, email the summary
2452 [[ -n ${MAILTO} ]] && cat ${logTmp} | mail -s "benchmark ${productionID} done" ${MAILTO}
2454 #copy logs to destination
2455 paranoidCp "$logTmp" "${commonOutputPath}"
2456 paranoidCp "$jsonLogTmp" "${commonOutputPath}"
2459 exec &> >(tee fileCopy.log)
2460 paranoidCp QAplots ${commonOutputPath}
2461 paranoidCp *.list ${commonOutputPath}
2462 paranoidCp *.root ${commonOutputPath}
2463 paranoidCp *.log ${commonOutputPath}
2464 paranoidCp fileCopy.log ${commonOutputPath}
2471 if [[ $# -lt 1 ]] ; then
2474 #1. define vars/arrays
2475 DIR=${1} #use input or exec in current dir
2476 pass=${2-"0"} #pass from input
2477 outfile="summary_pass${pass}.tree"
2479 test -f ${outfile} && : >${outfile}
2480 errfile=${outfile/tree/err}
2481 test -f ${errfile} && : >${errfile}
2483 declare -a counterString=(TOFevents TOFtracks TPCevents TPCtracks TRDevents TRDtracks T0events SDDevents SDDtracks MeanVertexevents)
2484 Ncounter=${#counterString[@]}
2486 declare -a statusString=(TRDStatus TOFStatus TPCStatus T0Status MeanVertexStatus)
2487 Nstatus=${#statusString[@]}
2490 declare -a ratesString=(rec stderr calib qa_barrel qa_outer)
2491 Nrates=${#ratesString[@]}
2493 runs=( $(ls -1 ${DIR}/meta/merge.cpass0* | while read x; do guessRunNumber $x; done) )
2496 echo -n runnumber/I >>${outfile}
2497 echo -n :cpass${pass}status/I >>${outfile}
2498 echo -n :cpass${pass}QAstatus/I >>${outfile}
2499 for i in ${ratesString[@]}; do
2500 echo -n :${i}OK/I >>${outfile}
2501 echo -n :${i}BAD/I >>${outfile}
2504 for i in ${counterString[@]} ${statusString[@]} ; do
2505 echo -n :${i}/I >>${outfile}
2507 Ncolumns=$((2 + 2*Nrates + Ncounter + Nstatus))
2512 for runnumber in ${runs[@]} ; do
2516 filejob="${DIR}/meta/cpass${pass}.job*.run${runnumber}.done"
2517 filemerge="${DIR}/meta/merge.cpass${pass}.run${runnumber}.done"
2518 fileOCDB=$(grep /ocdb.log ${filemerge} | awk '{print $1}')
2519 if ! $(/bin/ls ${filemerge} &>/dev/null) ; then
2520 echo "${filemerge} does not exist!" >>${errfile}
2522 elif ! $(/bin/ls ${filejob} &>/dev/null) ; then
2523 echo "${filejob} does not exist!" >>${errfile}
2524 echo -n ${runnumber} >> ${outfile}
2525 for i in $(seq ${Ncolumns}) ; do
2526 echo -n "-1" >> ${outfile}
2531 echo -n ${runnumber} >> ${outfile}
2532 #pass0status= grep '/ocdb.log' ${filemerge} | cut -d' ' -f2 | tr OK x1 | tr BAD xx0 | tr -d 'x'
2533 passStatus=$(grep '/ocdb.log' ${filemerge} | grep OK | wc -l)
2534 echo -n " ${passStatus}" >> ${outfile}
2535 qaStatus=$(grep '/mergeMakeOCDB.log' ${filemerge} | grep OK | wc -l)
2536 echo -n " ${qaStatus}" >> ${outfile}
2540 for i in $(seq 0 $((${Nrates}-1))) ; do
2541 var1=$(grep "/${ratesString[${i}]}.log" ${filejob} | grep OK | wc -l)
2542 var2=$(grep "/${ratesString[${i}]}.log" ${filejob} | grep BAD | wc -l)
2544 if [[ ${ratesString[${i}]} == "stderr" ]] ; then
2545 var1=$(grep "stderr" ${filejob} | grep OK | wc -l)
2546 var2=$(grep "stderr" ${filejob} | grep "rec.log" | grep BAD | wc -l)
2548 echo -n " ${var1}" >> ${outfile}
2549 echo -n " ${var2}" >> ${outfile}
2552 if [[ -f ${fileOCDB} ]] ; then
2554 for i in $(seq 0 $((${Ncounter}-1))) ; do
2555 var1=$(grep Monalisa ${fileOCDB} | grep ${counterString[${i}]} | cut -f2)
2556 echo -n " ${var1:-"-1"}" >> ${outfile}
2560 for i in $(seq 0 $((${Nstatus}-1))) ; do
2561 var1=$(grep "calibration status=" ${fileOCDB} | grep ${statusString[${i}]/Status/} | cut -d'=' -f2)
2562 echo -n " ${var1:-"-1"}" >> ${outfile}
2580 defaultOCDB="raw://"
2582 #makeflowPath="/hera/alice/aux/cctools/bin"
2583 #makeflowOptions="-T wq -N alice -d all -C ali-copilot.cern.ch:9097"
2584 #makeflowOptions="-T wq -N alice -C ali-copilot.cern.ch:9097"
2586 #batchCommand="/usr/bin/qsub"
2588 baseOutputDirectory="$PWD/output"
2589 #alirootEnv="/cvmfs/alice.cern.ch/bin/alienv setenv AliRoot/v5-04-34-AN -c"
2590 #alirootEnv="/home/mkrzewic/alisoft/balice_master.sh"
2591 #trustedQAtrainMacro='/hera/alice/mkrzewic/gsisvn/Calibration/QAtrain_duo.C'
2592 reconstructInTemporaryDir=0
2593 recoTriggerOptions="\"\""
2594 percentProcessedFilesToContinue=100
2595 maxSecondsToWait=$(( 3600*24 ))
2598 postSetUpActionCPass0=""
2599 postSetUpActionCPass1=""
2601 runCPass0MergeMakeOCDB=1
2603 runCPass1MergeMakeOCDB=1
2605 filteringFactorHighPt=1e2
2606 filteringFactorV0s=1e1
2609 #dontRedirectStdOutToLog=1
2610 logToFinalDestination=1
2611 ALIROOT_FORCE_COREDUMP=1
2615 #first, source the config file
2616 if [ -f ${configFile} ]; then
2617 source ${configFile}
2619 echo "config file ${configFile} not found!"
2624 for opt in "${args[@]}"; do
2625 [[ "${opt}" =~ encodedSpaces=.* ]] && encodedSpaces=1 && echo "encodedSpaces!" && break
2628 #then, parse the options as they override the options from file
2629 for opt in "${args[@]}"; do
2630 [[ -z ${opt} ]] && continue
2631 [[ -n ${encodedSpaces} ]] && opt="$(decSpaces ${opt})"
2632 [[ "${opt}" =~ ^[[:space:]]*$ ]] && continue
2633 if [[ ! "${opt}" =~ .*=.* ]]; then
2634 echo "badly formatted option \"${opt}\" should be: option=value, stopping..."
2637 local var="${opt%%=*}"
2638 local value="${opt#*=}"
2639 echo "${var}=${value}"
2640 export ${var}="${value}"
2644 [[ -z ${alirootEnv} ]] && echo "alirootEnv not defined!" && return 1
2646 #export the aliroot function if defined to override normal behaviour
2647 [[ $(type -t aliroot) =~ "function" ]] && export -f aliroot && echo "exporting aliroot() function..."
2655 if [[ -n ${useProfilingCommand} ]]; then
2656 profilerLogFile="cpu.txt"
2657 [[ "${args[@]}" =~ rec ]] && profilerLogFile="cpu_rec.txt"
2658 [[ "${args[@]}" =~ Calib ]] && profilerLogFile="cpu_calib.txt"
2659 echo running "${useProfilingCommand} aliroot ${args[@]} &> ${profilerLogFile}"
2660 ${useProfilingCommand} aliroot "${args[@]}" &> ${profilerLogFile}
2662 #to prevent an infinite recursion use "command aliroot" to disable
2663 #aliases and functions
2664 echo running command aliroot "${args[@]}"
2665 command aliroot "${args[@]}"
2672 #copies a single file to a local destination: the file may either come from
2673 #a local filesystem or from a remote location (whose protocol must be
2675 #copy is "robust" and it is repeated some times in case of failure before
2676 #giving up (1 is returned in that case)
2680 [[ -z "${maxCopyTries}" ]] && maxCopyTries=10
2682 proto="${src%%://*}"
2684 echo "copy file to local dest started: $src -> $dst"
2686 for (( i=1 ; i<=maxCopyTries ; i++ )) ; do
2688 echo "...attempt $i of $maxCopyTries"
2691 if [[ "$proto" == "$src" ]]; then
2696 xrdcp -f "$src" "$dst"
2699 curl -L "$src" -O "$dst"
2702 echo "protocol not supported: $proto"
2708 if [ $? == 0 ] ; then
2715 if [[ "$ok" == 1 ]] ; then
2716 echo "copy file to local dest OK after $i attempt(s): $src -> $dst"
2720 echo "copy file to local dest FAILED after $maxCopyTries attempt(s): $src -> $dst"
2726 #recursively copy files and directories
2727 #to avoid using find and the like as they kill
2728 #the performance on some cluster file systems
2729 #does not copy links to avoid problems
2730 sourceFiles=("${@}")
2731 destination="${sourceFiles[@]:(-1)}" #last element
2732 unset sourceFiles[${#sourceFiles[@]}-1] #remove last element (dst)
2733 for src in "${sourceFiles[@]}"; do
2734 if [[ -f "${src}" && ! -h "${src}" ]]; then
2735 paranoidCopyFile "${src}" "${destination}"
2736 elif [[ -d "${src}" && ! -h "${src}" ]]; then
2738 dst="${destination}/${src##*/}"
2740 paranoidCp "${src}"/* "${dst}"
2747 #copy a single file to a target in an existing dir
2748 #repeat a few times if copy fails
2749 #returns 1 on failure, 0 on success
2753 [[ -d "${dst}" ]] && dst="${dst}/${src##*/}"
2754 [[ -z "${maxCopyTries}" ]] && maxCopyTries=10
2756 echo "paranoid copy started: $src -> $dst"
2758 for (( i=1 ; i<=maxCopyTries ; i++ )) ; do
2760 echo "...attempt $i of $maxCopyTries"
2764 cmp -s "$src" "$dst"
2765 if [ $? == 0 ] ; then
2772 if [[ "$ok" == 1 ]] ; then
2773 echo "paranoid copy OK after $i attempt(s): $src -> $dst"
2777 echo "paranoid copy FAILED after $maxCopyTries attempt(s): $src -> $dst"
2783 #guess the period from the path, pick the rightmost one
2788 legoTrainRunNumber=""
2791 local shortRunNumber=""
2793 declare -a path=( $1 )
2794 local dirDepth=$(( ${#path[*]}-1 ))
2796 #for ((x=${dirDepth};x>=0;x--)); do
2797 for ((x=0;x<=${dirDepth};x++)); do
2799 [[ $((x-1)) -ge 0 ]] && local fieldPrev=${path[$((x-1))]}
2800 local field=${path[${x}]}
2801 local fieldNext=${path[$((x+1))]}
2803 [[ ${field} =~ ^[0-9]*$ && ${fieldNext} =~ (.*\.zip$|.*\.root$) ]] && legoTrainRunNumber=${field}
2804 [[ -n ${legoTrainRunNumber} && -z ${pass} ]] && pass=${fieldPrev}
2805 [[ ${field} =~ ^LHC[0-9][0-9][a-z].*$ ]] && period=${field%_*}
2806 [[ ${field} =~ ^000[0-9][0-9][0-9][0-9][0-9][0-9]$ ]] && runNumber=${field#000}
2807 [[ ${field} =~ ^[0-9][0-9][0-9][0-9][0-9][0-9]$ ]] && shortRunNumber=${field}
2808 [[ ${field} =~ ^20[0-9][0-9]$ ]] && year=${field}
2809 [[ ${field} =~ ^(^sim$|^data$) ]] && dataType=${field}
2812 [[ -z ${legoTrainRunNumber} ]] && pass=${path[$((dirDepth-1))]}
2813 [[ "${dataType}" =~ ^sim$ ]] && pass="passMC" && runNumber=${shortRunNumber}
2815 #if [[ -z ${dataType} || -z ${year} || -z ${period} || -z ${runNumber}} || -z ${pass} ]];
2816 if [[ -z ${runNumber}} ]];
2827 #these functions encode strings to and from a space-less form
2828 #use when spaces are not well handled (e.g. in arguments to
2829 #commands in makeflow files, etc.
2830 encSpaces()(echo "${1// /@@@@}")
2831 decSpaces()(echo "${1//@@@@/ }")