From 7ba6e9c9f05bca99f026a10bf4d35385f8972a0b Mon Sep 17 00:00:00 2001 From: Peter Loch <peterloch59@gmail.com> Date: Tue, 30 Mar 2021 16:04:37 +0000 Subject: [PATCH] Add new topo-cluster moment and foward tower disc spze reduction - New moment SECOND_TIME added to output item list for CaloCalTopoClusters (explorative) - Reduced set of moments in output item list for CaloCalFwdTopoTowers - Removed sampling data from objects in CaloCalFwdTopoTowers --- .../share/CaloRecOutputItemList_jobOptions.py | 5 +- .../CaloRec/python/CaloClusterTopoGetter.py | 2 +- .../CaloRec/python/CaloTopoClusterConfig.py | 3 +- .../CaloRec/python/MakeTowersFromClusters.py | 16 +- .../CaloRec/share/CaloTopoSignalFragment.py | 2 +- .../CaloRec/src/CaloClusterMomentsMaker.cxx | 321 +++++++++--------- .../CaloRec/src/CaloClusterMomentsMaker.h | 14 +- .../src/CaloTopoTowerFromClusterMaker.cxx | 9 +- .../src/CaloTopoTowerFromClusterMaker.h | 1 + .../Root/CaloClusterAccessors_v1.cxx | 1 + .../xAODCaloEvent/Root/CaloCluster_v1.cxx | 13 +- .../src/CaloClusterKineHelper.cxx | 26 +- .../xAODCaloEvent/xAODCaloEvent/selection.xml | 6 + .../xAODCaloEvent/versions/CaloCluster_v1.h | 32 +- 14 files changed, 262 insertions(+), 189 deletions(-) diff --git a/Calorimeter/CaloExample/CaloRecEx/share/CaloRecOutputItemList_jobOptions.py b/Calorimeter/CaloExample/CaloRecEx/share/CaloRecOutputItemList_jobOptions.py index d9e10e05a6c..7f143f2ac81 100644 --- a/Calorimeter/CaloExample/CaloRecEx/share/CaloRecOutputItemList_jobOptions.py +++ b/Calorimeter/CaloExample/CaloRecEx/share/CaloRecOutputItemList_jobOptions.py @@ -110,7 +110,8 @@ AODMoments=[#"LATERAL" ,"EM_PROBABILITY" #,"PTD" ,"BadChannelList" - ,#"LATERAL" + #,"LATERAL" + ,"SECOND_TIME" ] if jobproperties.CaloRecFlags.doExtendedClusterMoments.get_Value(): @@ -215,8 +216,6 @@ if jobproperties.CaloRecFlags.doCaloFwdTopoTower.get_Value(): AuxListItem+="."+moment CaloClusterItemList+=[AuxListItem] - - CaloAODList+=CaloClusterItemList # E4' cells diff --git a/Calorimeter/CaloRec/python/CaloClusterTopoGetter.py b/Calorimeter/CaloRec/python/CaloClusterTopoGetter.py index 0aeba2d994e..9f1d68111d0 100644 --- a/Calorimeter/CaloRec/python/CaloClusterTopoGetter.py +++ b/Calorimeter/CaloRec/python/CaloClusterTopoGetter.py @@ -234,7 +234,7 @@ class CaloClusterTopoGetter ( Configured ) : ,"AVG_TILE_Q" ,"PTD" ,"MASS" - ,"EM_PROBABILITY" + ,"SECOND_TIME" ] doDigiTruthFlag = False diff --git a/Calorimeter/CaloRec/python/CaloTopoClusterConfig.py b/Calorimeter/CaloRec/python/CaloTopoClusterConfig.py index a7a9979864d..4bc3520529e 100644 --- a/Calorimeter/CaloRec/python/CaloTopoClusterConfig.py +++ b/Calorimeter/CaloRec/python/CaloTopoClusterConfig.py @@ -1,4 +1,4 @@ -# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory @@ -135,6 +135,7 @@ def getTopoMoments(configFlags): ,"AVG_TILE_Q" ,"PTD" ,"MASS" + , "SECOND_TIME" ] # Disable for now, as broken on MC diff --git a/Calorimeter/CaloRec/python/MakeTowersFromClusters.py b/Calorimeter/CaloRec/python/MakeTowersFromClusters.py index 4e312a59e41..04293c4097d 100644 --- a/Calorimeter/CaloRec/python/MakeTowersFromClusters.py +++ b/Calorimeter/CaloRec/python/MakeTowersFromClusters.py @@ -24,6 +24,7 @@ def TowersFromClustersDict(clusterBuilderName = 'TowerFromClusterTool', cellEnergyThreshold = 0., applyLCW = False, buildCombinedSignal = False, + removeSamplingData = True, clusterRange = 5.): ''' Configuration dictionary for tower-to-cluster converter ''' @@ -38,7 +39,8 @@ def TowersFromClustersDict(clusterBuilderName = 'TowerFromClusterTool', 'PrepareLCW' : applyLCW, ### (control) prepare (and apply) LCW 'DoCellIndexCheck' : doCellIndexCheck, ### (control) check cell hash indices 'BuildCombinedTopoSignal' : buildCombinedSignal, ### (control) build combined topo-cluster/topo-tower container - 'TopoClusterRange' : clusterRange, ### (control) range for topo-cluster in combined mode + 'TopoClusterRange' : clusterRange, ### (control) range for topo-cluster in combined mode + 'RemoveSamplingData' : removeSamplingData, ### (control) remove all sampling data from tower } return configDict @@ -146,15 +148,15 @@ def MakeTowersFromClusters(towerMakerName = 'CaloTowerBuilderAlg', # clusterMoments.TwoGaussianNoise = jobproperties.CaloTopoClusterFlags.doTwoGaussianNoise() clusterMoments.MinBadLArQuality = 4000 clusterMoments.MomentsNames = [ - "CENTER_LAMBDA", - #"CENTER_MAG", + # "CENTER_LAMBDA", + # "CENTER_MAG", "LONGITUDINAL", - #"FIRST_ENG_DENS", - #"ENG_FRAC_MAX", + # "FIRST_ENG_DENS", + # "ENG_FRAC_MAX", "ENG_FRAC_EM", - #"PTD", + # "PTD", "SIGNIFICANCE", - "ENG_POS" + # "ENG_POS", ] from IOVDbSvc.CondDB import conddb diff --git a/Calorimeter/CaloRec/share/CaloTopoSignalFragment.py b/Calorimeter/CaloRec/share/CaloTopoSignalFragment.py index 79bcb1076bd..e43ade4a0b8 100644 --- a/Calorimeter/CaloRec/share/CaloTopoSignalFragment.py +++ b/Calorimeter/CaloRec/share/CaloTopoSignalFragment.py @@ -58,7 +58,7 @@ caloTowerMerger.TopoClusterRange = caloTowerDict['TopoClusterRange'] caloTowerMerger.TopoClusterContainerKey = caloTowerDict['CaloTopoClusterContainerKey'] #### caloTowerAlgo.CaloFwdTopoTowerBuilder.CaloTopoClusterContainerKey caloTowerMerger.TopoTowerContainerKey = caloTowerAlgo.TowersOutputName caloTowerMerger.TopoSignalContainerKey = 'CaloCalTopoSignals' -caloTowerMerger.OutputLevel = Lvl.DEBUG +## caloTowerMerger.OutputLevel = Lvl.DEBUG topSequence+=caloTowerAlgo topSequence+=caloTowerMerger diff --git a/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.cxx b/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.cxx index 5c679d82e58..1ebd1d49f9e 100644 --- a/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.cxx +++ b/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ //----------------------------------------------------------------------- @@ -12,6 +12,7 @@ // // Author List: // Sven Menke +// Peter Loch // //----------------------------------------------------------------------- @@ -39,78 +40,98 @@ #include <limits> #include <sstream> +#include <map> +#include <string> +#include <cstdio> + using CLHEP::deg; using CLHEP::cm; +// Known moments namespace { - - - //FIXME, somehow make sure these names are in sync with the xAOD variable names -struct MomentName -{ - const char* name; - xAOD::CaloCluster::MomentType mom; -}; - - -// Must be sorted by name. -MomentName moment_names[] = { - { "AVG_LAR_Q", xAOD::CaloCluster::AVG_LAR_Q }, - { "AVG_TILE_Q", xAOD::CaloCluster::AVG_TILE_Q }, - { "BADLARQ_FRAC", xAOD::CaloCluster::BADLARQ_FRAC }, - { "BAD_CELLS_CORR_E", xAOD::CaloCluster::BAD_CELLS_CORR_E }, - { "CELL_SIGNIFICANCE", xAOD::CaloCluster::CELL_SIGNIFICANCE }, - { "CELL_SIG_SAMPLING", xAOD::CaloCluster::CELL_SIG_SAMPLING }, - { "CENTER_LAMBDA", xAOD::CaloCluster::CENTER_LAMBDA }, - { "CENTER_MAG", xAOD::CaloCluster::CENTER_MAG }, - { "CENTER_X", xAOD::CaloCluster::CENTER_X }, - { "CENTER_Y", xAOD::CaloCluster::CENTER_Y }, - { "CENTER_Z", xAOD::CaloCluster::CENTER_Z }, - { "DELTA_ALPHA", xAOD::CaloCluster::DELTA_ALPHA }, - { "DELTA_PHI", xAOD::CaloCluster::DELTA_PHI }, - { "DELTA_THETA", xAOD::CaloCluster::DELTA_THETA }, - { "ENG_BAD_CELLS", xAOD::CaloCluster::ENG_BAD_CELLS }, - { "ENG_BAD_HV_CELLS", xAOD::CaloCluster::ENG_BAD_HV_CELLS }, - { "ENG_FRAC_CORE", xAOD::CaloCluster::ENG_FRAC_CORE }, - { "ENG_FRAC_EM", xAOD::CaloCluster::ENG_FRAC_EM }, - { "ENG_FRAC_MAX", xAOD::CaloCluster::ENG_FRAC_MAX }, - { "ENG_POS", xAOD::CaloCluster::ENG_POS }, - { "FIRST_ENG_DENS", xAOD::CaloCluster::FIRST_ENG_DENS }, - { "FIRST_ETA", xAOD::CaloCluster::FIRST_ETA }, - { "FIRST_PHI", xAOD::CaloCluster::FIRST_PHI }, - { "ISOLATION", xAOD::CaloCluster::ISOLATION }, - { "LATERAL", xAOD::CaloCluster::LATERAL }, - { "LONGITUDINAL", xAOD::CaloCluster::LONGITUDINAL }, - { "MASS", xAOD::CaloCluster::MASS }, - { "N_BAD_CELLS", xAOD::CaloCluster::N_BAD_CELLS }, - { "N_BAD_HV_CELLS", xAOD::CaloCluster::N_BAD_HV_CELLS }, - { "N_BAD_CELLS_CORR", xAOD::CaloCluster::N_BAD_CELLS_CORR }, - { "PTD", xAOD::CaloCluster::PTD }, - { "SECOND_ENG_DENS", xAOD::CaloCluster::SECOND_ENG_DENS }, - { "SECOND_LAMBDA", xAOD::CaloCluster::SECOND_LAMBDA }, - { "SECOND_R", xAOD::CaloCluster::SECOND_R }, - { "SIGNIFICANCE", xAOD::CaloCluster::SIGNIFICANCE }, -}; - -MomentName* moment_names_end = - moment_names + sizeof(moment_names)/sizeof(moment_names[0]); - -#if 0 -bool operator< (const std::string& v, const MomentName& m) -{ - return strcmp (v.c_str(), m.name) < 0; -} -#endif -bool operator< (const MomentName& m, const std::string& v) -{ - return strcmp (m.name, v.c_str()) < 0; -} - - + // name -> enum translator + std::map<std::string,xAOD::CaloCluster::MomentType> momentNameToEnumMap = { + { "AVG_LAR_Q", xAOD::CaloCluster::AVG_LAR_Q }, + { "AVG_TILE_Q", xAOD::CaloCluster::AVG_TILE_Q }, + { "BADLARQ_FRAC", xAOD::CaloCluster::BADLARQ_FRAC }, + { "BAD_CELLS_CORR_E", xAOD::CaloCluster::BAD_CELLS_CORR_E }, + { "CELL_SIGNIFICANCE", xAOD::CaloCluster::CELL_SIGNIFICANCE }, + { "CELL_SIG_SAMPLING", xAOD::CaloCluster::CELL_SIG_SAMPLING }, + { "CENTER_LAMBDA", xAOD::CaloCluster::CENTER_LAMBDA }, + { "CENTER_MAG", xAOD::CaloCluster::CENTER_MAG }, + { "CENTER_X", xAOD::CaloCluster::CENTER_X }, + { "CENTER_Y", xAOD::CaloCluster::CENTER_Y }, + { "CENTER_Z", xAOD::CaloCluster::CENTER_Z }, + { "DELTA_ALPHA", xAOD::CaloCluster::DELTA_ALPHA }, + { "DELTA_PHI", xAOD::CaloCluster::DELTA_PHI }, + { "DELTA_THETA", xAOD::CaloCluster::DELTA_THETA }, + { "ENG_BAD_CELLS", xAOD::CaloCluster::ENG_BAD_CELLS }, + { "ENG_BAD_HV_CELLS", xAOD::CaloCluster::ENG_BAD_HV_CELLS }, + { "ENG_FRAC_CORE", xAOD::CaloCluster::ENG_FRAC_CORE }, + { "ENG_FRAC_EM", xAOD::CaloCluster::ENG_FRAC_EM }, + { "ENG_FRAC_MAX", xAOD::CaloCluster::ENG_FRAC_MAX }, + { "ENG_POS", xAOD::CaloCluster::ENG_POS }, + { "FIRST_ENG_DENS", xAOD::CaloCluster::FIRST_ENG_DENS }, + { "FIRST_ETA", xAOD::CaloCluster::FIRST_ETA }, + { "FIRST_PHI", xAOD::CaloCluster::FIRST_PHI }, + { "ISOLATION", xAOD::CaloCluster::ISOLATION }, + { "LATERAL", xAOD::CaloCluster::LATERAL }, + { "LONGITUDINAL", xAOD::CaloCluster::LONGITUDINAL }, + { "MASS", xAOD::CaloCluster::MASS }, + { "N_BAD_CELLS", xAOD::CaloCluster::N_BAD_CELLS }, + { "N_BAD_HV_CELLS", xAOD::CaloCluster::N_BAD_HV_CELLS }, + { "N_BAD_CELLS_CORR", xAOD::CaloCluster::N_BAD_CELLS_CORR }, + { "PTD", xAOD::CaloCluster::PTD }, + { "SECOND_ENG_DENS", xAOD::CaloCluster::SECOND_ENG_DENS }, + { "SECOND_LAMBDA", xAOD::CaloCluster::SECOND_LAMBDA }, + { "SECOND_R", xAOD::CaloCluster::SECOND_R }, + { "SECOND_TIME", xAOD::CaloCluster::SECOND_TIME }, + { "SIGNIFICANCE", xAOD::CaloCluster::SIGNIFICANCE }, + { "EM_PROBABILITY", xAOD::CaloCluster::EM_PROBABILITY } + }; + // enum -> name translator + std::map<xAOD::CaloCluster::MomentType,std::string> momentEnumToNameMap = { + { xAOD::CaloCluster::AVG_LAR_Q, "AVG_LAR_Q" }, + { xAOD::CaloCluster::AVG_TILE_Q, "AVG_TILE_Q" }, + { xAOD::CaloCluster::BADLARQ_FRAC, "BADLARQ_FRAC" }, + { xAOD::CaloCluster::BAD_CELLS_CORR_E, "BAD_CELLS_CORR_E" }, + { xAOD::CaloCluster::CELL_SIGNIFICANCE, "CELL_SIGNIFICANCE"}, + { xAOD::CaloCluster::CELL_SIG_SAMPLING, "CELL_SIG_SAMPLING"}, + { xAOD::CaloCluster::CENTER_LAMBDA, "CENTER_LAMBDA" }, + { xAOD::CaloCluster::CENTER_MAG, "CENTER_MAG" }, + { xAOD::CaloCluster::CENTER_X, "CENTER_X" }, + { xAOD::CaloCluster::CENTER_Y, "CENTER_Y" }, + { xAOD::CaloCluster::CENTER_Z, "CENTER_Z" }, + { xAOD::CaloCluster::DELTA_ALPHA, "DELTA_ALPHA" }, + { xAOD::CaloCluster::DELTA_PHI, "DELTA_PHI" }, + { xAOD::CaloCluster::DELTA_THETA, "DELTA_THETA" }, + { xAOD::CaloCluster::ENG_BAD_CELLS, "ENG_BAD_CELLS" }, + { xAOD::CaloCluster::ENG_BAD_HV_CELLS, "ENG_BAD_HV_CELLS" }, + { xAOD::CaloCluster::ENG_FRAC_CORE, "ENG_FRAC_CORE" }, + { xAOD::CaloCluster::ENG_FRAC_EM, "ENG_FRAC_EM" }, + { xAOD::CaloCluster::ENG_FRAC_MAX, "ENG_FRAC_MAX" }, + { xAOD::CaloCluster::ENG_POS, "ENG_POS" }, + { xAOD::CaloCluster::FIRST_ENG_DENS, "FIRST_ENG_DENS" }, + { xAOD::CaloCluster::FIRST_ETA, "FIRST_ETA" }, + { xAOD::CaloCluster::FIRST_PHI, "FIRST_PHI" }, + { xAOD::CaloCluster::ISOLATION, "ISOLATION" }, + { xAOD::CaloCluster::LATERAL, "LATERAL" }, + { xAOD::CaloCluster::LONGITUDINAL, "LONGITUDINAL" }, + { xAOD::CaloCluster::MASS, "MASS" }, + { xAOD::CaloCluster::N_BAD_CELLS, "N_BAD_CELLS" }, + { xAOD::CaloCluster::N_BAD_HV_CELLS, "N_BAD_HV_CELLS" }, + { xAOD::CaloCluster::N_BAD_CELLS_CORR, "N_BAD_CELLS_CORR" }, + { xAOD::CaloCluster::PTD, "PTD" }, + { xAOD::CaloCluster::SECOND_ENG_DENS, "SECOND_ENG_DENS" }, + { xAOD::CaloCluster::SECOND_LAMBDA, "SECOND_LAMBDA" }, + { xAOD::CaloCluster::SECOND_R, "SECOND_R" }, + { xAOD::CaloCluster::SECOND_TIME, "SECOND_TIME" }, + { xAOD::CaloCluster::SIGNIFICANCE, "SIGNIFICANCE" }, + { xAOD::CaloCluster::EM_PROBABILITY, "EM_PROBABILITY" } + }; } - //############################################################################### CaloClusterMomentsMaker::CaloClusterMomentsMaker(const std::string& type, @@ -134,117 +155,102 @@ CaloClusterMomentsMaker::CaloClusterMomentsMaker(const std::string& type, // Name(s) of Moments to calculate declareProperty("MomentsNames",m_momentsNames); - // Name(s) of Moments which can be stored on the AOD - all others go to ESD - // m_momentsNamesAOD.push_back(std::string("FIRST_PHI")); - // m_momentsNamesAOD.push_back(std::string("FIRST_ETA")); - // m_momentsNamesAOD.push_back(std::string("SECOND_R")); - // m_momentsNamesAOD.push_back(std::string("SECOND_LAMBDA")); - // m_momentsNamesAOD.push_back(std::string("CENTER_LAMBDA")); - // m_momentsNamesAOD.push_back(std::string("FIRST_ENG_DENS")); - // m_momentsNamesAOD.push_back(std::string("ENG_BAD_CELLS")); - // m_momentsNamesAOD.push_back(std::string("N_BAD_CELLS")); - - //declareProperty("AODMomentsNames",m_momentsNamesAOD); - // maximum allowed angle between shower axis and the vector pointing - // to the shower center from the IP in degrees. This property is need + // Maximum allowed angle between shower axis and the vector pointing + // to the shower center from the IP in degrees. This property is needed // to protect against cases where all significant cells are in one sampling - // and the shower axis can not be defined from them + // and the shower axis can thus not be defined. declareProperty("MaxAxisAngle",m_maxAxisAngle); declareProperty("MinRLateral",m_minRLateral); declareProperty("MinLLongitudinal",m_minLLongitudinal); declareProperty("MinBadLArQuality",m_minBadLArQuality); - // use 2-gaussian noise for Tile + // Use 2-gaussian noise for Tile declareProperty("TwoGaussianNoise",m_twoGaussianNoise); declareProperty("LArHVFraction",m_larHVFraction,"Tool Handle for LArHVFraction"); - - /// Not used anymore (with xAOD), but required when configured from COOL. + // Not used anymore (with xAOD), but required when configured from COOL. declareProperty("AODMomentsNames",m_momentsNamesAOD); // Use weighting of neg. clusters option? declareProperty("WeightingOfNegClusters", m_absOpt); - } //############################################################################### StatusCode CaloClusterMomentsMaker::initialize() { - m_calculateSignificance = false; - m_calculateIsolation = false; - - // translate all moment names specified in MomentsNames property to moment enums, - // check that they are all valid and there are no repeating names - for(const auto& name: m_momentsNames) { - const MomentName* it = - std::lower_bound (moment_names, moment_names_end, name); - if (it != moment_names_end) { - m_validMoments.push_back (it->mom); - switch (it->mom) { - case xAOD::CaloCluster::SIGNIFICANCE: - case xAOD::CaloCluster::CELL_SIGNIFICANCE: - m_calculateSignificance = true; - break; - case xAOD::CaloCluster::ISOLATION: - m_calculateIsolation = true; - break; - case xAOD::CaloCluster::ENG_BAD_HV_CELLS: - m_calculateLArHVFraction = true; - default: - break; - } - } - else { - msg(MSG::ERROR) << "Moment " << name - << " is not a valid Moment name and will be ignored! " - << "Valid names are:"; - int count = 0; - for (const MomentName& m : moment_names) - msg() << ((count++)==0?" ":", ") << m.name; - msg() << endmsg; - } - } - + // loop list of requested moments + std::string::size_type nstr(0); int nmom(0); + for ( const auto& mom : m_momentsNames ) { + // check if moment is known (enumerator available) + auto fmap(momentNameToEnumMap.find(mom)); + if ( fmap != momentNameToEnumMap.end() ) { + // valid moment found + nstr = std::max(nstr,mom.length()); ++nmom; + if ( fmap->second == xAOD::CaloCluster::SECOND_TIME ) { + // special flag for second moment of cell times - this moment is not + // calculated in this tool! Do not add to internal (!) valid moments list. + // Its value is available from xAOD::CaloCluster::secondTime()! + m_secondTime = true; + } else if ( fmap->second == xAOD::CaloCluster::EM_PROBABILITY ) { + ATH_MSG_WARNING( mom << " not calculated in this tool - misconfiguration?" ); + } else { + // all other valid moments + m_validMoments.push_back(fmap->second); + // flag some special requests + switch (fmap->second) { + case xAOD::CaloCluster::SIGNIFICANCE: + case xAOD::CaloCluster::CELL_SIGNIFICANCE: + m_calculateSignificance = true; + break; + case xAOD::CaloCluster::ISOLATION: + m_calculateIsolation = true; + break; + case xAOD::CaloCluster::ENG_BAD_HV_CELLS: + m_calculateLArHVFraction = true; + default: + break; + } // set special processing flags + } // moment calculated with this tool + } else { + ATH_MSG_ERROR( "Moment name " << mom << " not known; known moments are:" ); + char buffer[128]; std::string::size_type lstr(nstr); + // determine field size + for ( auto fmom : momentNameToEnumMap ) { lstr = std::max(lstr,fmom.first.length()); } + // print available moments + for ( auto fmom : momentNameToEnumMap ) { + sprintf(buffer,"moment name: %-*.*s - enumerator: %i",(int)lstr,(int)lstr,fmom.first.c_str(),(int)fmom.second); + ATH_MSG_INFO(buffer); + } + return StatusCode::FAILURE; + } // found unknown moment name + } // loop configured moment names - // sort and remove duplicates, order is not required for any of the code below - // but still may be useful property + // sort and remove duplicates std::sort(m_validMoments.begin(), m_validMoments.end()); - m_validMoments.erase(std::unique(m_validMoments.begin(), - m_validMoments.end()), - m_validMoments.end()); - - - /* - // translate moment names in AODMomentsNames property into set of enums, - // only take valid names which are also in MomentsNames property - m_momentsAOD.reserve(m_momentsNamesAOD.size()); - for(const auto& name: m_momentsNamesAOD) { - const MomentName* it = - std::lower_bound (moment_names, moment_names_end, name); - if (it != moment_names_end) { - if (std::find(m_validMoments.begin(), m_validMoments.end(), it->mom) - != m_validMoments.end()) - { - m_momentsAOD.push_back(it->mom); - } - } + m_validMoments.erase(std::unique(m_validMoments.begin(),m_validMoments.end()),m_validMoments.end()); + + // print configured moments + ATH_MSG_INFO( "Construct and save " << nmom << " cluster moments: " ); + char buffer[128]; + for ( auto menum : m_validMoments ) { + sprintf(buffer,"moment name: %-*.*s - enumerator: %i",(int)nstr,(int)nstr,momentEnumToNameMap.at(menum).c_str(),(int)menum); + ATH_MSG_INFO( buffer ); } - */ - + if ( m_secondTime ) { + auto fmom(momentNameToEnumMap.find("SECOND_TIME")); + sprintf(buffer,"moment name: %-*.*s - enumerator: %i (save only)",(int)nstr,(int)nstr,fmom->first.c_str(),(int)fmom->second); + ATH_MSG_INFO( buffer ); + } + + // retrieve CaloCell ID server CHECK(detStore()->retrieve(m_calo_id,"CaloCell_ID")); + // retrieve the calo depth tool CHECK(m_caloDepthTool.retrieve()); - if (m_calculateSignificance) { - ATH_CHECK(m_noiseCDOKey.initialize()); - } + // retrieve specific servers and tools for selected processes + if (m_calculateSignificance) { ATH_CHECK(m_noiseCDOKey.initialize()); } + if (m_calculateLArHVFraction) { ATH_CHECK(m_larHVFraction.retrieve()); } else { m_larHVFraction.disable(); } - if (m_calculateLArHVFraction) { - ATH_CHECK(m_larHVFraction.retrieve()); - } - else { - m_larHVFraction.disable(); - } return StatusCode::SUCCESS; - } StatusCode CaloClusterMomentsMaker::finalize() @@ -256,6 +262,7 @@ StatusCode CaloClusterMomentsMaker::finalize() namespace CaloClusterMomentsMaker_detail { + struct cellinfo { double x; double y; @@ -903,7 +910,7 @@ CaloClusterMomentsMaker::execute(const EventContext& ctx, } } } - + // normalize moments and copy to Cluster Moment Store size_t size= m_validMoments.size(); for (size_t iMoment = 0; iMoment != size; ++iMoment) { @@ -913,9 +920,11 @@ CaloClusterMomentsMaker::execute(const EventContext& ctx, if ( moment == xAOD::CaloCluster::FIRST_PHI ) myMoments[iMoment] = CaloPhiRange::fix(myMoments[iMoment]); theCluster->insertMoment(moment,myMoments[iMoment]); - } - } - } + } // loop on moments for cluster + } // check on requested moments + // check on second moment of time if requested + if ( m_secondTime ) { theCluster->insertMoment(xAOD::CaloCluster::SECOND_TIME,theCluster->secondTime()); } + } // loop on clusters return StatusCode::SUCCESS; } diff --git a/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.h b/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.h index 0f3622d0280..82e5f0e299c 100644 --- a/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.h +++ b/Calorimeter/CaloRec/src/CaloClusterMomentsMaker.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ //Dear emacs, this is -*-c++-*- @@ -8,7 +8,8 @@ /** * @class CaloClusterMomentsMaker * @author Sven Menke <menke@mppmu.mpg.de> - * @date 28-February-2005 + * @author Peter Loch <loch@physics.arizona.edu> + * @date 23-March-2021 * @brief Calculate moments for CaloCluster objects * * This is a CaloClusterCollectionProcessor which can be plugged into a @@ -25,7 +26,10 @@ * Note that only cells with positive energy are used in this definition. * Common variables to calculate first and second moments of are * \f$\phi\f$, \f$\eta\f$, and radial and longitudinal distances from - * the shower axis and the shower center, respectively. */ + * the shower axis and the shower center, respectively. + * + * @since 23-March-2021: second moment of cell time distribution is calculated + */ #include "GaudiKernel/ToolHandle.h" @@ -133,6 +137,10 @@ class CaloClusterMomentsMaker: public AthAlgTool, virtual public CaloClusterColl * @brief if set to true use abs E value of cells to calculate * cluster moments */ bool m_absOpt; + + /** + * @brief Retreive second moment of cell times */ + bool m_secondTime = { false }; }; #endif // CALOCLUSTERMOMENTSMAKER_H diff --git a/Calorimeter/CaloRec/src/CaloTopoTowerFromClusterMaker.cxx b/Calorimeter/CaloRec/src/CaloTopoTowerFromClusterMaker.cxx index b3861bb3f86..563981cda3e 100644 --- a/Calorimeter/CaloRec/src/CaloTopoTowerFromClusterMaker.cxx +++ b/Calorimeter/CaloRec/src/CaloTopoTowerFromClusterMaker.cxx @@ -76,6 +76,7 @@ CaloTopoTowerFromClusterMaker::CaloTopoTowerFromClusterMaker(const std::string& declareProperty("DoCellIndexCheck", m_doCellIndexCheck, "Check cell hash indices for consistency"); declareProperty("BuildCombinedTopoSignal", m_buildCombinedSignal, "Build topo-clusters and topo-towers"); declareProperty("TopoClusterRange", m_clusterRange, "Rapidity range for using topo-clusters in combined signal mode"); + declareProperty("RemoveSamplingData", m_removeSamplingData, "Remove the associated sampling data"); } StatusCode CaloTopoTowerFromClusterMaker::initialize() @@ -183,6 +184,7 @@ StatusCode CaloTopoTowerFromClusterMaker::initialize() ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("BuildCombinedTopoSignal .... %s", blu[m_buildCombinedSignal].c_str()) ); ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("TopoClusterRange ........... %.2f", m_clusterRange) ); ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("ExcludedSamplings .......... %zu (number of)",m_excludedSamplingsName.size()) ); + ATH_MSG_INFO( CaloRec::Helpers::fmtMsg("RemoveSamplingData ......... %s", blu[m_removeSamplingData].c_str()) ); return StatusCode::SUCCESS; } @@ -268,8 +270,11 @@ StatusCode CaloTopoTowerFromClusterMaker::execute(const EventContext& ctx, clptr->addCellLink(lptr); // transfer cell links to CaloCluster clptr->setClusterSize(csize); // set the cluster size spec CaloRec::Helpers::calculateKine(clptr,false); // calculate kinematics and other signals from cells - clptr->setEta0(m_towerGeometrySvc->towerEta(ipc)); // save the tower center eta - clptr->setPhi0(m_towerGeometrySvc->towerPhi(ipc)); // save the tower center phi + if ( m_removeSamplingData ) { // remove sampling data and invalidate tower center + clptr->clearSamplingData(); clptr->setEta0(0.); clptr->setPhi0(0.); + } else { // keep sampling data and valid tower center + clptr->setEta0(m_towerGeometrySvc->towerEta(ipc)); clptr->setPhi0(m_towerGeometrySvc->towerPhi(ipc)); + } } else { delete lptr; } diff --git a/Calorimeter/CaloRec/src/CaloTopoTowerFromClusterMaker.h b/Calorimeter/CaloRec/src/CaloTopoTowerFromClusterMaker.h index 9bfd45b6b7d..328117f5b71 100644 --- a/Calorimeter/CaloRec/src/CaloTopoTowerFromClusterMaker.h +++ b/Calorimeter/CaloRec/src/CaloTopoTowerFromClusterMaker.h @@ -69,6 +69,7 @@ private: bool m_buildCombinedSignal = { false }; ///< Build topo-clusters within given @f$ y @f$ range, else topo-towers double m_energyThreshold; ///< Cell energy threshold, default is set in @c m_energyThresholdDef double m_clusterRange; ///< Range where topo-clusters are used when <tt>m_buildCombinedSignal = true</tt> + bool m_removeSamplingData = { true }; ///< Remove sampling data for towers /// @} /// @name Constants and parameters diff --git a/Event/xAOD/xAODCaloEvent/Root/CaloClusterAccessors_v1.cxx b/Event/xAOD/xAODCaloEvent/Root/CaloClusterAccessors_v1.cxx index 0a3353663d6..3708e0bf83b 100644 --- a/Event/xAOD/xAODCaloEvent/Root/CaloClusterAccessors_v1.cxx +++ b/Event/xAOD/xAODCaloEvent/Root/CaloClusterAccessors_v1.cxx @@ -56,6 +56,7 @@ namespace xAOD { DEFINE_ACCESSOR( SIGNIFICANCE ); DEFINE_ACCESSOR( PTD ); DEFINE_ACCESSOR( MASS ); + DEFINE_ACCESSOR( SECOND_TIME ); DEFINE_ACCESSOR( CELL_SIGNIFICANCE ); DEFINE_ACCESSOR( CELL_SIG_SAMPLING ); DEFINE_ACCESSOR( AVG_LAR_Q ); diff --git a/Event/xAOD/xAODCaloEvent/Root/CaloCluster_v1.cxx b/Event/xAOD/xAODCaloEvent/Root/CaloCluster_v1.cxx index 6b5b48e5180..52aa125df79 100644 --- a/Event/xAOD/xAODCaloEvent/Root/CaloCluster_v1.cxx +++ b/Event/xAOD/xAODCaloEvent/Root/CaloCluster_v1.cxx @@ -33,7 +33,8 @@ namespace xAOD { : IParticle(other), m_samplingPattern(other.samplingPattern()), m_cellLinks(nullptr), - m_recoStatus(other.m_recoStatus) { + m_recoStatus(other.m_recoStatus), + m_secondTime(other.m_secondTime) { setSignalState(other.signalState()); this->makePrivateStore(other); #if !(defined(SIMULATIONBASE) || defined(XAOD_ANALYSIS)) @@ -58,6 +59,7 @@ namespace xAOD { m_recoStatus=other.m_recoStatus; setSignalState(other.signalState()); m_samplingPattern=other.m_samplingPattern; + m_secondTime = other.m_secondTime; #if !(defined(SIMULATIONBASE) || defined(XAOD_ANALYSIS)) const CaloClusterCellLink* links=other.getCellLinks(); @@ -922,6 +924,15 @@ namespace xAOD { return true; } + void CaloCluster_v1::setSecondTime(CaloCluster_v1::flt_t stime) { m_secondTime = stime; } + + CaloCluster_v1::flt_t CaloCluster_v1::secondTime() const { + if ( m_secondTime < 0. ) { + double stime(0.); return this->retrieveMoment(SECOND_TIME,stime) ? stime : 0.; + } else { + return m_secondTime; + } + } #if !(defined(SIMULATIONBASE) || defined(XAOD_ANALYSIS)) size_t CaloCluster_v1::size() const { diff --git a/Event/xAOD/xAODCaloEvent/src/CaloClusterKineHelper.cxx b/Event/xAOD/xAODCaloEvent/src/CaloClusterKineHelper.cxx index 592ab047a04..320ba561fb1 100644 --- a/Event/xAOD/xAODCaloEvent/src/CaloClusterKineHelper.cxx +++ b/Event/xAOD/xAODCaloEvent/src/CaloClusterKineHelper.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ #ifndef SIMULATIONBASE @@ -12,6 +12,8 @@ #include "CaloGeoHelpers/CaloPhiRange.h" #include "CaloEvent/CaloPrefetch.h" +#include <cmath> + namespace { @@ -37,6 +39,7 @@ struct CellAccum PresenceInSample(), theNewEnergy(0), theNewTime(0), + theNewSecondTime(0), theNewEta(0), theNewPhi(0), phi0(-999), @@ -55,6 +58,7 @@ struct CellAccum bool PresenceInSample[CaloSampling::Unknown]; double theNewEnergy; double theNewTime; + double theNewSecondTime; double theNewEta; double theNewPhi; double phi0; @@ -160,9 +164,10 @@ void accumCell (const CaloClusterCellLink::const_iterator& cellIt, CellAccum& ac // Is time defined? if ( cell.provenance() & pmask ) { // keep the sign of weight for the time norm in case a cell is removed - double theTimeNorm = fabsweight * theEnergy * theEnergyNoWeight; - accum.theNewTime += theTimeNorm * cell.time(); - accum.timeNorm += theTimeNorm; + double theTimeNorm = fabsweight * theEnergy * theEnergyNoWeight; + accum.theNewTime += theTimeNorm * cell.time(); + accum.theNewSecondTime += theTimeNorm * cell.time() * cell.time(); + accum.timeNorm += theTimeNorm; } } } @@ -251,10 +256,17 @@ void CaloClusterKineHelper::calculateKine(xAOD::CaloCluster* clu, const bool use clu->setE(accum.theNewEnergy); clu->setM(0.0); - if ( timeNorm != 0. ) + if ( timeNorm != 0. ) { clu->setTime(accum.theNewTime/timeNorm); - else - clu->setTime(0); + // note that standard deviation of cell time distribution is >= 0. + // (no particular accommodation for <x^2> < <x><x>!) + // clu->setSecondTime(std::sqrt(std::max(accum.theNewSecondTime/timeNorm-clu->time()*clu->time(),0.))); + // consistency with other second moments: store variance! + clu->setSecondTime(accum.theNewSecondTime/timeNorm-clu->time()*clu->time()); + } else { + clu->setTime(0.); + clu->setSecondTime(0.); + } //Set Sampling pattern: diff --git a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/selection.xml b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/selection.xml index ec86a1c2207..ece9052cf69 100644 --- a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/selection.xml +++ b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/selection.xml @@ -6,6 +6,7 @@ <field name="m_signalState" transient="true" /> <field name="m_cellLinks" transient="true" /> <field name="m_recoStatus" transient="true" /> + <field name="m_secondTime" transient="true" /> </class> <read sourceClass="xAOD::CaloCluster_v1" version="[1-]" targetClass="xAOD::CaloCluster_v1" source="" target="m_signalState" > @@ -19,6 +20,11 @@ m_cellLinks = 0; ]]> </read> + <read sourceClass="xAOD::CaloCluster_v1" version="[1-]" + targetClass="xAOD::CaloCluster_v1" source="" target="m_secondTime" > + <![CDATA[ + m_secondTime = -999; + ]]> <class name="xAOD::CaloClusterContainer_v1" id="24997BCA-3F6A-4530-8826-822EE9FC3C08" /> <typedef name="xAOD::CaloCluster" /> diff --git a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/versions/CaloCluster_v1.h b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/versions/CaloCluster_v1.h index 2cd7b51a3c5..aae9d913cfd 100644 --- a/Event/xAOD/xAODCaloEvent/xAODCaloEvent/versions/CaloCluster_v1.h +++ b/Event/xAOD/xAODCaloEvent/xAODCaloEvent/versions/CaloCluster_v1.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ #ifndef XAODCALOEVENT_VERSIONS_CALOCLUSTER_V1_H #define XAODCALOEVENT_VERSIONS_CALOCLUSTER_V1_H @@ -14,7 +14,7 @@ extern "C" { // xAOD include(s): #include "xAODBase/IParticle.h" -//Defintion of CaloSamples (enum) +//Definition of CaloSamples (enum) #include "CaloGeoHelpers/CaloSampling.h" #include "xAODCaloEvent/CaloClusterBadChannelData.h" @@ -45,8 +45,11 @@ namespace xAOD { /// Description of a calorimeter cluster /// @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch> /// @author Walter Lampl <Walter.Lampl@cern.ch> + /// @author Peter Loch <Peter.Loch@cern.ch> /// - /// + /// @since 23-March-2021: added methods to set and retrieve second + /// moment of cell time distribution (persistified + /// as a cluster moment) class CaloCluster_v1 : public IParticle { friend class ::CaloClusterChangeSignalState; @@ -103,8 +106,8 @@ namespace xAOD { DELTA_PHI = 301, /// Angular shower axis deviation (\f$\theta\f$) from IP-to-Center DELTA_THETA = 302, - /// Angular shower axis deviation from IP-to-Center - DELTA_ALPHA = 303, + /// Angular shower axis deviation (\f$\Delta\alpha\f$) from IP-to-Center + DELTA_ALPHA = 303, CENTER_X = 401, ///< Cluster Centroid (\f$x\f$) CENTER_Y = 402, ///< Cluster Centroid (\f$y\f$) CENTER_Z = 403, ///< Cluster Centroid (\f$z\f$) @@ -153,6 +156,8 @@ namespace xAOD { DM_WEIGHT = 903, ///< Dead-material weight (E_dm/E_ooc) /// Confidence Level of a tile calorimeter cluster to be noise TILE_CONFIDENCE_LEVEL = 904, + /// Second moment of cell time distribution in cluster + SECOND_TIME = 910, VERTEX_FRACTION = 1000, /**< Vertex fraction of this cluster wrt. primary vertex of the event. Calculated in CaloRec/CaloClusterVertexFractionMaker.cxx */ NVERTEX_FRACTION = 1001, /**< slightly updated vertex fraction more pile up independent (similar to nJVF) */ @@ -442,6 +447,16 @@ namespace xAOD { void setTime(flt_t); /// Access cluster time flt_t time() const; + /// Set second moment of cell timing distribution + void setSecondTime(flt_t stime); + /// Access second moment of cell timing distribution + /// + /// For clusters read from persistent storage, this method returns the value + /// stored for the @c SECOND_TIME moment. + /// + /// @retval 0 if (1) moment is not available, (2) the cluster time could not be calculated, + /// or (3) the cluster has only one cell or all cells have exactly the same time. + flt_t secondTime() const; /// Access to sampling pattern (one bit per sampling) (Method may be removed later) unsigned samplingPattern() const; @@ -589,13 +604,16 @@ namespace xAOD { /// Current signal state State m_signalState; - ///Unique ptr to cell links. For cluster building + /// Unique ptr to cell links. For cluster building /// transient only , holds cells owned by the cluster if non-nullptr std::unique_ptr<CaloClusterCellLink> m_cellLinks; - ///Reco status (transient only) + /// Reco status (transient only) CaloRecoStatus m_recoStatus; + /// Second cell time moment (transient only) + double m_secondTime = { -1. }; + unsigned sampVarIdx(const CaloSample) const; float getSamplVarFromAcc(const Accessor<std::vector<float > >& acc, -- GitLab