processing of event_stat_outer.root
[u/mrichter/AliRoot.git] / PWGPP / QA / scripts / runQA.sh
CommitLineData
f7707400 1#!/bin/bash
bbefeafe 2# process QA output into plots and trending
3# run without arguments for examples
4# origin: Mikolaj Krzewicki, mkrzewic@cern.ch
5#
34af53b5 6if [ ${BASH_VERSINFO} -lt 4 ]; then
7 echo "bash version >= 4 needed, you have ${BASH_VERSION}, exiting..."
8 exit 1
9fi
10
f7707400 11main()
12{
0c9bef99 13 if [[ -z $1 ]]; then
0adcf494 14 echo "Usage: "
15 echo " ${0##*/} option=value [option=value]"
161409c5 16 echo " at least inputList should be specified, or configFile containing it:"
17 echo " ${0##*/} inputList=file.list"
0adcf494 18 echo " options override config file (if any), e.g.:"
19 echo " ${0##*/} configFile=runQA.config inputList=file.list outputDirectory=%det"
a48fad97 20 echo "some expert options"
21 echo " inputListHighPtTrees=file.list - external list of filtered trees, requires inputList to be set"
22 echo " includeDetectors=TPC,V0,MU - only process those"
23 echo " excludeDetectors=EVS,TPC - skip processing of those"
24 echo " - see example config file for more"
2c46f154 25 return 1
93e1d132 26 fi
34af53b5 27
c8973bf8 28 if ! parseConfig "$@"; then
0adcf494 29 ${0}
30 return 1
31 fi
0c9bef99 32
2c46f154 33 [[ -z $ALICE_ROOT ]] && echo "ALICE_ROOT not defined" && return 1
93e1d132 34
35 ocdbregex='raw://'
2c46f154 36 if [[ ${ocdbStorage} =~ ${ocdbregex} ]]; then
823d0979 37 alien-token-init ${alienUserName}
5ed6085c 38 #this is a hack! alien-token init seems not enough
39 #but the gclient_env script messes up the LD_LIBRARY_PATH
40 while read x; do
41 eval ${x};
42 done < <(grep -v "LD_LIBRARY_PATH" /tmp/gclient_env_${UID})
2c46f154 43 fi
0c9bef99 44
c8973bf8 45 updateQA "$@"
946127bb 46 return 0
f7707400 47}
48
0c9bef99 49updateQA()
f7707400 50{
51 umask 0002
c8973bf8 52 parseConfig "$@"
0adcf494 53
54 #be paranoid and make some full paths
0adcf494 55 [[ ! -f ${inputList} ]] && echo "no input list: ${inputList}" && return 1
7f49f812 56 inputList=$(get_realpath ${inputList})
0adcf494 57 mkdir -p ${workingDirectory}
813c1a35 58 #this is a trick to get the full path of workingDirectory
59 #(on a mac 'readlink -f' does not work...)
7f49f812 60 workingDirectory=$(workingDirectory=${workingDirectory%/}; cd ${workingDirectory%/*}; echo "${PWD}/${workingDirectory##*/}")
0adcf494 61 if [[ ! -d ${workingDirectory} ]]; then
62 echo "working dir $workingDirectory does not exist and cannot be created"
63 return 1
64 fi
65 cd ${workingDirectory}
66
67 echo JOB config:
68 echo inputList=$inputList
69 echo outputDirectory=$outputDirectory
70 echo
f7707400 71
142113c1 72 dateString=$(date +%Y-%m-%d-%H-%M-%S-%N)
93e1d132 73 echo "Start time QA process: $dateString"
74
9cc5d265 75 #logging
76 mkdir -p $logDirectory
2c46f154 77 [[ ! -d $logDirectory ]] && echo "no log dir $logDirectory" && return 1
93e1d132 78 logFile="$logDirectory/${0##*/}.${dateString}.log"
9cc5d265 79 touch ${logFile}
2c46f154 80 [[ ! -f ${logFile} ]] && echo "cannot write logfile $logfile" && return 1
93e1d132 81 echo "logFile = $logFile"
9cc5d265 82
83 #check lock
a360b7b2 84 lockFile=${workingDirectory}/runQA.lock
bf4e7ceb 85 [[ -f ${lockFile} ]] && echo "lock ${lockFile} exists!" | tee ${logFile} && return 1
9cc5d265 86 touch ${lockFile}
bf4e7ceb 87 [[ ! -f ${lockFile} ]] && echo "cannot lock $lockFile" | tee ${logFile} && return 1
9cc5d265 88
bf4e7ceb 89 exec &>${logFile}
90
0c9bef99 91 ################################################################
92 #ze detector loop
f7707400 93 for detectorScript in $ALICE_ROOT/PWGPP/QA/detectorQAscripts/*; do
3db1b975 94 echo
95 echo "##############################################"
244ec455 96 echo $(date)
bf4e7ceb 97 unset planB
98 [[ ! ${detectorScript} =~ .*\.sh$ ]] && continue
f7707400 99 detector=${detectorScript%.sh}
100 detector=${detector##*/}
64da9242 101 #by default we expect the container in the QA root file to de named like
102 #the detector
103 detectorQAcontainerName=${detector}
2c46f154 104
105 #skip if excluded
c1386fec 106 if [[ "${excludeDetectors}" =~ ${detector} ]]; then
107 echo "${detector} is excluded in config, skipping..."
108 continue
109 fi
2c46f154 110
161409c5 111 #if includeDetectors set, only process thoe detectors specified there
112 if [[ -n ${includeDetectors} && ! "${includeDetectors}" =~ ${detector} ]]; then
113 echo "${detector} not included in includeDetectors, skipping..."
114 continue
115 fi
116
2c46f154 117 logSummary=${logDirectory}/summary-${detector}-${dateString}.log
69b2d32e 118 hostInfo >> ${logSummary}
f7707400 119 outputDir=$(substituteDetectorName ${detector} ${outputDirectory})
bf4e7ceb 120 tmpDetectorRunDir=${workingDirectory}/tmpQAtmpRunDir${detector}-${dateString}
8e7a87c1 121 if ! mkdir -p ${tmpDetectorRunDir}; then
122 echo "cannot create the temp dir $tmpDetectorRunDir"
9cc5d265 123 continue
124 fi
8e7a87c1 125 cd ${tmpDetectorRunDir}
9cc5d265 126
8e7a87c1 127 tmpPrefix=${tmpDetectorRunDir}/${outputDir}
93e1d132 128 echo "running QA for ${detector}"
129 echo " outputDir=$outputDir"
130 echo " tmpPrefix=$tmpPrefix"
f7707400 131
dd03b684 132 #source the detector script
61fa85ce 133 #unset the detector functions from previous iterations (detectors)
f7707400 134 unset -f runLevelQA
4beeae53 135 unset -f runLevelQAouter
f7707400 136 unset -f periodLevelQA
dd03b684 137 unset -f runLevelEventStatQA
645f513c 138 unset -f runLevelHighPtTreeQA
139 unset -f periodLevelHighPtTreeQA
f7707400 140 source ${detectorScript}
141
142 #################################################################
143 #produce the QA and trending tree for each file (run)
2a6472ef 144 unset arrOfTouchedProductions
145 declare -A arrOfTouchedProductions
dd03b684 146 while read inputFile; do
2c46f154 147 echo
244ec455 148 echo $(date)
3db1b975 149
150 #first check if input file exists
dd03b684 151 [[ ! -f ${inputFile%\#*} ]] && echo "file ${inputFile%\#*} not accessible" && continue
2c46f154 152
dd03b684 153 if ! guessRunData ${inputFile}; then
154 echo "could not guess run data from ${inputFile}"
0adcf494 155 continue
156 fi
17b0cdcd 157 echo "anchorYear for ${originalPeriod} is: ${anchorYear}"
f7707400 158
2a6472ef 159 tmpProductionDir=${tmpPrefix}/${dataType}/${year}/${period}/${pass}
2a6472ef 160 tmpRunDir=${tmpProductionDir}/000${runNumber}
161 mkdir -p ${tmpRunDir}
162 cd ${tmpRunDir}
f7707400 163
dd03b684 164 #check what kind of input file we have, default is a zip archive
165 #set the inputs accordingly
166 qaFile=""
4beeae53 167 qaFileOuter=""
dd03b684 168 highPtTree=""
169 eventStatFile=""
e6b479eb 170 eventStatFileOuter=""
645f513c 171 #it is possible we get the highPt trees from somewhere else
172 #search the list of high pt trees for the proper run number
173 if [[ -n ${inputListHighPtTrees} ]]; then
645f513c 174 highPtTree=$(egrep -m1 ${runNumber} ${inputListHighPtTrees})
f8619ac0 175 echo "loaded the highPtTree ${highPtTree} from external file ${inputListHighPtTrees}"
645f513c 176 fi
dd03b684 177 #if we are explicit about the input file this takes precedence
178 #over earlier additions
179 [[ "${inputFile}" =~ QAresults.root$ ]] && qaFile=${inputFile}
4beeae53 180 [[ "${inputFile}" =~ QAresults_outer.root$ ]] && qaFileOuter=${inputFile}
dd03b684 181 [[ "${inputFile}" =~ FilterEvents_Trees.root$ ]] && highPtTree=${inputFile}
182 [[ "${inputFile}" =~ event_stat.root$ ]] && eventStatFile=${inputFile}
e6b479eb 183 [[ "${inputFile}" =~ event_stat_outer.root$ ]] && eventStatFileOuter=${inputFile}
dd03b684 184 if [[ "${inputFile}" =~ \.zip$ ]]; then
185 [[ -z ${qaFile} ]] && qaFile=${inputFile}
4beeae53 186 [[ -z ${qaFileOuter} ]] && qaFileOuter=${inputFile}
dd03b684 187 [[ -z ${highPtTree} ]] && highPtTree=${inputFile}
188 [[ -z ${eventStatFile} ]] && eventStatFile=${inputFile}
e6b479eb 189 [[ -z ${eventStatFileOuter} ]] && eventStatFileOuter=${inputFile}
dd03b684 190 fi
645f513c 191
dd03b684 192 #if we have zip archives in the input, extract the proper file name
193 #from the archive and append in a root-like fashion
645f513c 194 if [[ "$qaFile" =~ .*.zip$ ]]; then
195 if unzip -l ${qaFile} | egrep "QAresults.root" &>/dev/null; then
dd03b684 196 qaFile+="#QAresults.root"
39488911 197 elif unzip -l ${qaFile} | egrep "QAresults_barrel.root" &>/dev/null; then
dd03b684 198 qaFile+="#QAresults_barrel.root"
645f513c 199 else
200 qaFile=""
201 fi
202 fi
4beeae53 203 if [[ "$qaFileOuter" =~ .*.zip$ ]]; then
204 if unzip -l ${qaFileOuter} | egrep "QAresults_outer.root" &>/dev/null; then
205 qaFileOuter+="#QAresults_outer.root"
206 else
207 qaFileOuter=""
208 fi
209 fi
645f513c 210 if [[ "$highPtTree" =~ .*.zip$ ]]; then
211 if unzip -l ${highPtTree} | egrep "FilterEvents_Trees.root" &>/dev/null; then
dd03b684 212 highPtTree+="#FilterEvents_Trees.root"
645f513c 213 else
214 highPtTree=""
215 fi
de540baf 216 fi
dd03b684 217 if [[ "${eventStatFile}" =~ .*.zip$ ]]; then
218 if unzip -l ${eventStatFile} | egrep "event_stat.root" &>/dev/null; then
219 eventStatFile+="#event_stat.root"
220 elif unzip -l ${eventStatFile} | egrep "event_stat_barrel.root" &>/dev/null; then
221 eventStatFile+="#event_stat_barrel.root"
222 else
223 eventStatFile=""
224 fi
225 fi
e6b479eb 226 if [[ "${eventStatFileOuter}" =~ .*.zip$ ]]; then
227 if unzip -l ${eventStatFileOuter} | egrep "event_stat_outer.root" &>/dev/null; then
228 eventStatFileOuter+="#event_stat.root"
229 else
230 eventStatFileOuter=""
231 fi
232 fi
645f513c 233
dd03b684 234 echo qaFile=$qaFile
4beeae53 235 echo qaFileOuter=$qaFileOuter
dd03b684 236 echo highPtTree=$highPtTree
237 echo eventStatFile=$eventStatFile
e6b479eb 238 echo eventStatFileOuter=$eventStatFileOuter
dd03b684 239 echo ocdbStorage=${ocdbStorage}
240 echo
241
242 #standard QA based on QAresults.root file (and variants)
645f513c 243 if [[ -n ${qaFile} && $(type -t runLevelQA) =~ "function" ]]; then
244 echo running ${detector} runLevelQA for run ${runNumber} from ${qaFile}
dd03b684 245 ( runLevelQA "${qaFile}" ) &>> runLevelQA.log
246 #cache the touched production + an example file to guarantee consistent run data parsing
247 arrOfTouchedProductions[${tmpProductionDir}]="${inputFile%\#*}"
645f513c 248 fi
4beeae53 249 #standard QA based on QAresults_outer.root file (there in cpass, with different triggers)
250 if [[ -n ${qaFileOuter} && $(type -t runLevelQAouter) =~ "function" ]]; then
251 echo running ${detector} runLevelQAouter for run ${runNumber} from ${qaFileOuter}
252 ( runLevelQAouter "${qaFileOuter}" ) &>> runLevelQA.log
253 #cache the touched production + an example file to guarantee consistent run data parsing
254 arrOfTouchedProductions[${tmpProductionDir}]="${inputFile%\#*}"
255 fi
645f513c 256 #expert QA based on high pt trees
257 if [[ -n ${highPtTree} && $(type -t runLevelHighPtTreeQA) =~ "function" ]]; then
258 echo running ${detector} runLevelHighPtTreeQA for run ${runNumber} from ${highPtTree}
dd03b684 259 ( runLevelHighPtTreeQA "${highPtTree}" ) &>> runLevelQA.log
260 #cache the touched production + an example file to guarantee consistent run data parsing
261 arrOfTouchedProductions[${tmpProductionDir}]="${inputFile%\#*}"
262 fi
263 #event stat QA based on event_stat.root file
264 if [[ -n ${eventStatFile} && $(type -t runLevelEventStatQA) =~ "function" ]]; then
265 echo running ${detector} runLevelEventStatQA for run ${runNumber} from ${eventStatFile}
4beeae53 266 ( runLevelEventStatQA "${eventStatFile}" ) &>> runLevelQA.log
dd03b684 267 #cache the touched production + an example file to guarantee consistent run data parsing
268 arrOfTouchedProductions[${tmpProductionDir}]="${inputFile%\#*}"
269 fi
e6b479eb 270 #event stat QA based on event_stat_outer.root file
271 if [[ -n ${eventStatFileOuter} && $(type -t runLevelEventStatQAouter) =~ "function" ]]; then
272 echo running ${detector} runLevelEventStatQAouter for run ${runNumber} from ${eventStatFileOuter}
273 ( runLevelEventStatQAouter "${eventStatFileOuter}" ) &>> runLevelQA.log
274 #cache the touched production + an example file to guarantee consistent run data parsing
275 arrOfTouchedProductions[${tmpProductionDir}]="${inputFile%\#*}"
276 fi
dd03b684 277
278 #perform some default actions:
279 #if trending.root not created, create a default one
280 if [[ ! -f trending.root ]]; then
281 aliroot -b -q -l "$ALICE_ROOT/PWGPP/macros/simpleTrending.C(\"${qaFile}\",${runNumber},\"${detectorQAcontainerName}\",\"trending.root\",\"trending\",\"recreate\")" 2>&1 | tee -a runLevelQA.log
282 fi
283 if [[ ! -f trending.root ]]; then
284 echo "trending.root not created"
645f513c 285 fi
286
8e7a87c1 287 cd ${tmpDetectorRunDir}
f7707400 288
289 done < ${inputList}
290
291 #################################################################
292 #cache which productions were (re)done
93e1d132 293 echo "list of processed productions:"
2a6472ef 294 echo " ${!arrOfTouchedProductions[@]}"
93e1d132 295 echo
2a6472ef 296
f7707400 297 #################################################################
bf4e7ceb 298 #(re)do the merging/trending
2a6472ef 299 for tmpProductionDir in ${!arrOfTouchedProductions[@]}; do
bf4e7ceb 300 cd ${tmpProductionDir}
2c46f154 301 echo
302 echo "running period level stuff in ${tmpProductionDir}"
244ec455 303 echo $(date)
f7707400 304
f7707400 305 productionDir=${outputDir}/${tmpProductionDir#${tmpPrefix}}
bf4e7ceb 306 echo productionDir=${outputDir}/${tmpProductionDir#${tmpPrefix}}
2c46f154 307
f7707400 308 mkdir -p ${productionDir}
9cc5d265 309 if [[ ! -d ${productionDir} ]]; then
93e1d132 310 echo "cannot make productionDir $productionDir" && continue
9cc5d265 311 fi
f7707400 312
bf4e7ceb 313 #move runs to final destination
314 for dir in ${tmpProductionDir}/000*; do
315 echo
93e1d132 316 oldRunDir=${outputDir}/${dir#${tmpPrefix}}
762f2238 317 if ! guessRunData "${arrOfTouchedProductions[${tmpProductionDir}]}"; then
3b9c183a 318 echo "could not guess run data from ${arrOfTouchedProductions[${tmpProductionDir}]}"
0adcf494 319 continue
320 fi
2c46f154 321
322 #before moving - VALIDATE!!!
bf4e7ceb 323 if ! validate ${dir}; then
324 continue
325 fi
2c46f154 326
1aa30209 327 #moving a dir is an atomic operation, no locking necessary
93e1d132 328 if [[ -d ${oldRunDir} ]]; then
50864a2d 329 echo "removing old ${oldRunDir}"
93e1d132 330 rm -rf ${oldRunDir}
331 fi
2c46f154 332 echo "moving new ${runNumber} to ${productionDir}"
93e1d132 333 mv -f ${dir} ${productionDir}
334 done
033dacdc 335
3db1b975 336 #go to a temp dir to do the period level stuff in a completely clean dir
bf4e7ceb 337 tmpPeriodLevelQAdir="${tmpProductionDir}/periodLevelQA"
338 echo
45aec4ec 339 echo tmpPeriodLevelQAdir="${tmpPeriodLevelQAdir}"
bf4e7ceb 340 if ! mkdir -p ${tmpPeriodLevelQAdir}; then continue; fi
341 cd ${tmpPeriodLevelQAdir}
342
343 #link the final list of per-run dirs here, just the dirs
344 #to have a clean working directory
345 unset linkedStuff
346 declare -a linkedStuff
347 for x in ${productionDir}/000*; do [[ -d $x ]] && ln -s $x && linkedStuff+=(${x##*/}); done
bf4e7ceb 348
8e7a87c1 349 #merge trending files if any
350 if /bin/ls 000*/trending.root &>/dev/null; then
351 hadd trending.root 000*/trending.root &> periodLevelQA.log
645f513c 352 fi
353
bf4e7ceb 354 #run the period level trending/QA
645f513c 355 if [[ -f "trending.root" && $(type -t periodLevelQA) =~ "function" ]]; then
356 echo running ${detector} periodLevelQA for production ${period}/${pass}
dd03b684 357 ( periodLevelQA trending.root ) &>> periodLevelQA.log
645f513c 358 else
359 echo "WARNING: not running ${detector} periodLevelQA for production ${period}/${pass}, no trending.root"
8e7a87c1 360 fi
361
2c46f154 362 if ! validate ${PWD}; then continue; fi
2c46f154 363
bf4e7ceb 364 #here we are validated so move the produced QA to the final place
365 #clean up linked stuff first
366 [[ -n ${linkedStuff[@]} ]] && rm ${linkedStuff[@]}
1aa30209 367 periodLevelLock=${productionDir}/runQA.lock
368 if [[ ! -f ${periodLevelLock} ]]; then
369 #some of the output could be a directory, so handle that
370 #TODO: maybe use rsync?
371 #lock to avoid conflicts:
372 echo "${HOSTNAME} ${dateString}" > ${periodLevelLock}
373 for x in ${tmpPeriodLevelQAdir}/*; do
374 if [[ -d ${x} ]]; then
375 echo "removing ${productionDir}/${x##*/}"
376 rm -rf ${productionDir}/${x##*/}
377 echo "moving ${x} to ${productionDir}"
378 mv ${x} ${productionDir}
379 fi
380 if [[ -f ${x} ]]; then
381 echo "moving ${x} to ${productionDir}"
382 mv -f ${x} ${productionDir}
383 fi
384 done
385 rm -f ${periodLevelLock}
386 #remove the temp dir
387 rm -rf ${tmpPeriodLevelQAdir}
388 else
56af0297 389 echo "ERROR: cannot move to destination" >> ${logSummary}
390 echo "production dir ${productionDir} locked!" >> ${logSummary}
391 echo "check and maybe manually do:" >> ${logSummary}
392 echo " rm ${periodLevelLock}" >> ${logSummary}
393 echo " rsync -av ${tmpPeriodLevelQAdir}/ ${productionDir}/" >> ${logSummary}
c38409ba 394 planB=1
1aa30209 395 fi
bf4e7ceb 396
f7707400 397 done
398
9cc5d265 399 cd ${workingDirectory}
2c46f154 400
401 if [[ -z ${planB} ]]; then
9a5f8a19 402 echo
8e7a87c1 403 echo removing ${tmpDetectorRunDir}
404 rm -rf ${tmpDetectorRunDir}
2c46f154 405 else
406 executePlanB
407 fi
3db1b975 408 done #end of detector loop
f7707400 409
9cc5d265 410 #remove lock
411 rm -f ${lockFile}
946127bb 412 return 0
f7707400 413}
414
2c46f154 415executePlanB()
416{
417 #in case of emergency
6d28e820 418 #first check if we have the email of the detector expert defined,
419 #if yes, append to the mailing list
7e37467c 420 local mailTo=${MAILTO}
6d28e820 421 local detExpertEmailVar="MAILTO_${detector}"
7e37467c 422 [[ -n "${!detExpertEmailVar}" ]] && mailTo+=" ${!detExpertEmailVar}"
423 if [[ -n ${mailTo} ]]; then
2c46f154 424 echo
7e37467c 425 echo "trouble detected, sending email to ${mailTo}"
b2bf946d 426 cat ${logSummary} | mail -s "${detector} QA in need of assistance" ${mailTo}
2c46f154 427 fi
946127bb 428 return 0
2c46f154 429}
430
431validate()
432{
433 summarizeLogs ${1} >> ${logSummary}
434 logStatus=$?
435 if [[ ${logStatus} -ne 0 ]]; then
436 echo "WARNING not validated: ${1}"
437 planB=1
438 return 1
439 fi
440 return 0
441}
442
443summarizeLogs()
444{
445 local dir=$1
2a6472ef 446 [[ ! -d ${dir} ]] && dir=${PWD}
2c46f154 447
448 #print a summary of logs
449 logFiles=(
450 "*.log"
451 "stdout"
452 "stderr"
453 )
454
455 #check logs
456 local logstatus=0
457 for log in ${dir}/${logFiles[*]}; do
2c46f154 458 [[ ! -f ${log} ]] && continue
459 errorSummary=$(validateLog ${log})
460 validationStatus=$?
461 [[ validationStatus -ne 0 ]] && logstatus=1
462 if [[ ${validationStatus} -eq 0 ]]; then
463 #in pretend mode randomly report an error in rec.log some cases
464 if [[ -n ${pretend} && "${log}" == "rec.log" ]]; then
69b2d32e 465 [[ $(( ${RANDOM}%2 )) -ge 1 ]] && echo "${log} BAD random error" || echo "${log} OK"
2c46f154 466 else
69b2d32e 467 echo "${log} OK"
2c46f154 468 fi
469 elif [[ ${validationStatus} -eq 1 ]]; then
69b2d32e 470 echo "${log} BAD ${errorSummary}"
2c46f154 471 elif [[ ${validationStatus} -eq 2 ]]; then
69b2d32e 472 echo "${log} OK MWAH ${errorSummary}"
2c46f154 473 fi
474 done
475
476 #report core files
477 while read x; do
478 echo ${x}
479 chmod 644 ${x}
480 gdb --batch --quiet -ex "bt" -ex "quit" aliroot ${x} > stacktrace_${x//\//_}.log
481 done < <(/bin/ls ${PWD}/*/core 2>/dev/null; /bin/ls ${PWD}/core 2>/dev/null)
482
483 return ${logstatus}
484}
485
486validateLog()
487{
488 log=${1}
489 errorConditions=(
490 'There was a crash'
491 'floating'
492 'error while loading shared libraries'
493 'std::bad_alloc'
494 's_err_syswatch_'
495 'Thread [0-9]* (Thread'
496 'AliFatal'
497 'core dumped'
498 '\.C.*error:.*\.h: No such file'
499 'segmentation'
645f513c 500 'Interpreter error recovered'
2c46f154 501 )
502
503 warningConditions=(
504 'This is serious'
505 )
506
507 local logstatus=0
508 local errorSummary=""
509 local warningSummary=""
510
511 for ((i=0; i<${#errorConditions[@]};i++)); do
512 local tmp=$(grep -m1 -e "${errorConditions[${i}]}" ${log})
513 [[ -n ${tmp} ]] && tmp+=" : "
514 errorSummary+=${tmp}
515 done
516
517 for ((i=0; i<${#warningConditions[@]};i++)); do
518 local tmp=$(grep -m1 -e "${warningConditions[${i}]}" ${log})
519 [[ -n ${tmp} ]] && tmp+=" : "
520 warningSummary+=${tmp}
521 done
522
523 if [[ -n ${errorSummary} ]]; then
524 echo "${errorSummary}"
525 return 1
526 fi
527
528 if [[ -n ${warningSummary} ]]; then
529 echo "${warningSummary}"
530 return 2
531 fi
532
533 return 0
534}
535
f7707400 536parseConfig()
537{
d56eeaab 538 args=("$@")
539
0adcf494 540 #config file
541 configFile=""
542 #where to search for qa files
543 inputList=file.list
544 #working directory
545 workingDirectory="${PWD}"
546 #where to place the final qa plots
547 #outputDirectory="/afs/cern.ch/work/a/aliqa%det/www/"
548 outputDirectory="${workingDirectory}/%DET"
549 #filter out detector option
550 excludeDetectors="EXAMPLE"
551 #logs
552 logDirectory=${workingDirectory}/logs
0adcf494 553 #OCDB storage
b001e589 554 ocdbStorage="raw://"
0adcf494 555 #email to
556 #MAILTO="fbellini@cern.ch"
ae46a5f8 557 runMap="
558 2010 108350 139517
559 2011 140441 170593
560 2012 171590 193766
561 2013 194482 197692
562 "
0adcf494 563
564 #first, check if the config file is configured
565 #is yes - source it so that other options can override it
566 #if any
d56eeaab 567 for opt in "${args[@]}"; do
0adcf494 568 if [[ ${opt} =~ configFile=.* ]]; then
569 eval "${opt}"
7f49f812 570 [[ ! -f ${configFile} ]] && echo "configFile ${configFile} not found, exiting..." && return 1
d56eeaab 571 echo "using config file: ${configFile}"
0adcf494 572 source "${configFile}"
573 break
574 fi
575 done
f7707400 576
577 #then, parse the options as they override the options from file
d56eeaab 578 for opt in "${args[@]}"; do
579 if [[ ! "${opt}" =~ .*=.* ]]; then
0adcf494 580 echo "badly formatted option ${var}, should be: option=value, stopping..."
581 return 1
582 fi
d56eeaab 583 local var="${opt%%=*}"
584 local value="${opt#*=}"
c8973bf8 585 echo "${var}=${value}"
d56eeaab 586 export ${var}="${value}"
f7707400 587 done
946127bb 588 return 0
f7707400 589}
590
591guessRunData()
592{
593 #guess the period from the path, pick the rightmost one
594 period=""
595 runNumber=""
596 year=""
597 pass=""
598 legoTrainRunNumber=""
599 dataType=""
911c7ce3 600 originalPass=""
601 originalPeriod=""
7d4afda6 602 anchorYear=""
f7707400 603
17b0cdcd 604 shortRunNumber=""
c8973bf8 605 oldIFS=${IFS}
f7707400 606 local IFS="/"
607 declare -a path=( $1 )
c8973bf8 608 IFS="${oldIFS}"
f7707400 609 local dirDepth=$(( ${#path[*]}-1 ))
610 i=0
611 for ((x=${dirDepth};x>=0;x--)); do
612
613 [[ $((x-1)) -ge 0 ]] && local fieldPrev=${path[$((x-1))]}
614 local field=${path[${x}]}
615 local fieldNext=${path[$((x+1))]}
616
617 [[ ${field} =~ ^[0-9]*$ && ${fieldNext} =~ (.*\.zip$|.*\.root$) ]] && legoTrainRunNumber=${field}
618 [[ -n ${legoTrainRunNumber} && -z ${pass} ]] && pass=${fieldPrev}
911c7ce3 619 [[ ${field} =~ ^LHC[0-9][0-9][a-z].*$ ]] && period=${field%_*} && originalPeriod=${field}
f7707400 620 [[ ${field} =~ ^000[0-9][0-9][0-9][0-9][0-9][0-9]$ ]] && runNumber=${field#000}
621 [[ ${field} =~ ^[0-9][0-9][0-9][0-9][0-9][0-9]$ ]] && shortRunNumber=${field}
622 [[ ${field} =~ ^20[0-9][0-9]$ ]] && year=${field}
623 [[ ${field} =~ ^(^sim$|^data$) ]] && dataType=${field}
624 (( i++ ))
625 done
911c7ce3 626 originalPass=${pass}
17b0cdcd 627 [[ -n ${shortRunNumber} && "${legoTrainRunNumber}" =~ ${shortRunNumber} ]] && legoTrainRunNumber=""
f7707400 628 [[ -z ${legoTrainRunNumber} ]] && pass=${path[$((dirDepth-1))]}
17b0cdcd 629 [[ "${dataType}" =~ ^sim$ ]] && pass="passMC" && runNumber=${shortRunNumber} && originalPass="" #for MC not from lego, the runnumber is identified as lego train number, thus needs to be nulled
84ed81b2 630 [[ -n ${legoTrainRunNumber} ]] && pass+="_lego${legoTrainRunNumber}"
0c9bef99 631
c8973bf8 632 #modify the OCDB: set the year
17b0cdcd 633 if [[ ${dataType} =~ sim ]]; then
6ec9300a 634 anchorYear=$(run2year $runNumber)
1e1ffc38 635 if [[ -z "${anchorYear}" ]]; then
6ec9300a 636 echo "WARNING: anchorYear not available for this production: ${originalPeriod}, runNumber: ${runNumber}. Cannot set the OCDB."
1e1ffc38 637 return 1
638 fi
7d4afda6 639 ocdbStorage=$(setYear ${anchorYear} ${ocdbStorage})
640 else
641 ocdbStorage=$(setYear ${year} ${ocdbStorage})
642 fi
c8973bf8 643
2a6472ef 644 #if [[ -z ${dataType} || -z ${year} || -z ${period} || -z ${runNumber}} || -z ${pass} ]];
7cbc35b8 645 if [[ -z ${runNumber} ]]
0c9bef99 646 then
647 #error condition
648 return 1
0c9bef99 649 fi
946127bb 650
651 #ALL OK
652 return 0
f7707400 653}
654
6ec9300a 655run2year()
656{
657 #for a given run print the year.
658 #the run-year table is ${runMap} (a string)
659 #defined in the config file
660 #one line per year, format: year runMin runMax
661 local run=$1
257428d1 662 [[ -z ${run} ]] && return 1
663 local year=""
664 local runMin=""
665 local runMax=""
6ec9300a 666 while read year runMin runMax; do
257428d1 667 [[ -z ${year} || -z ${runMin} || -z ${runMax} ]] && continue
6ec9300a 668 [[ ${run} -ge ${runMin} && ${run} -le ${runMax} ]] && echo ${year} && break
669 done < <(echo "${runMap}")
670 return 0
671}
672
f7707400 673substituteDetectorName()
674{
675 local det=$1
676 local dir=$2
677 [[ ${dir} =~ \%det ]] && det=${det,,} && echo ${dir/\%det/${det}}
678 [[ ${dir} =~ \%DET ]] && det=${det} && echo ${dir/\%DET/${det}}
946127bb 679 return 0
f7707400 680}
681
7f49f812 682get_realpath()
683{
684 if [[ -f "$1" ]]
685 then
686 # file *must* exist
687 if cd "$(echo "${1%/*}")" &>/dev/null
688 then
689 # file *may* not be local
690 # exception is ./file.ext
691 # try 'cd .; cd -;' *works!*
692 local tmppwd="$PWD"
693 cd - &>/dev/null
694 else
695 # file *must* be local
696 local tmppwd="$PWD"
697 fi
698 else
699 # file *cannot* exist
700 return 1 # failure
701 fi
702 # reassemble realpath
703 echo "$tmppwd"/"${1##*/}"
704 return 0 # success
705}
706
c8973bf8 707setYear()
708{
709 #set the year
710 # ${1} - year to be set
711 # ${2} - where to set the year
712 local year1=$(guessYear ${1})
713 local year2=$(guessYear ${2})
714 local path=${2}
715 [[ ${year1} -ne ${year2} && -n ${year2} && -n ${year1} ]] && path=${2/\/${year2}\//\/${year1}\/}
716 echo ${path}
717 return 0
718}
719
720guessYear()
721{
722 #guess the year from the path, pick the rightmost one
723 local IFS="/"
724 declare -a pathArray=( ${1} )
725 local field
726 local year
727 for field in ${pathArray[@]}; do
728 [[ ${field} =~ ^20[0-9][0-9]$ ]] && year=${field}
729 done
730 echo ${year}
731 return 0
732}
733
69b2d32e 734hostInfo(){
735#
736# Hallo world - Print AliRoot/Root/Alien system info
737#
738
739#
740# HOST info
741#
742 echo --------------------------------------
743 echo
744 echo HOSTINFO
745 echo
746 echo HOSTINFO HOSTNAME" "$HOSTNAME
747 echo HOSTINFO DATE" "`date`
748 echo HOSTINFO gccpath" "`which gcc`
749 echo HOSTINFO gcc version" "`gcc --version | grep gcc`
750 echo --------------------------------------
751
752#
753# ROOT info
754#
755 echo --------------------------------------
756 echo
757 echo ROOTINFO
758 echo
759 echo ROOTINFO ROOT" "`which root`
760 echo ROOTINFO VERSION" "`root-config --version`
761 echo
762 echo --------------------------------------
763
764
765#
766# ALIROOT info
767#
768 echo --------------------------------------
769 echo
770 echo ALIROOTINFO
771 echo
772 echo ALIROOTINFO ALIROOT" "`which aliroot`
773 echo ALIROOTINFO VERSION" "`echo $ALICE_LEVEL`
774 echo ALIROOTINFO TARGET" "`echo $ALICE_TARGET`
775 echo
776 echo --------------------------------------
777
778#
779# Alien info
780#
781#echo --------------------------------------
782#echo
783#echo ALIENINFO
784#for a in `alien --printenv`; do echo ALIENINFO $a; done
785#echo
786#echo --------------------------------------
787
788#
789# Local Info
790#
791 echo PWD `pwd`
792 echo Dir
793 ls -al
794 echo
795 echo
796 echo
946127bb 797
798 return 0
69b2d32e 799}
800
c8973bf8 801main "$@"