diff --git a/LumiBlock/LumiBlockComps/CMakeLists.txt b/LumiBlock/LumiBlockComps/CMakeLists.txt index 6578270449e8abff67760cff090aceff6d01cec6..5ebe896b39802a63dd0b4157156378fde423c779 100644 --- a/LumiBlock/LumiBlockComps/CMakeLists.txt +++ b/LumiBlock/LumiBlockComps/CMakeLists.txt @@ -10,6 +10,7 @@ atlas_depends_on_subdirs( PUBLIC Control/AthenaBaseComps Control/AthenaKernel Control/StoreGate + Control/xAODRootAccess Database/AthenaPOOL/AthenaPoolKernel Database/CoolLumiUtilities Event/xAOD/xAODLuminosity @@ -48,6 +49,11 @@ atlas_add_dictionary( LumiBlockCompsDict INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} LINK_LIBRARIES ${COOL_LIBRARIES} ${ROOT_LIBRARIES} ${CORAL_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests CoolLumiUtilitiesLib xAODLuminosity GaudiKernel LumiBlockCoolQuery GoodRunsListsLib AthenaPoolUtilities DBDataModel EventInfo LumiBlockCompsLib ) +atlas_add_executable( getLumi + util/getLumi.cxx + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} + LINK_LIBRARIES ${COOL_LIBRARIES} ${ROOT_LIBRARIES} ${CORAL_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests CoolLumiUtilitiesLib xAODLuminosity GaudiKernel LumiBlockCoolQuery GoodRunsListsLib AthenaPoolUtilities DBDataModel EventInfo LumiBlockCompsLib ) + # Install files from the package: atlas_install_python_modules( python/*.py ) atlas_install_joboptions( share/*.py ) diff --git a/LumiBlock/LumiBlockComps/LumiBlockComps/LuminosityTool.h b/LumiBlock/LumiBlockComps/LumiBlockComps/LuminosityTool.h index a13b7753ac57b09511d17e84539a35159886cc34..9cd2921932cd343d680cafa52dc256c150e7a6f8 100644 --- a/LumiBlock/LumiBlockComps/LumiBlockComps/LuminosityTool.h +++ b/LumiBlock/LumiBlockComps/LumiBlockComps/LuminosityTool.h @@ -138,9 +138,17 @@ class LuminosityTool: public AthAlgTool, virtual public ILuminosityTool { // Channel to use to get muToLumi from calibration tool unsigned int m_calibChannel; + + // Backup channel in case calibChannel doesn't exist in online calibration folder + unsigned int m_calibBackupChannel; + + // Flag to control whether invalid data is skipped (True - default) returning a zero luminosity, + // or whether the available luminosity values are returned anyways (False). + bool m_skipInvalid; + }; #endif -#endif \ No newline at end of file +#endif diff --git a/LumiBlock/LumiBlockComps/Root/LumiBlockMetaDataTool.cxx b/LumiBlock/LumiBlockComps/Root/LumiBlockMetaDataTool.cxx index 16bf606005e5f17966f5d6882a44f08b4846bb92..4958b2a3e36d84365394df8e200e818b131736e0 100755 --- a/LumiBlock/LumiBlockComps/Root/LumiBlockMetaDataTool.cxx +++ b/LumiBlock/LumiBlockComps/Root/LumiBlockMetaDataTool.cxx @@ -5,7 +5,7 @@ /** Modified from @file ReadMeta.cxx * @brief The LumiBlockMetaDataTool reads luminosity metadata from input files and transfers it to output files * @author Marjorie Shapiro <mdshapiro@lbl.gov> based on work from Peter van Gemmeren <gemmeren@anl.gov> - * $Id: LumiBlockMetaDataTool.cxx 716108 2015-12-29 03:49:11Z ssnyder $ + * $Id: LumiBlockMetaDataTool.cxx 725529 2016-02-22 16:07:11Z will $ **/ #include "LumiBlockComps/LumiBlockMetaDataTool.h" @@ -244,7 +244,7 @@ StatusCode LumiBlockMetaDataTool::finishUp() { // // stop() is called whenever the event loop is finished. // ====================================================== - ATH_MSG_INFO( " finishUp: write lumiblocks to meta data store " ); + ATH_MSG_VERBOSE( " finishUp: write lumiblocks to meta data store " ); xAOD::LumiBlockRangeContainer* piovComplete = new xAOD::LumiBlockRangeContainer(); xAOD::LumiBlockRangeAuxContainer* piovCompleteAux = new xAOD::LumiBlockRangeAuxContainer(); @@ -261,7 +261,7 @@ StatusCode LumiBlockMetaDataTool::finishUp() { xAOD::LumiBlockRangeContainer::const_iterator it; if(m_cacheSuspectOutputRangeContainer->size()>0) { - msg(MSG::INFO) << "Suspect OutputRangeCollection with size " << m_cacheSuspectOutputRangeContainer->size() << endreq; + ATH_MSG_VERBOSE("Suspect OutputRangeCollection with size " << m_cacheSuspectOutputRangeContainer->size()); for(it=m_cacheSuspectOutputRangeContainer->begin(); it!=m_cacheSuspectOutputRangeContainer->end(); it++) { xAOD::LumiBlockRange* iovr = new xAOD::LumiBlockRange(*(*it)); piovSuspect->push_back(iovr); @@ -269,7 +269,7 @@ StatusCode LumiBlockMetaDataTool::finishUp() { } if(m_cacheOutputRangeContainer->size()>0) { - msg(MSG::INFO) << "OutputRangeCollection with size " << m_cacheOutputRangeContainer->size() << endreq; + ATH_MSG_VERBOSE("OutputRangeCollection with size " << m_cacheOutputRangeContainer->size()); m_cacheOutputRangeContainer->sort(xAOD::SortLumiBlockRangeByStart()); // Use tmp collection to do the merging @@ -284,7 +284,7 @@ StatusCode LumiBlockMetaDataTool::finishUp() { xAOD::LumiBlockRangeContainer::const_iterator ilast = m_cacheOutputRangeContainer->begin(); xAOD::LumiBlockRange* iovr = new xAOD::LumiBlockRange(*(*i)); p_tempLBColl->push_back(iovr); - ATH_MSG_INFO( "Push_back tmpLBColl with run " + ATH_MSG_VERBOSE( "Push_back tmpLBColl with run " << (*i)->startRunNumber() << " LB " << (*i)->startLumiBlockNumber() << " events seen " << (*ilast)->eventsSeen() << " expected " << (*i)->eventsExpected()); i++; @@ -299,7 +299,7 @@ StatusCode LumiBlockMetaDataTool::finishUp() { << (*ilast)->eventsExpected() << " and " << (*i)->eventsExpected() ); } else { - ATH_MSG_INFO( "Merge Run " << (*i)->startRunNumber() << " LB " << (*i)->startLumiBlockNumber() + ATH_MSG_VERBOSE( "Merge Run " << (*i)->startRunNumber() << " LB " << (*i)->startLumiBlockNumber() << " events seen " << iovr->eventsSeen() << "+" << (*i)->eventsSeen() << " and events expected " << iovr->eventsExpected() ); @@ -310,7 +310,7 @@ StatusCode LumiBlockMetaDataTool::finishUp() { else { iovr = new xAOD::LumiBlockRange(*(*i)); - ATH_MSG_INFO( "Push_back tmpLBColl with run " + ATH_MSG_VERBOSE( "Push_back tmpLBColl with run " << iovr->startRunNumber() << " LB " << iovr->startLumiBlockNumber() << " events seen " << iovr->eventsSeen() << " expected " << iovr->eventsExpected()); @@ -333,7 +333,7 @@ StatusCode LumiBlockMetaDataTool::finishUp() { if(piovComplete->size()>0) { - ATH_MSG_INFO( "Number of Complete LumiBlocks:" << piovComplete->size() ); + ATH_MSG_DEBUG( "Number of Complete LumiBlocks:" << piovComplete->size() ); xAOD::LumiBlockRangeContainer::const_iterator it; for(it=piovComplete->begin(); it!=piovComplete->end(); it++) { msg(MSG::INFO) << "\t [ (" @@ -348,7 +348,7 @@ StatusCode LumiBlockMetaDataTool::finishUp() { } if(piovUnfinished->size()>0) { - ATH_MSG_INFO( "Number of Unfinished LumiBlocks:" << piovUnfinished->size() ); + ATH_MSG_DEBUG( "Number of Unfinished LumiBlocks:" << piovUnfinished->size() ); xAOD::LumiBlockRangeContainer::const_iterator it; for(it=piovUnfinished->begin(); it!=piovUnfinished->end(); it++) { msg(MSG::INFO) << "\t [ (" @@ -362,7 +362,7 @@ StatusCode LumiBlockMetaDataTool::finishUp() { } } if(piovSuspect->size()>0) { - ATH_MSG_INFO( "Number of Suspect LumiBlocks:" << piovSuspect->size() ); + ATH_MSG_DEBUG( "Number of Suspect LumiBlocks:" << piovSuspect->size() ); xAOD::LumiBlockRangeContainer::const_iterator it; for(it=piovSuspect->begin(); it!=piovSuspect->end(); it++) { msg(MSG::INFO) << "\t [ (" diff --git a/LumiBlock/LumiBlockComps/cmt/requirements b/LumiBlock/LumiBlockComps/cmt/requirements index 265b144e924ad6d8098dbcdb6833d4d5034e34cc..1aac930427150885e11f9a19474d78b04391ffde 100644 --- a/LumiBlock/LumiBlockComps/cmt/requirements +++ b/LumiBlock/LumiBlockComps/cmt/requirements @@ -31,6 +31,7 @@ use CoraCool CoraCool-* Database -no_auto_imports use DBDataModel DBDataModel-* Database/AthenaPOOL use EventInfo EventInfo-* Event use GoodRunsLists GoodRunsLists-* DataQuality +end_private # Create a dual_use library since the lcgdict pattern doesn't work with component libraries using cmake. # This pollutes the linkopts for clients, but is otherwise harmless. @@ -44,6 +45,11 @@ apply_pattern declare_joboptions files="*.py" # Create dictionary for LumiBlockComps private use AtlasReflex AtlasReflex-* External - apply_pattern lcgdict dict=LumiBlockComps selectionfile=selection.xml headerfiles="../LumiBlockComps/LumiBlockCompsDict.h" +end_private + +use_if tag=AthAnalysisBase pkg=xAODRootAccess ver=xAODRootAccess-* root=Control +application getLumi ../util/getLumi.cxx +macro_append getLumi_dependencies " GoodRunsLists LumiBlockCompsLib " + diff --git a/LumiBlock/LumiBlockComps/python/LuminosityToolDefault.py b/LumiBlock/LumiBlockComps/python/LuminosityToolDefault.py index d036e3160618e64bd1e00cd3bd729635f880741c..e7576467a52b77b54722db069917584c9273a30c 100644 --- a/LumiBlock/LumiBlockComps/python/LuminosityToolDefault.py +++ b/LumiBlock/LumiBlockComps/python/LuminosityToolDefault.py @@ -159,6 +159,9 @@ class LuminosityToolOnline(LuminosityTool): super (LuminosityToolOnline, self).__init__(name) mlog = logging.getLogger(name) + + # Keep values for invalid data + self.SkipInvalid = False from IOVDbSvc.CondDB import conddb if conddb.dbdata == "COMP200": # Run1 diff --git a/LumiBlock/LumiBlockComps/src/LuminosityTool.cxx b/LumiBlock/LumiBlockComps/src/LuminosityTool.cxx index b22c5ddfdb6d2df1302c58a7d835cb7bfd9b27b5..bb779609599ac232400d2796c0e030db8b133217 100644 --- a/LumiBlock/LumiBlockComps/src/LuminosityTool.cxx +++ b/LumiBlock/LumiBlockComps/src/LuminosityTool.cxx @@ -38,7 +38,9 @@ LuminosityTool::LuminosityTool(const std::string& type, m_preferredChannel(0), m_luminousBunches(0), m_bunchInstLumiBlob(NULL), - m_calibChannel(0) + m_calibChannel(0), + m_calibBackupChannel(112), + m_skipInvalid(true) { declareInterface<ILuminosityTool>(this); declareProperty("LumiFolderName", m_lumiFolderName); @@ -48,6 +50,8 @@ LuminosityTool::LuminosityTool(const std::string& type, declareProperty("BunchGroupTool", m_bunchGroupTool); declareProperty("OnlineLumiCalibrationTool", m_onlineLumiCalibrationTool); declareProperty("LBLBFolderName", m_lblbFolderName); + declareProperty("CalibBackupChannel", m_calibBackupChannel); + declareProperty("SkipInvalid", m_skipInvalid); m_LBAvInstLumi = 0.; m_LBAvEvtsPerBX = 0.; @@ -291,15 +295,19 @@ LuminosityTool::updateAvgLumi( IOVSVC_CALLBACK_ARGS_P(/*idx*/, /*keys*/) ) } if (attrList["Valid"].isNull()) { - ATH_MSG_WARNING( " NULL validity information ... set lumi to 0" ); - return StatusCode::SUCCESS; + ATH_MSG_WARNING( " NULL validity information ... set lumi to 0" ); + return StatusCode::SUCCESS; } // Check validity (don't bother continuing if invalid) m_Valid = attrList["Valid"].data<cool::UInt32>(); if (m_Valid & 0x01) { - ATH_MSG_WARNING( " Invalid LB Average luminosity ... set lumi to 0" ); - return StatusCode::SUCCESS; + if (m_skipInvalid) { + ATH_MSG_WARNING( " Invalid LB Average luminosity ... set lumi to 0" ); + return StatusCode::SUCCESS; + } else { + ATH_MSG_WARNING( " Invalid LB Average luminosity ... continuing because skipInvalid == FALSE" ); + } } // Get preferred channel (needed for per-BCID calculation) @@ -350,7 +358,7 @@ LuminosityTool::updateAvgLumi( IOVSVC_CALLBACK_ARGS_P(/*idx*/, /*keys*/) ) // Check validity of per-BCID luminosity (will issue warning in recalcPerBCIDLumi int perBcidValid = (m_Valid/10) % 10; - if (perBcidValid > 0) { + if ((perBcidValid > 0) && m_skipInvalid) { return StatusCode::SUCCESS; } @@ -427,6 +435,20 @@ LuminosityTool::recalculatePerBCIDLumi() // This is the only correct way to do this! // The division below gives average mu (over all bunches) to total lumi m_MuToLumi = m_onlineLumiCalibrationTool->getMuToLumi(m_calibChannel); + + // Check if this is reasonable + if (m_MuToLumi < 0.) { + ATH_MSG_INFO(" Found muToLumi = " << m_MuToLumi << " for channel " << m_calibChannel << ". Try backup channel..." ); + m_MuToLumi = m_onlineLumiCalibrationTool->getMuToLumi(m_calibBackupChannel); + ATH_MSG_INFO(" Found muToLumi = " << m_MuToLumi << " for channel " << m_calibBackupChannel); + + if (m_MuToLumi < 0.) { + ATH_MSG_WARNING(" Found invalid muToLumi = " << m_MuToLumi << " for backup channel " << m_calibBackupChannel << "!"); + m_MuToLumi = 0.; + } + + } + //} else if (m_LBAvEvtsPerBX > 0.) { //m_MuToLumi = m_LBAvInstLumi / m_LBAvEvtsPerBX; } else { @@ -609,4 +631,4 @@ LuminosityTool::recalculatePerBCIDLumi() return; } -#endif \ No newline at end of file +#endif diff --git a/LumiBlock/LumiBlockComps/util/getLumi.cxx b/LumiBlock/LumiBlockComps/util/getLumi.cxx new file mode 100644 index 0000000000000000000000000000000000000000..65669a894062cc8aa8ef51c2514ececea942a682 --- /dev/null +++ b/LumiBlock/LumiBlockComps/util/getLumi.cxx @@ -0,0 +1,474 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///getLumi - the lumi helper application +///author: Will Buttinger (will@cern.ch) +///Small program to quickly get luminosity out of files with LumiMetaData folder +///Uses a root file generated using lumicalc service (atlas-lumicalc.cern.ch) +///usage: +/// getLumi.exe lumicalc.root /path/to/some/files*.root +/// option: -m shows which runs from the lumicalc file are not covered by the files you gave it +/// useful option for checking you have run over all data that your GRL covers +/// Note: This code is based on some old code I wrote a while ago, so it is by no means pretty! + + +#include <iostream> + +#ifndef XAOD_ANALYSIS +int main(int argc, char* argv[]) { + std::cout << " This application is currently only available in the analysis releases \n \ + Please setup an AthAnalysisBase release to use this application." << std::endl; + return 0; +} + +#else + + +#include "TROOT.h" +#include "TFile.h" +#include "TTree.h" +#include "TBranch.h" +#include "TApplication.h" +#include "TKey.h" +#include "TDirectory.h" +#include "TSystem.h" + +#include <getopt.h> +#include <cstdlib> +#include <vector> + +#include "GoodRunsLists/TGoodRunsListReader.h" + +#include "xAODRootAccess/Init.h" +#include "xAODRootAccess/TEvent.h" +#include "xAODLuminosity/LumiBlockRangeContainer.h" +#include "xAODLuminosity/LumiBlockRangeAuxContainer.h" + +struct lbx { + lbx() : nExpected(0),nSeen(0) {} + long nExpected; + long nSeen; +}; + +int main(int argc, char* argv[]) { + const char* optstring = "m"; + bool showMissing = false; +static struct option long_options[] = + { + /* name has_arg flag val */ + {"showMissing", no_argument , NULL, 'm'} + }; + + int longindex; + int option; + //int begin = 0; + //int end = 999; + int nOptions = 0; + while ((option = getopt_long(argc, argv, + optstring, long_options, &longindex)) != -1) { + switch (option) { + case 'm' : + showMissing = true;nOptions++; + break; + case '?' : + printf("Please supply a valid option to the program. Exiting\n"); + exit(1); + break; + } + } + + + + //first arg is the lumicalc file + if(argc<3+nOptions) { + std::cout << "Usage: <lumicalcfile.root> <list of xAOD or D3PD>" << std::endl; + std::cout << "Option: -m lists run numbers with any missing lumi" << std::endl; + std::cout << "" << std::endl; + std::cout << "Further Documentation: see https://twiki.cern.ch/twiki/bin/view/AtlasProtected/AthAnalysisBase#How_to_check_the_luminosity_cove " <<std::endl; + return 0; + } + gSystem->Load("libTree.so"); + + bool readXML=false; + Root::TGoodRunsList fromXAOD;Root::TGoodRunsList fromXAODIncomplete;Root::TGoodRunsList fromXAODSuspect; + std::map<uint, std::map<uint, lbx> > lbxs; + Root::TGoodRunsListReader grlReader; + + bool hasMask(false); + Root::TGoodRunsListReader grlMaskReader; + //hunt for xml files... we will use these as 'masks' for the included lumi + for(int i=2+nOptions;i<argc;i++) { + std::string s(argv[i]); + if(s.find(".xml")==std::string::npos) continue; + grlMaskReader.AddXMLFile( s ); + hasMask=true; + } + Root::TGoodRunsList grlMask; + if(hasMask) { + grlMaskReader.Interpret();grlMask.AddGRL(grlMaskReader.GetMergedGoodRunsList()); + } + + + //open all the d3pd-like files, and hunt for their lumi strings + for(int i=2+nOptions;i<argc;i++) { + //require to have ".root" in it + std::string s(argv[i]); + if(s.find(".root")==std::string::npos) continue; + TFile *file = TFile::Open(argv[i]); + if(file==0) continue; + std::cout << s; + //try to get lumi + + //if this is xAOD, it will have a MetaData tree ... + if(file->Get("MetaData")!=0) { + TTree* metaTree = static_cast<TTree*>(file->Get("MetaData")); + //use TEvent if the MetaData tree contains an EventFormat branch and only 1 entry + bool useTEvent(false); + if(metaTree->GetEntries()==1 && metaTree->FindBranch("EventFormat")) { + useTEvent = true; + } else { + metaTree->SetMakeClass(1); + } + std::vector<unsigned int> startRunNumber; + std::vector<unsigned int> stopRunNumber; + std::vector<unsigned int> startLumiBlockNumber; + std::vector<unsigned int> stopLumiBlockNumber; + std::vector<unsigned int> eventsExpected; + std::vector<unsigned int> eventsSeen; + + //use TEvent to read the lumiblocks, if we can + bool ok(false); + xAOD::TEvent event; + const xAOD::LumiBlockRangeContainer* lbrs = 0; + xAOD::LumiBlockRangeAuxContainer* lbrs_aux = 0; + if(useTEvent && event.readFrom(file,true,"MetaData").isSuccess()) { + if(event.containsMeta<xAOD::LumiBlockRangeContainer>("LumiBlocks")) { + event.retrieveMetaInput<xAOD::LumiBlockRangeContainer>(lbrs, "LumiBlocks").isSuccess(); + } + } else { + useTEvent=false; + if(metaTree->FindBranch("LumiBlocksAux.")) { + if(metaTree->FindBranch("LumiBlocksAux.")->GetSplitLevel()==0) { + std::cout << " Unable to read unsplit LumiBlocksAux" << std::endl; + } + lbrs = new xAOD::LumiBlockRangeContainer(); + lbrs_aux = new xAOD::LumiBlockRangeAuxContainer; + const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->setStore( lbrs_aux ); + metaTree->SetBranchAddress("LumiBlocksAux.startRunNumber",&startRunNumber); + metaTree->SetBranchAddress("LumiBlocksAux.stopRunNumber",&stopRunNumber); + metaTree->SetBranchAddress("LumiBlocksAux.startLumiBlockNumber",&startLumiBlockNumber); + metaTree->SetBranchAddress("LumiBlocksAux.stopLumiBlockNumber",&stopLumiBlockNumber); + metaTree->SetBranchAddress("LumiBlocksAux.eventsExpected",&eventsExpected); + metaTree->SetBranchAddress("LumiBlocksAux.eventsSeen",&eventsSeen); + } + } + + if(lbrs) { + std::cout << "...xAOD LumiBlocks"; + for(int ii=0;ii<metaTree->GetEntries();ii++) { + if(!useTEvent) { + const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->clear(); + metaTree->GetEntry(ii); + for(unsigned int j=0;j<startRunNumber.size();j++) { + xAOD::LumiBlockRange* r = new xAOD::LumiBlockRange; const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->push_back(r); + r->setStartRunNumber(startRunNumber.at(j));r->setStopRunNumber(stopRunNumber.at(j)); + r->setStartLumiBlockNumber(startLumiBlockNumber.at(j));r->setStopLumiBlockNumber(stopLumiBlockNumber.at(j)); + r->setEventsExpected(eventsExpected.at(j));r->setEventsSeen(eventsSeen.at(j)); + } + } + + //add lb to grl + for(auto lbr : *lbrs) { + for(uint runNum = lbr->startRunNumber(); runNum <= lbr->stopRunNumber(); runNum++) { + if(lbr->startLumiBlockNumber()!=lbr->stopLumiBlockNumber()) {std::cout << " Unexpected behaviour. Please report! " << std::endl; exit(1);} + for(uint lb = lbr->startLumiBlockNumber(); lb <= lbr->stopLumiBlockNumber(); lb++) { + //std::cout << runNum << ":" << lb << " ss=" << lbr->eventsSeen() << " exp="<< lbr->eventsExpected() << std::endl; + //if(lbr->startLumiBlockNumber()==97) std::cout << " seen = " << lbr->eventsSeen() << " vs " << lbr->eventsExpected() << std::endl; + lbxs[runNum][lb].nSeen += lbr->eventsSeen(); +//if(lbxs[runNum][lb].nSeen > lbr->eventsExpected()) { std::cout << file->GetName() << " AA: " << lbr->eventsSeen() << " (total = " << lbxs[runNum][lb].nSeen << ") vs " << lbr->eventsExpected() << std::endl; } + if(lbxs[runNum][lb].nExpected!=0 && lbxs[runNum][lb].nExpected != lbr->eventsExpected()) {std::cout << "...mismatch on expected events in [run,lb]=[" << runNum << "," << lb << "] got " << lbr->eventsExpected() << " but had " << lbxs[runNum][lb].nExpected << std::endl; exit(1); } + else if(lbxs[runNum][lb].nExpected==0) lbxs[runNum][lb].nExpected=lbr->eventsExpected(); + //fromXAOD.AddRunLumiBlock(runNum,lb); + } + } + } + ok=true; + } + std::cout << "...ok" << std::endl; + if(!useTEvent) { delete lbrs; delete lbrs_aux; } + } + + lbrs = 0;lbrs_aux=0; + if(useTEvent && event.readFrom(file,true,"MetaData").isSuccess()) { + if(event.containsMeta<xAOD::LumiBlockRangeContainer>("IncompleteLumiBlocks")) { + event.retrieveMetaInput<xAOD::LumiBlockRangeContainer>(lbrs, "IncompleteLumiBlocks").isSuccess(); + } + } else { + useTEvent=false; + if(metaTree->FindBranch("IncompleteLumiBlocksAux.")) { + if(metaTree->FindBranch("IncompleteLumiBlocksAux.")->GetSplitLevel()==0) { + std::cout << " Unable to read unsplit IncompleteLumiBlocksAux" << std::endl; + } + lbrs = new xAOD::LumiBlockRangeContainer(); + lbrs_aux = new xAOD::LumiBlockRangeAuxContainer; + const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->setStore( lbrs_aux ); + metaTree->ResetBranchAddresses(); + metaTree->SetBranchAddress("IncompleteLumiBlocksAux.startRunNumber",&startRunNumber); + metaTree->SetBranchAddress("IncompleteLumiBlocksAux.stopRunNumber",&stopRunNumber); + metaTree->SetBranchAddress("IncompleteLumiBlocksAux.startLumiBlockNumber",&startLumiBlockNumber); + metaTree->SetBranchAddress("IncompleteLumiBlocksAux.stopLumiBlockNumber",&stopLumiBlockNumber); + metaTree->SetBranchAddress("IncompleteLumiBlocksAux.eventsExpected",&eventsExpected); + metaTree->SetBranchAddress("IncompleteLumiBlocksAux.eventsSeen",&eventsSeen); + } + } + + if(lbrs) { + std::cout << "...xAOD IncompleteLumiBlocks"; + for(int ii=0;ii<metaTree->GetEntries();ii++) { + if(!useTEvent) { + const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->clear(); + metaTree->GetEntry(ii); + for(unsigned int j=0;j<startRunNumber.size();j++) { + xAOD::LumiBlockRange* r = new xAOD::LumiBlockRange; const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->push_back(r); + r->setStartRunNumber(startRunNumber.at(j));r->setStopRunNumber(stopRunNumber.at(j)); + r->setStartLumiBlockNumber(startLumiBlockNumber.at(j));r->setStopLumiBlockNumber(stopLumiBlockNumber.at(j)); + r->setEventsExpected(eventsExpected.at(j));r->setEventsSeen(eventsSeen.at(j)); + } + } + + //add lb to grl + for(auto lbr : *lbrs) { + for(uint runNum = lbr->startRunNumber(); runNum <= lbr->stopRunNumber(); runNum++) { + if(lbr->startLumiBlockNumber()!=lbr->stopLumiBlockNumber()) {std::cout << " Unexpected behaviour. Please report! " << std::endl; exit(1);} + for(uint lb = lbr->startLumiBlockNumber(); lb <= lbr->stopLumiBlockNumber(); lb++) { + //std::cout << runNum << ":" << lb << " ss=" << lbr->eventsSeen() << " exp="<< lbr->eventsExpected() << std::endl; + //if(lbr->startLumiBlockNumber()==97) std::cout << " seen = " << lbr->eventsSeen() << " vs " << lbr->eventsExpected() << std::endl; + lbxs[runNum][lb].nSeen += lbr->eventsSeen(); +//if(lbxs[runNum][lb].nSeen > lbr->eventsExpected()) { std::cout << file->GetName() << " AA: " << lbr->eventsSeen() << " (total = " << lbxs[runNum][lb].nSeen << ") vs " << lbr->eventsExpected() << std::endl; } + if(lbxs[runNum][lb].nExpected!=0 && lbxs[runNum][lb].nExpected != lbr->eventsExpected()) {std::cout << "...mismatch on expected events in [run,lb]=[" << runNum << "," << lb << "] got " << lbr->eventsExpected() << " but had " << lbxs[runNum][lb].nExpected << std::endl; exit(1); } + else if(lbxs[runNum][lb].nExpected==0) lbxs[runNum][lb].nExpected=lbr->eventsExpected(); + //fromXAOD.AddRunLumiBlock(runNum,lb); + } + } + } + ok=true; + } + std::cout << "...ok" << std::endl; + if(!useTEvent) { delete lbrs; lbrs = 0; delete lbrs_aux; lbrs_aux=0; } + } + + + + lbrs = 0;lbrs_aux=0; + if(useTEvent && event.readFrom(file,true,"MetaData").isSuccess()) { + if(event.containsMeta<xAOD::LumiBlockRangeContainer>("SuspectLumiBlocks")) { + event.retrieveMetaInput<xAOD::LumiBlockRangeContainer>(lbrs, "SuspectLumiBlocks").isSuccess(); + } + } else { + useTEvent=false; + if(metaTree->FindBranch("SuspectLumiBlocksAux.")) { + if(metaTree->FindBranch("SuspectLumiBlocksAux.")->GetSplitLevel()==0) { + std::cout << " Unable to read unsplit SuspectLumiBlocks" << std::endl; + } + lbrs = new xAOD::LumiBlockRangeContainer(); + lbrs_aux = new xAOD::LumiBlockRangeAuxContainer; + const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->setStore( lbrs_aux ); + metaTree->ResetBranchAddresses(); + metaTree->SetBranchAddress("SuspectLumiBlocksAux.startRunNumber",&startRunNumber); + metaTree->SetBranchAddress("SuspectLumiBlocksAux.stopRunNumber",&stopRunNumber); + metaTree->SetBranchAddress("SuspectLumiBlocksAux.startLumiBlockNumber",&startLumiBlockNumber); + metaTree->SetBranchAddress("SuspectLumiBlocksAux.stopLumiBlockNumber",&stopLumiBlockNumber); + metaTree->SetBranchAddress("SuspectLumiBlocksAux.eventsExpected",&eventsExpected); + metaTree->SetBranchAddress("SuspectLumiBlocksAux.eventsSeen",&eventsSeen); + } + } + + if(lbrs) { + std::cout << "...xAOD SuspectLumiBlocksAux"; + for(int ii=0;ii<metaTree->GetEntries();ii++) { + if(!useTEvent) { + const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->clear(); + metaTree->GetEntry(ii); + for(unsigned int j=0;j<startRunNumber.size();j++) { + xAOD::LumiBlockRange* r = new xAOD::LumiBlockRange; const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->push_back(r); + r->setStartRunNumber(startRunNumber.at(j));r->setStopRunNumber(stopRunNumber.at(j)); + r->setStartLumiBlockNumber(startLumiBlockNumber.at(j));r->setStopLumiBlockNumber(stopLumiBlockNumber.at(j)); + r->setEventsExpected(eventsExpected.at(j));r->setEventsSeen(eventsSeen.at(j)); + } + } +std::cout << lbrs->size() << " is size"<<std::endl; + //add lb to grl + for(auto lbr : *lbrs) { + for(uint runNum = lbr->startRunNumber(); runNum <= lbr->stopRunNumber(); runNum++) { + if(lbr->startLumiBlockNumber()!=lbr->stopLumiBlockNumber()) {std::cout << " Unexpected behaviour. Please report! " << std::endl; exit(1);} + for(uint lb = lbr->startLumiBlockNumber(); lb <= lbr->stopLumiBlockNumber(); lb++) { + //std::cout << runNum << ":" << lb << " ss=" << lbr->eventsSeen() << " exp="<< lbr->eventsExpected() << std::endl; + //if(lbr->startLumiBlockNumber()==97) std::cout << " seen = " << lbr->eventsSeen() << " vs " << lbr->eventsExpected() << std::endl; + lbxs[runNum][lb].nSeen += lbr->eventsSeen(); +//if(lbxs[runNum][lb].nSeen > lbr->eventsExpected()) { std::cout << file->GetName() << " AA: " << lbr->eventsSeen() << " (total = " << lbxs[runNum][lb].nSeen << ") vs " << lbr->eventsExpected() << std::endl; } + if(lbxs[runNum][lb].nExpected!=0 && lbxs[runNum][lb].nExpected != lbr->eventsExpected()) {std::cout << "...mismatch on expected events in [run,lb]=[" << runNum << "," << lb << "] got " << lbr->eventsExpected() << " but had " << lbxs[runNum][lb].nExpected << std::endl; exit(1); } + else if(lbxs[runNum][lb].nExpected==0) lbxs[runNum][lb].nExpected=lbr->eventsExpected(); + //fromXAOD.AddRunLumiBlock(runNum,lb); + } + } + } + ok=true; + } + std::cout << "...ok" << std::endl; + if(!useTEvent) { delete lbrs; lbrs = 0; delete lbrs_aux; lbrs_aux=0; } + } + + if(ok) continue; //don't try to read Lumi folder + } + + + if(file->GetDirectory("Lumi")==0) { std::cout << "...no Lumi folder. Skipping" << std::endl; } + else { + file->cd("Lumi"); + //look for lumiTree first + TTree* lumiTree = dynamic_cast<TTree*>(gDirectory->Get("lumiTree")); + if(lumiTree) { + std::cout << "...lumiTree"; + //use the lumitree instead + TString *in = 0; + lumiTree->SetBranchAddress("lumi",&in); + for(int j=0;j<lumiTree->GetEntries();j++) { + lumiTree->GetEntry(j); + grlReader.AddXMLString(*in); readXML=true; + } + std::cout << "...ok" << std::endl; + } else { + TList* keys = gDirectory->GetListOfKeys(); + //loop over all that are objstrings + for( Int_t j = 0; j < keys->GetEntries(); ++j ) { + TKey *key = dynamic_cast<TKey*>( keys->At( j ) ); + TObjString* ostring = (TObjString*) key->ReadObjectAny( TObjString::Class() ); + if( ! ostring ) { std::cout << "...skipping object: " << key->GetName() << std::endl; continue;} + // Check that it has the right format: + if( ostring->GetString().BeginsWith( "<?xml version=" ) && ostring->GetString().Contains( "DOCTYPE LumiRangeCollection" ) ) { + grlReader.AddXMLString( ostring->GetString() ); readXML=true; + std::cout << "...ok" << std::endl; + } + } + } + } + file->Close(); + delete file; + } + + //loop over lbx and build up the complete/incomplete/suspect list: + for(auto& it : lbxs) { + uint runNum = it.first; + for(auto& it2 : it.second) { + uint lbn = it2.first; + if(it2.second.nSeen==it2.second.nExpected) { fromXAOD.AddRunLumiBlock(runNum,lbn); } + else if(it2.second.nSeen > it2.second.nExpected) { + // std::cout << " suspect = " << it2.second.nSeen << " vs " << it2.second.nExpected << std::endl; + fromXAODSuspect.AddRunLumiBlock(runNum,lbn); } + else { fromXAODIncomplete.AddRunLumiBlock(runNum,lbn); } + } + } + + Root::TGoodRunsList l;Root::TGoodRunsList lIncomplete;Root::TGoodRunsList lSuspect; + l.AddGRL(fromXAOD); lIncomplete.AddGRL(fromXAODIncomplete); lSuspect.AddGRL(fromXAODSuspect);//have to do this because of weird GRL behaviour + if(readXML) { + grlReader.Interpret(); + l.AddGRL(grlReader.GetMergedGoodRunsList()); + } + + TFile *lumicalcFile = TFile::Open(argv[1+nOptions]); + if(lumicalcFile==0) { + std::cout << "Could not open lumicalc file: " << argv[1+nOptions] << std::endl; + return 0; + } + + TTree *tmp = (TTree*)lumicalcFile->Get( "LumiMetaData" ); + if(!tmp) { + std::cout << "Could not find LumiMetaData tree in lumicalc file: " << argv[1+nOptions] << std::endl; + return 0; + } + + Root::TGoodRunsList providedL; //keeps track of what came from lumicalc file + + std::cout << "Reading LumiMetaData..."; + + //structure expected is as given by iLumiCalc: + // RunNbr, AvergeInteractionPerXing, IntLumi + UInt_t runNbr=0;Float_t intLumi=0;TBranch *b_runNbr;TBranch *b_intLumi; + UInt_t lb=0.; TBranch *b_lb; + if(tmp->SetBranchAddress("RunNbr",&runNbr,&b_runNbr)!=0) { + std::cout << "Could not find RunNbr branch in LumiMetaData TTree" << std::endl; return 0; + } + if(tmp->SetBranchAddress("LBStart",&lb,&b_lb)!=0) { + std::cout << "Could not find LBStart branch in Data TTree" << std::endl; return 0; + } + if(tmp->SetBranchAddress("IntLumi",&intLumi,&b_intLumi)!=0) { + std::cout << "Could not find IntLumi branch in Data TTree" << std::endl; return 0; + } + long nEntries = tmp->GetEntries(); + double totalLumi = 0; double totalLumiIncomplete = 0; double totalLumiSuspect=0; + int startMissingBlock = -1;UInt_t lastRunNumber=0;UInt_t lastLb=0;double missingLumi=0; double allMissing=0; + std::map<UInt_t, bool> missingRuns;std::map<UInt_t,bool> allRuns;std::set<UInt_t> incompleteRuns; + for(long i=0;i<nEntries;i++) { + b_runNbr->GetEntry(i);b_intLumi->GetEntry(i);b_lb->GetEntry(i); + if(hasMask && !grlMask.HasRunLumiBlock(runNbr,lb)) continue; + providedL.AddRunLumiBlock(runNbr,lb); + bool hasLumi = l.HasRunLumiBlock(runNbr,lb); + + if(hasLumi) totalLumi += intLumi; + else if(lIncomplete.HasRunLumiBlock(runNbr,lb)) {hasLumi=true; totalLumiIncomplete += intLumi; incompleteRuns.insert(runNbr);} //else if ensures we never double count lumi + else if(lSuspect.HasRunLumiBlock(runNbr,lb)) {hasLumi=true;totalLumiSuspect += intLumi;} + + if(!hasLumi && intLumi==0.) hasLumi=true; //if there is no lumi, it's as good as having some + if((lastRunNumber!=runNbr&&startMissingBlock>=0) || (hasLumi && startMissingBlock>=0)) { + //print now, if startMissingBlock not negative + if(showMissing) std::cout << "[" << lastRunNumber << "," << startMissingBlock << "-" << lastLb << "," << missingLumi << "]";missingRuns[lastRunNumber]=true; + allMissing+=missingLumi; missingLumi=0; + startMissingBlock=-1; + } + if(!hasLumi && startMissingBlock==-1) {startMissingBlock=lb;missingLumi=intLumi/1E6;} + else if(!hasLumi) { missingLumi+=(intLumi/1E6); } + lastRunNumber=runNbr;lastLb=lb; + allRuns[runNbr] = true; + } + lumicalcFile->Close(); + allMissing += missingLumi; + if(missingRuns.size()>0 && showMissing) { + std::cout << std::endl << "Runs with incomplete blocks: "; + for(auto r : incompleteRuns) { + std::cout << r << ","; + } + std::cout << std::endl << "Runs with missing blocks: "; + for(std::map<UInt_t,bool>::iterator it=missingRuns.begin();it!=missingRuns.end();++it) { + std::cout << it->first << ","; + } + std::cout << std::endl << "Complete runs: "; + for(std::map<UInt_t,bool>::iterator it=allRuns.begin();it!=allRuns.end();++it) { + if(missingRuns.find(it->first) == missingRuns.end()) std::cout << it->first << ","; + } + std::cout << std::endl; + } + std::cout << "Done" << std::endl; + + std::cout << "Complete Luminosity = " << totalLumi/1E6 << " pb-1" << std::endl; + if(totalLumiIncomplete) std::cout << "Incomplete Luminosity = " << totalLumiIncomplete/1E6 << " pb-1" << std::endl; + if(totalLumiSuspect) std::cout << "Suspect Luminosity = " << totalLumiSuspect/1E6 << " pb-1" << std::endl; + std::cout << "(Complete+Incomplete+Suspect) Luminosity = " << (totalLumi+totalLumiIncomplete+totalLumiSuspect)/1E6 << " pb-1" << std::endl; + if(missingLumi) { + std::cout << "(Missing Lumonisity = " << allMissing << " pb-1)"; //already divided by 1E6 in loop above + if(!showMissing) std::cout << " rerun with the '-m' option to see runs where this luminosity resides"; + std::cout << std::endl; + } + + /* + Root::TGoodRunsList allL(l); allL.AddGRL(lIncomplete);allL.AddGRL(lSuspect); + auto uncovered = allL.GetPartNotIn(providedL); + if(!uncovered.IsEmpty()) { + std::cout << "Input files contain following lumiblocks not covered by lumicalc file:" << std::endl; + uncovered.Summary(1); + }*/ + +} + +#endif