diff --git a/graphics/VP1/VP1Algs/share/vp1 b/graphics/VP1/VP1Algs/share/vp1 index 9d167ec2ced7d46125550b7764e833ba4f2d2d0f..a002f03111787fac1c35d9912ad884f5903a203a 100755 --- a/graphics/VP1/VP1Algs/share/vp1 +++ b/graphics/VP1/VP1Algs/share/vp1 @@ -136,6 +136,7 @@ LOGFILE="" FILTEREVENTS="" FLAG_BATCH=0 FLAG_BATCH_ALL_EVENTS=0 +FLAG_BATCH_N_EVENTS=0 FLAG_BATCH_OUT_FOLDER="" FLAG_LARHV=0 # FLAG_FULLTOROIDS=0 @@ -197,6 +198,10 @@ while [ $i -le $# ]; do FLAG_HELP=1 + ######################## + # COMMAND-LINE OPTIONS # + ######################## + elif [ "x${arg}" == "x-larhv" ]; then FLAG_LARHV=1 # elif [ "x${arg}" == "x-fulltoroids" ]; then @@ -208,46 +213,53 @@ while [ $i -le $# ]; do # # # - ############## - # BATCH MODE # - ############## + #----------- + # BATCH MODE + #----------- # check if the user provided config files with -batch/-b options elif [ "x${arg}" == "x-batch" -o "x${arg}" == "x-b" ]; then if [[ "$*" == *.vp1* ]] then - #echo "config file: YES" FLAG_BATCH=1 # text in bold, note in bold and red. at the end we reset the text style echo "" echo -e "\e[1m\e[31m\e[4mNote!\e[24m You chose to run VP1 in 'batch-mode' ('${arg}').\e[39m" - echo -e "Thus the main VP1 window will be not shown, but in the end you will get a PNG file with the rendered image of the 3D window, based on the configuration file you provided.\e[0m" - echo "" - echo "(sleeping for 2 secs...)" + echo -e "Thus, the main VP1 window will be not shown, but in the end you will get a PNG file with the rendered image of the 3D window, based on the configuration file you provided.\e[0m" echo "" - sleep 2s # to let the user read the warning message about the batch mode else - #echo "config file: NO" - ERRORS="$ERRORS\nBatch mode needs a configuration file ('.vp1')" + ERRORS="$ERRORS\nBatch mode needs at least one configuration file ('.vp1')" fi elif [ "x${arg}" == "x-batch-all-events" ]; then FLAG_BATCH_ALL_EVENTS=1 - if [ "x$FLAG_BATCH_ALL_EVENTS" == "x1" -a "x$FLAG_BATCH" == "x0" ]; then - ERRORS="$ERRORS\nOption '-batch-all-events' can't be used without '-batch'..." - fi + elif [ "x${arg}" == "x-batch-random-config" ]; then + FLAG_BATCH_RANDOM_CONFIG=1 + echo -e "\e[1m\e[31m\e[4mNote!\e[24m You chose the option 'batch-random-config' ('${arg}').\e[39m" + echo -e "Thus, for each event a different configuration file will be used, randomly picked from the configuration files (.vp1) you provide.\e[0m" + echo #elif [ "x${arg}" == "x-batch-output-folder" ]; then elif [ "x${arg:0:21}" == "x-batch-output-folder=" ]; then FLAG_BATCH_OUT_FOLDER=${arg:21:$((${#arg}-21))} if [ "x$FLAG_BATCH_OUT_FOLDER" == "x" ]; then ERRORS="$ERRORS\nNeed argument to -batch-output-folder. Ex: -batch-output-folder=myFolder" fi - if [ "x$FLAG_BATCH_OUT_FOLDER" != "x" -a "x$FLAG_BATCH" == "x0" ]; then - ERRORS="$ERRORS\nOption '-batch-output-folder' can't be used without '-batch'..." - fi elif [ "x${arg:0:21}" == "x-batch-output-folder" ]; then # catch arg without '=' character FLAG_BATCH_OUT_FOLDER_2=${arg:20:$((${#arg}-20))} if [ "x$FLAG_BATCH_OUT_FOLDER_2" == "x" ]; then ERRORS="$ERRORS\nNeed argument to -batch-output-folder. Ex: -batch-output-folder=path/to/myFolder" fi + elif [ "x${arg:0:16}" == "x-batch-n-events=" ]; then + FLAG_BATCH_N_EVENTS=${arg:16:$((${#arg}-16))} + echo -e "\e[1m\e[31m\e[4mNote!\e[24m You chose to run VP1 in 'batch-mode' over ${FLAG_BATCH_N_EVENTS} events only. ('${arg}').\e[39m" + if [ "x$FLAG_BATCH_N_EVENTS" == "x" ]; then + ERRORS="$ERRORS\nNeed a numeric argument to -batch-n-events" + else + #check it is integer: + echo "$FLAG_BATCH_N_EVENTS" | grep '^[0-9][0-9]*$' > /dev/null 2>&1 || \ + ERRORS="$ERRORS\nArgument to -batch-n-events must be an integer!" + fi + #echo "(sleeping for 2 secs...)" + echo "" + sleep 2s # to let the user read the warning messages about the batch mode ### end of batch mode settings # # @@ -393,19 +405,22 @@ while [ $i -le $# ]; do LOCALEVENTSRC_AVAILDIRS[${#LOCALEVENTSRC_AVAILDIRS[@]}]="$EXTRADIR" fi fi - - ################### + + + ################### # VP1 CONFIG FILE # ################### elif [ ${#arg} -gt 4 -a ${arg:$((${#arg}-4)):4} == ".vp1" ]; then FILES_VP1CFG[${#FILES_VP1CFG[@]}]="${arg}" - + + ##################### # EXTRA JOB OPTIONS # ##################### elif [ ${#arg} -gt 3 -a ${arg:$((${#arg}-3)):3} == ".py" ]; then FILES_EXTRAJOBOPT[${#FILES_EXTRAJOBOPT[@]}]="${arg}" + ######################## # EOS / LFN INPUT DATA # ######################## @@ -457,6 +472,30 @@ done ### SETTINGS ### ######################## + +# batch mode +if [ "x$FLAG_BATCH_N_EVENTS" != "x0" -a "x$FLAG_BATCH" == "x0" ]; then + ERRORS="$ERRORS\nOption '-batch-n-events' can't be used without '-batch'..." +fi +if [ "x$FLAG_BATCH_N_EVENTS" != "x0" -a "x$FLAG_BATCH_ALL_EVENTS" == "x1" ]; then + ERRORS="$ERRORS\nOption '-batch-n-events' can't be used together with '-batch-all-events'... Please choose one or the other." +fi +if [ "x$FLAG_BATCH_ALL_EVENTS" == "x1" -a "x$FLAG_BATCH" == "x0" ]; then + ERRORS="$ERRORS\nOption '-batch-all-events' can't be used without '-batch'..." +fi +if [ "x$FLAG_BATCH_RANDOM_CONFIG" == "x1" -a "x$FLAG_BATCH" == "x0" ]; then + ERRORS="$ERRORS\nOption '-batch-random-config' can't be used without '-batch'..." +fi +if [ "x$FLAG_BATCH_RANDOM_CONFIG" == "x1" ]; then + echo -e "\e[1m\e[31m\e[4mNote!\e[24m You chose the option 'batch-random-config' ('${arg}').\e[39m" + echo -e "Thus, for each event a different configuration file will be used, randomly picked from the configuration files (.vp1) you provided:\e[0m" + printf "["; printf '"%s", ' "${FILES_VP1CFG[@]}"; printf "]\n"; echo +fi +if [ "x$FLAG_BATCH_OUT_FOLDER" != "x" -a "x$FLAG_BATCH" == "x0" ]; then + ERRORS="$ERRORS\nOption '-batch-output-folder' can't be used without '-batch'..." +fi + + #live & noautoconf flags (AutoConfiguration is disabled in live and livelocal modes) if [ "x$FLAG_LIVE" == "x1" ]; then @@ -621,8 +660,12 @@ if [ "x$FLAG_HELP" != "x0" ]; then echo echo " -batch-all-events : Process all events in the input data file in '-batch' mode. Use this together with '-batch'." echo + echo " -batch-n-events=N : Process 'N' events in the input data file in '-batch' mode. Use this together with '-batch'." + echo echo " -batch-output-folder : Specify an output folder to store the event displays produced with the '-batch' option." echo + echo " -batch-random-config : Run VP1 in 'batch' mode; for each single event a configuration file will be randomly picked out of the configuration files provided by the user. Use this together with '-batch'." + echo echo " -larhv : Access current LAr HV data in the DCS_OFL database via VP1 CaloReadout system." echo echo " -data : Input files are data [default assumption is simulation]. " @@ -731,6 +774,7 @@ if [ "x$FLAG_HELP" != "x0" ]; then echo "liberally (when it makes sense - of course dont put e.g. both -trigdec=file.xml and -trigdec=embedded)" echo echo + echo "*********" echo "Examples:" echo echo " * Simply run on the input files myevents1.pool.root and myevents2.pool.root" @@ -763,7 +807,7 @@ if [ "x$FLAG_HELP" != "x0" ]; then echo echo " \$>$APP myevents1.pool.root myconfig1.vp1 myconfig2.vp1" echo - echo " * Run on myevents1.pool.root, and preload the tab/channel configuration files myconfig1.vp1 and myconfig2.vp1:" + echo " * Run on myevents1.pool.root, and preload two tab/channel configuration files: myconfig1.vp1 and myconfig2.vp1; at start, VP1 will create multiple tabs, from the pieces of configuration information contained in both files:" echo echo " \$>$APP myevents1.pool.root myconfig1.vp1 myconfig2.vp1" echo @@ -802,7 +846,7 @@ while [ $i -le $((${#FILES_VP1CFG[@]}-1)) ]; do if [ "x$PYTHONFILES" == "x" ]; then PYTHONFILES='vp1CfgFiles=["'"${FILES_VP1CFG[$i]}"'"' else - PYTHONFILES="${PYTHONFILES},${FILES_VP1CFG[$i]}"'"' + PYTHONFILES="${PYTHONFILES}"',"'"${FILES_VP1CFG[$i]}"'"' fi i=$((i+1)) done @@ -912,10 +956,18 @@ if [ "x$FLAG_BATCH_ALL_EVENTS" != "x0" ]; then if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi OPTS="${OPTS}vp1BatchAllEvents=True" fi +if [ "x$FLAG_BATCH_N_EVENTS" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1BatchNEvents=$FLAG_BATCH_N_EVENTS" +fi if [ "x$FLAG_BATCH_OUT_FOLDER" != "x" ]; then if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi OPTS="${OPTS}vp1BatchOutFolder=\"$FLAG_BATCH_OUT_FOLDER\"" fi +if [ "x$FLAG_BATCH_RANDOM_CONFIG" != "x0" ]; then + if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi + OPTS="${OPTS}vp1BatchRandomConfiguration=True" +fi if [ "x$FLAG_LARHV" != "x0" ]; then if [ "x$OPTS" != "x" ]; then OPTS="$OPTS;"; fi OPTS="${OPTS}vp1LarHvData=True" diff --git a/graphics/VP1/VP1Algs/share/vp1.py b/graphics/VP1/VP1Algs/share/vp1.py index 93b547cbeaccaf8ef91b61774ef101798085a6db..862ce04dc59f9da452ebd603fb2e4a344fe17054 100644 --- a/graphics/VP1/VP1Algs/share/vp1.py +++ b/graphics/VP1/VP1Algs/share/vp1.py @@ -22,7 +22,9 @@ if not 'vp1MultiAvailableSrcDirs' in dir(): vp1MultiAvailableSrcDirs = [] if not 'vp1TrigDecXML' in dir(): vp1TrigDecXML="" if not 'vp1Batch' in dir(): vp1Batch=False if not 'vp1BatchAllEvents' in dir(): vp1BatchAllEvents=False +if not 'vp1BatchNEvents' in dir(): vp1BatchNEvents=0 if not 'vp1BatchOutFolder' in dir(): vp1BatchOutFolder="" +if not 'vp1BatchRandomConfiguration' in dir(): vp1BatchRandomConfiguration=False if not 'vp1LarHvData' in dir(): vp1LarHvData=False # if not 'vp1FullToroids' in dir(): vp1FullToroids=False if not 'vp1CruiseTime' in dir(): vp1CruiseTime=0 @@ -228,8 +230,12 @@ if vp1Batch: os.putenv("VP1_BATCHMODE","1") if vp1BatchAllEvents: os.putenv("VP1_BATCHMODE_ALLEVENTS","1") +if vp1BatchNEvents > 0: + os.putenv("VP1_BATCHMODE_NEVENTS", str(vp1BatchNEvents) ) if (vp1BatchOutFolder != ""): os.putenv("VP1_BATCHMODE_OUT_FOLDER", vp1BatchOutFolder) +if vp1BatchRandomConfiguration: + os.putenv("VP1_BATCHMODE_RANDOMCONFIG","1") diff --git a/graphics/VP1/VP1AlgsBatch/CMakeLists.txt b/graphics/VP1/VP1AlgsBatch/CMakeLists.txt index 9eafa4947feaf0926094a795230f49c2694db687..e7f4918b4485550573a4d84ea4d0202501c9b9b3 100644 --- a/graphics/VP1/VP1AlgsBatch/CMakeLists.txt +++ b/graphics/VP1/VP1AlgsBatch/CMakeLists.txt @@ -24,3 +24,5 @@ atlas_add_component( VP1AlgsBatch # Install files from the package: atlas_install_runtime( share/*.vp1 ) +atlas_install_joboptions( share/*.py ) +atlas_install_scripts( share/vp1batch ) diff --git a/graphics/VP1/VP1AlgsBatch/share/vp1batch b/graphics/VP1/VP1AlgsBatch/share/vp1batch new file mode 100755 index 0000000000000000000000000000000000000000..defba01ff99a5ffc29128a52369a0e56de4e1fbd --- /dev/null +++ b/graphics/VP1/VP1AlgsBatch/share/vp1batch @@ -0,0 +1,20 @@ +#!/bin/bash + +# Script for constructing the command which launches vp1 with advanced "batch" options +# +# Author: Riccardo.Maria.Bianchi@cern.ch +# 11 Jan 2019 + + +INPUT_FILE=$1 + + +echo "Running on input file '$1'" + +JOBOPT="VP1AlgsBatch/vp1batch.py" +if [ -f vp1batch.py ]; then + JOBOPT=vp1batch.py +fi + + +echo athena.py $ATHENAOPTS -c "'$OPTS'" $JOBOPT $EXTRAJOBOPT diff --git a/graphics/VP1/VP1AlgsBatch/share/vp1batch.py b/graphics/VP1/VP1AlgsBatch/share/vp1batch.py new file mode 100644 index 0000000000000000000000000000000000000000..9f9dcf5433b17fe10c0ae94c2430148306059bc3 --- /dev/null +++ b/graphics/VP1/VP1AlgsBatch/share/vp1batch.py @@ -0,0 +1,13 @@ + +if not 'vp1InputFile' in dir(): vp1InputFiles = [] + +# customize the algorithm +from VP1AlgsBatch.VP1AlgsBatchConf import VP1BatchOnLatestEvent +VP1BatchOnLatestEvent.DestinationDirectory="atlasathome_test" +VP1BatchOnLatestEvent.UseRandomVP1ConfigFile=True + + +from AthenaCommon.AlgSequence import AlgSequence +topSequence = AlgSequence() +topSequence += VP1BatchOnLatestEvent() +topSequence.TimeOut=0 diff --git a/graphics/VP1/VP1AlgsBatch/src/VP1BatchOnLatestEvent.cxx b/graphics/VP1/VP1AlgsBatch/src/VP1BatchOnLatestEvent.cxx index 23594404a1ddd7d9b0ddff529432a3b2d63c7e17..541101c33c0dfa487ce226a9a458f6b59fc19476 100755 --- a/graphics/VP1/VP1AlgsBatch/src/VP1BatchOnLatestEvent.cxx +++ b/graphics/VP1/VP1AlgsBatch/src/VP1BatchOnLatestEvent.cxx @@ -151,7 +151,7 @@ void VP1BatchOnLatestEvent::makeEventDisplay() { msg(MSG::INFO) << "--> Input VP1 Configuration file: " << m_inputVP1CfgFile << endmsg; - // LAUNCH VP1-Batch on the latest-produced ESD file + // build the command to launch VP1-Batch on the latest-produced ESD file std::string commandStr = "vp1 -batch"; // add custom output folder, if user specified it diff --git a/graphics/VP1/VP1Base/src/IVP13DStandardChannelWidget.cxx b/graphics/VP1/VP1Base/src/IVP13DStandardChannelWidget.cxx index 51d69c6725b433670a0caf72e907f39c315082f7..327ea8befd68e656332e2f5400ea1125c37663c2 100644 --- a/graphics/VP1/VP1Base/src/IVP13DStandardChannelWidget.cxx +++ b/graphics/VP1/VP1Base/src/IVP13DStandardChannelWidget.cxx @@ -435,7 +435,7 @@ void IVP13DStandardChannelWidget::stopSpinning() //___________________________________________________________________________ QPixmap IVP13DStandardChannelWidget::getSnapshot(bool transp, int width, bool batch) { - VP1Msg::messageDebug("IVP13DStandardChannelWidget::getSnapshot() - transparent bkg: "+QString(transp)+" , width: "+QString::number(width)+" , batch: "+QString(batch)); + VP1Msg::messageDebug("IVP13DStandardChannelWidget::getSnapshot() - transparent bkg: "+QString::number(transp)+" , width: "+QString::number(width)+" , batch: "+QString::number(batch)); // SoToVRML2Action tovrml2; // tovrml2.apply(m_d->selection); // SoVRMLGroup *newroot = tovrml2.getVRML2SceneGraph(); diff --git a/graphics/VP1/VP1Gui/CMakeLists.txt b/graphics/VP1/VP1Gui/CMakeLists.txt index c4a375db06b8ddb3873bc498f268d520fa5b88be..73e9f8a7757977441bab0ae883cfe477adf82d71 100644 --- a/graphics/VP1/VP1Gui/CMakeLists.txt +++ b/graphics/VP1/VP1Gui/CMakeLists.txt @@ -35,8 +35,3 @@ atlas_add_library( VP1Gui VP1Gui/*.h src/*.h src/*.cxx src/*.qrc Qt5::PrintSupport PRIVATE_LINK_LIBRARIES ${COIN3D_LIBRARIES} ${SOQT_LIBRARIES} Qt5::Network ) - -# Install files from the package: -##atlas_install_scripts( share/* ) # installs into bin/ -atlas_install_runtime( share/* ) # install into share/ - diff --git a/graphics/VP1/VP1Gui/VP1Gui/VP1ExecutionScheduler.h b/graphics/VP1/VP1Gui/VP1Gui/VP1ExecutionScheduler.h index 773653e88a7038e617fea1ed17a7f1096f9404ad..dac9c6a0f891ee97aae97870d32467e93de6f85e 100644 --- a/graphics/VP1/VP1Gui/VP1Gui/VP1ExecutionScheduler.h +++ b/graphics/VP1/VP1Gui/VP1Gui/VP1ExecutionScheduler.h @@ -54,10 +54,13 @@ public: //init/cleanup: - static VP1ExecutionScheduler* init(StoreGateSvc* eventStore,StoreGateSvc* detStore, - ISvcLocator* svcLocator,IToolSvc*toolSvc, + static VP1ExecutionScheduler* init(StoreGateSvc* eventStore, + StoreGateSvc* detStore, + ISvcLocator* svcLocator, + IToolSvc*toolSvc, QStringList joboptions, - QString initialCruiseMode = "NONE", unsigned initialCruiseSeconds = 10, + QString initialCruiseMode = "NONE", + unsigned initialCruiseSeconds = 10, QString singleEventSource = "", QString singleEventLocalTmpDir = "", unsigned localFileCacheLimit = 10, diff --git a/graphics/VP1/VP1Gui/VP1Gui/VP1MainWindow.h b/graphics/VP1/VP1Gui/VP1Gui/VP1MainWindow.h index 7c6a48ee98f952fd479906a78504086b56c75ea1..7507310dac57ad7e71aba72aa2e10da4594963cb 100644 --- a/graphics/VP1/VP1Gui/VP1Gui/VP1MainWindow.h +++ b/graphics/VP1/VP1Gui/VP1Gui/VP1MainWindow.h @@ -120,6 +120,7 @@ public slots: void selectedChannelChanged(IVP1ChannelWidget*); void loadConfigurationFromFile(QString file); + void replaceConfigurationFile(QString file); void addToMessageBox( const QString&, const QString& extrastyleopts = "", const QString& title = "", const QString& titleextrastyleopts = "" ); diff --git a/graphics/VP1/VP1Gui/VP1Gui/VP1TabManager.h b/graphics/VP1/VP1Gui/VP1Gui/VP1TabManager.h index 645fbca0a6999d3d6031abcf05d55a72fe0a20a7..8f21ea43185c1561a162776f32188d58ff264449 100644 --- a/graphics/VP1/VP1Gui/VP1Gui/VP1TabManager.h +++ b/graphics/VP1/VP1Gui/VP1Gui/VP1TabManager.h @@ -69,6 +69,8 @@ public slots: void moveChannelToTab(QString channeluniquename,QString tabname); void cloneChannelToTab(QString channeluniquename,QString tabname); void cloneTab(QString oldtabname,QString newtabname); + void removeAllTabs(); + void saveConfigurationToFile(QString filename,const bool& askonoverride=true); void loadConfigurationFromFile(QString filename,const QMap<QString,QString>& availableplugins); diff --git a/graphics/VP1/VP1Gui/src/VP1ExecutionScheduler.cxx b/graphics/VP1/VP1Gui/src/VP1ExecutionScheduler.cxx index 4cbc02c35b2ba88d572196aaa9c63dd004e65f9d..bac60a9e21fcbb5e4e9f02a37651d12fae81b131 100644 --- a/graphics/VP1/VP1Gui/src/VP1ExecutionScheduler.cxx +++ b/graphics/VP1/VP1Gui/src/VP1ExecutionScheduler.cxx @@ -56,6 +56,8 @@ #include "VP1Base/VP1AthenaPtrs.h" #include "VP1Base/VP1Settings.h" +#include "VP1UtilsBase/VP1BatchUtilities.h" + #include <QApplication> #include <QProgressBar> #include <QDesktopWidget> @@ -64,6 +66,7 @@ #include <QCursor> #include <QTimer> #include <QSet> +#include <QStringList> #include <QMessageBox> #include <Inventor/C/errors/debugerror.h> @@ -75,6 +78,19 @@ #include <sstream> // std::ostringstream #include <ctime> #include <stdexcept> +#include <string> +#include <vector> + + + +std::vector<std::string> qstringlistToVecString(QStringList list) +{ + std::vector<std::string> vec; + foreach(QString str, list) { + vec.push_back(str.toStdString()); + } + return vec; +} //___________________________________________________________________ @@ -87,8 +103,13 @@ public: VP1Prioritiser * prioritiser; VP1MainWindow* mainwindow; + long int eventsProcessed; + bool batchMode; bool batchModeAllEvents; + int batchModeNEvents; + bool batchModeRandomConfig; + VP1BatchUtilities* batchUtilities; VP1AvailEvents * availEvents; @@ -178,19 +199,24 @@ private: //___________________________________________________________________ VP1ExecutionScheduler::VP1ExecutionScheduler( QObject * parent, - StoreGateSvc* eventStore,StoreGateSvc* detStore, - ISvcLocator* svcLocator,IToolSvc*toolSvc, + StoreGateSvc* eventStore, + StoreGateSvc* detStore, + ISvcLocator* svcLocator, + IToolSvc*toolSvc, VP1AvailEvents * availEvents) : QObject(parent), m_d(new Imp) { m_d->availEvents = availEvents; VP1AthenaPtrs::setPointers(eventStore,detStore,svcLocator,toolSvc); + m_d->eventsProcessed = 0; m_d->scheduler = this; m_d->prioritiser = new VP1Prioritiser(this); m_d->mainwindow = new VP1MainWindow(this,availEvents);//mainwindow takes ownership of available events m_d->batchMode = false; + m_d->batchUtilities = nullptr; m_d->batchModeAllEvents = false; + m_d->batchModeNEvents = 0; m_d->allSystemsRefreshed = false; m_d->goingtonextevent=true; m_d->currentsystemrefreshing=0; @@ -211,19 +237,24 @@ VP1ExecutionScheduler::VP1ExecutionScheduler( QObject * parent, // Init and show the main window of VP1 SoQt::init( m_d->mainwindow );// SoQt::init( "VP1" ); + + // check if 'batch mode' bool batchMode = VP1QtUtils::environmentVariableIsSet("VP1_BATCHMODE"); // ::getenv("VP1_BATCHMODE"); qDebug() << "VP1ExecutionScheduler:: Do we run in 'batch' mode?" << batchMode; if (batchMode) { VP1Msg::messageWarningAllRed("User has run VP1 in 'batch-mode', so the main window of the program will not be shown."); m_d->batchMode = true; + + // check if the user set the "all events" option as well + m_d->batchModeAllEvents = VP1QtUtils::environmentVariableIsSet("VP1_BATCHMODE_ALLEVENTS"); + + // check if the user set the "random configuration file" option as well + m_d->batchModeRandomConfig = VP1QtUtils::environmentVariableIsSet("VP1_BATCHMODE_RANDOMCONFIG"); } else { m_d->mainwindow->show(); } - // If in batch mode, let's see if the user set the "all events" options as well - m_d->batchModeAllEvents = VP1QtUtils::environmentVariableIsSet("VP1_BATCHMODE_ALLEVENTS"); // ::getenv("VP1_BATCHMODE"); - m_d->pb = m_d->mainwindow->progressbar; m_d->pbtimer = new QTimer(this); @@ -265,6 +296,7 @@ VP1ExecutionScheduler::VP1ExecutionScheduler( QObject * parent, VP1ExecutionScheduler::~VP1ExecutionScheduler() { m_d->refreshtimer->stop(); + delete m_d->batchUtilities; delete m_d->mainwindow; delete m_d->prioritiser; delete m_d->globalEventFilter; @@ -272,8 +304,10 @@ VP1ExecutionScheduler::~VP1ExecutionScheduler() } //___________________________________________________________________ -VP1ExecutionScheduler* VP1ExecutionScheduler::init( StoreGateSvc* eventStore, StoreGateSvc* detStore, - ISvcLocator* svcLocator, IToolSvc*toolSvc, +VP1ExecutionScheduler* VP1ExecutionScheduler::init( StoreGateSvc* eventStore, + StoreGateSvc* detStore, + ISvcLocator* svcLocator, + IToolSvc*toolSvc, QStringList joboptions, QString initialCruiseMode, unsigned initialCruiseSeconds, @@ -354,7 +388,19 @@ VP1ExecutionScheduler* VP1ExecutionScheduler::init( StoreGateSvc* eventStore, St } else { foreach(QString opt,joboptions) scheduler->m_d->mainwindow->loadConfigurationFromFile(opt); + + if ( scheduler->m_d->batchMode ) { + if (scheduler->m_d->batchModeRandomConfig ) { + scheduler->m_d->batchUtilities = new VP1BatchUtilities( qstringlistToVecString(joboptions) ); + } + QString batchNevents = VP1QtUtils::environmentVariableValue("VP1_BATCHMODE_NEVENTS"); + if (batchNevents > 0 ) { + scheduler->m_d->batchModeNEvents = batchNevents.toInt(); + } + } } + + if (scheduler->m_d->mainwindow->tabWidget_central->count()<=1) { if (initialCruiseMode=="TAB") { VP1Msg::message("ERROR: Can not start in cruisemode TAB unless there are at least 2 tabs loaded from initial .vp1 files. Reverting to cruise mode NONE."); @@ -396,6 +442,7 @@ VP1ExecutionScheduler* VP1ExecutionScheduler::init( StoreGateSvc* eventStore, St if ( cruisesecs>0 ) scheduler->m_d->mainwindow->spinBox_cruise->setValue(cruisesecs); + return scheduler; } @@ -504,8 +551,15 @@ bool VP1ExecutionScheduler::executeNewEvent(const int& runnumber, const unsigned VP1Msg::messageDebug("batch mode: " + QString::number(m_d->batchMode)); + + if (m_d->batchModeRandomConfig) { + VP1Msg::messageDebug("User chose 'batch' and 'batch-random-config'. So we now replace the configuration with a random one from the input set..."); + QString randomConfigFile = QString::fromStdString( m_d->batchUtilities->getRandomConfigFile() ); + m_d->mainwindow->replaceConfigurationFile(randomConfigFile); + } + if ( m_d->batchMode && m_d->allVisibleRefreshed() ) { // or m_d->allSystemsRefreshed ??? - VP1Msg::messageDebug("We're in batch mode, skipping..."); + VP1Msg::messageDebug("We're in batch mode, skipping the execution of the GUI..."); } else { VP1Msg::messageDebug("skipEvent: " + QString::number(m_d->skipEvent)); if(m_d->skipEvent) { @@ -544,7 +598,8 @@ bool VP1ExecutionScheduler::executeNewEvent(const int& runnumber, const unsigned eraseSystem(s); } - VP1Msg::messageDebug("event processed."); + ++m_d->eventsProcessed; // we don't use Athena's tools for this, so we can use this in VP1Light as well. + VP1Msg::messageDebug("event processed. " + QString::number(m_d->eventsProcessed) + " events processed so far."); //Let channels know we are going to the next event now: foreach(IVP1ChannelWidget*cw, m_d->mainwindow->tabManager()->allChannels()) { @@ -553,7 +608,8 @@ bool VP1ExecutionScheduler::executeNewEvent(const int& runnumber, const unsigned qApp->processEvents(QEventLoop::ExcludeUserInputEvents|QEventLoop::ExcludeSocketNotifiers); - VP1Msg::messageDebug("mainwindow->mustQuit: " + QString::number(m_d->mainwindow->mustQuit()) ); + + VP1Msg::messageDebug("mainwindow->mustQuit ? " + QString::number(m_d->mainwindow->mustQuit()) ); return !m_d->mainwindow->mustQuit(); } @@ -737,6 +793,7 @@ void VP1ExecutionScheduler::refreshSystem(IVP1System*s) if (m_d->batchMode) { VP1Msg::messageDebug("we are in 'batch-mode'..."); + VP1Msg::messageDebug("batchModeNEvents: " + QString::number(m_d->batchModeNEvents) + " - m_d->eventsProcessed: " + QString::number(m_d->eventsProcessed) ); // saving the snapshot of the 3D window to a file QString save_ok = saveSnaphsotToFile(s, true); @@ -748,16 +805,34 @@ void VP1ExecutionScheduler::refreshSystem(IVP1System*s) if (m_d->batchModeAllEvents) { + VP1Msg::messageWarningAllRed("******************************************************************"); VP1Msg::messageWarningAllRed("'batch mode' with 'all events' option. Moving to the next event..."); VP1Msg::messageWarningAllRed("******************************************************************"); + // N.B. calling QApplication::quit() here it makes VP1 move to the next event; QApplication::quit(); - } else { - VP1Msg::messageWarningRed("'batch mode'. Now exiting VP1"); - - // Here we want to close VP1 completely. + // Now, VP1ExecutionScheduler::executeNewEvent() will end, then VP1Gui::executeNewEvent() will end, then they will start again: first VP1Gui then VP1ExecutionScheduler. + } else if ( m_d->batchModeNEvents > 0 ) { + if ( m_d->batchModeNEvents == m_d->eventsProcessed+1) { // here we use +1 because this is performed after the creation of the event snapshot. //TODO: maybe we can move this to a more natural place, at the beginning or at the end of an event + VP1Msg::messageWarningAllRed("******************************************************************"); + VP1Msg::messageWarningAllRed("'batch mode' with 'batch-n-events' option. Processed the " + QString::number(m_d->eventsProcessed+1) + " events set by the user. Now exiting VP1"); + VP1Msg::messageWarningAllRed("******************************************************************"); + m_d->mainwindow->close(); + } else { + VP1Msg::messageWarningAllRed("'batch mode' with 'batch-n-events' option. Moving to the next event..."); + // N.B. calling QApplication::quit() here it makes VP1 move to the next event; + QApplication::quit(); + // Now, VP1ExecutionScheduler::executeNewEvent() will end, then VP1Gui::executeNewEvent() will end, then they will start again: first VP1Gui then VP1ExecutionScheduler. + } + } + else { + // We come here if the user did not choose to run batch mode on all events. + // Thus, we want to close VP1 completely. // So, in order to do that, we have to call "MainWindow::close()" + VP1Msg::messageWarningRed("'batch mode'. Done. Now exiting VP1"); m_d->mainwindow->close(); } + + } } } diff --git a/graphics/VP1/VP1Gui/src/VP1Gui.cxx b/graphics/VP1/VP1Gui/src/VP1Gui.cxx index e57459886c9c1adb526708b03696013858abf5c5..920f95ddbd20e93d6fa4f914cfee09408812f264 100644 --- a/graphics/VP1/VP1Gui/src/VP1Gui.cxx +++ b/graphics/VP1/VP1Gui/src/VP1Gui.cxx @@ -184,7 +184,10 @@ void VP1Gui::init() VP1Msg::message(" Launching the VP1 GUI"); VP1Msg::message("==================================================="); VP1Msg::message(""); - m_d->the_scheduler = VP1ExecutionScheduler::init(m_d->sg,m_d->detstore,m_d->svclocator,m_d->toolSvc, + m_d->the_scheduler = VP1ExecutionScheduler::init(m_d->sg, + m_d->detstore, + m_d->svclocator, + m_d->toolSvc, m_d->initialvp1files, m_d->initialCruiseMode,m_d->initialCruiseSeconds, m_d->singleEventSource,m_d->singleEventLocalTmpDir, @@ -204,13 +207,9 @@ void VP1Gui::cleanup() //____________________________________________________________________ bool VP1Gui::executeNewEvent( const int& run, const uint64_t& event, const unsigned& triggerType, const unsigned& time ) { - //tests - int evN = event; - qulonglong evNqu = event; + VP1Msg::messageDebug("Examining new event ( run# "+QString::number(run)+", event# "+QString::number(event)+" )"); - qDebug() << "tests:" << QString::number(event) << QString::number(evN) << QString::number(evNqu); - VP1Msg::messageDebug("Examining new event ( run# "+QString::number(run)+", event# "+QString::number(event)+" )"); bool b = m_d->the_scheduler->executeNewEvent(run,event,triggerType,time); @@ -219,7 +218,7 @@ bool VP1Gui::executeNewEvent( const int& run, const uint64_t& event, const unsig // only when the user clicks on the "Next event" button. VP1Msg::messageDebug("Leaving event ( run# "+QString::number(run)+", event# "+QString::number(event)+" )" - +(nextRequestedEventFile().empty()?QString(""):". Next requested event: "+QString(nextRequestedEventFile().c_str()))); + +(nextRequestedEventFile().empty()?QString(""):". Next requested event file: "+QString(nextRequestedEventFile().c_str()))); VP1Msg::messageDebug("end of VP1Gui::executeNewEvent()."); diff --git a/graphics/VP1/VP1Gui/src/VP1MainWindow.cxx b/graphics/VP1/VP1Gui/src/VP1MainWindow.cxx index 9eae4f616a5f615a442547ea54a3f1824cca2786..341509dbe8471c50a431597402e31baba2e83246 100644 --- a/graphics/VP1/VP1Gui/src/VP1MainWindow.cxx +++ b/graphics/VP1/VP1Gui/src/VP1MainWindow.cxx @@ -1318,6 +1318,14 @@ void VP1MainWindow::loadConfigurationFromFile(QString file) { m_tabmanager->loadConfigurationFromFile(file,availablePluginFiles()); } +//_________________________________________________________________________________ +void VP1MainWindow::replaceConfigurationFile(QString file) +{ + VP1Msg::messageDebug("VP1MainWindow::replaceConfigurationFile() : " + file); + m_tabmanager->removeAllTabs(); + m_tabmanager->loadConfigurationFromFile(file,availablePluginFiles()); +} + //_________________________________________________________________________________ void VP1MainWindow::listenOnTcp() { diff --git a/graphics/VP1/VP1Gui/src/VP1TabManager.cxx b/graphics/VP1/VP1Gui/src/VP1TabManager.cxx index 3baf2179f05e0dd33bf629943448ecac67f3da4c..c72b69ef6b37057fc498e3fba58458b50b4bc83a 100644 --- a/graphics/VP1/VP1Gui/src/VP1TabManager.cxx +++ b/graphics/VP1/VP1Gui/src/VP1TabManager.cxx @@ -543,6 +543,7 @@ QStringList VP1TabManager::tabList() { void VP1TabManager::removeTab( QString tabname ) { if (!m_d->checkTabnameExists(tabname)) return; + bool save = m_d->dontEmitVisibilityChanges; m_d->dontEmitVisibilityChanges=true; @@ -578,6 +579,17 @@ void VP1TabManager::removeTab( QString tabname ) { currentVisibleChanged(); } + +//_______________________________________________________________________ +void VP1TabManager::removeAllTabs() +{ + VP1Msg::messageDebug("VP1TabManager::removeAllTabs()"); + foreach(QString tab, tabList() ) { + removeTab(tab); + } +} + + //___________________________________________________________________________________ void VP1TabManager::removeChannel(QString channeluniquename) { diff --git a/graphics/VP1/VP1UtilsBase/CMakeLists.txt b/graphics/VP1/VP1UtilsBase/CMakeLists.txt index 160aa3359f696c6fea764eb90b531f8b8b21545a..371b777769cd435d4b5770b1de70fdd7a1b4ccae 100644 --- a/graphics/VP1/VP1UtilsBase/CMakeLists.txt +++ b/graphics/VP1/VP1UtilsBase/CMakeLists.txt @@ -15,3 +15,7 @@ atlas_add_library( VP1UtilsBase VP1UtilsBase/*.h src/*.cxx PUBLIC_HEADERS VP1UtilsBase PRIVATE_LINK_LIBRARIES Qt5::Core ) + +# Install files from the package: +atlas_install_runtime( share/*.vp1 ) # default VP1 config files for batch mode +atlas_install_runtime( share/*.png ) # ATLAS logo diff --git a/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1BatchUtilities.h b/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1BatchUtilities.h new file mode 100644 index 0000000000000000000000000000000000000000..37725e8595836e3e50cab82801c9bd426eb4e6dc --- /dev/null +++ b/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1BatchUtilities.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1BatchUtilities // +// // +// Author: Riccardo Maria Bianchi <rbianchi@cern.ch> // +// // +// Initial version: Jan 2019 // +// // +///////////////////////////////////////////////////////////// + + +#ifndef VP1UTILSBASE_VP1BatchUtilities +#define VP1UTILSBASE_VP1BatchUtilities + +//NB: There should never be any Qt (or Athena of course) includes in this file!!! +#include <string> +#include <vector> + + +class VP1BatchUtilities +{ +public: + VP1BatchUtilities(std::vector<std::string> files); + ~VP1BatchUtilities() {}; + + std::string getRandomConfigFile(); + + static void overlayATLASlogo(); + static void overlayEventDetails(unsigned long runNumber, unsigned long eventNumber, std::string humanTimestamp); + +private: + std::vector<std::string> m_files; + int m_indexFile; + int m_lastIndexFile; +}; + +#endif diff --git a/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1FileUtilities.h b/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1FileUtilities.h index 2f76de8d3229de73dedcad1270193a94126ead8b..d13e560466923592da97b6f3937bffd887419ed9 100644 --- a/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1FileUtilities.h +++ b/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1FileUtilities.h @@ -19,7 +19,6 @@ #define VP1FILEUTILITIES_H //NB: There should never be any Qt (or Athena of course) includes in this file!!! - #include <string> class VP1FileUtilities @@ -54,10 +53,7 @@ public: int timeStamp, std::string textLabel = ""); - // - // **** Check if file exists **** - static bool fileExistsAndReadable(const std::string&); private: diff --git a/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1TimeUtilities.h b/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1TimeUtilities.h new file mode 100644 index 0000000000000000000000000000000000000000..791eaa476821a91d5a4279574bd8c0af7eb44aef --- /dev/null +++ b/graphics/VP1/VP1UtilsBase/VP1UtilsBase/VP1TimeUtilities.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Header file for class VP1BatchUtilities // +// // +// Author: Riccardo Maria Bianchi <rbianchi@cern.ch> // +// // +// Initial version: Jan 2019 // +// // +///////////////////////////////////////////////////////////// + + +#ifndef VP1UTILSBASE_VP1TimeUtilities +#define VP1UTILSBASE_VP1TimeUtilities + + +//NB: There should never be any Qt (or Athena of course) includes in this file!!! +#include <ctime> /* time_t, time, ctime */ +#include <string> + + +class VP1TimeUtilities +{ +public: + static std::string getHumanReadableTimestamp(time_t t_timestamp); + +private: + VP1TimeUtilities(); + ~VP1TimeUtilities(); +}; + +#endif diff --git a/graphics/VP1/VP1Gui/share/ATLAS-Logo-New_300pixels.png b/graphics/VP1/VP1UtilsBase/share/ATLAS-Logo-New_300pixels.png similarity index 100% rename from graphics/VP1/VP1Gui/share/ATLAS-Logo-New_300pixels.png rename to graphics/VP1/VP1UtilsBase/share/ATLAS-Logo-New_300pixels.png diff --git a/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wGeo_frontView.vp1 b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wGeo_frontView.vp1 new file mode 100644 index 0000000000000000000000000000000000000000..301d9b99702cae33fd65f4305f44757a5999ae2c Binary files /dev/null and b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wGeo_frontView.vp1 differ diff --git a/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wIDGeo.vp1 b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wIDGeo.vp1 new file mode 100644 index 0000000000000000000000000000000000000000..f3fc6cbf3430410282fe718d5fc48c6ec936e56f Binary files /dev/null and b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wIDGeo.vp1 differ diff --git a/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wPixel_3D.vp1 b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wPixel_3D.vp1 new file mode 100644 index 0000000000000000000000000000000000000000..68e29b6a8bebec446c3eb476d0c1ebbcaf7e7be3 Binary files /dev/null and b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wPixel_3D.vp1 differ diff --git a/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wPixel_wSCT_wGeo_3D.vp1 b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wPixel_wSCT_wGeo_3D.vp1 new file mode 100644 index 0000000000000000000000000000000000000000..927fdee1a45cadbd49ab6b19fd82b22d18f9e165 Binary files /dev/null and b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wPixel_wSCT_wGeo_3D.vp1 differ diff --git a/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wPixel_wSCT_wOpenCalo_wGeo_3D.vp1 b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wPixel_wSCT_wOpenCalo_wGeo_3D.vp1 new file mode 100644 index 0000000000000000000000000000000000000000..5a970a8f379cf4ceb0d3bbf070bf212d90fdf03a Binary files /dev/null and b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wPixel_wSCT_wOpenCalo_wGeo_3D.vp1 differ diff --git a/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo.vp1 b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo.vp1 new file mode 100644 index 0000000000000000000000000000000000000000..d12f0539f9b898238d8de9eb992b30509ec06980 Binary files /dev/null and b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo.vp1 differ diff --git a/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo_IAview.vp1 b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo_IAview.vp1 new file mode 100644 index 0000000000000000000000000000000000000000..a89af52bc0665a8987eb0baa1986b7ef8c89656e Binary files /dev/null and b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo_IAview.vp1 differ diff --git a/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo_wBarrel.vp1 b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo_wBarrel.vp1 new file mode 100644 index 0000000000000000000000000000000000000000..7bd6280374e2f8a6b708d230639694c0040f6d86 Binary files /dev/null and b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo_wBarrel.vp1 differ diff --git a/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo_wMDT.vp1 b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo_wMDT.vp1 new file mode 100644 index 0000000000000000000000000000000000000000..dcf4dbd655643a1cbd13c0ab7504ead1b219c455 Binary files /dev/null and b/graphics/VP1/VP1UtilsBase/share/vp1_conf_ATLASatHOME_truth_event_wTRTGeo_wMDT.vp1 differ diff --git a/graphics/VP1/VP1UtilsBase/src/VP1BatchUtilities.cxx b/graphics/VP1/VP1UtilsBase/src/VP1BatchUtilities.cxx new file mode 100644 index 0000000000000000000000000000000000000000..84fcf8bfec0c043d568aaab7ee09d329d5c6bdb2 --- /dev/null +++ b/graphics/VP1/VP1UtilsBase/src/VP1BatchUtilities.cxx @@ -0,0 +1,153 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1BatchUtilities // +// // +// Author: Riccardo Maria Bianchi <rbianchi@cern.ch> // +// // +// Initial version: Jan 2019 // +// // +///////////////////////////////////////////////////////////// + + +#include "VP1UtilsBase/VP1BatchUtilities.h" + +#include <string> +#include <vector> +#include <iostream> +#include <random> // C++11 +#include <iomanip> +#include <functional> + + + +VP1BatchUtilities::VP1BatchUtilities(std::vector<std::string> files) : m_indexFile(0), m_lastIndexFile(0) +{ + m_files = files; + std::cout << "Got vector of " << files.size() << " items" << std::endl; + // Iterate and print values of vector + for(std::string n : m_files) { + std::cout << n << '\n'; + } +} + + +std::string VP1BatchUtilities::getRandomConfigFile() +{ + std::cout <<"VP1BatchUtilities::getRandomConfigFile()" << std::endl; + + std::string configFile; + + + int nConfigFiles = m_files.size(); + std::cout << " ===> # config files: " << nConfigFiles << std::endl; + + // setup random generator in [0, nConfigFiles] + int nPositions = nConfigFiles - 1; + auto seed = std::random_device{}(); + auto randomDist = std::bind(std::uniform_int_distribution<int>(0, nPositions ), + std::mt19937(seed)); + + // get a random index, + m_indexFile = randomDist(); + // avoiding having the same index in a row + while ( m_indexFile == m_lastIndexFile ) { + m_indexFile = randomDist(); + } + m_lastIndexFile = m_indexFile; + std::cout << " ===> random index: " << m_indexFile << std::endl; + + configFile = m_files[m_indexFile]; + std::cout << " ===> random file: " << configFile << std::endl; + + return configFile; + +} + +// Overlay the ATLAS logo to the image +void VP1BatchUtilities::overlayATLASlogo() +{ + /* + * different example commands for logo overlay: + * + * std::string commandStr = "convert -composite `cat latest_vp1image` $TestArea/InstallArea/share/ATLAS-Logo-New_300pixels.png -geometry 150x150+0+0 -depth 8 test.png"; // this set the logo size to 150px and it draws it at (0,0)px + * std::string commandStr = "convert -composite `cat latest_vp1image` $TestArea/InstallArea/share/ATLAS-Logo-New_300pixels.png -geometry +10+10 -depth 8 test.png"; // this uses the original logo size and it draws it at (10,10)px + */ + + std::string commandStr = "convert -composite `cat latest_vp1image` $TestArea/InstallArea/share/ATLAS-Logo-New_300pixels.png -geometry +10+10 -depth 8 `cat latest_vp1image`"; + + std::cout << " ===> overlay the ATLAS logo: " << commandStr << std::endl; + try { + system(commandStr.c_str()); + } catch (std::runtime_error& err) { + std::cout << "Exception caught: " << err.what() << std::endl; + std::cout << "Unable to run 'convert'!" << std::endl; + } +} + +// Overlay the event details to the image +// it replaces the original image with a version having event details on it +void VP1BatchUtilities::overlayEventDetails(unsigned long runNumber, unsigned long eventNumber, std::string humanTimestamp) +{ + + std::string nRun = std::to_string(runNumber); + std::string nEvent = std::to_string(eventNumber); + + /* + * example of different bash command for event details overlay: + * + * nRun=0; nEvent=4; img=`cat latest_vp1image`; width=$(identify -format %W ${img}); width=$(( ${width} * 3 / 10 )); convert -background '#0008' -gravity west -fill white -size ${width}x80 -font Courier -density 72 -pointsize 18 -interline-spacing 4 caption:'Run number: '${nRun}'\nEvent number: '${nEvent}'\n2015-02-02, 15:10:00' ${img} +swap -gravity SouthEast -composite ${img}-30 + * nRun=0; nEvent=4; timestamp='ciao'; img=`cat latest_vp1image`; width=$(identify -format %W ${img}); width=$(( ${width} * 3 / 10 )); convert -background '#0008' -gravity west -fill white -size ${width}x80 -font Courier -density 72 -pointsize 18 -interline-spacing 4 caption:'Run number: '${nRun}'\nEvent number: '${nEvent}'\n'${timestamp} ${img} +swap -gravity SouthEast -composite ${img}-31 + * nRun=0; nEvent=4; timestamp='2015-02-02T10:10:00'; img=`cat latest_vp1image`; width=$(identify -format %W ${img}); width=$(( ${width} * 3 / 10 )); convert -background '#0008' -gravity west -fill white -size ${width}x80 -font Courier -density 72 -pointsize 18 -interline-spacing 4 caption:'Run number: '${nRun}'\nEvent number: '${nEvent}'\n'${timestamp} ${img} +swap -gravity SouthEast -composite ${img}-36 + */ + + std::string commandStr; + + // setting bash variables + commandStr += "nRun="+nRun+"; "; + commandStr += "nEvent="+nEvent+"; "; + if (humanTimestamp != "0") commandStr += "timestamp='"+humanTimestamp+"'; "; // 'timestamp' must not have white spaces + + // get input image + commandStr += "img=`cat latest_vp1image`; "; // get the filename of the latest image produced + commandStr += "width=$(identify -format %W ${img}); "; // get the width of the image + commandStr += "width=$(( ${width} * 3 / 10 )); "; // set the caption width as a fraction of the image width + + // ImageMagik 'convert' command settings. (ImageMagik is installed by default on SLC LXPLUS machines) + commandStr = commandStr + + "convert " + + "-background '#0008' " // semi-transparent grey bkg + + "-geometry +20+20 " // set an offset to the label position + + "-gravity West " // set text position inside the caption space (justification) + + "-fill white " // text font color + + "-size ${width}x80 " // set text size relative to 'width' + + + "-font Courier " // text font + + "-density 72 " // dots-per-inch resolution + + "-pointsize 18 " // text size in points + //+ "-interline-spacing 4 " // additional number of pixels between lines of text (only with ImageMagik >= 6.5.5-8!!! Lxplus has 6.7 but not all SLC6 machines...) + + //+ "caption:'Run number: ${nRun}' " // set the caption text + //+ (m_timeStamp > 0 ? "caption:'Run number: '${nRun}'\\nEvent number: '${nEvent}'\\n'${timestamp} " : "caption:'Run number: '${nRun}'\\nEvent number: '${nEvent}'\\n'${timestamp} ") // set the caption text; '\n' needs to be double-escaped while passed to system() + + "caption:'Run number: '${nRun}'\\nEvent number: '${nEvent}'\\n'${timestamp} " // set the caption text; '\n' needs to be double-escaped while passed to system() + + + "${img} " // imput image + + "+swap " + + "-gravity SouthEast " // set overall caption position + + "-composite " + + "${img}"; // output image: here we replace the original image + + + std::cout << " ===> overlay the event details: " << commandStr << std::endl; + try { + system(commandStr.c_str()); + } catch (std::runtime_error& err) { + std::cout << "Exception caught: " << err.what() << std::endl; + std::cout << "Unable to run 'convert'!" << std::endl; + } +} + + diff --git a/graphics/VP1/VP1UtilsBase/src/VP1TimeUtilities.cxx b/graphics/VP1/VP1UtilsBase/src/VP1TimeUtilities.cxx new file mode 100644 index 0000000000000000000000000000000000000000..14b7697aa7e7775e18f0c5c4cec6e858b7189a17 --- /dev/null +++ b/graphics/VP1/VP1UtilsBase/src/VP1TimeUtilities.cxx @@ -0,0 +1,40 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////// +// // +// Implementation of class VP1TimeUtilities // +// // +// Author: Riccardo Maria Bianchi <rbianchi@cern.ch> // +// // +// Initial version: Jan 2019 // +// // +///////////////////////////////////////////////////////////// + + +#include "VP1UtilsBase/VP1TimeUtilities.h" + +#include <iostream> +#include <iomanip> +#include <string> +#include <iostream> + + +std::string VP1TimeUtilities::getHumanReadableTimestamp(time_t t_timestamp) +{ + tm *ltm = localtime(&t_timestamp); + + std::string humanTimestamp; + + std::ostringstream ostri; + ostri << 1900 + ltm->tm_year + << "-" << 1 + ltm->tm_mon // tm_mon is in the range [0, 11], so 1 must be added to get real months + << "-" << ltm->tm_mday + << "T" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec; // << "CEST"; FIXME: check if time zone is available on data file + + humanTimestamp = ostri.str(); + //std::cout << "'human readable' timestamp: " << m_humanTimestamp << std::endl; + return humanTimestamp; +} +