Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:17:07

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