Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:07:37

0001 #!/bin/bash
0002 
0003 # load common HLT functions
0004 if [ -f "$CMSSW_BASE/src/HLTrigger/Configuration/common/utils.sh" ]; then
0005   source "$CMSSW_BASE/src/HLTrigger/Configuration/common/utils.sh"
0006 elif [ -f "$CMSSW_RELEASE_BASE/src/HLTrigger/Configuration/common/utils.sh" ]; then
0007   source "$CMSSW_RELEASE_BASE/src/HLTrigger/Configuration/common/utils.sh"
0008 else
0009   exit 1
0010 fi
0011 
0012 function log() {
0013   echo -e "$@"
0014 }
0015 
0016 function err() {
0017   echo -e "$@" 1>&2
0018 }
0019 
0020 NAME=$(basename $0)
0021 
0022 HELP="Run the integration tests over all paths in a given HLT menu.
0023 
0024 Usage:
0025   $NAME -h|--help
0026   $NAME [-d|--dir WORKDIR] [-s|--setup SETUP] [-i|--input RAW] [-j|--jobs JOBS]
0027         [--streams STREAMS] [--threads THREADS] [-x|--extra OPTIONS] [--mc]
0028         [ [-n|--size EVENTS] [-k|--skip EVENTS] | [-e|--events EVENTS] ] MENU
0029 
0030   MENU is the HLT menu to test (format: a local cmsRun cfg file, or the name of a ConfDB configuration).
0031 
0032   -s | --setup SETUP              HLT menu (format: ConfDB configuration) used for Services and EventSetup modules
0033                                   (useful when testing a ConfDB config that only contains Paths).
0034                                   Note it is an error to specify the converter/db here,
0035                                   it uses the same as set by the HLT menu
0036   -d | --dir         WORKDIR      Create all files and run all tests inside WORKDIR (defauls: ./hltintegration)
0037   -i | --input       INPUT        Use the specified EDM file as input (data tier: RAW)
0038   -n | --size        EVENTS       Run on EVENTS events (-1 for all, default is 100)
0039   -k | --skip        EVENTS       Skip the first EVENTS (default is 0)
0040   -e | --events      EVENTS       Run on a comma-separated list of EVENTS, a VEventRange
0041   -j | --jobs        JOBS         Run JOBS single trigger jobs in parallel (default 4)
0042        --streams     STREAMS      Run with STREAMS parallel streams (i.e. events) (default 0 means as many streams as threads)
0043        --threads     THREADS      Run with THREADS threads when running the whole HLT (default 4)
0044   -a | --accelerator ACCELERATOR  Keyword to choose allowed accelerators (examples: \"*\", \"cpu\", \"gpu-nvidia\")
0045   -x | --extra       OPTIONS      If the HLT menu is a local cmsRun cfg file, OPTIONS is used as
0046                                   additional arguments to cmsRun (i.e. \"cmsRun hlt.py [OPTIONS]\")
0047                                   If the HLT menu is the name of a ConfDB configuration, OPTIONS is used as
0048                                   additional arguments to hltGetConfiguration (i.e. \"hltGetConfiguration [MENU] [..] [OPTIONS]\")
0049        --mc                       Run over MC instead of data (the default)
0050   --dbproxy                       Use a socks proxy to connect to the ConfDB database
0051   --dbproxyhost      PROXYHOST    Host of the socks proxy (default: \"localhost\")
0052   --dbproxyport      PROXYPORT    Port of the socks proxy (default: 8080)
0053   -h | --help                     Print this help message and exit.
0054 
0055   The HLT menu used for the integration tests (MENU) can be specified
0056   as either (1) a cmsRun cfg file, or (2) the name of a ConfDB configuration.
0057   MENU is identified as a cmsRun cfg file if it is an existing regular file.
0058   For ConfDB configurations, the supported formats are
0059     - /path/to/configuration[/Vn]
0060     - [[{v1|v2|v3}/]{run3|run2|online|adg}:]/path/to/configuration[/Vn]
0061     - run:runnumber
0062   Allowed converters are \"v1\", \"v2\", and \"v3\" (default).
0063   Allowed databases are
0064     - \"run3\" (default, used for offline Run-3 development),
0065     - \"run2\" (previously used for Run-2 development),
0066     - \"online\" (used to extract online menus within Point 5) and
0067     - \"adg\" (used to extract the online menus outside Point 5).
0068   Other converters and databases exist, but they are for expert/special use only.
0069   If \"run:\" is used instead, the HLT menu used for the given run number is looked up and used.
0070   If no menu version is specified, the latest one is automatically used.
0071 
0072   It is possible to pass arbitrary command-line options to hltGetConfiguration, using \"-x --option\".
0073   To pass multiple options, enclose them in quotes, or use \"-x\" more than once.
0074 
0075   Note: '--events' is not supported together with '--size' or '--skip'.
0076 
0077 
0078 Examples:
0079 
0080   $NAME /dev/CMSSW_X_Y_Z/GRun
0081 
0082       will test the latest version of the GRun menu.
0083 
0084 
0085   $NAME /dev/CMSSW_X_Y_Z/GRun -x --l1-emulator
0086 
0087       will test the latest version of the GRun running the L1-Trigger emulator.
0088 
0089 
0090   $NAME /users/fwyzard/physics/HLT/V6 -s adg:/cdaq/physics/Run2011/1e33/v1.3/HLT/V6
0091 
0092       will test the paths from /users/fwyzard/physics/HLT/V6
0093       using the environment from the online menu \"1e33\" v1.3 V6
0094 
0095 "
0096 
0097 # parse command line argument and options
0098 OPTS=$(getopt -n "$NAME" -o "s:d:i:j:n:k:e:a:x:h" \
0099  -l "setup:,dir:,input:,jobs:,size:,skip:,streams:,threads:,accelerator:,events:,mc,extra:,help,dbproxy,dbproxyhost:,dbproxyport:" -- "$@")
0100 
0101 # invalid options
0102 if [ $? != 0 ]; then
0103   exit 1
0104 fi
0105 
0106 # reload the parsed options into the environment
0107 eval set -- "$OPTS"
0108 
0109 # check how many CPUs are available
0110 CPUS=`getconf _NPROCESSORS_ONLN`
0111 
0112 MENU=""
0113 SETUP=""
0114 INPUT=""
0115 SIZE=100
0116 SKIP=0
0117 EVENTS=""
0118 JOBS=4
0119 THREADS=4
0120 STREAMS=0
0121 ACCELERATOR="cpu"
0122 WORKDIR="hltintegration"
0123 EXTRA=""
0124 DATA=""
0125 DBPROXYOPTS=""
0126 
0127 SELECTION=""
0128 
0129 # parse options
0130 while true; do
0131   case "$1" in
0132     "-h" | "--help" )
0133       echo "$HELP"
0134       exit 0
0135       ;;
0136     "-s" | "--setup" )
0137       SETUP="$2"
0138       shift 2
0139       ;;
0140     "-d" | "--dir" )
0141       WORKDIR="$2"
0142       shift 2
0143       ;;
0144     "-i" | "--input" )
0145       INPUT="$2"
0146       shift 2
0147       ;;
0148     "-n" | "--size" )
0149       if [ "$SELECTION" == "complex" ]; then
0150         err "'--events' is not supported together with '--size' or '--skip'"
0151         exit 1
0152       fi
0153       SELECTION="simple"
0154       SIZE=$2
0155       if ((SIZE == 0)) && [ "$SIZE" != "0" ]; then
0156         err "$NAME error: invalid option \"$1 $2\""
0157         err "Try '$NAME --help' for more information."
0158         exit 1
0159       fi
0160       shift 2
0161       ;;
0162     "-k" | "--skip" )
0163       if [ "$SELECTION" == "complex" ]; then
0164         err "'--events' is not supported together with '--size' or '--skip'"
0165         exit 1
0166       fi
0167       SELECTION="simple"
0168       SKIP=$2
0169       if ((SKIP == 0)) && [ "$SKIP" != "0" ]; then
0170         err "$NAME error: invalid option \"$1 $2\""
0171         err "Try '$NAME --help' for more information."
0172         exit 1
0173       fi
0174       shift 2
0175       ;;
0176     "-e" | "--events" )
0177       if [ "$SELECTION" == "simple" ]; then
0178         err "'--events' is not supported together with '--size' or '--skip'"
0179         exit 1
0180       fi
0181       SELECTION="complex"
0182       SIZE=-1
0183       EVENTS="$2"
0184       shift 2
0185       ;;
0186     "-j" | "--jobs" )
0187       JOBS=$2
0188       if ((JOBS == 0)); then
0189         err "$NAME error: invalid option \"$1 $2\""
0190         err "Try '$NAME --help' for more information."
0191         exit 1
0192       fi
0193       shift 2
0194       ;;
0195     "--streams" )
0196       STREAMS=$2
0197       shift 2
0198       ;;
0199     "--threads" )
0200       THREADS=$2
0201       shift 2
0202       ;;
0203     "-a" | "--accelerator" )
0204       ACCELERATOR="$2"
0205       shift 2
0206       ;;
0207     "-x" | "--extra" )
0208       EXTRA="$EXTRA $2"
0209       shift 2
0210       ;;
0211     "--mc" )
0212       DATA="--mc"
0213       shift 1
0214       ;;
0215     "--dbproxy" )
0216       DBPROXYOPTS="${DBPROXYOPTS} --dbproxy"
0217       shift 1
0218       ;;
0219     "--dbproxyhost" )
0220       DBPROXYOPTS="${DBPROXYOPTS} --dbproxyhost $2"
0221       shift 2
0222       ;;
0223     "--dbproxyport" )
0224       DBPROXYOPTS="${DBPROXYOPTS} --dbproxyport $2"
0225       shift 2
0226       ;;
0227     "--" )
0228       # inserted by getopt to singal the end of options
0229       shift
0230       break
0231       ;;
0232   esac
0233 done
0234 
0235 # remove spurious whitespaces and tabs from EXTRA and DBPROXYOPTS
0236 EXTRA=$(echo "${EXTRA}" | xargs)
0237 DBPROXYOPTS=$(echo "${DBPROXYOPTS}" | xargs)
0238 
0239 # parse required argument
0240 if (( $# == 0 )); then
0241   err "$NAME error: missing argument."
0242   err "Try '$NAME --help' for more information."
0243   exit 1
0244 elif (( $# > 1 )); then
0245   err "$NAME error: too many arguments."
0246   err "Try '$NAME --help' for more information."
0247   exit 1
0248 else
0249   MENU="$1"
0250 fi
0251 
0252 log "----------------------------"
0253 log "Starting hltIntegrationTests"
0254 log "----------------------------"
0255 
0256 # create empty output directory
0257 rm -rf "${WORKDIR}"
0258 mkdir -p "${WORKDIR}"
0259 
0260 # if MENU = local cfg file, copy it to output directory
0261 # (that copy will be customised and used for the integration tests)
0262 if [ -f "${MENU}" ]; then
0263   cp "${MENU}" "${WORKDIR}"/hlt.py
0264 fi
0265 
0266 # move to, and run tests from, the output directory
0267 cd "${WORKDIR}"
0268 
0269 if [ -f hlt.py ]; then
0270 
0271   # customise cfg file
0272   log "Creating customised version of input cfg file (${MENU})"
0273 
0274   # warn that ${DATA} will be ignored
0275   [ ! "${DATA}" ] || printf "\n%s" "WARNING -- variable \${DATA}=\"${DATA}\" will be ignored !"
0276 
0277   cat <<@EOF >> hlt.py
0278 
0279 # change name of cms.Process
0280 process.setName_("TEST$(date -u +'%Y%m%d%H%M%S')")
0281 
0282 # disable HLT prescales
0283 if hasattr(process, 'PrescaleService'):
0284   del process.PrescaleService
0285 
0286 # set max number of input events
0287 process.maxEvents.input = ${SIZE}
0288 @EOF
0289 
0290   if [ "x${INPUT}" != "x" ]; then
0291     cat <<@EOF >> hlt.py
0292 
0293 # set input EDM file
0294 if hasattr(process, 'source') and hasattr(process.source, 'fileNames'):
0295   process.source.fileNames = [
0296     "${INPUT}",
0297   ]
0298 else:
0299   raise RuntimeError("ERROR -- unsupported cfg file: process.source.fileNames does not exist")
0300 @EOF
0301   fi
0302 
0303   # set MENU to name of ConfDB configuration (if any)
0304   MENU=$(python3 -c """
0305 import sys
0306 # redefine sys.argv (necessary to import
0307 # cfg file if the latter uses VarParsing)
0308 sys.argv = ['python3', 'hlt.py']
0309 from hlt import cms,process
0310 try:
0311   print(process.HLTConfigVersion.tableName.value())
0312 except:
0313   print('')
0314 """)
0315 
0316   # show name of ConfDB configuration (if available)
0317   [ ! "${MENU}" ] || log "ConfDB configuration: ${MENU}"
0318 
0319 else
0320   # if ${DATA} is empty, set it to "--data"
0321   [ "${DATA}" ] || DATA="--data"
0322   # download HLT menu from ConfDB
0323   HLTGETCMD="hltGetConfiguration ${MENU} \
0324     --process \"TEST$(date -u +'%Y%m%d%H%M%S')\"
0325     --full --offline ${DATA} --unprescale \
0326     --max-events ${SIZE} ${EXTRA} ${DBPROXYOPTS} --input ${INPUT}"
0327   HLTGETCMD=$(echo "${HLTGETCMD}" | xargs)
0328   log "Creating HLT menu from ConfDB configuration:\n> ${HLTGETCMD}"
0329   ${HLTGETCMD} > hlt.py
0330   # unset EXTRA environment variable (used later in cmsRun jobs)
0331   unset HLTGETCMD EXTRA
0332 fi
0333 
0334 # if missing, add a simplified HLTriggerFinalPath
0335 if ! grep -q HLTriggerFinalPath hlt.py; then
0336   cat >> hlt.py << @EOF
0337 
0338 # add (simplified) HLTriggerFinalPath if missing
0339 process.hltTriggerSummaryAOD = cms.EDProducer( "TriggerSummaryProducerAOD",
0340     processName = cms.string( "@" )
0341 )
0342 process.hltTriggerSummaryRAW = cms.EDProducer( "TriggerSummaryProducerRAW",
0343     processName = cms.string( "@" )
0344 )
0345 process.HLTriggerFinalPath = cms.Path( process.hltTriggerSummaryAOD + process.hltTriggerSummaryRAW )
0346 
0347 @EOF
0348 fi
0349 
0350 # select which events to run on
0351 if [ "${SELECTION}" == "complex" ]; then
0352   cat >> hlt.py << @EOF
0353 
0354 # event selection customised by hltIntegrationTests
0355 process.source.eventsToProcess = cms.untracked.VEventRange( '$(echo $EVENTS | sed -e"s/,/','/g")' )
0356 @EOF
0357 
0358 elif (( $SKIP > 0 )); then
0359   cat >> hlt.py << @EOF
0360 
0361 # event selection customised by hltIntegrationTests
0362 process.source.skipEvents = cms.untracked.uint32( $SKIP )
0363 @EOF
0364 fi
0365 
0366 # set the number of threads and streams for the whole hlt job
0367 cat >> hlt.py << @EOF
0368 
0369 # configure multithreading, and allocate 10 MB of stack space per thread
0370 process.options.numberOfThreads = $THREADS
0371 process.options.numberOfStreams = $STREAMS
0372 process.options.sizeOfStackForThreadsInKB = 10*1024
0373 # set allowed accelerators
0374 process.options.accelerators = [ "$ACCELERATOR" ]
0375 
0376 process.hltTriggerSummaryAOD.throw = cms.bool( True )
0377 @EOF
0378 
0379 # find the list of all trigger paths
0380 TRIGGERS=$(hltListPaths hlt.py -p --no-dep --exclude "^HLTriggerFinalPath$")
0381 echo "${TRIGGERS[@]}" > paths.txt
0382 
0383 # print some info
0384 if [ "$SELECTION" == "complex" ]; then
0385   log "Will run $(echo $TRIGGERS | wc -w) HLT paths over $(echo $EVENTS | tr ',' '\n' | wc -l) events, with $JOBS jobs in parallel"
0386 elif [ "$SIZE" == "-1" ]; then
0387   log "Will run $(echo $TRIGGERS | wc -w) HLT paths over all events, with $JOBS jobs in parallel"
0388 else
0389   log "Will run $(echo $TRIGGERS | wc -w) HLT paths over $SIZE events, with $JOBS jobs in parallel"
0390 fi
0391 
0392 # check the prescale modules
0393 hltCheckPrescaleModules -w hlt.py
0394 
0395 # check for multi-threading
0396 edmCheckMultithreading hlt.py | grep legacy
0397 
0398 log "Preparing single-trigger configurations"
0399 for TRIGGER in $TRIGGERS; do
0400   cat > "${TRIGGER}".py << @EOF
0401 from hlt import *
0402 
0403 process.hltOutput = cms.OutputModule( "PoolOutputModule",
0404     fileName = cms.untracked.string( "${TRIGGER}.root" ),
0405     fastCloning = cms.untracked.bool( False ),
0406     compressionAlgorithm = cms.untracked.string( "ZLIB" ),
0407     compressionLevel = cms.untracked.int32( 1 ),
0408     outputCommands = cms.untracked.vstring(
0409       'drop *',
0410       'keep edmTriggerResults_*_*_*',
0411     )
0412 )
0413 
0414 process.Output = cms.EndPath( process.hltOutput )
0415 
0416 process.schedule = cms.Schedule( process.${TRIGGER}, process.HLTriggerFinalPath, process.Output )
0417 
0418 process.hltTriggerSummaryAOD.throw = cms.bool( True )
0419 @EOF
0420 done
0421 
0422 # if a separate setup is requested, create the setup_cff.py file and patch all dumps to use it
0423 if [ "${SETUP}" ]; then
0424 
0425   if [ "${MENU}" ]; then
0426     # we use ${MENU} here, not ${SETUP}, as we force the same DB / converter as the main menu
0427     # this is the hltGetConfiguration behaviour and would be confusing if you had to
0428     # specify converter/db on the setup menu on hltIntegrationTests but not on hltGetConfiguration
0429     read SETUP_Vx SETUP_DB _ <<< $(parse_HLT_menu "${MENU}")
0430     log "Creating setup_cff from ConfDB configuration: ${SETUP_Vx}/${SETUP_DB}:${SETUP}"
0431     hltConfigFromDB --${SETUP_Vx} --${SETUP_DB} ${DBPROXYOPTS} --cff --configName "$SETUP" \
0432       --nopaths --services -FUShmDQMOutputService,-PrescaleService,-EvFDaqDirector,-FastMonitoringService > setup_cff.py
0433     sed -i -e's/process = cms.Process(.*)/&\nprocess.load("setup_cff")/' hlt.py $(for TRIGGER in $TRIGGERS; do echo "${TRIGGER}".py; done)
0434   else
0435     printf "%s\n" "WARNING -- \"--setup ${SETUP}\" will be ignored (failed to deduce name of HLT menu from hlt.py)"
0436   fi
0437 fi
0438 
0439 # run all HLT dumps
0440 cat > .makefile << @EOF
0441 TRIGGERS=$(echo $TRIGGERS)
0442 CFGS=\$(TRIGGERS:%=%.py)
0443 LOGS=\$(TRIGGERS:%=%.log)
0444 DONE=\$(TRIGGERS:%=%.done)
0445 
0446 .PHONY: all clean hlt \$(TRIGGERS)
0447 
0448 all: hlt \$(TRIGGERS)
0449 
0450 clean:
0451         @rm -f hlt.log hlt.done \$(LOGS) \$(DONE)
0452 
0453 hlt: hlt.done
0454 
0455 hlt.done: hlt.py
0456         @echo -e "\tfull menu dump"
0457         @cmsRun hlt.py ${EXTRA} >& hlt.log < /dev/zero && touch hlt.done
0458 
0459 \$(TRIGGERS): %: %.done
0460 
0461 \$(DONE): %.done: %.py
0462         @echo -e "\t\$*"
0463         @cmsRun \$*.py ${EXTRA} >& \$*.log < /dev/zero && touch \$*.done
0464 @EOF
0465 
0466 log "Running..."
0467 # if the whole hlt job runs with multithreading, run it by itself
0468 # otherwise, run it in parallel with the single-trigger jobs
0469 if ((THREADS > 0)); then
0470   make -f .makefile hlt
0471   make -f .makefile -j${JOBS} -k ${TRIGGERS}
0472 else
0473   make -f .makefile -j${JOBS} -k
0474 fi
0475 
0476 # compare HLT results
0477 log "Comparing the results of running each path by itself with those from the full menu"
0478 hltCompareResults
0479 STATUS=$?
0480 log "--------------------------"
0481 if [ "${STATUS}" -eq 0 ]; then
0482   log "hltIntegrationTests PASSED"
0483 else
0484   log "hltIntegrationTests FAILED"
0485 fi
0486 log "--------------------------"
0487 log "exit status: $STATUS"
0488 cd ..
0489 exit ${STATUS}